diff options
author | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-12 18:04:58 +0000 |
---|---|---|
committer | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-12 18:04:58 +0000 |
commit | fa51035c240ed1096c97dd7aaa505bd61857d672 (patch) | |
tree | 35f2ad644f67026ed8e4e6bf8943e0a99a2136b8 /media | |
parent | 1e75b26d2526d7a5ec2d9cc4ef1250fa3ea26e81 (diff) | |
download | chromium_src-fa51035c240ed1096c97dd7aaa505bd61857d672.zip chromium_src-fa51035c240ed1096c97dd7aaa505bd61857d672.tar.gz chromium_src-fa51035c240ed1096c97dd7aaa505bd61857d672.tar.bz2 |
Revert 114030 - Adding support for incremental cluster parsing.
BUG=104160
TEST=Covered by ChunkDemuxer unittests.
Review URL: http://codereview.chromium.org/8775035
TBR=acolwell@chromium.org
Review URL: http://codereview.chromium.org/8921010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114033 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/filters/chunk_demuxer.cc | 52 | ||||
-rw-r--r-- | media/filters/chunk_demuxer.h | 11 | ||||
-rw-r--r-- | media/media.gyp | 1 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser.cc | 36 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser.h | 2 | ||||
-rw-r--r-- | media/webm/webm_constants.h | 2 | ||||
-rw-r--r-- | media/webm/webm_info_parser.cc | 18 | ||||
-rw-r--r-- | media/webm/webm_parser.cc | 519 | ||||
-rw-r--r-- | media/webm/webm_parser.h | 113 | ||||
-rw-r--r-- | media/webm/webm_parser_unittest.cc | 264 | ||||
-rw-r--r-- | media/webm/webm_tracks_parser.cc | 38 |
11 files changed, 263 insertions, 793 deletions
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index f81b80f..d437d91 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc @@ -130,7 +130,7 @@ void ChunkDemuxerStream::Flush() { bool ChunkDemuxerStream::CanAddBuffers(const BufferQueue& buffers) const { base::AutoLock auto_lock(lock_); - // If we haven't seen any buffers yet, then anything can be added. + // If we haven't seen any buffers yet than anything can be added. if (last_buffer_timestamp_ == kNoTimestamp) return true; @@ -434,7 +434,7 @@ bool ChunkDemuxer::AppendData(const uint8* data, size_t length) { int cur_size = 0; int bytes_parsed = 0; int result = -1; - bool can_complete_seek = false; + bool parsed_a_cluster = false; byte_queue_.Peek(&cur, &cur_size); @@ -449,19 +449,16 @@ bool ChunkDemuxer::AppendData(const uint8* data, size_t length) { } break; - case INITIALIZED: { - bool buffers_added = false; - result = ParseCluster_Locked(cur, cur_size, &buffers_added); + case INITIALIZED: + result = ParseCluster_Locked(cur, cur_size); if (result < 0) { VLOG(1) << "AppendData(): parsing data failed"; ReportError_Locked(PIPELINE_ERROR_DECODE); return true; } - // We can complete the seek if we have successfully parsed - // some data and buffers were added to one of the DemuxerStreams. - can_complete_seek |= (result > 0 && buffers_added); - } break; + parsed_a_cluster = (result > 0); + break; case WAITING_FOR_INIT: case ENDED: @@ -480,7 +477,7 @@ bool ChunkDemuxer::AppendData(const uint8* data, size_t length) { byte_queue_.Pop(bytes_parsed); - if (can_complete_seek && seek_waits_for_data_) { + if (parsed_a_cluster && seek_waits_for_data_) { seek_waits_for_data_ = false; if (!seek_cb_.is_null()) @@ -733,8 +730,7 @@ bool ChunkDemuxer::SetupStreams() { return !no_supported_streams; } -int ChunkDemuxer::ParseCluster_Locked(const uint8* data, int size, - bool* buffers_added) { +int ChunkDemuxer::ParseCluster_Locked(const uint8* data, int size) { lock_.AssertAcquired(); if (!cluster_parser_.get()) return -1; @@ -753,6 +749,9 @@ int ChunkDemuxer::ParseCluster_Locked(const uint8* data, int size, } // Skip the element. return result + element_size; + } else if (id != kWebMIdCluster) { + VLOG(1) << "Unexpected ID 0x" << std::hex << id; + return -1; } int bytes_parsed = cluster_parser_->Parse(data, size); @@ -760,25 +759,20 @@ int ChunkDemuxer::ParseCluster_Locked(const uint8* data, int size, if (bytes_parsed <= 0) return bytes_parsed; - if (!cluster_parser_->audio_buffers().empty() || - !cluster_parser_->video_buffers().empty()) { - // Make sure we can add the buffers to both streams before we actually - // add them. This allows us to accept all of the data or none of it. - if ((audio_.get() && - !audio_->CanAddBuffers(cluster_parser_->audio_buffers())) || - (video_.get() && - !video_->CanAddBuffers(cluster_parser_->video_buffers()))) { - return -1; - } - - if (audio_.get()) - audio_->AddBuffers(cluster_parser_->audio_buffers()); + // Make sure we can add the buffers to both streams before we actutally + // add them. This allows us to accept all of the data or none of it. + if ((audio_.get() && + !audio_->CanAddBuffers(cluster_parser_->audio_buffers())) || + (video_.get() && + !video_->CanAddBuffers(cluster_parser_->video_buffers()))) { + return -1; + } - if (video_.get()) - video_->AddBuffers(cluster_parser_->video_buffers()); + if (audio_.get()) + audio_->AddBuffers(cluster_parser_->audio_buffers()); - *buffers_added = true; - } + if (video_.get()) + video_->AddBuffers(cluster_parser_->video_buffers()); // TODO(acolwell) : make this more representative of what is actually // buffered. diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h index 42f1097..b0f0d02 100644 --- a/media/filters/chunk_demuxer.h +++ b/media/filters/chunk_demuxer.h @@ -81,18 +81,13 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer { // found. bool SetupStreams(); - // Parse a cluster and add the buffers to the appropriate DemuxerStream. This - // method also skips over CUES elements if it happens to encounter them. - // - // |data| is expected to point to the beginning of an element. - // - // |buffers_added| - Indicates whether Buffers were added to DemuxerStreams - // during the call. This is only valid if the return value > 0. + // Parse a cluster add add the buffers to the appropriate DemxuerStream. + // |data| is expected to point to the beginning of a cluster element. // // Returns -1 if the parse fails. // Returns 0 if more data is needed. // Returns the number of bytes parsed on success. - int ParseCluster_Locked(const uint8* data, int size, bool* buffers_added); + int ParseCluster_Locked(const uint8* data, int size); // Reports an error and puts the demuxer in a state where it won't accept more // data. diff --git a/media/media.gyp b/media/media.gyp index abe8310..a52d4a5 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -621,7 +621,6 @@ 'video/capture/video_capture_device_unittest.cc', 'webm/cluster_builder.cc', 'webm/cluster_builder.h', - 'webm/webm_parser_unittest.cc', ], 'conditions': [ ['os_posix==1 and OS!="mac"', { diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc index fd716b2..8eb045c 100644 --- a/media/webm/webm_cluster_parser.cc +++ b/media/webm/webm_cluster_parser.cc @@ -26,7 +26,6 @@ WebMClusterParser::WebMClusterParser(int64 timecode_scale, audio_default_duration_(audio_default_duration), video_track_num_(video_track_num), video_default_duration_(video_default_duration), - parser_(kWebMIdCluster), last_block_timecode_(-1), cluster_timecode_(-1) { } @@ -34,25 +33,12 @@ WebMClusterParser::WebMClusterParser(int64 timecode_scale, WebMClusterParser::~WebMClusterParser() {} int WebMClusterParser::Parse(const uint8* buf, int size) { + last_block_timecode_ = -1; + cluster_timecode_ = -1; audio_buffers_.clear(); video_buffers_.clear(); - int result = parser_.Parse(buf, size, this); - - if (result <= 0) - return result; - - if (parser_.IsParsingComplete()) { - // Reset the parser if we're done parsing so that - // it is ready to accept another cluster on the next - // call. - parser_.Reset(); - - last_block_timecode_ = -1; - cluster_timecode_ = -1; - } - - return result; + return WebMParseListElement(buf, size, kWebMIdCluster, 1, this); } bool WebMClusterParser::OnListStart(int id) { @@ -81,17 +67,17 @@ bool WebMClusterParser::OnUInt(int id, int64 val) { } bool WebMClusterParser::OnFloat(int id, double val) { - DVLOG(1) << "Unexpected float element with ID " << std::hex << id; + VLOG(1) << "Unexpected float element with ID " << std::hex << id; return false; } bool WebMClusterParser::OnBinary(int id, const uint8* data, int size) { - DVLOG(1) << "Unexpected binary element with ID " << std::hex << id; + VLOG(1) << "Unexpected binary element with ID " << std::hex << id; return false; } bool WebMClusterParser::OnString(int id, const std::string& str) { - DVLOG(1) << "Unexpected string element with ID " << std::hex << id; + VLOG(1) << "Unexpected string element with ID " << std::hex << id; return false; } @@ -99,17 +85,17 @@ bool WebMClusterParser::OnSimpleBlock(int track_num, int timecode, int flags, const uint8* data, int size) { if (cluster_timecode_ == -1) { - DVLOG(1) << "Got SimpleBlock before cluster timecode."; + VLOG(1) << "Got SimpleBlock before cluster timecode."; return false; } if (timecode < 0) { - DVLOG(1) << "Got SimpleBlock with negative timecode offset " << timecode; + VLOG(1) << "Got SimpleBlock with negative timecode offset " << timecode; return false; } if (last_block_timecode_ != -1 && timecode < last_block_timecode_) { - DVLOG(1) << "Got SimpleBlock with a timecode before the previous block."; + VLOG(1) << "Got SimpleBlock with a timecode before the previous block."; return false; } @@ -129,13 +115,13 @@ bool WebMClusterParser::OnSimpleBlock(int track_num, int timecode, buffer->SetDuration(video_default_duration_); queue = &video_buffers_; } else { - DVLOG(1) << "Unexpected track number " << track_num; + VLOG(1) << "Unexpected track number " << track_num; return false; } if (!queue->empty() && buffer->GetTimestamp() == queue->back()->GetTimestamp()) { - DVLOG(1) << "Got SimpleBlock timecode is not strictly monotonically " + VLOG(1) << "Got SimpleBlock timecode is not strictly monotonically " << "increasing for track " << track_num; return false; } diff --git a/media/webm/webm_cluster_parser.h b/media/webm/webm_cluster_parser.h index 7fb1b94..5a367b0 100644 --- a/media/webm/webm_cluster_parser.h +++ b/media/webm/webm_cluster_parser.h @@ -53,8 +53,6 @@ class WebMClusterParser : public WebMParserClient { int video_track_num_; base::TimeDelta video_default_duration_; - WebMListParser parser_; - int64 last_block_timecode_; int64 cluster_timecode_; diff --git a/media/webm/webm_constants.h b/media/webm/webm_constants.h index 96e7c01..471115b 100644 --- a/media/webm/webm_constants.h +++ b/media/webm/webm_constants.h @@ -64,8 +64,6 @@ const int kWebMIdVideo = 0xE0; const int kWebMIdVoid = 0xEC; const int kWebMIdWritingApp = 0x5741; -const int64 kWebMUnknownSize = GG_LONGLONG(0x00FFFFFFFFFFFFFF); - // Default timecode scale if the TimecodeScale element is // not specified in the INFO element. const int kWebMDefaultTimecodeScale = 1000000; diff --git a/media/webm/webm_info_parser.cc b/media/webm/webm_info_parser.cc index 5807d7e..41e1a25 100644 --- a/media/webm/webm_info_parser.cc +++ b/media/webm/webm_info_parser.cc @@ -17,17 +17,7 @@ WebMInfoParser::WebMInfoParser() WebMInfoParser::~WebMInfoParser() {} int WebMInfoParser::Parse(const uint8* buf, int size) { - timecode_scale_ = -1; - duration_ = -1; - - WebMListParser parser(kWebMIdInfo); - int result = parser.Parse(buf, size, this); - - if (result <= 0) - return result; - - // For now we do all or nothing parsing. - return parser.IsParsingComplete() ? result : 0; + return WebMParseListElement(buf, size, kWebMIdInfo, 1, this); } bool WebMInfoParser::OnListStart(int id) { return true; } @@ -46,7 +36,7 @@ bool WebMInfoParser::OnUInt(int id, int64 val) { return true; if (timecode_scale_ != -1) { - DVLOG(1) << "Multiple values for id " << std::hex << id << " specified"; + VLOG(1) << "Multiple values for id " << std::hex << id << " specified"; return false; } @@ -56,12 +46,12 @@ bool WebMInfoParser::OnUInt(int id, int64 val) { bool WebMInfoParser::OnFloat(int id, double val) { if (id != kWebMIdDuration) { - DVLOG(1) << "Unexpected float for id" << std::hex << id; + VLOG(1) << "Unexpected float for id" << std::hex << id; return false; } if (duration_ != -1) { - DVLOG(1) << "Multiple values for duration."; + VLOG(1) << "Multiple values for duration."; return false; } diff --git a/media/webm/webm_parser.cc b/media/webm/webm_parser.cc index 1422308..1e42815 100644 --- a/media/webm/webm_parser.cc +++ b/media/webm/webm_parser.cc @@ -20,7 +20,6 @@ namespace media { static const int kMaxLevelDepth = 6; enum ElementType { - UNKNOWN, LIST, UINT, FLOAT, @@ -31,13 +30,13 @@ enum ElementType { }; struct ElementIdInfo { + int level_; ElementType type_; int id_; }; struct ListElementInfo { int id_; - int level_; const ElementIdInfo* id_info_; int id_info_size_; }; @@ -48,83 +47,84 @@ struct ListElementInfo { // marked as SKIP because they are valid, but we don't care about them // right now. static const ElementIdInfo kClusterIds[] = { - {UINT, kWebMIdTimecode}, - {SBLOCK, kWebMIdSimpleBlock}, - {LIST, kWebMIdBlockGroup}, -}; - -static const ElementIdInfo kSegmentIds[] = { - {SKIP, kWebMIdSeekHead}, // TODO(acolwell): add SeekHead info - {LIST, kWebMIdInfo}, - {LIST, kWebMIdCluster}, - {LIST, kWebMIdTracks}, - {SKIP, kWebMIdCues}, // TODO(acolwell): add CUES info + {2, UINT, kWebMIdTimecode}, + {2, SBLOCK, kWebMIdSimpleBlock}, + {2, LIST, kWebMIdBlockGroup}, }; static const ElementIdInfo kInfoIds[] = { - {SKIP, kWebMIdSegmentUID}, - {UINT, kWebMIdTimecodeScale}, - {FLOAT, kWebMIdDuration}, - {SKIP, kWebMIdDateUTC}, - {SKIP, kWebMIdTitle}, - {SKIP, kWebMIdMuxingApp}, - {SKIP, kWebMIdWritingApp}, + {2, SKIP, kWebMIdSegmentUID}, + {2, UINT, kWebMIdTimecodeScale}, + {2, FLOAT, kWebMIdDuration}, + {2, SKIP, kWebMIdDateUTC}, + {2, SKIP, kWebMIdTitle}, + {2, SKIP, kWebMIdMuxingApp}, + {2, SKIP, kWebMIdWritingApp}, }; static const ElementIdInfo kTracksIds[] = { - {LIST, kWebMIdTrackEntry}, + {2, LIST, kWebMIdTrackEntry}, }; static const ElementIdInfo kTrackEntryIds[] = { - {UINT, kWebMIdTrackNumber}, - {SKIP, kWebMIdTrackUID}, - {UINT, kWebMIdTrackType}, - {SKIP, kWebMIdFlagEnabled}, - {SKIP, kWebMIdFlagDefault}, - {SKIP, kWebMIdFlagForced}, - {UINT, kWebMIdFlagLacing}, - {UINT, kWebMIdDefaultDuration}, - {SKIP, kWebMIdName}, - {SKIP, kWebMIdLanguage}, - {STRING, kWebMIdCodecID}, - {BINARY, kWebMIdCodecPrivate}, - {SKIP, kWebMIdCodecName}, - {LIST, kWebMIdVideo}, - {LIST, kWebMIdAudio}, + {3, UINT, kWebMIdTrackNumber}, + {3, SKIP, kWebMIdTrackUID}, + {3, UINT, kWebMIdTrackType}, + {3, SKIP, kWebMIdFlagEnabled}, + {3, SKIP, kWebMIdFlagDefault}, + {3, SKIP, kWebMIdFlagForced}, + {3, UINT, kWebMIdFlagLacing}, + {3, UINT, kWebMIdDefaultDuration}, + {3, SKIP, kWebMIdName}, + {3, SKIP, kWebMIdLanguage}, + {3, STRING, kWebMIdCodecID}, + {3, BINARY, kWebMIdCodecPrivate}, + {3, SKIP, kWebMIdCodecName}, + {3, LIST, kWebMIdVideo}, + {3, LIST, kWebMIdAudio}, }; static const ElementIdInfo kVideoIds[] = { - {SKIP, kWebMIdFlagInterlaced}, - {SKIP, kWebMIdStereoMode}, - {UINT, kWebMIdPixelWidth}, - {UINT, kWebMIdPixelHeight}, - {SKIP, kWebMIdPixelCropBottom}, - {SKIP, kWebMIdPixelCropTop}, - {SKIP, kWebMIdPixelCropLeft}, - {SKIP, kWebMIdPixelCropRight}, - {SKIP, kWebMIdDisplayWidth}, - {SKIP, kWebMIdDisplayHeight}, - {SKIP, kWebMIdDisplayUnit}, - {SKIP, kWebMIdAspectRatioType}, + {4, SKIP, kWebMIdFlagInterlaced}, + {4, SKIP, kWebMIdStereoMode}, + {4, UINT, kWebMIdPixelWidth}, + {4, UINT, kWebMIdPixelHeight}, + {4, SKIP, kWebMIdPixelCropBottom}, + {4, SKIP, kWebMIdPixelCropTop}, + {4, SKIP, kWebMIdPixelCropLeft}, + {4, SKIP, kWebMIdPixelCropRight}, + {4, SKIP, kWebMIdDisplayWidth}, + {4, SKIP, kWebMIdDisplayHeight}, + {4, SKIP, kWebMIdDisplayUnit}, + {4, SKIP, kWebMIdAspectRatioType}, }; static const ElementIdInfo kAudioIds[] = { - {SKIP, kWebMIdSamplingFrequency}, - {SKIP, kWebMIdOutputSamplingFrequency}, - {UINT, kWebMIdChannels}, - {SKIP, kWebMIdBitDepth}, + {4, SKIP, kWebMIdSamplingFrequency}, + {4, SKIP, kWebMIdOutputSamplingFrequency}, + {4, UINT, kWebMIdChannels}, + {4, SKIP, kWebMIdBitDepth}, +}; + +static const ElementIdInfo kClustersOnly[] = { + {1, LIST, kWebMIdCluster}, }; static const ListElementInfo kListElementInfo[] = { - { kWebMIdCluster, 1, kClusterIds, sizeof(kClusterIds) }, - { kWebMIdSegment, 0, kSegmentIds, sizeof(kSegmentIds) }, - { kWebMIdInfo, 1, kInfoIds, sizeof(kInfoIds) }, - { kWebMIdTracks, 1, kTracksIds, sizeof(kTracksIds) }, - { kWebMIdTrackEntry, 2, kTrackEntryIds, sizeof(kTrackEntryIds) }, - { kWebMIdVideo, 3, kVideoIds, sizeof(kVideoIds) }, - { kWebMIdAudio, 3, kAudioIds, sizeof(kAudioIds) }, + { kWebMIdCluster, kClusterIds, sizeof(kClusterIds) }, + { kWebMIdInfo, kInfoIds, sizeof(kInfoIds) }, + { kWebMIdTracks, kTracksIds, sizeof(kTracksIds) }, + { kWebMIdTrackEntry, kTrackEntryIds, sizeof(kTrackEntryIds) }, + { kWebMIdVideo, kVideoIds, sizeof(kVideoIds) }, + { kWebMIdAudio, kAudioIds, sizeof(kAudioIds) }, }; +// Number of elements in kListElementInfo. +const int kListElementInfoCount = + sizeof(kListElementInfo) / sizeof(ListElementInfo); + +WebMParserClient::~WebMParserClient() {} + // 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. @@ -206,27 +206,22 @@ int WebMParseElementHeader(const uint8* buf, int 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_size) { - - // Check for global element IDs that can be anywhere. - if (id == kWebMIdVoid || id == kWebMIdCRC32) - return SKIP; - +// Finds ElementIdInfo for a specific ID. +static const ElementIdInfo* FindIdInfo(int id, + const ElementIdInfo* id_info, + int id_info_size) { int count = id_info_size / sizeof(*id_info); for (int i = 0; i < count; ++i) { if (id == id_info[i].id_) - return id_info[i].type_; + return &id_info[i]; } - return UNKNOWN; + return NULL; } // Finds ListElementInfo for a specific ID. static const ListElementInfo* FindListInfo(int id) { - for (size_t i = 0; i < arraysize(kListElementInfo); ++i) { + for (int i = 0; i < kListElementInfoCount; ++i) { if (id == kListElementInfo[i].id_) return &kListElementInfo[i]; } @@ -242,7 +237,7 @@ static int ParseSimpleBlock(const uint8* buf, int size, // Return an error if the trackNum > 127. We just aren't // going to support large track numbers right now. if ((buf[0] & 0x80) != 0x80) { - DVLOG(1) << "TrackNumber over 127 not supported"; + VLOG(1) << "TrackNumber over 127 not supported"; return -1; } @@ -252,7 +247,7 @@ static int ParseSimpleBlock(const uint8* buf, int size, int lacing = (flags >> 1) & 0x3; if (lacing != 0) { - DVLOG(1) << "Lacing " << lacing << " not supported yet."; + VLOG(1) << "Lacing " << lacing << " not supported yet."; return -1; } @@ -270,6 +265,39 @@ static int ParseSimpleBlock(const uint8* buf, int size, return size; } +static int ParseElements(const ElementIdInfo* id_info, + int id_info_size, + const uint8* buf, int size, int level, + WebMParserClient* client); + +static int ParseElementList(const uint8* buf, int size, + int id, int level, + WebMParserClient* client) { + const ListElementInfo* list_info = FindListInfo(id); + + if (!list_info) { + VLOG(1) << "Failed to find list info for ID " << std::hex << id; + return -1; + } + + if (!client->OnListStart(id)) + return -1; + + int result = ParseElements(list_info->id_info_, + list_info->id_info_size_, + buf, size, + level + 1, + client); + + if (result <= 0) + return result; + + if (!client->OnListEnd(id)) + return -1; + + DCHECK_EQ(result, size); + return result; +} static int ParseUInt(const uint8* buf, int size, int id, WebMParserClient* client) { @@ -326,285 +354,142 @@ static int ParseFloat(const uint8* buf, int size, int id, return size; } -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 SBLOCK: - result = ParseSimpleBlock(buf, element_size, client); - break; - 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: - if (client->OnBinary(id, buf, element_size)) { - result = element_size; - } else { - result = -1; - } - break; - case STRING: - if (client->OnString(id, - std::string(reinterpret_cast<const char*>(buf), - element_size))) { - result = element_size; - } else { - result = -1; - } - 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() {} - -WebMListParser::WebMListParser(int id) - : state_(NEED_LIST_HEADER), - root_id_(id) { - const ListElementInfo* list_info = FindListInfo(id); - - DCHECK(list_info); +static int ParseElements(const ElementIdInfo* id_info, + int id_info_size, + const uint8* buf, int size, int level, + WebMParserClient* client) { + DCHECK_GE(id_info_size, 0); + DCHECK_GE(size, 0); + DCHECK_GE(level, 0); - root_level_ = list_info->level_; -} + const uint8* cur = buf; + int cur_size = size; + int used = 0; -WebMListParser::~WebMListParser() {} + if (level > kMaxLevelDepth) + return -1; -void WebMListParser::Reset() { - ChangeState(NEED_LIST_HEADER); - list_state_stack_.clear(); -} + while (cur_size > 0) { + int id = 0; + int64 element_size = 0; + int result = WebMParseElementHeader(cur, cur_size, &id, &element_size); -int WebMListParser::Parse(const uint8* buf, int size, - WebMParserClient* client) { - DCHECK(buf); - DCHECK(client); + if (result <= 0) + return result; - if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST) - return -1; + cur += result; + cur_size -= result; + used += result; - if (size == 0) - return 0; + // Check to see if the element is larger than the remaining data. + if (element_size > cur_size) + return 0; - const uint8* cur = buf; - int cur_size = size; - int bytes_parsed = 0; + const ElementIdInfo* info = FindIdInfo(id, id_info, id_info_size); - 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 (info == NULL) { + VLOG(1) << "No info for ID " << std::hex << id; - if (result < 0) - return result; + // TODO(acolwell): Change this to return -1 after the API has solidified. + // We don't want to allow elements we don't recognize. + cur += element_size; + cur_size -= element_size; + used += element_size; + continue; + } - if (result == 0) - return bytes_parsed; + if (info->level_ != level) { + VLOG(1) << "ID " << std::hex << id << std::dec << " at level " + << level << " instead of " << info->level_; + return -1; + } - switch(state_) { - case NEED_LIST_HEADER: { - if (element_id != root_id_) { - ChangeState(PARSE_ERROR); + switch(info->type_) { + case SBLOCK: + if (ParseSimpleBlock(cur, element_size, client) <= 0) return -1; - } - - // TODO(acolwell): Add support for lists of unknown size. - if (element_size == kWebMUnknownSize) { - ChangeState(PARSE_ERROR); + break; + case LIST: + if (ParseElementList(cur, element_size, id, level, client) < 0) return -1; - } - - ChangeState(INSIDE_LIST); - if (!OnListStart(root_id_, element_size, client)) + break; + case UINT: + if (ParseUInt(cur, element_size, id, client) <= 0) 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, client); - - DCHECK_LE(result, header_size + element_data_size); - if (result < 0) { - ChangeState(PARSE_ERROR); + case FLOAT: + if (ParseFloat(cur, element_size, id, client) <= 0) return -1; - } - - if (result == 0) - return bytes_parsed; - break; - } - case DONE_PARSING_LIST: - case PARSE_ERROR: - // Shouldn't be able to get here. - NOTIMPLEMENTED(); + case BINARY: + if (!client->OnBinary(id, cur, element_size)) + return -1; break; - } - - cur += result; - cur_size -= result; - bytes_parsed += result; + case STRING: + if (!client->OnString(id, + std::string(reinterpret_cast<const char*>(cur), + element_size))) + return -1; + break; + case SKIP: + // Do nothing. + break; + default: + VLOG(1) << "Unhandled id type " << info->type_; + return -1; + }; + + cur += element_size; + cur_size -= element_size; + used += element_size; } - return (state_ == PARSE_ERROR) ? -1 : bytes_parsed; + return used; } -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, - WebMParserClient* client) { - 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_size_); - - // Unexpected ID. - if (id_type == UNKNOWN) { - DVLOG(1) << "No ElementType info for ID 0x" << std::hex << id; - return -1; - } - - // 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) { +// Parses a single list element that matches |id|. This method fails if the +// buffer points to an element that does not match |id|. +int WebMParseListElement(const uint8* buf, int size, int id, + int level, WebMParserClient* client) { + if (size < 0) return -1; - } - - if (id_type == LIST) { - list_state.bytes_parsed_ += header_size; - - if (!OnListStart(id, element_size, client)) - return -1; - return header_size; - } - // Make sure we have the entire element before trying to parse a non-list - // element. - if (size < element_size) + if (size == 0) return 0; - int bytes_parsed = ParseNonListElement(id_type, id, element_size, - data, size, 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(client)) - return -1; - } - - return result; -} - -bool WebMListParser::OnListStart(int id, int64 size, WebMParserClient* client) { - ListState list_state = { id, size, 0, FindListInfo(id)}; - - if (!list_state.element_info_) - return false; - - int current_level = root_level_ + list_state_stack_.size() - 1; - if (current_level + 1 != list_state.element_info_->level_) - return false; - - if (!list_state_stack_.empty()) { - - // Make sure the new list doesn't go past the end of the current list. - ListState current_list = list_state_stack_.back(); - if (current_list.size_ != kWebMUnknownSize && - current_list.size_ < current_list.bytes_parsed_ + size) - return false; - } - - if (!client->OnListStart(id)) - return false; + const uint8* cur = buf; + int cur_size = size; + int bytes_parsed = 0; + int element_id = 0; + int64 element_size = 0; + int result = WebMParseElementHeader(cur, cur_size, &element_id, + &element_size); - list_state_stack_.push_back(list_state); + if (result <= 0) + return result; - if (size == 0) { - return OnListEnd(client); - } + cur += result; + cur_size -= result; + bytes_parsed += result; - return true; -} - -bool WebMListParser::OnListEnd(WebMParserClient* client) { - int lists_ended = 0; - for (; !list_state_stack_.empty(); ++lists_ended) { - const ListState& list_state = list_state_stack_.back(); + if (element_id != id) + return -1; - if (list_state.bytes_parsed_ != list_state.size_) - break; + if (element_size > cur_size) + return 0; - if (!client->OnListEnd(list_state.id_)) - return false; + if (element_size > 0) { + result = ParseElementList(cur, element_size, element_id, level, client); - int64 bytes_parsed = list_state.bytes_parsed_; - list_state_stack_.pop_back(); + if (result <= 0) + return result; - if (!list_state_stack_.empty()) { - // Update the bytes_parsed_ for the parent element. - list_state_stack_.back().bytes_parsed_ += bytes_parsed; - } + cur += result; + cur_size -= result; + bytes_parsed += result; } - DCHECK_GE(lists_ended, 1); - - if (list_state_stack_.empty()) - ChangeState(DONE_PARSING_LIST); - - return true; + return bytes_parsed; } } // namespace media diff --git a/media/webm/webm_parser.h b/media/webm/webm_parser.h index bc3e09f..7d15f9b 100644 --- a/media/webm/webm_parser.h +++ b/media/webm/webm_parser.h @@ -6,10 +6,8 @@ #define MEDIA_WEBM_WEBM_PARSER_H_ #include <string> -#include <vector> #include "base/basictypes.h" -#include "media/base/media_export.h" namespace media { @@ -23,7 +21,7 @@ namespace media { // indicates whether the parsed data is valid. If false is returned // then the parse is immediately terminated and an error is reported by the // parser. -class MEDIA_EXPORT WebMParserClient { +class WebMParserClient { public: virtual ~WebMParserClient(); @@ -36,106 +34,6 @@ class MEDIA_EXPORT WebMParserClient { virtual bool OnSimpleBlock(int track_num, int timecode, int flags, const uint8* data, int size) = 0; - protected: - WebMParserClient(); - - DISALLOW_COPY_AND_ASSIGN(WebMParserClient); -}; - -struct ListElementInfo; - -// Parses a WebM list element and all of its children. This -// class supports incremental parsing of the list so Parse() -// can be called multiple times with pieces of the list. -// IsParsingComplete() will return true once the entire list has -// been parsed. -class MEDIA_EXPORT WebMListParser { - public: - // |id| - Element ID of the list we intend to parse. - explicit WebMListParser(int id); - ~WebMListParser(); - - // Resets the state of the parser so it can start parsing a new list. - void Reset(); - - // Parses list data contained in |buf|. - // |client| Called as different elements in the list are parsed. - // - // Returns < 0 if the parse fails. - // Returns 0 if more data is needed. - // Returning > 0 indicates success & the number of bytes parsed. - int Parse(const uint8* buf, int size, WebMParserClient* client); - - // Returns true if the entire list has been parsed. - bool IsParsingComplete() const; - - private: - enum State { - NEED_LIST_HEADER, - INSIDE_LIST, - DONE_PARSING_LIST, - PARSE_ERROR, - }; - - struct ListState { - int id_; - int size_; - int bytes_parsed_; - const ListElementInfo* element_info_; - }; - - void ChangeState(State new_state); - - // Parses a single element in the current list. - // - // |header_size| - The size of the element header - // |id| - The ID of the element being parsed. - // |element_size| - The size of the element body. - // |data| - Pointer to the element contents. - // |size| - Number of bytes in |data| - // |client| - Client to pass the parsed data to. - // - // Returns < 0 if the parse fails. - // Returns 0 if more data is needed. - // Returning > 0 indicates success & the number of bytes parsed. - int ParseListElement(int header_size, - int id, int64 element_size, - const uint8* data, int size, - WebMParserClient* client); - - // Called when starting to parse a new list. - // - // |id| - The ID of the new list. - // |size| - The size of the new list. - // |client| - The client object to notify that a new list is being parsed. - // - // Returns true if this list can be started in the current context. False - // if starting this list causes some sort of parse error. - bool OnListStart(int id, int64 size, WebMParserClient* client); - - // Called when the end of the current list has been reached. This may also - // signal the end of the current list's ancestors if the current list happens - // to be at the end of its parent. - // - // |client| - The client to notify about lists ending. - // - // Returns true if no errors occurred while ending this list(s). - bool OnListEnd(WebMParserClient* client); - - State state_; - - // Element ID passed to the constructor. - int root_id_; - - // Element level for |root_id_|. Used to verify that elements appear at - // the correct level. - int root_level_; - - // Stack of state for all the lists currently being parsed. Lists are - // added and removed from this stack as they are parsed. - std::vector<ListState> list_state_stack_; - - DISALLOW_COPY_AND_ASSIGN(WebMListParser); }; // Parses an element header & returns the ID and element size. @@ -149,6 +47,15 @@ class MEDIA_EXPORT WebMListParser { int WebMParseElementHeader(const uint8* buf, int size, int* id, int64* element_size); +// Parses a single list element that matches |id|. This method fails if the +// buffer points to an element that does not match |id|. +// +// Returns -1 if the parse fails. +// Returns 0 if more data is needed. +// Returns the number of bytes parsed on success. +int WebMParseListElement(const uint8* buf, int size, int id, + int level, WebMParserClient* client); + } // namespace media #endif // MEDIA_WEBM_WEBM_PARSER_H_ diff --git a/media/webm/webm_parser_unittest.cc b/media/webm/webm_parser_unittest.cc deleted file mode 100644 index e377fda..0000000 --- a/media/webm/webm_parser_unittest.cc +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) 2011 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/cluster_builder.h" -#include "media/webm/webm_constants.h" -#include "media/webm/webm_parser.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::InSequence; -using ::testing::Return; -using ::testing::StrictMock; -using ::testing::_; - -namespace media { - -class MockWebMParserClient : public WebMParserClient { - public: - virtual ~MockWebMParserClient() {} - - // WebMParserClient methods. - MOCK_METHOD1(OnListStart, bool(int)); - MOCK_METHOD1(OnListEnd, bool(int)); - MOCK_METHOD2(OnUInt, bool(int, int64)); - MOCK_METHOD2(OnFloat, bool(int, double)); - MOCK_METHOD3(OnBinary, bool(int, const uint8*, int)); - MOCK_METHOD2(OnString, bool(int, const std::string&)); - MOCK_METHOD5(OnSimpleBlock, bool(int, int, int, const uint8*, int)); -}; - -class WebMParserTest : public testing::Test { - protected: - StrictMock<MockWebMParserClient> client_; -}; - -struct SimpleBlockInfo { - int track_num; - int timestamp; -}; - -static void AddSimpleBlock(ClusterBuilder* cb, int track_num, - int64 timecode) { - uint8 data[] = { 0x00 }; - cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); -} - -static Cluster* CreateCluster(int timecode, - const SimpleBlockInfo* block_info, - int block_count) { - ClusterBuilder cb; - cb.SetClusterTimecode(0); - - for (int i = 0; i < block_count; i++) - AddSimpleBlock(&cb, block_info[i].track_num, block_info[i].timestamp); - - return cb.Finish(); -} - -static void CreateClusterExpectations(int timecode, - const SimpleBlockInfo* block_info, - int block_count, - MockWebMParserClient* client) { - - InSequence s; - EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); - EXPECT_CALL(*client, OnUInt(kWebMIdTimecode, 0)).WillOnce(Return(true)); - - for (int i = 0; i < block_count; i++) { - EXPECT_CALL(*client, OnSimpleBlock(block_info[i].track_num, - block_info[i].timestamp, - _, _, _)) - .WillOnce(Return(true)); - } - - EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); -} - -TEST_F(WebMParserTest, EmptyCluster) { - const uint8 kEmptyCluster[] = { - 0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0) - }; - int size = sizeof(kEmptyCluster); - - InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); - EXPECT_CALL(client_, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); - - WebMListParser parser(kWebMIdCluster); - int result = parser.Parse(kEmptyCluster, size, &client_); - EXPECT_EQ(size, result); - EXPECT_TRUE(parser.IsParsingComplete()); -} - -TEST_F(WebMParserTest, EmptyClusterInSegment) { - const uint8 kBuffer[] = { - 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5) - 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0) - }; - int size = sizeof(kBuffer); - - InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); - EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); - EXPECT_CALL(client_, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); - EXPECT_CALL(client_, OnListEnd(kWebMIdSegment)).WillOnce(Return(true)); - - WebMListParser parser(kWebMIdSegment); - int result = parser.Parse(kBuffer, size, &client_); - EXPECT_EQ(size, result); - EXPECT_TRUE(parser.IsParsingComplete()); -} - -// Test the case where a non-list child element has a size -// that is beyond the end of the parent. -TEST_F(WebMParserTest, ChildNonListLargerThanParent) { - const uint8 kBuffer[] = { - 0x1F, 0x43, 0xB6, 0x75, 0x81, // CLUSTER (size = 1) - 0xE7, 0x81, 0x01, // Timecode (size=1, value=1) - }; - int size = sizeof(kBuffer); - - InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); - - WebMListParser parser(kWebMIdCluster); - int result = parser.Parse(kBuffer, size, &client_); - EXPECT_EQ(-1, result); - EXPECT_FALSE(parser.IsParsingComplete()); -} - -// Test the case where a list child element has a size -// that is beyond the end of the parent. -TEST_F(WebMParserTest, ChildListLargerThanParent) { - const uint8 kBuffer[] = { - 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5) - 0x1F, 0x43, 0xB6, 0x75, 0x81, 0x11 // CLUSTER (size = 1) - }; - int size = sizeof(kBuffer); - - InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); - - WebMListParser parser(kWebMIdSegment); - int result = parser.Parse(kBuffer, size, &client_); - EXPECT_EQ(-1, result); - EXPECT_FALSE(parser.IsParsingComplete()); -} - -// Expecting to parse a Cluster, but get a Segment. -TEST_F(WebMParserTest, ListIdDoesNotMatch) { - const uint8 kBuffer[] = { - 0x18, 0x53, 0x80, 0x67, 0x80, // SEGMENT (size = 0) - }; - int size = sizeof(kBuffer); - - WebMListParser parser(kWebMIdCluster); - int result = parser.Parse(kBuffer, size, &client_); - EXPECT_EQ(-1, result); - EXPECT_FALSE(parser.IsParsingComplete()); -} - -TEST_F(WebMParserTest, InvalidElementInList) { - const uint8 kBuffer[] = { - 0x18, 0x53, 0x80, 0x67, 0x82, // SEGMENT (size = 2) - 0xAE, 0x80, // TrackEntry (size = 0) - }; - int size = sizeof(kBuffer); - - InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); - - WebMListParser parser(kWebMIdSegment); - int result = parser.Parse(kBuffer, size, &client_); - EXPECT_EQ(-1, result); - EXPECT_FALSE(parser.IsParsingComplete()); -} - -TEST_F(WebMParserTest, VoidAndCRC32InList) { - const uint8 kBuffer[] = { - 0x18, 0x53, 0x80, 0x67, 0x99, // SEGMENT (size = 25) - 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3) - 0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3) - 0x1F, 0x43, 0xB6, 0x75, 0x8A, // CLUSTER (size = 10) - 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3) - 0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3) - }; - int size = sizeof(kBuffer); - - InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); - EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); - EXPECT_CALL(client_, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); - EXPECT_CALL(client_, OnListEnd(kWebMIdSegment)).WillOnce(Return(true)); - - WebMListParser parser(kWebMIdSegment); - int result = parser.Parse(kBuffer, size, &client_); - EXPECT_EQ(size, result); - EXPECT_TRUE(parser.IsParsingComplete()); -} - - -TEST_F(WebMParserTest, ParseListElementWithSingleCall) { - const SimpleBlockInfo kBlockInfo[] = { - { 0, 1 }, - { 1, 2 }, - { 0, 3 }, - { 0, 4 }, - { 1, 4 }, - }; - int block_count = arraysize(kBlockInfo); - - scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); - CreateClusterExpectations(0, kBlockInfo, block_count, &client_); - - WebMListParser parser(kWebMIdCluster); - int result = parser.Parse(cluster->data(), cluster->size(), &client_); - EXPECT_EQ(cluster->size(), result); - EXPECT_TRUE(parser.IsParsingComplete()); -} - -TEST_F(WebMParserTest, ParseListElementWithMultipleCalls) { - const SimpleBlockInfo kBlockInfo[] = { - { 0, 1 }, - { 1, 2 }, - { 0, 3 }, - { 0, 4 }, - { 1, 4 }, - }; - int block_count = arraysize(kBlockInfo); - - scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); - CreateClusterExpectations(0, kBlockInfo, block_count, &client_); - - const uint8* data = cluster->data(); - int size = cluster->size(); - int default_parse_size = 3; - WebMListParser parser(kWebMIdCluster); - int parse_size = std::min(default_parse_size, size); - - while (size > 0) { - int result = parser.Parse(data, parse_size, &client_); - EXPECT_GE(result, 0); - EXPECT_LE(result, parse_size); - - if (result == 0) { - // The parser needs more data so increase the parse_size a little. - EXPECT_FALSE(parser.IsParsingComplete()); - parse_size += default_parse_size; - parse_size = std::min(parse_size, size); - continue; - } - - parse_size = default_parse_size; - - data += result; - size -= result; - - EXPECT_EQ((size == 0), parser.IsParsingComplete()); - } - EXPECT_TRUE(parser.IsParsingComplete()); -} - -} // namespace media diff --git a/media/webm/webm_tracks_parser.cc b/media/webm/webm_tracks_parser.cc index 7cd9569..29b4f33 100644 --- a/media/webm/webm_tracks_parser.cc +++ b/media/webm/webm_tracks_parser.cc @@ -9,39 +9,21 @@ namespace media { -static const base::TimeDelta kNoDuration = - base::TimeDelta::FromMicroseconds(-1); - WebMTracksParser::WebMTracksParser(int64 timecode_scale) : timecode_scale_(timecode_scale), track_type_(-1), track_num_(-1), track_default_duration_(-1), audio_track_num_(-1), - audio_default_duration_(kNoDuration), + audio_default_duration_(base::TimeDelta::FromMicroseconds(-1)), video_track_num_(-1), - video_default_duration_(kNoDuration) { + video_default_duration_(base::TimeDelta::FromMicroseconds(-1)) { } WebMTracksParser::~WebMTracksParser() {} int WebMTracksParser::Parse(const uint8* buf, int size) { - track_type_ =-1; - track_num_ = -1; - track_default_duration_ = -1; - audio_track_num_ = -1; - audio_default_duration_ = kNoDuration; - video_track_num_ = -1; - video_default_duration_ = kNoDuration; - - WebMListParser parser(kWebMIdTracks); - int result = parser.Parse(buf, size, this); - - if (result <= 0) - return result; - - // For now we do all or nothing parsing. - return parser.IsParsingComplete() ? result : 0; + return WebMParseListElement(buf, size, kWebMIdTracks, 1, this); } @@ -58,9 +40,9 @@ bool WebMTracksParser::OnListStart(int id) { bool WebMTracksParser::OnListEnd(int id) { if (id == kWebMIdTrackEntry) { if (track_type_ == -1 || track_num_ == -1) { - DVLOG(1) << "Missing TrackEntry data" - << " TrackType " << track_type_ - << " TrackNum " << track_num_; + VLOG(1) << "Missing TrackEntry data" + << " TrackType " << track_type_ + << " TrackNum " << track_num_; return false; } @@ -75,7 +57,7 @@ bool WebMTracksParser::OnListEnd(int id) { audio_track_num_ = track_num_; audio_default_duration_ = default_duration; } else { - DVLOG(1) << "Unexpected TrackType " << track_type_; + VLOG(1) << "Unexpected TrackType " << track_type_; return false; } @@ -104,7 +86,7 @@ bool WebMTracksParser::OnUInt(int id, int64 val) { } if (*dst != -1) { - DVLOG(1) << "Multiple values for id " << std::hex << id << " specified"; + VLOG(1) << "Multiple values for id " << std::hex << id << " specified"; return false; } @@ -113,7 +95,7 @@ bool WebMTracksParser::OnUInt(int id, int64 val) { } bool WebMTracksParser::OnFloat(int id, double val) { - DVLOG(1) << "Unexpected float for id" << std::hex << id; + VLOG(1) << "Unexpected float for id" << std::hex << id; return false; } @@ -126,7 +108,7 @@ bool WebMTracksParser::OnString(int id, const std::string& str) { return false; if (str != "A_VORBIS" && str != "V_VP8") { - DVLOG(1) << "Unexpected CodecID " << str; + VLOG(1) << "Unexpected CodecID " << str; return false; } |