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

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: rebase Created 7 years, 8 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
« no previous file with comments | « media/filters/vpx_video_decoder.h ('k') | media/media.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..76054eb1cbd26dd087782f94c606c9f119c4280e 100644
--- a/media/filters/vpx_video_decoder.cc
+++ b/media/filters/vpx_video_decoder.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/message_loop_proxy.h"
#include "base/string_number_conversions.h"
+#include "base/sys_byteorder.h"
#include "media/base/bind_to_loop.h"
#include "media/base/decoder_buffer.h"
#include "media/base/demuxer_stream.h"
@@ -20,15 +21,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 +50,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,45 +82,60 @@ void VpxVideoDecoder::Initialize(
status_cb.Run(PIPELINE_OK);
}
-bool VpxVideoDecoder::ConfigureDecoder() {
- const VideoDecoderConfig& config = demuxer_stream_->video_decoder_config();
- if (!config.IsValidConfig()) {
- DLOG(ERROR) << "Invalid video stream config: "
- << config.AsHumanReadableString();
- return false;
- }
-
- if (config.codec() != kCodecVP9)
- return false;
-
- CloseDecoder();
-
- vpx_codec_ = new vpx_codec_ctx();
+static scoped_ptr<vpx_codec_ctx, VpxDeleter> InitializeVpxContext(
+ scoped_ptr<vpx_codec_ctx, VpxDeleter> context,
+ const VideoDecoderConfig& config) {
+ 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();
- vpx_codec_err_t status = vpx_codec_dec_init(vpx_codec_,
- vpx_codec_vp9_dx(),
+ vpx_codec_err_t status = vpx_codec_dec_init(context.get(),
+ config.codec() == kCodecVP9 ?
+ vpx_codec_vp9_dx() :
+ vpx_codec_vp8_dx(),
&vpx_config,
0);
if (status != VPX_CODEC_OK) {
LOG(ERROR) << "vpx_codec_dec_init failed, status=" << status;
- delete vpx_codec_;
- vpx_codec_ = NULL;
+ context.reset();
+ }
+ return context.Pass();
+}
+
+bool VpxVideoDecoder::ConfigureDecoder() {
+ const VideoDecoderConfig& config = demuxer_stream_->video_decoder_config();
+ if (!config.IsValidConfig()) {
+ DLOG(ERROR) << "Invalid video stream config: "
+ << config.AsHumanReadableString();
return false;
}
- return true;
-}
+ 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;
+
+ vpx_codec_ = InitializeVpxContext(vpx_codec_.Pass(), config);
+ if (!vpx_codec_.get())
+ return false;
-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);
+ if (!vpx_codec_alpha_.get())
+ return false;
}
+
+ return true;
}
void VpxVideoDecoder::Read(const ReadCB& read_cb) {
@@ -246,7 +251,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 +275,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 +287,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 +298,45 @@ bool VpxVideoDecoder::Decode(
return false;
}
- CopyVpxImageTo(vpx_image, video_frame);
+ const vpx_image_t* vpx_image_alpha = NULL;
+ if (vpx_codec_alpha_.get() && buffer->GetSideDataSize() >= 8) {
+ // Pass alpha data to libvpx.
+ int64 timestamp_alpha = buffer->GetTimestamp().InMicroseconds();
+ void* user_priv_alpha = reinterpret_cast<void*>(&timestamp_alpha);
+
+ // First 8 bytes of side data is side_data_id in big endian.
+ const uint64 side_data_id = base::NetToHost64(
+ *(reinterpret_cast<const uint64*>(buffer->GetSideData())));
+ 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 +350,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 +363,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 +383,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
« no previous file with comments | « media/filters/vpx_video_decoder.h ('k') | media/media.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698