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

Unified Diff: media/filters/vpx_video_decoder.cc

Issue 1869303004: media: Implement zero-copy video playback for VP8. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: optimize only VP8 Created 4 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/renderers/default_renderer_factory.cc » ('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 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*>(&timestamp_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*>(&timestamp_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;
}
« no previous file with comments | « media/filters/vpx_video_decoder.h ('k') | media/renderers/default_renderer_factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698