summaryrefslogtreecommitdiffstats
path: root/chromium/media/webm/webm_parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/webm/webm_parser.cc')
-rw-r--r--chromium/media/webm/webm_parser.cc947
1 files changed, 0 insertions, 947 deletions
diff --git a/chromium/media/webm/webm_parser.cc b/chromium/media/webm/webm_parser.cc
deleted file mode 100644
index f1509abb830..00000000000
--- a/chromium/media/webm/webm_parser.cc
+++ /dev/null
@@ -1,947 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/webm/webm_parser.h"
-
-// This file contains code to parse WebM file elements. It was created
-// from information in the Matroska spec.
-// http://www.matroska.org/technical/specs/index.html
-// This file contains code for encrypted WebM. Current WebM
-// encrypted request for comments specification is here
-// http://wiki.webmproject.org/encryption/webm-encryption-rfc
-
-#include <iomanip>
-
-#include "base/logging.h"
-#include "media/webm/webm_constants.h"
-
-namespace media {
-
-enum ElementType {
- UNKNOWN,
- LIST, // Referred to as Master Element in the Matroska spec.
- UINT,
- FLOAT,
- BINARY,
- STRING,
- SKIP,
-};
-
-struct ElementIdInfo {
- ElementType type_;
- int id_;
-};
-
-struct ListElementInfo {
- int id_;
- int level_;
- const ElementIdInfo* id_info_;
- int id_info_count_;
-};
-
-// The following are tables indicating what IDs are valid sub-elements
-// of particular elements. If an element is encountered that doesn't
-// appear in the list, a parsing error is signalled. Some elements are
-// marked as SKIP because they are valid, but we don't care about them
-// right now.
-static const ElementIdInfo kEBMLHeaderIds[] = {
- {UINT, kWebMIdEBMLVersion},
- {UINT, kWebMIdEBMLReadVersion},
- {UINT, kWebMIdEBMLMaxIDLength},
- {UINT, kWebMIdEBMLMaxSizeLength},
- {STRING, kWebMIdDocType},
- {UINT, kWebMIdDocTypeVersion},
- {UINT, kWebMIdDocTypeReadVersion},
-};
-
-static const ElementIdInfo kSegmentIds[] = {
- {LIST, kWebMIdSeekHead},
- {LIST, kWebMIdInfo},
- {LIST, kWebMIdCluster},
- {LIST, kWebMIdTracks},
- {LIST, kWebMIdCues},
- {LIST, kWebMIdAttachments},
- {LIST, kWebMIdChapters},
- {LIST, kWebMIdTags},
-};
-
-static const ElementIdInfo kSeekHeadIds[] = {
- {LIST, kWebMIdSeek},
-};
-
-static const ElementIdInfo kSeekIds[] = {
- {BINARY, kWebMIdSeekID},
- {UINT, kWebMIdSeekPosition},
-};
-
-static const ElementIdInfo kInfoIds[] = {
- {BINARY, kWebMIdSegmentUID},
- {STRING, kWebMIdSegmentFilename},
- {BINARY, kWebMIdPrevUID},
- {STRING, kWebMIdPrevFilename},
- {BINARY, kWebMIdNextUID},
- {STRING, kWebMIdNextFilename},
- {BINARY, kWebMIdSegmentFamily},
- {LIST, kWebMIdChapterTranslate},
- {UINT, kWebMIdTimecodeScale},
- {FLOAT, kWebMIdDuration},
- {BINARY, kWebMIdDateUTC},
- {STRING, kWebMIdTitle},
- {STRING, kWebMIdMuxingApp},
- {STRING, kWebMIdWritingApp},
-};
-
-static const ElementIdInfo kChapterTranslateIds[] = {
- {UINT, kWebMIdChapterTranslateEditionUID},
- {UINT, kWebMIdChapterTranslateCodec},
- {BINARY, kWebMIdChapterTranslateID},
-};
-
-static const ElementIdInfo kClusterIds[] = {
- {BINARY, kWebMIdSimpleBlock},
- {UINT, kWebMIdTimecode},
- {LIST, kWebMIdSilentTracks},
- {UINT, kWebMIdPosition},
- {UINT, kWebMIdPrevSize},
- {LIST, kWebMIdBlockGroup},
-};
-
-static const ElementIdInfo kSilentTracksIds[] = {
- {UINT, kWebMIdSilentTrackNumber},
-};
-
-static const ElementIdInfo kBlockGroupIds[] = {
- {BINARY, kWebMIdBlock},
- {LIST, kWebMIdBlockAdditions},
- {UINT, kWebMIdBlockDuration},
- {UINT, kWebMIdReferencePriority},
- {BINARY, kWebMIdReferenceBlock},
- {BINARY, kWebMIdCodecState},
- {UINT, kWebMIdDiscardPadding},
- {LIST, kWebMIdSlices},
-};
-
-static const ElementIdInfo kBlockAdditionsIds[] = {
- {LIST, kWebMIdBlockMore},
-};
-
-static const ElementIdInfo kBlockMoreIds[] = {
- {UINT, kWebMIdBlockAddID},
- {BINARY, kWebMIdBlockAdditional},
-};
-
-static const ElementIdInfo kSlicesIds[] = {
- {LIST, kWebMIdTimeSlice},
-};
-
-static const ElementIdInfo kTimeSliceIds[] = {
- {UINT, kWebMIdLaceNumber},
-};
-
-static const ElementIdInfo kTracksIds[] = {
- {LIST, kWebMIdTrackEntry},
-};
-
-static const ElementIdInfo kTrackEntryIds[] = {
- {UINT, kWebMIdTrackNumber},
- {UINT, kWebMIdTrackUID},
- {UINT, kWebMIdTrackType},
- {UINT, kWebMIdFlagEnabled},
- {UINT, kWebMIdFlagDefault},
- {UINT, kWebMIdFlagForced},
- {UINT, kWebMIdFlagLacing},
- {UINT, kWebMIdMinCache},
- {UINT, kWebMIdMaxCache},
- {UINT, kWebMIdDefaultDuration},
- {FLOAT, kWebMIdTrackTimecodeScale},
- {UINT, kWebMIdMaxBlockAdditionId},
- {STRING, kWebMIdName},
- {STRING, kWebMIdLanguage},
- {STRING, kWebMIdCodecID},
- {BINARY, kWebMIdCodecPrivate},
- {STRING, kWebMIdCodecName},
- {UINT, kWebMIdAttachmentLink},
- {UINT, kWebMIdCodecDecodeAll},
- {UINT, kWebMIdTrackOverlay},
- {UINT, kWebMIdCodecDelay},
- {UINT, kWebMIdSeekPreRoll},
- {LIST, kWebMIdTrackTranslate},
- {LIST, kWebMIdVideo},
- {LIST, kWebMIdAudio},
- {LIST, kWebMIdTrackOperation},
- {LIST, kWebMIdContentEncodings},
-};
-
-static const ElementIdInfo kTrackTranslateIds[] = {
- {UINT, kWebMIdTrackTranslateEditionUID},
- {UINT, kWebMIdTrackTranslateCodec},
- {BINARY, kWebMIdTrackTranslateTrackID},
-};
-
-static const ElementIdInfo kVideoIds[] = {
- {UINT, kWebMIdFlagInterlaced},
- {UINT, kWebMIdStereoMode},
- {UINT, kWebMIdAlphaMode},
- {UINT, kWebMIdPixelWidth},
- {UINT, kWebMIdPixelHeight},
- {UINT, kWebMIdPixelCropBottom},
- {UINT, kWebMIdPixelCropTop},
- {UINT, kWebMIdPixelCropLeft},
- {UINT, kWebMIdPixelCropRight},
- {UINT, kWebMIdDisplayWidth},
- {UINT, kWebMIdDisplayHeight},
- {UINT, kWebMIdDisplayUnit},
- {UINT, kWebMIdAspectRatioType},
- {BINARY, kWebMIdColorSpace},
- {FLOAT, kWebMIdFrameRate},
-};
-
-static const ElementIdInfo kAudioIds[] = {
- {FLOAT, kWebMIdSamplingFrequency},
- {FLOAT, kWebMIdOutputSamplingFrequency},
- {UINT, kWebMIdChannels},
- {UINT, kWebMIdBitDepth},
-};
-
-static const ElementIdInfo kTrackOperationIds[] = {
- {LIST, kWebMIdTrackCombinePlanes},
- {LIST, kWebMIdJoinBlocks},
-};
-
-static const ElementIdInfo kTrackCombinePlanesIds[] = {
- {LIST, kWebMIdTrackPlane},
-};
-
-static const ElementIdInfo kTrackPlaneIds[] = {
- {UINT, kWebMIdTrackPlaneUID},
- {UINT, kWebMIdTrackPlaneType},
-};
-
-static const ElementIdInfo kJoinBlocksIds[] = {
- {UINT, kWebMIdTrackJoinUID},
-};
-
-static const ElementIdInfo kContentEncodingsIds[] = {
- {LIST, kWebMIdContentEncoding},
-};
-
-static const ElementIdInfo kContentEncodingIds[] = {
- {UINT, kWebMIdContentEncodingOrder},
- {UINT, kWebMIdContentEncodingScope},
- {UINT, kWebMIdContentEncodingType},
- {LIST, kWebMIdContentCompression},
- {LIST, kWebMIdContentEncryption},
-};
-
-static const ElementIdInfo kContentCompressionIds[] = {
- {UINT, kWebMIdContentCompAlgo},
- {BINARY, kWebMIdContentCompSettings},
-};
-
-static const ElementIdInfo kContentEncryptionIds[] = {
- {LIST, kWebMIdContentEncAESSettings},
- {UINT, kWebMIdContentEncAlgo},
- {BINARY, kWebMIdContentEncKeyID},
- {BINARY, kWebMIdContentSignature},
- {BINARY, kWebMIdContentSigKeyID},
- {UINT, kWebMIdContentSigAlgo},
- {UINT, kWebMIdContentSigHashAlgo},
-};
-
-static const ElementIdInfo kContentEncAESSettingsIds[] = {
- {UINT, kWebMIdAESSettingsCipherMode},
-};
-
-static const ElementIdInfo kCuesIds[] = {
- {LIST, kWebMIdCuePoint},
-};
-
-static const ElementIdInfo kCuePointIds[] = {
- {UINT, kWebMIdCueTime},
- {LIST, kWebMIdCueTrackPositions},
-};
-
-static const ElementIdInfo kCueTrackPositionsIds[] = {
- {UINT, kWebMIdCueTrack},
- {UINT, kWebMIdCueClusterPosition},
- {UINT, kWebMIdCueBlockNumber},
- {UINT, kWebMIdCueCodecState},
- {LIST, kWebMIdCueReference},
-};
-
-static const ElementIdInfo kCueReferenceIds[] = {
- {UINT, kWebMIdCueRefTime},
-};
-
-static const ElementIdInfo kAttachmentsIds[] = {
- {LIST, kWebMIdAttachedFile},
-};
-
-static const ElementIdInfo kAttachedFileIds[] = {
- {STRING, kWebMIdFileDescription},
- {STRING, kWebMIdFileName},
- {STRING, kWebMIdFileMimeType},
- {BINARY, kWebMIdFileData},
- {UINT, kWebMIdFileUID},
-};
-
-static const ElementIdInfo kChaptersIds[] = {
- {LIST, kWebMIdEditionEntry},
-};
-
-static const ElementIdInfo kEditionEntryIds[] = {
- {UINT, kWebMIdEditionUID},
- {UINT, kWebMIdEditionFlagHidden},
- {UINT, kWebMIdEditionFlagDefault},
- {UINT, kWebMIdEditionFlagOrdered},
- {LIST, kWebMIdChapterAtom},
-};
-
-static const ElementIdInfo kChapterAtomIds[] = {
- {UINT, kWebMIdChapterUID},
- {UINT, kWebMIdChapterTimeStart},
- {UINT, kWebMIdChapterTimeEnd},
- {UINT, kWebMIdChapterFlagHidden},
- {UINT, kWebMIdChapterFlagEnabled},
- {BINARY, kWebMIdChapterSegmentUID},
- {UINT, kWebMIdChapterSegmentEditionUID},
- {UINT, kWebMIdChapterPhysicalEquiv},
- {LIST, kWebMIdChapterTrack},
- {LIST, kWebMIdChapterDisplay},
- {LIST, kWebMIdChapProcess},
-};
-
-static const ElementIdInfo kChapterTrackIds[] = {
- {UINT, kWebMIdChapterTrackNumber},
-};
-
-static const ElementIdInfo kChapterDisplayIds[] = {
- {STRING, kWebMIdChapString},
- {STRING, kWebMIdChapLanguage},
- {STRING, kWebMIdChapCountry},
-};
-
-static const ElementIdInfo kChapProcessIds[] = {
- {UINT, kWebMIdChapProcessCodecID},
- {BINARY, kWebMIdChapProcessPrivate},
- {LIST, kWebMIdChapProcessCommand},
-};
-
-static const ElementIdInfo kChapProcessCommandIds[] = {
- {UINT, kWebMIdChapProcessTime},
- {BINARY, kWebMIdChapProcessData},
-};
-
-static const ElementIdInfo kTagsIds[] = {
- {LIST, kWebMIdTag},
-};
-
-static const ElementIdInfo kTagIds[] = {
- {LIST, kWebMIdTargets},
- {LIST, kWebMIdSimpleTag},
-};
-
-static const ElementIdInfo kTargetsIds[] = {
- {UINT, kWebMIdTargetTypeValue},
- {STRING, kWebMIdTargetType},
- {UINT, kWebMIdTagTrackUID},
- {UINT, kWebMIdTagEditionUID},
- {UINT, kWebMIdTagChapterUID},
- {UINT, kWebMIdTagAttachmentUID},
-};
-
-static const ElementIdInfo kSimpleTagIds[] = {
- {STRING, kWebMIdTagName},
- {STRING, kWebMIdTagLanguage},
- {UINT, kWebMIdTagDefault},
- {STRING, kWebMIdTagString},
- {BINARY, kWebMIdTagBinary},
-};
-
-#define LIST_ELEMENT_INFO(id, level, id_info) \
- { (id), (level), (id_info), arraysize(id_info) }
-
-static const ListElementInfo kListElementInfo[] = {
- LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds),
- LIST_ELEMENT_INFO(kWebMIdEBMLHeader, 0, kEBMLHeaderIds),
- LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds),
- LIST_ELEMENT_INFO(kWebMIdSeekHead, 1, kSeekHeadIds),
- LIST_ELEMENT_INFO(kWebMIdSeek, 2, kSeekIds),
- LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds),
- LIST_ELEMENT_INFO(kWebMIdChapterTranslate, 2, kChapterTranslateIds),
- LIST_ELEMENT_INFO(kWebMIdSilentTracks, 2, kSilentTracksIds),
- LIST_ELEMENT_INFO(kWebMIdBlockGroup, 2, kBlockGroupIds),
- LIST_ELEMENT_INFO(kWebMIdBlockAdditions, 3, kBlockAdditionsIds),
- LIST_ELEMENT_INFO(kWebMIdBlockMore, 4, kBlockMoreIds),
- LIST_ELEMENT_INFO(kWebMIdSlices, 3, kSlicesIds),
- LIST_ELEMENT_INFO(kWebMIdTimeSlice, 4, kTimeSliceIds),
- LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds),
- LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds),
- LIST_ELEMENT_INFO(kWebMIdTrackTranslate, 3, kTrackTranslateIds),
- LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds),
- LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds),
- LIST_ELEMENT_INFO(kWebMIdTrackOperation, 3, kTrackOperationIds),
- LIST_ELEMENT_INFO(kWebMIdTrackCombinePlanes, 4, kTrackCombinePlanesIds),
- LIST_ELEMENT_INFO(kWebMIdTrackPlane, 5, kTrackPlaneIds),
- LIST_ELEMENT_INFO(kWebMIdJoinBlocks, 4, kJoinBlocksIds),
- LIST_ELEMENT_INFO(kWebMIdContentEncodings, 3, kContentEncodingsIds),
- LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds),
- LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds),
- LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds),
- LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings, 6, kContentEncAESSettingsIds),
- LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds),
- LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds),
- LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds),
- LIST_ELEMENT_INFO(kWebMIdCueReference, 4, kCueReferenceIds),
- LIST_ELEMENT_INFO(kWebMIdAttachments, 1, kAttachmentsIds),
- LIST_ELEMENT_INFO(kWebMIdAttachedFile, 2, kAttachedFileIds),
- LIST_ELEMENT_INFO(kWebMIdChapters, 1, kChaptersIds),
- LIST_ELEMENT_INFO(kWebMIdEditionEntry, 2, kEditionEntryIds),
- LIST_ELEMENT_INFO(kWebMIdChapterAtom, 3, kChapterAtomIds),
- LIST_ELEMENT_INFO(kWebMIdChapterTrack, 4, kChapterTrackIds),
- LIST_ELEMENT_INFO(kWebMIdChapterDisplay, 4, kChapterDisplayIds),
- LIST_ELEMENT_INFO(kWebMIdChapProcess, 4, kChapProcessIds),
- LIST_ELEMENT_INFO(kWebMIdChapProcessCommand, 5, kChapProcessCommandIds),
- LIST_ELEMENT_INFO(kWebMIdTags, 1, kTagsIds),
- LIST_ELEMENT_INFO(kWebMIdTag, 2, kTagIds),
- LIST_ELEMENT_INFO(kWebMIdTargets, 3, kTargetsIds),
- LIST_ELEMENT_INFO(kWebMIdSimpleTag, 3, kSimpleTagIds),
-};
-
-// Parses an element header id or size field. These fields are variable length
-// encoded. The first byte indicates how many bytes the field occupies.
-// |buf| - The buffer to parse.
-// |size| - The number of bytes in |buf|
-// |max_bytes| - The maximum number of bytes the field can be. ID fields
-// set this to 4 & element size fields set this to 8. If the
-// first byte indicates a larger field size than this it is a
-// parser error.
-// |mask_first_byte| - For element size fields the field length encoding bits
-// need to be masked off. This parameter is true for
-// element size fields and is false for ID field values.
-//
-// Returns: The number of bytes parsed on success. -1 on error.
-static int ParseWebMElementHeaderField(const uint8* buf, int size,
- int max_bytes, bool mask_first_byte,
- int64* num) {
- DCHECK(buf);
- DCHECK(num);
-
- if (size < 0)
- return -1;
-
- if (size == 0)
- return 0;
-
- int mask = 0x80;
- uint8 ch = buf[0];
- int extra_bytes = -1;
- bool all_ones = false;
- for (int i = 0; i < max_bytes; ++i) {
- if ((ch & mask) != 0) {
- mask = ~mask & 0xff;
- *num = mask_first_byte ? ch & mask : ch;
- all_ones = (ch & mask) == mask;
- extra_bytes = i;
- break;
- }
- mask = 0x80 | mask >> 1;
- }
-
- if (extra_bytes == -1)
- return -1;
-
- // Return 0 if we need more data.
- if ((1 + extra_bytes) > size)
- return 0;
-
- int bytes_used = 1;
-
- for (int i = 0; i < extra_bytes; ++i) {
- ch = buf[bytes_used++];
- all_ones &= (ch == 0xff);
- *num = (*num << 8) | ch;
- }
-
- if (all_ones)
- *num = kint64max;
-
- return bytes_used;
-}
-
-int WebMParseElementHeader(const uint8* buf, int size,
- int* id, int64* element_size) {
- DCHECK(buf);
- DCHECK_GE(size, 0);
- DCHECK(id);
- DCHECK(element_size);
-
- if (size == 0)
- return 0;
-
- int64 tmp = 0;
- int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4, false, &tmp);
-
- if (num_id_bytes <= 0)
- return num_id_bytes;
-
- if (tmp == kint64max)
- tmp = kWebMReservedId;
-
- *id = static_cast<int>(tmp);
-
- int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes,
- size - num_id_bytes,
- 8, true, &tmp);
-
- if (num_size_bytes <= 0)
- return num_size_bytes;
-
- if (tmp == kint64max)
- tmp = kWebMUnknownSize;
-
- *element_size = tmp;
- DVLOG(3) << "WebMParseElementHeader() : id " << std::hex << *id << std::dec
- << " size " << *element_size;
- return num_id_bytes + num_size_bytes;
-}
-
-// Finds ElementType for a specific ID.
-static ElementType FindIdType(int id,
- const ElementIdInfo* id_info,
- int id_info_count) {
-
- // Check for global element IDs that can be anywhere.
- if (id == kWebMIdVoid || id == kWebMIdCRC32)
- return SKIP;
-
- for (int i = 0; i < id_info_count; ++i) {
- if (id == id_info[i].id_)
- return id_info[i].type_;
- }
-
- return UNKNOWN;
-}
-
-// Finds ListElementInfo for a specific ID.
-static const ListElementInfo* FindListInfo(int id) {
- for (size_t i = 0; i < arraysize(kListElementInfo); ++i) {
- if (id == kListElementInfo[i].id_)
- return &kListElementInfo[i];
- }
-
- return NULL;
-}
-
-static int FindListLevel(int id) {
- const ListElementInfo* list_info = FindListInfo(id);
- if (list_info)
- return list_info->level_;
-
- return -1;
-}
-
-static int ParseUInt(const uint8* buf, int size, int id,
- WebMParserClient* client) {
- if ((size <= 0) || (size > 8))
- return -1;
-
- // Read in the big-endian integer.
- int64 value = 0;
- for (int i = 0; i < size; ++i)
- value = (value << 8) | buf[i];
-
- if (!client->OnUInt(id, value))
- return -1;
-
- return size;
-}
-
-static int ParseFloat(const uint8* buf, int size, int id,
- WebMParserClient* client) {
-
- if ((size != 4) && (size != 8))
- return -1;
-
- double value = -1;
-
- // Read the bytes from big-endian form into a native endian integer.
- int64 tmp = 0;
- for (int i = 0; i < size; ++i)
- tmp = (tmp << 8) | buf[i];
-
- // Use a union to convert the integer bit pattern into a floating point
- // number.
- if (size == 4) {
- union {
- int32 src;
- float dst;
- } tmp2;
- tmp2.src = static_cast<int32>(tmp);
- value = tmp2.dst;
- } else if (size == 8) {
- union {
- int64 src;
- double dst;
- } tmp2;
- tmp2.src = tmp;
- value = tmp2.dst;
- } else {
- return -1;
- }
-
- if (!client->OnFloat(id, value))
- return -1;
-
- return size;
-}
-
-static int ParseBinary(const uint8* buf, int size, int id,
- WebMParserClient* client) {
- return client->OnBinary(id, buf, size) ? size : -1;
-}
-
-static int ParseString(const uint8* buf, int size, int id,
- WebMParserClient* client) {
- const uint8* end = static_cast<const uint8*>(memchr(buf, '\0', size));
- int length = (end != NULL) ? static_cast<int>(end - buf) : size;
- std::string str(reinterpret_cast<const char*>(buf), length);
- return client->OnString(id, str) ? size : -1;
-}
-
-static int ParseNonListElement(ElementType type, int id, int64 element_size,
- const uint8* buf, int size,
- WebMParserClient* client) {
- DCHECK_GE(size, element_size);
-
- int result = -1;
- switch(type) {
- case LIST:
- NOTIMPLEMENTED();
- result = -1;
- break;
- case UINT:
- result = ParseUInt(buf, element_size, id, client);
- break;
- case FLOAT:
- result = ParseFloat(buf, element_size, id, client);
- break;
- case BINARY:
- result = ParseBinary(buf, element_size, id, client);
- break;
- case STRING:
- result = ParseString(buf, element_size, id, client);
- break;
- case SKIP:
- result = element_size;
- break;
- default:
- DVLOG(1) << "Unhandled ID type " << type;
- return -1;
- };
-
- DCHECK_LE(result, size);
- return result;
-}
-
-WebMParserClient::WebMParserClient() {}
-WebMParserClient::~WebMParserClient() {}
-
-WebMParserClient* WebMParserClient::OnListStart(int id) {
- DVLOG(1) << "Unexpected list element start with ID " << std::hex << id;
- return NULL;
-}
-
-bool WebMParserClient::OnListEnd(int id) {
- DVLOG(1) << "Unexpected list element end with ID " << std::hex << id;
- return false;
-}
-
-bool WebMParserClient::OnUInt(int id, int64 val) {
- DVLOG(1) << "Unexpected unsigned integer element with ID " << std::hex << id;
- return false;
-}
-
-bool WebMParserClient::OnFloat(int id, double val) {
- DVLOG(1) << "Unexpected float element with ID " << std::hex << id;
- return false;
-}
-
-bool WebMParserClient::OnBinary(int id, const uint8* data, int size) {
- DVLOG(1) << "Unexpected binary element with ID " << std::hex << id;
- return false;
-}
-
-bool WebMParserClient::OnString(int id, const std::string& str) {
- DVLOG(1) << "Unexpected string element with ID " << std::hex << id;
- return false;
-}
-
-WebMListParser::WebMListParser(int id, WebMParserClient* client)
- : state_(NEED_LIST_HEADER),
- root_id_(id),
- root_level_(FindListLevel(id)),
- root_client_(client) {
- DCHECK_GE(root_level_, 0);
- DCHECK(client);
-}
-
-WebMListParser::~WebMListParser() {}
-
-void WebMListParser::Reset() {
- ChangeState(NEED_LIST_HEADER);
- list_state_stack_.clear();
-}
-
-int WebMListParser::Parse(const uint8* buf, int size) {
- DCHECK(buf);
-
- if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
- return -1;
-
- if (size == 0)
- return 0;
-
- const uint8* cur = buf;
- int cur_size = size;
- int bytes_parsed = 0;
-
- while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
- int element_id = 0;
- int64 element_size = 0;
- int result = WebMParseElementHeader(cur, cur_size, &element_id,
- &element_size);
-
- if (result < 0)
- return result;
-
- if (result == 0)
- return bytes_parsed;
-
- switch(state_) {
- case NEED_LIST_HEADER: {
- if (element_id != root_id_) {
- ChangeState(PARSE_ERROR);
- return -1;
- }
-
- // Only allow Segment & Cluster to have an unknown size.
- if (element_size == kWebMUnknownSize &&
- (element_id != kWebMIdSegment) &&
- (element_id != kWebMIdCluster)) {
- ChangeState(PARSE_ERROR);
- return -1;
- }
-
- ChangeState(INSIDE_LIST);
- if (!OnListStart(root_id_, element_size))
- return -1;
-
- break;
- }
-
- case INSIDE_LIST: {
- int header_size = result;
- const uint8* element_data = cur + header_size;
- int element_data_size = cur_size - header_size;
-
- if (element_size < element_data_size)
- element_data_size = element_size;
-
- result = ParseListElement(header_size, element_id, element_size,
- element_data, element_data_size);
-
- DCHECK_LE(result, header_size + element_data_size);
- if (result < 0) {
- ChangeState(PARSE_ERROR);
- return -1;
- }
-
- if (result == 0)
- return bytes_parsed;
-
- break;
- }
- case DONE_PARSING_LIST:
- case PARSE_ERROR:
- // Shouldn't be able to get here.
- NOTIMPLEMENTED();
- break;
- }
-
- cur += result;
- cur_size -= result;
- bytes_parsed += result;
- }
-
- return (state_ == PARSE_ERROR) ? -1 : bytes_parsed;
-}
-
-bool WebMListParser::IsParsingComplete() const {
- return state_ == DONE_PARSING_LIST;
-}
-
-void WebMListParser::ChangeState(State new_state) {
- state_ = new_state;
-}
-
-int WebMListParser::ParseListElement(int header_size,
- int id, int64 element_size,
- const uint8* data, int size) {
- DCHECK_GT(list_state_stack_.size(), 0u);
-
- ListState& list_state = list_state_stack_.back();
- DCHECK(list_state.element_info_);
-
- const ListElementInfo* element_info = list_state.element_info_;
- ElementType id_type =
- FindIdType(id, element_info->id_info_, element_info->id_info_count_);
-
- // Unexpected ID.
- if (id_type == UNKNOWN) {
- if (list_state.size_ != kWebMUnknownSize ||
- !IsSiblingOrAncestor(list_state.id_, id)) {
- DVLOG(1) << "No ElementType info for ID 0x" << std::hex << id;
- return -1;
- }
-
- // We've reached the end of a list of unknown size. Update the size now that
- // we know it and dispatch the end of list calls.
- list_state.size_ = list_state.bytes_parsed_;
-
- if (!OnListEnd())
- return -1;
-
- // Check to see if all open lists have ended.
- if (list_state_stack_.size() == 0)
- return 0;
-
- list_state = list_state_stack_.back();
- }
-
- // Make sure the whole element can fit inside the current list.
- int64 total_element_size = header_size + element_size;
- if (list_state.size_ != kWebMUnknownSize &&
- list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
- return -1;
- }
-
- if (id_type == LIST) {
- list_state.bytes_parsed_ += header_size;
-
- if (!OnListStart(id, element_size))
- return -1;
- return header_size;
- }
-
- // Make sure we have the entire element before trying to parse a non-list
- // element.
- if (size < element_size)
- return 0;
-
- int bytes_parsed = ParseNonListElement(id_type, id, element_size,
- data, size, list_state.client_);
- DCHECK_LE(bytes_parsed, size);
-
- // Return if an error occurred or we need more data.
- // Note: bytes_parsed is 0 for a successful parse of a size 0 element. We
- // need to check the element_size to disambiguate the "need more data" case
- // from a successful parse.
- if (bytes_parsed < 0 || (bytes_parsed == 0 && element_size != 0))
- return bytes_parsed;
-
- int result = header_size + bytes_parsed;
- list_state.bytes_parsed_ += result;
-
- // See if we have reached the end of the current list.
- if (list_state.bytes_parsed_ == list_state.size_) {
- if (!OnListEnd())
- return -1;
- }
-
- return result;
-}
-
-bool WebMListParser::OnListStart(int id, int64 size) {
- const ListElementInfo* element_info = FindListInfo(id);
- if (!element_info)
- return false;
-
- int current_level = root_level_ + list_state_stack_.size() - 1;
- if (current_level + 1 != element_info->level_)
- return false;
-
- WebMParserClient* current_list_client = NULL;
- if (!list_state_stack_.empty()) {
- // Make sure the new list doesn't go past the end of the current list.
- ListState current_list_state = list_state_stack_.back();
- if (current_list_state.size_ != kWebMUnknownSize &&
- current_list_state.size_ < current_list_state.bytes_parsed_ + size)
- return false;
- current_list_client = current_list_state.client_;
- } else {
- current_list_client = root_client_;
- }
-
- WebMParserClient* new_list_client = current_list_client->OnListStart(id);
- if (!new_list_client)
- return false;
-
- ListState new_list_state = { id, size, 0, element_info, new_list_client };
- list_state_stack_.push_back(new_list_state);
-
- if (size == 0)
- return OnListEnd();
-
- return true;
-}
-
-bool WebMListParser::OnListEnd() {
- int lists_ended = 0;
- for (; !list_state_stack_.empty(); ++lists_ended) {
- const ListState& list_state = list_state_stack_.back();
-
- if (list_state.bytes_parsed_ != list_state.size_)
- break;
-
- list_state_stack_.pop_back();
-
- int64 bytes_parsed = list_state.bytes_parsed_;
- WebMParserClient* client = NULL;
- if (!list_state_stack_.empty()) {
- // Update the bytes_parsed_ for the parent element.
- list_state_stack_.back().bytes_parsed_ += bytes_parsed;
- client = list_state_stack_.back().client_;
- } else {
- client = root_client_;
- }
-
- if (!client->OnListEnd(list_state.id_))
- return false;
- }
-
- DCHECK_GE(lists_ended, 1);
-
- if (list_state_stack_.empty())
- ChangeState(DONE_PARSING_LIST);
-
- return true;
-}
-
-bool WebMListParser::IsSiblingOrAncestor(int id_a, int id_b) const {
- DCHECK((id_a == kWebMIdSegment) || (id_a == kWebMIdCluster));
-
- if (id_a == kWebMIdCluster) {
- // kWebMIdCluster siblings.
- for (size_t i = 0; i < arraysize(kSegmentIds); i++) {
- if (kSegmentIds[i].id_ == id_b)
- return true;
- }
- }
-
- // kWebMIdSegment siblings.
- return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader));
-}
-
-} // namespace media