Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1395)

Unified Diff: media/filters/vpx_video_decoder.cc

Issue 12263013: media: Add support for playback of VP8 Alpha video streams (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: minor fixes Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/filters/vpx_video_decoder.cc
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc
index 0b92a7d8459c4e152bbd7261b56ce7dcc1c32ffe..8616007fc2ed9c6d90b2ba2f1cbe73c0e53b669c 100644
--- a/media/filters/vpx_video_decoder.cc
+++ b/media/filters/vpx_video_decoder.cc
@@ -59,7 +59,8 @@ VpxVideoDecoder::VpxVideoDecoder(
const scoped_refptr<base::MessageLoopProxy>& message_loop)
: message_loop_(message_loop),
state_(kUninitialized),
- vpx_codec_(NULL) {
+ vpx_codec_(NULL),
+ vpx_codec_alpha_(NULL) {
}
VpxVideoDecoder::~VpxVideoDecoder() {
@@ -100,8 +101,19 @@ bool VpxVideoDecoder::ConfigureDecoder() {
return false;
}
- if (config.codec() != kCodecVP9)
- return false;
+ format_ = config.format();
scherkus (not reviewing) 2013/02/22 23:18:01 it looks like the only reason for storing format_
vignesh 2013/02/25 21:51:42 Done.
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ bool can_handle = false;
+ if (cmd_line->HasSwitch(switches::kEnableVp9Playback) &&
+ config.codec() == kCodecVP9) {
+ can_handle = true;
scherkus (not reviewing) 2013/02/22 23:18:01 de-indent by 2
vignesh 2013/02/25 21:51:42 Done.
+ }
+ if (cmd_line->HasSwitch(switches::kEnableVp8AlphaPlayback) &&
+ config.codec() == kCodecVP8 && format_ == VideoFrame::YV12A) {
+ can_handle = true;
+ }
+ if (!can_handle)
+ return false;
scherkus (not reviewing) 2013/02/22 23:18:01 de-indent by 2
vignesh 2013/02/25 21:51:42 Done.
CloseDecoder();
@@ -112,7 +124,9 @@ bool VpxVideoDecoder::ConfigureDecoder() {
vpx_config.threads = GetThreadCount();
vpx_codec_err_t status = vpx_codec_dec_init(vpx_codec_,
- vpx_codec_vp9_dx(),
+ config.codec() == kCodecVP9 ?
+ vpx_codec_vp9_dx() :
+ vpx_codec_vp8_dx(),
&vpx_config,
0);
if (status != VPX_CODEC_OK) {
@@ -122,6 +136,26 @@ bool VpxVideoDecoder::ConfigureDecoder() {
return false;
}
+ if(format_ == VideoFrame::YV12A) {
scherkus (not reviewing) 2013/02/22 23:18:01 add space between if and (
vignesh 2013/02/25 21:51:42 Done.
+ vpx_codec_alpha_ = new vpx_codec_ctx();
+ vpx_codec_dec_cfg_t vpx_config_alpha = {0};
+
+ vpx_config_alpha.w = config.coded_size().width();
+ vpx_config_alpha.h = config.coded_size().height();
+ vpx_config_alpha.threads = GetThreadCount();
+
+ status = vpx_codec_dec_init(vpx_codec_alpha_,
+ vpx_codec_vp8_dx(),
+ &vpx_config_alpha,
+ 0);
+ if (status != VPX_CODEC_OK) {
+ LOG(ERROR) << "vpx_codec_dec_init failed, status=" << status;
+ delete vpx_codec_alpha_;
+ vpx_codec_alpha_ = NULL;
+ return false;
+ }
+ }
+
return true;
}
@@ -131,6 +165,11 @@ void VpxVideoDecoder::CloseDecoder() {
delete vpx_codec_;
vpx_codec_ = NULL;
}
+ if (vpx_codec_alpha_) {
+ vpx_codec_destroy(vpx_codec_alpha_);
+ delete vpx_codec_alpha_;
+ vpx_codec_alpha_ = NULL;
+ }
}
void VpxVideoDecoder::Read(const ReadCB& read_cb) {
@@ -246,7 +285,7 @@ void VpxVideoDecoder::DecodeBuffer(
}
// Any successful decode counts!
- if (buffer->GetDataSize()) {
+ if (buffer->GetDataSize() && buffer->GetSideDataSize()) {
PipelineStatistics statistics;
statistics.video_bytes_decoded = buffer->GetDataSize();
statistics_cb_.Run(statistics);
@@ -293,7 +332,47 @@ bool VpxVideoDecoder::Decode(
return false;
}
- CopyVpxImageTo(vpx_image, video_frame);
+ const vpx_image_t* vpx_image_alpha = NULL;
+ if(format_ == VideoFrame::YV12A) {
scherkus (not reviewing) 2013/02/22 23:18:01 add space between if and (
vignesh 2013/02/25 21:51:42 Done.
+
scherkus (not reviewing) 2013/02/22 23:18:01 nit: remove extra blank line
vignesh 2013/02/25 21:51:42 Done.
+ // Pass alpha data to libvpx.
+ int64 timestamp_alpha = buffer->GetTimestamp().InMicroseconds();
+ void* user_priv_alpha = reinterpret_cast<void*>(&timestamp_alpha);
+ const uint8* side_data_id_buf = buffer->GetSideData();
+ uint64_t side_data_id = side_data_id_buf[0];
+ for (size_t i = 1; i < 8; ++i) {
scherkus (not reviewing) 2013/02/22 23:18:01 what's all this stuff doing?
vignesh 2013/02/25 21:51:42 first 8 bytes of side_data is side_data_id in big
+ side_data_id <<= 8;
+ side_data_id |= side_data_id_buf[i];
+ }
+ if (side_data_id == 1) {
+ status = vpx_codec_decode(vpx_codec_alpha_,
+ buffer->GetSideData() + 8,
scherkus (not reviewing) 2013/02/22 23:18:01 what's the magic +8 for?
vignesh 2013/02/25 21:51:42 first 8 bytes of side_data is side_data_id and the
+ buffer->GetSideDataSize() - 8,
+ user_priv_alpha,
+ 0);
+
+ if (status != VPX_CODEC_OK) {
+ LOG(ERROR) << "vpx_codec_decode() failed on alpha, status=" << status;
+ return false;
+ }
+
+ // Gets pointer to decoded data.
+ vpx_codec_iter_t iter_alpha = NULL;
+ vpx_image_alpha = vpx_codec_get_frame(vpx_codec_alpha_, &iter_alpha);
+ if (!vpx_image_alpha) {
+ *video_frame = NULL;
+ return true;
+ }
+
+ if (vpx_image_alpha->user_priv !=
+ reinterpret_cast<void*>(&timestamp_alpha)) {
+ LOG(ERROR) << "Invalid output timestamp on alpha.";
+ return false;
+ }
+ }
+ }
+
+ CopyVpxImageTo(vpx_image, vpx_image_alpha, video_frame);
(*video_frame)->SetTimestamp(base::TimeDelta::FromMicroseconds(timestamp));
return true;
}
@@ -307,7 +386,8 @@ void VpxVideoDecoder::DoReset() {
}
void VpxVideoDecoder::CopyVpxImageTo(
- const vpx_image* vpx_image,
+ const struct vpx_image* vpx_image,
+ const struct vpx_image* vpx_image_alpha,
scoped_refptr<VideoFrame>* video_frame) {
CHECK(vpx_image);
CHECK_EQ(vpx_image->d_w % 2, 0U);
@@ -319,11 +399,12 @@ void VpxVideoDecoder::CopyVpxImageTo(
gfx::Size natural_size =
demuxer_stream_->video_decoder_config().natural_size();
- *video_frame = VideoFrame::CreateFrame(VideoFrame::YV12,
+ *video_frame = VideoFrame::CreateFrame(format_,
size,
gfx::Rect(size),
natural_size,
kNoTimestamp());
+
CopyYPlane(vpx_image->planes[VPX_PLANE_Y],
vpx_image->stride[VPX_PLANE_Y],
vpx_image->d_h,
@@ -336,6 +417,26 @@ void VpxVideoDecoder::CopyVpxImageTo(
vpx_image->stride[VPX_PLANE_V],
vpx_image->d_h / 2,
*video_frame);
+ if(format_ == VideoFrame::YV12A) {
scherkus (not reviewing) 2013/02/22 23:18:01 add space between if and (
vignesh 2013/02/25 21:51:42 Done.
+ if(vpx_image_alpha) {
scherkus (not reviewing) 2013/02/22 23:18:01 are we guaranteed to always produce an alpha image
vignesh 2013/02/25 21:51:42 yes. because there could be video files with no al
+ CopyAPlane(vpx_image_alpha->planes[VPX_PLANE_Y],
+ vpx_image->stride[VPX_PLANE_Y],
+ vpx_image->d_h,
+ *video_frame);
+ } else {
+ /* there is no alpha. set it to opaque */
scherkus (not reviewing) 2013/02/22 23:18:01 use // for comments
vignesh 2013/02/25 21:51:42 Done.
+ uint64_t alpha_plane_size = vpx_image->stride[VPX_PLANE_Y] *
+ vpx_image->d_h;
+ unsigned char* alpha_plane = static_cast<unsigned char*>(
+ malloc(alpha_plane_size));
scherkus (not reviewing) 2013/02/22 23:18:01 this seems a bit silly: we're allocating a frame,
vignesh 2013/02/25 21:51:42 Adding a ClearAPlane function. Although, the notio
+ memset(alpha_plane, 255, alpha_plane_size);
+ CopyAPlane(alpha_plane,
+ vpx_image->stride[VPX_PLANE_Y],
+ vpx_image->d_h,
+ *video_frame);
+ free(alpha_plane);
+ }
+ }
}
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698