summaryrefslogtreecommitdiffstats
path: root/media/webm
diff options
context:
space:
mode:
authormatthewjheaney@chromium.org <matthewjheaney@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-16 17:35:03 +0000
committermatthewjheaney@chromium.org <matthewjheaney@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-16 17:35:03 +0000
commitb8a7ef6c5418644dade8c34dea5e74f8b379a7fb (patch)
treeb626b0b263579529e264141a47deba8f494bbaf0 /media/webm
parent9dae1e66de46883333455bc5943e929f3e3cc80b (diff)
downloadchromium_src-b8a7ef6c5418644dade8c34dea5e74f8b379a7fb.zip
chromium_src-b8a7ef6c5418644dade8c34dea5e74f8b379a7fb.tar.gz
chromium_src-b8a7ef6c5418644dade8c34dea5e74f8b379a7fb.tar.bz2
Parse WebM track name and language
The Track header of a WebM file contains (among other items) a track name and track language. We do not currently use this information. However, it is needed to construct WebVTT inband text tracks. The WebM tracks parser has been modified to provide this information to its clients. (An earlier version of this commit failed to compile on some systems. The problem was that some integer constants needed to be qualified with a suffix to specify an extra precision integer type.) BUG=230708 Review URL: https://chromiumcodereview.appspot.com/15205002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200562 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/webm')
-rw-r--r--media/webm/tracks_builder.cc211
-rw-r--r--media/webm/tracks_builder.h56
-rw-r--r--media/webm/webm_cluster_parser.cc6
-rw-r--r--media/webm/webm_cluster_parser.h3
-rw-r--r--media/webm/webm_cluster_parser_unittest.cc42
-rw-r--r--media/webm/webm_constants.cc14
-rw-r--r--media/webm/webm_constants.h14
-rw-r--r--media/webm/webm_tracks_parser.cc40
-rw-r--r--media/webm/webm_tracks_parser.h17
-rw-r--r--media/webm/webm_tracks_parser_unittest.cc93
10 files changed, 463 insertions, 33 deletions
diff --git a/media/webm/tracks_builder.cc b/media/webm/tracks_builder.cc
new file mode 100644
index 0000000..370ca82
--- /dev/null
+++ b/media/webm/tracks_builder.cc
@@ -0,0 +1,211 @@
+// Copyright (c) 2013 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/tracks_builder.h"
+
+#include "media/webm/webm_constants.h"
+
+namespace media {
+
+// Returns size of an integer, formatted using Matroska serialization.
+static int GetUIntMkvSize(uint64 value) {
+ if (value < 0x07FULL)
+ return 1;
+ if (value < 0x03FFFULL)
+ return 2;
+ if (value < 0x01FFFFFULL)
+ return 3;
+ if (value < 0x0FFFFFFFULL)
+ return 4;
+ if (value < 0x07FFFFFFFFULL)
+ return 5;
+ if (value < 0x03FFFFFFFFFFULL)
+ return 6;
+ if (value < 0x01FFFFFFFFFFFFULL)
+ return 7;
+ return 8;
+}
+
+// Returns the minimium size required to serialize an integer value.
+static int GetUIntSize(uint64 value) {
+ if (value < 0x0100ULL)
+ return 1;
+ if (value < 0x010000ULL)
+ return 2;
+ if (value < 0x01000000ULL)
+ return 3;
+ if (value < 0x0100000000ULL)
+ return 4;
+ if (value < 0x010000000000ULL)
+ return 5;
+ if (value < 0x01000000000000ULL)
+ return 6;
+ if (value < 0x0100000000000000ULL)
+ return 7;
+ return 8;
+}
+
+static int MasterElementSize(int element_id, int payload_size) {
+ return GetUIntSize(element_id) + GetUIntMkvSize(payload_size) + payload_size;
+}
+
+static int IntElementSize(int element_id, int value) {
+ return GetUIntSize(element_id) + 1 + GetUIntSize(value);
+}
+
+static int StringElementSize(int element_id, const std::string& value) {
+ return GetUIntSize(element_id) +
+ GetUIntMkvSize(value.length()) +
+ value.length();
+}
+
+static void SerializeInt(uint8** buf_ptr, int* buf_size_ptr,
+ int64 value, int size) {
+ uint8*& buf = *buf_ptr;
+ int& buf_size = *buf_size_ptr;
+
+ for (int idx = 1; idx <= size; ++idx) {
+ *buf++ = static_cast<uint8>(value >> ((size - idx) * 8));
+ --buf_size;
+ }
+}
+
+static void WriteElementId(uint8** buf, int* buf_size, int element_id) {
+ SerializeInt(buf, buf_size, element_id, GetUIntSize(element_id));
+}
+
+static void WriteUInt(uint8** buf, int* buf_size, uint64 value) {
+ const int size = GetUIntMkvSize(value);
+ value |= (1ULL << (size * 7)); // Matroska formatting
+ SerializeInt(buf, buf_size, value, size);
+}
+
+static void WriteMasterElement(uint8** buf, int* buf_size,
+ int element_id, int payload_size) {
+ WriteElementId(buf, buf_size, element_id);
+ WriteUInt(buf, buf_size, payload_size);
+}
+
+static void WriteIntElement(uint8** buf, int* buf_size,
+ int element_id, int value) {
+ WriteElementId(buf, buf_size, element_id);
+
+ const int size = GetUIntSize(value);
+ WriteUInt(buf, buf_size, size);
+
+ SerializeInt(buf, buf_size, value, size);
+}
+
+static void WriteStringElement(uint8** buf_ptr, int* buf_size_ptr,
+ int element_id, const std::string& value) {
+ uint8*& buf = *buf_ptr;
+ int& buf_size = *buf_size_ptr;
+
+ WriteElementId(&buf, &buf_size, element_id);
+
+ const uint64 size = value.length();
+ WriteUInt(&buf, &buf_size, size);
+
+ memcpy(buf, value.data(), size);
+ buf += size;
+ buf_size -= size;
+}
+
+TracksBuilder::TracksBuilder() {}
+TracksBuilder::~TracksBuilder() {}
+
+void TracksBuilder::AddTrack(
+ int track_num,
+ int track_type,
+ const std::string& codec_id,
+ const std::string& name,
+ const std::string& language) {
+ tracks_.push_back(Track(track_num, track_type, codec_id, name, language));
+}
+
+std::vector<uint8> TracksBuilder::Finish() {
+ // Allocate the storage
+ std::vector<uint8> buffer;
+ buffer.resize(GetTracksSize());
+
+ // Populate the storage with a tracks header
+ WriteTracks(&buffer[0], buffer.size());
+
+ return buffer;
+}
+
+int TracksBuilder::GetTracksSize() const {
+ return MasterElementSize(kWebMIdTracks, GetTracksPayloadSize());
+}
+
+int TracksBuilder::GetTracksPayloadSize() const {
+ int payload_size = 0;
+
+ for (TrackList::const_iterator itr = tracks_.begin();
+ itr != tracks_.end(); ++itr) {
+ payload_size += itr->GetSize();
+ }
+
+ return payload_size;
+}
+
+void TracksBuilder::WriteTracks(uint8* buf, int buf_size) const {
+ WriteMasterElement(&buf, &buf_size, kWebMIdTracks, GetTracksPayloadSize());
+
+ for (TrackList::const_iterator itr = tracks_.begin();
+ itr != tracks_.end(); ++itr) {
+ itr->Write(&buf, &buf_size);
+ }
+}
+
+TracksBuilder::Track::Track(int track_num, int track_type,
+ const std::string& codec_id,
+ const std::string& name,
+ const std::string& language)
+ : track_num_(track_num),
+ track_type_(track_type),
+ codec_id_(codec_id),
+ name_(name),
+ language_(language) {
+}
+
+int TracksBuilder::Track::GetSize() const {
+ return MasterElementSize(kWebMIdTrackEntry, GetPayloadSize());
+}
+
+int TracksBuilder::Track::GetPayloadSize() const {
+ int size = 0;
+
+ size += IntElementSize(kWebMIdTrackNumber, track_num_);
+ size += IntElementSize(kWebMIdTrackType, track_type_);
+
+ if (!codec_id_.empty())
+ size += StringElementSize(kWebMIdCodecID, codec_id_);
+
+ if (!name_.empty())
+ size += StringElementSize(kWebMIdName, name_);
+
+ if (!language_.empty())
+ size += StringElementSize(kWebMIdLanguage, language_);
+
+ return size;
+}
+
+void TracksBuilder::Track::Write(uint8** buf, int* buf_size) const {
+ WriteMasterElement(buf, buf_size, kWebMIdTrackEntry, GetPayloadSize());
+
+ WriteIntElement(buf, buf_size, kWebMIdTrackNumber, track_num_);
+ WriteIntElement(buf, buf_size, kWebMIdTrackType, track_type_);
+
+ if (!codec_id_.empty())
+ WriteStringElement(buf, buf_size, kWebMIdCodecID, codec_id_);
+
+ if (!name_.empty())
+ WriteStringElement(buf, buf_size, kWebMIdName, name_);
+
+ if (!language_.empty())
+ WriteStringElement(buf, buf_size, kWebMIdLanguage, language_);
+}
+
+} // namespace media
diff --git a/media/webm/tracks_builder.h b/media/webm/tracks_builder.h
new file mode 100644
index 0000000..87ceaed
--- /dev/null
+++ b/media/webm/tracks_builder.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2013 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.
+
+#ifndef MEDIA_WEBM_TRACKS_BUILDER_H_
+#define MEDIA_WEBM_TRACKS_BUILDER_H_
+
+#include <list>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+
+namespace media {
+
+class TracksBuilder {
+ public:
+ TracksBuilder();
+ ~TracksBuilder();
+
+ void AddTrack(int track_num, int track_type, const std::string& codec_id,
+ const std::string& name, const std::string& language);
+
+ std::vector<uint8> Finish();
+
+ private:
+ int GetTracksSize() const;
+ int GetTracksPayloadSize() const;
+ void WriteTracks(uint8* buffer, int buffer_size) const;
+
+ class Track {
+ public:
+ Track(int track_num, int track_type, const std::string& codec_id,
+ const std::string& name, const std::string& language);
+
+ int GetSize() const;
+ void Write(uint8** buf, int* buf_size) const;
+ private:
+ int GetPayloadSize() const;
+
+ int track_num_;
+ int track_type_;
+ std::string codec_id_;
+ std::string name_;
+ std::string language_;
+ };
+
+ typedef std::list<Track> TrackList;
+ TrackList tracks_;
+
+ DISALLOW_COPY_AND_ASSIGN(TracksBuilder);
+};
+
+} // namespace media
+
+#endif // MEDIA_WEBM_TRACKS_BUILDER_H_
diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc
index 1d47720..ec89b67 100644
--- a/media/webm/webm_cluster_parser.cc
+++ b/media/webm/webm_cluster_parser.cc
@@ -48,7 +48,7 @@ bool WebMClusterParser::TextTrackIterator::operator()(
WebMClusterParser::WebMClusterParser(
int64 timecode_scale, int audio_track_num, int video_track_num,
- const std::set<int>& text_tracks,
+ const WebMTracksParser::TextTracks& text_tracks,
const std::set<int64>& ignored_tracks,
const std::string& audio_encryption_key_id,
const std::string& video_encryption_key_id,
@@ -67,10 +67,10 @@ 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();
+ for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin();
it != text_tracks.end();
++it) {
- text_track_map_.insert(std::make_pair(*it, Track(*it, false)));
+ text_track_map_.insert(std::make_pair(it->first, Track(it->first, false)));
}
}
diff --git a/media/webm/webm_cluster_parser.h b/media/webm/webm_cluster_parser.h
index 62cbde1..63d8626 100644
--- a/media/webm/webm_cluster_parser.h
+++ b/media/webm/webm_cluster_parser.h
@@ -15,6 +15,7 @@
#include "media/base/media_log.h"
#include "media/base/stream_parser_buffer.h"
#include "media/webm/webm_parser.h"
+#include "media/webm/webm_tracks_parser.h"
namespace media {
@@ -74,7 +75,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
WebMClusterParser(int64 timecode_scale,
int audio_track_num,
int video_track_num,
- const std::set<int>& text_tracks,
+ const WebMTracksParser::TextTracks& text_tracks,
const std::set<int64>& ignored_tracks,
const std::string& audio_encryption_key_id,
const std::string& video_encryption_key_id,
diff --git a/media/webm/webm_cluster_parser_unittest.cc b/media/webm/webm_cluster_parser_unittest.cc
index baa35f2..cea97e5 100644
--- a/media/webm/webm_cluster_parser_unittest.cc
+++ b/media/webm/webm_cluster_parser_unittest.cc
@@ -206,7 +206,7 @@ class WebMClusterParserTest : public testing::Test {
: parser_(new WebMClusterParser(kTimecodeScale,
kAudioTrackNum,
kVideoTrackNum,
- std::set<int>(),
+ WebMTracksParser::TextTracks(),
std::set<int64>(),
std::string(),
std::string(),
@@ -338,7 +338,7 @@ TEST_F(WebMClusterParserTest, IgnoredTracks) {
parser_.reset(new WebMClusterParser(kTimecodeScale,
kAudioTrackNum,
kVideoTrackNum,
- std::set<int>(),
+ WebMTracksParser::TextTracks(),
ignored_tracks,
std::string(),
std::string(),
@@ -372,8 +372,13 @@ TEST_F(WebMClusterParserTest, IgnoredTracks) {
}
TEST_F(WebMClusterParserTest, ParseTextTracks) {
- std::set<int> text_tracks;
- text_tracks.insert(kTextTrackNum);
+ typedef WebMTracksParser::TextTracks TextTracks;
+ TextTracks text_tracks;
+ WebMTracksParser::TextTrackInfo text_track_info;
+
+ text_track_info.kind = kTextSubtitles;
+ text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum),
+ text_track_info));
parser_.reset(new WebMClusterParser(kTimecodeScale,
kAudioTrackNum,
@@ -404,8 +409,13 @@ TEST_F(WebMClusterParserTest, ParseTextTracks) {
}
TEST_F(WebMClusterParserTest, TextTracksSimpleBlock) {
- std::set<int> text_tracks;
- text_tracks.insert(kTextTrackNum);
+ typedef WebMTracksParser::TextTracks TextTracks;
+ TextTracks text_tracks;
+ WebMTracksParser::TextTrackInfo text_track_info;
+
+ text_track_info.kind = kTextSubtitles;
+ text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum),
+ text_track_info));
parser_.reset(new WebMClusterParser(kTimecodeScale,
kAudioTrackNum,
@@ -429,14 +439,20 @@ TEST_F(WebMClusterParserTest, TextTracksSimpleBlock) {
}
TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) {
- typedef std::set<int> TextTrackSet;
- TextTrackSet text_tracks;
+ typedef WebMTracksParser::TextTracks TextTracks;
+ TextTracks text_tracks;
+ WebMTracksParser::TextTrackInfo text_track_info;
const int kSubtitleTextTrackNum = kTextTrackNum;
const int kCaptionTextTrackNum = kTextTrackNum + 1;
- text_tracks.insert(kSubtitleTextTrackNum);
- text_tracks.insert(kCaptionTextTrackNum);
+ text_track_info.kind = kTextSubtitles;
+ text_tracks.insert(std::make_pair(TextTracks::key_type(kSubtitleTextTrackNum),
+ text_track_info));
+
+ text_track_info.kind = kTextCaptions;
+ text_tracks.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum),
+ text_track_info));
parser_.reset(new WebMClusterParser(kTimecodeScale,
kAudioTrackNum,
@@ -472,7 +488,7 @@ TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) {
const WebMClusterParser::BufferQueue* text_buffers;
while (text_it(&text_track_num, &text_buffers)) {
- const TextTrackSet::const_iterator find_result =
+ const WebMTracksParser::TextTracks::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,
@@ -486,7 +502,7 @@ TEST_F(WebMClusterParserTest, ParseEncryptedBlock) {
parser_.reset(new WebMClusterParser(kTimecodeScale,
kAudioTrackNum,
kVideoTrackNum,
- std::set<int>(),
+ WebMTracksParser::TextTracks(),
std::set<int64>(),
std::string(),
"video_key_id",
@@ -505,7 +521,7 @@ TEST_F(WebMClusterParserTest, ParseBadEncryptedBlock) {
parser_.reset(new WebMClusterParser(kTimecodeScale,
kAudioTrackNum,
kVideoTrackNum,
- std::set<int>(),
+ WebMTracksParser::TextTracks(),
std::set<int64>(),
std::string(),
"video_key_id",
diff --git a/media/webm/webm_constants.cc b/media/webm/webm_constants.cc
new file mode 100644
index 0000000..13ae086
--- /dev/null
+++ b/media/webm/webm_constants.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/webm/webm_constants.h"
+
+namespace media {
+
+const char kWebMCodecSubtitles[] = "D_WEBVTT/SUBTITLES";
+const char kWebMCodecCaptions[] = "D_WEBVTT/CAPTIONS";
+const char kWebMCodecDescriptions[] = "D_WEBVTT/DESCRIPTIONS";
+const char kWebMCodecMetadata[] = "D_WEBVTT/METADATA";
+
+} // namespace media
diff --git a/media/webm/webm_constants.h b/media/webm/webm_constants.h
index 7e5e3b1..5cfd5e6 100644
--- a/media/webm/webm_constants.h
+++ b/media/webm/webm_constants.h
@@ -6,6 +6,7 @@
#define MEDIA_WEBM_WEBM_CONSTANTS_H_
#include "base/basictypes.h"
+#include "media/base/media_export.h"
namespace media {
@@ -205,6 +206,19 @@ const uint8 kWebMFlagEncryptedFrame = 0x1;
const int kWebMIvSize = 8;
const int kWebMSignalByteSize = 1;
+// Current specification for WebVTT embedded in WebM
+// http://wiki.webmproject.org/webm-metadata/temporal-metadata/webvtt-in-webm
+
+const int kWebMTrackTypeVideo = 1;
+const int kWebMTrackTypeAudio = 2;
+const int kWebMTrackTypeSubtitlesOrCaptions = 0x11;
+const int kWebMTrackTypeDescriptionsOrMetadata = 0x21;
+
+MEDIA_EXPORT extern const char kWebMCodecSubtitles[];
+MEDIA_EXPORT extern const char kWebMCodecCaptions[];
+MEDIA_EXPORT extern const char kWebMCodecDescriptions[];
+MEDIA_EXPORT extern const char kWebMCodecMetadata[];
+
} // namespace media
#endif // MEDIA_WEBM_WEBM_CONSTANTS_H_
diff --git a/media/webm/webm_tracks_parser.cc b/media/webm/webm_tracks_parser.cc
index 7d11f69..4cf6f4a 100644
--- a/media/webm/webm_tracks_parser.cc
+++ b/media/webm/webm_tracks_parser.cc
@@ -12,23 +12,17 @@
namespace media {
-// Values for TrackType element.
-static const int kWebMTrackTypeVideo = 1;
-static const int kWebMTrackTypeAudio = 2;
-static const int kWebMTrackTypeSubtitlesOrCaptions = 0x11;
-static const int kWebMTrackTypeDescriptionsOrMetadata = 0x21;
-
static TextKind CodecIdToTextKind(const std::string& codec_id) {
- if (codec_id == "D_WEBVTT/SUBTITLES")
+ if (codec_id == kWebMCodecSubtitles)
return kTextSubtitles;
- if (codec_id == "D_WEBVTT/CAPTIONS")
+ if (codec_id == kWebMCodecCaptions)
return kTextCaptions;
- if (codec_id == "D_WEBVTT/DESCRIPTIONS")
+ if (codec_id == kWebMCodecDescriptions)
return kTextDescriptions;
- if (codec_id == "D_WEBVTT/METADATA")
+ if (codec_id == kWebMCodecMetadata)
return kTextMetadata;
return kTextNone;
@@ -49,6 +43,8 @@ WebMTracksParser::~WebMTracksParser() {}
int WebMTracksParser::Parse(const uint8* buf, int size) {
track_type_ =-1;
track_num_ = -1;
+ track_name_.clear();
+ track_language_.clear();
audio_track_num_ = -1;
audio_decoder_config_ = AudioDecoderConfig();
video_track_num_ = -1;
@@ -77,6 +73,8 @@ WebMParserClient* WebMTracksParser::OnListStart(int id) {
if (id == kWebMIdTrackEntry) {
track_type_ = -1;
track_num_ = -1;
+ track_name_.clear();
+ track_language_.clear();
codec_id_ = "";
codec_private_.clear();
audio_client_.Reset();
@@ -115,8 +113,9 @@ bool WebMTracksParser::OnListEnd(int id) {
return false;
}
+ TextKind text_track_kind = kTextNone;
if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) {
- TextKind text_track_kind = CodecIdToTextKind(codec_id_);
+ text_track_kind = CodecIdToTextKind(codec_id_);
if (text_track_kind == kTextNone) {
MEDIA_LOG(log_cb_) << "Missing TrackEntry CodecID"
<< " TrackNum " << track_num_;
@@ -130,7 +129,7 @@ bool WebMTracksParser::OnListEnd(int id) {
return false;
}
} else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
- TextKind text_track_kind = CodecIdToTextKind(codec_id_);
+ text_track_kind = CodecIdToTextKind(codec_id_);
if (text_track_kind == kTextNone) {
MEDIA_LOG(log_cb_) << "Missing TrackEntry CodecID"
<< " TrackNum " << track_num_;
@@ -186,7 +185,10 @@ bool WebMTracksParser::OnListEnd(int id) {
}
} else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions ||
track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
- text_tracks_.insert(track_num_);
+ TextTrackInfo& text_track_info = text_tracks_[track_num_];
+ text_track_info.kind = text_track_kind;
+ text_track_info.name = track_name_;
+ text_track_info.language = track_language_;
} else {
MEDIA_LOG(log_cb_) << "Unexpected TrackType " << track_type_;
return false;
@@ -194,6 +196,8 @@ bool WebMTracksParser::OnListEnd(int id) {
track_type_ = -1;
track_num_ = -1;
+ track_name_.clear();
+ track_language_.clear();
codec_id_ = "";
codec_private_.clear();
track_content_encodings_client_.reset();
@@ -258,6 +262,16 @@ bool WebMTracksParser::OnString(int id, const std::string& str) {
return true;
}
+ if (id == kWebMIdName) {
+ track_name_ = str;
+ return true;
+ }
+
+ if (id == kWebMIdLanguage) {
+ track_language_ = str;
+ return true;
+ }
+
return true;
}
diff --git a/media/webm/webm_tracks_parser.h b/media/webm/webm_tracks_parser.h
index 79d8888..d5be6ce 100644
--- a/media/webm/webm_tracks_parser.h
+++ b/media/webm/webm_tracks_parser.h
@@ -5,6 +5,7 @@
#ifndef MEDIA_WEBM_WEBM_TRACKS_PARSER_H_
#define MEDIA_WEBM_WEBM_TRACKS_PARSER_H_
+#include <map>
#include <set>
#include <string>
#include <vector>
@@ -22,7 +23,7 @@
namespace media {
// Parser for WebM Tracks element.
-class WebMTracksParser : public WebMParserClient {
+class MEDIA_EXPORT WebMTracksParser : public WebMParserClient {
public:
explicit WebMTracksParser(const LogCB& log_cb);
virtual ~WebMTracksParser();
@@ -54,7 +55,15 @@ class WebMTracksParser : public WebMParserClient {
return video_decoder_config_;
}
- const std::set<int>& text_tracks() const {
+ struct TextTrackInfo {
+ TextKind kind;
+ std::string name;
+ std::string language;
+ };
+
+ typedef std::map<int64, TextTrackInfo> TextTracks;
+
+ const TextTracks& text_tracks() const {
return text_tracks_;
}
@@ -69,13 +78,15 @@ class WebMTracksParser : public WebMParserClient {
int64 track_type_;
int64 track_num_;
+ std::string track_name_;
+ std::string track_language_;
std::string codec_id_;
std::vector<uint8> codec_private_;
scoped_ptr<WebMContentEncodingsClient> track_content_encodings_client_;
int64 audio_track_num_;
int64 video_track_num_;
- std::set<int> text_tracks_;
+ TextTracks text_tracks_;
std::set<int64> ignored_tracks_;
std::string audio_encryption_key_id_;
std::string video_encryption_key_id_;
diff --git a/media/webm/webm_tracks_parser_unittest.cc b/media/webm/webm_tracks_parser_unittest.cc
new file mode 100644
index 0000000..6d23669
--- /dev/null
+++ b/media/webm/webm_tracks_parser_unittest.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2013 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 "base/logging.h"
+#include "media/webm/tracks_builder.h"
+#include "media/webm/webm_constants.h"
+#include "media/webm/webm_tracks_parser.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::InSequence;
+using ::testing::Return;
+using ::testing::_;
+
+namespace media {
+
+static const int kTypeSubtitlesOrCaptions = 0x11;
+static const int kTypeDescriptionsOrMetadata = 0x21;
+
+class WebMTracksParserTest : public testing::Test {
+ public:
+ WebMTracksParserTest() {}
+};
+
+static void VerifyTextTrackInfo(const uint8* buffer,
+ int buffer_size,
+ TextKind text_kind,
+ const std::string& name,
+ const std::string& language) {
+ scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB()));
+
+ int result = parser->Parse(buffer, buffer_size);
+ EXPECT_GT(result, 0);
+ EXPECT_EQ(result, buffer_size);
+
+ const WebMTracksParser::TextTracks& text_tracks = parser->text_tracks();
+ EXPECT_EQ(text_tracks.size(), WebMTracksParser::TextTracks::size_type(1));
+
+ const WebMTracksParser::TextTracks::const_iterator itr = text_tracks.begin();
+ EXPECT_EQ(itr->first, 1); // track num
+
+ const WebMTracksParser::TextTrackInfo& info = itr->second;
+ EXPECT_EQ(info.kind, text_kind);
+ EXPECT_TRUE(info.name == name);
+ EXPECT_TRUE(info.language == language);
+}
+
+TEST_F(WebMTracksParserTest, TestSubtitleNoNameNoLang) {
+ InSequence s;
+
+ TracksBuilder tb;
+ tb.AddTrack(1, kWebMTrackTypeSubtitlesOrCaptions,
+ kWebMCodecSubtitles, "", "");
+
+ const std::vector<uint8> buf = tb.Finish();
+ VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", "");
+}
+
+TEST_F(WebMTracksParserTest, TestSubtitleYesNameNoLang) {
+ InSequence s;
+
+ TracksBuilder tb;
+ tb.AddTrack(1, kWebMTrackTypeSubtitlesOrCaptions,
+ kWebMCodecSubtitles, "Spock", "");
+
+ const std::vector<uint8> buf = tb.Finish();
+ VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Spock", "");
+}
+
+TEST_F(WebMTracksParserTest, TestSubtitleNoNameYesLang) {
+ InSequence s;
+
+ TracksBuilder tb;
+ tb.AddTrack(1, kWebMTrackTypeSubtitlesOrCaptions,
+ kWebMCodecSubtitles, "", "eng");
+
+ const std::vector<uint8> buf = tb.Finish();
+ VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", "eng");
+}
+
+TEST_F(WebMTracksParserTest, TestSubtitleYesNameYesLang) {
+ InSequence s;
+
+ TracksBuilder tb;
+ tb.AddTrack(1, kWebMTrackTypeSubtitlesOrCaptions,
+ kWebMCodecSubtitles, "Picard", "fre");
+
+ const std::vector<uint8> buf = tb.Finish();
+ VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Picard", "fre");
+}
+
+} // namespace media