diff options
author | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-29 22:36:56 +0000 |
---|---|---|
committer | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-29 22:36:56 +0000 |
commit | cc289a6c2cc29b1d6d6eb66f49a303846ecbb7d4 (patch) | |
tree | f16f4a18dcb5742326d203eee700307de4f33591 /media/webm | |
parent | d313bf6cd10b4b0e9b089834b254785edb32fe51 (diff) | |
download | chromium_src-cc289a6c2cc29b1d6d6eb66f49a303846ecbb7d4.zip chromium_src-cc289a6c2cc29b1d6d6eb66f49a303846ecbb7d4.tar.gz chromium_src-cc289a6c2cc29b1d6d6eb66f49a303846ecbb7d4.tar.bz2 |
Add multiple WebMParserClient support in WebM parser.
When start processing a new List, the current WebMParserClient would be able to
specify another WebMParserClient to handle this list. This is achieved by
returning the new WebMParserClient by WebMParserClient::OnListStart.
BUG=none
TEST=passed media_unittests
Review URL: http://codereview.chromium.org/9022020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@115992 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/webm')
-rw-r--r-- | media/webm/webm_cluster_parser.cc | 23 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser.h | 5 | ||||
-rw-r--r-- | media/webm/webm_constants.h | 8 | ||||
-rw-r--r-- | media/webm/webm_info_parser.cc | 15 | ||||
-rw-r--r-- | media/webm/webm_info_parser.h | 4 | ||||
-rw-r--r-- | media/webm/webm_parser.cc | 174 | ||||
-rw-r--r-- | media/webm/webm_parser.h | 48 | ||||
-rw-r--r-- | media/webm/webm_parser_unittest.cc | 113 | ||||
-rw-r--r-- | media/webm/webm_tracks_parser.cc | 24 | ||||
-rw-r--r-- | media/webm/webm_tracks_parser.h | 6 |
10 files changed, 242 insertions, 178 deletions
diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc index fc64176..2d84405 100644 --- a/media/webm/webm_cluster_parser.cc +++ b/media/webm/webm_cluster_parser.cc @@ -26,7 +26,7 @@ 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), + parser_(kWebMIdCluster, this), last_block_timecode_(-1), cluster_timecode_(-1) { } @@ -45,7 +45,7 @@ int WebMClusterParser::Parse(const uint8* buf, int size) { audio_buffers_.clear(); video_buffers_.clear(); - int result = parser_.Parse(buf, size, this); + int result = parser_.Parse(buf, size); if (result <= 0) return result; @@ -63,11 +63,11 @@ int WebMClusterParser::Parse(const uint8* buf, int size) { return result; } -bool WebMClusterParser::OnListStart(int id) { +WebMParserClient* WebMClusterParser::OnListStart(int id) { if (id == kWebMIdCluster) cluster_timecode_ = -1; - return true; + return this; } bool WebMClusterParser::OnListEnd(int id) { @@ -88,21 +88,6 @@ bool WebMClusterParser::OnUInt(int id, int64 val) { return true; } -bool WebMClusterParser::OnFloat(int id, double val) { - DVLOG(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; - return false; -} - -bool WebMClusterParser::OnString(int id, const std::string& str) { - DVLOG(1) << "Unexpected string element with ID " << std::hex << id; - return false; -} - bool WebMClusterParser::OnSimpleBlock(int track_num, int timecode, int flags, const uint8* data, int size) { diff --git a/media/webm/webm_cluster_parser.h b/media/webm/webm_cluster_parser.h index 445d207..2db3755 100644 --- a/media/webm/webm_cluster_parser.h +++ b/media/webm/webm_cluster_parser.h @@ -40,12 +40,9 @@ class WebMClusterParser : public WebMParserClient { private: // WebMParserClient methods. - virtual bool OnListStart(int id) OVERRIDE; + virtual WebMParserClient* OnListStart(int id) OVERRIDE; virtual bool OnListEnd(int id) OVERRIDE; virtual bool OnUInt(int id, int64 val) OVERRIDE; - virtual bool OnFloat(int id, double val) OVERRIDE; - virtual bool OnBinary(int id, const uint8* data, int size) OVERRIDE; - virtual bool OnString(int id, const std::string& str) OVERRIDE; virtual bool OnSimpleBlock(int track_num, int timecode, int flags, const uint8* data, int size) OVERRIDE; diff --git a/media/webm/webm_constants.h b/media/webm/webm_constants.h index 96e7c01..5421048 100644 --- a/media/webm/webm_constants.h +++ b/media/webm/webm_constants.h @@ -66,14 +66,6 @@ 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; - -// Values for TrackType element. -const int kWebMTrackTypeVideo = 1; -const int kWebMTrackTypeAudio = 2; - } // namespace media #endif // MEDIA_WEBM_WEBM_CONSTANTS_H_ diff --git a/media/webm/webm_info_parser.cc b/media/webm/webm_info_parser.cc index 5807d7e..6df1690b 100644 --- a/media/webm/webm_info_parser.cc +++ b/media/webm/webm_info_parser.cc @@ -9,6 +9,10 @@ namespace media { +// Default timecode scale if the TimecodeScale element is +// not specified in the INFO element. +static const int kWebMDefaultTimecodeScale = 1000000; + WebMInfoParser::WebMInfoParser() : timecode_scale_(-1), duration_(-1) { @@ -20,8 +24,8 @@ int WebMInfoParser::Parse(const uint8* buf, int size) { timecode_scale_ = -1; duration_ = -1; - WebMListParser parser(kWebMIdInfo); - int result = parser.Parse(buf, size, this); + WebMListParser parser(kWebMIdInfo, this); + int result = parser.Parse(buf, size); if (result <= 0) return result; @@ -30,7 +34,7 @@ int WebMInfoParser::Parse(const uint8* buf, int size) { return parser.IsParsingComplete() ? result : 0; } -bool WebMInfoParser::OnListStart(int id) { return true; } +WebMParserClient* WebMInfoParser::OnListStart(int id) { return this; } bool WebMInfoParser::OnListEnd(int id) { if (id == kWebMIdInfo && timecode_scale_ == -1) { @@ -77,9 +81,4 @@ bool WebMInfoParser::OnString(int id, const std::string& str) { return true; } -bool WebMInfoParser::OnSimpleBlock(int track_num, int timecode, int flags, - const uint8* data, int size) { - return false; -} - } // namespace media diff --git a/media/webm/webm_info_parser.h b/media/webm/webm_info_parser.h index 102a81b..2cc7879 100644 --- a/media/webm/webm_info_parser.h +++ b/media/webm/webm_info_parser.h @@ -28,14 +28,12 @@ class WebMInfoParser : public WebMParserClient { private: // WebMParserClient methods - virtual bool OnListStart(int id) OVERRIDE; + virtual WebMParserClient* OnListStart(int id) OVERRIDE; virtual bool OnListEnd(int id) OVERRIDE; virtual bool OnUInt(int id, int64 val) OVERRIDE; virtual bool OnFloat(int id, double val) OVERRIDE; virtual bool OnBinary(int id, const uint8* data, int size) OVERRIDE; virtual bool OnString(int id, const std::string& str) OVERRIDE; - virtual bool OnSimpleBlock(int track_num, int timecode, int flags, - const uint8* data, int size) OVERRIDE; int64 timecode_scale_; double duration_; diff --git a/media/webm/webm_parser.cc b/media/webm/webm_parser.cc index 1422308..a8348e0 100644 --- a/media/webm/webm_parser.cc +++ b/media/webm/webm_parser.cc @@ -15,13 +15,9 @@ namespace media { -// Maximum depth of WebM elements. Some WebM elements are lists of -// other elements. This limits the number levels of recursion allowed. -static const int kMaxLevelDepth = 6; - enum ElementType { UNKNOWN, - LIST, + LIST, // Referred to as Master Element in the Matroska spec. UINT, FLOAT, BINARY, @@ -39,7 +35,7 @@ struct ListElementInfo { int id_; int level_; const ElementIdInfo* id_info_; - int id_info_size_; + int id_info_count_; }; // The following are tables indicating what IDs are valid sub-elements @@ -115,14 +111,17 @@ static const ElementIdInfo kAudioIds[] = { {SKIP, kWebMIdBitDepth}, }; +#define LIST_ELEMENT_INFO(id, level, id_info) \ + { (id), (level), (id_info), arraysize(id_info) } + 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) }, + LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds), + LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds), + LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds), + LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds), + LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds), + LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds), + LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds), }; // Parses an element header id or size field. These fields are variable length @@ -209,14 +208,13 @@ int WebMParseElementHeader(const uint8* buf, int size, // Finds ElementType for a specific ID. static ElementType FindIdType(int id, const ElementIdInfo* id_info, - int id_info_size) { + int id_info_count) { // Check for global element IDs that can be anywhere. if (id == kWebMIdVoid || id == kWebMIdCRC32) return SKIP; - int count = id_info_size / sizeof(*id_info); - for (int i = 0; i < count; ++i) { + for (int i = 0; i < id_info_count; ++i) { if (id == id_info[i].id_) return id_info[i].type_; } @@ -234,6 +232,14 @@ static const ListElementInfo* FindListInfo(int id) { return NULL; } +static int FindListLevel(int id) { + const ListElementInfo* list_info = FindListInfo(id); + if (list_info) + return list_info->level_; + + return -1; +} + static int ParseSimpleBlock(const uint8* buf, int size, WebMParserClient* client) { if (size < 4) @@ -326,6 +332,17 @@ static int ParseFloat(const uint8* buf, int size, int id, 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) { + std::string str(reinterpret_cast<const char*>(buf), size); + return client->OnString(id, str) ? size : -1; +} + static int ParseNonListElement(ElementType type, int id, int64 element_size, const uint8* buf, int size, WebMParserClient* client) { @@ -347,20 +364,10 @@ static int ParseNonListElement(ElementType type, int id, int64 element_size, result = ParseFloat(buf, element_size, id, client); break; case BINARY: - if (client->OnBinary(id, buf, element_size)) { - result = element_size; - } else { - result = -1; - } + result = ParseBinary(buf, element_size, id, client); break; case STRING: - if (client->OnString(id, - std::string(reinterpret_cast<const char*>(buf), - element_size))) { - result = element_size; - } else { - result = -1; - } + result = ParseString(buf, element_size, id, client); break; case SKIP: result = element_size; @@ -377,14 +384,49 @@ static int ParseNonListElement(ElementType type, int id, int64 element_size, WebMParserClient::WebMParserClient() {} WebMParserClient::~WebMParserClient() {} -WebMListParser::WebMListParser(int id) - : state_(NEED_LIST_HEADER), - root_id_(id) { - const ListElementInfo* list_info = FindListInfo(id); +WebMParserClient* WebMParserClient::OnListStart(int id) { + DVLOG(1) << "Unexpected list element start with ID " << std::hex << id; + return NULL; +} - DCHECK(list_info); +bool WebMParserClient::OnListEnd(int id) { + DVLOG(1) << "Unexpected list element end with ID " << std::hex << id; + return false; +} - root_level_ = list_info->level_; +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; +} + +bool WebMParserClient::OnSimpleBlock(int track_num, int timecode, int flags, + const uint8* data, int size) { + DVLOG(1) << "Unexpected simple block element"; + 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() {} @@ -394,10 +436,8 @@ void WebMListParser::Reset() { list_state_stack_.clear(); } -int WebMListParser::Parse(const uint8* buf, int size, - WebMParserClient* client) { +int WebMListParser::Parse(const uint8* buf, int size) { DCHECK(buf); - DCHECK(client); if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST) return -1; @@ -435,7 +475,7 @@ int WebMListParser::Parse(const uint8* buf, int size, } ChangeState(INSIDE_LIST); - if (!OnListStart(root_id_, element_size, client)) + if (!OnListStart(root_id_, element_size)) return -1; break; @@ -450,7 +490,7 @@ int WebMListParser::Parse(const uint8* buf, int size, element_data_size = element_size; result = ParseListElement(header_size, element_id, element_size, - element_data, element_data_size, client); + element_data, element_data_size); DCHECK_LE(result, header_size + element_data_size); if (result < 0) { @@ -488,8 +528,7 @@ void WebMListParser::ChangeState(State new_state) { int WebMListParser::ParseListElement(int header_size, int id, int64 element_size, - const uint8* data, int size, - WebMParserClient* client) { + const uint8* data, int size) { DCHECK_GT(list_state_stack_.size(), 0u); ListState& list_state = list_state_stack_.back(); @@ -497,7 +536,7 @@ int WebMListParser::ParseListElement(int header_size, const ListElementInfo* element_info = list_state.element_info_; ElementType id_type = - FindIdType(id, element_info->id_info_, element_info->id_info_size_); + FindIdType(id, element_info->id_info_, element_info->id_info_count_); // Unexpected ID. if (id_type == UNKNOWN) { @@ -515,7 +554,7 @@ int WebMListParser::ParseListElement(int header_size, if (id_type == LIST) { list_state.bytes_parsed_ += header_size; - if (!OnListStart(id, element_size, client)) + if (!OnListStart(id, element_size)) return -1; return header_size; } @@ -526,7 +565,7 @@ int WebMListParser::ParseListElement(int header_size, return 0; int bytes_parsed = ParseNonListElement(id_type, id, element_size, - data, size, client); + data, size, list_state.client_); DCHECK_LE(bytes_parsed, size); // Return if an error occurred or we need more data. @@ -541,45 +580,48 @@ int WebMListParser::ParseListElement(int header_size, // See if we have reached the end of the current list. if (list_state.bytes_parsed_ == list_state.size_) { - if (!OnListEnd(client)) + if (!OnListEnd()) 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_) +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 != list_state.element_info_->level_) + 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 = list_state_stack_.back(); - if (current_list.size_ != kWebMUnknownSize && - current_list.size_ < current_list.bytes_parsed_ + size) + 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_; } - if (!client->OnListStart(id)) + WebMParserClient* new_list_client = current_list_client->OnListStart(id); + if (!new_list_client) return false; - list_state_stack_.push_back(list_state); + 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(client); - } + if (size == 0) + return OnListEnd(); return true; } -bool WebMListParser::OnListEnd(WebMParserClient* client) { +bool WebMListParser::OnListEnd() { int lists_ended = 0; for (; !list_state_stack_.empty(); ++lists_ended) { const ListState& list_state = list_state_stack_.back(); @@ -587,16 +629,20 @@ bool WebMListParser::OnListEnd(WebMParserClient* client) { if (list_state.bytes_parsed_ != list_state.size_) break; - if (!client->OnListEnd(list_state.id_)) - return false; - - int64 bytes_parsed = list_state.bytes_parsed_; 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); diff --git a/media/webm/webm_parser.h b/media/webm/webm_parser.h index bc3e09f..4575286 100644 --- a/media/webm/webm_parser.h +++ b/media/webm/webm_parser.h @@ -19,23 +19,26 @@ namespace media { // The ID of the element that was parsed is given along with the value // stored in the element. List elements generate calls at the start and // end of the list. Any pointers passed to these methods are only guaranteed -// to be valid for the life of that call. Each method returns a bool that -// 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. +// to be valid for the life of that call. Each method (except for OnListStart) +// returns a bool that indicates whether the parsed data is valid. OnListStart +// returns a pointer to a WebMParserClient object, which should be used to +// handle elements parsed out of the list being started. If false (or NULL by +// OnListStart) is returned then the parse is immediately terminated and an +// error is reported by the parser. class MEDIA_EXPORT WebMParserClient { public: virtual ~WebMParserClient(); - virtual bool OnListStart(int id) = 0; - virtual bool OnListEnd(int id) = 0; - virtual bool OnUInt(int id, int64 val) = 0; - virtual bool OnFloat(int id, double val) = 0; - virtual bool OnBinary(int id, const uint8* data, int size) = 0; - virtual bool OnString(int id, const std::string& str) = 0; + virtual WebMParserClient* OnListStart(int id); + virtual bool OnListEnd(int id); + virtual bool OnUInt(int id, int64 val); + virtual bool OnFloat(int id, double val); + virtual bool OnBinary(int id, const uint8* data, int size); + virtual bool OnString(int id, const std::string& str); virtual bool OnSimpleBlock(int track_num, int timecode, int flags, - const uint8* data, int size) = 0; + const uint8* data, int size); + protected: WebMParserClient(); @@ -52,19 +55,19 @@ struct ListElementInfo; class MEDIA_EXPORT WebMListParser { public: // |id| - Element ID of the list we intend to parse. - explicit WebMListParser(int id); + // |client| - Called as different elements in the list are parsed. + WebMListParser(int id, WebMParserClient* client); ~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); + int Parse(const uint8* buf, int size); // Returns true if the entire list has been parsed. bool IsParsingComplete() const; @@ -82,6 +85,7 @@ class MEDIA_EXPORT WebMListParser { int size_; int bytes_parsed_; const ListElementInfo* element_info_; + WebMParserClient* client_; }; void ChangeState(State new_state); @@ -100,8 +104,7 @@ class MEDIA_EXPORT WebMListParser { // 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); + const uint8* data, int size); // Called when starting to parse a new list. // @@ -111,25 +114,26 @@ class MEDIA_EXPORT WebMListParser { // // 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); + bool OnListStart(int id, int64 size); // 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); + bool OnListEnd(); State state_; // Element ID passed to the constructor. - int root_id_; + const int root_id_; // Element level for |root_id_|. Used to verify that elements appear at // the correct level. - int root_level_; + const int root_level_; + + // WebMParserClient to handle the root list. + WebMParserClient* const root_client_; // Stack of state for all the lists currently being parsed. Lists are // added and removed from this stack as they are parsed. diff --git a/media/webm/webm_parser_unittest.cc b/media/webm/webm_parser_unittest.cc index 3c8600b..bfb5624 100644 --- a/media/webm/webm_parser_unittest.cc +++ b/media/webm/webm_parser_unittest.cc @@ -10,6 +10,7 @@ using ::testing::InSequence; using ::testing::Return; +using ::testing::ReturnNull; using ::testing::StrictMock; using ::testing::_; @@ -20,7 +21,7 @@ class MockWebMParserClient : public WebMParserClient { virtual ~MockWebMParserClient() {} // WebMParserClient methods. - MOCK_METHOD1(OnListStart, bool(int)); + MOCK_METHOD1(OnListStart, WebMParserClient*(int)); MOCK_METHOD1(OnListEnd, bool(int)); MOCK_METHOD2(OnUInt, bool(int, int64)); MOCK_METHOD2(OnFloat, bool(int, double)); @@ -64,7 +65,7 @@ static void CreateClusterExpectations(int timecode, MockWebMParserClient* client) { InSequence s; - EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); + EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(client)); EXPECT_CALL(*client, OnUInt(kWebMIdTimecode, timecode)) .WillOnce(Return(true)); @@ -86,11 +87,11 @@ TEST_F(WebMParserTest, EmptyCluster) { int size = sizeof(kEmptyCluster); InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); + EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(&client_)); EXPECT_CALL(client_, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); - WebMListParser parser(kWebMIdCluster); - int result = parser.Parse(kEmptyCluster, size, &client_); + WebMListParser parser(kWebMIdCluster, &client_); + int result = parser.Parse(kEmptyCluster, size); EXPECT_EQ(size, result); EXPECT_TRUE(parser.IsParsingComplete()); } @@ -103,13 +104,13 @@ TEST_F(WebMParserTest, EmptyClusterInSegment) { 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_, OnListStart(kWebMIdSegment)).WillOnce(Return(&client_)); + EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(&client_)); 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_); + WebMListParser parser(kWebMIdSegment, &client_); + int result = parser.Parse(kBuffer, size); EXPECT_EQ(size, result); EXPECT_TRUE(parser.IsParsingComplete()); } @@ -124,10 +125,10 @@ TEST_F(WebMParserTest, ChildNonListLargerThanParent) { int size = sizeof(kBuffer); InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); + EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(&client_)); - WebMListParser parser(kWebMIdCluster); - int result = parser.Parse(kBuffer, size, &client_); + WebMListParser parser(kWebMIdCluster, &client_); + int result = parser.Parse(kBuffer, size); EXPECT_EQ(-1, result); EXPECT_FALSE(parser.IsParsingComplete()); } @@ -142,10 +143,10 @@ TEST_F(WebMParserTest, ChildListLargerThanParent) { int size = sizeof(kBuffer); InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); + EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(&client_)); - WebMListParser parser(kWebMIdSegment); - int result = parser.Parse(kBuffer, size, &client_); + WebMListParser parser(kWebMIdSegment, &client_); + int result = parser.Parse(kBuffer, size); EXPECT_EQ(-1, result); EXPECT_FALSE(parser.IsParsingComplete()); } @@ -157,8 +158,8 @@ TEST_F(WebMParserTest, ListIdDoesNotMatch) { }; int size = sizeof(kBuffer); - WebMListParser parser(kWebMIdCluster); - int result = parser.Parse(kBuffer, size, &client_); + WebMListParser parser(kWebMIdCluster, &client_); + int result = parser.Parse(kBuffer, size); EXPECT_EQ(-1, result); EXPECT_FALSE(parser.IsParsingComplete()); } @@ -171,10 +172,10 @@ TEST_F(WebMParserTest, InvalidElementInList) { int size = sizeof(kBuffer); InSequence s; - EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); + EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(&client_)); - WebMListParser parser(kWebMIdSegment); - int result = parser.Parse(kBuffer, size, &client_); + WebMListParser parser(kWebMIdSegment, &client_); + int result = parser.Parse(kBuffer, size); EXPECT_EQ(-1, result); EXPECT_FALSE(parser.IsParsingComplete()); } @@ -191,13 +192,13 @@ TEST_F(WebMParserTest, VoidAndCRC32InList) { 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_, OnListStart(kWebMIdSegment)).WillOnce(Return(&client_)); + EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(&client_)); 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_); + WebMListParser parser(kWebMIdSegment, &client_); + int result = parser.Parse(kBuffer, size); EXPECT_EQ(size, result); EXPECT_TRUE(parser.IsParsingComplete()); } @@ -216,8 +217,8 @@ TEST_F(WebMParserTest, ParseListElementWithSingleCall) { scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); CreateClusterExpectations(0, kBlockInfo, block_count, true, &client_); - WebMListParser parser(kWebMIdCluster); - int result = parser.Parse(cluster->data(), cluster->size(), &client_); + WebMListParser parser(kWebMIdCluster, &client_); + int result = parser.Parse(cluster->data(), cluster->size()); EXPECT_EQ(cluster->size(), result); EXPECT_TRUE(parser.IsParsingComplete()); } @@ -238,11 +239,11 @@ TEST_F(WebMParserTest, ParseListElementWithMultipleCalls) { const uint8* data = cluster->data(); int size = cluster->size(); int default_parse_size = 3; - WebMListParser parser(kWebMIdCluster); + WebMListParser parser(kWebMIdCluster, &client_); int parse_size = std::min(default_parse_size, size); while (size > 0) { - int result = parser.Parse(data, parse_size, &client_); + int result = parser.Parse(data, parse_size); EXPECT_GE(result, 0); EXPECT_LE(result, parse_size); @@ -284,11 +285,11 @@ TEST_F(WebMParserTest, TestReset) { // Now expect all blocks. CreateClusterExpectations(0, kBlockInfo, block_count, true, &client_); - WebMListParser parser(kWebMIdCluster); + WebMListParser parser(kWebMIdCluster, &client_); // Send slightly less than the full cluster so all but the last block is // parsed. - int result = parser.Parse(cluster->data(), cluster->size() - 1, &client_); + int result = parser.Parse(cluster->data(), cluster->size() - 1); EXPECT_GT(result, 0); EXPECT_LT(result, cluster->size()); EXPECT_FALSE(parser.IsParsingComplete()); @@ -296,9 +297,59 @@ TEST_F(WebMParserTest, TestReset) { parser.Reset(); // Now parse a whole cluster to verify that all the blocks will get parsed. - result = parser.Parse(cluster->data(), cluster->size(), &client_); + result = parser.Parse(cluster->data(), cluster->size()); EXPECT_EQ(result, cluster->size()); EXPECT_TRUE(parser.IsParsingComplete()); } +// Test the case where multiple clients are used for different lists. +TEST_F(WebMParserTest, MultipleClients) { + const uint8 kBuffer[] = { + 0x18, 0x53, 0x80, 0x67, 0x94, // SEGMENT (size = 20) + 0x16, 0x54, 0xAE, 0x6B, 0x85, // TRACKS (size = 5) + 0xAE, 0x83, // TRACKENTRY (size = 3) + 0xD7, 0x81, 0x01, // TRACKNUMBER (size = 1) + 0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5) + 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3) + }; + int size = sizeof(kBuffer); + + StrictMock<MockWebMParserClient> c1_; + StrictMock<MockWebMParserClient> c2_; + StrictMock<MockWebMParserClient> c3_; + + InSequence s; + EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(&c1_)); + EXPECT_CALL(c1_, OnListStart(kWebMIdTracks)).WillOnce(Return(&c2_)); + EXPECT_CALL(c2_, OnListStart(kWebMIdTrackEntry)).WillOnce(Return(&c3_)); + EXPECT_CALL(c3_, OnUInt(kWebMIdTrackNumber, 1)).WillOnce(Return(true)); + EXPECT_CALL(c2_, OnListEnd(kWebMIdTrackEntry)).WillOnce(Return(true)); + EXPECT_CALL(c1_, OnListEnd(kWebMIdTracks)).WillOnce(Return(true)); + EXPECT_CALL(c1_, OnListStart(kWebMIdCluster)).WillOnce(Return(&c2_)); + EXPECT_CALL(c1_, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); + EXPECT_CALL(client_, OnListEnd(kWebMIdSegment)).WillOnce(Return(true)); + + WebMListParser parser(kWebMIdSegment, &client_); + int result = parser.Parse(kBuffer, size); + EXPECT_EQ(size, result); + EXPECT_TRUE(parser.IsParsingComplete()); +} + +// Test the case where multiple clients are used for different lists. +TEST_F(WebMParserTest, InvalidClient) { + const uint8 kBuffer[] = { + 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 20) + 0x16, 0x54, 0xAE, 0x6B, 0x80, // TRACKS (size = 5) + }; + int size = sizeof(kBuffer); + + InSequence s; + EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(ReturnNull()); + + WebMListParser parser(kWebMIdSegment, &client_); + int result = parser.Parse(kBuffer, size); + EXPECT_EQ(-1, result); + EXPECT_FALSE(parser.IsParsingComplete()); +} + } // namespace media diff --git a/media/webm/webm_tracks_parser.cc b/media/webm/webm_tracks_parser.cc index dfeb811..18f7647 100644 --- a/media/webm/webm_tracks_parser.cc +++ b/media/webm/webm_tracks_parser.cc @@ -9,6 +9,10 @@ namespace media { +// Values for TrackType element. +static const int kWebMTrackTypeVideo = 1; +static const int kWebMTrackTypeAudio = 2; + WebMTracksParser::WebMTracksParser(int64 timecode_scale) : timecode_scale_(timecode_scale), track_type_(-1), @@ -29,8 +33,8 @@ int WebMTracksParser::Parse(const uint8* buf, int size) { video_track_num_ = -1; video_default_duration_ = base::TimeDelta(); - WebMListParser parser(kWebMIdTracks); - int result = parser.Parse(buf, size, this); + WebMListParser parser(kWebMIdTracks, this); + int result = parser.Parse(buf, size); if (result <= 0) return result; @@ -40,14 +44,14 @@ int WebMTracksParser::Parse(const uint8* buf, int size) { } -bool WebMTracksParser::OnListStart(int id) { +WebMParserClient* WebMTracksParser::OnListStart(int id) { if (id == kWebMIdTrackEntry) { track_type_ = -1; track_num_ = -1; track_default_duration_ = -1; } - return true; + return this; } bool WebMTracksParser::OnListEnd(int id) { @@ -95,7 +99,7 @@ bool WebMTracksParser::OnUInt(int id, int64 val) { case kWebMIdTrackType: dst = &track_type_; break; - case kWebMIdDefaultDuration: + case kWebMIdDefaultDuration: dst = &track_default_duration_; break; default: @@ -111,11 +115,6 @@ bool WebMTracksParser::OnUInt(int id, int64 val) { return true; } -bool WebMTracksParser::OnFloat(int id, double val) { - DVLOG(1) << "Unexpected float for id" << std::hex << id; - return false; -} - bool WebMTracksParser::OnBinary(int id, const uint8* data, int size) { return true; } @@ -132,9 +131,4 @@ bool WebMTracksParser::OnString(int id, const std::string& str) { return true; } -bool WebMTracksParser::OnSimpleBlock(int track_num, int timecode, int flags, - const uint8* data, int size) { - return false; -} - } // namespace media diff --git a/media/webm/webm_tracks_parser.h b/media/webm/webm_tracks_parser.h index c4eff0d..fe46c25 100644 --- a/media/webm/webm_tracks_parser.h +++ b/media/webm/webm_tracks_parser.h @@ -36,14 +36,12 @@ class WebMTracksParser : public WebMParserClient { private: // WebMParserClient methods - virtual bool OnListStart(int id) OVERRIDE; + virtual WebMParserClient* OnListStart(int id) OVERRIDE; virtual bool OnListEnd(int id) OVERRIDE; virtual bool OnUInt(int id, int64 val) OVERRIDE; - virtual bool OnFloat(int id, double val) OVERRIDE; virtual bool OnBinary(int id, const uint8* data, int size) OVERRIDE; virtual bool OnString(int id, const std::string& str) OVERRIDE; - virtual bool OnSimpleBlock(int track_num, int timecode, int flags, - const uint8* data, int size) OVERRIDE; + int64 timecode_scale_; int64 track_type_; |