Commit 462d699b authored by Ted Meyer's avatar Ted Meyer Committed by Commit Bot

Picture Processing in D3D11PictureBuffer

This refactor sees D3D11PictureBuffer no longer holding a D3D11Texture2D,
instead it holds a wrapper class which is responsible for creating and
owning gpu resources and mailboxes.

The default wrapper behaves exactly like the old implementation.

Bug: 963742
Change-Id: I49c67517203ef6464a6f0f2d3609bd7e484ac4a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1614937
Commit-Queue: Ted Meyer <tmathmeyer@chromium.org>
Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664459}
parent 8f2502b2
...@@ -177,6 +177,8 @@ component("gpu") { ...@@ -177,6 +177,8 @@ component("gpu") {
"windows/d3d11_h264_accelerator.h", "windows/d3d11_h264_accelerator.h",
"windows/d3d11_picture_buffer.cc", "windows/d3d11_picture_buffer.cc",
"windows/d3d11_picture_buffer.h", "windows/d3d11_picture_buffer.h",
"windows/d3d11_texture_wrapper.cc",
"windows/d3d11_texture_wrapper.h",
"windows/d3d11_video_context_wrapper.cc", "windows/d3d11_video_context_wrapper.cc",
"windows/d3d11_video_context_wrapper.h", "windows/d3d11_video_context_wrapper.h",
"windows/d3d11_video_decoder.cc", "windows/d3d11_video_decoder.cc",
......
...@@ -7,177 +7,71 @@ ...@@ -7,177 +7,71 @@
#include <d3d11.h> #include <d3d11.h>
#include <d3d11_1.h> #include <d3d11_1.h>
#include <windows.h> #include <windows.h>
#include <wrl/client.h>
#include <memory> #include <memory>
#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/texture_manager.h"
#include "media/base/media_log.h"
#include "media/gpu/windows/return_on_failure.h" #include "media/gpu/windows/return_on_failure.h"
#include "third_party/angle/include/EGL/egl.h" #include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h" #include "third_party/angle/include/EGL/eglext.h"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image_dxgi.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/scoped_binders.h"
namespace media { namespace media {
D3D11PictureBuffer::D3D11PictureBuffer(GLenum target, D3D11PictureBuffer::D3D11PictureBuffer(
gfx::Size size, GLenum target,
size_t level) std::unique_ptr<Texture2DWrapper> texture_wrapper,
: target_(target), size_(size), level_(level) {} gfx::Size size,
size_t level)
: target_(target),
texture_wrapper_(std::move(texture_wrapper)),
size_(size),
level_(level) {}
D3D11PictureBuffer::~D3D11PictureBuffer() { D3D11PictureBuffer::~D3D11PictureBuffer() {
// TODO(liberato): post destruction of |gpu_resources_| to the gpu thread. // TODO(liberato): post destruction of |gpu_resources_| to the gpu thread.
} }
bool D3D11PictureBuffer::Init( bool D3D11PictureBuffer::Init(GetCommandBufferHelperCB get_helper_cb,
base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()> get_helper_cb, ComD3D11VideoDevice video_device,
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device, const GUID& decoder_guid,
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture, int textures_per_picture,
const GUID& decoder_guid, std::unique_ptr<MediaLog> media_log) {
int textures_per_picture) {
texture_ = texture;
D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC view_desc = {}; D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC view_desc = {};
view_desc.DecodeProfile = decoder_guid; view_desc.DecodeProfile = decoder_guid;
view_desc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D; view_desc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D;
view_desc.Texture2D.ArraySlice = (UINT)level_; view_desc.Texture2D.ArraySlice = (UINT)level_;
HRESULT hr = video_device->CreateVideoDecoderOutputView( if (!texture_wrapper_->Init(std::move(get_helper_cb), level_, target_, size_,
texture.Get(), &view_desc, output_view_.GetAddressOf()); textures_per_picture)) {
media_log->AddEvent(
if (!SUCCEEDED(hr)) media_log->CreateStringEvent(MediaLogEvent::MEDIA_ERROR_LOG_ENTRY,
"error", "Failed to Init the wrapper"));
return false; return false;
// Generate mailboxes and holders.
std::vector<gpu::Mailbox> mailboxes;
for (int texture_idx = 0; texture_idx < textures_per_picture; texture_idx++) {
mailboxes.push_back(gpu::Mailbox::Generate());
mailbox_holders_[texture_idx] = gpu::MailboxHolder(
mailboxes[texture_idx], gpu::SyncToken(), GL_TEXTURE_EXTERNAL_OES);
} }
// Start construction of the GpuResources. HRESULT hr = video_device->CreateVideoDecoderOutputView(
// We send the texture itself, since we assume that we're using the angle Texture().Get(), &view_desc, &output_view_);
// device for decoding. Sharing seems not to work very well. Otherwise, we
// would create the texture with KEYED_MUTEX and NTHANDLE, then send along if (!SUCCEEDED(hr)) {
// a handle that we get from |texture| as an IDXGIResource1. media_log->AddEvent(media_log->CreateStringEvent(
// TODO(liberato): this should happen on the gpu thread. MediaLogEvent::MEDIA_ERROR_LOG_ENTRY, "error",
gpu_resources_ = std::make_unique<GpuResources>(); "Failed to CreateVideoDecoderOutputView"));
if (!gpu_resources_->Init(std::move(get_helper_cb), level_,
std::move(mailboxes), target_, size_, texture,
textures_per_picture))
return false; return false;
}
return true; return true;
} }
D3D11PictureBuffer::GpuResources::GpuResources() {} const MailboxHolderArray& D3D11PictureBuffer::ProcessTexture() const {
return texture_wrapper_->ProcessTexture(this);
D3D11PictureBuffer::GpuResources::~GpuResources() {
if (helper_ && helper_->MakeContextCurrent()) {
for (uint32_t service_id : service_ids_)
helper_->DestroyTexture(service_id);
}
} }
bool D3D11PictureBuffer::GpuResources::Init( ComD3D11Texture2D D3D11PictureBuffer::Texture() const {
base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()> get_helper_cb, return texture_wrapper_->Texture();
int level,
const std::vector<gpu::Mailbox> mailboxes,
GLenum target,
gfx::Size size,
Microsoft::WRL::ComPtr<ID3D11Texture2D> angle_texture,
int textures_per_picture) {
helper_ = get_helper_cb.Run();
if (!helper_ || !helper_->MakeContextCurrent())
return false;
// Create the textures and attach them to the mailboxes.
for (int texture_idx = 0; texture_idx < textures_per_picture; texture_idx++) {
uint32_t service_id =
helper_->CreateTexture(target, GL_RGBA, size.width(), size.height(),
GL_RGBA, GL_UNSIGNED_BYTE);
service_ids_.push_back(service_id);
helper_->ProduceTexture(mailboxes[texture_idx], service_id);
}
// Create the stream for zero-copy use by gl.
EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
const EGLint stream_attributes[] = {
EGL_CONSUMER_LATENCY_USEC_KHR,
0,
EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR,
0,
EGL_NONE,
};
EGLStreamKHR stream = eglCreateStreamKHR(egl_display, stream_attributes);
RETURN_ON_FAILURE(!!stream, "Could not create stream", false);
// |stream| will be destroyed when the GLImage is.
// TODO(liberato): for tests, it will be destroyed pretty much at the end of
// this function unless |helper_| retains it. Also, this won't work if we
// have a FakeCommandBufferHelper since the service IDs aren't meaningful.
scoped_refptr<gl::GLImage> gl_image =
base::MakeRefCounted<gl::GLImageDXGI>(size, stream);
gl::ScopedActiveTexture texture0(GL_TEXTURE0);
gl::ScopedTextureBinder texture0_binder(GL_TEXTURE_EXTERNAL_OES,
service_ids_[0]);
gl::ScopedActiveTexture texture1(GL_TEXTURE1);
gl::ScopedTextureBinder texture1_binder(GL_TEXTURE_EXTERNAL_OES,
service_ids_[1]);
EGLAttrib consumer_attributes[] = {
EGL_COLOR_BUFFER_TYPE,
EGL_YUV_BUFFER_EXT,
EGL_YUV_NUMBER_OF_PLANES_EXT,
2,
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
0,
EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
1,
EGL_NONE,
};
EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
egl_display, stream, consumer_attributes);
RETURN_ON_FAILURE(result, "Could not set stream consumer", false);
EGLAttrib producer_attributes[] = {
EGL_NONE,
};
result = eglCreateStreamProducerD3DTextureANGLE(egl_display, stream,
producer_attributes);
RETURN_ON_FAILURE(result, "Could not create stream", false);
EGLAttrib frame_attributes[] = {
EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, level, EGL_NONE,
};
result = eglStreamPostD3DTextureANGLE(egl_display, stream,
static_cast<void*>(angle_texture.Get()),
frame_attributes);
RETURN_ON_FAILURE(result, "Could not post texture", false);
result = eglStreamConsumerAcquireKHR(egl_display, stream);
RETURN_ON_FAILURE(result, "Could not post acquire stream", false);
gl::GLImageDXGI* gl_image_dxgi =
static_cast<gl::GLImageDXGI*>(gl_image.get());
gl_image_dxgi->SetTexture(angle_texture, level);
// Bind the image to each texture.
for (size_t texture_idx = 0; texture_idx < service_ids_.size();
texture_idx++) {
helper_->BindImage(service_ids_[texture_idx], gl_image.get(),
false /* client_managed */);
}
return true;
} }
} // namespace media } // namespace media
...@@ -9,15 +9,19 @@ ...@@ -9,15 +9,19 @@
#include <dxva.h> #include <dxva.h>
#include <wrl/client.h> #include <wrl/client.h>
#include <memory>
#include <vector> #include <vector>
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/ipc/service/command_buffer_stub.h" #include "gpu/ipc/service/command_buffer_stub.h"
#include "media/base/media_log.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/gpu/command_buffer_helper.h" #include "media/gpu/command_buffer_helper.h"
#include "media/gpu/media_gpu_export.h" #include "media/gpu/media_gpu_export.h"
#include "media/gpu/windows/d3d11_texture_wrapper.h"
#include "media/video/picture.h" #include "media/video/picture.h"
#include "third_party/angle/include/EGL/egl.h" #include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h" #include "third_party/angle/include/EGL/eglext.h"
...@@ -25,6 +29,8 @@ ...@@ -25,6 +29,8 @@
namespace media { namespace media {
class Texture2DWrapper;
// PictureBuffer that owns Chrome Textures to display it, and keep a reference // PictureBuffer that owns Chrome Textures to display it, and keep a reference
// to the D3D texture that backs the image. // to the D3D texture that backs the image.
// //
...@@ -41,20 +47,26 @@ namespace media { ...@@ -41,20 +47,26 @@ namespace media {
class MEDIA_GPU_EXPORT D3D11PictureBuffer class MEDIA_GPU_EXPORT D3D11PictureBuffer
: public base::RefCountedThreadSafe<D3D11PictureBuffer> { : public base::RefCountedThreadSafe<D3D11PictureBuffer> {
public: public:
using MailboxHolderArray = gpu::MailboxHolder[VideoFrame::kMaxPlanes]; // |texture_wrapper| is responsible for controlling mailbox access to
// the ID3D11Texture2D,
D3D11PictureBuffer(GLenum target, gfx::Size size, size_t level); // |level| is the picturebuffer index inside the Array-type ID3D11Texture2D.
D3D11PictureBuffer(GLenum target,
bool Init(base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()> std::unique_ptr<Texture2DWrapper> texture_wrapper,
get_helper_cb, gfx::Size size,
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device, size_t level);
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture,
bool Init(GetCommandBufferHelperCB get_helper_cb,
ComD3D11VideoDevice video_device,
const GUID& decoder_guid, const GUID& decoder_guid,
int textures_per_picture); int textures_per_picture,
std::unique_ptr<MediaLog> media_log);
// Return the mailbox holders that can be used to create a VideoFrame for us.
const MailboxHolderArray& ProcessTexture() const;
ComD3D11Texture2D Texture() const;
const gfx::Size& size() const { return size_; } const gfx::Size& size() const { return size_; }
size_t level() const { return level_; } size_t level() const { return level_; }
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture() const { return texture_; }
// Is this PictureBuffer backing a VideoFrame right now? // Is this PictureBuffer backing a VideoFrame right now?
bool in_client_use() const { return in_client_use_; } bool in_client_use() const { return in_client_use_; }
...@@ -65,14 +77,10 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer ...@@ -65,14 +77,10 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer
void set_in_client_use(bool use) { in_client_use_ = use; } void set_in_client_use(bool use) { in_client_use_ = use; }
void set_in_picture_use(bool use) { in_picture_use_ = use; } void set_in_picture_use(bool use) { in_picture_use_ = use; }
const Microsoft::WRL::ComPtr<ID3D11VideoDecoderOutputView>& output_view() const ComD3D11VideoDecoderOutputView& output_view() const {
const {
return output_view_; return output_view_;
} }
// Return the mailbox holders that can be used to create a VideoFrame for us.
const MailboxHolderArray& mailbox_holders() const { return mailbox_holders_; }
// Shouldn't be here, but simpler for now. // Shouldn't be here, but simpler for now.
base::TimeDelta timestamp_; base::TimeDelta timestamp_;
...@@ -81,46 +89,13 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer ...@@ -81,46 +89,13 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer
friend class base::RefCountedThreadSafe<D3D11PictureBuffer>; friend class base::RefCountedThreadSafe<D3D11PictureBuffer>;
GLenum target_; GLenum target_;
std::unique_ptr<Texture2DWrapper> texture_wrapper_;
gfx::Size size_; gfx::Size size_;
bool in_picture_use_ = false; bool in_picture_use_ = false;
bool in_client_use_ = false; bool in_client_use_ = false;
size_t level_; size_t level_;
// TODO(liberato): I don't think that we need to remember |texture_|. The ComD3D11VideoDecoderOutputView output_view_;
// GLImage will do so, so it will last long enough for any VideoFrames that
// reference it.
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture_;
Microsoft::WRL::ComPtr<ID3D11VideoDecoderOutputView> output_view_;
MailboxHolderArray mailbox_holders_;
// Things that are to be accessed / freed only on the main thread. In
// addition to setting up the textures to render from a D3D11 texture,
// these also hold the chrome GL Texture objects so that the client
// can use the mailbox.
class GpuResources {
public:
GpuResources();
~GpuResources();
bool Init(base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()>
get_helper_cb,
int level,
const std::vector<gpu::Mailbox> mailboxes,
GLenum target,
gfx::Size size,
Microsoft::WRL::ComPtr<ID3D11Texture2D> angle_texture,
int textures_per_picture);
std::vector<uint32_t> service_ids_;
private:
scoped_refptr<CommandBufferHelper> helper_;
DISALLOW_COPY_AND_ASSIGN(GpuResources);
};
std::unique_ptr<GpuResources> gpu_resources_;
DISALLOW_COPY_AND_ASSIGN(D3D11PictureBuffer); DISALLOW_COPY_AND_ASSIGN(D3D11PictureBuffer);
}; };
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/windows/d3d11_texture_wrapper.h"
#include <memory>
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "media/gpu/windows/return_on_failure.h"
namespace media {
Texture2DWrapper::Texture2DWrapper(ComD3D11Texture2D texture)
: texture_(texture) {}
Texture2DWrapper::~Texture2DWrapper() {}
const ComD3D11Texture2D Texture2DWrapper::Texture() const {
return texture_;
}
DefaultTexture2DWrapper::DefaultTexture2DWrapper(ComD3D11Texture2D texture)
: Texture2DWrapper(texture) {}
DefaultTexture2DWrapper::~DefaultTexture2DWrapper() {}
const MailboxHolderArray& DefaultTexture2DWrapper::ProcessTexture(
const D3D11PictureBuffer* owner_pb) {
return mailbox_holders_;
}
bool DefaultTexture2DWrapper::Init(GetCommandBufferHelperCB get_helper_cb,
size_t array_slice,
GLenum target,
gfx::Size size,
int textures_per_picture) {
gpu_resources_ = std::make_unique<GpuResources>();
if (!gpu_resources_)
return false;
// Generate mailboxes and holders.
std::vector<gpu::Mailbox> mailboxes;
for (int texture_idx = 0; texture_idx < textures_per_picture; texture_idx++) {
mailboxes.push_back(gpu::Mailbox::Generate());
mailbox_holders_[texture_idx] = gpu::MailboxHolder(
mailboxes[texture_idx], gpu::SyncToken(), GL_TEXTURE_EXTERNAL_OES);
}
// Start construction of the GpuResources.
// We send the texture itself, since we assume that we're using the angle
// device for decoding. Sharing seems not to work very well. Otherwise, we
// would create the texture with KEYED_MUTEX and NTHANDLE, then send along
// a handle that we get from |texture| as an IDXGIResource1.
// TODO(liberato): this should happen on the gpu thread.
return gpu_resources_->Init(std::move(get_helper_cb), array_slice,
std::move(mailboxes), target, size, Texture(),
textures_per_picture);
return true;
}
DefaultTexture2DWrapper::GpuResources::GpuResources() {}
DefaultTexture2DWrapper::GpuResources::~GpuResources() {
if (helper_ && helper_->MakeContextCurrent()) {
for (uint32_t service_id : service_ids_)
helper_->DestroyTexture(service_id);
}
}
bool DefaultTexture2DWrapper::GpuResources::Init(
GetCommandBufferHelperCB get_helper_cb,
int array_slice,
const std::vector<gpu::Mailbox> mailboxes,
GLenum target,
gfx::Size size,
ComD3D11Texture2D angle_texture,
int textures_per_picture) {
helper_ = get_helper_cb.Run();
if (!helper_ || !helper_->MakeContextCurrent())
return false;
// Create the textures and attach them to the mailboxes.
for (int texture_idx = 0; texture_idx < textures_per_picture; texture_idx++) {
uint32_t service_id =
helper_->CreateTexture(target, GL_RGBA, size.width(), size.height(),
GL_RGBA, GL_UNSIGNED_BYTE);
service_ids_.push_back(service_id);
helper_->ProduceTexture(mailboxes[texture_idx], service_id);
}
// Create the stream for zero-copy use by gl.
EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
const EGLint stream_attributes[] = {
EGL_CONSUMER_LATENCY_USEC_KHR,
0,
EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR,
0,
EGL_NONE,
};
EGLStreamKHR stream = eglCreateStreamKHR(egl_display, stream_attributes);
RETURN_ON_FAILURE(!!stream, "Could not create stream", false);
// |stream| will be destroyed when the GLImage is.
// TODO(liberato): for tests, it will be destroyed pretty much at the end of
// this function unless |helper_| retains it. Also, this won't work if we
// have a FakeCommandBufferHelper since the service IDs aren't meaningful.
scoped_refptr<gl::GLImage> gl_image =
base::MakeRefCounted<gl::GLImageDXGI>(size, stream);
gl::ScopedActiveTexture texture0(GL_TEXTURE0);
gl::ScopedTextureBinder texture0_binder(GL_TEXTURE_EXTERNAL_OES,
service_ids_[0]);
gl::ScopedActiveTexture texture1(GL_TEXTURE1);
gl::ScopedTextureBinder texture1_binder(GL_TEXTURE_EXTERNAL_OES,
service_ids_[1]);
EGLAttrib consumer_attributes[] = {
EGL_COLOR_BUFFER_TYPE,
EGL_YUV_BUFFER_EXT,
EGL_YUV_NUMBER_OF_PLANES_EXT,
2,
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
0,
EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
1,
EGL_NONE,
};
EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
egl_display, stream, consumer_attributes);
RETURN_ON_FAILURE(result, "Could not set stream consumer", false);
EGLAttrib producer_attributes[] = {
EGL_NONE,
};
result = eglCreateStreamProducerD3DTextureANGLE(egl_display, stream,
producer_attributes);
RETURN_ON_FAILURE(result, "Could not create stream", false);
EGLAttrib frame_attributes[] = {
EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
array_slice,
EGL_NONE,
};
result = eglStreamPostD3DTextureANGLE(egl_display, stream,
static_cast<void*>(angle_texture.Get()),
frame_attributes);
RETURN_ON_FAILURE(result, "Could not post texture", false);
result = eglStreamConsumerAcquireKHR(egl_display, stream);
RETURN_ON_FAILURE(result, "Could not post acquire stream", false);
gl::GLImageDXGI* gl_image_dxgi =
static_cast<gl::GLImageDXGI*>(gl_image.get());
gl_image_dxgi->SetTexture(angle_texture, array_slice);
// Bind the image to each texture.
for (size_t texture_idx = 0; texture_idx < service_ids_.size();
texture_idx++) {
helper_->BindImage(service_ids_[texture_idx], gl_image.get(),
false /* client_managed */);
}
return true;
}
} // namespace media
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_WINDOWS_D3D11_TEXTURE_WRAPPER_H_
#define MEDIA_GPU_WINDOWS_D3D11_TEXTURE_WRAPPER_H_
#include <d3d11.h>
#include <wrl/client.h>
#include <memory>
#include <vector>
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "media/base/video_frame.h"
#include "media/gpu/command_buffer_helper.h"
#include "media/gpu/media_gpu_export.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image_dxgi.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/scoped_binders.h"
namespace media {
using CommandBufferHelperPtr = scoped_refptr<CommandBufferHelper>;
using MailboxHolderArray = gpu::MailboxHolder[VideoFrame::kMaxPlanes];
using GetCommandBufferHelperCB =
base::RepeatingCallback<CommandBufferHelperPtr()>;
using ComD3D11VideoDevice = Microsoft::WRL::ComPtr<ID3D11VideoDevice>;
using ComD3D11Texture2D = Microsoft::WRL::ComPtr<ID3D11Texture2D>;
using ComD3D11VideoDecoderOutputView =
Microsoft::WRL::ComPtr<ID3D11VideoDecoderOutputView>;
class D3D11PictureBuffer;
// Support different strategies for processing pictures - some may need copying,
// for example.
class MEDIA_GPU_EXPORT Texture2DWrapper {
public:
Texture2DWrapper(ComD3D11Texture2D texture);
virtual ~Texture2DWrapper();
virtual const ComD3D11Texture2D Texture() const;
// This pointer can be raw, since each Texture2DWrapper is directly owned
// by the D3D11PictureBuffer through a unique_ptr.
virtual const MailboxHolderArray& ProcessTexture(
const D3D11PictureBuffer* owner_pb) = 0;
virtual bool Init(GetCommandBufferHelperCB get_helper_cb,
size_t array_slice,
GLenum target,
gfx::Size size,
int textures_per_picture) = 0;
private:
ComD3D11Texture2D texture_;
};
// The default texture wrapper that uses GPUResources to talk to hardware
// on behalf of a Texture2D.
class MEDIA_GPU_EXPORT DefaultTexture2DWrapper : public Texture2DWrapper {
public:
DefaultTexture2DWrapper(ComD3D11Texture2D texture);
~DefaultTexture2DWrapper() override;
bool Init(GetCommandBufferHelperCB get_helper_cb,
size_t array_slice,
GLenum target,
gfx::Size size,
int textures_per_picture) override;
const MailboxHolderArray& ProcessTexture(
const D3D11PictureBuffer* owner_pb) override;
private:
// Things that are to be accessed / freed only on the main thread. In
// addition to setting up the textures to render from a D3D11 texture,
// these also hold the chrome GL Texture objects so that the client
// can use the mailbox.
class GpuResources {
public:
GpuResources();
~GpuResources();
bool Init(GetCommandBufferHelperCB get_helper_cb,
int array_slice,
const std::vector<gpu::Mailbox> mailboxes,
GLenum target,
gfx::Size size,
ComD3D11Texture2D angle_texture,
int textures_per_picture);
std::vector<uint32_t> service_ids_;
private:
scoped_refptr<CommandBufferHelper> helper_;
DISALLOW_COPY_AND_ASSIGN(GpuResources);
};
std::unique_ptr<GpuResources> gpu_resources_;
MailboxHolderArray mailbox_holders_;
};
} // namespace media
#endif // MEDIA_GPU_WINDOWS_D3D11_TEXTURE_WRAPPER_H_
...@@ -671,11 +671,12 @@ void D3D11VideoDecoder::CreatePictureBuffers() { ...@@ -671,11 +671,12 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
// Create each picture buffer. // Create each picture buffer.
const int textures_per_picture = 2; // From the VDA const int textures_per_picture = 2; // From the VDA
for (size_t i = 0; i < TextureSelector::BUFFER_COUNT; i++) { for (size_t i = 0; i < TextureSelector::BUFFER_COUNT; i++) {
picture_buffers_.push_back( auto processor = std::make_unique<DefaultTexture2DWrapper>(out_texture);
new D3D11PictureBuffer(GL_TEXTURE_EXTERNAL_OES, size, i)); picture_buffers_.push_back(new D3D11PictureBuffer(
if (!picture_buffers_[i]->Init(get_helper_cb_, video_device_, out_texture, GL_TEXTURE_EXTERNAL_OES, std::move(processor), size, i));
if (!picture_buffers_[i]->Init(get_helper_cb_, video_device_,
texture_selector_->decoder_guid, texture_selector_->decoder_guid,
textures_per_picture)) { textures_per_picture, media_log_->Clone())) {
NotifyError("Unable to allocate PictureBuffer"); NotifyError("Unable to allocate PictureBuffer");
return; return;
} }
...@@ -713,7 +714,7 @@ void D3D11VideoDecoder::OutputResult(const CodecPicture* picture, ...@@ -713,7 +714,7 @@ void D3D11VideoDecoder::OutputResult(const CodecPicture* picture,
base::TimeDelta timestamp = picture_buffer->timestamp_; base::TimeDelta timestamp = picture_buffer->timestamp_;
scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures( scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
texture_selector_->pixel_format, picture_buffer->mailbox_holders(), texture_selector_->pixel_format, picture_buffer->ProcessTexture(),
VideoFrame::ReleaseMailboxCB(), picture_buffer->size(), visible_rect, VideoFrame::ReleaseMailboxCB(), picture_buffer->size(), visible_rect,
GetNaturalSize(visible_rect, pixel_aspect_ratio), timestamp); GetNaturalSize(visible_rect, pixel_aspect_ratio), timestamp);
......
...@@ -151,7 +151,7 @@ void D3D11VP9Accelerator::CopyReferenceFrames( ...@@ -151,7 +151,7 @@ void D3D11VP9Accelerator::CopyReferenceFrames(
DXVA_PicParams_VP9* pic_params, DXVA_PicParams_VP9* pic_params,
const Vp9ReferenceFrameVector& ref_frames) { const Vp9ReferenceFrameVector& ref_frames) {
D3D11_TEXTURE2D_DESC texture_descriptor; D3D11_TEXTURE2D_DESC texture_descriptor;
pic.picture_buffer()->texture()->GetDesc(&texture_descriptor); pic.picture_buffer()->Texture()->GetDesc(&texture_descriptor);
for (size_t i = 0; i < base::size(pic_params->ref_frame_map); i++) { for (size_t i = 0; i < base::size(pic_params->ref_frame_map); i++) {
auto ref_pic = ref_frames.GetFrame(i); auto ref_pic = ref_frames.GetFrame(i);
......
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