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*>(×tamp_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*>(×tamp_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 |