summaryrefslogtreecommitdiffstats
path: root/media/webm
diff options
context:
space:
mode:
authorxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-29 22:36:56 +0000
committerxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-29 22:36:56 +0000
commitcc289a6c2cc29b1d6d6eb66f49a303846ecbb7d4 (patch)
treef16f4a18dcb5742326d203eee700307de4f33591 /media/webm
parentd313bf6cd10b4b0e9b089834b254785edb32fe51 (diff)
downloadchromium_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.cc23
-rw-r--r--media/webm/webm_cluster_parser.h5
-rw-r--r--media/webm/webm_constants.h8
-rw-r--r--media/webm/webm_info_parser.cc15
-rw-r--r--media/webm/webm_info_parser.h4
-rw-r--r--media/webm/webm_parser.cc174
-rw-r--r--media/webm/webm_parser.h48
-rw-r--r--media/webm/webm_parser_unittest.cc113
-rw-r--r--media/webm/webm_tracks_parser.cc24
-rw-r--r--media/webm/webm_tracks_parser.h6
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_;