diff options
author | vigneshv@chromium.org <vigneshv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-22 12:43:22 +0000 |
---|---|---|
committer | vigneshv@chromium.org <vigneshv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-22 12:43:22 +0000 |
commit | 05e78a90a52f8af3b66b4991f67684d008abc6de (patch) | |
tree | 56eae3a56c831d2bd41cb23eb20e349640983bc9 /media | |
parent | e70d98d66f19052f5abf3324f7094a2206887ba2 (diff) | |
download | chromium_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.cc | 20 | ||||
-rw-r--r-- | media/base/decoder_buffer.h | 1 | ||||
-rw-r--r-- | media/base/stream_parser_buffer.cc | 17 | ||||
-rw-r--r-- | media/base/stream_parser_buffer.h | 7 | ||||
-rw-r--r-- | media/filters/pipeline_integration_test.cc | 18 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser.cc | 101 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser.h | 8 | ||||
-rw-r--r-- | media/webm/webm_constants.h | 1 | ||||
-rw-r--r-- | media/webm/webm_parser.cc | 1 | ||||
-rw-r--r-- | media/webm/webm_video_client.cc | 12 | ||||
-rw-r--r-- | media/webm/webm_video_client.h | 1 |
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); }; |