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"
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},
200 {LIST, kWebMIdColor},
201 {LIST, kWebMIdProjection},
204 static const ElementIdInfo kColorIds[] = {
205 {UINT, kWebMIdColorMatrixCoefficients},
206 {UINT, kWebMIdColorBitsPerChannel},
207 {UINT, kWebMIdColorChromaSubsamplingHorz},
208 {UINT, kWebMIdColorChromaSubsamplingVert},
209 {UINT, kWebMIdColorCbSamplingHorz},
210 {UINT, kWebMIdColorCbSamplingVert},
211 {UINT, kWebMIdColorChromaSitingHorz},
212 {UINT, kWebMIdColorChromaSitingVert},
213 {UINT, kWebMIdColorRange},
214 {UINT, kWebMIdColorTransferCharacteristics},
215 {UINT, kWebMIdColorPrimaries},
216 {UINT, kWebMIdColorMaxCLL},
217 {UINT, kWebMIdColorMaxFALL},
218 {LIST, kWebMIdColorMasteringMetadata},
221 static const ElementIdInfo kProjectionIds[] = {
222 {UINT, kWebMIdProjectionType},
225 static const ElementIdInfo kAudioIds[] = {
226 {FLOAT, kWebMIdSamplingFrequency},
227 {FLOAT, kWebMIdOutputSamplingFrequency},
228 {UINT, kWebMIdChannels},
229 {UINT, kWebMIdBitDepth},
232 static const ElementIdInfo kTrackOperationIds[] = {
233 {LIST, kWebMIdTrackCombinePlanes},
234 {LIST, kWebMIdJoinBlocks},
237 static const ElementIdInfo kTrackCombinePlanesIds[] = {
238 {LIST, kWebMIdTrackPlane},
241 static const ElementIdInfo kTrackPlaneIds[] = {
242 {UINT, kWebMIdTrackPlaneUID},
243 {UINT, kWebMIdTrackPlaneType},
246 static const ElementIdInfo kJoinBlocksIds[] = {
247 {UINT, kWebMIdTrackJoinUID},
250 static const ElementIdInfo kContentEncodingsIds[] = {
251 {LIST, kWebMIdContentEncoding},
254 static const ElementIdInfo kContentEncodingIds[] = {
255 {UINT, kWebMIdContentEncodingOrder},
256 {UINT, kWebMIdContentEncodingScope},
257 {UINT, kWebMIdContentEncodingType},
258 {LIST, kWebMIdContentCompression},
259 {LIST, kWebMIdContentEncryption},
262 static const ElementIdInfo kContentCompressionIds[] = {
263 {UINT, kWebMIdContentCompAlgo},
264 {BINARY, kWebMIdContentCompSettings},
267 static const ElementIdInfo kContentEncryptionIds[] = {
268 {LIST, kWebMIdContentEncAESSettings},
269 {UINT, kWebMIdContentEncAlgo},
270 {BINARY, kWebMIdContentEncKeyID},
271 {BINARY, kWebMIdContentSignature},
272 {BINARY, kWebMIdContentSigKeyID},
273 {UINT, kWebMIdContentSigAlgo},
274 {UINT, kWebMIdContentSigHashAlgo},
277 static const ElementIdInfo kContentEncAESSettingsIds[] = {
278 {UINT, kWebMIdAESSettingsCipherMode},
281 static const ElementIdInfo kCuesIds[] = {
282 {LIST, kWebMIdCuePoint},
285 static const ElementIdInfo kCuePointIds[] = {
286 {UINT, kWebMIdCueTime},
287 {LIST, kWebMIdCueTrackPositions},
290 static const ElementIdInfo kCueTrackPositionsIds[] = {
291 {UINT, kWebMIdCueTrack},
292 {UINT, kWebMIdCueClusterPosition},
293 {UINT, kWebMIdCueBlockNumber},
294 {UINT, kWebMIdCueCodecState},
295 {LIST, kWebMIdCueReference},
298 static const ElementIdInfo kCueReferenceIds[] = {
299 {UINT, kWebMIdCueRefTime},
302 static const ElementIdInfo kAttachmentsIds[] = {
303 {LIST, kWebMIdAttachedFile},
306 static const ElementIdInfo kAttachedFileIds[] = {
307 {STRING, kWebMIdFileDescription},
308 {STRING, kWebMIdFileName},
309 {STRING, kWebMIdFileMimeType},
310 {BINARY, kWebMIdFileData},
311 {UINT, kWebMIdFileUID},
314 static const ElementIdInfo kChaptersIds[] = {
315 {LIST, kWebMIdEditionEntry},
318 static const ElementIdInfo kEditionEntryIds[] = {
319 {UINT, kWebMIdEditionUID},
320 {UINT, kWebMIdEditionFlagHidden},
321 {UINT, kWebMIdEditionFlagDefault},
322 {UINT, kWebMIdEditionFlagOrdered},
323 {LIST, kWebMIdChapterAtom},
326 static const ElementIdInfo kChapterAtomIds[] = {
327 {UINT, kWebMIdChapterUID},
328 {UINT, kWebMIdChapterTimeStart},
329 {UINT, kWebMIdChapterTimeEnd},
330 {UINT, kWebMIdChapterFlagHidden},
331 {UINT, kWebMIdChapterFlagEnabled},
332 {BINARY, kWebMIdChapterSegmentUID},
333 {UINT, kWebMIdChapterSegmentEditionUID},
334 {UINT, kWebMIdChapterPhysicalEquiv},
335 {LIST, kWebMIdChapterTrack},
336 {LIST, kWebMIdChapterDisplay},
337 {LIST, kWebMIdChapProcess},
340 static const ElementIdInfo kChapterTrackIds[] = {
341 {UINT, kWebMIdChapterTrackNumber},
344 static const ElementIdInfo kChapterDisplayIds[] = {
345 {STRING, kWebMIdChapString},
346 {STRING, kWebMIdChapLanguage},
347 {STRING, kWebMIdChapCountry},
350 static const ElementIdInfo kChapProcessIds[] = {
351 {UINT, kWebMIdChapProcessCodecID},
352 {BINARY, kWebMIdChapProcessPrivate},
353 {LIST, kWebMIdChapProcessCommand},
356 static const ElementIdInfo kChapProcessCommandIds[] = {
357 {UINT, kWebMIdChapProcessTime},
358 {BINARY, kWebMIdChapProcessData},
361 static const ElementIdInfo kTagsIds[] = {
365 static const ElementIdInfo kTagIds[] = {
366 {LIST, kWebMIdTargets},
367 {LIST, kWebMIdSimpleTag},
370 static const ElementIdInfo kTargetsIds[] = {
371 {UINT, kWebMIdTargetTypeValue},
372 {STRING, kWebMIdTargetType},
373 {UINT, kWebMIdTagTrackUID},
374 {UINT, kWebMIdTagEditionUID},
375 {UINT, kWebMIdTagChapterUID},
376 {UINT, kWebMIdTagAttachmentUID},
379 static const ElementIdInfo kSimpleTagIds[] = {
380 {STRING, kWebMIdTagName},
381 {STRING, kWebMIdTagLanguage},
382 {UINT, kWebMIdTagDefault},
383 {STRING, kWebMIdTagString},
384 {BINARY, kWebMIdTagBinary},
387 #define LIST_ELEMENT_INFO(id, level, id_info) \
388 { (id), (level), (id_info), arraysize(id_info) }
390 static const ListElementInfo kListElementInfo[] = {
391 LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds),
392 LIST_ELEMENT_INFO(kWebMIdEBMLHeader, 0, kEBMLHeaderIds),
393 LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds),
394 LIST_ELEMENT_INFO(kWebMIdSeekHead, 1, kSeekHeadIds),
395 LIST_ELEMENT_INFO(kWebMIdSeek, 2, kSeekIds),
396 LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds),
397 LIST_ELEMENT_INFO(kWebMIdChapterTranslate, 2, kChapterTranslateIds),
398 LIST_ELEMENT_INFO(kWebMIdSilentTracks, 2, kSilentTracksIds),
399 LIST_ELEMENT_INFO(kWebMIdBlockGroup, 2, kBlockGroupIds),
400 LIST_ELEMENT_INFO(kWebMIdBlockAdditions, 3, kBlockAdditionsIds),
401 LIST_ELEMENT_INFO(kWebMIdBlockMore, 4, kBlockMoreIds),
402 LIST_ELEMENT_INFO(kWebMIdSlices, 3, kSlicesIds),
403 LIST_ELEMENT_INFO(kWebMIdTimeSlice, 4, kTimeSliceIds),
404 LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds),
405 LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds),
406 LIST_ELEMENT_INFO(kWebMIdTrackTranslate, 3, kTrackTranslateIds),
407 LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds),
408 LIST_ELEMENT_INFO(kWebMIdColor, 4, kColorIds),
409 LIST_ELEMENT_INFO(kWebMIdProjection, 4, kProjectionIds),
410 LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds),
411 LIST_ELEMENT_INFO(kWebMIdTrackOperation, 3, kTrackOperationIds),
412 LIST_ELEMENT_INFO(kWebMIdTrackCombinePlanes, 4, kTrackCombinePlanesIds),
413 LIST_ELEMENT_INFO(kWebMIdTrackPlane, 5, kTrackPlaneIds),
414 LIST_ELEMENT_INFO(kWebMIdJoinBlocks, 4, kJoinBlocksIds),
415 LIST_ELEMENT_INFO(kWebMIdContentEncodings, 3, kContentEncodingsIds),
416 LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds),
417 LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds),
418 LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds),
419 LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings, 6, kContentEncAESSettingsIds),
420 LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds),
421 LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds),
422 LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds),
423 LIST_ELEMENT_INFO(kWebMIdCueReference, 4, kCueReferenceIds),
424 LIST_ELEMENT_INFO(kWebMIdAttachments, 1, kAttachmentsIds),
425 LIST_ELEMENT_INFO(kWebMIdAttachedFile, 2, kAttachedFileIds),
426 LIST_ELEMENT_INFO(kWebMIdChapters, 1, kChaptersIds),
427 LIST_ELEMENT_INFO(kWebMIdEditionEntry, 2, kEditionEntryIds),
428 LIST_ELEMENT_INFO(kWebMIdChapterAtom, 3, kChapterAtomIds),
429 LIST_ELEMENT_INFO(kWebMIdChapterTrack, 4, kChapterTrackIds),
430 LIST_ELEMENT_INFO(kWebMIdChapterDisplay, 4, kChapterDisplayIds),
431 LIST_ELEMENT_INFO(kWebMIdChapProcess, 4, kChapProcessIds),
432 LIST_ELEMENT_INFO(kWebMIdChapProcessCommand, 5, kChapProcessCommandIds),
433 LIST_ELEMENT_INFO(kWebMIdTags, 1, kTagsIds),
434 LIST_ELEMENT_INFO(kWebMIdTag, 2, kTagIds),
435 LIST_ELEMENT_INFO(kWebMIdTargets, 3, kTargetsIds),
436 LIST_ELEMENT_INFO(kWebMIdSimpleTag, 3, kSimpleTagIds),
452 static int ParseWebMElementHeaderField(
const uint8_t* buf,
455 bool mask_first_byte,
468 int extra_bytes = -1;
469 bool all_ones =
false;
470 for (
int i = 0; i < max_bytes; ++i) {
471 if ((ch & mask) != 0) {
473 *num = mask_first_byte ? ch & mask : ch;
474 all_ones = (ch & mask) == mask;
478 mask = 0x80 | mask >> 1;
481 if (extra_bytes == -1)
485 if ((1 + extra_bytes) > size)
490 for (
int i = 0; i < extra_bytes; ++i) {
491 ch = buf[bytes_used++];
492 all_ones &= (ch == 0xff);
493 *num = (*num << 8) | ch;
497 *num = std::numeric_limits<int64_t>::max();
502 int WebMParseElementHeader(
const uint8_t* buf,
505 int64_t* element_size) {
509 DCHECK(element_size);
515 int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4,
false, &tmp);
517 if (num_id_bytes <= 0)
520 if (tmp == std::numeric_limits<int64_t>::max())
521 tmp = kWebMReservedId;
523 *
id =
static_cast<int>(tmp);
525 int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes,
529 if (num_size_bytes <= 0)
530 return num_size_bytes;
532 if (tmp == std::numeric_limits<int64_t>::max())
533 tmp = kWebMUnknownSize;
536 DVLOG(3) <<
"WebMParseElementHeader() : id " << std::hex << *
id << std::dec
537 <<
" size " << *element_size;
538 return num_id_bytes + num_size_bytes;
542 static ElementType FindIdType(
int id,
543 const ElementIdInfo* id_info,
547 if (
id == kWebMIdVoid ||
id == kWebMIdCRC32)
550 for (
int i = 0; i < id_info_count; ++i) {
551 if (
id == id_info[i].id_)
552 return id_info[i].type_;
559 static const ListElementInfo* FindListInfo(
int id) {
560 for (
size_t i = 0; i < arraysize(kListElementInfo); ++i) {
561 if (
id == kListElementInfo[i].id_)
562 return &kListElementInfo[i];
568 static int FindListLevel(
int id) {
569 const ListElementInfo* list_info = FindListInfo(
id);
571 return list_info->level_;
576 static int ParseUInt(
const uint8_t* buf,
579 WebMParserClient* client) {
580 if ((size <= 0) || (size > 8))
585 for (
int i = 0; i < size; ++i)
586 value = (value << 8) | buf[i];
591 if (!base::IsValueInRangeForNumericType<int64_t>(value))
594 if (!client->OnUInt(
id, value))
600 static int ParseFloat(
const uint8_t* buf,
603 WebMParserClient* client) {
604 if ((size != 4) && (size != 8))
611 for (
int i = 0; i < size; ++i)
612 tmp = (tmp << 8) | buf[i];
621 tmp2.src =
static_cast<int32_t
>(tmp);
623 }
else if (size == 8) {
634 if (!client->OnFloat(
id, value))
640 static int ParseBinary(
const uint8_t* buf,
643 WebMParserClient* client) {
644 return client->OnBinary(
id, buf, size) ? size : -1;
647 static int ParseString(
const uint8_t* buf,
650 WebMParserClient* client) {
651 const uint8_t* end =
static_cast<const uint8_t*
>(memchr(buf,
'\0', size));
652 int length = (end != NULL) ?
static_cast<int>(end - buf) : size;
653 std::string str(
reinterpret_cast<const char*
>(buf), length);
654 return client->OnString(
id, str) ? size : -1;
657 static int ParseNonListElement(ElementType type,
659 int64_t element_size,
662 WebMParserClient* client) {
663 DCHECK_GE(size, element_size);
672 result = ParseUInt(buf, element_size,
id, client);
675 result = ParseFloat(buf, element_size,
id, client);
678 result = ParseBinary(buf, element_size,
id, client);
681 result = ParseString(buf, element_size,
id, client);
684 result = element_size;
687 DVLOG(1) <<
"Unhandled ID type " << type;
691 DCHECK_LE(result, size);
695 WebMParserClient::WebMParserClient() {}
696 WebMParserClient::~WebMParserClient() {}
698 WebMParserClient* WebMParserClient::OnListStart(
int id) {
699 DVLOG(1) <<
"Unexpected list element start with ID " << std::hex << id;
703 bool WebMParserClient::OnListEnd(
int id) {
704 DVLOG(1) <<
"Unexpected list element end with ID " << std::hex << id;
708 bool WebMParserClient::OnUInt(
int id, int64_t val) {
709 DVLOG(1) <<
"Unexpected unsigned integer element with ID " << std::hex << id;
713 bool WebMParserClient::OnFloat(
int id,
double val) {
714 DVLOG(1) <<
"Unexpected float element with ID " << std::hex << id;
718 bool WebMParserClient::OnBinary(
int id,
const uint8_t* data,
int size) {
719 DVLOG(1) <<
"Unexpected binary element with ID " << std::hex << id;
723 bool WebMParserClient::OnString(
int id,
const std::string& str) {
724 DVLOG(1) <<
"Unexpected string element with ID " << std::hex << id;
729 : state_(NEED_LIST_HEADER),
731 root_level_(FindListLevel(id)),
732 root_client_(client) {
733 DCHECK_GE(root_level_, 0);
737 WebMListParser::~WebMListParser() {}
740 ChangeState(NEED_LIST_HEADER);
741 list_state_stack_.clear();
747 if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
753 const uint8_t* cur = buf;
755 int bytes_parsed = 0;
757 while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
759 int64_t element_size = 0;
760 int result = WebMParseElementHeader(cur, cur_size, &element_id,
770 case NEED_LIST_HEADER: {
771 if (element_id != root_id_) {
772 ChangeState(PARSE_ERROR);
777 if (element_size == kWebMUnknownSize &&
778 (element_id != kWebMIdSegment) &&
779 (element_id != kWebMIdCluster)) {
780 ChangeState(PARSE_ERROR);
784 ChangeState(INSIDE_LIST);
785 if (!OnListStart(root_id_, element_size))
792 int header_size = result;
793 const uint8_t* element_data = cur + header_size;
794 int element_data_size = cur_size - header_size;
796 if (element_size < element_data_size)
797 element_data_size = element_size;
799 result = ParseListElement(header_size, element_id, element_size,
800 element_data, element_data_size);
802 DCHECK_LE(result, header_size + element_data_size);
804 ChangeState(PARSE_ERROR);
813 case DONE_PARSING_LIST:
822 bytes_parsed += result;
825 return (state_ == PARSE_ERROR) ? -1 : bytes_parsed;
829 return state_ == DONE_PARSING_LIST;
832 void WebMListParser::ChangeState(State new_state) {
836 int WebMListParser::ParseListElement(
int header_size,
838 int64_t element_size,
841 DCHECK_GT(list_state_stack_.size(), 0u);
843 ListState& list_state = list_state_stack_.back();
844 DCHECK(list_state.element_info_);
846 const ListElementInfo* element_info = list_state.element_info_;
847 ElementType id_type =
848 FindIdType(
id, element_info->id_info_, element_info->id_info_count_);
851 if (id_type == UNKNOWN) {
852 if (list_state.size_ != kWebMUnknownSize ||
853 !IsSiblingOrAncestor(list_state.id_,
id)) {
854 DVLOG(1) <<
"No ElementType info for ID 0x" << std::hex << id;
860 list_state.size_ = list_state.bytes_parsed_;
866 if (list_state_stack_.size() == 0)
869 list_state = list_state_stack_.back();
873 int64_t total_element_size = header_size + element_size;
874 if (list_state.size_ != kWebMUnknownSize &&
875 list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
879 if (id_type == LIST) {
880 list_state.bytes_parsed_ += header_size;
882 if (!OnListStart(
id, element_size))
889 if (size < element_size)
892 int bytes_parsed = ParseNonListElement(id_type,
id, element_size,
893 data, size, list_state.client_);
894 DCHECK_LE(bytes_parsed, size);
900 if (bytes_parsed < 0 || (bytes_parsed == 0 && element_size != 0))
903 int result = header_size + bytes_parsed;
904 list_state.bytes_parsed_ += result;
907 if (list_state.bytes_parsed_ == list_state.size_) {
915 bool WebMListParser::OnListStart(
int id, int64_t size) {
916 const ListElementInfo* element_info = FindListInfo(
id);
921 root_level_ +
static_cast<int>(list_state_stack_.size()) - 1;
922 if (current_level + 1 != element_info->level_)
925 WebMParserClient* current_list_client = NULL;
926 if (!list_state_stack_.empty()) {
928 ListState current_list_state = list_state_stack_.back();
929 if (current_list_state.size_ != kWebMUnknownSize &&
930 current_list_state.size_ < current_list_state.bytes_parsed_ + size)
932 current_list_client = current_list_state.client_;
934 current_list_client = root_client_;
937 WebMParserClient* new_list_client = current_list_client->OnListStart(
id);
938 if (!new_list_client)
941 ListState new_list_state = { id, size, 0, element_info, new_list_client };
942 list_state_stack_.push_back(new_list_state);
950 bool WebMListParser::OnListEnd() {
952 for (; !list_state_stack_.empty(); ++lists_ended) {
953 const ListState& list_state = list_state_stack_.back();
954 int64_t bytes_parsed = list_state.bytes_parsed_;
955 int id = list_state.id_;
957 if (bytes_parsed != list_state.size_)
960 list_state_stack_.pop_back();
962 WebMParserClient* client = NULL;
963 if (!list_state_stack_.empty()) {
965 list_state_stack_.back().bytes_parsed_ += bytes_parsed;
966 client = list_state_stack_.back().client_;
968 client = root_client_;
971 if (!client->OnListEnd(
id))
975 DCHECK_GE(lists_ended, 1);
977 if (list_state_stack_.empty())
978 ChangeState(DONE_PARSING_LIST);
983 bool WebMListParser::IsSiblingOrAncestor(
int id_a,
int id_b)
const {
984 DCHECK((id_a == kWebMIdSegment) || (id_a == kWebMIdCluster));
986 if (id_a == kWebMIdCluster) {
988 for (
size_t i = 0; i < arraysize(kSegmentIds); i++) {
989 if (kSegmentIds[i].id_ == id_b)
995 return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader));