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

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: addressing comments on patchset 5 Created 7 years, 9 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..9b7a986942b1d18937df6e329d90d9da7d942486 100644
--- a/media/filters/vpx_video_decoder.cc
+++ b/media/filters/vpx_video_decoder.cc
@@ -20,15 +20,6 @@
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
-// Include libvpx header files.
-// VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide
-// backwards compatibility for legacy applications using the library.
-#define VPX_CODEC_DISABLE_COMPAT 1
-extern "C" {
-#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h"
-#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
-}
-
namespace media {
// Always try to use three threads for video decoding. There is little reason
@@ -58,13 +49,11 @@ static int GetThreadCount() {
VpxVideoDecoder::VpxVideoDecoder(
const scoped_refptr<base::MessageLoopProxy>& message_loop)
: message_loop_(message_loop),
- state_(kUninitialized),
- vpx_codec_(NULL) {
+ state_(kUninitialized) {
}
VpxVideoDecoder::~VpxVideoDecoder() {
DCHECK_EQ(kUninitialized, state_);
- CloseDecoder();
}
void VpxVideoDecoder::Initialize(
@@ -92,6 +81,25 @@ void VpxVideoDecoder::Initialize(
status_cb.Run(PIPELINE_OK);
}
+scoped_ptr<vpx_codec_ctx, VpxDeleter> InitializeVpxContext(
scherkus (not reviewing) 2013/04/04 22:54:00 should be static
vignesh 2013/04/05 19:06:58 Done.
+ scoped_ptr<vpx_codec_ctx, VpxDeleter> context,
+ const VideoDecoderConfig& config,
+ vpx_codec_err_t* status) {
scherkus (not reviewing) 2013/04/04 22:54:00 how about LOG(ERROR) the status code inside this f
vignesh 2013/04/05 19:06:58 Done.
+ context.reset(new vpx_codec_ctx());
+ vpx_codec_dec_cfg_t vpx_config = {0};
+ vpx_config.w = config.coded_size().width();
+ vpx_config.h = config.coded_size().height();
+ vpx_config.threads = GetThreadCount();
+
+ *status = vpx_codec_dec_init(context.get(),
+ config.codec() == kCodecVP9 ?
+ vpx_codec_vp9_dx() :
+ vpx_codec_vp8_dx(),
+ &vpx_config,
+ 0);
+ return context.Pass();
+}
+
bool VpxVideoDecoder::ConfigureDecoder() {
const VideoDecoderConfig& config = demuxer_stream_->video_decoder_config();
if (!config.IsValidConfig()) {
@@ -100,37 +108,36 @@ bool VpxVideoDecoder::ConfigureDecoder() {
return false;
}
- if (config.codec() != kCodecVP9)
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ bool can_handle = false;
+ if (cmd_line->HasSwitch(switches::kEnableVp9Playback) &&
+ config.codec() == kCodecVP9) {
+ can_handle = true;
+ }
+ if (cmd_line->HasSwitch(switches::kEnableVp8AlphaPlayback) &&
+ config.codec() == kCodecVP8 && config.format() == VideoFrame::YV12A) {
+ can_handle = true;
+ }
+ if (!can_handle)
return false;
- CloseDecoder();
-
- vpx_codec_ = new vpx_codec_ctx();
- vpx_codec_dec_cfg_t vpx_config = {0};
- vpx_config.w = config.coded_size().width();
- vpx_config.h = config.coded_size().height();
- vpx_config.threads = GetThreadCount();
-
- vpx_codec_err_t status = vpx_codec_dec_init(vpx_codec_,
- vpx_codec_vp9_dx(),
- &vpx_config,
- 0);
+ vpx_codec_err_t status;
+ vpx_codec_ = InitializeVpxContext(vpx_codec_.Pass(), config, &status);
if (status != VPX_CODEC_OK) {
LOG(ERROR) << "vpx_codec_dec_init failed, status=" << status;
- delete vpx_codec_;
- vpx_codec_ = NULL;
return false;
}
- return true;
-}
-
-void VpxVideoDecoder::CloseDecoder() {
- if (vpx_codec_) {
- vpx_codec_destroy(vpx_codec_);
- delete vpx_codec_;
- vpx_codec_ = NULL;
+ if (config.format() == VideoFrame::YV12A) {
+ vpx_codec_alpha_ = InitializeVpxContext(vpx_codec_alpha_.Pass(), config,
+ &status);
+ if (status != VPX_CODEC_OK) {
+ LOG(ERROR) << "vpx_codec_dec_init failed, status=" << status;
+ return false;
+ }
}
+
+ return true;
}
void VpxVideoDecoder::Read(const ReadCB& read_cb) {
@@ -246,7 +253,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);
@@ -270,7 +277,7 @@ bool VpxVideoDecoder::Decode(
// Pass |buffer| to libvpx.
int64 timestamp = buffer->GetTimestamp().InMicroseconds();
void* user_priv = reinterpret_cast<void*>(&timestamp);
- vpx_codec_err_t status = vpx_codec_decode(vpx_codec_,
+ vpx_codec_err_t status = vpx_codec_decode(vpx_codec_.get(),
buffer->GetData(),
buffer->GetDataSize(),
user_priv,
@@ -282,7 +289,7 @@ bool VpxVideoDecoder::Decode(
// Gets pointer to decoded data.
vpx_codec_iter_t iter = NULL;
- const vpx_image_t* vpx_image = vpx_codec_get_frame(vpx_codec_, &iter);
+ const vpx_image_t* vpx_image = vpx_codec_get_frame(vpx_codec_.get(), &iter);
if (!vpx_image) {
*video_frame = NULL;
return true;
@@ -293,7 +300,49 @@ bool VpxVideoDecoder::Decode(
return false;
}
- CopyVpxImageTo(vpx_image, video_frame);
+ const vpx_image_t* vpx_image_alpha = NULL;
+ if (vpx_codec_alpha_.get()) {
+ // 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();
+
+ // First 8 bytes of side data is side_data_id in big endian.
scherkus (not reviewing) 2013/04/04 22:54:00 I think you can use base/sys_byteorder.h uint64 s
vignesh 2013/04/05 19:06:58 Thanks :) Done.
+ uint64_t side_data_id = side_data_id_buf[0];
scherkus (not reviewing) 2013/04/04 22:54:00 nit: drop the _t suffix -- chromium code uses uint
vignesh 2013/04/05 19:06:58 Done.
+ for (size_t i = 1; i < 8; ++i) {
+ side_data_id <<= 8;
+ side_data_id |= side_data_id_buf[i];
scherkus (not reviewing) 2013/04/04 22:54:00 right now the code always assumes GetData() is non
vignesh 2013/04/05 19:06:58 Done.
+ }
+ if (side_data_id == 1) {
+ status = vpx_codec_decode(vpx_codec_alpha_.get(),
+ buffer->GetSideData() + 8,
+ 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_.get(),
+ &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 +356,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 +369,14 @@ void VpxVideoDecoder::CopyVpxImageTo(
gfx::Size natural_size =
demuxer_stream_->video_decoder_config().natural_size();
- *video_frame = VideoFrame::CreateFrame(VideoFrame::YV12,
+ *video_frame = VideoFrame::CreateFrame(vpx_codec_alpha_.get() ?
+ VideoFrame::YV12A :
+ VideoFrame::YV12,
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 +389,17 @@ void VpxVideoDecoder::CopyVpxImageTo(
vpx_image->stride[VPX_PLANE_V],
vpx_image->d_h / 2,
*video_frame);
+ if (!vpx_codec_alpha_.get())
+ return;
+ if (!vpx_image_alpha) {
+ MakeOpaqueAPlane(vpx_image->stride[VPX_PLANE_Y], vpx_image->d_h,
+ *video_frame);
+ return;
+ }
+ CopyAPlane(vpx_image_alpha->planes[VPX_PLANE_Y],
+ vpx_image->stride[VPX_PLANE_Y],
+ vpx_image->d_h,
+ *video_frame);
}
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698