Index: media/filters/vpx_video_decoder.cc |
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc |
index 2d60d917a43d1855ee1226ac0c74dcf726002e30..437187ba4d979c493d6056b539dea5ab833352fa 100644 |
--- a/media/filters/vpx_video_decoder.cc |
+++ b/media/filters/vpx_video_decoder.cc |
@@ -33,6 +33,7 @@ |
#include "media/base/bind_to_current_loop.h" |
#include "media/base/decoder_buffer.h" |
#include "media/base/media_switches.h" |
+#include "media/video/gpu_memory_buffer_video_frame_pool.h" |
// Include libvpx header files. |
// VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide |
@@ -358,7 +359,14 @@ void VpxVideoDecoder::MemoryPool::OnVideoFrameDestroyed( |
} |
VpxVideoDecoder::VpxVideoDecoder() |
- : state_(kUninitialized), vpx_codec_(nullptr), vpx_codec_alpha_(nullptr) { |
+ : VpxVideoDecoder(std::unique_ptr<GpuMemoryBufferVideoFramePool>()) {} |
+ |
+VpxVideoDecoder::VpxVideoDecoder( |
+ std::unique_ptr<GpuMemoryBufferVideoFramePool> gpu_video_frame_pool) |
+ : state_(kUninitialized), |
+ vpx_codec_(nullptr), |
+ vpx_codec_alpha_(nullptr), |
+ gpu_video_frame_pool_(std::move(gpu_video_frame_pool)) { |
thread_checker_.DetachFromThread(); |
} |
@@ -570,9 +578,13 @@ bool VpxVideoDecoder::VpxDecode(const scoped_refptr<DecoderBuffer>& buffer, |
return false; |
} |
- if (!CopyVpxImageToVideoFrame(vpx_image, video_frame)) |
+ if (!CopyVpxImageToVideoFrame(vpx_image, buffer, video_frame)) |
return false; |
+ // VP8 alpha vpx_image_t is missing. Regard it as success. |
+ if (!(*video_frame)) |
+ return true; |
+ |
(*video_frame)->set_timestamp(base::TimeDelta::FromMicroseconds(timestamp)); |
// Default to the color space from the config, but if the bistream specifies |
@@ -586,74 +598,12 @@ bool VpxVideoDecoder::VpxDecode(const scoped_refptr<DecoderBuffer>& buffer, |
->metadata() |
->SetInteger(VideoFrameMetadata::COLOR_SPACE, color_space); |
- if (!vpx_codec_alpha_) |
- return true; |
- |
- if (buffer->side_data_size() < 8) { |
- // TODO(mcasas): Is this a warning or an error? |
- DLOG(WARNING) << "Making Alpha channel opaque due to missing input"; |
- const uint32_t kAlphaOpaqueValue = 255; |
- libyuv::SetPlane((*video_frame)->visible_data(VideoFrame::kAPlane), |
- (*video_frame)->stride(VideoFrame::kAPlane), |
- (*video_frame)->visible_rect().width(), |
- (*video_frame)->visible_rect().height(), |
- kAlphaOpaqueValue); |
- return true; |
- } |
- |
- // First 8 bytes of side data is |side_data_id| in big endian. |
- const uint64_t side_data_id = base::NetToHost64( |
- *(reinterpret_cast<const uint64_t*>(buffer->side_data()))); |
- if (side_data_id != 1) |
- return true; |
- |
- // Try and decode buffer->side_data() minus the first 8 bytes as a full frame. |
- int64_t timestamp_alpha = buffer->timestamp().InMicroseconds(); |
- void* user_priv_alpha = reinterpret_cast<void*>(×tamp_alpha); |
- { |
- TRACE_EVENT1("media", "vpx_codec_decode_alpha", "timestamp_alpha", |
- timestamp_alpha); |
- vpx_codec_err_t status = vpx_codec_decode( |
- vpx_codec_alpha_, buffer->side_data() + 8, buffer->side_data_size() - 8, |
- user_priv_alpha, 0 /* deadline */); |
- if (status != VPX_CODEC_OK) { |
- DLOG(ERROR) << "vpx_codec_decode() failed for the alpha: " |
- << vpx_codec_error(vpx_codec_); |
- return false; |
- } |
- } |
- |
- vpx_codec_iter_t iter_alpha = NULL; |
- const vpx_image_t* vpx_image_alpha = |
- vpx_codec_get_frame(vpx_codec_alpha_, &iter_alpha); |
- if (!vpx_image_alpha) { |
- *video_frame = nullptr; |
- return true; |
- } |
- |
- if (vpx_image_alpha->user_priv != user_priv_alpha) { |
- DLOG(ERROR) << "Invalid output timestamp on alpha."; |
- return false; |
- } |
- |
- if (vpx_image_alpha->d_h != vpx_image->d_h || |
- vpx_image_alpha->d_w != vpx_image->d_w) { |
- DLOG(ERROR) << "The alpha plane dimensions are not the same as the " |
- "image dimensions."; |
- return false; |
- } |
- |
- libyuv::CopyPlane(vpx_image_alpha->planes[VPX_PLANE_Y], |
- vpx_image_alpha->stride[VPX_PLANE_Y], |
- (*video_frame)->visible_data(VideoFrame::kAPlane), |
- (*video_frame)->stride(VideoFrame::kAPlane), |
- (*video_frame)->visible_rect().width(), |
- (*video_frame)->visible_rect().height()); |
return true; |
} |
bool VpxVideoDecoder::CopyVpxImageToVideoFrame( |
const struct vpx_image* vpx_image, |
+ const scoped_refptr<DecoderBuffer>& buffer, |
scoped_refptr<VideoFrame>* video_frame) { |
DCHECK(vpx_image); |
@@ -710,24 +660,87 @@ bool VpxVideoDecoder::CopyVpxImageToVideoFrame( |
DCHECK(codec_format == PIXEL_FORMAT_YV12 || |
codec_format == PIXEL_FORMAT_YV12A); |
- *video_frame = frame_pool_.CreateFrame( |
- codec_format, visible_size, gfx::Rect(visible_size), |
- config_.natural_size(), kNoTimestamp()); |
- if (!(*video_frame)) |
- return false; |
- |
+ std::unique_ptr<VideoFrameFuture> video_frame_future = |
+ gpu_video_frame_pool_->CreateFrame( |
+ codec_format, visible_size, gfx::Rect(visible_size), |
+ config_.natural_size(), kNoTimestamp()); |
libyuv::I420Copy( |
vpx_image->planes[VPX_PLANE_Y], vpx_image->stride[VPX_PLANE_Y], |
vpx_image->planes[VPX_PLANE_U], vpx_image->stride[VPX_PLANE_U], |
vpx_image->planes[VPX_PLANE_V], vpx_image->stride[VPX_PLANE_V], |
- (*video_frame)->visible_data(VideoFrame::kYPlane), |
- (*video_frame)->stride(VideoFrame::kYPlane), |
- (*video_frame)->visible_data(VideoFrame::kUPlane), |
- (*video_frame)->stride(VideoFrame::kUPlane), |
- (*video_frame)->visible_data(VideoFrame::kVPlane), |
- (*video_frame)->stride(VideoFrame::kVPlane), coded_size.width(), |
+ video_frame_future->data(VideoFrame::kYPlane), |
+ video_frame_future->stride(VideoFrame::kYPlane), |
+ video_frame_future->data(VideoFrame::kUPlane), |
+ video_frame_future->stride(VideoFrame::kUPlane), |
+ video_frame_future->data(VideoFrame::kVPlane), |
+ video_frame_future->stride(VideoFrame::kVPlane), coded_size.width(), |
coded_size.height()); |
+ for (int i = 0; i < 1 && vpx_codec_alpha_; i++) { |
+ if (buffer->side_data_size() < 8) { |
+ // TODO(mcasas): Is this a warning or an error? |
+ DLOG(WARNING) << "Making Alpha channel opaque due to missing input"; |
+ const uint32_t kAlphaOpaqueValue = 255; |
+ libyuv::SetPlane(video_frame_future->data(VideoFrame::kAPlane), |
+ video_frame_future->stride(VideoFrame::kAPlane), |
+ coded_size.width(), coded_size.height(), |
+ kAlphaOpaqueValue); |
+ break; |
+ } |
+ |
+ // First 8 bytes of side data is |side_data_id| in big endian. |
+ const uint64_t side_data_id = base::NetToHost64( |
+ *(reinterpret_cast<const uint64_t*>(buffer->side_data()))); |
+ if (side_data_id != 1) |
+ break; |
+ |
+ // Try and decode buffer->side_data() minus the first 8 bytes as a full |
+ // frame. |
+ int64_t timestamp_alpha = buffer->timestamp().InMicroseconds(); |
+ void* user_priv_alpha = reinterpret_cast<void*>(×tamp_alpha); |
+ { |
+ TRACE_EVENT1("media", "vpx_codec_decode_alpha", "timestamp_alpha", |
+ timestamp_alpha); |
+ vpx_codec_err_t status = vpx_codec_decode( |
+ vpx_codec_alpha_, buffer->side_data() + 8, |
+ buffer->side_data_size() - 8, user_priv_alpha, 0 /* deadline */); |
+ if (status != VPX_CODEC_OK) { |
+ DLOG(ERROR) << "vpx_codec_decode() failed for the alpha: " |
+ << vpx_codec_error(vpx_codec_); |
+ return false; |
+ } |
+ } |
+ |
+ vpx_codec_iter_t iter_alpha = NULL; |
+ const vpx_image_t* vpx_image_alpha = |
+ vpx_codec_get_frame(vpx_codec_alpha_, &iter_alpha); |
+ if (!vpx_image_alpha) { |
+ *video_frame = nullptr; |
+ return true; |
+ } |
+ |
+ if (vpx_image_alpha->user_priv != user_priv_alpha) { |
+ DLOG(ERROR) << "Invalid output timestamp on alpha."; |
+ return false; |
+ } |
+ |
+ if (vpx_image_alpha->d_h != vpx_image->d_h || |
+ vpx_image_alpha->d_w != vpx_image->d_w) { |
+ DLOG(ERROR) << "The alpha plane dimensions are not the same as the " |
+ "image dimensions."; |
+ return false; |
+ } |
+ |
+ libyuv::CopyPlane(vpx_image_alpha->planes[VPX_PLANE_Y], |
+ vpx_image_alpha->stride[VPX_PLANE_Y], |
+ video_frame_future->data(VideoFrame::kAPlane), |
+ video_frame_future->stride(VideoFrame::kAPlane), |
+ coded_size.width(), coded_size.height()); |
+ } |
+ |
+ *video_frame = video_frame_future->Release(); |
+ if (!(*video_frame)) |
+ return false; |
return true; |
} |