Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / media / formats / webm / webm_parser.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/formats/webm/webm_parser.h"
6
7 // This file contains code to parse WebM file elements. It was created
8 // from information in the Matroska spec.
9 // http://www.matroska.org/technical/specs/index.html
10 // This file contains code for encrypted WebM. Current WebM
11 // encrypted request for comments specification is here
12 // http://wiki.webmproject.org/encryption/webm-encryption-rfc
13
14 #include <iomanip>
15
16 #include "base/logging.h"
17 #include "base/numerics/safe_conversions.h"
18 #include "media/formats/webm/webm_constants.h"
19
20 namespace media {
21
22 enum ElementType {
23   UNKNOWN,
24   LIST,  // Referred to as Master Element in the Matroska spec.
25   UINT,
26   FLOAT,
27   BINARY,
28   STRING,
29   SKIP,
30 };
31
32 struct ElementIdInfo {
33   ElementType type_;
34   int id_;
35 };
36
37 struct ListElementInfo {
38   int id_;
39   int level_;
40   const ElementIdInfo* id_info_;
41   int id_info_count_;
42 };
43
44 // The following are tables indicating what IDs are valid sub-elements
45 // of particular elements. If an element is encountered that doesn't
46 // appear in the list, a parsing error is signalled. Some elements are
47 // marked as SKIP because they are valid, but we don't care about them
48 // right now.
49 static const ElementIdInfo kEBMLHeaderIds[] = {
50   {UINT, kWebMIdEBMLVersion},
51   {UINT, kWebMIdEBMLReadVersion},
52   {UINT, kWebMIdEBMLMaxIDLength},
53   {UINT, kWebMIdEBMLMaxSizeLength},
54   {STRING, kWebMIdDocType},
55   {UINT, kWebMIdDocTypeVersion},
56   {UINT, kWebMIdDocTypeReadVersion},
57 };
58
59 static const ElementIdInfo kSegmentIds[] = {
60   {LIST, kWebMIdSeekHead},
61   {LIST, kWebMIdInfo},
62   {LIST, kWebMIdCluster},
63   {LIST, kWebMIdTracks},
64   {LIST, kWebMIdCues},
65   {LIST, kWebMIdAttachments},
66   {LIST, kWebMIdChapters},
67   {LIST, kWebMIdTags},
68 };
69
70 static const ElementIdInfo kSeekHeadIds[] = {
71   {LIST, kWebMIdSeek},
72 };
73
74 static const ElementIdInfo kSeekIds[] = {
75   {BINARY, kWebMIdSeekID},
76   {UINT, kWebMIdSeekPosition},
77 };
78
79 static const ElementIdInfo kInfoIds[] = {
80   {BINARY, kWebMIdSegmentUID},
81   {STRING, kWebMIdSegmentFilename},
82   {BINARY, kWebMIdPrevUID},
83   {STRING, kWebMIdPrevFilename},
84   {BINARY, kWebMIdNextUID},
85   {STRING, kWebMIdNextFilename},
86   {BINARY, kWebMIdSegmentFamily},
87   {LIST, kWebMIdChapterTranslate},
88   {UINT, kWebMIdTimecodeScale},
89   {FLOAT, kWebMIdDuration},
90   {BINARY, kWebMIdDateUTC},
91   {STRING, kWebMIdTitle},
92   {STRING, kWebMIdMuxingApp},
93   {STRING, kWebMIdWritingApp},
94 };
95
96 static const ElementIdInfo kChapterTranslateIds[] = {
97   {UINT, kWebMIdChapterTranslateEditionUID},
98   {UINT, kWebMIdChapterTranslateCodec},
99   {BINARY, kWebMIdChapterTranslateID},
100 };
101
102 static const ElementIdInfo kClusterIds[] = {
103   {BINARY, kWebMIdSimpleBlock},
104   {UINT, kWebMIdTimecode},
105   {LIST, kWebMIdSilentTracks},
106   {UINT, kWebMIdPosition},
107   {UINT, kWebMIdPrevSize},
108   {LIST, kWebMIdBlockGroup},
109 };
110
111 static const ElementIdInfo kSilentTracksIds[] = {
112   {UINT, kWebMIdSilentTrackNumber},
113 };
114
115 static const ElementIdInfo kBlockGroupIds[] = {
116   {BINARY, kWebMIdBlock},
117   {LIST, kWebMIdBlockAdditions},
118   {UINT, kWebMIdBlockDuration},
119   {UINT, kWebMIdReferencePriority},
120   {BINARY, kWebMIdReferenceBlock},
121   {BINARY, kWebMIdCodecState},
122   {BINARY, kWebMIdDiscardPadding},
123   {LIST, kWebMIdSlices},
124 };
125
126 static const ElementIdInfo kBlockAdditionsIds[] = {
127   {LIST, kWebMIdBlockMore},
128 };
129
130 static const ElementIdInfo kBlockMoreIds[] = {
131   {UINT, kWebMIdBlockAddID},
132   {BINARY, kWebMIdBlockAdditional},
133 };
134
135 static const ElementIdInfo kSlicesIds[] = {
136   {LIST, kWebMIdTimeSlice},
137 };
138
139 static const ElementIdInfo kTimeSliceIds[] = {
140   {UINT, kWebMIdLaceNumber},
141 };
142
143 static const ElementIdInfo kTracksIds[] = {
144   {LIST, kWebMIdTrackEntry},
145 };
146
147 static const ElementIdInfo kTrackEntryIds[] = {
148   {UINT, kWebMIdTrackNumber},
149   {UINT, kWebMIdTrackUID},
150   {UINT, kWebMIdTrackType},
151   {UINT, kWebMIdFlagEnabled},
152   {UINT, kWebMIdFlagDefault},
153   {UINT, kWebMIdFlagForced},
154   {UINT, kWebMIdFlagLacing},
155   {UINT, kWebMIdMinCache},
156   {UINT, kWebMIdMaxCache},
157   {UINT, kWebMIdDefaultDuration},
158   {FLOAT, kWebMIdTrackTimecodeScale},
159   {UINT, kWebMIdMaxBlockAdditionId},
160   {STRING, kWebMIdName},
161   {STRING, kWebMIdLanguage},
162   {STRING, kWebMIdCodecID},
163   {BINARY, kWebMIdCodecPrivate},
164   {STRING, kWebMIdCodecName},
165   {UINT, kWebMIdAttachmentLink},
166   {UINT, kWebMIdCodecDecodeAll},
167   {UINT, kWebMIdTrackOverlay},
168   {UINT, kWebMIdCodecDelay},
169   {UINT, kWebMIdSeekPreRoll},
170   {LIST, kWebMIdTrackTranslate},
171   {LIST, kWebMIdVideo},
172   {LIST, kWebMIdAudio},
173   {LIST, kWebMIdTrackOperation},
174   {LIST, kWebMIdContentEncodings},
175 };
176
177 static const ElementIdInfo kTrackTranslateIds[] = {
178   {UINT, kWebMIdTrackTranslateEditionUID},
179   {UINT, kWebMIdTrackTranslateCodec},
180   {BINARY, kWebMIdTrackTranslateTrackID},
181 };
182
183 static const ElementIdInfo kVideoIds[] = {
184   {UINT, kWebMIdFlagInterlaced},
185   {UINT, kWebMIdStereoMode},
186   {UINT, kWebMIdAlphaMode},
187   {UINT, kWebMIdPixelWidth},
188   {UINT, kWebMIdPixelHeight},
189   {UINT, kWebMIdPixelCropBottom},
190   {UINT, kWebMIdPixelCropTop},
191   {UINT, kWebMIdPixelCropLeft},
192   {UINT, kWebMIdPixelCropRight},
193   {UINT, kWebMIdDisplayWidth},
194   {UINT, kWebMIdDisplayHeight},
195   {UINT, kWebMIdDisplayUnit},
196   {UINT, kWebMIdAspectRatioType},
197   {BINARY, kWebMIdColorSpace},
198   {FLOAT, kWebMIdFrameRate},
199 };
200
201 static const ElementIdInfo kAudioIds[] = {
202   {FLOAT, kWebMIdSamplingFrequency},
203   {FLOAT, kWebMIdOutputSamplingFrequency},
204   {UINT, kWebMIdChannels},
205   {UINT, kWebMIdBitDepth},
206 };
207
208 static const ElementIdInfo kTrackOperationIds[] = {
209   {LIST, kWebMIdTrackCombinePlanes},
210   {LIST, kWebMIdJoinBlocks},
211 };
212
213 static const ElementIdInfo kTrackCombinePlanesIds[] = {
214   {LIST, kWebMIdTrackPlane},
215 };
216
217 static const ElementIdInfo kTrackPlaneIds[] = {
218   {UINT, kWebMIdTrackPlaneUID},
219   {UINT, kWebMIdTrackPlaneType},
220 };
221
222 static const ElementIdInfo kJoinBlocksIds[] = {
223   {UINT, kWebMIdTrackJoinUID},
224 };
225
226 static const ElementIdInfo kContentEncodingsIds[] = {
227   {LIST, kWebMIdContentEncoding},
228 };
229
230 static const ElementIdInfo kContentEncodingIds[] = {
231   {UINT, kWebMIdContentEncodingOrder},
232   {UINT, kWebMIdContentEncodingScope},
233   {UINT, kWebMIdContentEncodingType},
234   {LIST, kWebMIdContentCompression},
235   {LIST, kWebMIdContentEncryption},
236 };
237
238 static const ElementIdInfo kContentCompressionIds[] = {
239   {UINT, kWebMIdContentCompAlgo},
240   {BINARY, kWebMIdContentCompSettings},
241 };
242
243 static const ElementIdInfo kContentEncryptionIds[] = {
244   {LIST, kWebMIdContentEncAESSettings},
245   {UINT, kWebMIdContentEncAlgo},
246   {BINARY, kWebMIdContentEncKeyID},
247   {BINARY, kWebMIdContentSignature},
248   {BINARY, kWebMIdContentSigKeyID},
249   {UINT, kWebMIdContentSigAlgo},
250   {UINT, kWebMIdContentSigHashAlgo},
251 };
252
253 static const ElementIdInfo kContentEncAESSettingsIds[] = {
254   {UINT, kWebMIdAESSettingsCipherMode},
255 };
256
257 static const ElementIdInfo kCuesIds[] = {
258   {LIST, kWebMIdCuePoint},
259 };
260
261 static const ElementIdInfo kCuePointIds[] = {
262   {UINT, kWebMIdCueTime},
263   {LIST, kWebMIdCueTrackPositions},
264 };
265
266 static const ElementIdInfo kCueTrackPositionsIds[] = {
267   {UINT, kWebMIdCueTrack},
268   {UINT, kWebMIdCueClusterPosition},
269   {UINT, kWebMIdCueBlockNumber},
270   {UINT, kWebMIdCueCodecState},
271   {LIST, kWebMIdCueReference},
272 };
273
274 static const ElementIdInfo kCueReferenceIds[] = {
275   {UINT, kWebMIdCueRefTime},
276 };
277
278 static const ElementIdInfo kAttachmentsIds[] = {
279   {LIST, kWebMIdAttachedFile},
280 };
281
282 static const ElementIdInfo kAttachedFileIds[] = {
283   {STRING, kWebMIdFileDescription},
284   {STRING, kWebMIdFileName},
285   {STRING, kWebMIdFileMimeType},
286   {BINARY, kWebMIdFileData},
287   {UINT, kWebMIdFileUID},
288 };
289
290 static const ElementIdInfo kChaptersIds[] = {
291   {LIST, kWebMIdEditionEntry},
292 };
293
294 static const ElementIdInfo kEditionEntryIds[] = {
295   {UINT, kWebMIdEditionUID},
296   {UINT, kWebMIdEditionFlagHidden},
297   {UINT, kWebMIdEditionFlagDefault},
298   {UINT, kWebMIdEditionFlagOrdered},
299   {LIST, kWebMIdChapterAtom},
300 };
301
302 static const ElementIdInfo kChapterAtomIds[] = {
303   {UINT, kWebMIdChapterUID},
304   {UINT, kWebMIdChapterTimeStart},
305   {UINT, kWebMIdChapterTimeEnd},
306   {UINT, kWebMIdChapterFlagHidden},
307   {UINT, kWebMIdChapterFlagEnabled},
308   {BINARY, kWebMIdChapterSegmentUID},
309   {UINT, kWebMIdChapterSegmentEditionUID},
310   {UINT, kWebMIdChapterPhysicalEquiv},
311   {LIST, kWebMIdChapterTrack},
312   {LIST, kWebMIdChapterDisplay},
313   {LIST, kWebMIdChapProcess},
314 };
315
316 static const ElementIdInfo kChapterTrackIds[] = {
317   {UINT, kWebMIdChapterTrackNumber},
318 };
319
320 static const ElementIdInfo kChapterDisplayIds[] = {
321   {STRING, kWebMIdChapString},
322   {STRING, kWebMIdChapLanguage},
323   {STRING, kWebMIdChapCountry},
324 };
325
326 static const ElementIdInfo kChapProcessIds[] = {
327   {UINT, kWebMIdChapProcessCodecID},
328   {BINARY, kWebMIdChapProcessPrivate},
329   {LIST, kWebMIdChapProcessCommand},
330 };
331
332 static const ElementIdInfo kChapProcessCommandIds[] = {
333   {UINT, kWebMIdChapProcessTime},
334   {BINARY, kWebMIdChapProcessData},
335 };
336
337 static const ElementIdInfo kTagsIds[] = {
338   {LIST, kWebMIdTag},
339 };
340
341 static const ElementIdInfo kTagIds[] = {
342   {LIST, kWebMIdTargets},
343   {LIST, kWebMIdSimpleTag},
344 };
345
346 static const ElementIdInfo kTargetsIds[] = {
347   {UINT, kWebMIdTargetTypeValue},
348   {STRING, kWebMIdTargetType},
349   {UINT, kWebMIdTagTrackUID},
350   {UINT, kWebMIdTagEditionUID},
351   {UINT, kWebMIdTagChapterUID},
352   {UINT, kWebMIdTagAttachmentUID},
353 };
354
355 static const ElementIdInfo kSimpleTagIds[] = {
356   {STRING, kWebMIdTagName},
357   {STRING, kWebMIdTagLanguage},
358   {UINT, kWebMIdTagDefault},
359   {STRING, kWebMIdTagString},
360   {BINARY, kWebMIdTagBinary},
361 };
362
363 #define LIST_ELEMENT_INFO(id, level, id_info) \
364     { (id), (level), (id_info), arraysize(id_info) }
365
366 static const ListElementInfo kListElementInfo[] = {
367   LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds),
368   LIST_ELEMENT_INFO(kWebMIdEBMLHeader, 0, kEBMLHeaderIds),
369   LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds),
370   LIST_ELEMENT_INFO(kWebMIdSeekHead, 1, kSeekHeadIds),
371   LIST_ELEMENT_INFO(kWebMIdSeek, 2, kSeekIds),
372   LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds),
373   LIST_ELEMENT_INFO(kWebMIdChapterTranslate, 2, kChapterTranslateIds),
374   LIST_ELEMENT_INFO(kWebMIdSilentTracks, 2, kSilentTracksIds),
375   LIST_ELEMENT_INFO(kWebMIdBlockGroup, 2, kBlockGroupIds),
376   LIST_ELEMENT_INFO(kWebMIdBlockAdditions, 3, kBlockAdditionsIds),
377   LIST_ELEMENT_INFO(kWebMIdBlockMore, 4, kBlockMoreIds),
378   LIST_ELEMENT_INFO(kWebMIdSlices, 3, kSlicesIds),
379   LIST_ELEMENT_INFO(kWebMIdTimeSlice, 4, kTimeSliceIds),
380   LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds),
381   LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds),
382   LIST_ELEMENT_INFO(kWebMIdTrackTranslate, 3, kTrackTranslateIds),
383   LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds),
384   LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds),
385   LIST_ELEMENT_INFO(kWebMIdTrackOperation, 3, kTrackOperationIds),
386   LIST_ELEMENT_INFO(kWebMIdTrackCombinePlanes, 4, kTrackCombinePlanesIds),
387   LIST_ELEMENT_INFO(kWebMIdTrackPlane, 5, kTrackPlaneIds),
388   LIST_ELEMENT_INFO(kWebMIdJoinBlocks, 4, kJoinBlocksIds),
389   LIST_ELEMENT_INFO(kWebMIdContentEncodings, 3, kContentEncodingsIds),
390   LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds),
391   LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds),
392   LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds),
393   LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings, 6, kContentEncAESSettingsIds),
394   LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds),
395   LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds),
396   LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds),
397   LIST_ELEMENT_INFO(kWebMIdCueReference, 4, kCueReferenceIds),
398   LIST_ELEMENT_INFO(kWebMIdAttachments, 1, kAttachmentsIds),
399   LIST_ELEMENT_INFO(kWebMIdAttachedFile, 2, kAttachedFileIds),
400   LIST_ELEMENT_INFO(kWebMIdChapters, 1, kChaptersIds),
401   LIST_ELEMENT_INFO(kWebMIdEditionEntry, 2, kEditionEntryIds),
402   LIST_ELEMENT_INFO(kWebMIdChapterAtom, 3, kChapterAtomIds),
403   LIST_ELEMENT_INFO(kWebMIdChapterTrack, 4, kChapterTrackIds),
404   LIST_ELEMENT_INFO(kWebMIdChapterDisplay, 4, kChapterDisplayIds),
405   LIST_ELEMENT_INFO(kWebMIdChapProcess, 4, kChapProcessIds),
406   LIST_ELEMENT_INFO(kWebMIdChapProcessCommand, 5, kChapProcessCommandIds),
407   LIST_ELEMENT_INFO(kWebMIdTags, 1, kTagsIds),
408   LIST_ELEMENT_INFO(kWebMIdTag, 2, kTagIds),
409   LIST_ELEMENT_INFO(kWebMIdTargets, 3, kTargetsIds),
410   LIST_ELEMENT_INFO(kWebMIdSimpleTag, 3, kSimpleTagIds),
411 };
412
413 // Parses an element header id or size field. These fields are variable length
414 // encoded. The first byte indicates how many bytes the field occupies.
415 // |buf|  - The buffer to parse.
416 // |size| - The number of bytes in |buf|
417 // |max_bytes| - The maximum number of bytes the field can be. ID fields
418 //               set this to 4 & element size fields set this to 8. If the
419 //               first byte indicates a larger field size than this it is a
420 //               parser error.
421 // |mask_first_byte| - For element size fields the field length encoding bits
422 //                     need to be masked off. This parameter is true for
423 //                     element size fields and is false for ID field values.
424 //
425 // Returns: The number of bytes parsed on success. -1 on error.
426 static int ParseWebMElementHeaderField(const uint8* buf, int size,
427                                        int max_bytes, bool mask_first_byte,
428                                        int64* num) {
429   DCHECK(buf);
430   DCHECK(num);
431
432   if (size < 0)
433     return -1;
434
435   if (size == 0)
436     return 0;
437
438   int mask = 0x80;
439   uint8 ch = buf[0];
440   int extra_bytes = -1;
441   bool all_ones = false;
442   for (int i = 0; i < max_bytes; ++i) {
443     if ((ch & mask) != 0) {
444       mask = ~mask & 0xff;
445       *num = mask_first_byte ? ch & mask : ch;
446       all_ones = (ch & mask) == mask;
447       extra_bytes = i;
448       break;
449     }
450     mask = 0x80 | mask >> 1;
451   }
452
453   if (extra_bytes == -1)
454     return -1;
455
456   // Return 0 if we need more data.
457   if ((1 + extra_bytes) > size)
458     return 0;
459
460   int bytes_used = 1;
461
462   for (int i = 0; i < extra_bytes; ++i) {
463     ch = buf[bytes_used++];
464     all_ones &= (ch == 0xff);
465     *num = (*num << 8) | ch;
466   }
467
468   if (all_ones)
469     *num = kint64max;
470
471   return bytes_used;
472 }
473
474 int WebMParseElementHeader(const uint8* buf, int size,
475                            int* id, int64* element_size) {
476   DCHECK(buf);
477   DCHECK_GE(size, 0);
478   DCHECK(id);
479   DCHECK(element_size);
480
481   if (size == 0)
482     return 0;
483
484   int64 tmp = 0;
485   int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4, false, &tmp);
486
487   if (num_id_bytes <= 0)
488     return num_id_bytes;
489
490   if (tmp == kint64max)
491     tmp = kWebMReservedId;
492
493   *id = static_cast<int>(tmp);
494
495   int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes,
496                                                    size - num_id_bytes,
497                                                    8, true, &tmp);
498
499   if (num_size_bytes <= 0)
500     return num_size_bytes;
501
502   if (tmp == kint64max)
503     tmp = kWebMUnknownSize;
504
505   *element_size = tmp;
506   DVLOG(3) << "WebMParseElementHeader() : id " << std::hex << *id << std::dec
507            << " size " << *element_size;
508   return num_id_bytes + num_size_bytes;
509 }
510
511 // Finds ElementType for a specific ID.
512 static ElementType FindIdType(int id,
513                               const ElementIdInfo* id_info,
514                               int id_info_count) {
515
516   // Check for global element IDs that can be anywhere.
517   if (id == kWebMIdVoid || id == kWebMIdCRC32)
518     return SKIP;
519
520   for (int i = 0; i < id_info_count; ++i) {
521     if (id == id_info[i].id_)
522       return id_info[i].type_;
523   }
524
525   return UNKNOWN;
526 }
527
528 // Finds ListElementInfo for a specific ID.
529 static const ListElementInfo* FindListInfo(int id) {
530   for (size_t i = 0; i < arraysize(kListElementInfo); ++i) {
531     if (id == kListElementInfo[i].id_)
532       return &kListElementInfo[i];
533   }
534
535   return NULL;
536 }
537
538 static int FindListLevel(int id) {
539   const ListElementInfo* list_info = FindListInfo(id);
540   if (list_info)
541     return list_info->level_;
542
543   return -1;
544 }
545
546 static int ParseUInt(const uint8* buf, int size, int id,
547                      WebMParserClient* client) {
548   if ((size <= 0) || (size > 8))
549     return -1;
550
551   // Read in the big-endian integer.
552   uint64 value = 0;
553   for (int i = 0; i < size; ++i)
554     value = (value << 8) | buf[i];
555
556   // We use int64 in place of uint64 everywhere for convenience.  See this bug
557   // for more details: http://crbug.com/366750#c3
558   if (!base::IsValueInRangeForNumericType<int64>(value))
559     return -1;
560
561   if (!client->OnUInt(id, value))
562     return -1;
563
564   return size;
565 }
566
567 static int ParseFloat(const uint8* buf, int size, int id,
568                       WebMParserClient* client) {
569
570   if ((size != 4) && (size != 8))
571     return -1;
572
573   double value = -1;
574
575   // Read the bytes from big-endian form into a native endian integer.
576   int64 tmp = 0;
577   for (int i = 0; i < size; ++i)
578     tmp = (tmp << 8) | buf[i];
579
580   // Use a union to convert the integer bit pattern into a floating point
581   // number.
582   if (size == 4) {
583     union {
584       int32 src;
585       float dst;
586     } tmp2;
587     tmp2.src = static_cast<int32>(tmp);
588     value = tmp2.dst;
589   } else if (size == 8) {
590     union {
591       int64 src;
592       double dst;
593     } tmp2;
594     tmp2.src = tmp;
595     value = tmp2.dst;
596   } else {
597     return -1;
598   }
599
600   if (!client->OnFloat(id, value))
601     return -1;
602
603   return size;
604 }
605
606 static int ParseBinary(const uint8* buf, int size, int id,
607                        WebMParserClient* client) {
608   return client->OnBinary(id, buf, size) ? size : -1;
609 }
610
611 static int ParseString(const uint8* buf, int size, int id,
612                        WebMParserClient* client) {
613   const uint8* end = static_cast<const uint8*>(memchr(buf, '\0', size));
614   int length = (end != NULL) ? static_cast<int>(end - buf) : size;
615   std::string str(reinterpret_cast<const char*>(buf), length);
616   return client->OnString(id, str) ? size : -1;
617 }
618
619 static int ParseNonListElement(ElementType type, int id, int64 element_size,
620                                const uint8* buf, int size,
621                                WebMParserClient* client) {
622   DCHECK_GE(size, element_size);
623
624   int result = -1;
625   switch(type) {
626     case LIST:
627       NOTIMPLEMENTED();
628       result = -1;
629       break;
630     case UINT:
631       result = ParseUInt(buf, element_size, id, client);
632       break;
633     case FLOAT:
634       result = ParseFloat(buf, element_size, id, client);
635       break;
636     case BINARY:
637       result = ParseBinary(buf, element_size, id, client);
638       break;
639     case STRING:
640       result = ParseString(buf, element_size, id, client);
641       break;
642     case SKIP:
643       result = element_size;
644       break;
645     default:
646       DVLOG(1) << "Unhandled ID type " << type;
647       return -1;
648   };
649
650   DCHECK_LE(result, size);
651   return result;
652 }
653
654 WebMParserClient::WebMParserClient() {}
655 WebMParserClient::~WebMParserClient() {}
656
657 WebMParserClient* WebMParserClient::OnListStart(int id) {
658   DVLOG(1) << "Unexpected list element start with ID " << std::hex << id;
659   return NULL;
660 }
661
662 bool WebMParserClient::OnListEnd(int id) {
663   DVLOG(1) << "Unexpected list element end with ID " << std::hex << id;
664   return false;
665 }
666
667 bool WebMParserClient::OnUInt(int id, int64 val) {
668   DVLOG(1) << "Unexpected unsigned integer element with ID " << std::hex << id;
669   return false;
670 }
671
672 bool WebMParserClient::OnFloat(int id, double val) {
673   DVLOG(1) << "Unexpected float element with ID " << std::hex << id;
674   return false;
675 }
676
677 bool WebMParserClient::OnBinary(int id, const uint8* data, int size) {
678   DVLOG(1) << "Unexpected binary element with ID " << std::hex << id;
679   return false;
680 }
681
682 bool WebMParserClient::OnString(int id, const std::string& str) {
683   DVLOG(1) << "Unexpected string element with ID " << std::hex << id;
684   return false;
685 }
686
687 WebMListParser::WebMListParser(int id, WebMParserClient* client)
688     : state_(NEED_LIST_HEADER),
689       root_id_(id),
690       root_level_(FindListLevel(id)),
691       root_client_(client) {
692   DCHECK_GE(root_level_, 0);
693   DCHECK(client);
694 }
695
696 WebMListParser::~WebMListParser() {}
697
698 void WebMListParser::Reset() {
699   ChangeState(NEED_LIST_HEADER);
700   list_state_stack_.clear();
701 }
702
703 int WebMListParser::Parse(const uint8* buf, int size) {
704   DCHECK(buf);
705
706   if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
707     return -1;
708
709   if (size == 0)
710     return 0;
711
712   const uint8* cur = buf;
713   int cur_size = size;
714   int bytes_parsed = 0;
715
716   while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
717     int element_id = 0;
718     int64 element_size = 0;
719     int result = WebMParseElementHeader(cur, cur_size, &element_id,
720                                         &element_size);
721
722     if (result < 0)
723       return result;
724
725     if (result == 0)
726       return bytes_parsed;
727
728     switch(state_) {
729       case NEED_LIST_HEADER: {
730         if (element_id != root_id_) {
731           ChangeState(PARSE_ERROR);
732           return -1;
733         }
734
735         // Only allow Segment & Cluster to have an unknown size.
736         if (element_size == kWebMUnknownSize &&
737             (element_id != kWebMIdSegment) &&
738             (element_id != kWebMIdCluster)) {
739           ChangeState(PARSE_ERROR);
740           return -1;
741         }
742
743         ChangeState(INSIDE_LIST);
744         if (!OnListStart(root_id_, element_size))
745           return -1;
746
747         break;
748       }
749
750       case INSIDE_LIST: {
751         int header_size = result;
752         const uint8* element_data = cur + header_size;
753         int element_data_size = cur_size - header_size;
754
755         if (element_size < element_data_size)
756           element_data_size = element_size;
757
758         result = ParseListElement(header_size, element_id, element_size,
759                                   element_data, element_data_size);
760
761         DCHECK_LE(result, header_size + element_data_size);
762         if (result < 0) {
763           ChangeState(PARSE_ERROR);
764           return -1;
765         }
766
767         if (result == 0)
768           return bytes_parsed;
769
770         break;
771       }
772       case DONE_PARSING_LIST:
773       case PARSE_ERROR:
774         // Shouldn't be able to get here.
775         NOTIMPLEMENTED();
776         break;
777     }
778
779     cur += result;
780     cur_size -= result;
781     bytes_parsed += result;
782   }
783
784   return (state_ == PARSE_ERROR) ? -1 : bytes_parsed;
785 }
786
787 bool WebMListParser::IsParsingComplete() const {
788   return state_ == DONE_PARSING_LIST;
789 }
790
791 void WebMListParser::ChangeState(State new_state) {
792   state_ = new_state;
793 }
794
795 int WebMListParser::ParseListElement(int header_size,
796                                      int id, int64 element_size,
797                                      const uint8* data, int size) {
798   DCHECK_GT(list_state_stack_.size(), 0u);
799
800   ListState& list_state = list_state_stack_.back();
801   DCHECK(list_state.element_info_);
802
803   const ListElementInfo* element_info = list_state.element_info_;
804   ElementType id_type =
805       FindIdType(id, element_info->id_info_, element_info->id_info_count_);
806
807   // Unexpected ID.
808   if (id_type == UNKNOWN) {
809     if (list_state.size_ != kWebMUnknownSize ||
810         !IsSiblingOrAncestor(list_state.id_, id)) {
811       DVLOG(1) << "No ElementType info for ID 0x" << std::hex << id;
812       return -1;
813     }
814
815     // We've reached the end of a list of unknown size. Update the size now that
816     // we know it and dispatch the end of list calls.
817     list_state.size_ = list_state.bytes_parsed_;
818
819     if (!OnListEnd())
820       return -1;
821
822     // Check to see if all open lists have ended.
823     if (list_state_stack_.size() == 0)
824       return 0;
825
826     list_state = list_state_stack_.back();
827   }
828
829   // Make sure the whole element can fit inside the current list.
830   int64 total_element_size = header_size + element_size;
831   if (list_state.size_ != kWebMUnknownSize &&
832       list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
833     return -1;
834   }
835
836   if (id_type == LIST) {
837     list_state.bytes_parsed_ += header_size;
838
839     if (!OnListStart(id, element_size))
840       return -1;
841     return header_size;
842   }
843
844   // Make sure we have the entire element before trying to parse a non-list
845   // element.
846   if (size < element_size)
847     return 0;
848
849   int bytes_parsed = ParseNonListElement(id_type, id, element_size,
850                                          data, size, list_state.client_);
851   DCHECK_LE(bytes_parsed, size);
852
853   // Return if an error occurred or we need more data.
854   // Note: bytes_parsed is 0 for a successful parse of a size 0 element. We
855   // need to check the element_size to disambiguate the "need more data" case
856   // from a successful parse.
857   if (bytes_parsed < 0 || (bytes_parsed == 0 && element_size != 0))
858     return bytes_parsed;
859
860   int result = header_size + bytes_parsed;
861   list_state.bytes_parsed_ += result;
862
863   // See if we have reached the end of the current list.
864   if (list_state.bytes_parsed_ == list_state.size_) {
865     if (!OnListEnd())
866       return -1;
867   }
868
869   return result;
870 }
871
872 bool WebMListParser::OnListStart(int id, int64 size) {
873   const ListElementInfo* element_info = FindListInfo(id);
874   if (!element_info)
875     return false;
876
877   int current_level = root_level_ + list_state_stack_.size() - 1;
878   if (current_level + 1 != element_info->level_)
879     return false;
880
881   WebMParserClient* current_list_client = NULL;
882   if (!list_state_stack_.empty()) {
883     // Make sure the new list doesn't go past the end of the current list.
884     ListState current_list_state = list_state_stack_.back();
885     if (current_list_state.size_ != kWebMUnknownSize &&
886         current_list_state.size_ < current_list_state.bytes_parsed_ + size)
887       return false;
888     current_list_client = current_list_state.client_;
889   } else {
890     current_list_client = root_client_;
891   }
892
893   WebMParserClient* new_list_client = current_list_client->OnListStart(id);
894   if (!new_list_client)
895     return false;
896
897   ListState new_list_state = { id, size, 0, element_info, new_list_client };
898   list_state_stack_.push_back(new_list_state);
899
900   if (size == 0)
901     return OnListEnd();
902
903   return true;
904 }
905
906 bool WebMListParser::OnListEnd() {
907   int lists_ended = 0;
908   for (; !list_state_stack_.empty(); ++lists_ended) {
909     const ListState& list_state = list_state_stack_.back();
910
911     if (list_state.bytes_parsed_ != list_state.size_)
912       break;
913
914     list_state_stack_.pop_back();
915
916     int64 bytes_parsed = list_state.bytes_parsed_;
917     WebMParserClient* client = NULL;
918     if (!list_state_stack_.empty()) {
919       // Update the bytes_parsed_ for the parent element.
920       list_state_stack_.back().bytes_parsed_ += bytes_parsed;
921       client = list_state_stack_.back().client_;
922     } else {
923       client = root_client_;
924     }
925
926     if (!client->OnListEnd(list_state.id_))
927       return false;
928   }
929
930   DCHECK_GE(lists_ended, 1);
931
932   if (list_state_stack_.empty())
933     ChangeState(DONE_PARSING_LIST);
934
935   return true;
936 }
937
938 bool WebMListParser::IsSiblingOrAncestor(int id_a, int id_b) const {
939   DCHECK((id_a == kWebMIdSegment) || (id_a == kWebMIdCluster));
940
941   if (id_a == kWebMIdCluster) {
942     // kWebMIdCluster siblings.
943     for (size_t i = 0; i < arraysize(kSegmentIds); i++) {
944       if (kSegmentIds[i].id_ == id_b)
945         return true;
946     }
947   }
948
949   // kWebMIdSegment siblings.
950   return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader));
951 }
952
953 }  // namespace media