| Index: media/filters/vpx_video_decoder.cc
|
| diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc
|
| index e270335504a523131f55f0f05325f98eeb79806d..25e6314275616e9543e693e0b41c3767bf813e16 100644
|
| --- a/media/filters/vpx_video_decoder.cc
|
| +++ b/media/filters/vpx_video_decoder.cc
|
| @@ -30,6 +30,7 @@
|
| #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/vpx_external_frame_buffer.h"
|
| #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
|
| }
|
|
|
| @@ -73,7 +74,8 @@ VpxVideoDecoder::VpxVideoDecoder(
|
| weak_factory_(this),
|
| state_(kUninitialized),
|
| vpx_codec_(NULL),
|
| - vpx_codec_alpha_(NULL) {
|
| + vpx_codec_alpha_(NULL),
|
| + frame_buffers_(NULL) {
|
| }
|
|
|
| VpxVideoDecoder::~VpxVideoDecoder() {
|
| @@ -124,6 +126,21 @@ static vpx_codec_ctx* InitializeVpxContext(vpx_codec_ctx* context,
|
| return context;
|
| }
|
|
|
| +int32 VpxVideoDecoder::ReallocVP9FrameBuffer(void *user_priv, size_t new_size,
|
| + vpx_codec_frame_buffer *fb) {
|
| + if (!fb)
|
| + return -1;
|
| + if (fb->data)
|
| + delete[] fb->data;
|
| + fb->data = new uint8[new_size];
|
| + if (!fb->data) {
|
| + fb->size = 0;
|
| + return -1;
|
| + }
|
| + fb->size = new_size;
|
| + return VPX_CODEC_OK;
|
| +}
|
| +
|
| bool VpxVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config) {
|
| const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
|
| bool can_handle = false;
|
| @@ -142,6 +159,21 @@ bool VpxVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config) {
|
| if (!vpx_codec_)
|
| return false;
|
|
|
| + // We use our own buffers for VP9 so that there is no need to copy data after
|
| + // decoding.
|
| + if (config.codec() == kCodecVP9 &&
|
| + VPX_DECODER_ABI_VERSION >= kVP9MinABIVersion) {
|
| + frame_buffers_ = new vpx_codec_frame_buffer[kVP9MaxFrameBuffers]();
|
| + if (vpx_codec_set_frame_buffers(vpx_codec_,
|
| + frame_buffers_,
|
| + kVP9MaxFrameBuffers,
|
| + VpxVideoDecoder::ReallocVP9FrameBuffer,
|
| + NULL)) {
|
| + LOG(ERROR) << "Failed to configure external buffers.";
|
| + return false;
|
| + }
|
| + }
|
| +
|
| if (config.format() == VideoFrame::YV12A) {
|
| vpx_codec_alpha_ = InitializeVpxContext(vpx_codec_alpha_, config);
|
| if (!vpx_codec_alpha_)
|
| @@ -156,6 +188,12 @@ void VpxVideoDecoder::CloseDecoder() {
|
| vpx_codec_destroy(vpx_codec_);
|
| delete vpx_codec_;
|
| vpx_codec_ = NULL;
|
| + if (frame_buffers_) {
|
| + for (int i = 0; i < kVP9MaxFrameBuffers; i++)
|
| + delete[] frame_buffers_[i].data;
|
| + delete[] frame_buffers_;
|
| + frame_buffers_ = NULL;
|
| + }
|
| }
|
| if (vpx_codec_alpha_) {
|
| vpx_codec_destroy(vpx_codec_alpha_);
|
| @@ -342,6 +380,21 @@ void VpxVideoDecoder::CopyVpxImageTo(const vpx_image* vpx_image,
|
|
|
| gfx::Size size(vpx_image->d_w, vpx_image->d_h);
|
|
|
| + if (!vpx_codec_alpha_ && VPX_DECODER_ABI_VERSION >= kVP9MinABIVersion) {
|
| + *video_frame = VideoFrame::WrapExternalYuvData(
|
| + VideoFrame::YV12,
|
| + size, gfx::Rect(size), config_.natural_size(),
|
| + vpx_image->stride[VPX_PLANE_Y],
|
| + vpx_image->stride[VPX_PLANE_U],
|
| + vpx_image->stride[VPX_PLANE_V],
|
| + vpx_image->planes[VPX_PLANE_Y],
|
| + vpx_image->planes[VPX_PLANE_U],
|
| + vpx_image->planes[VPX_PLANE_V],
|
| + kNoTimestamp(),
|
| + base::Closure());
|
| + return;
|
| + }
|
| +
|
| *video_frame = frame_pool_.CreateFrame(
|
| vpx_codec_alpha_ ? VideoFrame::YV12A : VideoFrame::YV12,
|
| size,
|
| @@ -361,8 +414,6 @@ void VpxVideoDecoder::CopyVpxImageTo(const vpx_image* vpx_image,
|
| vpx_image->stride[VPX_PLANE_V],
|
| (vpx_image->d_h + 1) / 2,
|
| video_frame->get());
|
| - if (!vpx_codec_alpha_)
|
| - return;
|
| if (!vpx_image_alpha) {
|
| MakeOpaqueAPlane(
|
| vpx_image->stride[VPX_PLANE_Y], vpx_image->d_h, video_frame->get());
|
|
|