Commit 78fc7422 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

Add SharedImage support to VTVideoDecodeAccelerator

Directly create a SharedImageBackingGLImage that wraps the
GLImage is already being created. Register this backing
using SharedImageFactory::RegisterBacking. This is the same
pattern used by GpuSharedImageVideoFactory::CreateImageInternal
among others.

Pass the reference-counted destructor callback to PictureReady
callback.

Move the format definitions to a single block and add a TODO
indicating that the format of GL_BGRA seems inappropriate (but
it works, for unclear reasons).

Assume that the SkiaRenderer is only used with the passthrough
decoder. Either the decoder type will need to be plumbed, or
we will bake in the assumption.

Add GPU_GLES2_EXPORT to the relevant structures used in media
code.

Bug: 1108909
Change-Id: I33e230945e9c3d231195f735a878d903f11c95ab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2380743
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarKai Ninomiya <kainino@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803515}
parent d1ae2a34
......@@ -13,7 +13,7 @@ namespace gpu {
// Common helper functions for SharedImageBackingGLTexture and
// SharedImageBackingPassthroughGLImage.
class SharedImageBackingGLCommon {
class GPU_GLES2_EXPORT SharedImageBackingGLCommon {
public:
// These parameters are used to explicitly initialize a GL texture.
struct InitializeGLTextureParams {
......
......@@ -7,6 +7,7 @@
#include "gpu/command_buffer/service/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_image_backing_gl_common.h"
#include "gpu/gpu_gles2_export.h"
namespace gpu {
......@@ -137,7 +138,7 @@ class SharedImageRepresentationOverlayImpl
// Implementation of SharedImageBacking that creates a GL Texture that is backed
// by a GLImage and stores it as a gles2::Texture. Can be used with the legacy
// mailbox implementation.
class SharedImageBackingGLImage
class GPU_GLES2_EXPORT SharedImageBackingGLImage
: public SharedImageBacking,
public SharedImageRepresentationGLTextureClient {
public:
......
......@@ -47,6 +47,7 @@ source_set("mac") {
":vt_beta_stubs",
"//base",
"//components/crash/core/common:crash_key",
"//gpu/command_buffer/service:gles2",
"//gpu/ipc/service",
"//media",
"//media/gpu:common",
......
......@@ -34,7 +34,13 @@
#include "base/trace_event/process_memory_dump.h"
#include "base/version.h"
#include "components/crash/core/common/crash_key.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/shared_image_backing_gl_image.h"
#include "gpu/command_buffer/service/shared_image_factory.h"
#include "gpu/ipc/service/shared_image_stub.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/filters/vp9_parser.h"
......@@ -457,9 +463,12 @@ VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id)
VTVideoDecodeAccelerator::Frame::~Frame() {}
VTVideoDecodeAccelerator::PictureInfo::PictureInfo()
: uses_shared_images(true) {}
VTVideoDecodeAccelerator::PictureInfo::PictureInfo(uint32_t client_texture_id,
uint32_t service_texture_id)
: bitstream_id(0),
: uses_shared_images(false),
client_texture_id(client_texture_id),
service_texture_id(service_texture_id) {}
......@@ -1231,12 +1240,18 @@ void VTVideoDecodeAccelerator::AssignPictureBuffers(
DCHECK(!picture_info_map_.count(picture.id()));
assigned_picture_ids_.insert(picture.id());
available_picture_ids_.push_back(picture.id());
DCHECK_LE(1u, picture.client_texture_ids().size());
DCHECK_LE(1u, picture.service_texture_ids().size());
picture_info_map_.insert(std::make_pair(
picture.id(),
std::make_unique<PictureInfo>(picture.client_texture_ids()[0],
picture.service_texture_ids()[0])));
if (picture.client_texture_ids().empty() &&
picture.service_texture_ids().empty()) {
picture_info_map_.insert(
std::make_pair(picture.id(), std::make_unique<PictureInfo>()));
} else {
DCHECK_LE(1u, picture.client_texture_ids().size());
DCHECK_LE(1u, picture.service_texture_ids().size());
picture_info_map_.insert(std::make_pair(
picture.id(),
std::make_unique<PictureInfo>(picture.client_texture_ids()[0],
picture.service_texture_ids()[0])));
}
}
// Pictures are not marked as uncleared until after this method returns, and
......@@ -1260,9 +1275,13 @@ void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) {
// Drop references to allow the underlying buffer to be released.
PictureInfo* picture_info = it->second.get();
gl_client_.bind_image.Run(picture_info->client_texture_id,
gpu::GetPlatformSpecificTextureTarget(), nullptr,
false);
if (picture_info->uses_shared_images) {
picture_info->scoped_shared_image = nullptr;
} else {
gl_client_.bind_image.Run(picture_info->client_texture_id,
gpu::GetPlatformSpecificTextureTarget(), nullptr,
false);
}
picture_info->gl_image = nullptr;
picture_info->bitstream_id = 0;
......@@ -1482,14 +1501,22 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
PictureInfo* picture_info = it->second.get();
DCHECK(!picture_info->gl_image);
const gfx::BufferFormat buffer_format =
config_.profile == VP9PROFILE_PROFILE2
? gfx::BufferFormat::P010
: gfx::BufferFormat::YUV_420_BIPLANAR;
// TODO(https://crbug.com/1108909): BGRA is not an appropriate value for
// these parameters.
const GLenum gl_format = GL_BGRA_EXT;
const viz::ResourceFormat viz_resource_format =
viz::ResourceFormat::BGRA_8888;
scoped_refptr<gl::GLImageIOSurface> gl_image(
gl::GLImageIOSurface::Create(frame.image_size, GL_BGRA_EXT));
gl::GLImageIOSurface::Create(frame.image_size, gl_format));
if (!gl_image->InitializeWithCVPixelBuffer(
frame.image.get(),
gfx::GenericSharedMemoryId(g_cv_pixel_buffer_ids.GetNext()),
config_.profile == VP9PROFILE_PROFILE2
? gfx::BufferFormat::P010
: gfx::BufferFormat::YUV_420_BIPLANAR)) {
buffer_format)) {
NOTIFY_STATUS("Failed to initialize GLImageIOSurface", PLATFORM_FAILURE,
SFT_PLATFORM_ERROR);
}
......@@ -1497,12 +1524,62 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
gfx::ColorSpace color_space = GetImageBufferColorSpace(frame.image);
gl_image->SetColorSpaceForYUVToRGBConversion(color_space);
if (!gl_client_.bind_image.Run(picture_info->client_texture_id,
gpu::GetPlatformSpecificTextureTarget(),
gl_image, false)) {
DLOG(ERROR) << "Failed to bind image";
NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
return false;
scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image;
if (picture_info->uses_shared_images) {
gpu::SharedImageStub* shared_image_stub = client_->GetSharedImageStub();
DCHECK(shared_image_stub);
const uint32_t shared_image_usage =
gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT;
gpu::Mailbox mailbox = gpu::Mailbox::GenerateForSharedImage();
gpu::SharedImageBackingGLCommon::InitializeGLTextureParams gl_params;
gl_params.target = GL_TEXTURE_RECTANGLE_ARB;
gl_params.internal_format = gl_format;
gl_params.format = gl_format;
gl_params.type = GL_UNSIGNED_BYTE;
gl_params.is_cleared = true;
gpu::SharedImageBackingGLCommon::UnpackStateAttribs gl_attribs;
// TODO(https://crbug.com/1108909): Plumb the correct value of
// |is_passthrough|, or deprecate the non-passthrough path.
const bool is_passthrough = true;
auto shared_image = std::make_unique<gpu::SharedImageBackingGLImage>(
gl_image, mailbox, viz_resource_format, frame.image_size, color_space,
kTopLeft_GrSurfaceOrigin, kOpaque_SkAlphaType, shared_image_usage,
gl_params, gl_attribs, is_passthrough);
const bool success = shared_image_stub->factory()->RegisterBacking(
std::move(shared_image), /* legacy_mailbox */ true);
if (!success) {
DLOG(ERROR) << "Failed to register shared image";
NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
return false;
}
// Wrap the destroy callback in a lambda that ensures that it be called on
// the appropriate thread.
auto destroy_shared_image_lambda =
[](gpu::SharedImageStub::SharedImageDestructionCallback callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), gpu::SyncToken()));
};
auto destroy_shared_image_callback = base::BindOnce(
destroy_shared_image_lambda,
shared_image_stub->GetSharedImageDestructionCallback(mailbox),
gpu_task_runner_);
scoped_shared_image = scoped_refptr<Picture::ScopedSharedImage>(
new Picture::ScopedSharedImage(
mailbox, GL_TEXTURE_RECTANGLE_ARB,
std::move(destroy_shared_image_callback)));
} else {
if (!gl_client_.bind_image.Run(picture_info->client_texture_id,
gpu::GetPlatformSpecificTextureTarget(),
gl_image, false)) {
DLOG(ERROR) << "Failed to bind image";
NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
return false;
}
}
picture_info->gl_image = gl_image;
picture_info->bitstream_id = frame.bitstream_id;
......@@ -1524,6 +1601,7 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
// we don't need to use them when the image is never bound? Bindings are
// typically only created when WebGL is in use.
picture.set_read_lock_fences_enabled(true);
picture.set_scoped_shared_image(scoped_shared_image);
client_->PictureReady(std::move(picture));
return true;
}
......
......@@ -10,8 +10,6 @@
#include <map>
#include <memory>
#include <VideoToolbox/VideoToolbox.h>
#include "base/containers/queue.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
......@@ -26,8 +24,13 @@
#include "media/video/h264_poc.h"
#include "media/video/video_decode_accelerator.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_image_io_surface.h"
// This must be included after gl_bindings.h, or the various GL headers on the
// system and in the source tree will conflict with each other.
#include <VideoToolbox/VideoToolbox.h>
namespace media {
class VP9ConfigChangeDetector;
class VP9SuperFrameBitstreamFilter;
......@@ -130,16 +133,26 @@ class VTVideoDecodeAccelerator : public VideoDecodeAccelerator,
};
struct PictureInfo {
// A PictureInfo that specifies no texture IDs will be used for shared
// images.
PictureInfo();
PictureInfo(uint32_t client_texture_id, uint32_t service_texture_id);
~PictureInfo();
// If true, then |scoped_shared_image| is used and |client_texture_id| and
// |service_texture_id| are not used.
const bool uses_shared_images;
// Information about the currently bound image, for OnMemoryDump().
scoped_refptr<gl::GLImageIOSurface> gl_image;
int32_t bitstream_id;
int32_t bitstream_id = 0;
// Texture IDs for the image buffer.
const uint32_t client_texture_id;
const uint32_t service_texture_id;
const uint32_t client_texture_id = 0;
const uint32_t service_texture_id = 0;
// The shared image holder that will be passed to the client.
scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image;
private:
DISALLOW_COPY_AND_ASSIGN(PictureInfo);
......
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