13#include <packager/media/formats/webm/webm_parser.h>
23#include <absl/log/check.h>
24#include <absl/log/log.h>
26#include <packager/macros/logging.h>
27#include <packager/media/formats/webm/webm_constants.h>
47struct ListElementInfo {
50 const ElementIdInfo* id_info_;
59static const ElementIdInfo kEBMLHeaderIds[] = {
60 {UINT, kWebMIdEBMLVersion}, {UINT, kWebMIdEBMLReadVersion},
61 {UINT, kWebMIdEBMLMaxIDLength}, {UINT, kWebMIdEBMLMaxSizeLength},
62 {STRING, kWebMIdDocType}, {UINT, kWebMIdDocTypeVersion},
63 {UINT, kWebMIdDocTypeReadVersion},
66static const ElementIdInfo kSegmentIds[] = {
67 {LIST, kWebMIdSeekHead}, {LIST, kWebMIdInfo}, {LIST, kWebMIdCluster},
68 {LIST, kWebMIdTracks}, {LIST, kWebMIdCues}, {LIST, kWebMIdAttachments},
69 {LIST, kWebMIdChapters}, {LIST, kWebMIdTags},
72static const ElementIdInfo kSeekHeadIds[] = {
76static const ElementIdInfo kSeekIds[] = {
77 {BINARY, kWebMIdSeekID},
78 {UINT, kWebMIdSeekPosition},
81static const ElementIdInfo kInfoIds[] = {
82 {BINARY, kWebMIdSegmentUID}, {STRING, kWebMIdSegmentFilename},
83 {BINARY, kWebMIdPrevUID}, {STRING, kWebMIdPrevFilename},
84 {BINARY, kWebMIdNextUID}, {STRING, kWebMIdNextFilename},
85 {BINARY, kWebMIdSegmentFamily}, {LIST, kWebMIdChapterTranslate},
86 {UINT, kWebMIdTimecodeScale}, {FLOAT, kWebMIdDuration},
87 {BINARY, kWebMIdDateUTC}, {STRING, kWebMIdTitle},
88 {STRING, kWebMIdMuxingApp}, {STRING, kWebMIdWritingApp},
91static const ElementIdInfo kChapterTranslateIds[] = {
92 {UINT, kWebMIdChapterTranslateEditionUID},
93 {UINT, kWebMIdChapterTranslateCodec},
94 {BINARY, kWebMIdChapterTranslateID},
97static const ElementIdInfo kClusterIds[] = {
98 {BINARY, kWebMIdSimpleBlock}, {UINT, kWebMIdTimecode},
99 {LIST, kWebMIdSilentTracks}, {UINT, kWebMIdPosition},
100 {UINT, kWebMIdPrevSize}, {LIST, kWebMIdBlockGroup},
103static const ElementIdInfo kSilentTracksIds[] = {
104 {UINT, kWebMIdSilentTrackNumber},
107static const ElementIdInfo kBlockGroupIds[] = {
108 {BINARY, kWebMIdBlock}, {LIST, kWebMIdBlockAdditions},
109 {UINT, kWebMIdBlockDuration}, {UINT, kWebMIdReferencePriority},
110 {BINARY, kWebMIdReferenceBlock}, {BINARY, kWebMIdCodecState},
111 {BINARY, kWebMIdDiscardPadding}, {LIST, kWebMIdSlices},
114static const ElementIdInfo kBlockAdditionsIds[] = {
115 {LIST, kWebMIdBlockMore},
118static const ElementIdInfo kBlockMoreIds[] = {
119 {UINT, kWebMIdBlockAddID},
120 {BINARY, kWebMIdBlockAdditional},
123static const ElementIdInfo kSlicesIds[] = {
124 {LIST, kWebMIdTimeSlice},
127static const ElementIdInfo kTimeSliceIds[] = {
128 {UINT, kWebMIdLaceNumber},
131static const ElementIdInfo kTracksIds[] = {
132 {LIST, kWebMIdTrackEntry},
135static const ElementIdInfo kTrackEntryIds[] = {
136 {UINT, kWebMIdTrackNumber},
137 {BINARY, kWebMIdTrackUID},
138 {UINT, kWebMIdTrackType},
139 {UINT, kWebMIdFlagEnabled},
140 {UINT, kWebMIdFlagDefault},
141 {UINT, kWebMIdFlagForced},
142 {UINT, kWebMIdFlagLacing},
143 {UINT, kWebMIdMinCache},
144 {UINT, kWebMIdMaxCache},
145 {UINT, kWebMIdDefaultDuration},
146 {FLOAT, kWebMIdTrackTimecodeScale},
147 {UINT, kWebMIdMaxBlockAdditionId},
148 {STRING, kWebMIdName},
149 {STRING, kWebMIdLanguage},
150 {STRING, kWebMIdCodecID},
151 {BINARY, kWebMIdCodecPrivate},
152 {STRING, kWebMIdCodecName},
153 {UINT, kWebMIdAttachmentLink},
154 {UINT, kWebMIdCodecDecodeAll},
155 {UINT, kWebMIdTrackOverlay},
156 {UINT, kWebMIdCodecDelay},
157 {UINT, kWebMIdSeekPreRoll},
158 {LIST, kWebMIdTrackTranslate},
159 {LIST, kWebMIdVideo},
160 {LIST, kWebMIdAudio},
161 {LIST, kWebMIdTrackOperation},
162 {LIST, kWebMIdContentEncodings},
165static const ElementIdInfo kTrackTranslateIds[] = {
166 {UINT, kWebMIdTrackTranslateEditionUID},
167 {UINT, kWebMIdTrackTranslateCodec},
168 {BINARY, kWebMIdTrackTranslateTrackID},
171static const ElementIdInfo kVideoIds[] = {
172 {UINT, kWebMIdFlagInterlaced}, {UINT, kWebMIdStereoMode},
173 {UINT, kWebMIdAlphaMode}, {UINT, kWebMIdPixelWidth},
174 {UINT, kWebMIdPixelHeight}, {UINT, kWebMIdPixelCropBottom},
175 {UINT, kWebMIdPixelCropTop}, {UINT, kWebMIdPixelCropLeft},
176 {UINT, kWebMIdPixelCropRight}, {UINT, kWebMIdDisplayWidth},
177 {UINT, kWebMIdDisplayHeight}, {UINT, kWebMIdDisplayUnit},
178 {UINT, kWebMIdAspectRatioType}, {BINARY, kWebMIdColorSpace},
179 {FLOAT, kWebMIdFrameRate}, {LIST, kWebMIdColor},
180 {LIST, kWebMIdProjection},
183static const ElementIdInfo kColorIds[] = {
184 {UINT, kWebMIdColorMatrixCoefficients},
185 {UINT, kWebMIdColorBitsPerChannel},
186 {UINT, kWebMIdColorChromaSubsamplingHorz},
187 {UINT, kWebMIdColorChromaSubsamplingVert},
188 {UINT, kWebMIdColorCbSamplingHorz},
189 {UINT, kWebMIdColorCbSamplingVert},
190 {UINT, kWebMIdColorChromaSitingHorz},
191 {UINT, kWebMIdColorChromaSitingVert},
192 {UINT, kWebMIdColorRange},
193 {UINT, kWebMIdColorTransferCharacteristics},
194 {UINT, kWebMIdColorPrimaries},
195 {UINT, kWebMIdColorMaxCLL},
196 {UINT, kWebMIdColorMaxFALL},
197 {LIST, kWebMIdColorMasteringMetadata},
200static const ElementIdInfo kProjectionIds[] = {
201 {UINT, kWebMIdProjectionType},
204static const ElementIdInfo kAudioIds[] = {
205 {FLOAT, kWebMIdSamplingFrequency},
206 {FLOAT, kWebMIdOutputSamplingFrequency},
207 {UINT, kWebMIdChannels},
208 {UINT, kWebMIdBitDepth},
211static const ElementIdInfo kTrackOperationIds[] = {
212 {LIST, kWebMIdTrackCombinePlanes},
213 {LIST, kWebMIdJoinBlocks},
216static const ElementIdInfo kTrackCombinePlanesIds[] = {
217 {LIST, kWebMIdTrackPlane},
220static const ElementIdInfo kTrackPlaneIds[] = {
221 {UINT, kWebMIdTrackPlaneUID},
222 {UINT, kWebMIdTrackPlaneType},
225static const ElementIdInfo kJoinBlocksIds[] = {
226 {UINT, kWebMIdTrackJoinUID},
229static const ElementIdInfo kContentEncodingsIds[] = {
230 {LIST, kWebMIdContentEncoding},
233static const ElementIdInfo kContentEncodingIds[] = {
234 {UINT, kWebMIdContentEncodingOrder}, {UINT, kWebMIdContentEncodingScope},
235 {UINT, kWebMIdContentEncodingType}, {LIST, kWebMIdContentCompression},
236 {LIST, kWebMIdContentEncryption},
239static const ElementIdInfo kContentCompressionIds[] = {
240 {UINT, kWebMIdContentCompAlgo},
241 {BINARY, kWebMIdContentCompSettings},
244static const ElementIdInfo kContentEncryptionIds[] = {
245 {LIST, kWebMIdContentEncAESSettings}, {UINT, kWebMIdContentEncAlgo},
246 {BINARY, kWebMIdContentEncKeyID}, {BINARY, kWebMIdContentSignature},
247 {BINARY, kWebMIdContentSigKeyID}, {UINT, kWebMIdContentSigAlgo},
248 {UINT, kWebMIdContentSigHashAlgo},
251static const ElementIdInfo kContentEncAESSettingsIds[] = {
252 {UINT, kWebMIdAESSettingsCipherMode},
255static const ElementIdInfo kCuesIds[] = {
256 {LIST, kWebMIdCuePoint},
259static const ElementIdInfo kCuePointIds[] = {
260 {UINT, kWebMIdCueTime},
261 {LIST, kWebMIdCueTrackPositions},
264static const ElementIdInfo kCueTrackPositionsIds[] = {
265 {UINT, kWebMIdCueTrack}, {UINT, kWebMIdCueClusterPosition},
266 {UINT, kWebMIdCueBlockNumber}, {UINT, kWebMIdCueCodecState},
267 {LIST, kWebMIdCueReference},
270static const ElementIdInfo kCueReferenceIds[] = {
271 {UINT, kWebMIdCueRefTime},
274static const ElementIdInfo kAttachmentsIds[] = {
275 {LIST, kWebMIdAttachedFile},
278static const ElementIdInfo kAttachedFileIds[] = {
279 {STRING, kWebMIdFileDescription}, {STRING, kWebMIdFileName},
280 {STRING, kWebMIdFileMimeType}, {BINARY, kWebMIdFileData},
281 {UINT, kWebMIdFileUID},
284static const ElementIdInfo kChaptersIds[] = {
285 {LIST, kWebMIdEditionEntry},
288static const ElementIdInfo kEditionEntryIds[] = {
289 {UINT, kWebMIdEditionUID}, {UINT, kWebMIdEditionFlagHidden},
290 {UINT, kWebMIdEditionFlagDefault}, {UINT, kWebMIdEditionFlagOrdered},
291 {LIST, kWebMIdChapterAtom},
294static const ElementIdInfo kChapterAtomIds[] = {
295 {UINT, kWebMIdChapterUID},
296 {UINT, kWebMIdChapterTimeStart},
297 {UINT, kWebMIdChapterTimeEnd},
298 {UINT, kWebMIdChapterFlagHidden},
299 {UINT, kWebMIdChapterFlagEnabled},
300 {BINARY, kWebMIdChapterSegmentUID},
301 {UINT, kWebMIdChapterSegmentEditionUID},
302 {UINT, kWebMIdChapterPhysicalEquiv},
303 {LIST, kWebMIdChapterTrack},
304 {LIST, kWebMIdChapterDisplay},
305 {LIST, kWebMIdChapProcess},
308static const ElementIdInfo kChapterTrackIds[] = {
309 {UINT, kWebMIdChapterTrackNumber},
312static const ElementIdInfo kChapterDisplayIds[] = {
313 {STRING, kWebMIdChapString},
314 {STRING, kWebMIdChapLanguage},
315 {STRING, kWebMIdChapCountry},
318static const ElementIdInfo kChapProcessIds[] = {
319 {UINT, kWebMIdChapProcessCodecID},
320 {BINARY, kWebMIdChapProcessPrivate},
321 {LIST, kWebMIdChapProcessCommand},
324static const ElementIdInfo kChapProcessCommandIds[] = {
325 {UINT, kWebMIdChapProcessTime},
326 {BINARY, kWebMIdChapProcessData},
329static const ElementIdInfo kTagsIds[] = {
333static const ElementIdInfo kTagIds[] = {
334 {LIST, kWebMIdTargets},
335 {LIST, kWebMIdSimpleTag},
338static const ElementIdInfo kTargetsIds[] = {
339 {UINT, kWebMIdTargetTypeValue}, {STRING, kWebMIdTargetType},
340 {UINT, kWebMIdTagTrackUID}, {UINT, kWebMIdTagEditionUID},
341 {UINT, kWebMIdTagChapterUID}, {UINT, kWebMIdTagAttachmentUID},
344static const ElementIdInfo kSimpleTagIds[] = {
345 {STRING, kWebMIdTagName}, {STRING, kWebMIdTagLanguage},
346 {UINT, kWebMIdTagDefault}, {STRING, kWebMIdTagString},
347 {BINARY, kWebMIdTagBinary},
350#define LIST_ELEMENT_INFO(id, level, id_info) \
351 {(id), (level), (id_info), std::size(id_info)}
353static const ListElementInfo kListElementInfo[] = {
354 LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds),
355 LIST_ELEMENT_INFO(kWebMIdEBMLHeader, 0, kEBMLHeaderIds),
356 LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds),
357 LIST_ELEMENT_INFO(kWebMIdSeekHead, 1, kSeekHeadIds),
358 LIST_ELEMENT_INFO(kWebMIdSeek, 2, kSeekIds),
359 LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds),
360 LIST_ELEMENT_INFO(kWebMIdChapterTranslate, 2, kChapterTranslateIds),
361 LIST_ELEMENT_INFO(kWebMIdSilentTracks, 2, kSilentTracksIds),
362 LIST_ELEMENT_INFO(kWebMIdBlockGroup, 2, kBlockGroupIds),
363 LIST_ELEMENT_INFO(kWebMIdBlockAdditions, 3, kBlockAdditionsIds),
364 LIST_ELEMENT_INFO(kWebMIdBlockMore, 4, kBlockMoreIds),
365 LIST_ELEMENT_INFO(kWebMIdSlices, 3, kSlicesIds),
366 LIST_ELEMENT_INFO(kWebMIdTimeSlice, 4, kTimeSliceIds),
367 LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds),
368 LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds),
369 LIST_ELEMENT_INFO(kWebMIdTrackTranslate, 3, kTrackTranslateIds),
370 LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds),
371 LIST_ELEMENT_INFO(kWebMIdColor, 4, kColorIds),
372 LIST_ELEMENT_INFO(kWebMIdProjection, 4, kProjectionIds),
373 LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds),
374 LIST_ELEMENT_INFO(kWebMIdTrackOperation, 3, kTrackOperationIds),
375 LIST_ELEMENT_INFO(kWebMIdTrackCombinePlanes, 4, kTrackCombinePlanesIds),
376 LIST_ELEMENT_INFO(kWebMIdTrackPlane, 5, kTrackPlaneIds),
377 LIST_ELEMENT_INFO(kWebMIdJoinBlocks, 4, kJoinBlocksIds),
378 LIST_ELEMENT_INFO(kWebMIdContentEncodings, 3, kContentEncodingsIds),
379 LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds),
380 LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds),
381 LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds),
382 LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings,
384 kContentEncAESSettingsIds),
385 LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds),
386 LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds),
387 LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds),
388 LIST_ELEMENT_INFO(kWebMIdCueReference, 4, kCueReferenceIds),
389 LIST_ELEMENT_INFO(kWebMIdAttachments, 1, kAttachmentsIds),
390 LIST_ELEMENT_INFO(kWebMIdAttachedFile, 2, kAttachedFileIds),
391 LIST_ELEMENT_INFO(kWebMIdChapters, 1, kChaptersIds),
392 LIST_ELEMENT_INFO(kWebMIdEditionEntry, 2, kEditionEntryIds),
393 LIST_ELEMENT_INFO(kWebMIdChapterAtom, 3, kChapterAtomIds),
394 LIST_ELEMENT_INFO(kWebMIdChapterTrack, 4, kChapterTrackIds),
395 LIST_ELEMENT_INFO(kWebMIdChapterDisplay, 4, kChapterDisplayIds),
396 LIST_ELEMENT_INFO(kWebMIdChapProcess, 4, kChapProcessIds),
397 LIST_ELEMENT_INFO(kWebMIdChapProcessCommand, 5, kChapProcessCommandIds),
398 LIST_ELEMENT_INFO(kWebMIdTags, 1, kTagsIds),
399 LIST_ELEMENT_INFO(kWebMIdTag, 2, kTagIds),
400 LIST_ELEMENT_INFO(kWebMIdTargets, 3, kTargetsIds),
401 LIST_ELEMENT_INFO(kWebMIdSimpleTag, 3, kSimpleTagIds),
417static int ParseWebMElementHeaderField(
const uint8_t* buf,
420 bool mask_first_byte,
433 int extra_bytes = -1;
434 bool all_ones =
false;
435 for (
int i = 0; i < max_bytes; ++i) {
436 if ((ch & mask) != 0) {
438 *num = mask_first_byte ? ch & mask : ch;
439 all_ones = (ch & mask) == mask;
443 mask = 0x80 | mask >> 1;
446 if (extra_bytes == -1)
450 if ((1 + extra_bytes) > size)
455 for (
int i = 0; i < extra_bytes; ++i) {
456 ch = buf[bytes_used++];
457 all_ones &= (ch == 0xff);
458 *num = (*num << 8) | ch;
462 *num = std::numeric_limits<int64_t>::max();
467int WebMParseElementHeader(
const uint8_t* buf,
470 int64_t* element_size) {
474 DCHECK(element_size);
480 int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4,
false, &tmp);
482 if (num_id_bytes <= 0)
485 if (tmp == std::numeric_limits<int64_t>::max())
486 tmp = kWebMReservedId;
488 *
id =
static_cast<int>(tmp);
490 int num_size_bytes = ParseWebMElementHeaderField(
491 buf + num_id_bytes, size - num_id_bytes, 8,
true, &tmp);
493 if (num_size_bytes <= 0)
494 return num_size_bytes;
496 if (tmp == std::numeric_limits<int64_t>::max())
497 tmp = kWebMUnknownSize;
500 DVLOG(3) <<
"WebMParseElementHeader() : id " << std::hex << *
id << std::dec
501 <<
" size " << *element_size;
502 return num_id_bytes + num_size_bytes;
506static ElementType FindIdType(
int id,
507 const ElementIdInfo* id_info,
510 if (
id == kWebMIdVoid ||
id == kWebMIdCRC32)
513 for (
int i = 0; i < id_info_count; ++i) {
514 if (
id == id_info[i].id_)
515 return id_info[i].type_;
522static const ListElementInfo* FindListInfo(
int id) {
523 for (
size_t i = 0; i < std::size(kListElementInfo); ++i) {
524 if (
id == kListElementInfo[i].id_)
525 return &kListElementInfo[i];
531static int FindListLevel(
int id) {
532 const ListElementInfo* list_info = FindListInfo(
id);
534 return list_info->level_;
539static int ParseUInt(
const uint8_t* buf,
542 WebMParserClient* client) {
543 if ((size <= 0) || (size > 8))
548 for (
int i = 0; i < size; ++i)
549 value = (value << 8) | buf[i];
554 if (value >
static_cast<uint64_t
>(std::numeric_limits<int64_t>::max()))
557 if (!client->OnUInt(
id, value))
563static int ParseFloat(
const uint8_t* buf,
566 WebMParserClient* client) {
567 if ((size != 4) && (size != 8))
574 for (
int i = 0; i < size; ++i)
575 tmp = (tmp << 8) | buf[i];
584 tmp2.src =
static_cast<int32_t
>(tmp);
586 }
else if (size == 8) {
597 if (!client->OnFloat(
id, value))
603static int ParseBinary(
const uint8_t* buf,
606 WebMParserClient* client) {
607 return client->OnBinary(
id, buf, size) ? size : -1;
610static int ParseString(
const uint8_t* buf,
613 WebMParserClient* client) {
614 const uint8_t* end =
static_cast<const uint8_t*
>(memchr(buf,
'\0', size));
615 int length = (end != NULL) ?
static_cast<int>(end - buf) : size;
616 std::string str(
reinterpret_cast<const char*
>(buf), length);
617 return client->OnString(
id, str) ? size : -1;
620static int ParseNonListElement(ElementType type,
622 int64_t element_size,
625 WebMParserClient* client) {
626 DCHECK_GE(size, element_size);
635 result = ParseUInt(buf, element_size,
id, client);
638 result = ParseFloat(buf, element_size,
id, client);
641 result = ParseBinary(buf, element_size,
id, client);
644 result = ParseString(buf, element_size,
id, client);
647 result = element_size;
650 DVLOG(1) <<
"Unhandled ID type " << type;
654 DCHECK_LE(result, size);
658WebMParserClient::WebMParserClient() {}
659WebMParserClient::~WebMParserClient() {}
661WebMParserClient* WebMParserClient::OnListStart(
int id) {
662 DVLOG(1) <<
"Unexpected list element start with ID " << std::hex << id;
666bool WebMParserClient::OnListEnd(
int id) {
667 DVLOG(1) <<
"Unexpected list element end with ID " << std::hex << id;
671bool WebMParserClient::OnUInt(
int id, int64_t ) {
672 DVLOG(1) <<
"Unexpected unsigned integer element with ID " << std::hex << id;
676bool WebMParserClient::OnFloat(
int id,
double ) {
677 DVLOG(1) <<
"Unexpected float element with ID " << std::hex << id;
681bool WebMParserClient::OnBinary(
int id,
const uint8_t* ,
int ) {
682 DVLOG(1) <<
"Unexpected binary element with ID " << std::hex << id;
686bool WebMParserClient::OnString(
int id,
const std::string& ) {
687 DVLOG(1) <<
"Unexpected string element with ID " << std::hex << id;
692 : state_(NEED_LIST_HEADER),
694 root_level_(FindListLevel(id)),
695 root_client_(client) {
696 DCHECK_GE(root_level_, 0);
700WebMListParser::~WebMListParser() {}
703 ChangeState(NEED_LIST_HEADER);
704 list_state_stack_.clear();
710 if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
716 const uint8_t* cur = buf;
718 int bytes_parsed = 0;
720 while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
722 int64_t element_size = 0;
724 WebMParseElementHeader(cur, cur_size, &element_id, &element_size);
733 case NEED_LIST_HEADER: {
734 if (element_id != root_id_) {
735 ChangeState(PARSE_ERROR);
740 if (element_size == kWebMUnknownSize &&
741 (element_id != kWebMIdSegment) && (element_id != kWebMIdCluster)) {
742 ChangeState(PARSE_ERROR);
746 ChangeState(INSIDE_LIST);
747 if (!OnListStart(root_id_, element_size))
754 int header_size = result;
755 const uint8_t* element_data = cur + header_size;
756 int element_data_size = cur_size - header_size;
758 if (element_size < element_data_size)
759 element_data_size = element_size;
761 result = ParseListElement(header_size, element_id, element_size,
762 element_data, element_data_size);
764 DCHECK_LE(result, header_size + element_data_size);
766 ChangeState(PARSE_ERROR);
775 case DONE_PARSING_LIST:
784 bytes_parsed += result;
787 return (state_ == PARSE_ERROR) ? -1 : bytes_parsed;
791 return state_ == DONE_PARSING_LIST;
794void WebMListParser::ChangeState(State new_state) {
798int WebMListParser::ParseListElement(
int header_size,
800 int64_t element_size,
803 DCHECK_GT(list_state_stack_.size(), 0u);
805 ListState& list_state = list_state_stack_.back();
806 DCHECK(list_state.element_info_);
808 const ListElementInfo* element_info = list_state.element_info_;
809 ElementType id_type =
810 FindIdType(
id, element_info->id_info_, element_info->id_info_count_);
813 if (id_type == UNKNOWN) {
814 if (list_state.size_ != kWebMUnknownSize ||
815 !IsSiblingOrAncestor(list_state.id_,
id)) {
816 DVLOG(1) <<
"No ElementType info for ID 0x" << std::hex << id;
822 list_state.size_ = list_state.bytes_parsed_;
828 if (list_state_stack_.size() == 0)
831 list_state = list_state_stack_.back();
835 int64_t total_element_size = header_size + element_size;
836 if (list_state.size_ != kWebMUnknownSize &&
837 list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
841 if (id_type == LIST) {
842 list_state.bytes_parsed_ += header_size;
844 if (!OnListStart(
id, element_size))
851 if (size < element_size)
854 int bytes_parsed = ParseNonListElement(id_type,
id, element_size, data, size,
856 DCHECK_LE(bytes_parsed, size);
862 if (bytes_parsed < 0 || (bytes_parsed == 0 && element_size != 0))
865 int result = header_size + bytes_parsed;
866 list_state.bytes_parsed_ += result;
869 if (list_state.bytes_parsed_ == list_state.size_) {
877bool WebMListParser::OnListStart(
int id, int64_t size) {
878 const ListElementInfo* element_info = FindListInfo(
id);
883 root_level_ +
static_cast<int>(list_state_stack_.size()) - 1;
884 if (current_level + 1 != element_info->level_)
887 WebMParserClient* current_list_client = NULL;
888 if (!list_state_stack_.empty()) {
890 ListState current_list_state = list_state_stack_.back();
891 if (current_list_state.size_ != kWebMUnknownSize &&
892 current_list_state.size_ < current_list_state.bytes_parsed_ + size)
894 current_list_client = current_list_state.client_;
896 current_list_client = root_client_;
899 WebMParserClient* new_list_client = current_list_client->OnListStart(
id);
900 if (!new_list_client)
903 ListState new_list_state = {id, size, 0, element_info, new_list_client};
904 list_state_stack_.push_back(new_list_state);
912bool WebMListParser::OnListEnd() {
914 for (; !list_state_stack_.empty(); ++lists_ended) {
915 const ListState& list_state = list_state_stack_.back();
916 int64_t bytes_parsed = list_state.bytes_parsed_;
917 int id = list_state.id_;
919 if (bytes_parsed != list_state.size_)
922 list_state_stack_.pop_back();
924 WebMParserClient* client = NULL;
925 if (!list_state_stack_.empty()) {
927 list_state_stack_.back().bytes_parsed_ += bytes_parsed;
928 client = list_state_stack_.back().client_;
930 client = root_client_;
933 if (!client->OnListEnd(
id))
937 DCHECK_GE(lists_ended, 1);
939 if (list_state_stack_.empty())
940 ChangeState(DONE_PARSING_LIST);
945bool WebMListParser::IsSiblingOrAncestor(
int id_a,
int id_b)
const {
946 DCHECK((id_a == kWebMIdSegment) || (id_a == kWebMIdCluster));
948 if (id_a == kWebMIdCluster) {
950 for (
size_t i = 0; i < std::size(kSegmentIds); i++) {
951 if (kSegmentIds[i].id_ == id_b)
957 return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader));
All the methods that are virtual are virtual for mocking.