13 #include <packager/media/formats/webm/webm_parser.h>
17 #include <absl/log/check.h>
18 #include <absl/log/log.h>
20 #include <packager/macros/logging.h>
21 #include <packager/media/formats/webm/webm_constants.h>
36 struct ElementIdInfo {
41 struct ListElementInfo {
44 const ElementIdInfo* id_info_;
53 static const ElementIdInfo kEBMLHeaderIds[] = {
54 {UINT, kWebMIdEBMLVersion},
55 {UINT, kWebMIdEBMLReadVersion},
56 {UINT, kWebMIdEBMLMaxIDLength},
57 {UINT, kWebMIdEBMLMaxSizeLength},
58 {STRING, kWebMIdDocType},
59 {UINT, kWebMIdDocTypeVersion},
60 {UINT, kWebMIdDocTypeReadVersion},
63 static const ElementIdInfo kSegmentIds[] = {
64 {LIST, kWebMIdSeekHead},
66 {LIST, kWebMIdCluster},
67 {LIST, kWebMIdTracks},
69 {LIST, kWebMIdAttachments},
70 {LIST, kWebMIdChapters},
74 static const ElementIdInfo kSeekHeadIds[] = {
78 static const ElementIdInfo kSeekIds[] = {
79 {BINARY, kWebMIdSeekID},
80 {UINT, kWebMIdSeekPosition},
83 static const ElementIdInfo kInfoIds[] = {
84 {BINARY, kWebMIdSegmentUID},
85 {STRING, kWebMIdSegmentFilename},
86 {BINARY, kWebMIdPrevUID},
87 {STRING, kWebMIdPrevFilename},
88 {BINARY, kWebMIdNextUID},
89 {STRING, kWebMIdNextFilename},
90 {BINARY, kWebMIdSegmentFamily},
91 {LIST, kWebMIdChapterTranslate},
92 {UINT, kWebMIdTimecodeScale},
93 {FLOAT, kWebMIdDuration},
94 {BINARY, kWebMIdDateUTC},
95 {STRING, kWebMIdTitle},
96 {STRING, kWebMIdMuxingApp},
97 {STRING, kWebMIdWritingApp},
100 static const ElementIdInfo kChapterTranslateIds[] = {
101 {UINT, kWebMIdChapterTranslateEditionUID},
102 {UINT, kWebMIdChapterTranslateCodec},
103 {BINARY, kWebMIdChapterTranslateID},
106 static const ElementIdInfo kClusterIds[] = {
107 {BINARY, kWebMIdSimpleBlock},
108 {UINT, kWebMIdTimecode},
109 {LIST, kWebMIdSilentTracks},
110 {UINT, kWebMIdPosition},
111 {UINT, kWebMIdPrevSize},
112 {LIST, kWebMIdBlockGroup},
115 static const ElementIdInfo kSilentTracksIds[] = {
116 {UINT, kWebMIdSilentTrackNumber},
119 static const ElementIdInfo kBlockGroupIds[] = {
120 {BINARY, kWebMIdBlock},
121 {LIST, kWebMIdBlockAdditions},
122 {UINT, kWebMIdBlockDuration},
123 {UINT, kWebMIdReferencePriority},
124 {BINARY, kWebMIdReferenceBlock},
125 {BINARY, kWebMIdCodecState},
126 {BINARY, kWebMIdDiscardPadding},
127 {LIST, kWebMIdSlices},
130 static const ElementIdInfo kBlockAdditionsIds[] = {
131 {LIST, kWebMIdBlockMore},
134 static const ElementIdInfo kBlockMoreIds[] = {
135 {UINT, kWebMIdBlockAddID},
136 {BINARY, kWebMIdBlockAdditional},
139 static const ElementIdInfo kSlicesIds[] = {
140 {LIST, kWebMIdTimeSlice},
143 static const ElementIdInfo kTimeSliceIds[] = {
144 {UINT, kWebMIdLaceNumber},
147 static const ElementIdInfo kTracksIds[] = {
148 {LIST, kWebMIdTrackEntry},
151 static const ElementIdInfo kTrackEntryIds[] = {
152 {UINT, kWebMIdTrackNumber},
153 {BINARY, kWebMIdTrackUID},
154 {UINT, kWebMIdTrackType},
155 {UINT, kWebMIdFlagEnabled},
156 {UINT, kWebMIdFlagDefault},
157 {UINT, kWebMIdFlagForced},
158 {UINT, kWebMIdFlagLacing},
159 {UINT, kWebMIdMinCache},
160 {UINT, kWebMIdMaxCache},
161 {UINT, kWebMIdDefaultDuration},
162 {FLOAT, kWebMIdTrackTimecodeScale},
163 {UINT, kWebMIdMaxBlockAdditionId},
164 {STRING, kWebMIdName},
165 {STRING, kWebMIdLanguage},
166 {STRING, kWebMIdCodecID},
167 {BINARY, kWebMIdCodecPrivate},
168 {STRING, kWebMIdCodecName},
169 {UINT, kWebMIdAttachmentLink},
170 {UINT, kWebMIdCodecDecodeAll},
171 {UINT, kWebMIdTrackOverlay},
172 {UINT, kWebMIdCodecDelay},
173 {UINT, kWebMIdSeekPreRoll},
174 {LIST, kWebMIdTrackTranslate},
175 {LIST, kWebMIdVideo},
176 {LIST, kWebMIdAudio},
177 {LIST, kWebMIdTrackOperation},
178 {LIST, kWebMIdContentEncodings},
181 static const ElementIdInfo kTrackTranslateIds[] = {
182 {UINT, kWebMIdTrackTranslateEditionUID},
183 {UINT, kWebMIdTrackTranslateCodec},
184 {BINARY, kWebMIdTrackTranslateTrackID},
187 static const ElementIdInfo kVideoIds[] = {
188 {UINT, kWebMIdFlagInterlaced},
189 {UINT, kWebMIdStereoMode},
190 {UINT, kWebMIdAlphaMode},
191 {UINT, kWebMIdPixelWidth},
192 {UINT, kWebMIdPixelHeight},
193 {UINT, kWebMIdPixelCropBottom},
194 {UINT, kWebMIdPixelCropTop},
195 {UINT, kWebMIdPixelCropLeft},
196 {UINT, kWebMIdPixelCropRight},
197 {UINT, kWebMIdDisplayWidth},
198 {UINT, kWebMIdDisplayHeight},
199 {UINT, kWebMIdDisplayUnit},
200 {UINT, kWebMIdAspectRatioType},
201 {BINARY, kWebMIdColorSpace},
202 {FLOAT, kWebMIdFrameRate},
203 {LIST, kWebMIdColor},
204 {LIST, kWebMIdProjection},
207 static const ElementIdInfo kColorIds[] = {
208 {UINT, kWebMIdColorMatrixCoefficients},
209 {UINT, kWebMIdColorBitsPerChannel},
210 {UINT, kWebMIdColorChromaSubsamplingHorz},
211 {UINT, kWebMIdColorChromaSubsamplingVert},
212 {UINT, kWebMIdColorCbSamplingHorz},
213 {UINT, kWebMIdColorCbSamplingVert},
214 {UINT, kWebMIdColorChromaSitingHorz},
215 {UINT, kWebMIdColorChromaSitingVert},
216 {UINT, kWebMIdColorRange},
217 {UINT, kWebMIdColorTransferCharacteristics},
218 {UINT, kWebMIdColorPrimaries},
219 {UINT, kWebMIdColorMaxCLL},
220 {UINT, kWebMIdColorMaxFALL},
221 {LIST, kWebMIdColorMasteringMetadata},
224 static const ElementIdInfo kProjectionIds[] = {
225 {UINT, kWebMIdProjectionType},
228 static const ElementIdInfo kAudioIds[] = {
229 {FLOAT, kWebMIdSamplingFrequency},
230 {FLOAT, kWebMIdOutputSamplingFrequency},
231 {UINT, kWebMIdChannels},
232 {UINT, kWebMIdBitDepth},
235 static const ElementIdInfo kTrackOperationIds[] = {
236 {LIST, kWebMIdTrackCombinePlanes},
237 {LIST, kWebMIdJoinBlocks},
240 static const ElementIdInfo kTrackCombinePlanesIds[] = {
241 {LIST, kWebMIdTrackPlane},
244 static const ElementIdInfo kTrackPlaneIds[] = {
245 {UINT, kWebMIdTrackPlaneUID},
246 {UINT, kWebMIdTrackPlaneType},
249 static const ElementIdInfo kJoinBlocksIds[] = {
250 {UINT, kWebMIdTrackJoinUID},
253 static const ElementIdInfo kContentEncodingsIds[] = {
254 {LIST, kWebMIdContentEncoding},
257 static const ElementIdInfo kContentEncodingIds[] = {
258 {UINT, kWebMIdContentEncodingOrder},
259 {UINT, kWebMIdContentEncodingScope},
260 {UINT, kWebMIdContentEncodingType},
261 {LIST, kWebMIdContentCompression},
262 {LIST, kWebMIdContentEncryption},
265 static const ElementIdInfo kContentCompressionIds[] = {
266 {UINT, kWebMIdContentCompAlgo},
267 {BINARY, kWebMIdContentCompSettings},
270 static const ElementIdInfo kContentEncryptionIds[] = {
271 {LIST, kWebMIdContentEncAESSettings},
272 {UINT, kWebMIdContentEncAlgo},
273 {BINARY, kWebMIdContentEncKeyID},
274 {BINARY, kWebMIdContentSignature},
275 {BINARY, kWebMIdContentSigKeyID},
276 {UINT, kWebMIdContentSigAlgo},
277 {UINT, kWebMIdContentSigHashAlgo},
280 static const ElementIdInfo kContentEncAESSettingsIds[] = {
281 {UINT, kWebMIdAESSettingsCipherMode},
284 static const ElementIdInfo kCuesIds[] = {
285 {LIST, kWebMIdCuePoint},
288 static const ElementIdInfo kCuePointIds[] = {
289 {UINT, kWebMIdCueTime},
290 {LIST, kWebMIdCueTrackPositions},
293 static const ElementIdInfo kCueTrackPositionsIds[] = {
294 {UINT, kWebMIdCueTrack},
295 {UINT, kWebMIdCueClusterPosition},
296 {UINT, kWebMIdCueBlockNumber},
297 {UINT, kWebMIdCueCodecState},
298 {LIST, kWebMIdCueReference},
301 static const ElementIdInfo kCueReferenceIds[] = {
302 {UINT, kWebMIdCueRefTime},
305 static const ElementIdInfo kAttachmentsIds[] = {
306 {LIST, kWebMIdAttachedFile},
309 static const ElementIdInfo kAttachedFileIds[] = {
310 {STRING, kWebMIdFileDescription},
311 {STRING, kWebMIdFileName},
312 {STRING, kWebMIdFileMimeType},
313 {BINARY, kWebMIdFileData},
314 {UINT, kWebMIdFileUID},
317 static const ElementIdInfo kChaptersIds[] = {
318 {LIST, kWebMIdEditionEntry},
321 static const ElementIdInfo kEditionEntryIds[] = {
322 {UINT, kWebMIdEditionUID},
323 {UINT, kWebMIdEditionFlagHidden},
324 {UINT, kWebMIdEditionFlagDefault},
325 {UINT, kWebMIdEditionFlagOrdered},
326 {LIST, kWebMIdChapterAtom},
329 static const ElementIdInfo kChapterAtomIds[] = {
330 {UINT, kWebMIdChapterUID},
331 {UINT, kWebMIdChapterTimeStart},
332 {UINT, kWebMIdChapterTimeEnd},
333 {UINT, kWebMIdChapterFlagHidden},
334 {UINT, kWebMIdChapterFlagEnabled},
335 {BINARY, kWebMIdChapterSegmentUID},
336 {UINT, kWebMIdChapterSegmentEditionUID},
337 {UINT, kWebMIdChapterPhysicalEquiv},
338 {LIST, kWebMIdChapterTrack},
339 {LIST, kWebMIdChapterDisplay},
340 {LIST, kWebMIdChapProcess},
343 static const ElementIdInfo kChapterTrackIds[] = {
344 {UINT, kWebMIdChapterTrackNumber},
347 static const ElementIdInfo kChapterDisplayIds[] = {
348 {STRING, kWebMIdChapString},
349 {STRING, kWebMIdChapLanguage},
350 {STRING, kWebMIdChapCountry},
353 static const ElementIdInfo kChapProcessIds[] = {
354 {UINT, kWebMIdChapProcessCodecID},
355 {BINARY, kWebMIdChapProcessPrivate},
356 {LIST, kWebMIdChapProcessCommand},
359 static const ElementIdInfo kChapProcessCommandIds[] = {
360 {UINT, kWebMIdChapProcessTime},
361 {BINARY, kWebMIdChapProcessData},
364 static const ElementIdInfo kTagsIds[] = {
368 static const ElementIdInfo kTagIds[] = {
369 {LIST, kWebMIdTargets},
370 {LIST, kWebMIdSimpleTag},
373 static const ElementIdInfo kTargetsIds[] = {
374 {UINT, kWebMIdTargetTypeValue},
375 {STRING, kWebMIdTargetType},
376 {UINT, kWebMIdTagTrackUID},
377 {UINT, kWebMIdTagEditionUID},
378 {UINT, kWebMIdTagChapterUID},
379 {UINT, kWebMIdTagAttachmentUID},
382 static const ElementIdInfo kSimpleTagIds[] = {
383 {STRING, kWebMIdTagName},
384 {STRING, kWebMIdTagLanguage},
385 {UINT, kWebMIdTagDefault},
386 {STRING, kWebMIdTagString},
387 {BINARY, kWebMIdTagBinary},
390 #define LIST_ELEMENT_INFO(id, level, id_info) \
391 { (id), (level), (id_info), std::size(id_info) }
393 static const ListElementInfo kListElementInfo[] = {
394 LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds),
395 LIST_ELEMENT_INFO(kWebMIdEBMLHeader, 0, kEBMLHeaderIds),
396 LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds),
397 LIST_ELEMENT_INFO(kWebMIdSeekHead, 1, kSeekHeadIds),
398 LIST_ELEMENT_INFO(kWebMIdSeek, 2, kSeekIds),
399 LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds),
400 LIST_ELEMENT_INFO(kWebMIdChapterTranslate, 2, kChapterTranslateIds),
401 LIST_ELEMENT_INFO(kWebMIdSilentTracks, 2, kSilentTracksIds),
402 LIST_ELEMENT_INFO(kWebMIdBlockGroup, 2, kBlockGroupIds),
403 LIST_ELEMENT_INFO(kWebMIdBlockAdditions, 3, kBlockAdditionsIds),
404 LIST_ELEMENT_INFO(kWebMIdBlockMore, 4, kBlockMoreIds),
405 LIST_ELEMENT_INFO(kWebMIdSlices, 3, kSlicesIds),
406 LIST_ELEMENT_INFO(kWebMIdTimeSlice, 4, kTimeSliceIds),
407 LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds),
408 LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds),
409 LIST_ELEMENT_INFO(kWebMIdTrackTranslate, 3, kTrackTranslateIds),
410 LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds),
411 LIST_ELEMENT_INFO(kWebMIdColor, 4, kColorIds),
412 LIST_ELEMENT_INFO(kWebMIdProjection, 4, kProjectionIds),
413 LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds),
414 LIST_ELEMENT_INFO(kWebMIdTrackOperation, 3, kTrackOperationIds),
415 LIST_ELEMENT_INFO(kWebMIdTrackCombinePlanes, 4, kTrackCombinePlanesIds),
416 LIST_ELEMENT_INFO(kWebMIdTrackPlane, 5, kTrackPlaneIds),
417 LIST_ELEMENT_INFO(kWebMIdJoinBlocks, 4, kJoinBlocksIds),
418 LIST_ELEMENT_INFO(kWebMIdContentEncodings, 3, kContentEncodingsIds),
419 LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds),
420 LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds),
421 LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds),
422 LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings, 6, kContentEncAESSettingsIds),
423 LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds),
424 LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds),
425 LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds),
426 LIST_ELEMENT_INFO(kWebMIdCueReference, 4, kCueReferenceIds),
427 LIST_ELEMENT_INFO(kWebMIdAttachments, 1, kAttachmentsIds),
428 LIST_ELEMENT_INFO(kWebMIdAttachedFile, 2, kAttachedFileIds),
429 LIST_ELEMENT_INFO(kWebMIdChapters, 1, kChaptersIds),
430 LIST_ELEMENT_INFO(kWebMIdEditionEntry, 2, kEditionEntryIds),
431 LIST_ELEMENT_INFO(kWebMIdChapterAtom, 3, kChapterAtomIds),
432 LIST_ELEMENT_INFO(kWebMIdChapterTrack, 4, kChapterTrackIds),
433 LIST_ELEMENT_INFO(kWebMIdChapterDisplay, 4, kChapterDisplayIds),
434 LIST_ELEMENT_INFO(kWebMIdChapProcess, 4, kChapProcessIds),
435 LIST_ELEMENT_INFO(kWebMIdChapProcessCommand, 5, kChapProcessCommandIds),
436 LIST_ELEMENT_INFO(kWebMIdTags, 1, kTagsIds),
437 LIST_ELEMENT_INFO(kWebMIdTag, 2, kTagIds),
438 LIST_ELEMENT_INFO(kWebMIdTargets, 3, kTargetsIds),
439 LIST_ELEMENT_INFO(kWebMIdSimpleTag, 3, kSimpleTagIds),
455 static int ParseWebMElementHeaderField(
const uint8_t* buf,
458 bool mask_first_byte,
471 int extra_bytes = -1;
472 bool all_ones =
false;
473 for (
int i = 0; i < max_bytes; ++i) {
474 if ((ch & mask) != 0) {
476 *num = mask_first_byte ? ch & mask : ch;
477 all_ones = (ch & mask) == mask;
481 mask = 0x80 | mask >> 1;
484 if (extra_bytes == -1)
488 if ((1 + extra_bytes) > size)
493 for (
int i = 0; i < extra_bytes; ++i) {
494 ch = buf[bytes_used++];
495 all_ones &= (ch == 0xff);
496 *num = (*num << 8) | ch;
500 *num = std::numeric_limits<int64_t>::max();
505 int WebMParseElementHeader(
const uint8_t* buf,
508 int64_t* element_size) {
512 DCHECK(element_size);
518 int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4,
false, &tmp);
520 if (num_id_bytes <= 0)
523 if (tmp == std::numeric_limits<int64_t>::max())
524 tmp = kWebMReservedId;
526 *
id =
static_cast<int>(tmp);
528 int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes,
532 if (num_size_bytes <= 0)
533 return num_size_bytes;
535 if (tmp == std::numeric_limits<int64_t>::max())
536 tmp = kWebMUnknownSize;
539 DVLOG(3) <<
"WebMParseElementHeader() : id " << std::hex << *
id << std::dec
540 <<
" size " << *element_size;
541 return num_id_bytes + num_size_bytes;
545 static ElementType FindIdType(
int id,
546 const ElementIdInfo* id_info,
550 if (
id == kWebMIdVoid ||
id == kWebMIdCRC32)
553 for (
int i = 0; i < id_info_count; ++i) {
554 if (
id == id_info[i].id_)
555 return id_info[i].type_;
562 static const ListElementInfo* FindListInfo(
int id) {
563 for (
size_t i = 0; i < std::size(kListElementInfo); ++i) {
564 if (
id == kListElementInfo[i].id_)
565 return &kListElementInfo[i];
571 static int FindListLevel(
int id) {
572 const ListElementInfo* list_info = FindListInfo(
id);
574 return list_info->level_;
579 static int ParseUInt(
const uint8_t* buf,
582 WebMParserClient* client) {
583 if ((size <= 0) || (size > 8))
588 for (
int i = 0; i < size; ++i)
589 value = (value << 8) | buf[i];
594 if (value >
static_cast<uint64_t
>(std::numeric_limits<int64_t>::max()))
597 if (!client->OnUInt(
id, value))
603 static int ParseFloat(
const uint8_t* buf,
606 WebMParserClient* client) {
607 if ((size != 4) && (size != 8))
614 for (
int i = 0; i < size; ++i)
615 tmp = (tmp << 8) | buf[i];
624 tmp2.src =
static_cast<int32_t
>(tmp);
626 }
else if (size == 8) {
637 if (!client->OnFloat(
id, value))
643 static int ParseBinary(
const uint8_t* buf,
646 WebMParserClient* client) {
647 return client->OnBinary(
id, buf, size) ? size : -1;
650 static int ParseString(
const uint8_t* buf,
653 WebMParserClient* client) {
654 const uint8_t* end =
static_cast<const uint8_t*
>(memchr(buf,
'\0', size));
655 int length = (end != NULL) ?
static_cast<int>(end - buf) : size;
656 std::string str(
reinterpret_cast<const char*
>(buf), length);
657 return client->OnString(
id, str) ? size : -1;
660 static int ParseNonListElement(ElementType type,
662 int64_t element_size,
665 WebMParserClient* client) {
666 DCHECK_GE(size, element_size);
675 result = ParseUInt(buf, element_size,
id, client);
678 result = ParseFloat(buf, element_size,
id, client);
681 result = ParseBinary(buf, element_size,
id, client);
684 result = ParseString(buf, element_size,
id, client);
687 result = element_size;
690 DVLOG(1) <<
"Unhandled ID type " << type;
694 DCHECK_LE(result, size);
698 WebMParserClient::WebMParserClient() {}
699 WebMParserClient::~WebMParserClient() {}
701 WebMParserClient* WebMParserClient::OnListStart(
int id) {
702 DVLOG(1) <<
"Unexpected list element start with ID " << std::hex << id;
706 bool WebMParserClient::OnListEnd(
int id) {
707 DVLOG(1) <<
"Unexpected list element end with ID " << std::hex << id;
711 bool WebMParserClient::OnUInt(
int id, int64_t ) {
712 DVLOG(1) <<
"Unexpected unsigned integer element with ID " << std::hex << id;
716 bool WebMParserClient::OnFloat(
int id,
double ) {
717 DVLOG(1) <<
"Unexpected float element with ID " << std::hex << id;
721 bool WebMParserClient::OnBinary(
int id,
const uint8_t* ,
int ) {
722 DVLOG(1) <<
"Unexpected binary element with ID " << std::hex << id;
726 bool WebMParserClient::OnString(
int id,
const std::string& ) {
727 DVLOG(1) <<
"Unexpected string element with ID " << std::hex << id;
732 : state_(NEED_LIST_HEADER),
734 root_level_(FindListLevel(id)),
735 root_client_(client) {
736 DCHECK_GE(root_level_, 0);
740 WebMListParser::~WebMListParser() {}
743 ChangeState(NEED_LIST_HEADER);
744 list_state_stack_.clear();
750 if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
756 const uint8_t* cur = buf;
758 int bytes_parsed = 0;
760 while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
762 int64_t element_size = 0;
763 int result = WebMParseElementHeader(cur, cur_size, &element_id,
773 case NEED_LIST_HEADER: {
774 if (element_id != root_id_) {
775 ChangeState(PARSE_ERROR);
780 if (element_size == kWebMUnknownSize &&
781 (element_id != kWebMIdSegment) &&
782 (element_id != kWebMIdCluster)) {
783 ChangeState(PARSE_ERROR);
787 ChangeState(INSIDE_LIST);
788 if (!OnListStart(root_id_, element_size))
795 int header_size = result;
796 const uint8_t* element_data = cur + header_size;
797 int element_data_size = cur_size - header_size;
799 if (element_size < element_data_size)
800 element_data_size = element_size;
802 result = ParseListElement(header_size, element_id, element_size,
803 element_data, element_data_size);
805 DCHECK_LE(result, header_size + element_data_size);
807 ChangeState(PARSE_ERROR);
816 case DONE_PARSING_LIST:
825 bytes_parsed += result;
828 return (state_ == PARSE_ERROR) ? -1 : bytes_parsed;
832 return state_ == DONE_PARSING_LIST;
835 void WebMListParser::ChangeState(State new_state) {
839 int WebMListParser::ParseListElement(
int header_size,
841 int64_t element_size,
844 DCHECK_GT(list_state_stack_.size(), 0u);
846 ListState& list_state = list_state_stack_.back();
847 DCHECK(list_state.element_info_);
849 const ListElementInfo* element_info = list_state.element_info_;
850 ElementType id_type =
851 FindIdType(
id, element_info->id_info_, element_info->id_info_count_);
854 if (id_type == UNKNOWN) {
855 if (list_state.size_ != kWebMUnknownSize ||
856 !IsSiblingOrAncestor(list_state.id_,
id)) {
857 DVLOG(1) <<
"No ElementType info for ID 0x" << std::hex << id;
863 list_state.size_ = list_state.bytes_parsed_;
869 if (list_state_stack_.size() == 0)
872 list_state = list_state_stack_.back();
876 int64_t total_element_size = header_size + element_size;
877 if (list_state.size_ != kWebMUnknownSize &&
878 list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
882 if (id_type == LIST) {
883 list_state.bytes_parsed_ += header_size;
885 if (!OnListStart(
id, element_size))
892 if (size < element_size)
895 int bytes_parsed = ParseNonListElement(id_type,
id, element_size,
896 data, size, list_state.client_);
897 DCHECK_LE(bytes_parsed, size);
903 if (bytes_parsed < 0 || (bytes_parsed == 0 && element_size != 0))
906 int result = header_size + bytes_parsed;
907 list_state.bytes_parsed_ += result;
910 if (list_state.bytes_parsed_ == list_state.size_) {
918 bool WebMListParser::OnListStart(
int id, int64_t size) {
919 const ListElementInfo* element_info = FindListInfo(
id);
924 root_level_ +
static_cast<int>(list_state_stack_.size()) - 1;
925 if (current_level + 1 != element_info->level_)
928 WebMParserClient* current_list_client = NULL;
929 if (!list_state_stack_.empty()) {
931 ListState current_list_state = list_state_stack_.back();
932 if (current_list_state.size_ != kWebMUnknownSize &&
933 current_list_state.size_ < current_list_state.bytes_parsed_ + size)
935 current_list_client = current_list_state.client_;
937 current_list_client = root_client_;
940 WebMParserClient* new_list_client = current_list_client->OnListStart(
id);
941 if (!new_list_client)
944 ListState new_list_state = { id, size, 0, element_info, new_list_client };
945 list_state_stack_.push_back(new_list_state);
953 bool WebMListParser::OnListEnd() {
955 for (; !list_state_stack_.empty(); ++lists_ended) {
956 const ListState& list_state = list_state_stack_.back();
957 int64_t bytes_parsed = list_state.bytes_parsed_;
958 int id = list_state.id_;
960 if (bytes_parsed != list_state.size_)
963 list_state_stack_.pop_back();
965 WebMParserClient* client = NULL;
966 if (!list_state_stack_.empty()) {
968 list_state_stack_.back().bytes_parsed_ += bytes_parsed;
969 client = list_state_stack_.back().client_;
971 client = root_client_;
974 if (!client->OnListEnd(
id))
978 DCHECK_GE(lists_ended, 1);
980 if (list_state_stack_.empty())
981 ChangeState(DONE_PARSING_LIST);
986 bool WebMListParser::IsSiblingOrAncestor(
int id_a,
int id_b)
const {
987 DCHECK((id_a == kWebMIdSegment) || (id_a == kWebMIdCluster));
989 if (id_a == kWebMIdCluster) {
991 for (
size_t i = 0; i < std::size(kSegmentIds); i++) {
992 if (kSegmentIds[i].id_ == id_b)
998 return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader));
All the methods that are virtual are virtual for mocking.