5 #include "packager/media/formats/webm/webm_parser.h"
16 #include "packager/base/logging.h"
17 #include "packager/base/numerics/safe_conversions.h"
18 #include "packager/media/formats/webm/webm_constants.h"
20 namespace edash_packager {
33 struct ElementIdInfo {
38 struct ListElementInfo {
41 const ElementIdInfo* id_info_;
50 static const ElementIdInfo kEBMLHeaderIds[] = {
51 {UINT, kWebMIdEBMLVersion},
52 {UINT, kWebMIdEBMLReadVersion},
53 {UINT, kWebMIdEBMLMaxIDLength},
54 {UINT, kWebMIdEBMLMaxSizeLength},
55 {STRING, kWebMIdDocType},
56 {UINT, kWebMIdDocTypeVersion},
57 {UINT, kWebMIdDocTypeReadVersion},
60 static const ElementIdInfo kSegmentIds[] = {
61 {LIST, kWebMIdSeekHead},
63 {LIST, kWebMIdCluster},
64 {LIST, kWebMIdTracks},
66 {LIST, kWebMIdAttachments},
67 {LIST, kWebMIdChapters},
71 static const ElementIdInfo kSeekHeadIds[] = {
75 static const ElementIdInfo kSeekIds[] = {
76 {BINARY, kWebMIdSeekID},
77 {UINT, kWebMIdSeekPosition},
80 static const ElementIdInfo kInfoIds[] = {
81 {BINARY, kWebMIdSegmentUID},
82 {STRING, kWebMIdSegmentFilename},
83 {BINARY, kWebMIdPrevUID},
84 {STRING, kWebMIdPrevFilename},
85 {BINARY, kWebMIdNextUID},
86 {STRING, kWebMIdNextFilename},
87 {BINARY, kWebMIdSegmentFamily},
88 {LIST, kWebMIdChapterTranslate},
89 {UINT, kWebMIdTimecodeScale},
90 {FLOAT, kWebMIdDuration},
91 {BINARY, kWebMIdDateUTC},
92 {STRING, kWebMIdTitle},
93 {STRING, kWebMIdMuxingApp},
94 {STRING, kWebMIdWritingApp},
97 static const ElementIdInfo kChapterTranslateIds[] = {
98 {UINT, kWebMIdChapterTranslateEditionUID},
99 {UINT, kWebMIdChapterTranslateCodec},
100 {BINARY, kWebMIdChapterTranslateID},
103 static const ElementIdInfo kClusterIds[] = {
104 {BINARY, kWebMIdSimpleBlock},
105 {UINT, kWebMIdTimecode},
106 {LIST, kWebMIdSilentTracks},
107 {UINT, kWebMIdPosition},
108 {UINT, kWebMIdPrevSize},
109 {LIST, kWebMIdBlockGroup},
112 static const ElementIdInfo kSilentTracksIds[] = {
113 {UINT, kWebMIdSilentTrackNumber},
116 static const ElementIdInfo kBlockGroupIds[] = {
117 {BINARY, kWebMIdBlock},
118 {LIST, kWebMIdBlockAdditions},
119 {UINT, kWebMIdBlockDuration},
120 {UINT, kWebMIdReferencePriority},
121 {BINARY, kWebMIdReferenceBlock},
122 {BINARY, kWebMIdCodecState},
123 {BINARY, kWebMIdDiscardPadding},
124 {LIST, kWebMIdSlices},
127 static const ElementIdInfo kBlockAdditionsIds[] = {
128 {LIST, kWebMIdBlockMore},
131 static const ElementIdInfo kBlockMoreIds[] = {
132 {UINT, kWebMIdBlockAddID},
133 {BINARY, kWebMIdBlockAdditional},
136 static const ElementIdInfo kSlicesIds[] = {
137 {LIST, kWebMIdTimeSlice},
140 static const ElementIdInfo kTimeSliceIds[] = {
141 {UINT, kWebMIdLaceNumber},
144 static const ElementIdInfo kTracksIds[] = {
145 {LIST, kWebMIdTrackEntry},
148 static const ElementIdInfo kTrackEntryIds[] = {
149 {UINT, kWebMIdTrackNumber},
150 {BINARY, kWebMIdTrackUID},
151 {UINT, kWebMIdTrackType},
152 {UINT, kWebMIdFlagEnabled},
153 {UINT, kWebMIdFlagDefault},
154 {UINT, kWebMIdFlagForced},
155 {UINT, kWebMIdFlagLacing},
156 {UINT, kWebMIdMinCache},
157 {UINT, kWebMIdMaxCache},
158 {UINT, kWebMIdDefaultDuration},
159 {FLOAT, kWebMIdTrackTimecodeScale},
160 {UINT, kWebMIdMaxBlockAdditionId},
161 {STRING, kWebMIdName},
162 {STRING, kWebMIdLanguage},
163 {STRING, kWebMIdCodecID},
164 {BINARY, kWebMIdCodecPrivate},
165 {STRING, kWebMIdCodecName},
166 {UINT, kWebMIdAttachmentLink},
167 {UINT, kWebMIdCodecDecodeAll},
168 {UINT, kWebMIdTrackOverlay},
169 {UINT, kWebMIdCodecDelay},
170 {UINT, kWebMIdSeekPreRoll},
171 {LIST, kWebMIdTrackTranslate},
172 {LIST, kWebMIdVideo},
173 {LIST, kWebMIdAudio},
174 {LIST, kWebMIdTrackOperation},
175 {LIST, kWebMIdContentEncodings},
178 static const ElementIdInfo kTrackTranslateIds[] = {
179 {UINT, kWebMIdTrackTranslateEditionUID},
180 {UINT, kWebMIdTrackTranslateCodec},
181 {BINARY, kWebMIdTrackTranslateTrackID},
184 static const ElementIdInfo kVideoIds[] = {
185 {UINT, kWebMIdFlagInterlaced},
186 {UINT, kWebMIdStereoMode},
187 {UINT, kWebMIdAlphaMode},
188 {UINT, kWebMIdPixelWidth},
189 {UINT, kWebMIdPixelHeight},
190 {UINT, kWebMIdPixelCropBottom},
191 {UINT, kWebMIdPixelCropTop},
192 {UINT, kWebMIdPixelCropLeft},
193 {UINT, kWebMIdPixelCropRight},
194 {UINT, kWebMIdDisplayWidth},
195 {UINT, kWebMIdDisplayHeight},
196 {UINT, kWebMIdDisplayUnit},
197 {UINT, kWebMIdAspectRatioType},
198 {BINARY, kWebMIdColorSpace},
199 {FLOAT, kWebMIdFrameRate},
202 static const ElementIdInfo kAudioIds[] = {
203 {FLOAT, kWebMIdSamplingFrequency},
204 {FLOAT, kWebMIdOutputSamplingFrequency},
205 {UINT, kWebMIdChannels},
206 {UINT, kWebMIdBitDepth},
209 static const ElementIdInfo kTrackOperationIds[] = {
210 {LIST, kWebMIdTrackCombinePlanes},
211 {LIST, kWebMIdJoinBlocks},
214 static const ElementIdInfo kTrackCombinePlanesIds[] = {
215 {LIST, kWebMIdTrackPlane},
218 static const ElementIdInfo kTrackPlaneIds[] = {
219 {UINT, kWebMIdTrackPlaneUID},
220 {UINT, kWebMIdTrackPlaneType},
223 static const ElementIdInfo kJoinBlocksIds[] = {
224 {UINT, kWebMIdTrackJoinUID},
227 static const ElementIdInfo kContentEncodingsIds[] = {
228 {LIST, kWebMIdContentEncoding},
231 static const ElementIdInfo kContentEncodingIds[] = {
232 {UINT, kWebMIdContentEncodingOrder},
233 {UINT, kWebMIdContentEncodingScope},
234 {UINT, kWebMIdContentEncodingType},
235 {LIST, kWebMIdContentCompression},
236 {LIST, kWebMIdContentEncryption},
239 static const ElementIdInfo kContentCompressionIds[] = {
240 {UINT, kWebMIdContentCompAlgo},
241 {BINARY, kWebMIdContentCompSettings},
244 static const ElementIdInfo kContentEncryptionIds[] = {
245 {LIST, kWebMIdContentEncAESSettings},
246 {UINT, kWebMIdContentEncAlgo},
247 {BINARY, kWebMIdContentEncKeyID},
248 {BINARY, kWebMIdContentSignature},
249 {BINARY, kWebMIdContentSigKeyID},
250 {UINT, kWebMIdContentSigAlgo},
251 {UINT, kWebMIdContentSigHashAlgo},
254 static const ElementIdInfo kContentEncAESSettingsIds[] = {
255 {UINT, kWebMIdAESSettingsCipherMode},
258 static const ElementIdInfo kCuesIds[] = {
259 {LIST, kWebMIdCuePoint},
262 static const ElementIdInfo kCuePointIds[] = {
263 {UINT, kWebMIdCueTime},
264 {LIST, kWebMIdCueTrackPositions},
267 static const ElementIdInfo kCueTrackPositionsIds[] = {
268 {UINT, kWebMIdCueTrack},
269 {UINT, kWebMIdCueClusterPosition},
270 {UINT, kWebMIdCueBlockNumber},
271 {UINT, kWebMIdCueCodecState},
272 {LIST, kWebMIdCueReference},
275 static const ElementIdInfo kCueReferenceIds[] = {
276 {UINT, kWebMIdCueRefTime},
279 static const ElementIdInfo kAttachmentsIds[] = {
280 {LIST, kWebMIdAttachedFile},
283 static const ElementIdInfo kAttachedFileIds[] = {
284 {STRING, kWebMIdFileDescription},
285 {STRING, kWebMIdFileName},
286 {STRING, kWebMIdFileMimeType},
287 {BINARY, kWebMIdFileData},
288 {UINT, kWebMIdFileUID},
291 static const ElementIdInfo kChaptersIds[] = {
292 {LIST, kWebMIdEditionEntry},
295 static const ElementIdInfo kEditionEntryIds[] = {
296 {UINT, kWebMIdEditionUID},
297 {UINT, kWebMIdEditionFlagHidden},
298 {UINT, kWebMIdEditionFlagDefault},
299 {UINT, kWebMIdEditionFlagOrdered},
300 {LIST, kWebMIdChapterAtom},
303 static const ElementIdInfo kChapterAtomIds[] = {
304 {UINT, kWebMIdChapterUID},
305 {UINT, kWebMIdChapterTimeStart},
306 {UINT, kWebMIdChapterTimeEnd},
307 {UINT, kWebMIdChapterFlagHidden},
308 {UINT, kWebMIdChapterFlagEnabled},
309 {BINARY, kWebMIdChapterSegmentUID},
310 {UINT, kWebMIdChapterSegmentEditionUID},
311 {UINT, kWebMIdChapterPhysicalEquiv},
312 {LIST, kWebMIdChapterTrack},
313 {LIST, kWebMIdChapterDisplay},
314 {LIST, kWebMIdChapProcess},
317 static const ElementIdInfo kChapterTrackIds[] = {
318 {UINT, kWebMIdChapterTrackNumber},
321 static const ElementIdInfo kChapterDisplayIds[] = {
322 {STRING, kWebMIdChapString},
323 {STRING, kWebMIdChapLanguage},
324 {STRING, kWebMIdChapCountry},
327 static const ElementIdInfo kChapProcessIds[] = {
328 {UINT, kWebMIdChapProcessCodecID},
329 {BINARY, kWebMIdChapProcessPrivate},
330 {LIST, kWebMIdChapProcessCommand},
333 static const ElementIdInfo kChapProcessCommandIds[] = {
334 {UINT, kWebMIdChapProcessTime},
335 {BINARY, kWebMIdChapProcessData},
338 static const ElementIdInfo kTagsIds[] = {
342 static const ElementIdInfo kTagIds[] = {
343 {LIST, kWebMIdTargets},
344 {LIST, kWebMIdSimpleTag},
347 static const ElementIdInfo kTargetsIds[] = {
348 {UINT, kWebMIdTargetTypeValue},
349 {STRING, kWebMIdTargetType},
350 {UINT, kWebMIdTagTrackUID},
351 {UINT, kWebMIdTagEditionUID},
352 {UINT, kWebMIdTagChapterUID},
353 {UINT, kWebMIdTagAttachmentUID},
356 static const ElementIdInfo kSimpleTagIds[] = {
357 {STRING, kWebMIdTagName},
358 {STRING, kWebMIdTagLanguage},
359 {UINT, kWebMIdTagDefault},
360 {STRING, kWebMIdTagString},
361 {BINARY, kWebMIdTagBinary},
364 #define LIST_ELEMENT_INFO(id, level, id_info) \
365 { (id), (level), (id_info), arraysize(id_info) }
367 static const ListElementInfo kListElementInfo[] = {
368 LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds),
369 LIST_ELEMENT_INFO(kWebMIdEBMLHeader, 0, kEBMLHeaderIds),
370 LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds),
371 LIST_ELEMENT_INFO(kWebMIdSeekHead, 1, kSeekHeadIds),
372 LIST_ELEMENT_INFO(kWebMIdSeek, 2, kSeekIds),
373 LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds),
374 LIST_ELEMENT_INFO(kWebMIdChapterTranslate, 2, kChapterTranslateIds),
375 LIST_ELEMENT_INFO(kWebMIdSilentTracks, 2, kSilentTracksIds),
376 LIST_ELEMENT_INFO(kWebMIdBlockGroup, 2, kBlockGroupIds),
377 LIST_ELEMENT_INFO(kWebMIdBlockAdditions, 3, kBlockAdditionsIds),
378 LIST_ELEMENT_INFO(kWebMIdBlockMore, 4, kBlockMoreIds),
379 LIST_ELEMENT_INFO(kWebMIdSlices, 3, kSlicesIds),
380 LIST_ELEMENT_INFO(kWebMIdTimeSlice, 4, kTimeSliceIds),
381 LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds),
382 LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds),
383 LIST_ELEMENT_INFO(kWebMIdTrackTranslate, 3, kTrackTranslateIds),
384 LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds),
385 LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds),
386 LIST_ELEMENT_INFO(kWebMIdTrackOperation, 3, kTrackOperationIds),
387 LIST_ELEMENT_INFO(kWebMIdTrackCombinePlanes, 4, kTrackCombinePlanesIds),
388 LIST_ELEMENT_INFO(kWebMIdTrackPlane, 5, kTrackPlaneIds),
389 LIST_ELEMENT_INFO(kWebMIdJoinBlocks, 4, kJoinBlocksIds),
390 LIST_ELEMENT_INFO(kWebMIdContentEncodings, 3, kContentEncodingsIds),
391 LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds),
392 LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds),
393 LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds),
394 LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings, 6, kContentEncAESSettingsIds),
395 LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds),
396 LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds),
397 LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds),
398 LIST_ELEMENT_INFO(kWebMIdCueReference, 4, kCueReferenceIds),
399 LIST_ELEMENT_INFO(kWebMIdAttachments, 1, kAttachmentsIds),
400 LIST_ELEMENT_INFO(kWebMIdAttachedFile, 2, kAttachedFileIds),
401 LIST_ELEMENT_INFO(kWebMIdChapters, 1, kChaptersIds),
402 LIST_ELEMENT_INFO(kWebMIdEditionEntry, 2, kEditionEntryIds),
403 LIST_ELEMENT_INFO(kWebMIdChapterAtom, 3, kChapterAtomIds),
404 LIST_ELEMENT_INFO(kWebMIdChapterTrack, 4, kChapterTrackIds),
405 LIST_ELEMENT_INFO(kWebMIdChapterDisplay, 4, kChapterDisplayIds),
406 LIST_ELEMENT_INFO(kWebMIdChapProcess, 4, kChapProcessIds),
407 LIST_ELEMENT_INFO(kWebMIdChapProcessCommand, 5, kChapProcessCommandIds),
408 LIST_ELEMENT_INFO(kWebMIdTags, 1, kTagsIds),
409 LIST_ELEMENT_INFO(kWebMIdTag, 2, kTagIds),
410 LIST_ELEMENT_INFO(kWebMIdTargets, 3, kTargetsIds),
411 LIST_ELEMENT_INFO(kWebMIdSimpleTag, 3, kSimpleTagIds),
427 static int ParseWebMElementHeaderField(
const uint8_t* buf,
430 bool mask_first_byte,
443 int extra_bytes = -1;
444 bool all_ones =
false;
445 for (
int i = 0; i < max_bytes; ++i) {
446 if ((ch & mask) != 0) {
448 *num = mask_first_byte ? ch & mask : ch;
449 all_ones = (ch & mask) == mask;
453 mask = 0x80 | mask >> 1;
456 if (extra_bytes == -1)
460 if ((1 + extra_bytes) > size)
465 for (
int i = 0; i < extra_bytes; ++i) {
466 ch = buf[bytes_used++];
467 all_ones &= (ch == 0xff);
468 *num = (*num << 8) | ch;
477 int WebMParseElementHeader(
const uint8_t* buf,
480 int64_t* element_size) {
484 DCHECK(element_size);
490 int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4,
false, &tmp);
492 if (num_id_bytes <= 0)
495 if (tmp == kint64max)
496 tmp = kWebMReservedId;
498 *
id =
static_cast<int>(tmp);
500 int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes,
504 if (num_size_bytes <= 0)
505 return num_size_bytes;
507 if (tmp == kint64max)
508 tmp = kWebMUnknownSize;
511 DVLOG(3) <<
"WebMParseElementHeader() : id " << std::hex << *
id << std::dec
512 <<
" size " << *element_size;
513 return num_id_bytes + num_size_bytes;
517 static ElementType FindIdType(
int id,
518 const ElementIdInfo* id_info,
522 if (
id == kWebMIdVoid ||
id == kWebMIdCRC32)
525 for (
int i = 0; i < id_info_count; ++i) {
526 if (
id == id_info[i].id_)
527 return id_info[i].type_;
534 static const ListElementInfo* FindListInfo(
int id) {
535 for (
size_t i = 0; i < arraysize(kListElementInfo); ++i) {
536 if (
id == kListElementInfo[i].id_)
537 return &kListElementInfo[i];
543 static int FindListLevel(
int id) {
544 const ListElementInfo* list_info = FindListInfo(
id);
546 return list_info->level_;
551 static int ParseUInt(
const uint8_t* buf,
554 WebMParserClient* client) {
555 if ((size <= 0) || (size > 8))
560 for (
int i = 0; i < size; ++i)
561 value = (value << 8) | buf[i];
566 if (!base::IsValueInRangeForNumericType<int64_t>(value))
569 if (!client->OnUInt(
id, value))
575 static int ParseFloat(
const uint8_t* buf,
578 WebMParserClient* client) {
579 if ((size != 4) && (size != 8))
586 for (
int i = 0; i < size; ++i)
587 tmp = (tmp << 8) | buf[i];
596 tmp2.src =
static_cast<int32_t
>(tmp);
598 }
else if (size == 8) {
609 if (!client->OnFloat(
id, value))
615 static int ParseBinary(
const uint8_t* buf,
618 WebMParserClient* client) {
619 return client->OnBinary(
id, buf, size) ? size : -1;
622 static int ParseString(
const uint8_t* buf,
625 WebMParserClient* client) {
626 const uint8_t* end =
static_cast<const uint8_t*
>(memchr(buf,
'\0', size));
627 int length = (end != NULL) ? static_cast<int>(end - buf) : size;
628 std::string str(reinterpret_cast<const char*>(buf), length);
629 return client->OnString(
id, str) ? size : -1;
632 static int ParseNonListElement(ElementType type,
634 int64_t element_size,
637 WebMParserClient* client) {
638 DCHECK_GE(size, element_size);
647 result = ParseUInt(buf, element_size,
id, client);
650 result = ParseFloat(buf, element_size,
id, client);
653 result = ParseBinary(buf, element_size,
id, client);
656 result = ParseString(buf, element_size,
id, client);
659 result = element_size;
662 DVLOG(1) <<
"Unhandled ID type " << type;
666 DCHECK_LE(result, size);
670 WebMParserClient::WebMParserClient() {}
671 WebMParserClient::~WebMParserClient() {}
673 WebMParserClient* WebMParserClient::OnListStart(
int id) {
674 DVLOG(1) <<
"Unexpected list element start with ID " << std::hex << id;
678 bool WebMParserClient::OnListEnd(
int id) {
679 DVLOG(1) <<
"Unexpected list element end with ID " << std::hex << id;
683 bool WebMParserClient::OnUInt(
int id, int64_t val) {
684 DVLOG(1) <<
"Unexpected unsigned integer element with ID " << std::hex << id;
688 bool WebMParserClient::OnFloat(
int id,
double val) {
689 DVLOG(1) <<
"Unexpected float element with ID " << std::hex << id;
693 bool WebMParserClient::OnBinary(
int id,
const uint8_t* data,
int size) {
694 DVLOG(1) <<
"Unexpected binary element with ID " << std::hex << id;
698 bool WebMParserClient::OnString(
int id,
const std::string& str) {
699 DVLOG(1) <<
"Unexpected string element with ID " << std::hex << id;
703 WebMListParser::WebMListParser(
int id, WebMParserClient* client)
704 : state_(NEED_LIST_HEADER),
706 root_level_(FindListLevel(id)),
707 root_client_(client) {
708 DCHECK_GE(root_level_, 0);
712 WebMListParser::~WebMListParser() {}
714 void WebMListParser::Reset() {
715 ChangeState(NEED_LIST_HEADER);
716 list_state_stack_.clear();
719 int WebMListParser::Parse(
const uint8_t* buf,
int size) {
722 if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
728 const uint8_t* cur = buf;
730 int bytes_parsed = 0;
732 while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
734 int64_t element_size = 0;
735 int result = WebMParseElementHeader(cur, cur_size, &element_id,
745 case NEED_LIST_HEADER: {
746 if (element_id != root_id_) {
747 ChangeState(PARSE_ERROR);
752 if (element_size == kWebMUnknownSize &&
753 (element_id != kWebMIdSegment) &&
754 (element_id != kWebMIdCluster)) {
755 ChangeState(PARSE_ERROR);
759 ChangeState(INSIDE_LIST);
760 if (!OnListStart(root_id_, element_size))
767 int header_size = result;
768 const uint8_t* element_data = cur + header_size;
769 int element_data_size = cur_size - header_size;
771 if (element_size < element_data_size)
772 element_data_size = element_size;
774 result = ParseListElement(header_size, element_id, element_size,
775 element_data, element_data_size);
777 DCHECK_LE(result, header_size + element_data_size);
779 ChangeState(PARSE_ERROR);
788 case DONE_PARSING_LIST:
797 bytes_parsed += result;
800 return (state_ == PARSE_ERROR) ? -1 : bytes_parsed;
803 bool WebMListParser::IsParsingComplete()
const {
804 return state_ == DONE_PARSING_LIST;
807 void WebMListParser::ChangeState(State new_state) {
811 int WebMListParser::ParseListElement(
int header_size,
813 int64_t element_size,
816 DCHECK_GT(list_state_stack_.size(), 0u);
818 ListState& list_state = list_state_stack_.back();
819 DCHECK(list_state.element_info_);
821 const ListElementInfo* element_info = list_state.element_info_;
822 ElementType id_type =
823 FindIdType(
id, element_info->id_info_, element_info->id_info_count_);
826 if (id_type == UNKNOWN) {
827 if (list_state.size_ != kWebMUnknownSize ||
828 !IsSiblingOrAncestor(list_state.id_,
id)) {
829 DVLOG(1) <<
"No ElementType info for ID 0x" << std::hex << id;
835 list_state.size_ = list_state.bytes_parsed_;
841 if (list_state_stack_.size() == 0)
844 list_state = list_state_stack_.back();
848 int64_t total_element_size = header_size + element_size;
849 if (list_state.size_ != kWebMUnknownSize &&
850 list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
854 if (id_type == LIST) {
855 list_state.bytes_parsed_ += header_size;
857 if (!OnListStart(
id, element_size))
864 if (size < element_size)
867 int bytes_parsed = ParseNonListElement(id_type,
id, element_size,
868 data, size, list_state.client_);
869 DCHECK_LE(bytes_parsed, size);
875 if (bytes_parsed < 0 || (bytes_parsed == 0 && element_size != 0))
878 int result = header_size + bytes_parsed;
879 list_state.bytes_parsed_ += result;
882 if (list_state.bytes_parsed_ == list_state.size_) {
890 bool WebMListParser::OnListStart(
int id, int64_t size) {
891 const ListElementInfo* element_info = FindListInfo(
id);
895 int current_level = root_level_ + list_state_stack_.size() - 1;
896 if (current_level + 1 != element_info->level_)
899 WebMParserClient* current_list_client = NULL;
900 if (!list_state_stack_.empty()) {
902 ListState current_list_state = list_state_stack_.back();
903 if (current_list_state.size_ != kWebMUnknownSize &&
904 current_list_state.size_ < current_list_state.bytes_parsed_ + size)
906 current_list_client = current_list_state.client_;
908 current_list_client = root_client_;
911 WebMParserClient* new_list_client = current_list_client->OnListStart(
id);
912 if (!new_list_client)
915 ListState new_list_state = { id, size, 0, element_info, new_list_client };
916 list_state_stack_.push_back(new_list_state);
924 bool WebMListParser::OnListEnd() {
926 for (; !list_state_stack_.empty(); ++lists_ended) {
927 const ListState& list_state = list_state_stack_.back();
928 int64_t bytes_parsed = list_state.bytes_parsed_;
929 int id = list_state.id_;
931 if (bytes_parsed != list_state.size_)
934 list_state_stack_.pop_back();
936 WebMParserClient* client = NULL;
937 if (!list_state_stack_.empty()) {
939 list_state_stack_.back().bytes_parsed_ += bytes_parsed;
940 client = list_state_stack_.back().client_;
942 client = root_client_;
945 if (!client->OnListEnd(
id))
949 DCHECK_GE(lists_ended, 1);
951 if (list_state_stack_.empty())
952 ChangeState(DONE_PARSING_LIST);
957 bool WebMListParser::IsSiblingOrAncestor(
int id_a,
int id_b)
const {
958 DCHECK((id_a == kWebMIdSegment) || (id_a == kWebMIdCluster));
960 if (id_a == kWebMIdCluster) {
962 for (
size_t i = 0; i < arraysize(kSegmentIds); i++) {
963 if (kSegmentIds[i].id_ == id_b)
969 return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader));