Commit 5e3de235 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

Add blink::Picture::ScopedSharedImage

Create a blink::Picture::ScopedSharedImage structure, which will
keep a SharedImage alive as long as it is alive. This will be
used to pass a SharedImage from the hardware decoder across to
the VTVideoDecodeAccelerator.

The PictureBufferManager is where the decision about use of
SharedImage will be made. It will be sent to the
VTVideoDecodeAccelerator by specifying an empty PictureBuffer.

Bug: 1108909
Change-Id: Iabb71b1b69dd922dc44aca3821f243fcdd22c6d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2377419
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#802723}
parent 546db6c3
...@@ -992,6 +992,12 @@ bool VideoFrame::IsMappable() const { ...@@ -992,6 +992,12 @@ bool VideoFrame::IsMappable() const {
} }
bool VideoFrame::HasTextures() const { bool VideoFrame::HasTextures() const {
// A SharedImage can be turned into a texture, and so it counts as a texture
// in the context of this call.
if (mailbox_holders_[0].mailbox.IsSharedImage())
return true;
DCHECK(!wrapped_frame_ || !wrapped_frame_->HasTextures());
return wrapped_frame_ ? wrapped_frame_->HasTextures() return wrapped_frame_ ? wrapped_frame_->HasTextures()
: !mailbox_holders_[0].mailbox.IsZero(); : !mailbox_holders_[0].mailbox.IsZero();
} }
......
...@@ -27,6 +27,11 @@ int32_t NextID(int32_t* counter) { ...@@ -27,6 +27,11 @@ int32_t NextID(int32_t* counter) {
return value; return value;
} }
bool UseSharedImage() {
// TODO(https://crbug.com/1108909): Enable shared image use on macOS.
return false;
}
class PictureBufferManagerImpl : public PictureBufferManager { class PictureBufferManagerImpl : public PictureBufferManager {
public: public:
explicit PictureBufferManagerImpl( explicit PictureBufferManagerImpl(
...@@ -82,34 +87,38 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -82,34 +87,38 @@ class PictureBufferManagerImpl : public PictureBufferManager {
DCHECK(planes); DCHECK(planes);
DCHECK_LE(planes, static_cast<uint32_t>(VideoFrame::kMaxPlanes)); DCHECK_LE(planes, static_cast<uint32_t>(VideoFrame::kMaxPlanes));
// TODO(sandersd): Consider requiring that CreatePictureBuffers() is called if (!UseSharedImage()) {
// with the context current. // TODO(sandersd): Consider requiring that CreatePictureBuffers() is
if (!command_buffer_helper_->MakeContextCurrent()) { // called with the context current.
DVLOG(1) << "Failed to make context current"; if (!command_buffer_helper_->MakeContextCurrent()) {
return std::vector<PictureBuffer>(); DVLOG(1) << "Failed to make context current";
return std::vector<PictureBuffer>();
}
} }
std::vector<PictureBuffer> picture_buffers; std::vector<PictureBuffer> picture_buffers;
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
PictureBufferData picture_data = {pixel_format, texture_size}; PictureBufferData picture_data = {pixel_format, texture_size};
for (uint32_t j = 0; j < planes; j++) { if (!UseSharedImage()) {
// Create a texture for this plane. for (uint32_t j = 0; j < planes; j++) {
GLuint service_id = command_buffer_helper_->CreateTexture( // Create a texture for this plane.
texture_target, GL_RGBA, texture_size.width(), GLuint service_id = command_buffer_helper_->CreateTexture(
texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE); texture_target, GL_RGBA, texture_size.width(),
DCHECK(service_id); texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE);
picture_data.service_ids.push_back(service_id); DCHECK(service_id);
picture_data.service_ids.push_back(service_id);
// The texture is not cleared yet, but it will be before the VDA outputs
// it. Rather than requiring output to happen on the GPU thread, mark // The texture is not cleared yet, but it will be before the VDA
// the texture as cleared immediately. // outputs it. Rather than requiring output to happen on the GPU
command_buffer_helper_->SetCleared(service_id); // thread, mark the texture as cleared immediately.
command_buffer_helper_->SetCleared(service_id);
// Generate a mailbox while we are still on the GPU thread.
picture_data.mailbox_holders[j] = gpu::MailboxHolder( // Generate a mailbox while we are still on the GPU thread.
command_buffer_helper_->CreateMailbox(service_id), gpu::SyncToken(), picture_data.mailbox_holders[j] = gpu::MailboxHolder(
texture_target); command_buffer_helper_->CreateMailbox(service_id),
gpu::SyncToken(), texture_target);
}
} }
// Generate a picture buffer ID and record the picture buffer. // Generate a picture buffer ID and record the picture buffer.
...@@ -208,6 +217,15 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -208,6 +217,15 @@ class PictureBufferManagerImpl : public PictureBufferManager {
// Record the output. // Record the output.
picture_buffer_data.output_count++; picture_buffer_data.output_count++;
// If this |picture| has a SharedImage, then keep a reference to the
// SharedImage in |picture_buffer_data| and update the gpu::MailboxHolder.
DCHECK_EQ(UseSharedImage(), !!picture.scoped_shared_image());
if (auto scoped_shared_image = picture.scoped_shared_image()) {
picture_buffer_data.scoped_shared_image = scoped_shared_image;
picture_buffer_data.mailbox_holders[0] =
scoped_shared_image->GetMailboxHolder();
}
// Create and return a VideoFrame for the picture buffer. // Create and return a VideoFrame for the picture buffer.
scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures( scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
picture_buffer_data.pixel_format, picture_buffer_data.mailbox_holders, picture_buffer_data.pixel_format, picture_buffer_data.mailbox_holders,
...@@ -297,6 +315,7 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -297,6 +315,7 @@ class PictureBufferManagerImpl : public PictureBufferManager {
DCHECK(gpu_task_runner_->BelongsToCurrentThread()); DCHECK(gpu_task_runner_->BelongsToCurrentThread());
std::vector<GLuint> service_ids; std::vector<GLuint> service_ids;
scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image;
{ {
base::AutoLock lock(picture_buffers_lock_); base::AutoLock lock(picture_buffers_lock_);
const auto& it = picture_buffers_.find(picture_buffer_id); const auto& it = picture_buffers_.find(picture_buffer_id);
...@@ -304,9 +323,16 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -304,9 +323,16 @@ class PictureBufferManagerImpl : public PictureBufferManager {
DCHECK(it->second.dismissed); DCHECK(it->second.dismissed);
DCHECK(!it->second.IsInUse()); DCHECK(!it->second.IsInUse());
service_ids = std::move(it->second.service_ids); service_ids = std::move(it->second.service_ids);
scoped_shared_image = std::move(it->second.scoped_shared_image);
picture_buffers_.erase(it); picture_buffers_.erase(it);
} }
// If this PictureBuffer is using a SharedImage, let it fall out of scope.
if (scoped_shared_image) {
DCHECK(service_ids.empty());
return;
}
if (!command_buffer_helper_->MakeContextCurrent()) if (!command_buffer_helper_->MakeContextCurrent())
return; return;
...@@ -326,6 +352,7 @@ class PictureBufferManagerImpl : public PictureBufferManager { ...@@ -326,6 +352,7 @@ class PictureBufferManagerImpl : public PictureBufferManager {
gfx::Size texture_size; gfx::Size texture_size;
std::vector<GLuint> service_ids; std::vector<GLuint> service_ids;
gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image;
bool dismissed = false; bool dismissed = false;
// The same picture buffer can be output from the VDA multiple times // The same picture buffer can be output from the VDA multiple times
......
...@@ -32,7 +32,6 @@ PictureBuffer::PictureBuffer(int32_t id, ...@@ -32,7 +32,6 @@ PictureBuffer::PictureBuffer(int32_t id,
service_texture_ids_(service_texture_ids), service_texture_ids_(service_texture_ids),
texture_target_(texture_target), texture_target_(texture_target),
pixel_format_(pixel_format) { pixel_format_(pixel_format) {
DCHECK(!service_texture_ids_.empty());
// We either not have client texture ids at all, or if we do, then their // We either not have client texture ids at all, or if we do, then their
// number must be the same as the number of service texture ids. // number must be the same as the number of service texture ids.
DCHECK(client_texture_ids_.empty() || DCHECK(client_texture_ids_.empty() ||
...@@ -86,4 +85,15 @@ Picture::Picture(const Picture& other) = default; ...@@ -86,4 +85,15 @@ Picture::Picture(const Picture& other) = default;
Picture::~Picture() = default; Picture::~Picture() = default;
Picture::ScopedSharedImage::ScopedSharedImage(
gpu::Mailbox mailbox,
uint32_t texture_target,
base::OnceClosure destruction_closure)
: destruction_closure_(std::move(destruction_closure)),
mailbox_holder_(mailbox, gpu::SyncToken(), texture_target) {}
Picture::ScopedSharedImage::~ScopedSharedImage() {
std::move(destruction_closure_).Run();
}
} // namespace media } // namespace media
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
#include <vector> #include <vector>
#include "gpu/command_buffer/common/mailbox.h" #include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/media_export.h" #include "media/base/media_export.h"
#include "media/base/video_types.h" #include "media/base/video_types.h"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
...@@ -78,6 +80,26 @@ class MEDIA_EXPORT PictureBuffer { ...@@ -78,6 +80,26 @@ class MEDIA_EXPORT PictureBuffer {
// This is the media-namespace equivalent of PP_Picture_Dev. // This is the media-namespace equivalent of PP_Picture_Dev.
class MEDIA_EXPORT Picture { class MEDIA_EXPORT Picture {
public: public:
// An object that keeps alive a SharedImage until it goes out of scope.
// Used to manage the lifetime of SharedImage-backed decoded frames.
class MEDIA_EXPORT ScopedSharedImage
: public base::RefCountedThreadSafe<ScopedSharedImage> {
public:
ScopedSharedImage(gpu::Mailbox mailbox,
uint32_t texture_target,
base::OnceClosure destruction_closure);
const gpu::MailboxHolder& GetMailboxHolder() const {
return mailbox_holder_;
}
private:
friend class base::RefCountedThreadSafe<ScopedSharedImage>;
~ScopedSharedImage();
base::OnceClosure destruction_closure_;
gpu::MailboxHolder mailbox_holder_;
};
// Defaults |size_changed_| to false. Size changed is currently only used // Defaults |size_changed_| to false. Size changed is currently only used
// by AVDA and is set via set_size_changd(). // by AVDA and is set via set_size_changd().
Picture(int32_t picture_buffer_id, Picture(int32_t picture_buffer_id,
...@@ -128,6 +150,14 @@ class MEDIA_EXPORT Picture { ...@@ -128,6 +150,14 @@ class MEDIA_EXPORT Picture {
wants_promotion_hint_ = wants_promotion_hint; wants_promotion_hint_ = wants_promotion_hint;
} }
void set_scoped_shared_image(
scoped_refptr<ScopedSharedImage> scoped_shared_image) {
scoped_shared_image_ = scoped_shared_image;
}
scoped_refptr<ScopedSharedImage> scoped_shared_image() const {
return scoped_shared_image_;
}
private: private:
int32_t picture_buffer_id_; int32_t picture_buffer_id_;
int32_t bitstream_buffer_id_; int32_t bitstream_buffer_id_;
...@@ -138,6 +168,7 @@ class MEDIA_EXPORT Picture { ...@@ -138,6 +168,7 @@ class MEDIA_EXPORT Picture {
bool size_changed_; bool size_changed_;
bool texture_owner_; bool texture_owner_;
bool wants_promotion_hint_; bool wants_promotion_hint_;
scoped_refptr<ScopedSharedImage> scoped_shared_image_;
}; };
} // namespace media } // namespace media
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment