1*103e46e4SHarish Mahendrakar // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2*103e46e4SHarish Mahendrakar //
3*103e46e4SHarish Mahendrakar // Use of this source code is governed by a BSD-style license
4*103e46e4SHarish Mahendrakar // that can be found in the LICENSE file in the root of the source
5*103e46e4SHarish Mahendrakar // tree. An additional intellectual property rights grant can be found
6*103e46e4SHarish Mahendrakar // in the file PATENTS. All contributing project authors may
7*103e46e4SHarish Mahendrakar // be found in the AUTHORS file in the root of the source tree.
8*103e46e4SHarish Mahendrakar #include "src/block_parser.h"
9*103e46e4SHarish Mahendrakar
10*103e46e4SHarish Mahendrakar #include <cassert>
11*103e46e4SHarish Mahendrakar #include <cstdint>
12*103e46e4SHarish Mahendrakar #include <numeric>
13*103e46e4SHarish Mahendrakar #include <type_traits>
14*103e46e4SHarish Mahendrakar #include <vector>
15*103e46e4SHarish Mahendrakar
16*103e46e4SHarish Mahendrakar #include "src/parser_utils.h"
17*103e46e4SHarish Mahendrakar #include "webm/element.h"
18*103e46e4SHarish Mahendrakar
19*103e46e4SHarish Mahendrakar namespace webm {
20*103e46e4SHarish Mahendrakar
21*103e46e4SHarish Mahendrakar namespace {
22*103e46e4SHarish Mahendrakar
23*103e46e4SHarish Mahendrakar // The ParseBasicBlockFlags functions parse extra flag bits into the block,
24*103e46e4SHarish Mahendrakar // depending on the type of block that is being parsed.
ParseBasicBlockFlags(std::uint8_t,Block *)25*103e46e4SHarish Mahendrakar void ParseBasicBlockFlags(std::uint8_t /* flags */, Block* /* block */) {
26*103e46e4SHarish Mahendrakar // Block has no extra flags that aren't already handled.
27*103e46e4SHarish Mahendrakar }
28*103e46e4SHarish Mahendrakar
ParseBasicBlockFlags(std::uint8_t flags,SimpleBlock * block)29*103e46e4SHarish Mahendrakar void ParseBasicBlockFlags(std::uint8_t flags, SimpleBlock* block) {
30*103e46e4SHarish Mahendrakar block->is_key_frame = (0x80 & flags) != 0;
31*103e46e4SHarish Mahendrakar block->is_discardable = (0x01 & flags) != 0;
32*103e46e4SHarish Mahendrakar }
33*103e46e4SHarish Mahendrakar
34*103e46e4SHarish Mahendrakar // The BasicBlockBegin functions call the Callback event handler and get the
35*103e46e4SHarish Mahendrakar // correct action for the parser, depending on the type of block that is being
36*103e46e4SHarish Mahendrakar // parsed.
BasicBlockBegin(const ElementMetadata & metadata,const Block & block,Callback * callback,Action * action)37*103e46e4SHarish Mahendrakar Status BasicBlockBegin(const ElementMetadata& metadata, const Block& block,
38*103e46e4SHarish Mahendrakar Callback* callback, Action* action) {
39*103e46e4SHarish Mahendrakar return callback->OnBlockBegin(metadata, block, action);
40*103e46e4SHarish Mahendrakar }
41*103e46e4SHarish Mahendrakar
BasicBlockBegin(const ElementMetadata & metadata,const SimpleBlock & block,Callback * callback,Action * action)42*103e46e4SHarish Mahendrakar Status BasicBlockBegin(const ElementMetadata& metadata,
43*103e46e4SHarish Mahendrakar const SimpleBlock& block, Callback* callback,
44*103e46e4SHarish Mahendrakar Action* action) {
45*103e46e4SHarish Mahendrakar return callback->OnSimpleBlockBegin(metadata, block, action);
46*103e46e4SHarish Mahendrakar }
47*103e46e4SHarish Mahendrakar
48*103e46e4SHarish Mahendrakar // The BasicBlockEnd functions call the Callback event handler depending on the
49*103e46e4SHarish Mahendrakar // type of block that is being parsed.
BasicBlockEnd(const ElementMetadata & metadata,const Block & block,Callback * callback)50*103e46e4SHarish Mahendrakar Status BasicBlockEnd(const ElementMetadata& metadata, const Block& block,
51*103e46e4SHarish Mahendrakar Callback* callback) {
52*103e46e4SHarish Mahendrakar return callback->OnBlockEnd(metadata, block);
53*103e46e4SHarish Mahendrakar }
54*103e46e4SHarish Mahendrakar
BasicBlockEnd(const ElementMetadata & metadata,const SimpleBlock & block,Callback * callback)55*103e46e4SHarish Mahendrakar Status BasicBlockEnd(const ElementMetadata& metadata, const SimpleBlock& block,
56*103e46e4SHarish Mahendrakar Callback* callback) {
57*103e46e4SHarish Mahendrakar return callback->OnSimpleBlockEnd(metadata, block);
58*103e46e4SHarish Mahendrakar }
59*103e46e4SHarish Mahendrakar
60*103e46e4SHarish Mahendrakar } // namespace
61*103e46e4SHarish Mahendrakar
62*103e46e4SHarish Mahendrakar template <typename T>
Init(const ElementMetadata & metadata,std::uint64_t max_size)63*103e46e4SHarish Mahendrakar Status BasicBlockParser<T>::Init(const ElementMetadata& metadata,
64*103e46e4SHarish Mahendrakar std::uint64_t max_size) {
65*103e46e4SHarish Mahendrakar assert(metadata.size == kUnknownElementSize || metadata.size <= max_size);
66*103e46e4SHarish Mahendrakar
67*103e46e4SHarish Mahendrakar if (metadata.size == kUnknownElementSize || metadata.size < 5) {
68*103e46e4SHarish Mahendrakar return Status(Status::kInvalidElementSize);
69*103e46e4SHarish Mahendrakar }
70*103e46e4SHarish Mahendrakar
71*103e46e4SHarish Mahendrakar *this = {};
72*103e46e4SHarish Mahendrakar frame_metadata_.parent_element = metadata;
73*103e46e4SHarish Mahendrakar
74*103e46e4SHarish Mahendrakar return Status(Status::kOkCompleted);
75*103e46e4SHarish Mahendrakar }
76*103e46e4SHarish Mahendrakar
77*103e46e4SHarish Mahendrakar template <typename T>
Feed(Callback * callback,Reader * reader,std::uint64_t * num_bytes_read)78*103e46e4SHarish Mahendrakar Status BasicBlockParser<T>::Feed(Callback* callback, Reader* reader,
79*103e46e4SHarish Mahendrakar std::uint64_t* num_bytes_read) {
80*103e46e4SHarish Mahendrakar assert(callback != nullptr);
81*103e46e4SHarish Mahendrakar assert(reader != nullptr);
82*103e46e4SHarish Mahendrakar assert(num_bytes_read != nullptr);
83*103e46e4SHarish Mahendrakar
84*103e46e4SHarish Mahendrakar *num_bytes_read = 0;
85*103e46e4SHarish Mahendrakar
86*103e46e4SHarish Mahendrakar Status status;
87*103e46e4SHarish Mahendrakar std::uint64_t local_num_bytes_read;
88*103e46e4SHarish Mahendrakar
89*103e46e4SHarish Mahendrakar while (true) {
90*103e46e4SHarish Mahendrakar switch (state_) {
91*103e46e4SHarish Mahendrakar case State::kReadingHeader: {
92*103e46e4SHarish Mahendrakar status = header_parser_.Feed(callback, reader, &local_num_bytes_read);
93*103e46e4SHarish Mahendrakar *num_bytes_read += local_num_bytes_read;
94*103e46e4SHarish Mahendrakar header_bytes_read_ += local_num_bytes_read;
95*103e46e4SHarish Mahendrakar if (!status.completed_ok()) {
96*103e46e4SHarish Mahendrakar return status;
97*103e46e4SHarish Mahendrakar }
98*103e46e4SHarish Mahendrakar value_.track_number = header_parser_.value().track_number;
99*103e46e4SHarish Mahendrakar value_.timecode = header_parser_.value().timecode;
100*103e46e4SHarish Mahendrakar
101*103e46e4SHarish Mahendrakar std::uint8_t flags = header_parser_.value().flags;
102*103e46e4SHarish Mahendrakar value_.is_visible = (0x08 & flags) == 0;
103*103e46e4SHarish Mahendrakar value_.lacing = static_cast<Lacing>(flags & 0x06);
104*103e46e4SHarish Mahendrakar ParseBasicBlockFlags(flags, &value_);
105*103e46e4SHarish Mahendrakar
106*103e46e4SHarish Mahendrakar if (value_.lacing == Lacing::kNone) {
107*103e46e4SHarish Mahendrakar value_.num_frames = 1;
108*103e46e4SHarish Mahendrakar state_ = State::kGettingAction;
109*103e46e4SHarish Mahendrakar } else {
110*103e46e4SHarish Mahendrakar state_ = State::kReadingLaceCount;
111*103e46e4SHarish Mahendrakar }
112*103e46e4SHarish Mahendrakar continue;
113*103e46e4SHarish Mahendrakar }
114*103e46e4SHarish Mahendrakar
115*103e46e4SHarish Mahendrakar case State::kReadingLaceCount: {
116*103e46e4SHarish Mahendrakar assert(lace_sizes_.empty());
117*103e46e4SHarish Mahendrakar std::uint8_t lace_count;
118*103e46e4SHarish Mahendrakar status = ReadByte(reader, &lace_count);
119*103e46e4SHarish Mahendrakar if (!status.completed_ok()) {
120*103e46e4SHarish Mahendrakar return status;
121*103e46e4SHarish Mahendrakar }
122*103e46e4SHarish Mahendrakar ++*num_bytes_read;
123*103e46e4SHarish Mahendrakar ++header_bytes_read_;
124*103e46e4SHarish Mahendrakar // Lace count is stored as (count - 1).
125*103e46e4SHarish Mahendrakar value_.num_frames = lace_count + 1;
126*103e46e4SHarish Mahendrakar state_ = State::kGettingAction;
127*103e46e4SHarish Mahendrakar continue;
128*103e46e4SHarish Mahendrakar }
129*103e46e4SHarish Mahendrakar
130*103e46e4SHarish Mahendrakar case State::kGettingAction: {
131*103e46e4SHarish Mahendrakar Action action = Action::kRead;
132*103e46e4SHarish Mahendrakar status = BasicBlockBegin(frame_metadata_.parent_element, value_,
133*103e46e4SHarish Mahendrakar callback, &action);
134*103e46e4SHarish Mahendrakar if (!status.completed_ok()) {
135*103e46e4SHarish Mahendrakar return status;
136*103e46e4SHarish Mahendrakar }
137*103e46e4SHarish Mahendrakar if (action == Action::kSkip) {
138*103e46e4SHarish Mahendrakar state_ = State::kSkipping;
139*103e46e4SHarish Mahendrakar } else if (value_.lacing == Lacing::kNone || value_.num_frames == 1) {
140*103e46e4SHarish Mahendrakar state_ = State::kValidatingSize;
141*103e46e4SHarish Mahendrakar } else if (value_.lacing == Lacing::kXiph) {
142*103e46e4SHarish Mahendrakar state_ = State::kReadingXiphLaceSizes;
143*103e46e4SHarish Mahendrakar } else if (value_.lacing == Lacing::kEbml) {
144*103e46e4SHarish Mahendrakar state_ = State::kReadingFirstEbmlLaceSize;
145*103e46e4SHarish Mahendrakar } else {
146*103e46e4SHarish Mahendrakar state_ = State::kCalculatingFixedLaceSizes;
147*103e46e4SHarish Mahendrakar }
148*103e46e4SHarish Mahendrakar continue;
149*103e46e4SHarish Mahendrakar }
150*103e46e4SHarish Mahendrakar
151*103e46e4SHarish Mahendrakar case State::kReadingXiphLaceSizes:
152*103e46e4SHarish Mahendrakar assert(value_.num_frames > 0);
153*103e46e4SHarish Mahendrakar while (static_cast<int>(lace_sizes_.size()) < value_.num_frames - 1) {
154*103e46e4SHarish Mahendrakar std::uint8_t byte;
155*103e46e4SHarish Mahendrakar do {
156*103e46e4SHarish Mahendrakar status = ReadByte(reader, &byte);
157*103e46e4SHarish Mahendrakar if (!status.completed_ok()) {
158*103e46e4SHarish Mahendrakar return status;
159*103e46e4SHarish Mahendrakar }
160*103e46e4SHarish Mahendrakar ++*num_bytes_read;
161*103e46e4SHarish Mahendrakar ++header_bytes_read_;
162*103e46e4SHarish Mahendrakar xiph_lace_size_ += byte;
163*103e46e4SHarish Mahendrakar } while (byte == 255);
164*103e46e4SHarish Mahendrakar
165*103e46e4SHarish Mahendrakar lace_sizes_.push_back(xiph_lace_size_);
166*103e46e4SHarish Mahendrakar xiph_lace_size_ = 0;
167*103e46e4SHarish Mahendrakar }
168*103e46e4SHarish Mahendrakar state_ = State::kValidatingSize;
169*103e46e4SHarish Mahendrakar continue;
170*103e46e4SHarish Mahendrakar
171*103e46e4SHarish Mahendrakar case State::kReadingFirstEbmlLaceSize:
172*103e46e4SHarish Mahendrakar assert(value_.num_frames > 0);
173*103e46e4SHarish Mahendrakar assert(lace_sizes_.empty());
174*103e46e4SHarish Mahendrakar status = uint_parser_.Feed(callback, reader, &local_num_bytes_read);
175*103e46e4SHarish Mahendrakar *num_bytes_read += local_num_bytes_read;
176*103e46e4SHarish Mahendrakar header_bytes_read_ += local_num_bytes_read;
177*103e46e4SHarish Mahendrakar if (!status.completed_ok()) {
178*103e46e4SHarish Mahendrakar return status;
179*103e46e4SHarish Mahendrakar }
180*103e46e4SHarish Mahendrakar lace_sizes_.push_back(uint_parser_.value());
181*103e46e4SHarish Mahendrakar uint_parser_ = {};
182*103e46e4SHarish Mahendrakar state_ = State::kReadingEbmlLaceSizes;
183*103e46e4SHarish Mahendrakar continue;
184*103e46e4SHarish Mahendrakar
185*103e46e4SHarish Mahendrakar case State::kReadingEbmlLaceSizes:
186*103e46e4SHarish Mahendrakar assert(value_.num_frames > 0);
187*103e46e4SHarish Mahendrakar assert(!lace_sizes_.empty());
188*103e46e4SHarish Mahendrakar while (static_cast<int>(lace_sizes_.size()) < value_.num_frames - 1) {
189*103e46e4SHarish Mahendrakar status = uint_parser_.Feed(callback, reader, &local_num_bytes_read);
190*103e46e4SHarish Mahendrakar *num_bytes_read += local_num_bytes_read;
191*103e46e4SHarish Mahendrakar header_bytes_read_ += local_num_bytes_read;
192*103e46e4SHarish Mahendrakar if (!status.completed_ok()) {
193*103e46e4SHarish Mahendrakar return status;
194*103e46e4SHarish Mahendrakar }
195*103e46e4SHarish Mahendrakar constexpr std::uint64_t one = 1; // Prettier than a static_cast.
196*103e46e4SHarish Mahendrakar std::uint64_t offset =
197*103e46e4SHarish Mahendrakar (one << (uint_parser_.encoded_length() * 7 - 1)) - 1;
198*103e46e4SHarish Mahendrakar lace_sizes_.push_back(lace_sizes_.back() + uint_parser_.value() -
199*103e46e4SHarish Mahendrakar offset);
200*103e46e4SHarish Mahendrakar uint_parser_ = {};
201*103e46e4SHarish Mahendrakar }
202*103e46e4SHarish Mahendrakar state_ = State::kValidatingSize;
203*103e46e4SHarish Mahendrakar continue;
204*103e46e4SHarish Mahendrakar
205*103e46e4SHarish Mahendrakar case State::kCalculatingFixedLaceSizes: {
206*103e46e4SHarish Mahendrakar assert(value_.num_frames > 0);
207*103e46e4SHarish Mahendrakar assert(lace_sizes_.empty());
208*103e46e4SHarish Mahendrakar if (header_bytes_read_ >= frame_metadata_.parent_element.size) {
209*103e46e4SHarish Mahendrakar return Status(Status::kInvalidElementValue);
210*103e46e4SHarish Mahendrakar }
211*103e46e4SHarish Mahendrakar std::uint64_t laced_data_size =
212*103e46e4SHarish Mahendrakar frame_metadata_.parent_element.size - header_bytes_read_;
213*103e46e4SHarish Mahendrakar std::uint64_t frame_size = laced_data_size / value_.num_frames;
214*103e46e4SHarish Mahendrakar if (laced_data_size % value_.num_frames != 0) {
215*103e46e4SHarish Mahendrakar return Status(Status::kInvalidElementValue);
216*103e46e4SHarish Mahendrakar }
217*103e46e4SHarish Mahendrakar lace_sizes_.resize(value_.num_frames, frame_size);
218*103e46e4SHarish Mahendrakar frame_metadata_.position =
219*103e46e4SHarish Mahendrakar frame_metadata_.parent_element.position + header_bytes_read_;
220*103e46e4SHarish Mahendrakar frame_metadata_.size = frame_size;
221*103e46e4SHarish Mahendrakar state_ = State::kReadingFrames;
222*103e46e4SHarish Mahendrakar continue;
223*103e46e4SHarish Mahendrakar }
224*103e46e4SHarish Mahendrakar
225*103e46e4SHarish Mahendrakar case State::kValidatingSize: {
226*103e46e4SHarish Mahendrakar std::uint64_t sum = std::accumulate(
227*103e46e4SHarish Mahendrakar lace_sizes_.begin(), lace_sizes_.end(), header_bytes_read_);
228*103e46e4SHarish Mahendrakar if (sum >= frame_metadata_.parent_element.size) {
229*103e46e4SHarish Mahendrakar return Status(Status::kInvalidElementValue);
230*103e46e4SHarish Mahendrakar }
231*103e46e4SHarish Mahendrakar lace_sizes_.push_back(frame_metadata_.parent_element.size - sum);
232*103e46e4SHarish Mahendrakar frame_metadata_.position = frame_metadata_.parent_element.position +
233*103e46e4SHarish Mahendrakar frame_metadata_.parent_element.header_size +
234*103e46e4SHarish Mahendrakar header_bytes_read_;
235*103e46e4SHarish Mahendrakar frame_metadata_.size = lace_sizes_[0];
236*103e46e4SHarish Mahendrakar state_ = State::kReadingFrames;
237*103e46e4SHarish Mahendrakar continue;
238*103e46e4SHarish Mahendrakar }
239*103e46e4SHarish Mahendrakar
240*103e46e4SHarish Mahendrakar case State::kSkipping:
241*103e46e4SHarish Mahendrakar do {
242*103e46e4SHarish Mahendrakar // Skip the remaining part of the header and all of the frames.
243*103e46e4SHarish Mahendrakar status = reader->Skip(
244*103e46e4SHarish Mahendrakar frame_metadata_.parent_element.size - header_bytes_read_,
245*103e46e4SHarish Mahendrakar &local_num_bytes_read);
246*103e46e4SHarish Mahendrakar *num_bytes_read += local_num_bytes_read;
247*103e46e4SHarish Mahendrakar header_bytes_read_ += local_num_bytes_read;
248*103e46e4SHarish Mahendrakar } while (status.code == Status::kOkPartial);
249*103e46e4SHarish Mahendrakar return status;
250*103e46e4SHarish Mahendrakar
251*103e46e4SHarish Mahendrakar case State::kReadingFrames:
252*103e46e4SHarish Mahendrakar assert(value_.num_frames > 0);
253*103e46e4SHarish Mahendrakar assert(static_cast<int>(lace_sizes_.size()) == value_.num_frames);
254*103e46e4SHarish Mahendrakar for (; current_lace_ < lace_sizes_.size(); ++current_lace_) {
255*103e46e4SHarish Mahendrakar const std::uint64_t original = lace_sizes_[current_lace_];
256*103e46e4SHarish Mahendrakar status = callback->OnFrame(frame_metadata_, reader,
257*103e46e4SHarish Mahendrakar &lace_sizes_[current_lace_]);
258*103e46e4SHarish Mahendrakar *num_bytes_read += original - lace_sizes_[current_lace_];
259*103e46e4SHarish Mahendrakar if (!status.completed_ok()) {
260*103e46e4SHarish Mahendrakar return status;
261*103e46e4SHarish Mahendrakar }
262*103e46e4SHarish Mahendrakar assert(lace_sizes_[current_lace_] == 0);
263*103e46e4SHarish Mahendrakar if (current_lace_ + 1 < lace_sizes_.size()) {
264*103e46e4SHarish Mahendrakar frame_metadata_.position += frame_metadata_.size;
265*103e46e4SHarish Mahendrakar frame_metadata_.size = lace_sizes_[current_lace_ + 1];
266*103e46e4SHarish Mahendrakar }
267*103e46e4SHarish Mahendrakar }
268*103e46e4SHarish Mahendrakar state_ = State::kDone;
269*103e46e4SHarish Mahendrakar continue;
270*103e46e4SHarish Mahendrakar
271*103e46e4SHarish Mahendrakar case State::kDone:
272*103e46e4SHarish Mahendrakar return BasicBlockEnd(frame_metadata_.parent_element, value_, callback);
273*103e46e4SHarish Mahendrakar }
274*103e46e4SHarish Mahendrakar }
275*103e46e4SHarish Mahendrakar }
276*103e46e4SHarish Mahendrakar
277*103e46e4SHarish Mahendrakar template <typename T>
WasSkipped() const278*103e46e4SHarish Mahendrakar bool BasicBlockParser<T>::WasSkipped() const {
279*103e46e4SHarish Mahendrakar return state_ == State::kSkipping;
280*103e46e4SHarish Mahendrakar }
281*103e46e4SHarish Mahendrakar
282*103e46e4SHarish Mahendrakar template class BasicBlockParser<Block>;
283*103e46e4SHarish Mahendrakar template class BasicBlockParser<SimpleBlock>;
284*103e46e4SHarish Mahendrakar
285*103e46e4SHarish Mahendrakar } // namespace webm
286