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},
203 static const ElementIdInfo kColorIds[] = {
204 {UINT, kWebMIdColorMatrixCoefficients},
205 {UINT, kWebMIdColorBitsPerChannel},
206 {UINT, kWebMIdColorChromaSubsamplingHorz},
207 {UINT, kWebMIdColorChromaSubsamplingVert},
208 {UINT, kWebMIdColorCbSamplingHorz},
209 {UINT, kWebMIdColorCbSamplingVert},
210 {UINT, kWebMIdColorChromaSitingHorz},
211 {UINT, kWebMIdColorChromaSitingVert},
212 {UINT, kWebMIdColorRange},
213 {UINT, kWebMIdColorTransferCharacteristics},
214 {UINT, kWebMIdColorPrimaries},
215 {UINT, kWebMIdColorMaxCLL},
216 {UINT, kWebMIdColorMaxFALL},
217 {LIST, kWebMIdColorMasteringMetadata},
220 static const ElementIdInfo kAudioIds[] = {
221 {FLOAT, kWebMIdSamplingFrequency},
222 {FLOAT, kWebMIdOutputSamplingFrequency},
223 {UINT, kWebMIdChannels},
224 {UINT, kWebMIdBitDepth},
227 static const ElementIdInfo kTrackOperationIds[] = {
228 {LIST, kWebMIdTrackCombinePlanes},
229 {LIST, kWebMIdJoinBlocks},
232 static const ElementIdInfo kTrackCombinePlanesIds[] = {
233 {LIST, kWebMIdTrackPlane},
236 static const ElementIdInfo kTrackPlaneIds[] = {
237 {UINT, kWebMIdTrackPlaneUID},
238 {UINT, kWebMIdTrackPlaneType},
241 static const ElementIdInfo kJoinBlocksIds[] = {
242 {UINT, kWebMIdTrackJoinUID},
245 static const ElementIdInfo kContentEncodingsIds[] = {
246 {LIST, kWebMIdContentEncoding},
249 static const ElementIdInfo kContentEncodingIds[] = {
250 {UINT, kWebMIdContentEncodingOrder},
251 {UINT, kWebMIdContentEncodingScope},
252 {UINT, kWebMIdContentEncodingType},
253 {LIST, kWebMIdContentCompression},
254 {LIST, kWebMIdContentEncryption},
257 static const ElementIdInfo kContentCompressionIds[] = {
258 {UINT, kWebMIdContentCompAlgo},
259 {BINARY, kWebMIdContentCompSettings},
262 static const ElementIdInfo kContentEncryptionIds[] = {
263 {LIST, kWebMIdContentEncAESSettings},
264 {UINT, kWebMIdContentEncAlgo},
265 {BINARY, kWebMIdContentEncKeyID},
266 {BINARY, kWebMIdContentSignature},
267 {BINARY, kWebMIdContentSigKeyID},
268 {UINT, kWebMIdContentSigAlgo},
269 {UINT, kWebMIdContentSigHashAlgo},
272 static const ElementIdInfo kContentEncAESSettingsIds[] = {
273 {UINT, kWebMIdAESSettingsCipherMode},
276 static const ElementIdInfo kCuesIds[] = {
277 {LIST, kWebMIdCuePoint},
280 static const ElementIdInfo kCuePointIds[] = {
281 {UINT, kWebMIdCueTime},
282 {LIST, kWebMIdCueTrackPositions},
285 static const ElementIdInfo kCueTrackPositionsIds[] = {
286 {UINT, kWebMIdCueTrack},
287 {UINT, kWebMIdCueClusterPosition},
288 {UINT, kWebMIdCueBlockNumber},
289 {UINT, kWebMIdCueCodecState},
290 {LIST, kWebMIdCueReference},
293 static const ElementIdInfo kCueReferenceIds[] = {
294 {UINT, kWebMIdCueRefTime},
297 static const ElementIdInfo kAttachmentsIds[] = {
298 {LIST, kWebMIdAttachedFile},
301 static const ElementIdInfo kAttachedFileIds[] = {
302 {STRING, kWebMIdFileDescription},
303 {STRING, kWebMIdFileName},
304 {STRING, kWebMIdFileMimeType},
305 {BINARY, kWebMIdFileData},
306 {UINT, kWebMIdFileUID},
309 static const ElementIdInfo kChaptersIds[] = {
310 {LIST, kWebMIdEditionEntry},
313 static const ElementIdInfo kEditionEntryIds[] = {
314 {UINT, kWebMIdEditionUID},
315 {UINT, kWebMIdEditionFlagHidden},
316 {UINT, kWebMIdEditionFlagDefault},
317 {UINT, kWebMIdEditionFlagOrdered},
318 {LIST, kWebMIdChapterAtom},
321 static const ElementIdInfo kChapterAtomIds[] = {
322 {UINT, kWebMIdChapterUID},
323 {UINT, kWebMIdChapterTimeStart},
324 {UINT, kWebMIdChapterTimeEnd},
325 {UINT, kWebMIdChapterFlagHidden},
326 {UINT, kWebMIdChapterFlagEnabled},
327 {BINARY, kWebMIdChapterSegmentUID},
328 {UINT, kWebMIdChapterSegmentEditionUID},
329 {UINT, kWebMIdChapterPhysicalEquiv},
330 {LIST, kWebMIdChapterTrack},
331 {LIST, kWebMIdChapterDisplay},
332 {LIST, kWebMIdChapProcess},
335 static const ElementIdInfo kChapterTrackIds[] = {
336 {UINT, kWebMIdChapterTrackNumber},
339 static const ElementIdInfo kChapterDisplayIds[] = {
340 {STRING, kWebMIdChapString},
341 {STRING, kWebMIdChapLanguage},
342 {STRING, kWebMIdChapCountry},
345 static const ElementIdInfo kChapProcessIds[] = {
346 {UINT, kWebMIdChapProcessCodecID},
347 {BINARY, kWebMIdChapProcessPrivate},
348 {LIST, kWebMIdChapProcessCommand},
351 static const ElementIdInfo kChapProcessCommandIds[] = {
352 {UINT, kWebMIdChapProcessTime},
353 {BINARY, kWebMIdChapProcessData},
356 static const ElementIdInfo kTagsIds[] = {
360 static const ElementIdInfo kTagIds[] = {
361 {LIST, kWebMIdTargets},
362 {LIST, kWebMIdSimpleTag},
365 static const ElementIdInfo kTargetsIds[] = {
366 {UINT, kWebMIdTargetTypeValue},
367 {STRING, kWebMIdTargetType},
368 {UINT, kWebMIdTagTrackUID},
369 {UINT, kWebMIdTagEditionUID},
370 {UINT, kWebMIdTagChapterUID},
371 {UINT, kWebMIdTagAttachmentUID},
374 static const ElementIdInfo kSimpleTagIds[] = {
375 {STRING, kWebMIdTagName},
376 {STRING, kWebMIdTagLanguage},
377 {UINT, kWebMIdTagDefault},
378 {STRING, kWebMIdTagString},
379 {BINARY, kWebMIdTagBinary},
382 #define LIST_ELEMENT_INFO(id, level, id_info) \ 383 { (id), (level), (id_info), arraysize(id_info) } 385 static const ListElementInfo kListElementInfo[] = {
386 LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds),
387 LIST_ELEMENT_INFO(kWebMIdEBMLHeader, 0, kEBMLHeaderIds),
388 LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds),
389 LIST_ELEMENT_INFO(kWebMIdSeekHead, 1, kSeekHeadIds),
390 LIST_ELEMENT_INFO(kWebMIdSeek, 2, kSeekIds),
391 LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds),
392 LIST_ELEMENT_INFO(kWebMIdChapterTranslate, 2, kChapterTranslateIds),
393 LIST_ELEMENT_INFO(kWebMIdSilentTracks, 2, kSilentTracksIds),
394 LIST_ELEMENT_INFO(kWebMIdBlockGroup, 2, kBlockGroupIds),
395 LIST_ELEMENT_INFO(kWebMIdBlockAdditions, 3, kBlockAdditionsIds),
396 LIST_ELEMENT_INFO(kWebMIdBlockMore, 4, kBlockMoreIds),
397 LIST_ELEMENT_INFO(kWebMIdSlices, 3, kSlicesIds),
398 LIST_ELEMENT_INFO(kWebMIdTimeSlice, 4, kTimeSliceIds),
399 LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds),
400 LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds),
401 LIST_ELEMENT_INFO(kWebMIdTrackTranslate, 3, kTrackTranslateIds),
402 LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds),
403 LIST_ELEMENT_INFO(kWebMIdColor, 4, kColorIds),
404 LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds),
405 LIST_ELEMENT_INFO(kWebMIdTrackOperation, 3, kTrackOperationIds),
406 LIST_ELEMENT_INFO(kWebMIdTrackCombinePlanes, 4, kTrackCombinePlanesIds),
407 LIST_ELEMENT_INFO(kWebMIdTrackPlane, 5, kTrackPlaneIds),
408 LIST_ELEMENT_INFO(kWebMIdJoinBlocks, 4, kJoinBlocksIds),
409 LIST_ELEMENT_INFO(kWebMIdContentEncodings, 3, kContentEncodingsIds),
410 LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds),
411 LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds),
412 LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds),
413 LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings, 6, kContentEncAESSettingsIds),
414 LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds),
415 LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds),
416 LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds),
417 LIST_ELEMENT_INFO(kWebMIdCueReference, 4, kCueReferenceIds),
418 LIST_ELEMENT_INFO(kWebMIdAttachments, 1, kAttachmentsIds),
419 LIST_ELEMENT_INFO(kWebMIdAttachedFile, 2, kAttachedFileIds),
420 LIST_ELEMENT_INFO(kWebMIdChapters, 1, kChaptersIds),
421 LIST_ELEMENT_INFO(kWebMIdEditionEntry, 2, kEditionEntryIds),
422 LIST_ELEMENT_INFO(kWebMIdChapterAtom, 3, kChapterAtomIds),
423 LIST_ELEMENT_INFO(kWebMIdChapterTrack, 4, kChapterTrackIds),
424 LIST_ELEMENT_INFO(kWebMIdChapterDisplay, 4, kChapterDisplayIds),
425 LIST_ELEMENT_INFO(kWebMIdChapProcess, 4, kChapProcessIds),
426 LIST_ELEMENT_INFO(kWebMIdChapProcessCommand, 5, kChapProcessCommandIds),
427 LIST_ELEMENT_INFO(kWebMIdTags, 1, kTagsIds),
428 LIST_ELEMENT_INFO(kWebMIdTag, 2, kTagIds),
429 LIST_ELEMENT_INFO(kWebMIdTargets, 3, kTargetsIds),
430 LIST_ELEMENT_INFO(kWebMIdSimpleTag, 3, kSimpleTagIds),
446 static int ParseWebMElementHeaderField(
const uint8_t* buf,
449 bool mask_first_byte,
462 int extra_bytes = -1;
463 bool all_ones =
false;
464 for (
int i = 0; i < max_bytes; ++i) {
465 if ((ch & mask) != 0) {
467 *num = mask_first_byte ? ch & mask : ch;
468 all_ones = (ch & mask) == mask;
472 mask = 0x80 | mask >> 1;
475 if (extra_bytes == -1)
479 if ((1 + extra_bytes) > size)
484 for (
int i = 0; i < extra_bytes; ++i) {
485 ch = buf[bytes_used++];
486 all_ones &= (ch == 0xff);
487 *num = (*num << 8) | ch;
491 *num = std::numeric_limits<int64_t>::max();
496 int WebMParseElementHeader(
const uint8_t* buf,
499 int64_t* element_size) {
503 DCHECK(element_size);
509 int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4,
false, &tmp);
511 if (num_id_bytes <= 0)
514 if (tmp == std::numeric_limits<int64_t>::max())
515 tmp = kWebMReservedId;
517 *
id =
static_cast<int>(tmp);
519 int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes,
523 if (num_size_bytes <= 0)
524 return num_size_bytes;
526 if (tmp == std::numeric_limits<int64_t>::max())
527 tmp = kWebMUnknownSize;
530 DVLOG(3) <<
"WebMParseElementHeader() : id " << std::hex << *
id << std::dec
531 <<
" size " << *element_size;
532 return num_id_bytes + num_size_bytes;
536 static ElementType FindIdType(
int id,
537 const ElementIdInfo* id_info,
541 if (
id == kWebMIdVoid ||
id == kWebMIdCRC32)
544 for (
int i = 0; i < id_info_count; ++i) {
545 if (
id == id_info[i].id_)
546 return id_info[i].type_;
553 static const ListElementInfo* FindListInfo(
int id) {
554 for (
size_t i = 0; i < arraysize(kListElementInfo); ++i) {
555 if (
id == kListElementInfo[i].id_)
556 return &kListElementInfo[i];
562 static int FindListLevel(
int id) {
563 const ListElementInfo* list_info = FindListInfo(
id);
565 return list_info->level_;
570 static int ParseUInt(
const uint8_t* buf,
573 WebMParserClient* client) {
574 if ((size <= 0) || (size > 8))
579 for (
int i = 0; i < size; ++i)
580 value = (value << 8) | buf[i];
585 if (!base::IsValueInRangeForNumericType<int64_t>(value))
588 if (!client->OnUInt(
id, value))
594 static int ParseFloat(
const uint8_t* buf,
597 WebMParserClient* client) {
598 if ((size != 4) && (size != 8))
605 for (
int i = 0; i < size; ++i)
606 tmp = (tmp << 8) | buf[i];
615 tmp2.src =
static_cast<int32_t
>(tmp);
617 }
else if (size == 8) {
628 if (!client->OnFloat(
id, value))
634 static int ParseBinary(
const uint8_t* buf,
637 WebMParserClient* client) {
638 return client->OnBinary(
id, buf, size) ? size : -1;
641 static int ParseString(
const uint8_t* buf,
644 WebMParserClient* client) {
645 const uint8_t* end =
static_cast<const uint8_t*
>(memchr(buf,
'\0', size));
646 int length = (end != NULL) ? static_cast<int>(end - buf) : size;
647 std::string str(reinterpret_cast<const char*>(buf), length);
648 return client->OnString(
id, str) ? size : -1;
651 static int ParseNonListElement(ElementType type,
653 int64_t element_size,
656 WebMParserClient* client) {
657 DCHECK_GE(size, element_size);
666 result = ParseUInt(buf, element_size,
id, client);
669 result = ParseFloat(buf, element_size,
id, client);
672 result = ParseBinary(buf, element_size,
id, client);
675 result = ParseString(buf, element_size,
id, client);
678 result = element_size;
681 DVLOG(1) <<
"Unhandled ID type " << type;
685 DCHECK_LE(result, size);
689 WebMParserClient::WebMParserClient() {}
690 WebMParserClient::~WebMParserClient() {}
692 WebMParserClient* WebMParserClient::OnListStart(
int id) {
693 DVLOG(1) <<
"Unexpected list element start with ID " << std::hex << id;
697 bool WebMParserClient::OnListEnd(
int id) {
698 DVLOG(1) <<
"Unexpected list element end with ID " << std::hex << id;
702 bool WebMParserClient::OnUInt(
int id, int64_t val) {
703 DVLOG(1) <<
"Unexpected unsigned integer element with ID " << std::hex << id;
707 bool WebMParserClient::OnFloat(
int id,
double val) {
708 DVLOG(1) <<
"Unexpected float element with ID " << std::hex << id;
712 bool WebMParserClient::OnBinary(
int id,
const uint8_t* data,
int size) {
713 DVLOG(1) <<
"Unexpected binary element with ID " << std::hex << id;
717 bool WebMParserClient::OnString(
int id,
const std::string& str) {
718 DVLOG(1) <<
"Unexpected string element with ID " << std::hex << id;
723 : state_(NEED_LIST_HEADER),
725 root_level_(FindListLevel(id)),
726 root_client_(client) {
727 DCHECK_GE(root_level_, 0);
731 WebMListParser::~WebMListParser() {}
734 ChangeState(NEED_LIST_HEADER);
735 list_state_stack_.clear();
741 if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
747 const uint8_t* cur = buf;
749 int bytes_parsed = 0;
751 while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
753 int64_t element_size = 0;
754 int result = WebMParseElementHeader(cur, cur_size, &element_id,
764 case NEED_LIST_HEADER: {
765 if (element_id != root_id_) {
766 ChangeState(PARSE_ERROR);
771 if (element_size == kWebMUnknownSize &&
772 (element_id != kWebMIdSegment) &&
773 (element_id != kWebMIdCluster)) {
774 ChangeState(PARSE_ERROR);
778 ChangeState(INSIDE_LIST);
779 if (!OnListStart(root_id_, element_size))
786 int header_size = result;
787 const uint8_t* element_data = cur + header_size;
788 int element_data_size = cur_size - header_size;
790 if (element_size < element_data_size)
791 element_data_size = element_size;
793 result = ParseListElement(header_size, element_id, element_size,
794 element_data, element_data_size);
796 DCHECK_LE(result, header_size + element_data_size);
798 ChangeState(PARSE_ERROR);
807 case DONE_PARSING_LIST:
816 bytes_parsed += result;
819 return (state_ == PARSE_ERROR) ? -1 : bytes_parsed;
823 return state_ == DONE_PARSING_LIST;
826 void WebMListParser::ChangeState(State new_state) {
830 int WebMListParser::ParseListElement(
int header_size,
832 int64_t element_size,
835 DCHECK_GT(list_state_stack_.size(), 0u);
837 ListState& list_state = list_state_stack_.back();
838 DCHECK(list_state.element_info_);
840 const ListElementInfo* element_info = list_state.element_info_;
841 ElementType id_type =
842 FindIdType(
id, element_info->id_info_, element_info->id_info_count_);
845 if (id_type == UNKNOWN) {
846 if (list_state.size_ != kWebMUnknownSize ||
847 !IsSiblingOrAncestor(list_state.id_,
id)) {
848 DVLOG(1) <<
"No ElementType info for ID 0x" << std::hex << id;
854 list_state.size_ = list_state.bytes_parsed_;
860 if (list_state_stack_.size() == 0)
863 list_state = list_state_stack_.back();
867 int64_t total_element_size = header_size + element_size;
868 if (list_state.size_ != kWebMUnknownSize &&
869 list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
873 if (id_type == LIST) {
874 list_state.bytes_parsed_ += header_size;
876 if (!OnListStart(
id, element_size))
883 if (size < element_size)
886 int bytes_parsed = ParseNonListElement(id_type,
id, element_size,
887 data, size, list_state.client_);
888 DCHECK_LE(bytes_parsed, size);
894 if (bytes_parsed < 0 || (bytes_parsed == 0 && element_size != 0))
897 int result = header_size + bytes_parsed;
898 list_state.bytes_parsed_ += result;
901 if (list_state.bytes_parsed_ == list_state.size_) {
909 bool WebMListParser::OnListStart(
int id, int64_t size) {
910 const ListElementInfo* element_info = FindListInfo(
id);
915 root_level_ +
static_cast<int>(list_state_stack_.size()) - 1;
916 if (current_level + 1 != element_info->level_)
920 if (!list_state_stack_.empty()) {
922 ListState current_list_state = list_state_stack_.back();
923 if (current_list_state.size_ != kWebMUnknownSize &&
924 current_list_state.size_ < current_list_state.bytes_parsed_ + size)
926 current_list_client = current_list_state.client_;
928 current_list_client = root_client_;
932 if (!new_list_client)
935 ListState new_list_state = { id, size, 0, element_info, new_list_client };
936 list_state_stack_.push_back(new_list_state);
944 bool WebMListParser::OnListEnd() {
946 for (; !list_state_stack_.empty(); ++lists_ended) {
947 const ListState& list_state = list_state_stack_.back();
948 int64_t bytes_parsed = list_state.bytes_parsed_;
949 int id = list_state.id_;
951 if (bytes_parsed != list_state.size_)
954 list_state_stack_.pop_back();
957 if (!list_state_stack_.empty()) {
959 list_state_stack_.back().bytes_parsed_ += bytes_parsed;
960 client = list_state_stack_.back().client_;
962 client = root_client_;
965 if (!client->OnListEnd(
id))
969 DCHECK_GE(lists_ended, 1);
971 if (list_state_stack_.empty())
972 ChangeState(DONE_PARSING_LIST);
977 bool WebMListParser::IsSiblingOrAncestor(
int id_a,
int id_b)
const {
978 DCHECK((id_a == kWebMIdSegment) || (id_a == kWebMIdCluster));
980 if (id_a == kWebMIdCluster) {
982 for (
size_t i = 0; i < arraysize(kSegmentIds); i++) {
983 if (kSegmentIds[i].id_ == id_b)
989 return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader));
All the methods that are virtual are virtual for mocking.