15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/formats/webm/webm_parser.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains code to parse WebM file elements. It was created
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from information in the Matroska spec.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://www.matroska.org/technical/specs/index.html
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains code for encrypted WebM. Current WebM
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// encrypted request for comments specification is here
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://wiki.webmproject.org/encryption/webm-encryption-rfc
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iomanip>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/numerics/safe_conversions.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/formats/webm/webm_constants.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ElementType {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNKNOWN,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST,  // Referred to as Master Element in the Matroska spec.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FLOAT,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BINARY,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STRING,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SKIP,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ElementIdInfo {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ElementType type_;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int id_;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ListElementInfo {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int id_;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int level_;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ElementIdInfo* id_info_;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int id_info_count_;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following are tables indicating what IDs are valid sub-elements
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of particular elements. If an element is encountered that doesn't
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// appear in the list, a parsing error is signalled. Some elements are
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// marked as SKIP because they are valid, but we don't care about them
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// right now.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kEBMLHeaderIds[] = {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdEBMLVersion},
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdEBMLReadVersion},
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdEBMLMaxIDLength},
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdEBMLMaxSizeLength},
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdDocType},
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdDocTypeVersion},
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdDocTypeReadVersion},
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kSegmentIds[] = {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdSeekHead},
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdInfo},
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdCluster},
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTracks},
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdCues},
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdAttachments},
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdChapters},
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTags},
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kSeekHeadIds[] = {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdSeek},
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kSeekIds[] = {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdSeekID},
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdSeekPosition},
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kInfoIds[] = {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdSegmentUID},
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdSegmentFilename},
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdPrevUID},
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdPrevFilename},
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdNextUID},
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdNextFilename},
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdSegmentFamily},
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdChapterTranslate},
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTimecodeScale},
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {FLOAT, kWebMIdDuration},
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdDateUTC},
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdTitle},
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdMuxingApp},
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdWritingApp},
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kChapterTranslateIds[] = {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterTranslateEditionUID},
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterTranslateCodec},
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdChapterTranslateID},
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kClusterIds[] = {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdSimpleBlock},
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTimecode},
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdSilentTracks},
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdPosition},
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdPrevSize},
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdBlockGroup},
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kSilentTracksIds[] = {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdSilentTrackNumber},
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kBlockGroupIds[] = {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdBlock},
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdBlockAdditions},
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdBlockDuration},
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdReferencePriority},
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdReferenceBlock},
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdCodecState},
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  {BINARY, kWebMIdDiscardPadding},
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdSlices},
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kBlockAdditionsIds[] = {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdBlockMore},
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kBlockMoreIds[] = {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdBlockAddID},
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdBlockAdditional},
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kSlicesIds[] = {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTimeSlice},
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTimeSliceIds[] = {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdLaceNumber},
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTracksIds[] = {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTrackEntry},
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTrackEntryIds[] = {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTrackNumber},
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  {BINARY, kWebMIdTrackUID},
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTrackType},
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdFlagEnabled},
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdFlagDefault},
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdFlagForced},
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdFlagLacing},
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdMinCache},
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdMaxCache},
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdDefaultDuration},
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {FLOAT, kWebMIdTrackTimecodeScale},
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdMaxBlockAdditionId},
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdName},
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdLanguage},
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdCodecID},
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdCodecPrivate},
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdCodecName},
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdAttachmentLink},
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdCodecDecodeAll},
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTrackOverlay},
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  {UINT, kWebMIdCodecDelay},
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  {UINT, kWebMIdSeekPreRoll},
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTrackTranslate},
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdVideo},
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdAudio},
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTrackOperation},
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdContentEncodings},
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTrackTranslateIds[] = {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTrackTranslateEditionUID},
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTrackTranslateCodec},
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdTrackTranslateTrackID},
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kVideoIds[] = {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdFlagInterlaced},
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdStereoMode},
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  {UINT, kWebMIdAlphaMode},
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdPixelWidth},
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdPixelHeight},
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdPixelCropBottom},
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdPixelCropTop},
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdPixelCropLeft},
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdPixelCropRight},
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdDisplayWidth},
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdDisplayHeight},
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdDisplayUnit},
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdAspectRatioType},
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdColorSpace},
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  {FLOAT, kWebMIdFrameRate},
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kAudioIds[] = {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {FLOAT, kWebMIdSamplingFrequency},
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {FLOAT, kWebMIdOutputSamplingFrequency},
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChannels},
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdBitDepth},
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTrackOperationIds[] = {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTrackCombinePlanes},
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdJoinBlocks},
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTrackCombinePlanesIds[] = {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTrackPlane},
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTrackPlaneIds[] = {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTrackPlaneUID},
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTrackPlaneType},
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kJoinBlocksIds[] = {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTrackJoinUID},
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kContentEncodingsIds[] = {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdContentEncoding},
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kContentEncodingIds[] = {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdContentEncodingOrder},
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdContentEncodingScope},
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdContentEncodingType},
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdContentCompression},
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdContentEncryption},
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kContentCompressionIds[] = {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdContentCompAlgo},
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdContentCompSettings},
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kContentEncryptionIds[] = {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdContentEncAESSettings},
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdContentEncAlgo},
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdContentEncKeyID},
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdContentSignature},
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdContentSigKeyID},
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdContentSigAlgo},
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdContentSigHashAlgo},
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kContentEncAESSettingsIds[] = {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdAESSettingsCipherMode},
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kCuesIds[] = {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdCuePoint},
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kCuePointIds[] = {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdCueTime},
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdCueTrackPositions},
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kCueTrackPositionsIds[] = {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdCueTrack},
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdCueClusterPosition},
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdCueBlockNumber},
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdCueCodecState},
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdCueReference},
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kCueReferenceIds[] = {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdCueRefTime},
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kAttachmentsIds[] = {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdAttachedFile},
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kAttachedFileIds[] = {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdFileDescription},
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdFileName},
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdFileMimeType},
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdFileData},
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdFileUID},
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kChaptersIds[] = {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdEditionEntry},
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kEditionEntryIds[] = {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdEditionUID},
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdEditionFlagHidden},
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdEditionFlagDefault},
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdEditionFlagOrdered},
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdChapterAtom},
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kChapterAtomIds[] = {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterUID},
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterTimeStart},
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterTimeEnd},
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterFlagHidden},
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterFlagEnabled},
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdChapterSegmentUID},
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterSegmentEditionUID},
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterPhysicalEquiv},
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdChapterTrack},
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdChapterDisplay},
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdChapProcess},
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kChapterTrackIds[] = {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapterTrackNumber},
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kChapterDisplayIds[] = {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdChapString},
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdChapLanguage},
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdChapCountry},
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kChapProcessIds[] = {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapProcessCodecID},
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdChapProcessPrivate},
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdChapProcessCommand},
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kChapProcessCommandIds[] = {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdChapProcessTime},
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdChapProcessData},
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTagsIds[] = {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTag},
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTagIds[] = {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdTargets},
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {LIST, kWebMIdSimpleTag},
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kTargetsIds[] = {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTargetTypeValue},
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdTargetType},
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTagTrackUID},
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTagEditionUID},
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTagChapterUID},
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTagAttachmentUID},
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ElementIdInfo kSimpleTagIds[] = {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdTagName},
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdTagLanguage},
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {UINT, kWebMIdTagDefault},
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {STRING, kWebMIdTagString},
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {BINARY, kWebMIdTagBinary},
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LIST_ELEMENT_INFO(id, level, id_info) \
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { (id), (level), (id_info), arraysize(id_info) }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ListElementInfo kListElementInfo[] = {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds),
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdEBMLHeader, 0, kEBMLHeaderIds),
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds),
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdSeekHead, 1, kSeekHeadIds),
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdSeek, 2, kSeekIds),
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds),
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdChapterTranslate, 2, kChapterTranslateIds),
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdSilentTracks, 2, kSilentTracksIds),
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdBlockGroup, 2, kBlockGroupIds),
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdBlockAdditions, 3, kBlockAdditionsIds),
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdBlockMore, 4, kBlockMoreIds),
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdSlices, 3, kSlicesIds),
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTimeSlice, 4, kTimeSliceIds),
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds),
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds),
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTrackTranslate, 3, kTrackTranslateIds),
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds),
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTrackOperation, 3, kTrackOperationIds),
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTrackCombinePlanes, 4, kTrackCombinePlanesIds),
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTrackPlane, 5, kTrackPlaneIds),
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdJoinBlocks, 4, kJoinBlocksIds),
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdContentEncodings, 3, kContentEncodingsIds),
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds),
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds),
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds),
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings, 6, kContentEncAESSettingsIds),
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds),
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds),
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds),
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdCueReference, 4, kCueReferenceIds),
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdAttachments, 1, kAttachmentsIds),
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdAttachedFile, 2, kAttachedFileIds),
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdChapters, 1, kChaptersIds),
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdEditionEntry, 2, kEditionEntryIds),
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdChapterAtom, 3, kChapterAtomIds),
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdChapterTrack, 4, kChapterTrackIds),
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdChapterDisplay, 4, kChapterDisplayIds),
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdChapProcess, 4, kChapProcessIds),
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdChapProcessCommand, 5, kChapProcessCommandIds),
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTags, 1, kTagsIds),
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTag, 2, kTagIds),
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdTargets, 3, kTargetsIds),
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_ELEMENT_INFO(kWebMIdSimpleTag, 3, kSimpleTagIds),
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parses an element header id or size field. These fields are variable length
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// encoded. The first byte indicates how many bytes the field occupies.
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |buf|  - The buffer to parse.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |size| - The number of bytes in |buf|
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |max_bytes| - The maximum number of bytes the field can be. ID fields
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//               set this to 4 & element size fields set this to 8. If the
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//               first byte indicates a larger field size than this it is a
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//               parser error.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |mask_first_byte| - For element size fields the field length encoding bits
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     need to be masked off. This parameter is true for
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     element size fields and is false for ID field values.
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns: The number of bytes parsed on success. -1 on error.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ParseWebMElementHeaderField(const uint8* buf, int size,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       int max_bytes, bool mask_first_byte,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       int64* num) {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(num);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size < 0)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size == 0)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int mask = 0x80;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 ch = buf[0];
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_bytes = -1;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool all_ones = false;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < max_bytes; ++i) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ch & mask) != 0) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask = ~mask & 0xff;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = mask_first_byte ? ch & mask : ch;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      all_ones = (ch & mask) == mask;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extra_bytes = i;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mask = 0x80 | mask >> 1;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_bytes == -1)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return 0 if we need more data.
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((1 + extra_bytes) > size)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_used = 1;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < extra_bytes; ++i) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ch = buf[bytes_used++];
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    all_ones &= (ch == 0xff);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *num = (*num << 8) | ch;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (all_ones)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *num = kint64max;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bytes_used;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WebMParseElementHeader(const uint8* buf, int size,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int* id, int64* element_size) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(size, 0);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(id);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(element_size);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size == 0)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 tmp = 0;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4, false, &tmp);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_id_bytes <= 0)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return num_id_bytes;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tmp == kint64max)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp = kWebMReservedId;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *id = static_cast<int>(tmp);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   size - num_id_bytes,
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   8, true, &tmp);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_size_bytes <= 0)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return num_size_bytes;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tmp == kint64max)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp = kWebMUnknownSize;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *element_size = tmp;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(3) << "WebMParseElementHeader() : id " << std::hex << *id << std::dec
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << " size " << *element_size;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return num_id_bytes + num_size_bytes;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Finds ElementType for a specific ID.
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static ElementType FindIdType(int id,
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const ElementIdInfo* id_info,
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int id_info_count) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for global element IDs that can be anywhere.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id == kWebMIdVoid || id == kWebMIdCRC32)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SKIP;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < id_info_count; ++i) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (id == id_info[i].id_)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return id_info[i].type_;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UNKNOWN;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Finds ListElementInfo for a specific ID.
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ListElementInfo* FindListInfo(int id) {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kListElementInfo); ++i) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (id == kListElementInfo[i].id_)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &kListElementInfo[i];
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int FindListLevel(int id) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ListElementInfo* list_info = FindListInfo(id);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (list_info)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return list_info->level_;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return -1;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ParseUInt(const uint8* buf, int size, int id,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     WebMParserClient* client) {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((size <= 0) || (size > 8))
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read in the big-endian integer.
5525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  uint64 value = 0;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < size; ++i)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value = (value << 8) | buf[i];
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // We use int64 in place of uint64 everywhere for convenience.  See this bug
5575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // for more details: http://crbug.com/366750#c3
5585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!base::IsValueInRangeForNumericType<int64>(value))
5595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return -1;
5605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!client->OnUInt(id, value))
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ParseFloat(const uint8* buf, int size, int id,
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      WebMParserClient* client) {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((size != 4) && (size != 8))
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double value = -1;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the bytes from big-endian form into a native endian integer.
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 tmp = 0;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < size; ++i)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp = (tmp << 8) | buf[i];
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use a union to convert the integer bit pattern into a floating point
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // number.
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size == 4) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    union {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int32 src;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float dst;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } tmp2;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp2.src = static_cast<int32>(tmp);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value = tmp2.dst;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (size == 8) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    union {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 src;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double dst;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } tmp2;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp2.src = tmp;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value = tmp2.dst;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!client->OnFloat(id, value))
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ParseBinary(const uint8* buf, int size, int id,
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       WebMParserClient* client) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return client->OnBinary(id, buf, size) ? size : -1;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ParseString(const uint8* buf, int size, int id,
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       WebMParserClient* client) {
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const uint8* end = static_cast<const uint8*>(memchr(buf, '\0', size));
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int length = (end != NULL) ? static_cast<int>(end - buf) : size;
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string str(reinterpret_cast<const char*>(buf), length);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return client->OnString(id, str) ? size : -1;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ParseNonListElement(ElementType type, int id, int64 element_size,
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const uint8* buf, int size,
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               WebMParserClient* client) {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(size, element_size);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = -1;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch(type) {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case LIST:
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTIMPLEMENTED();
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = -1;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case UINT:
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = ParseUInt(buf, element_size, id, client);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FLOAT:
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = ParseFloat(buf, element_size, id, client);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BINARY:
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = ParseBinary(buf, element_size, id, client);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STRING:
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = ParseString(buf, element_size, id, client);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SKIP:
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = element_size;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "Unhandled ID type " << type;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(result, size);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebMParserClient::WebMParserClient() {}
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebMParserClient::~WebMParserClient() {}
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebMParserClient* WebMParserClient::OnListStart(int id) {
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Unexpected list element start with ID " << std::hex << id;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMParserClient::OnListEnd(int id) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Unexpected list element end with ID " << std::hex << id;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMParserClient::OnUInt(int id, int64 val) {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Unexpected unsigned integer element with ID " << std::hex << id;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMParserClient::OnFloat(int id, double val) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Unexpected float element with ID " << std::hex << id;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMParserClient::OnBinary(int id, const uint8* data, int size) {
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Unexpected binary element with ID " << std::hex << id;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMParserClient::OnString(int id, const std::string& str) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Unexpected string element with ID " << std::hex << id;
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebMListParser::WebMListParser(int id, WebMParserClient* client)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : state_(NEED_LIST_HEADER),
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_id_(id),
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_level_(FindListLevel(id)),
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_client_(client) {
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(root_level_, 0);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(client);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebMListParser::~WebMListParser() {}
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebMListParser::Reset() {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeState(NEED_LIST_HEADER);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  list_state_stack_.clear();
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WebMListParser::Parse(const uint8* buf, int size) {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size == 0)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* cur = buf;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cur_size = size;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_parsed = 0;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int element_id = 0;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 element_size = 0;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = WebMParseElementHeader(cur, cur_size, &element_id,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &element_size);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result < 0)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == 0)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return bytes_parsed;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch(state_) {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case NEED_LIST_HEADER: {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (element_id != root_id_) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ChangeState(PARSE_ERROR);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return -1;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Only allow Segment & Cluster to have an unknown size.
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (element_size == kWebMUnknownSize &&
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (element_id != kWebMIdSegment) &&
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (element_id != kWebMIdCluster)) {
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ChangeState(PARSE_ERROR);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return -1;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ChangeState(INSIDE_LIST);
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!OnListStart(root_id_, element_size))
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return -1;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case INSIDE_LIST: {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int header_size = result;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const uint8* element_data = cur + header_size;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int element_data_size = cur_size - header_size;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (element_size < element_data_size)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          element_data_size = element_size;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = ParseListElement(header_size, element_id, element_size,
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  element_data, element_data_size);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_LE(result, header_size + element_data_size);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (result < 0) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ChangeState(PARSE_ERROR);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return -1;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (result == 0)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return bytes_parsed;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case DONE_PARSING_LIST:
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PARSE_ERROR:
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Shouldn't be able to get here.
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTIMPLEMENTED();
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur += result;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_size -= result;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_parsed += result;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (state_ == PARSE_ERROR) ? -1 : bytes_parsed;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMListParser::IsParsingComplete() const {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state_ == DONE_PARSING_LIST;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebMListParser::ChangeState(State new_state) {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = new_state;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WebMListParser::ParseListElement(int header_size,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     int id, int64 element_size,
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const uint8* data, int size) {
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(list_state_stack_.size(), 0u);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListState& list_state = list_state_stack_.back();
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(list_state.element_info_);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ListElementInfo* element_info = list_state.element_info_;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ElementType id_type =
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FindIdType(id, element_info->id_info_, element_info->id_info_count_);
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unexpected ID.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id_type == UNKNOWN) {
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (list_state.size_ != kWebMUnknownSize ||
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !IsSiblingOrAncestor(list_state.id_, id)) {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "No ElementType info for ID 0x" << std::hex << id;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've reached the end of a list of unknown size. Update the size now that
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we know it and dispatch the end of list calls.
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list_state.size_ = list_state.bytes_parsed_;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OnListEnd())
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check to see if all open lists have ended.
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (list_state_stack_.size() == 0)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list_state = list_state_stack_.back();
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the whole element can fit inside the current list.
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 total_element_size = header_size + element_size;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (list_state.size_ != kWebMUnknownSize &&
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id_type == LIST) {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list_state.bytes_parsed_ += header_size;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OnListStart(id, element_size))
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return header_size;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we have the entire element before trying to parse a non-list
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // element.
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size < element_size)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_parsed = ParseNonListElement(id_type, id, element_size,
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         data, size, list_state.client_);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(bytes_parsed, size);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return if an error occurred or we need more data.
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: bytes_parsed is 0 for a successful parse of a size 0 element. We
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // need to check the element_size to disambiguate the "need more data" case
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from a successful parse.
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bytes_parsed < 0 || (bytes_parsed == 0 && element_size != 0))
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return bytes_parsed;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = header_size + bytes_parsed;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  list_state.bytes_parsed_ += result;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See if we have reached the end of the current list.
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (list_state.bytes_parsed_ == list_state.size_) {
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OnListEnd())
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMListParser::OnListStart(int id, int64 size) {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ListElementInfo* element_info = FindListInfo(id);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!element_info)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int current_level = root_level_ + list_state_stack_.size() - 1;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_level + 1 != element_info->level_)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebMParserClient* current_list_client = NULL;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!list_state_stack_.empty()) {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure the new list doesn't go past the end of the current list.
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListState current_list_state = list_state_stack_.back();
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current_list_state.size_ != kWebMUnknownSize &&
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_list_state.size_ < current_list_state.bytes_parsed_ + size)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_list_client = current_list_state.client_;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_list_client = root_client_;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebMParserClient* new_list_client = current_list_client->OnListStart(id);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!new_list_client)
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListState new_list_state = { id, size, 0, element_info, new_list_client };
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  list_state_stack_.push_back(new_list_state);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size == 0)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnListEnd();
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMListParser::OnListEnd() {
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int lists_ended = 0;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; !list_state_stack_.empty(); ++lists_ended) {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListState& list_state = list_state_stack_.back();
9101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int64 bytes_parsed = list_state.bytes_parsed_;
9111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int id = list_state.id_;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (bytes_parsed != list_state.size_)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list_state_stack_.pop_back();
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebMParserClient* client = NULL;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!list_state_stack_.empty()) {
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Update the bytes_parsed_ for the parent element.
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      list_state_stack_.back().bytes_parsed_ += bytes_parsed;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client = list_state_stack_.back().client_;
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client = root_client_;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!client->OnListEnd(id))
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(lists_ended, 1);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (list_state_stack_.empty())
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeState(DONE_PARSING_LIST);
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMListParser::IsSiblingOrAncestor(int id_a, int id_b) const {
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK((id_a == kWebMIdSegment) || (id_a == kWebMIdCluster));
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id_a == kWebMIdCluster) {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // kWebMIdCluster siblings.
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < arraysize(kSegmentIds); i++) {
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (kSegmentIds[i].id_ == id_b)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kWebMIdSegment siblings.
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader));
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
955