summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorvigneshv@chromium.org <vigneshv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-22 12:43:22 +0000
committervigneshv@chromium.org <vigneshv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-22 12:43:22 +0000
commit05e78a90a52f8af3b66b4991f67684d008abc6de (patch)
tree56eae3a56c831d2bd41cb23eb20e349640983bc9 /media
parente70d98d66f19052f5abf3324f7094a2206887ba2 (diff)
downloadchromium_src-05e78a90a52f8af3b66b4991f67684d008abc6de.zip
chromium_src-05e78a90a52f8af3b66b4991f67684d008abc6de.tar.gz
chromium_src-05e78a90a52f8af3b66b4991f67684d008abc6de.tar.bz2
Adding VP8 Alpha support in Media Source
Adding support for playback of VP8 videos with Alpha Channel through the Media Source API. BUG=242357 TEST=VP8 Alpha Streams play properly via Media Source Review URL: https://chromiumcodereview.appspot.com/15342004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@201496 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/base/decoder_buffer.cc20
-rw-r--r--media/base/decoder_buffer.h1
-rw-r--r--media/base/stream_parser_buffer.cc17
-rw-r--r--media/base/stream_parser_buffer.h7
-rw-r--r--media/filters/pipeline_integration_test.cc18
-rw-r--r--media/webm/webm_cluster_parser.cc101
-rw-r--r--media/webm/webm_cluster_parser.h8
-rw-r--r--media/webm/webm_constants.h1
-rw-r--r--media/webm/webm_parser.cc1
-rw-r--r--media/webm/webm_video_client.cc12
-rw-r--r--media/webm/webm_video_client.h1
11 files changed, 133 insertions, 54 deletions
diff --git a/media/base/decoder_buffer.cc b/media/base/decoder_buffer.cc
index aec4521..d3acc26 100644
--- a/media/base/decoder_buffer.cc
+++ b/media/base/decoder_buffer.cc
@@ -15,30 +15,20 @@ DecoderBuffer::DecoderBuffer(int size)
Initialize();
}
-DecoderBuffer::DecoderBuffer(const uint8* data, int size)
- : size_(size),
- side_data_size_(0) {
- if (!data) {
- CHECK_EQ(size_, 0);
- return;
- }
-
- Initialize();
- memcpy(data_.get(), data, size_);
-}
-
DecoderBuffer::DecoderBuffer(const uint8* data, int size,
const uint8* side_data, int side_data_size)
: size_(size),
side_data_size_(side_data_size) {
if (!data) {
CHECK_EQ(size_, 0);
+ CHECK(!side_data);
return;
}
Initialize();
memcpy(data_.get(), data, size_);
- memcpy(side_data_.get(), side_data, side_data_size_);
+ if (side_data)
+ memcpy(side_data_.get(), side_data, side_data_size_);
}
DecoderBuffer::~DecoderBuffer() {}
@@ -60,7 +50,7 @@ scoped_refptr<DecoderBuffer> DecoderBuffer::CopyFrom(const uint8* data,
int data_size) {
// If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
CHECK(data);
- return make_scoped_refptr(new DecoderBuffer(data, data_size));
+ return make_scoped_refptr(new DecoderBuffer(data, data_size, NULL, 0));
}
// static
@@ -77,7 +67,7 @@ scoped_refptr<DecoderBuffer> DecoderBuffer::CopyFrom(const uint8* data,
// static
scoped_refptr<DecoderBuffer> DecoderBuffer::CreateEOSBuffer() {
- return make_scoped_refptr(new DecoderBuffer(NULL, 0));
+ return make_scoped_refptr(new DecoderBuffer(NULL, 0, NULL, 0));
}
base::TimeDelta DecoderBuffer::GetTimestamp() const {
diff --git a/media/base/decoder_buffer.h b/media/base/decoder_buffer.h
index 168ab2c..d1c20dd 100644
--- a/media/base/decoder_buffer.h
+++ b/media/base/decoder_buffer.h
@@ -89,7 +89,6 @@ class MEDIA_EXPORT DecoderBuffer
// Allocates a buffer of size |size| >= 0 and copies |data| into it. Buffer
// will be padded and aligned as necessary. If |data| is NULL then |data_| is
// set to NULL and |buffer_size_| to 0.
- DecoderBuffer(const uint8* data, int size);
DecoderBuffer(const uint8* data, int size,
const uint8* side_data, int side_data_size);
virtual ~DecoderBuffer();
diff --git a/media/base/stream_parser_buffer.cc b/media/base/stream_parser_buffer.cc
index 547cf27..f1dd6fd 100644
--- a/media/base/stream_parser_buffer.cc
+++ b/media/base/stream_parser_buffer.cc
@@ -10,13 +10,21 @@
namespace media {
scoped_refptr<StreamParserBuffer> StreamParserBuffer::CreateEOSBuffer() {
- return make_scoped_refptr(new StreamParserBuffer(NULL, 0, false));
+ return make_scoped_refptr(new StreamParserBuffer(NULL, 0, NULL, 0, false));
}
scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom(
const uint8* data, int data_size, bool is_keyframe) {
return make_scoped_refptr(
- new StreamParserBuffer(data, data_size, is_keyframe));
+ new StreamParserBuffer(data, data_size, NULL, 0, is_keyframe));
+}
+
+scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom(
+ const uint8* data, int data_size,
+ const uint8* side_data, int side_data_size, bool is_keyframe) {
+ return make_scoped_refptr(
+ new StreamParserBuffer(data, data_size, side_data, side_data_size,
+ is_keyframe));
}
base::TimeDelta StreamParserBuffer::GetDecodeTimestamp() const {
@@ -30,8 +38,9 @@ void StreamParserBuffer::SetDecodeTimestamp(const base::TimeDelta& timestamp) {
}
StreamParserBuffer::StreamParserBuffer(const uint8* data, int data_size,
- bool is_keyframe)
- : DecoderBuffer(data, data_size),
+ const uint8* side_data,
+ int side_data_size, bool is_keyframe)
+ : DecoderBuffer(data, data_size, side_data, side_data_size),
is_keyframe_(is_keyframe),
decode_timestamp_(kNoTimestamp()),
config_id_(kInvalidConfigId) {
diff --git a/media/base/stream_parser_buffer.h b/media/base/stream_parser_buffer.h
index 90e4ca9..8899f11 100644
--- a/media/base/stream_parser_buffer.h
+++ b/media/base/stream_parser_buffer.h
@@ -18,6 +18,9 @@ class MEDIA_EXPORT StreamParserBuffer : public DecoderBuffer {
static scoped_refptr<StreamParserBuffer> CreateEOSBuffer();
static scoped_refptr<StreamParserBuffer> CopyFrom(
const uint8* data, int data_size, bool is_keyframe);
+ static scoped_refptr<StreamParserBuffer> CopyFrom(
+ const uint8* data, int data_size,
+ const uint8* side_data, int side_data_size, bool is_keyframe);
bool IsKeyframe() const { return is_keyframe_; }
// Decode timestamp. If not explicitly set, or set to kNoTimestamp(), the
@@ -31,7 +34,9 @@ class MEDIA_EXPORT StreamParserBuffer : public DecoderBuffer {
void SetConfigId(int config_id);
private:
- StreamParserBuffer(const uint8* data, int data_size, bool is_keyframe);
+ StreamParserBuffer(const uint8* data, int data_size,
+ const uint8* side_data, int side_data_size,
+ bool is_keyframe);
virtual ~StreamParserBuffer();
bool is_keyframe_;
diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc
index 63a6892..ccbdd6d 100644
--- a/media/filters/pipeline_integration_test.cc
+++ b/media/filters/pipeline_integration_test.cc
@@ -54,6 +54,7 @@ static const int k640IsoFileDurationMs = 2737;
static const int k640IsoCencFileDurationMs = 2736;
static const int k1280IsoFileDurationMs = 2736;
static const int kVP9WebMFileDurationMs = 2736;
+static const int kVP8AWebMFileDurationMs = 2700;
// Note: Tests using this class only exercise the DecryptingDemuxerStream path.
// They do not exercise the Decrypting{Audio|Video}Decoder path.
@@ -479,6 +480,23 @@ TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VideoOnly_VP9_WebM) {
Stop();
}
+TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_VP8A_WebM) {
+ MockMediaSource source("bear-vp8a.webm", kVideoOnlyWebM, kAppendWholeFile);
+ StartPipelineWithMediaSource(&source);
+ source.EndOfStream();
+
+ EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
+ EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
+ EXPECT_EQ(kVP8AWebMFileDurationMs,
+ pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
+
+ Play();
+
+ ASSERT_TRUE(WaitUntilOnEnded());
+ source.Abort();
+ Stop();
+}
+
TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_WebM) {
MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
kAppendWholeFile);
diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc
index ec89b67..41e193f 100644
--- a/media/webm/webm_cluster_parser.cc
+++ b/media/webm/webm_cluster_parser.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/logging.h"
+#include "base/sys_byteorder.h"
#include "media/base/buffers.h"
#include "media/base/decrypt_config.h"
#include "media/webm/webm_constants.h"
@@ -61,6 +62,8 @@ WebMClusterParser::WebMClusterParser(
last_block_timecode_(-1),
block_data_size_(-1),
block_duration_(-1),
+ block_add_id_(-1),
+ block_additional_data_size_(-1),
cluster_timecode_(-1),
cluster_start_time_(kNoTimestamp()),
cluster_ended_(false),
@@ -134,6 +137,10 @@ WebMParserClient* WebMClusterParser::OnListStart(int id) {
block_data_.reset();
block_data_size_ = -1;
block_duration_ = -1;
+ } else if (id == kWebMIdBlockAdditions) {
+ block_add_id_ = -1;
+ block_additional_data_.reset();
+ block_additional_data_size_ = -1;
}
return this;
@@ -150,30 +157,41 @@ bool WebMClusterParser::OnListEnd(int id) {
}
bool result = ParseBlock(false, block_data_.get(), block_data_size_,
- block_duration_);
+ block_additional_data_.get(),
+ block_additional_data_size_, block_duration_);
block_data_.reset();
block_data_size_ = -1;
block_duration_ = -1;
+ block_add_id_ = -1;
+ block_additional_data_.reset();
+ block_additional_data_size_ = -1;
return result;
}
bool WebMClusterParser::OnUInt(int id, int64 val) {
- if (id == kWebMIdTimecode) {
- if (cluster_timecode_ != -1)
- return false;
-
- cluster_timecode_ = val;
- } else if (id == kWebMIdBlockDuration) {
- if (block_duration_ != -1)
- return false;
- block_duration_ = val;
+ int64* dst;
+ switch (id) {
+ case kWebMIdTimecode:
+ dst = &cluster_timecode_;
+ break;
+ case kWebMIdBlockDuration:
+ dst = &block_duration_;
+ break;
+ case kWebMIdBlockAddID:
+ dst = &block_add_id_;
+ break;
+ default:
+ return true;
}
-
+ if (*dst != -1)
+ return false;
+ *dst = val;
return true;
}
bool WebMClusterParser::ParseBlock(bool is_simple_block, const uint8* buf,
- int size, int duration) {
+ int size, const uint8* additional,
+ int additional_size, int duration) {
if (size < 4)
return false;
@@ -201,32 +219,58 @@ bool WebMClusterParser::ParseBlock(bool is_simple_block, const uint8* buf,
const uint8* frame_data = buf + 4;
int frame_size = size - (frame_data - buf);
return OnBlock(is_simple_block, track_num, timecode, duration, flags,
- frame_data, frame_size);
+ frame_data, frame_size, additional, additional_size);
}
bool WebMClusterParser::OnBinary(int id, const uint8* data, int size) {
- if (id == kWebMIdSimpleBlock)
- return ParseBlock(true, data, size, -1);
-
- if (id != kWebMIdBlock)
- return true;
+ switch (id) {
+ case kWebMIdSimpleBlock:
+ return ParseBlock(true, data, size, NULL, -1, -1);
+
+ case kWebMIdBlock:
+ if (block_data_) {
+ MEDIA_LOG(log_cb_) << "More than 1 Block in a BlockGroup is not "
+ "supported.";
+ return false;
+ }
+ block_data_.reset(new uint8[size]);
+ memcpy(block_data_.get(), data, size);
+ block_data_size_ = size;
+ return true;
+
+ case kWebMIdBlockAdditional: {
+ uint64 block_add_id = base::HostToNet64(block_add_id_);
+ if (block_additional_data_) {
+ // TODO(vigneshv): Technically, more than 1 BlockAdditional is allowed
+ // as per matroska spec. But for now we don't have a use case to
+ // support parsing of such files. Take a look at this again when such a
+ // case arises.
+ MEDIA_LOG(log_cb_) << "More than 1 BlockAdditional in a BlockGroup is "
+ "not supported.";
+ return false;
+ }
+ // First 8 bytes of side_data in DecoderBuffer is the BlockAddID
+ // element's value in Big Endian format. This is done to mimic ffmpeg
+ // demuxer's behavior.
+ block_additional_data_size_ = size + sizeof(block_add_id);
+ block_additional_data_.reset(new uint8[block_additional_data_size_]);
+ memcpy(block_additional_data_.get(), &block_add_id,
+ sizeof(block_add_id));
+ memcpy(block_additional_data_.get() + 8, data, size);
+ return true;
+ }
- if (block_data_) {
- MEDIA_LOG(log_cb_) << "More than 1 Block in a BlockGroup is not supported.";
- return false;
+ default:
+ return true;
}
-
- block_data_.reset(new uint8[size]);
- memcpy(block_data_.get(), data, size);
- block_data_size_ = size;
- return true;
}
bool WebMClusterParser::OnBlock(bool is_simple_block, int track_num,
int timecode,
int block_duration,
int flags,
- const uint8* data, int size) {
+ const uint8* data, int size,
+ const uint8* additional, int additional_size) {
DCHECK_GE(size, 0);
if (cluster_timecode_ == -1) {
MEDIA_LOG(log_cb_) << "Got a block before cluster timecode.";
@@ -279,7 +323,8 @@ bool WebMClusterParser::OnBlock(bool is_simple_block, int track_num,
is_simple_block ? (flags & 0x80) != 0 : track->IsKeyframe(data, size);
scoped_refptr<StreamParserBuffer> buffer =
- StreamParserBuffer::CopyFrom(data, size, is_keyframe);
+ StreamParserBuffer::CopyFrom(data, size, additional, additional_size,
+ is_keyframe);
// Every encrypted Block has a signal byte and IV prepended to it. Current
// encrypted WebM request for comments specification is here
diff --git a/media/webm/webm_cluster_parser.h b/media/webm/webm_cluster_parser.h
index 63d8626..e156d47 100644
--- a/media/webm/webm_cluster_parser.h
+++ b/media/webm/webm_cluster_parser.h
@@ -110,9 +110,10 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
virtual bool OnBinary(int id, const uint8* data, int size) OVERRIDE;
bool ParseBlock(bool is_simple_block, const uint8* buf, int size,
- int duration);
+ const uint8* additional, int additional_size, int duration);
bool OnBlock(bool is_simple_block, int track_num, int timecode, int duration,
- int flags, const uint8* data, int size);
+ int flags, const uint8* data, int size,
+ const uint8* additional, int additional_size);
// Resets the Track objects associated with each text track.
void ResetTextTracks();
@@ -133,6 +134,9 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
scoped_ptr<uint8[]> block_data_;
int block_data_size_;
int64 block_duration_;
+ int64 block_add_id_;
+ scoped_ptr<uint8[]> block_additional_data_;
+ int block_additional_data_size_;
int64 cluster_timecode_;
base::TimeDelta cluster_start_time_;
diff --git a/media/webm/webm_constants.h b/media/webm/webm_constants.h
index 5cfd5e6..cda45e0 100644
--- a/media/webm/webm_constants.h
+++ b/media/webm/webm_constants.h
@@ -14,6 +14,7 @@ namespace media {
// This is a subset of the IDs in the Matroska spec.
// http://www.matroska.org/technical/specs/index.html
const int kWebMIdAESSettingsCipherMode = 0x47E8;
+const int kWebMIdAlphaMode = 0x53C0;
const int kWebMIdAspectRatioType = 0x54B3;
const int kWebMIdAttachedFile = 0x61A7;
const int kWebMIdAttachmentLink = 0x7446;
diff --git a/media/webm/webm_parser.cc b/media/webm/webm_parser.cc
index fb9f899..30e5c1b5 100644
--- a/media/webm/webm_parser.cc
+++ b/media/webm/webm_parser.cc
@@ -179,6 +179,7 @@ static const ElementIdInfo kTrackTranslateIds[] = {
static const ElementIdInfo kVideoIds[] = {
{UINT, kWebMIdFlagInterlaced},
{UINT, kWebMIdStereoMode},
+ {UINT, kWebMIdAlphaMode},
{UINT, kWebMIdPixelWidth},
{UINT, kWebMIdPixelHeight},
{UINT, kWebMIdPixelCropBottom},
diff --git a/media/webm/webm_video_client.cc b/media/webm/webm_video_client.cc
index b4e729e..1d0cbcb 100644
--- a/media/webm/webm_video_client.cc
+++ b/media/webm/webm_video_client.cc
@@ -27,6 +27,7 @@ void WebMVideoClient::Reset() {
display_width_ = -1;
display_height_ = -1;
display_unit_ = -1;
+ alpha_mode_ = -1;
}
bool WebMVideoClient::InitializeConfig(
@@ -47,6 +48,9 @@ bool WebMVideoClient::InitializeConfig(
return false;
}
+ VideoFrame::Format format =
+ (alpha_mode_ == 1) ? VideoFrame::YV12A : VideoFrame::YV12;
+
if (pixel_width_ <= 0 || pixel_height_ <= 0)
return false;
@@ -93,9 +97,8 @@ bool WebMVideoClient::InitializeConfig(
}
config->Initialize(
- video_codec, profile, VideoFrame::YV12, coded_size,
- visible_rect, natural_size, extra_data, extra_data_size,
- is_encrypted, true);
+ video_codec, profile, format, coded_size, visible_rect, natural_size,
+ extra_data, extra_data_size, is_encrypted, true);
return config->IsValidConfig();
}
@@ -130,6 +133,9 @@ bool WebMVideoClient::OnUInt(int id, int64 val) {
case kWebMIdDisplayUnit:
dst = &display_unit_;
break;
+ case kWebMIdAlphaMode:
+ dst = &alpha_mode_;
+ break;
default:
return true;
}
diff --git a/media/webm/webm_video_client.h b/media/webm/webm_video_client.h
index eb6be6d..d1872ba 100644
--- a/media/webm/webm_video_client.h
+++ b/media/webm/webm_video_client.h
@@ -51,6 +51,7 @@ class WebMVideoClient : public WebMParserClient {
int64 display_width_;
int64 display_height_;
int64 display_unit_;
+ int64 alpha_mode_;
DISALLOW_COPY_AND_ASSIGN(WebMVideoClient);
};