summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/media.gyp10
-rw-r--r--media/webm/webm_audio_client.cc112
-rw-r--r--media/webm/webm_audio_client.h52
-rw-r--r--media/webm/webm_stream_parser.cc199
-rw-r--r--media/webm/webm_stream_parser.h3
-rw-r--r--media/webm/webm_tracks_parser.cc109
-rw-r--r--media/webm/webm_tracks_parser.h25
-rw-r--r--media/webm/webm_video_client.cc154
-rw-r--r--media/webm/webm_video_client.h60
9 files changed, 483 insertions, 241 deletions
diff --git a/media/media.gyp b/media/media.gyp
index 82bab1c..c6977e4 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -412,6 +412,8 @@
'video/picture.h',
'video/video_decode_accelerator.cc',
'video/video_decode_accelerator.h',
+ 'webm/webm_audio_client.cc',
+ 'webm/webm_audio_client.h',
'webm/webm_cluster_parser.cc',
'webm/webm_cluster_parser.h',
'webm/webm_constants.h',
@@ -429,6 +431,8 @@
'webm/webm_stream_parser.h',
'webm/webm_tracks_parser.cc',
'webm/webm_tracks_parser.h',
+ 'webm/webm_video_client.cc',
+ 'webm/webm_video_client.h',
],
'direct_dependent_settings': {
'include_dirs': [
@@ -465,8 +469,6 @@
'ffmpeg/ffmpeg_common.h',
'filters/audio_file_reader.cc',
'filters/audio_file_reader.h',
- 'filters/chunk_demuxer.cc',
- 'filters/chunk_demuxer.h',
'filters/blocking_url_protocol.cc',
'filters/blocking_url_protocol.h',
'filters/ffmpeg_audio_decoder.cc',
@@ -479,10 +481,6 @@
'filters/ffmpeg_h264_to_annex_b_bitstream_converter.h',
'filters/ffmpeg_video_decoder.cc',
'filters/ffmpeg_video_decoder.h',
- 'webm/webm_cluster_parser.cc',
- 'webm/webm_cluster_parser.h',
- 'webm/webm_stream_parser.cc',
- 'webm/webm_stream_parser.h',
],
}],
['media_use_libvpx == 1', {
diff --git a/media/webm/webm_audio_client.cc b/media/webm/webm_audio_client.cc
new file mode 100644
index 0000000..e52f44b
--- /dev/null
+++ b/media/webm/webm_audio_client.cc
@@ -0,0 +1,112 @@
+// 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_audio_client.h"
+
+#include "media/base/audio_decoder_config.h"
+#include "media/base/channel_layout.h"
+#include "media/webm/webm_constants.h"
+
+namespace media {
+
+WebMAudioClient::WebMAudioClient(const LogCB& log_cb)
+ : log_cb_(log_cb) {
+ Reset();
+}
+
+WebMAudioClient::~WebMAudioClient() {
+}
+
+void WebMAudioClient::Reset() {
+ channels_ = -1;
+ samples_per_second_ = -1;
+ output_samples_per_second_ = -1;
+}
+
+bool WebMAudioClient::InitializeConfig(
+ const std::string& codec_id, const std::vector<uint8>& codec_private,
+ bool is_encrypted, AudioDecoderConfig* config) {
+ DCHECK(config);
+
+ AudioCodec audio_codec = kUnknownAudioCodec;
+ if (codec_id == "A_VORBIS") {
+ audio_codec = kCodecVorbis;
+ } else {
+ MEDIA_LOG(log_cb_) << "Unsupported audio codec_id " << codec_id;
+ return false;
+ }
+
+ if (samples_per_second_ <= 0)
+ return false;
+
+ // Set channel layout default if a Channels element was not present.
+ if (channels_ == -1)
+ channels_ = 1;
+
+ ChannelLayout channel_layout = GuessChannelLayout(channels_);
+
+ if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
+ MEDIA_LOG(log_cb_) << "Unsupported channel count " << channels_;
+ return false;
+ }
+
+ int samples_per_second = samples_per_second_;
+ if (output_samples_per_second_ > 0)
+ samples_per_second = output_samples_per_second_;
+
+ const uint8* extra_data = NULL;
+ size_t extra_data_size = 0;
+ if (codec_private.size() > 0) {
+ extra_data = &codec_private[0];
+ extra_data_size = codec_private.size();
+ }
+
+ config->Initialize(
+ audio_codec, kSampleFormatPlanarF32, channel_layout,
+ samples_per_second, extra_data, extra_data_size, is_encrypted, true);
+ return config->IsValidConfig();
+}
+
+bool WebMAudioClient::OnUInt(int id, int64 val) {
+ if (id == kWebMIdChannels) {
+ if (channels_ != -1) {
+ MEDIA_LOG(log_cb_) << "Multiple values for id " << std::hex << id
+ << " specified. (" << channels_ << " and " << val
+ << ")";
+ return false;
+ }
+
+ channels_ = val;
+ }
+ return true;
+}
+
+bool WebMAudioClient::OnFloat(int id, double val) {
+ double* dst = NULL;
+
+ switch (id) {
+ case kWebMIdSamplingFrequency:
+ dst = &samples_per_second_;
+ break;
+ case kWebMIdOutputSamplingFrequency:
+ dst = &output_samples_per_second_;
+ break;
+ default:
+ return true;
+ }
+
+ if (val <= 0)
+ return false;
+
+ if (*dst != -1) {
+ MEDIA_LOG(log_cb_) << "Multiple values for id " << std::hex << id
+ << " specified (" << *dst << " and " << val << ")";
+ return false;
+ }
+
+ *dst = val;
+ return true;
+}
+
+} // namespace media
diff --git a/media/webm/webm_audio_client.h b/media/webm/webm_audio_client.h
new file mode 100644
index 0000000..1338f5c
--- /dev/null
+++ b/media/webm/webm_audio_client.h
@@ -0,0 +1,52 @@
+// 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_WEBM_AUDIO_CLIENT_H_
+#define MEDIA_WEBM_WEBM_AUDIO_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include "media/base/media_log.h"
+#include "media/webm/webm_parser.h"
+
+namespace media {
+class AudioDecoderConfig;
+
+// Helper class used to parse an Audio element inside a TrackEntry element.
+class WebMAudioClient : public WebMParserClient {
+ public:
+ explicit WebMAudioClient(const LogCB& log_cb);
+ virtual ~WebMAudioClient();
+
+ // Reset this object's state so it can process a new audio track element.
+ void Reset();
+
+ // Initialize |config| with the data in |codec_id|, |codec_private|,
+ // |is_encrypted| and the fields parsed from the last audio track element this
+ // object was used to parse.
+ // Returns true if |config| was successfully initialized.
+ // Returns false if there was unexpected values in the provided parameters or
+ // audio track element fields.
+ bool InitializeConfig(const std::string& codec_id,
+ const std::vector<uint8>& codec_private,
+ bool is_encrypted,
+ AudioDecoderConfig* config);
+
+ private:
+ // WebMParserClient implementation.
+ virtual bool OnUInt(int id, int64 val) OVERRIDE;
+ virtual bool OnFloat(int id, double val) OVERRIDE;
+
+ LogCB log_cb_;
+ int channels_;
+ double samples_per_second_;
+ double output_samples_per_second_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebMAudioClient);
+};
+
+} // namespace media
+
+#endif // MEDIA_WEBM_WEBM_AUDIO_CLIENT_H_
diff --git a/media/webm/webm_stream_parser.cc b/media/webm/webm_stream_parser.cc
index f47fa41..514a6d0 100644
--- a/media/webm/webm_stream_parser.cc
+++ b/media/webm/webm_stream_parser.cc
@@ -8,9 +8,6 @@
#include "base/callback.h"
#include "base/logging.h"
-#include "media/ffmpeg/ffmpeg_common.h"
-#include "media/filters/ffmpeg_glue.h"
-#include "media/filters/in_memory_url_protocol.h"
#include "media/webm/webm_cluster_parser.h"
#include "media/webm/webm_constants.h"
#include "media/webm/webm_content_encodings.h"
@@ -20,156 +17,6 @@
namespace media {
-// Helper class that uses FFmpeg to create AudioDecoderConfig &
-// VideoDecoderConfig objects.
-//
-// This dependency on FFmpeg can be removed once we update WebMTracksParser
-// to parse the necessary data to construct AudioDecoderConfig &
-// VideoDecoderConfig objects. http://crbug.com/108756
-class FFmpegConfigHelper {
- public:
- FFmpegConfigHelper();
- ~FFmpegConfigHelper();
-
- bool Parse(const uint8* data, int size);
-
- const AudioDecoderConfig& audio_config() const;
- const VideoDecoderConfig& video_config() const;
-
- private:
- static const uint8 kWebMHeader[];
- static const int kSegmentSizeOffset;
- static const uint8 kEmptyCluster[];
-
- bool OpenFormatContext(const uint8* data, int size);
- bool SetupStreamConfigs();
-
- AudioDecoderConfig audio_config_;
- VideoDecoderConfig video_config_;
-
- // Backing buffer for |url_protocol_|.
- scoped_array<uint8> url_protocol_buffer_;
-
- // Protocol used by FFmpegGlue. It must outlive the context object.
- scoped_ptr<InMemoryUrlProtocol> url_protocol_;
-
- // Glue for interfacing InMemoryUrlProtocol with FFmpeg.
- scoped_ptr<FFmpegGlue> glue_;
-
- DISALLOW_COPY_AND_ASSIGN(FFmpegConfigHelper);
-};
-
-// WebM File Header. This is prepended to the INFO & TRACKS
-// data passed to Init() before handing it to FFmpeg. Essentially
-// we are making the INFO & TRACKS data look like a small WebM
-// file so we can use FFmpeg to initialize the AVFormatContext.
-const uint8 FFmpegConfigHelper::kWebMHeader[] = {
- 0x1A, 0x45, 0xDF, 0xA3, 0x9F, // EBML (size = 0x1f)
- 0x42, 0x86, 0x81, 0x01, // EBMLVersion = 1
- 0x42, 0xF7, 0x81, 0x01, // EBMLReadVersion = 1
- 0x42, 0xF2, 0x81, 0x04, // EBMLMaxIDLength = 4
- 0x42, 0xF3, 0x81, 0x08, // EBMLMaxSizeLength = 8
- 0x42, 0x82, 0x84, 0x77, 0x65, 0x62, 0x6D, // DocType = "webm"
- 0x42, 0x87, 0x81, 0x02, // DocTypeVersion = 2
- 0x42, 0x85, 0x81, 0x02, // DocTypeReadVersion = 2
- // EBML end
- 0x18, 0x53, 0x80, 0x67, // Segment
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // segment(size = 0)
- // INFO goes here.
-};
-
-// Offset of the segment size field in kWebMHeader. Used to update
-// the segment size field before handing the buffer to FFmpeg.
-const int FFmpegConfigHelper::kSegmentSizeOffset = sizeof(kWebMHeader) - 8;
-
-const uint8 FFmpegConfigHelper::kEmptyCluster[] = {
- 0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0)
-};
-
-FFmpegConfigHelper::FFmpegConfigHelper() {}
-
-FFmpegConfigHelper::~FFmpegConfigHelper() {
- if (url_protocol_.get()) {
- url_protocol_.reset();
- url_protocol_buffer_.reset();
- }
-
- if (glue_.get())
- glue_.reset();
-}
-
-bool FFmpegConfigHelper::Parse(const uint8* data, int size) {
- return OpenFormatContext(data, size) && SetupStreamConfigs();
-}
-
-const AudioDecoderConfig& FFmpegConfigHelper::audio_config() const {
- return audio_config_;
-}
-
-const VideoDecoderConfig& FFmpegConfigHelper::video_config() const {
- return video_config_;
-}
-
-bool FFmpegConfigHelper::OpenFormatContext(const uint8* data, int size) {
- DCHECK(!url_protocol_.get());
- DCHECK(!url_protocol_buffer_.get());
- DCHECK(!glue_.get());
-
- int segment_size = size + sizeof(kEmptyCluster);
- int buf_size = sizeof(kWebMHeader) + segment_size;
- url_protocol_buffer_.reset(new uint8[buf_size]);
- uint8* buf = url_protocol_buffer_.get();
- memcpy(buf, kWebMHeader, sizeof(kWebMHeader));
- memcpy(buf + sizeof(kWebMHeader), data, size);
- memcpy(buf + sizeof(kWebMHeader) + size, kEmptyCluster,
- sizeof(kEmptyCluster));
-
- // Update the segment size in the buffer.
- int64 tmp = (segment_size & GG_LONGLONG(0x00FFFFFFFFFFFFFF)) |
- GG_LONGLONG(0x0100000000000000);
- for (int i = 0; i < 8; i++) {
- buf[kSegmentSizeOffset + i] = (tmp >> (8 * (7 - i))) & 0xff;
- }
-
- url_protocol_.reset(new InMemoryUrlProtocol(buf, buf_size, true));
- glue_.reset(new FFmpegGlue(url_protocol_.get()));
-
- // Open FFmpeg AVFormatContext.
- return glue_->OpenContext();
-}
-
-bool FFmpegConfigHelper::SetupStreamConfigs() {
- AVFormatContext* format_context = glue_->format_context();
- int result = avformat_find_stream_info(format_context, NULL);
-
- if (result < 0)
- return false;
-
- bool no_supported_streams = true;
- for (size_t i = 0; i < format_context->nb_streams; ++i) {
- AVStream* stream = format_context->streams[i];
- AVMediaType codec_type = stream->codec->codec_type;
-
- if (codec_type == AVMEDIA_TYPE_AUDIO &&
- stream->codec->codec_id == CODEC_ID_VORBIS &&
- !audio_config_.IsValidConfig()) {
- AVStreamToAudioDecoderConfig(stream, &audio_config_);
- no_supported_streams = false;
- continue;
- }
-
- if (codec_type == AVMEDIA_TYPE_VIDEO &&
- stream->codec->codec_id == CODEC_ID_VP8 &&
- !video_config_.IsValidConfig()) {
- AVStreamToVideoDecoderConfig(stream, &video_config_);
- no_supported_streams = false;
- continue;
- }
- }
-
- return !no_supported_streams;
-}
-
WebMStreamParser::WebMStreamParser()
: state_(kWaitingForInit),
waiting_for_buffers_(false) {
@@ -338,51 +185,13 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
duration = base::TimeDelta::FromMicroseconds(duration_in_us);
}
- FFmpegConfigHelper config_helper;
- if (!config_helper.Parse(data, bytes_parsed)) {
- DVLOG(1) << "Failed to parse config data.";
- return -1;
- }
-
- bool is_audio_encrypted = !tracks_parser.audio_encryption_key_id().empty();
- AudioDecoderConfig audio_config;
- if (is_audio_encrypted) {
- const AudioDecoderConfig& original_audio_config =
- config_helper.audio_config();
-
- audio_config.Initialize(original_audio_config.codec(),
- original_audio_config.sample_format(),
- original_audio_config.channel_layout(),
- original_audio_config.samples_per_second(),
- original_audio_config.extra_data(),
- original_audio_config.extra_data_size(),
- is_audio_encrypted,
- false);
-
+ const AudioDecoderConfig& audio_config = tracks_parser.audio_decoder_config();
+ if (audio_config.is_encrypted())
FireNeedKey(tracks_parser.audio_encryption_key_id());
- } else {
- audio_config = config_helper.audio_config();
- }
-
- bool is_video_encrypted = !tracks_parser.video_encryption_key_id().empty();
- VideoDecoderConfig video_config;
- if (is_video_encrypted) {
- const VideoDecoderConfig& original_video_config =
- config_helper.video_config();
- video_config.Initialize(original_video_config.codec(),
- original_video_config.profile(),
- original_video_config.format(),
- original_video_config.coded_size(),
- original_video_config.visible_rect(),
- original_video_config.natural_size(),
- original_video_config.extra_data(),
- original_video_config.extra_data_size(),
- is_video_encrypted, false);
+ const VideoDecoderConfig& video_config = tracks_parser.video_decoder_config();
+ if (video_config.is_encrypted())
FireNeedKey(tracks_parser.video_encryption_key_id());
- } else {
- video_config = config_helper.video_config();
- }
if (!config_cb_.Run(audio_config, video_config)) {
DVLOG(1) << "New config data isn't allowed.";
diff --git a/media/webm/webm_stream_parser.h b/media/webm/webm_stream_parser.h
index c98805a..7407542 100644
--- a/media/webm/webm_stream_parser.h
+++ b/media/webm/webm_stream_parser.h
@@ -12,10 +12,11 @@
#include "media/base/byte_queue.h"
#include "media/base/stream_parser.h"
#include "media/base/video_decoder_config.h"
-#include "media/webm/webm_cluster_parser.h"
namespace media {
+class WebMClusterParser;
+
class WebMStreamParser : public StreamParser {
public:
WebMStreamParser();
diff --git a/media/webm/webm_tracks_parser.cc b/media/webm/webm_tracks_parser.cc
index 2dbac41..7703504 100644
--- a/media/webm/webm_tracks_parser.cc
+++ b/media/webm/webm_tracks_parser.cc
@@ -18,13 +18,30 @@ 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")
+ return kTextSubtitles;
+
+ if (codec_id == "D_WEBVTT/CAPTIONS")
+ return kTextCaptions;
+
+ if (codec_id == "D_WEBVTT/DESCRIPTIONS")
+ return kTextDescriptions;
+
+ if (codec_id == "D_WEBVTT/METADATA")
+ return kTextMetadata;
+
+ return kTextNone;
+}
+
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) {
+ log_cb_(log_cb),
+ audio_client_(log_cb),
+ video_client_(log_cb) {
}
WebMTracksParser::~WebMTracksParser() {}
@@ -32,9 +49,10 @@ WebMTracksParser::~WebMTracksParser() {}
int WebMTracksParser::Parse(const uint8* buf, int size) {
track_type_ =-1;
track_num_ = -1;
- text_track_kind_ = kTextNone;
audio_track_num_ = -1;
+ audio_decoder_config_ = AudioDecoderConfig();
video_track_num_ = -1;
+ video_decoder_config_ = VideoDecoderConfig();
text_tracks_.clear();
ignored_tracks_.clear();
@@ -59,10 +77,19 @@ WebMParserClient* WebMTracksParser::OnListStart(int id) {
if (id == kWebMIdTrackEntry) {
track_type_ = -1;
track_num_ = -1;
- text_track_kind_ = kTextNone;
+ codec_id_ = "";
+ codec_private_.clear();
+ audio_client_.Reset();
+ video_client_.Reset();
return this;
}
+ if (id == kWebMIdAudio)
+ return &audio_client_;
+
+ if (id == kWebMIdVideo)
+ return &video_client_;
+
return this;
}
@@ -89,27 +116,29 @@ bool WebMTracksParser::OnListEnd(int id) {
}
if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) {
- if (text_track_kind_ == kTextNone) {
+ TextKind text_track_kind = CodecIdToTextKind(codec_id_);
+ 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) {
+ 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) {
+ TextKind text_track_kind = CodecIdToTextKind(codec_id_);
+ 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) {
+ if (text_track_kind != kTextDescriptions &&
+ text_track_kind != kTextMetadata) {
MEDIA_LOG(log_cb_) << "Wrong TrackEntry CodecID"
<< " TrackNum " << track_num_;
return false;
@@ -129,6 +158,13 @@ bool WebMTracksParser::OnListEnd(int id) {
if (audio_track_num_ == -1) {
audio_track_num_ = track_num_;
audio_encryption_key_id_ = encryption_key_id;
+
+ DCHECK(!audio_decoder_config_.IsValidConfig());
+ if (!audio_client_.InitializeConfig(
+ codec_id_, codec_private_, !audio_encryption_key_id_.empty(),
+ &audio_decoder_config_)) {
+ return false;
+ }
} else {
MEDIA_LOG(log_cb_) << "Ignoring audio track " << track_num_;
ignored_tracks_.insert(track_num_);
@@ -137,6 +173,13 @@ bool WebMTracksParser::OnListEnd(int id) {
if (video_track_num_ == -1) {
video_track_num_ = track_num_;
video_encryption_key_id_ = encryption_key_id;
+
+ DCHECK(!video_decoder_config_.IsValidConfig());
+ if (!video_client_.InitializeConfig(
+ codec_id_, codec_private_, !video_encryption_key_id_.empty(),
+ &video_decoder_config_)) {
+ return false;
+ }
} else {
MEDIA_LOG(log_cb_) << "Ignoring video track " << track_num_;
ignored_tracks_.insert(track_num_);
@@ -151,8 +194,12 @@ bool WebMTracksParser::OnListEnd(int id) {
track_type_ = -1;
track_num_ = -1;
+ codec_id_ = "";
+ codec_private_.clear();
track_content_encodings_client_.reset();
- text_track_kind_ = kTextNone;
+
+ audio_client_.Reset();
+ video_client_.Reset();
return true;
}
@@ -188,39 +235,27 @@ bool WebMTracksParser::OnFloat(int id, double val) {
}
bool WebMTracksParser::OnBinary(int id, const uint8* data, int size) {
+ if (id == kWebMIdCodecPrivate) {
+ if (!codec_private_.empty()) {
+ MEDIA_LOG(log_cb_) << "Multiple CodecPrivate fields in a track.";
+ return false;
+ }
+
+ codec_private_.assign(data, data + size);
+ return true;
+ }
return true;
}
bool WebMTracksParser::OnString(int id, const std::string& str) {
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;
+ if (!codec_id_.empty()) {
+ MEDIA_LOG(log_cb_) << "Multiple CodecID fields in a track";
+ return false;
}
- MEDIA_LOG(log_cb_) << "Unexpected CodecID " << str;
- return false;
+ codec_id_ = str;
+ return true;
}
return true;
diff --git a/media/webm/webm_tracks_parser.h b/media/webm/webm_tracks_parser.h
index 5593349..79d8888 100644
--- a/media/webm/webm_tracks_parser.h
+++ b/media/webm/webm_tracks_parser.h
@@ -7,12 +7,17 @@
#include <set>
#include <string>
+#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
+#include "media/base/audio_decoder_config.h"
#include "media/base/media_log.h"
+#include "media/base/video_decoder_config.h"
+#include "media/webm/webm_audio_client.h"
#include "media/webm/webm_content_encodings_client.h"
#include "media/webm/webm_parser.h"
+#include "media/webm/webm_video_client.h"
namespace media {
@@ -36,16 +41,25 @@ class WebMTracksParser : public WebMParserClient {
const std::string& audio_encryption_key_id() const {
return audio_encryption_key_id_;
}
+
+ const AudioDecoderConfig& audio_decoder_config() {
+ return audio_decoder_config_;
+ }
+
const std::string& video_encryption_key_id() const {
return video_encryption_key_id_;
}
+ const VideoDecoderConfig& video_decoder_config() {
+ return video_decoder_config_;
+ }
+
const std::set<int>& text_tracks() const {
return text_tracks_;
}
private:
- // WebMParserClient methods
+ // WebMParserClient implementation.
virtual WebMParserClient* OnListStart(int id) OVERRIDE;
virtual bool OnListEnd(int id) OVERRIDE;
virtual bool OnUInt(int id, int64 val) OVERRIDE;
@@ -55,8 +69,9 @@ class WebMTracksParser : public WebMParserClient {
int64 track_type_;
int64 track_num_;
+ std::string codec_id_;
+ std::vector<uint8> codec_private_;
scoped_ptr<WebMContentEncodingsClient> track_content_encodings_client_;
- TextKind text_track_kind_;
int64 audio_track_num_;
int64 video_track_num_;
@@ -66,6 +81,12 @@ class WebMTracksParser : public WebMParserClient {
std::string video_encryption_key_id_;
LogCB log_cb_;
+ WebMAudioClient audio_client_;
+ AudioDecoderConfig audio_decoder_config_;
+
+ WebMVideoClient video_client_;
+ VideoDecoderConfig video_decoder_config_;
+
DISALLOW_COPY_AND_ASSIGN(WebMTracksParser);
};
diff --git a/media/webm/webm_video_client.cc b/media/webm/webm_video_client.cc
new file mode 100644
index 0000000..bb4b111
--- /dev/null
+++ b/media/webm/webm_video_client.cc
@@ -0,0 +1,154 @@
+// 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_video_client.h"
+
+#include "media/base/video_decoder_config.h"
+#include "media/webm/webm_constants.h"
+
+namespace media {
+
+WebMVideoClient::WebMVideoClient(const LogCB& log_cb)
+ : log_cb_(log_cb) {
+ Reset();
+}
+
+WebMVideoClient::~WebMVideoClient() {
+}
+
+void WebMVideoClient::Reset() {
+ pixel_width_ = -1;
+ pixel_height_ = -1;
+ crop_bottom_ = -1;
+ crop_top_ = -1;
+ crop_left_ = -1;
+ crop_right_ = -1;
+ display_width_ = -1;
+ display_height_ = -1;
+ display_unit_ = -1;
+}
+
+bool WebMVideoClient::InitializeConfig(
+ const std::string& codec_id, const std::vector<uint8>& codec_private,
+ bool is_encrypted, VideoDecoderConfig* config) {
+ DCHECK(config);
+
+ VideoCodec video_codec = kUnknownVideoCodec;
+ VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
+ if (codec_id == "V_VP8") {
+ video_codec = kCodecVP8;
+ profile = VP8PROFILE_MAIN;
+ } else {
+ MEDIA_LOG(log_cb_) << "Unsupported video codec_id " << codec_id;
+ return false;
+ }
+
+ if (pixel_width_ <= 0 || pixel_height_ <= 0)
+ return false;
+
+ // Set crop and display unit defaults if these elements are not present.
+ if (crop_bottom_ == -1)
+ crop_bottom_ = 0;
+
+ if (crop_top_ == -1)
+ crop_top_ = 0;
+
+ if (crop_left_ == -1)
+ crop_left_ = 0;
+
+ if (crop_right_ == -1)
+ crop_right_ = 0;
+
+ if (display_unit_ == -1)
+ display_unit_ = 0;
+
+ gfx::Size coded_size(pixel_width_, pixel_height_);
+ gfx::Rect visible_rect(crop_top_, crop_left_,
+ pixel_width_ - (crop_left_ + crop_right_),
+ pixel_height_ - (crop_top_ + crop_bottom_));
+ gfx::Size natural_size = coded_size;
+ if (display_unit_ == 0) {
+ if (display_width_ <= 0)
+ display_width_ = pixel_width_;
+ if (display_height_ <= 0)
+ display_height_ = pixel_height_;
+ natural_size = gfx::Size(display_width_, display_height_);
+ } else if (display_unit_ == 3) {
+ if (display_width_ <= 0 || display_height_ <= 0)
+ return false;
+ natural_size = gfx::Size(display_width_, display_height_);
+ } else {
+ MEDIA_LOG(log_cb_) << "Unsupported display unit type " << display_unit_;
+ return false;
+ }
+ const uint8* extra_data = NULL;
+ size_t extra_data_size = 0;
+ if (codec_private.size() > 0) {
+ extra_data = &codec_private[0];
+ extra_data_size = codec_private.size();
+ }
+
+ config->Initialize(
+ video_codec, profile, VideoFrame::YV12, coded_size,
+ visible_rect, natural_size, extra_data, extra_data_size,
+ is_encrypted, true);
+ return config->IsValidConfig();
+}
+
+bool WebMVideoClient::OnUInt(int id, int64 val) {
+ int64* dst = NULL;
+
+ switch (id) {
+ case kWebMIdPixelWidth:
+ dst = &pixel_width_;
+ break;
+ case kWebMIdPixelHeight:
+ dst = &pixel_height_;
+ break;
+ case kWebMIdPixelCropTop:
+ dst = &crop_top_;
+ break;
+ case kWebMIdPixelCropBottom:
+ dst = &crop_bottom_;
+ break;
+ case kWebMIdPixelCropLeft:
+ dst = &crop_left_;
+ break;
+ case kWebMIdPixelCropRight:
+ dst = &crop_right_;
+ break;
+ case kWebMIdDisplayWidth:
+ dst = &display_width_;
+ break;
+ case kWebMIdDisplayHeight:
+ dst = &display_height_;
+ break;
+ case kWebMIdDisplayUnit:
+ dst = &display_unit_;
+ break;
+ default:
+ return true;
+ }
+
+ if (*dst != -1) {
+ MEDIA_LOG(log_cb_) << "Multiple values for id " << std::hex << id
+ << " specified (" << *dst << " and " << val << ")";
+ return false;
+ }
+
+ *dst = val;
+ return true;
+}
+
+bool WebMVideoClient::OnBinary(int id, const uint8* data, int size) {
+ // Accept binary fields we don't care about for now.
+ return true;
+}
+
+bool WebMVideoClient::OnFloat(int id, double val) {
+ // Accept float fields we don't care about for now.
+ return true;
+}
+
+} // namespace media
diff --git a/media/webm/webm_video_client.h b/media/webm/webm_video_client.h
new file mode 100644
index 0000000..eb6be6d
--- /dev/null
+++ b/media/webm/webm_video_client.h
@@ -0,0 +1,60 @@
+// 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_WEBM_VIDEO_CLIENT_H_
+#define MEDIA_WEBM_WEBM_VIDEO_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include "media/base/media_log.h"
+#include "media/webm/webm_parser.h"
+
+namespace media {
+class VideoDecoderConfig;
+
+// Helper class used to parse a Video element inside a TrackEntry element.
+class WebMVideoClient : public WebMParserClient {
+ public:
+ explicit WebMVideoClient(const LogCB& log_cb);
+ virtual ~WebMVideoClient();
+
+ // Reset this object's state so it can process a new video track element.
+ void Reset();
+
+ // Initialize |config| with the data in |codec_id|, |codec_private|,
+ // |is_encrypted| and the fields parsed from the last video track element this
+ // object was used to parse.
+ // Returns true if |config| was successfully initialized.
+ // Returns false if there was unexpected values in the provided parameters or
+ // video track element fields. The contents of |config| are undefined in this
+ // case and should not be relied upon.
+ bool InitializeConfig(const std::string& codec_id,
+ const std::vector<uint8>& codec_private,
+ bool is_encrypted,
+ VideoDecoderConfig* config);
+
+ private:
+ // WebMParserClient implementation.
+ virtual bool OnUInt(int id, int64 val) OVERRIDE;
+ virtual bool OnBinary(int id, const uint8* data, int size) OVERRIDE;
+ virtual bool OnFloat(int id, double val) OVERRIDE;
+
+ LogCB log_cb_;
+ int64 pixel_width_;
+ int64 pixel_height_;
+ int64 crop_bottom_;
+ int64 crop_top_;
+ int64 crop_left_;
+ int64 crop_right_;
+ int64 display_width_;
+ int64 display_height_;
+ int64 display_unit_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebMVideoClient);
+};
+
+} // namespace media
+
+#endif // MEDIA_WEBM_WEBM_VIDEO_CLIENT_H_