diff options
author | matthewjheaney@chromium.org <matthewjheaney@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-08 02:20:25 +0000 |
---|---|---|
committer | matthewjheaney@chromium.org <matthewjheaney@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-08 02:20:25 +0000 |
commit | 4d5a0faa1170057dbbb6caabca181cd648adea24 (patch) | |
tree | 86c723d9321fee8fb92910d6fa6b4c7ad550cd79 /media/webm | |
parent | 8c711adfd9e9d958c078488526d901963478d1aa (diff) | |
download | chromium_src-4d5a0faa1170057dbbb6caabca181cd648adea24.zip chromium_src-4d5a0faa1170057dbbb6caabca181cd648adea24.tar.gz chromium_src-4d5a0faa1170057dbbb6caabca181cd648adea24.tar.bz2 |
media source should ignore subtitles in webm files
BUG=167152
Review URL: https://chromiumcodereview.appspot.com/11635058
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@181410 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/webm')
-rw-r--r-- | media/webm/webm_cluster_parser.cc | 69 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser.h | 34 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser_unittest.cc | 165 | ||||
-rw-r--r-- | media/webm/webm_parser.h | 9 | ||||
-rw-r--r-- | media/webm/webm_stream_parser.cc | 5 | ||||
-rw-r--r-- | media/webm/webm_tracks_parser.cc | 75 | ||||
-rw-r--r-- | media/webm/webm_tracks_parser.h | 6 |
7 files changed, 350 insertions, 13 deletions
diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc index 785a89d..8a984c8 100644 --- a/media/webm/webm_cluster_parser.cc +++ b/media/webm/webm_cluster_parser.cc @@ -23,8 +23,41 @@ static std::string GenerateCounterBlock(const uint8* iv, int iv_size) { return counter_block; } +WebMClusterParser::TextTrackIterator::TextTrackIterator( + const TextTrackMap& text_track_map) : + iterator_(text_track_map.begin()), + iterator_end_(text_track_map.end()) { +} + +WebMClusterParser::TextTrackIterator::TextTrackIterator( + const TextTrackIterator& rhs) : + iterator_(rhs.iterator_), + iterator_end_(rhs.iterator_end_) { +} + +WebMClusterParser::TextTrackIterator::~TextTrackIterator() { +} + +bool WebMClusterParser::TextTrackIterator::operator()( + int* track_num, + const BufferQueue** buffers) { + if (iterator_ == iterator_end_) { + *track_num = 0; + *buffers = NULL; + + return false; + } + + *track_num = iterator_->first; + *buffers = &iterator_->second.buffers(); + + ++iterator_; + return true; +} + WebMClusterParser::WebMClusterParser( int64 timecode_scale, int audio_track_num, int video_track_num, + const std::set<int>& text_tracks, const std::set<int64>& ignored_tracks, const std::string& audio_encryption_key_id, const std::string& video_encryption_key_id, @@ -43,6 +76,11 @@ WebMClusterParser::WebMClusterParser( audio_(audio_track_num, false), video_(video_track_num, true), log_cb_(log_cb) { + for (std::set<int>::const_iterator it = text_tracks.begin(); + it != text_tracks.end(); + ++it) { + text_track_map_.insert(std::make_pair(*it, Track(*it, false))); + } } WebMClusterParser::~WebMClusterParser() {} @@ -55,11 +93,13 @@ void WebMClusterParser::Reset() { parser_.Reset(); audio_.Reset(); video_.Reset(); + ResetTextTracks(); } int WebMClusterParser::Parse(const uint8* buf, int size) { audio_.Reset(); video_.Reset(); + ResetTextTracks(); int result = parser_.Parse(buf, size); @@ -90,6 +130,11 @@ int WebMClusterParser::Parse(const uint8* buf, int size) { return result; } +WebMClusterParser::TextTrackIterator +WebMClusterParser::CreateTextTrackIterator() const { + return TextTrackIterator(text_track_map_); +} + WebMParserClient* WebMClusterParser::OnListStart(int id) { if (id == kWebMIdCluster) { cluster_timecode_ = -1; @@ -219,6 +264,12 @@ bool WebMClusterParser::OnBlock(bool is_simple_block, int track_num, encryption_key_id = video_encryption_key_id_; } else if (ignored_tracks_.find(track_num) != ignored_tracks_.end()) { return true; + } else if (Track* const text_track = FindTextTrack(track_num)) { + if (is_simple_block) // BlockGroup is required for WebVTT cues + return false; + if (block_duration < 0) // not specified + return false; + track = text_track; } else { MEDIA_LOG(log_cb_) << "Unexpected track number " << track_num; return false; @@ -336,4 +387,22 @@ bool WebMClusterParser::Track::IsKeyframe(const uint8* data, int size) const { return true; } +void WebMClusterParser::ResetTextTracks() { + for (TextTrackMap::iterator it = text_track_map_.begin(); + it != text_track_map_.end(); + ++it) { + it->second.Reset(); + } +} + +WebMClusterParser::Track* +WebMClusterParser::FindTextTrack(int track_num) { + const TextTrackMap::iterator it = text_track_map_.find(track_num); + + if (it == text_track_map_.end()) + return NULL; + + return &it->second; +} + } // namespace media diff --git a/media/webm/webm_cluster_parser.h b/media/webm/webm_cluster_parser.h index 29e4490..a1a5175 100644 --- a/media/webm/webm_cluster_parser.h +++ b/media/webm/webm_cluster_parser.h @@ -6,6 +6,7 @@ #define MEDIA_WEBM_WEBM_CLUSTER_PARSER_H_ #include <deque> +#include <map> #include <set> #include <string> @@ -18,12 +19,33 @@ namespace media { class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { + class Track; + typedef std::map<int, Track> TextTrackMap; public: typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; + class MEDIA_EXPORT TextTrackIterator { + public: + explicit TextTrackIterator(const TextTrackMap& text_track_map); + TextTrackIterator(const TextTrackIterator& rhs); + ~TextTrackIterator(); + + // To visit each text track. If the iterator is exhausted, it returns + // as parameters the values 0 and NULL, and the function returns false. + // Otherwise, it returns the buffers for the associated track, and the + // function returns true. + bool operator()(int* track_num, const BufferQueue** buffers); + private: + TextTrackIterator& operator=(const TextTrackIterator&); + + TextTrackMap::const_iterator iterator_; + const TextTrackMap::const_iterator iterator_end_; + }; + WebMClusterParser(int64 timecode_scale, int audio_track_num, int video_track_num, + const std::set<int>& text_tracks, const std::set<int64>& ignored_tracks, const std::string& audio_encryption_key_id, const std::string& video_encryption_key_id, @@ -44,6 +66,9 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { const BufferQueue& audio_buffers() const { return audio_.buffers(); } const BufferQueue& video_buffers() const { return video_.buffers(); } + // Returns an iterator object, allowing each text track to be visited. + TextTrackIterator CreateTextTrackIterator() const; + // Returns true if the last Parse() call stopped at the end of a cluster. bool cluster_ended() const { return cluster_ended_; } @@ -85,6 +110,13 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { bool OnBlock(bool is_simple_block, int track_num, int timecode, int duration, int flags, const uint8* data, int size); + // Resets the Track objects associated with each text track. + void ResetTextTracks(); + + // Search for the indicated track_num among the text tracks. Returns NULL + // if that track num is not a text track. + Track* FindTextTrack(int track_num); + double timecode_multiplier_; // Multiplier used to convert timecodes into // microseconds. std::set<int64> ignored_tracks_; @@ -104,7 +136,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { Track audio_; Track video_; - + TextTrackMap text_track_map_; LogCB log_cb_; DISALLOW_IMPLICIT_CONSTRUCTORS(WebMClusterParser); diff --git a/media/webm/webm_cluster_parser_unittest.cc b/media/webm/webm_cluster_parser_unittest.cc index 034c072..07deb05 100644 --- a/media/webm/webm_cluster_parser_unittest.cc +++ b/media/webm/webm_cluster_parser_unittest.cc @@ -69,10 +69,12 @@ static scoped_ptr<Cluster> CreateCluster(int timecode, static bool VerifyBuffers(const WebMClusterParser::BufferQueue& audio_buffers, const WebMClusterParser::BufferQueue& video_buffers, + const WebMClusterParser::BufferQueue& text_buffers, const BlockInfo* block_info, int block_count) { size_t audio_offset = 0; size_t video_offset = 0; + size_t text_offset = 0; for (int i = 0; i < block_count; i++) { const WebMClusterParser::BufferQueue* buffers = NULL; size_t* offset; @@ -83,6 +85,9 @@ static bool VerifyBuffers(const WebMClusterParser::BufferQueue& audio_buffers, } else if (block_info[i].track_num == kVideoTrackNum) { buffers = &video_buffers; offset = &video_offset; + } else if (block_info[i].track_num == kTextTrackNum) { + buffers = &text_buffers; + offset = &text_offset; } else { LOG(ERROR) << "Unexpected track number " << block_info[i].track_num; return false; @@ -109,12 +114,57 @@ static bool VerifyBuffers(const WebMClusterParser::BufferQueue& audio_buffers, static bool VerifyBuffers(const scoped_ptr<WebMClusterParser>& parser, const BlockInfo* block_info, int block_count) { + typedef WebMClusterParser::TextTrackIterator TextTrackIterator; + TextTrackIterator text_it = parser->CreateTextTrackIterator(); + + int text_track_num; + const WebMClusterParser::BufferQueue* text_buffers; + + while (text_it(&text_track_num, &text_buffers)) + break; + + const WebMClusterParser::BufferQueue no_text_buffers; + + if (text_buffers == NULL) + text_buffers = &no_text_buffers; + return VerifyBuffers(parser->audio_buffers(), parser->video_buffers(), + *text_buffers, block_info, block_count); } +static bool VerifyTextBuffers( + const scoped_ptr<WebMClusterParser>& parser, + const BlockInfo* block_info_ptr, + int block_count, + int text_track_num, + const WebMClusterParser::BufferQueue& text_buffers) { + const BlockInfo* const block_info_end = block_info_ptr + block_count; + + typedef WebMClusterParser::BufferQueue::const_iterator TextBufferIter; + TextBufferIter buffer_iter = text_buffers.begin(); + const TextBufferIter buffer_end = text_buffers.end(); + + while (block_info_ptr != block_info_end) { + const BlockInfo& block_info = *block_info_ptr++; + + if (block_info.track_num != text_track_num) + continue; + + EXPECT_FALSE(block_info.use_simple_block); + EXPECT_FALSE(buffer_iter == buffer_end); + + const scoped_refptr<StreamParserBuffer> buffer = *buffer_iter++; + EXPECT_EQ(buffer->GetTimestamp().InMilliseconds(), block_info.timestamp); + EXPECT_EQ(buffer->GetDuration().InMilliseconds(), block_info.duration); + } + + EXPECT_TRUE(buffer_iter == buffer_end); + return true; +} + static void AppendToEnd(const WebMClusterParser::BufferQueue& src, WebMClusterParser::BufferQueue* dest) { for (WebMClusterParser::BufferQueue::const_iterator itr = src.begin(); @@ -127,8 +177,11 @@ class WebMClusterParserTest : public testing::Test { public: WebMClusterParserTest() : parser_(new WebMClusterParser( - kTimecodeScale, kAudioTrackNum, kVideoTrackNum, std::set<int64>(), - "", "", LogCB())) { + kTimecodeScale, kAudioTrackNum, kVideoTrackNum, + std::set<int>(), + std::set<int64>(), + "", "", + LogCB())) { } protected: @@ -171,6 +224,7 @@ TEST_F(WebMClusterParserTest, ParseClusterWithMultipleCalls) { WebMClusterParser::BufferQueue audio_buffers; WebMClusterParser::BufferQueue video_buffers; + const WebMClusterParser::BufferQueue no_text_buffers; const uint8* data = cluster->data(); int size = cluster->size(); @@ -197,7 +251,8 @@ TEST_F(WebMClusterParserTest, ParseClusterWithMultipleCalls) { data += result; size -= result; } - ASSERT_TRUE(VerifyBuffers(audio_buffers, video_buffers, kDefaultBlockInfo, + ASSERT_TRUE(VerifyBuffers(audio_buffers, video_buffers, + no_text_buffers, kDefaultBlockInfo, block_count)); } @@ -253,7 +308,9 @@ TEST_F(WebMClusterParserTest, IgnoredTracks) { ignored_tracks.insert(kTextTrackNum); parser_.reset(new WebMClusterParser( - kTimecodeScale, kAudioTrackNum, kVideoTrackNum, ignored_tracks, "", "", + kTimecodeScale, kAudioTrackNum, kVideoTrackNum, + std::set<int>(), + ignored_tracks, "", "", LogCB())); const BlockInfo kInputBlockInfo[] = { @@ -283,4 +340,104 @@ TEST_F(WebMClusterParserTest, IgnoredTracks) { ASSERT_TRUE(VerifyBuffers(parser_, kOutputBlockInfo, output_block_count)); } +TEST_F(WebMClusterParserTest, ParseTextTracks) { + std::set<int> text_tracks; + text_tracks.insert(kTextTrackNum); + + parser_.reset(new WebMClusterParser( + kTimecodeScale, kAudioTrackNum, kVideoTrackNum, + text_tracks, + std::set<int64>(), "", "", + LogCB())); + + const BlockInfo kInputBlockInfo[] = { + { kAudioTrackNum, 0, 23, true }, + { kAudioTrackNum, 23, 23, true }, + { kVideoTrackNum, 33, 33, true }, + { kTextTrackNum, 33, 42, false }, + { kAudioTrackNum, 46, 23, true }, + { kTextTrackNum, 55, 44, false }, + { kVideoTrackNum, 67, 33, true }, + }; + int input_block_count = arraysize(kInputBlockInfo); + + scoped_ptr<Cluster> cluster( + CreateCluster(0, kInputBlockInfo, input_block_count)); + + int result = parser_->Parse(cluster->data(), cluster->size()); + EXPECT_EQ(cluster->size(), result); + ASSERT_TRUE(VerifyBuffers(parser_, kInputBlockInfo, input_block_count)); +} + +TEST_F(WebMClusterParserTest, TextTracksSimpleBlock) { + std::set<int> text_tracks; + text_tracks.insert(kTextTrackNum); + + parser_.reset(new WebMClusterParser( + kTimecodeScale, kAudioTrackNum, kVideoTrackNum, + text_tracks, + std::set<int64>(), "", "", + LogCB())); + + const BlockInfo kInputBlockInfo[] = { + { kTextTrackNum, 33, 42, true }, + }; + int input_block_count = arraysize(kInputBlockInfo); + + scoped_ptr<Cluster> cluster( + CreateCluster(0, kInputBlockInfo, input_block_count)); + + int result = parser_->Parse(cluster->data(), cluster->size()); + EXPECT_LT(result, 0); +} + +TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) { + typedef std::set<int> TextTrackSet; + TextTrackSet text_tracks; + + const int kSubtitleTextTrackNum = kTextTrackNum; + const int kCaptionTextTrackNum = kTextTrackNum + 1; + + text_tracks.insert(kSubtitleTextTrackNum); + text_tracks.insert(kCaptionTextTrackNum); + + parser_.reset(new WebMClusterParser( + kTimecodeScale, kAudioTrackNum, kVideoTrackNum, + text_tracks, + std::set<int64>(), "", "", + LogCB())); + + const BlockInfo kInputBlockInfo[] = { + { kAudioTrackNum, 0, 23, true }, + { kAudioTrackNum, 23, 23, true }, + { kVideoTrackNum, 33, 33, true }, + { kSubtitleTextTrackNum, 33, 42, false }, + { kAudioTrackNum, 46, 23, true }, + { kCaptionTextTrackNum, 55, 44, false }, + { kVideoTrackNum, 67, 33, true }, + { kSubtitleTextTrackNum, 67, 33, false }, + }; + int input_block_count = arraysize(kInputBlockInfo); + + scoped_ptr<Cluster> cluster( + CreateCluster(0, kInputBlockInfo, input_block_count)); + + int result = parser_->Parse(cluster->data(), cluster->size()); + EXPECT_EQ(cluster->size(), result); + + WebMClusterParser::TextTrackIterator text_it = + parser_->CreateTextTrackIterator(); + + int text_track_num; + const WebMClusterParser::BufferQueue* text_buffers; + + while (text_it(&text_track_num, &text_buffers)) { + const TextTrackSet::const_iterator find_result = + text_tracks.find(text_track_num); + ASSERT_TRUE(find_result != text_tracks.end()); + ASSERT_TRUE(VerifyTextBuffers(parser_, kInputBlockInfo, input_block_count, + text_track_num, *text_buffers)); + } +} + } // namespace media diff --git a/media/webm/webm_parser.h b/media/webm/webm_parser.h index 68611a8..1fa71e7 100644 --- a/media/webm/webm_parser.h +++ b/media/webm/webm_parser.h @@ -153,6 +153,15 @@ class MEDIA_EXPORT WebMListParser { int MEDIA_EXPORT WebMParseElementHeader(const uint8* buf, int size, int* id, int64* element_size); +// Specifies the varieties of text tracks. +enum TextKind { + kTextNone, + kTextSubtitles, + kTextCaptions, + kTextDescriptions, + kTextMetadata +}; + } // namespace media #endif // MEDIA_WEBM_WEBM_PARSER_H_ diff --git a/media/webm/webm_stream_parser.cc b/media/webm/webm_stream_parser.cc index 02c1357..db854a9 100644 --- a/media/webm/webm_stream_parser.cc +++ b/media/webm/webm_stream_parser.cc @@ -294,6 +294,7 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) { case kWebMIdVoid: case kWebMIdCRC32: case kWebMIdCues: + case kWebMIdChapters: if (cur_size < (result + element_size)) { // We don't have the whole element yet. Signal we need more data. return 0; @@ -395,6 +396,7 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) { info_parser.timecode_scale(), tracks_parser.audio_track_num(), tracks_parser.video_track_num(), + tracks_parser.text_tracks(), tracks_parser.ignored_tracks(), tracks_parser.audio_encryption_key_id(), tracks_parser.video_encryption_key_id(), @@ -424,7 +426,8 @@ int WebMStreamParser::ParseCluster(const uint8* data, int size) { if (id == kWebMIdCluster) waiting_for_buffers_ = true; - if (id == kWebMIdCues) { + // TODO(matthewjheaney): implement support for chapters + if (id == kWebMIdCues || id == kWebMIdChapters) { if (size < (result + element_size)) { // We don't have the whole element yet. Signal we need more data. return 0; diff --git a/media/webm/webm_tracks_parser.cc b/media/webm/webm_tracks_parser.cc index 508530b..2dbac41 100644 --- a/media/webm/webm_tracks_parser.cc +++ b/media/webm/webm_tracks_parser.cc @@ -15,11 +15,13 @@ namespace media { // Values for TrackType element. static const int kWebMTrackTypeVideo = 1; static const int kWebMTrackTypeAudio = 2; -static const int kWebMTrackTypeSubtitle = 0x11; +static const int kWebMTrackTypeSubtitlesOrCaptions = 0x11; +static const int kWebMTrackTypeDescriptionsOrMetadata = 0x21; WebMTracksParser::WebMTracksParser(const LogCB& log_cb) : track_type_(-1), track_num_(-1), + text_track_kind_(kTextNone), audio_track_num_(-1), video_track_num_(-1), log_cb_(log_cb) { @@ -30,8 +32,11 @@ WebMTracksParser::~WebMTracksParser() {} int WebMTracksParser::Parse(const uint8* buf, int size) { track_type_ =-1; track_num_ = -1; + text_track_kind_ = kTextNone; audio_track_num_ = -1; video_track_num_ = -1; + text_tracks_.clear(); + ignored_tracks_.clear(); WebMListParser parser(kWebMIdTracks, this); int result = parser.Parse(buf, size); @@ -54,6 +59,7 @@ WebMParserClient* WebMTracksParser::OnListStart(int id) { if (id == kWebMIdTrackEntry) { track_type_ = -1; track_num_ = -1; + text_track_kind_ = kTextNone; return this; } @@ -76,11 +82,40 @@ bool WebMTracksParser::OnListEnd(int id) { if (track_type_ != kWebMTrackTypeAudio && track_type_ != kWebMTrackTypeVideo && - track_type_ != kWebMTrackTypeSubtitle) { + track_type_ != kWebMTrackTypeSubtitlesOrCaptions && + track_type_ != kWebMTrackTypeDescriptionsOrMetadata) { MEDIA_LOG(log_cb_) << "Unexpected TrackType " << track_type_; return false; } + if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) { + if (text_track_kind_ == kTextNone) { + MEDIA_LOG(log_cb_) << "Missing TrackEntry CodecID" + << " TrackNum " << track_num_; + return false; + } + + if (text_track_kind_ != kTextSubtitles && + text_track_kind_ != kTextCaptions) { + MEDIA_LOG(log_cb_) << "Wrong TrackEntry CodecID" + << " TrackNum " << track_num_; + return false; + } + } else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) { + if (text_track_kind_ == kTextNone) { + MEDIA_LOG(log_cb_) << "Missing TrackEntry CodecID" + << " TrackNum " << track_num_; + return false; + } + + if (text_track_kind_ != kTextDescriptions && + text_track_kind_ != kTextMetadata) { + MEDIA_LOG(log_cb_) << "Wrong TrackEntry CodecID" + << " TrackNum " << track_num_; + return false; + } + } + std::string encryption_key_id; if (track_content_encodings_client_.get()) { DCHECK(!track_content_encodings_client_->content_encodings().empty()); @@ -106,9 +141,9 @@ bool WebMTracksParser::OnListEnd(int id) { MEDIA_LOG(log_cb_) << "Ignoring video track " << track_num_; ignored_tracks_.insert(track_num_); } - } else if (track_type_ == kWebMTrackTypeSubtitle) { - MEDIA_LOG(log_cb_) << "Ignoring subtitle track " << track_num_; - ignored_tracks_.insert(track_num_); + } else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions || + track_type_ == kWebMTrackTypeDescriptionsOrMetadata) { + text_tracks_.insert(track_num_); } else { MEDIA_LOG(log_cb_) << "Unexpected TrackType " << track_type_; return false; @@ -117,6 +152,7 @@ bool WebMTracksParser::OnListEnd(int id) { track_type_ = -1; track_num_ = -1; track_content_encodings_client_.reset(); + text_track_kind_ = kTextNone; return true; } @@ -156,8 +192,33 @@ bool WebMTracksParser::OnBinary(int id, const uint8* data, int size) { } bool WebMTracksParser::OnString(int id, const std::string& str) { - if (id == kWebMIdCodecID && str != "A_VORBIS" && str != "V_VP8" && - str.find("D_WEBVTT/") != 0) { + if (id == kWebMIdCodecID) { + if (str == "V_VP8") + return true; + + if (str == "A_VORBIS") + return true; + + if (str == "D_WEBVTT/SUBTITLES") { + text_track_kind_ = kTextSubtitles; + return true; + } + + if (str == "D_WEBVTT/CAPTIONS") { + text_track_kind_ = kTextCaptions; + return true; + } + + if (str == "D_WEBVTT/DESCRIPTIONS") { + text_track_kind_ = kTextDescriptions; + return true; + } + + if (str == "D_WEBVTT/METADATA") { + text_track_kind_ = kTextMetadata; + return true; + } + MEDIA_LOG(log_cb_) << "Unexpected CodecID " << str; return false; } diff --git a/media/webm/webm_tracks_parser.h b/media/webm/webm_tracks_parser.h index 8af3678..5593349 100644 --- a/media/webm/webm_tracks_parser.h +++ b/media/webm/webm_tracks_parser.h @@ -40,6 +40,10 @@ class WebMTracksParser : public WebMParserClient { return video_encryption_key_id_; } + const std::set<int>& text_tracks() const { + return text_tracks_; + } + private: // WebMParserClient methods virtual WebMParserClient* OnListStart(int id) OVERRIDE; @@ -52,9 +56,11 @@ class WebMTracksParser : public WebMParserClient { int64 track_type_; int64 track_num_; scoped_ptr<WebMContentEncodingsClient> track_content_encodings_client_; + TextKind text_track_kind_; int64 audio_track_num_; int64 video_track_num_; + std::set<int> text_tracks_; std::set<int64> ignored_tracks_; std::string audio_encryption_key_id_; std::string video_encryption_key_id_; |