0

Delete DXVAVideoDecoder and scaffolding.

This has been disabled since M112 and the PPAPI migration to Mojo
has completed, so we can delete this all in M116!

Bug: 1378004, 1448064
Change-Id: If6d1c7fed4ef3a34c40eee32b5a82f840c1c1687
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4568892
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Dan Sanders <sandersd@chromium.org>
Reviewed-by: Sami Kyöstilä <skyostil@chromium.org>
Reviewed-by: Frank Liberato <liberato@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1152586}
This commit is contained in:
Dale Curtis
2023-06-02 16:31:57 +00:00
committed by Chromium LUCI CQ
parent 895988a8d3
commit 51f418c2a3
23 changed files with 6 additions and 5165 deletions

@ -80,7 +80,6 @@
X("drm") \
X("drmcursor") \
X("dwrite") \
X("DXVA_Decoding") \
X("evdev") \
X("event") \
X("exo") \

@ -86,7 +86,6 @@
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "media/base/win/mf_initializer.h"
#include "media/gpu/windows/dxva_video_decode_accelerator_win.h"
#include "sandbox/win/src/sandbox.h"
#endif
@ -155,9 +154,7 @@ class ContentSandboxHelper : public gpu::GpuSandboxHelper {
#endif
#endif // BUILDFLAG(USE_VAAPI)
#if BUILDFLAG(IS_WIN)
if (media::PreSandboxMediaFoundationInitialization()) {
media::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
}
media::PreSandboxMediaFoundationInitialization();
#endif
#if BUILDFLAG(IS_MAC)

@ -159,10 +159,6 @@ class PixelTestPages():
@staticmethod
def DefaultPages(base_name: str) -> List[PixelTestPage]:
sw_compositing_args = [cba.DISABLE_GPU_COMPOSITING]
browser_args_DXVA = [
cba.DISABLE_D3D11_VIDEO_DECODER,
cba.ENABLE_DXVA_VIDEO_DECODER,
]
experimental_hdr_args = [cba.ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES]
return [
@ -230,11 +226,6 @@ class PixelTestPages():
# tends to produce images with all colors shifted by a
# small amount.
matching_algorithm=GENERAL_MP4_ALGO),
# Surprisingly stable, does not appear to require inexact matching.
PixelTestPage('pixel_video_mp4.html?width=240&height=135&use_timer=1',
base_name + '_Video_MP4_DXVA',
browser_args=browser_args_DXVA,
test_rect=[0, 0, 240, 135]),
PixelTestPage(
'pixel_video_mp4_four_colors_aspect_4x3.html'
'?width=240&height=135&use_timer=1',
@ -281,15 +272,6 @@ class PixelTestPages():
pixel_delta_threshold=30,
edge_threshold=20,
ignored_border_thickness=1)),
PixelTestPage('pixel_video_vp9.html?width=240&height=135&use_timer=1',
base_name + '_Video_VP9_DXVA',
browser_args=browser_args_DXVA,
test_rect=[0, 0, 240, 135],
matching_algorithm=algo.SobelMatchingAlgorithm(
max_different_pixels=31100,
pixel_delta_threshold=30,
edge_threshold=250,
ignored_border_thickness=1)),
PixelTestPage(
'pixel_video_media_stream_incompatible_stride.html',
base_name + '_Video_Media_Stream_Incompatible_Stride',
@ -974,10 +956,6 @@ class PixelTestPages():
browser_args_BGRA = browser_args + [
'--direct-composition-video-swap-chain-format=bgra'
]
browser_args_DXVA = browser_args + [
cba.DISABLE_D3D11_VIDEO_DECODER,
cba.ENABLE_DXVA_VIDEO_DECODER,
]
browser_args_vp_scaling = [
cba.ENABLE_DIRECT_COMPOSITION_VIDEO_OVERLAYS,
cba.ENABLE_DIRECT_COMPOSITION_VP_SCALING,
@ -1013,11 +991,6 @@ class PixelTestPages():
test_rect=[0, 0, 240, 135],
browser_args=browser_args,
matching_algorithm=permissive_dc_sobel_algorithm),
PixelTestPage('pixel_video_mp4.html?width=240&height=135',
base_name + '_DirectComposition_Video_MP4_DXVA',
browser_args=browser_args_DXVA,
test_rect=[0, 0, 240, 135],
matching_algorithm=permissive_dc_sobel_algorithm),
PixelTestPage('pixel_video_mp4.html?width=960&height=540',
base_name + '_DirectComposition_Video_MP4_Fullsize',
browser_args=browser_args,
@ -1082,11 +1055,6 @@ class PixelTestPages():
test_rect=[0, 0, 240, 135],
browser_args=browser_args,
matching_algorithm=very_permissive_dc_sobel_algorithm),
PixelTestPage('pixel_video_vp9.html?width=240&height=135',
base_name + '_DirectComposition_Video_VP9_DXVA',
browser_args=browser_args_DXVA,
test_rect=[0, 0, 240, 135],
matching_algorithm=very_permissive_dc_sobel_algorithm),
PixelTestPage(
'pixel_video_vp9.html?width=960&height=540',
base_name + '_DirectComposition_Video_VP9_Fullsize',
@ -1137,11 +1105,6 @@ class PixelTestPages():
test_rect=[0, 0, 240, 136],
browser_args=browser_args,
matching_algorithm=permissive_dc_sobel_algorithm),
PixelTestPage('pixel_video_underlay.html?width=240&height=136&swaps=12',
base_name + '_DirectComposition_Underlay_DXVA',
test_rect=[0, 0, 240, 136],
browser_args=browser_args_DXVA,
matching_algorithm=permissive_dc_sobel_algorithm),
PixelTestPage('pixel_video_underlay.html?width=960&height=540&swaps=12',
base_name + '_DirectComposition_Underlay_Fullsize',
test_rect=[0, 0, 960, 540],

@ -162,16 +162,6 @@ crbug.com/575305 [ android android-webview-instrumentation ] Pixel_WebGLSadCanva
# context loss which results in hardware decoder loss.
crbug.com/580386 [ android ] Pixel_Video_Context_Loss_MP4 [ Skip ]
# Skip on platforms where DXVA vs D3D11 decoder doesn't matter.
crbug.com/927901 [ linux ] Pixel_Video_MP4_DXVA [ Skip ]
crbug.com/927901 [ android ] Pixel_Video_MP4_DXVA [ Skip ]
crbug.com/927901 [ mac ] Pixel_Video_MP4_DXVA [ Skip ]
crbug.com/927901 [ chromeos ] Pixel_Video_MP4_DXVA [ Skip ]
crbug.com/927901 [ linux ] Pixel_Video_VP9_DXVA [ Skip ]
crbug.com/927901 [ android ] Pixel_Video_VP9_DXVA [ Skip ]
crbug.com/927901 [ mac ] Pixel_Video_VP9_DXVA [ Skip ]
crbug.com/927901 [ chromeos ] Pixel_Video_VP9_DXVA [ Skip ]
# Skip dual gpu switching tests on Mac Nvidia because this
# configuration has been forced to use only the low-power GPU due to
# graphics driver bugs.

@ -107,14 +107,12 @@ crbug.com/1009860 [ fuchsia ] SwapChainTraceTest_* [ Skip ]
# Playing videos not supported in Fuchsia emulators.
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_BackdropFilter [ Skip ]
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_MP4 [ Skip ]
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_MP4_DXVA [ Skip ]
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_MP4_FourColors_Aspect_4x3 [ Skip ]
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_MP4_FourColors_Rot_180 [ Skip ]
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_MP4_FourColors_Rot_270 [ Skip ]
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_MP4_FourColors_Rot_90 [ Skip ]
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_MP4_Rounded_Corner [ Skip ]
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_VP9 [ Skip ]
crbug.com/1096431 [ fuchsia fuchsia-board-qemu-x64 ] TraceTest_Video_VP9_DXVA [ Skip ]
# Skip unaccelerated canvas test since we don't use swap chains without GPU compositing.
crbug.com/1009860 [ win10 ] SwapChainTraceTest_CanvasUnacceleratedLowLatency2D [ Skip ]

@ -3142,49 +3142,6 @@
"dont_delete_source_texture_for_egl_image"
]
},
{
"id": 336,
"cr_bugs": [625785],
"description": "DXVA video decoder crashes on some AMD GPUs.",
"os": {
"type": "win"
},
"vendor_id": "0x1002",
"device_id": ["0x15d8", "0x15dd"],
"exceptions": [
{
"vendor_id": "0x1002",
"driver_version": {
"op": "between",
"value": "26.20.11030.2",
"value2": "26.20.11999.99999"
}
},
{
"driver_version": {
"op": "between",
"value": "26.20.12020.15",
"value2": "26.20.12999.99999"
}
},
{
"driver_version": {
"op": "between",
"value": "26.20.13001.27002",
"value2": "26.20.13999.99999"
}
},
{
"driver_version": {
"op": ">=",
"value": "26.20.14001.7001"
}
}
],
"features": [
"disable_dxva_video_decoder"
]
},
{
"id": 337,
"description": "Disable hardware MFT H.264 encoder on older NVIDIA drivers",
@ -3642,18 +3599,6 @@
"disable_accelerated_vp9_profile2_decode"
]
},
{
"id": 374,
"cr_bugs": [1087422],
"description": "VP9 resilient mode causes corruptions with AMD VCN HW decoders, using DXVA",
"os": {
"type": "win"
},
"vendor_id": "0x1002",
"features": [
"disallow_vp9_resilient_dxva_decoding"
]
},
{
"id": 376,
"cr_bugs": [1219028],
@ -3790,7 +3735,7 @@
},
{
"id": 387,
"description": "DXVAVideoDecodeAccelerator doesn't support a set of legacy AMD Gpus",
"description": "Windows hardware decoding doesn't support a set of legacy AMD GPUs",
"cr_bugs": [822644, 1187900],
"os": {
"type": "win"
@ -3841,7 +3786,7 @@
},
{
"id": 388,
"description": "DXVAVideoDecodeAccelerator doesn't support a set of legacy Intel Gpus",
"description": "Windows hardware decoding doesn't support a set of legacy Intel GPUs",
"cr_bugs": [822644, 1187900],
"os": {
"type": "win"

@ -39,7 +39,6 @@ disable_discard_framebuffer
disable_drdc
disable_dual_source_blending_support
disable_dxgi_zero_copy_video
disable_dxva_video_decoder
disable_dynamic_video_encode_framerate_update
disable_egl_ext_image_dma_buf_import_modifiers
disable_es3_gl_context
@ -68,7 +67,6 @@ disable_vp_scaling
disable_vp_super_resolution
disable_webgl_rgb_multisampling_usage
disallow_large_instanced_draw
disallow_vp9_resilient_dxva_decoding
dont_delete_source_texture_for_egl_image
dont_initialize_uninitialized_locals
dont_use_eglclientwaitsync_with_timeout

@ -1202,11 +1202,6 @@ BASE_FEATURE(kD3D11Vp9kSVCHWDecoding,
"D3D11Vp9kSVCHWDecoding",
base::FEATURE_DISABLED_BY_DEFAULT);
// Controls whether the DXVA video decoder is enabled on Windows.
BASE_FEATURE(kDXVAVideoDecoding,
"DXVAVideoDecoding",
base::FEATURE_DISABLED_BY_DEFAULT);
// The Media Foundation Rendering Strategy determines which presentation mode
// Media Foundation Renderer should use for presenting clear content. This
// strategy has no impact for protected content, which must always use Direct

@ -379,7 +379,6 @@ MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaFoundationClearPlayback);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kAllowMediaFoundationFrameServerMode);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kWasapiRawAudioCapture);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kD3D11Vp9kSVCHWDecoding);
MEDIA_EXPORT BASE_DECLARE_FEATURE(kDXVAVideoDecoding);
// Strategy affecting how Media Foundation Renderer determines its rendering
// mode when used with clear video media. This strategy does not impact

@ -244,14 +244,6 @@ component("gpu") {
"windows/d3d_accelerator.h",
"windows/d3d_video_decoder_wrapper.cc",
"windows/d3d_video_decoder_wrapper.h",
"windows/dxva_picture_buffer_win.cc",
"windows/dxva_picture_buffer_win.h",
"windows/dxva_video_decode_accelerator_win.cc",
"windows/dxva_video_decode_accelerator_win.h",
"windows/gl_image_egl_stream.cc",
"windows/gl_image_egl_stream.h",
"windows/gl_image_pbuffer.cc",
"windows/gl_image_pbuffer.h",
"windows/init_guid.cc",
"windows/media_foundation_video_encode_accelerator_win.cc",
"windows/media_foundation_video_encode_accelerator_win.h",

@ -16,10 +16,6 @@
#include "media/gpu/media_gpu_export.h"
#include "media/media_buildflags.h"
#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#include "media/gpu/windows/dxva_video_decode_accelerator_win.h"
#endif
#if BUILDFLAG(IS_APPLE)
#include "media/gpu/mac/vt_video_decode_accelerator_mac.h"
#endif
@ -52,11 +48,7 @@ gpu::VideoDecodeAcceleratorCapabilities GetDecoderCapabilitiesInternal(
// TODO(posciak,henryhsu): improve this so that we choose a superset of
// resolutions and other supported profile parameters.
VideoDecodeAccelerator::Capabilities capabilities;
#if BUILDFLAG(IS_WIN)
capabilities.supported_profiles =
DXVAVideoDecodeAccelerator::GetSupportedProfiles(gpu_preferences,
workarounds);
#elif BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
#if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
#if BUILDFLAG(USE_VAAPI)
capabilities.supported_profiles =
VaapiVideoDecodeAccelerator::GetSupportedProfiles();
@ -137,10 +129,6 @@ GpuVideoDecodeAcceleratorFactory::CreateVDA(
const gpu::GpuPreferences&,
MediaLog* media_log) const;
const CreateVDAFp create_vda_fps[] = {
#if BUILDFLAG(IS_WIN)
&GpuVideoDecodeAcceleratorFactory::CreateDXVAVDA,
#endif
// Usually only one of USE_VAAPI or USE_V4L2_CODEC is defined on ChromeOS,
// except for Chromeboxes with companion video acceleration chips, which have
// both. In those cases prefer the VA creation function.
@ -168,21 +156,6 @@ GpuVideoDecodeAcceleratorFactory::CreateVDA(
return nullptr;
}
#if BUILDFLAG(IS_WIN)
std::unique_ptr<VideoDecodeAccelerator>
GpuVideoDecodeAcceleratorFactory::CreateDXVAVDA(
const gpu::GpuDriverBugWorkarounds& workarounds,
const gpu::GpuPreferences& gpu_preferences,
MediaLog* media_log) const {
std::unique_ptr<VideoDecodeAccelerator> decoder;
DVLOG(0) << "Initializing DXVA HW decoder for windows.";
decoder.reset(new DXVAVideoDecodeAccelerator(
gl_client_.get_context, gl_client_.make_context_current,
gl_client_.bind_image, workarounds, gpu_preferences, media_log));
return decoder;
}
#endif
#if BUILDFLAG(USE_VAAPI)
std::unique_ptr<VideoDecodeAccelerator>
GpuVideoDecodeAcceleratorFactory::CreateVaapiVDA(

@ -963,10 +963,6 @@ bool D3D11VideoDecoder::OutputResult(const CodecPicture* picture,
// However, we may choose to set ALLOW_OVERLAY to false even if
// the finch flag is enabled. We may not choose to set ALLOW_OVERLAY if the
// flag is off, however.
//
// Also note that, since we end up binding textures with GLImageEGLStream,
// it's probably okay just to allow overlay always, and let the swap chain
// presenter decide if it wants to.
frame->metadata().allow_overlay = true;
frame->metadata().power_efficient = true;

@ -1,640 +0,0 @@
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/windows/dxva_picture_buffer_win.h"
#include "base/metrics/histogram_functions.h"
#include "media/base/win/mf_helpers.h"
#include "media/gpu/windows/dxva_video_decode_accelerator_win.h"
#include "media/gpu/windows/gl_image_egl_stream.h"
#include "media/gpu/windows/gl_image_pbuffer.h"
#include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/scoped_binders.h"
namespace media {
enum {
// The keyed mutex should always be released before the other thread
// attempts to acquire it, so AcquireSync should always return immediately.
kAcquireSyncWaitMs = 0,
};
// static
std::unique_ptr<DXVAPictureBuffer> DXVAPictureBuffer::Create(
const DXVAVideoDecodeAccelerator& decoder,
const PictureBuffer& buffer,
EGLConfig egl_config) {
switch (decoder.GetPictureBufferMechanism()) {
case DXVAVideoDecodeAccelerator::PictureBufferMechanism::BIND: {
auto picture_buffer = std::make_unique<EGLStreamPictureBuffer>(buffer);
if (!picture_buffer->Initialize())
return nullptr;
return picture_buffer;
}
case DXVAVideoDecodeAccelerator::PictureBufferMechanism::COPY_TO_NV12: {
auto picture_buffer =
std::make_unique<EGLStreamCopyPictureBuffer>(buffer);
if (!picture_buffer->Initialize(decoder))
return nullptr;
return picture_buffer;
}
case DXVAVideoDecodeAccelerator::PictureBufferMechanism::COPY_TO_RGB: {
auto picture_buffer = std::make_unique<PbufferPictureBuffer>(buffer);
if (!picture_buffer->Initialize(decoder, egl_config))
return nullptr;
return picture_buffer;
}
}
NOTREACHED_NORETURN();
}
DXVAPictureBuffer::~DXVAPictureBuffer() {}
void DXVAPictureBuffer::ResetReuseFence() {
NOTREACHED();
}
bool DXVAPictureBuffer::CopyOutputSampleDataToPictureBuffer(
DXVAVideoDecodeAccelerator* decoder,
IDirect3DSurface9* dest_surface,
ID3D11Texture2D* dx11_texture,
int input_buffer_id) {
NOTREACHED_NORETURN();
}
void DXVAPictureBuffer::set_bound() {
DCHECK_EQ(UNUSED, state_);
state_ = BOUND;
}
gl::GLFence* DXVAPictureBuffer::reuse_fence() {
return nullptr;
}
bool DXVAPictureBuffer::CopySurfaceComplete(IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface) {
NOTREACHED_NORETURN();
}
DXVAPictureBuffer::DXVAPictureBuffer(const PictureBuffer& buffer)
: picture_buffer_(buffer) {}
bool DXVAPictureBuffer::BindSampleToTexture(
DXVAVideoDecodeAccelerator* decoder,
Microsoft::WRL::ComPtr<IMFSample> sample) {
NOTREACHED_NORETURN();
}
bool PbufferPictureBuffer::Initialize(const DXVAVideoDecodeAccelerator& decoder,
EGLConfig egl_config) {
RETURN_ON_FAILURE(!picture_buffer_.service_texture_ids().empty(),
"No service texture ids provided", false);
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
EGLint use_rgb = 1;
eglGetConfigAttrib(egl_display, egl_config, EGL_BIND_TO_TEXTURE_RGB,
&use_rgb);
EGLint red_bits = 8;
eglGetConfigAttrib(egl_display, egl_config, EGL_RED_SIZE, &red_bits);
if (!InitializeTexture(decoder, !!use_rgb, red_bits == 16))
return false;
EGLint attrib_list[] = {EGL_WIDTH,
size().width(),
EGL_HEIGHT,
size().height(),
EGL_TEXTURE_FORMAT,
use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA,
EGL_TEXTURE_TARGET,
EGL_TEXTURE_2D,
EGL_NONE};
decoding_surface_ = eglCreatePbufferFromClientBuffer(
egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, texture_share_handle_,
egl_config, attrib_list);
RETURN_ON_FAILURE(decoding_surface_, "Failed to create surface", false);
gl_image_ = base::MakeRefCounted<GLImagePbuffer>(size(), decoding_surface_);
if (decoder.d3d11_device_ && decoder.use_keyed_mutex_) {
void* keyed_mutex = nullptr;
EGLBoolean ret =
eglQuerySurfacePointerANGLE(egl_display, decoding_surface_,
EGL_DXGI_KEYED_MUTEX_ANGLE, &keyed_mutex);
RETURN_ON_FAILURE(keyed_mutex && ret == EGL_TRUE,
"Failed to query ANGLE keyed mutex", false);
egl_keyed_mutex_ = Microsoft::WRL::ComPtr<IDXGIKeyedMutex>(
static_cast<IDXGIKeyedMutex*>(keyed_mutex));
}
use_rgb_ = !!use_rgb;
return true;
}
bool PbufferPictureBuffer::InitializeTexture(
const DXVAVideoDecodeAccelerator& decoder,
bool use_rgb,
bool use_fp16) {
DCHECK(!texture_share_handle_);
if (decoder.d3d11_device_) {
D3D11_TEXTURE2D_DESC desc;
desc.Width = picture_buffer_.size().width();
desc.Height = picture_buffer_.size().height();
desc.MipLevels = 1;
desc.ArraySize = 1;
if (use_fp16) {
desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
} else {
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
}
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = 0;
desc.MiscFlags = decoder.use_keyed_mutex_
? D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
: D3D11_RESOURCE_MISC_SHARED;
HRESULT hr = decoder.d3d11_device_->CreateTexture2D(
&desc, nullptr, &dx11_decoding_texture_);
RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
RETURN_ON_HR_FAILURE(
SetDebugName(dx11_decoding_texture_.Get(), "DXVADecoder_PictureBuffer"),
"SetDebugNameFail", false);
if (decoder.use_keyed_mutex_) {
hr = dx11_decoding_texture_.As(&dx11_keyed_mutex_);
RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", false);
}
Microsoft::WRL::ComPtr<IDXGIResource> resource;
hr = dx11_decoding_texture_.As(&resource);
DCHECK(SUCCEEDED(hr));
hr = resource->GetSharedHandle(&texture_share_handle_);
RETURN_ON_FAILURE(SUCCEEDED(hr) && texture_share_handle_,
"Failed to query shared handle", false);
} else {
HRESULT hr = E_FAIL;
hr = decoder.d3d9_device_ex_->CreateTexture(
picture_buffer_.size().width(), picture_buffer_.size().height(), 1,
D3DUSAGE_RENDERTARGET, use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, &decoding_texture_, &texture_share_handle_);
RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
RETURN_ON_FAILURE(texture_share_handle_, "Failed to query shared handle",
false);
}
return true;
}
void PbufferPictureBuffer::ResetReuseFence() {
DCHECK_EQ(IN_CLIENT, state_);
if (!reuse_fence_ || !reuse_fence_->ResetSupported())
reuse_fence_ = gl::GLFence::Create();
else
reuse_fence_->ResetState();
state_ = WAITING_TO_REUSE;
}
bool PbufferPictureBuffer::CopyOutputSampleDataToPictureBuffer(
DXVAVideoDecodeAccelerator* decoder,
IDirect3DSurface9* dest_surface,
ID3D11Texture2D* dx11_texture,
int input_buffer_id) {
DCHECK_EQ(BOUND, state_);
state_ = COPYING;
DCHECK(dest_surface || dx11_texture);
if (dx11_texture) {
// Grab a reference on the decoder texture. This reference will be released
// when we receive a notification that the copy was completed or when the
// DXVAPictureBuffer instance is destroyed.
decoder_dx11_texture_ = dx11_texture;
if (!decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.Get(),
dx11_keyed_mutex_, keyed_mutex_value_, id(),
input_buffer_id, color_space_)) {
// |this| might be destroyed.
return false;
}
return true;
}
D3DSURFACE_DESC surface_desc;
HRESULT hr = dest_surface->GetDesc(&surface_desc);
RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
D3DSURFACE_DESC texture_desc;
decoding_texture_->GetLevelDesc(0, &texture_desc);
if (texture_desc.Width != surface_desc.Width ||
texture_desc.Height != surface_desc.Height) {
NOTREACHED() << "Decode surface of different dimension than texture";
return false;
}
hr = decoder->d3d9_->CheckDeviceFormatConversion(
D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, surface_desc.Format,
use_rgb_ ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8);
RETURN_ON_HR_FAILURE(hr, "Device does not support format converision", false);
// The same picture buffer can be reused for a different frame. Release the
// target surface and the decoder references here.
target_surface_.Reset();
decoder_surface_.Reset();
// Grab a reference on the decoder surface and the target surface. These
// references will be released when we receive a notification that the
// copy was completed or when the DXVAPictureBuffer instance is destroyed.
// We hold references here as it is easier to manage their lifetimes.
hr = decoding_texture_->GetSurfaceLevel(0, &target_surface_);
RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);
decoder_surface_ = dest_surface;
decoder->CopySurface(decoder_surface_.Get(), target_surface_.Get(), id(),
input_buffer_id, color_space_);
color_space_ = gfx::ColorSpace();
return true;
}
gl::GLFence* PbufferPictureBuffer::reuse_fence() {
return reuse_fence_.get();
}
bool PbufferPictureBuffer::CopySurfaceComplete(
IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface) {
DCHECK_EQ(COPYING, state_);
state_ = IN_CLIENT;
GLint current_texture = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
glBindTexture(GL_TEXTURE_2D, picture_buffer_.service_texture_ids()[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (src_surface && dest_surface) {
DCHECK_EQ(src_surface, decoder_surface_.Get());
DCHECK_EQ(dest_surface, target_surface_.Get());
decoder_surface_.Reset();
target_surface_.Reset();
} else {
DCHECK(decoder_dx11_texture_.Get());
decoder_dx11_texture_.Reset();
}
if (egl_keyed_mutex_) {
keyed_mutex_value_++;
HRESULT result =
egl_keyed_mutex_->AcquireSync(keyed_mutex_value_, kAcquireSyncWaitMs);
RETURN_ON_FAILURE(result == S_OK, "Could not acquire sync mutex", false);
}
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
eglBindTexImage(egl_display, decoding_surface_, EGL_BACK_BUFFER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, current_texture);
return true;
}
bool PbufferPictureBuffer::AllowOverlay() const {
return false;
}
bool PbufferPictureBuffer::CanBindSamples() const {
return false;
}
PbufferPictureBuffer::PbufferPictureBuffer(const PictureBuffer& buffer)
: DXVAPictureBuffer(buffer),
decoding_surface_(NULL),
texture_share_handle_(nullptr),
keyed_mutex_value_(0),
use_rgb_(true) {}
PbufferPictureBuffer::~PbufferPictureBuffer() {
// decoding_surface_ will be deleted by gl_image_.
}
bool PbufferPictureBuffer::ReusePictureBuffer() {
DCHECK_NE(UNUSED, state_);
DCHECK(decoding_surface_);
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
eglReleaseTexImage(egl_display, decoding_surface_, EGL_BACK_BUFFER);
decoder_surface_.Reset();
target_surface_.Reset();
decoder_dx11_texture_.Reset();
state_ = UNUSED;
if (egl_keyed_mutex_) {
HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_);
RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false);
}
return true;
}
EGLStreamPictureBuffer::EGLStreamPictureBuffer(const PictureBuffer& buffer)
: DXVAPictureBuffer(buffer), stream_(nullptr) {}
EGLStreamPictureBuffer::~EGLStreamPictureBuffer() {
// stream_ will be deleted by gl_image_.
}
bool EGLStreamPictureBuffer::Initialize() {
RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2,
"Not enough texture ids provided", false);
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
const EGLint stream_attributes[] = {
EGL_CONSUMER_LATENCY_USEC_KHR,
0,
EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR,
0,
EGL_NONE,
};
stream_ = eglCreateStreamKHR(egl_display, stream_attributes);
RETURN_ON_FAILURE(!!stream_, "Could not create stream", false);
gl_image_ = base::MakeRefCounted<GLImageEGLStream>(size(), stream_);
gl::ScopedActiveTexture texture0(GL_TEXTURE0);
gl::ScopedTextureBinder texture0_binder(
GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]);
gl::ScopedActiveTexture texture1(GL_TEXTURE1);
gl::ScopedTextureBinder texture1_binder(
GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_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 producer", false);
return true;
}
bool EGLStreamPictureBuffer::ReusePictureBuffer() {
DCHECK_NE(UNUSED, state_);
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
if (stream_) {
EGLBoolean result = eglStreamConsumerReleaseKHR(egl_display, stream_);
RETURN_ON_FAILURE(result, "Could not release stream", false);
}
if (current_d3d_sample_) {
dx11_decoding_texture_.Reset();
current_d3d_sample_.Reset();
}
state_ = UNUSED;
return true;
}
bool EGLStreamPictureBuffer::BindSampleToTexture(
DXVAVideoDecodeAccelerator* decoder,
Microsoft::WRL::ComPtr<IMFSample> sample) {
DCHECK_EQ(BOUND, state_);
state_ = IN_CLIENT;
shared_images_.resize(picture_buffer_.service_texture_ids().size());
current_d3d_sample_ = sample;
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
Microsoft::WRL::ComPtr<IMFMediaBuffer> output_buffer;
HRESULT hr = current_d3d_sample_->GetBufferByIndex(0, &output_buffer);
RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false);
Microsoft::WRL::ComPtr<IMFDXGIBuffer> dxgi_buffer;
hr = output_buffer.As(&dxgi_buffer);
RETURN_ON_HR_FAILURE(hr, "Failed to get DXGIBuffer from output sample",
false);
hr = dxgi_buffer->GetResource(IID_PPV_ARGS(&dx11_decoding_texture_));
RETURN_ON_HR_FAILURE(hr, "Failed to get texture from output sample", false);
UINT subresource;
dxgi_buffer->GetSubresourceIndex(&subresource);
EGLAttrib frame_attributes[] = {
EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
static_cast<EGLAttrib>(subresource),
EGL_NONE,
};
EGLBoolean result = eglStreamPostD3DTextureANGLE(
egl_display, stream_, static_cast<void*>(dx11_decoding_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);
GLImageEGLStream* gl_image_egl_stream =
static_cast<GLImageEGLStream*>(gl_image_.get());
DCHECK(gl_image_egl_stream);
gl_image_egl_stream->SetTexture(dx11_decoding_texture_, subresource);
return true;
}
bool EGLStreamPictureBuffer::AllowOverlay() const {
return true;
}
bool EGLStreamPictureBuffer::CanBindSamples() const {
return true;
}
EGLStreamCopyPictureBuffer::EGLStreamCopyPictureBuffer(
const PictureBuffer& buffer)
: DXVAPictureBuffer(buffer), stream_(nullptr) {}
EGLStreamCopyPictureBuffer::~EGLStreamCopyPictureBuffer() {
// stream_ will be deleted by gl_image_.
}
bool EGLStreamCopyPictureBuffer::Initialize(
const DXVAVideoDecodeAccelerator& decoder) {
RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2,
"Not enough texture ids provided", false);
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
const EGLint stream_attributes[] = {
EGL_CONSUMER_LATENCY_USEC_KHR,
0,
EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR,
0,
EGL_NONE,
};
stream_ = eglCreateStreamKHR(egl_display, stream_attributes);
RETURN_ON_FAILURE(!!stream_, "Could not create stream", false);
gl_image_ = base::MakeRefCounted<GLImageEGLStream>(size(), stream_);
gl::ScopedActiveTexture texture0(GL_TEXTURE0);
gl::ScopedTextureBinder texture0_binder(
GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]);
gl::ScopedActiveTexture texture1(GL_TEXTURE1);
gl::ScopedTextureBinder texture1_binder(
GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_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 producer", false);
DCHECK(decoder.use_keyed_mutex_);
D3D11_TEXTURE2D_DESC desc;
desc.Width = picture_buffer_.size().width();
desc.Height = picture_buffer_.size().height();
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_NV12;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = 0;
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
HRESULT hr = decoder.d3d11_device_->CreateTexture2D(&desc, nullptr,
&decoder_copy_texture_);
RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
RETURN_ON_HR_FAILURE(SetDebugName(decoder_copy_texture_.Get(),
"DXVADecoder_EGLStreamCopyPictureBuffer"),
"SetDebugNameFail", false);
DCHECK(decoder.use_keyed_mutex_);
hr = decoder_copy_texture_.As(&dx11_keyed_mutex_);
RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", false);
Microsoft::WRL::ComPtr<IDXGIResource> resource;
hr = decoder_copy_texture_.As(&resource);
DCHECK(SUCCEEDED(hr));
hr = resource->GetSharedHandle(&texture_share_handle_);
RETURN_ON_FAILURE(SUCCEEDED(hr) && texture_share_handle_,
"Failed to query shared handle", false);
hr = decoder.angle_device_->OpenSharedResource(
texture_share_handle_, IID_PPV_ARGS(&angle_copy_texture_));
RETURN_ON_HR_FAILURE(hr, "Failed to open shared resource", false);
hr = angle_copy_texture_.As(&egl_keyed_mutex_);
RETURN_ON_HR_FAILURE(hr, "Failed to get ANGLE mutex", false);
return true;
}
bool EGLStreamCopyPictureBuffer::CopyOutputSampleDataToPictureBuffer(
DXVAVideoDecodeAccelerator* decoder,
IDirect3DSurface9* dest_surface,
ID3D11Texture2D* dx11_texture,
int input_buffer_id) {
DCHECK_EQ(BOUND, state_);
state_ = COPYING;
DCHECK(dx11_texture);
// Grab a reference on the decoder texture. This reference will be released
// when we receive a notification that the copy was completed or when the
// DXVAPictureBuffer instance is destroyed.
dx11_decoding_texture_ = dx11_texture;
if (!decoder->CopyTexture(dx11_texture, decoder_copy_texture_.Get(),
dx11_keyed_mutex_, keyed_mutex_value_, id(),
input_buffer_id, color_space_)) {
// |this| might be destroyed
return false;
}
// The texture copy will acquire the current keyed mutex value and release
// with the value + 1.
keyed_mutex_value_++;
return true;
}
bool EGLStreamCopyPictureBuffer::CopySurfaceComplete(
IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface) {
DCHECK(!src_surface);
DCHECK(!dest_surface);
DCHECK_EQ(COPYING, state_);
state_ = IN_CLIENT;
dx11_decoding_texture_.Reset();
HRESULT hr =
egl_keyed_mutex_->AcquireSync(keyed_mutex_value_, kAcquireSyncWaitMs);
RETURN_ON_FAILURE(hr == S_OK, "Could not acquire sync mutex", false);
EGLAttrib frame_attributes[] = {
EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0, EGL_NONE,
};
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
EGLBoolean result = eglStreamPostD3DTextureANGLE(
egl_display, stream_, static_cast<void*>(angle_copy_texture_.Get()),
frame_attributes);
RETURN_ON_FAILURE(result, "Could not post stream", false);
result = eglStreamConsumerAcquireKHR(egl_display, stream_);
RETURN_ON_FAILURE(result, "Could not post acquire stream", false);
GLImageEGLStream* gl_image_egl_stream =
static_cast<GLImageEGLStream*>(gl_image_.get());
DCHECK(gl_image_egl_stream);
gl_image_egl_stream->SetTexture(angle_copy_texture_, 0);
return true;
}
bool EGLStreamCopyPictureBuffer::ReusePictureBuffer() {
DCHECK_NE(UNUSED, state_);
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
if (state_ == IN_CLIENT) {
HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_);
RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false);
}
state_ = UNUSED;
if (stream_) {
EGLBoolean result = eglStreamConsumerReleaseKHR(egl_display, stream_);
RETURN_ON_FAILURE(result, "Could not release stream", false);
}
return true;
}
bool EGLStreamCopyPictureBuffer::AllowOverlay() const {
return true;
}
bool EGLStreamCopyPictureBuffer::CanBindSamples() const {
return false;
}
} // namespace media

@ -1,250 +0,0 @@
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_WINDOWS_DXVA_PICTURE_BUFFER_WIN_H_
#define MEDIA_GPU_WINDOWS_DXVA_PICTURE_BUFFER_WIN_H_
#include <d3d11.h>
#include <d3d9.h>
#include <mfidl.h>
#include <wrl/client.h>
#include <memory>
#include "media/gpu/windows/d3d11_com_defs.h"
#include "media/video/picture.h"
#include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_image.h"
interface IMFSample;
namespace media {
class DXVAVideoDecodeAccelerator;
// Maintains information about a DXVA picture buffer, i.e. whether it is
// available for rendering, the texture information, etc.
class DXVAPictureBuffer {
public:
enum State { UNUSED, BOUND, COPYING, IN_CLIENT, WAITING_TO_REUSE };
static std::unique_ptr<DXVAPictureBuffer> Create(
const DXVAVideoDecodeAccelerator& decoder,
const PictureBuffer& buffer,
EGLConfig egl_config);
DXVAPictureBuffer(const DXVAPictureBuffer&) = delete;
DXVAPictureBuffer& operator=(const DXVAPictureBuffer&) = delete;
virtual ~DXVAPictureBuffer();
virtual bool ReusePictureBuffer() = 0;
virtual void ResetReuseFence();
// Copies the output sample data to the picture buffer provided by the
// client.
// The dest_surface parameter contains the decoded bits.
virtual bool CopyOutputSampleDataToPictureBuffer(
DXVAVideoDecodeAccelerator* decoder,
IDirect3DSurface9* dest_surface,
ID3D11Texture2D* dx11_texture,
int input_buffer_id);
bool available() const { return state_ == UNUSED; }
State state() const { return state_; }
const PictureBuffer& picture_buffer() const { return picture_buffer_; }
int id() const { return picture_buffer_.id(); }
gfx::Size size() const { return picture_buffer_.size(); }
void set_bound();
scoped_refptr<gl::GLImage> gl_image() { return gl_image_; }
const gfx::Rect& visible_rect() const { return visible_rect_; }
void set_visible_rect(const gfx::Rect& visible_rect) {
visible_rect_ = visible_rect;
}
const gfx::ColorSpace& color_space() const { return color_space_; }
void set_color_space(const gfx::ColorSpace& color_space) {
color_space_ = color_space;
}
const std::vector<scoped_refptr<Picture::ScopedSharedImage>>& shared_images()
const {
return shared_images_;
}
void set_shared_image(
size_t plane,
scoped_refptr<Picture::ScopedSharedImage> shared_image) {
DCHECK(plane < shared_images_.size());
shared_images_[plane] = std::move(shared_image);
}
// Picture buffer data used to create a shared image backing.
const PictureBuffer::TextureIds& service_texture_ids() const {
return picture_buffer_.service_texture_ids();
}
gfx::Size texture_size(size_t plane) {
return picture_buffer_.texture_size(plane);
}
VideoPixelFormat pixel_format() const {
return picture_buffer_.pixel_format();
}
// Returns true if these could in theory be used as an overlay. May
// still be drawn using GL depending on the scene and precise hardware
// support.
virtual bool AllowOverlay() const = 0;
// Returns true if BindSampleToTexture should be used. Otherwise
// CopyOutputSampleDataToPicture should be used.
virtual bool CanBindSamples() const = 0;
bool waiting_to_reuse() const { return state_ == WAITING_TO_REUSE; }
virtual gl::GLFence* reuse_fence();
// Called when the source surface |src_surface| is copied to the destination
// |dest_surface|
virtual bool CopySurfaceComplete(IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface);
virtual bool BindSampleToTexture(DXVAVideoDecodeAccelerator* decoder,
Microsoft::WRL::ComPtr<IMFSample> sample);
protected:
explicit DXVAPictureBuffer(const PictureBuffer& buffer);
State state_ = UNUSED;
PictureBuffer picture_buffer_;
gfx::Rect visible_rect_;
gfx::ColorSpace color_space_;
scoped_refptr<gl::GLImage> gl_image_;
std::vector<scoped_refptr<Picture::ScopedSharedImage>> shared_images_;
};
// Copies the video result into an RGBA EGL pbuffer.
class PbufferPictureBuffer : public DXVAPictureBuffer {
public:
explicit PbufferPictureBuffer(const PictureBuffer& buffer);
~PbufferPictureBuffer() override;
bool Initialize(const DXVAVideoDecodeAccelerator& decoder,
EGLConfig egl_config);
bool InitializeTexture(const DXVAVideoDecodeAccelerator& decoder,
bool use_rgb,
bool use_fp16);
bool ReusePictureBuffer() override;
void ResetReuseFence() override;
bool CopyOutputSampleDataToPictureBuffer(DXVAVideoDecodeAccelerator* decoder,
IDirect3DSurface9* dest_surface,
ID3D11Texture2D* dx11_texture,
int input_buffer_id) override;
gl::GLFence* reuse_fence() override;
bool CopySurfaceComplete(IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface) override;
bool AllowOverlay() const override;
bool CanBindSamples() const override;
protected:
EGLSurface decoding_surface_;
std::unique_ptr<gl::GLFence> reuse_fence_;
HANDLE texture_share_handle_;
Microsoft::WRL::ComPtr<IDirect3DTexture9> decoding_texture_;
ComD3D11Texture2D dx11_decoding_texture_;
Microsoft::WRL::ComPtr<IDXGIKeyedMutex> egl_keyed_mutex_;
Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_;
// This is the last value that was used to release the keyed mutex.
uint64_t keyed_mutex_value_;
// The following |IDirect3DSurface9| interface pointers are used to hold
// references on the surfaces during the course of a StretchRect operation
// to copy the source surface to the target. The references are released
// when the StretchRect operation i.e. the copy completes.
Microsoft::WRL::ComPtr<IDirect3DSurface9> decoder_surface_;
Microsoft::WRL::ComPtr<IDirect3DSurface9> target_surface_;
// This ID3D11Texture2D interface pointer is used to hold a reference to the
// decoder texture during the course of a copy operation. This reference is
// released when the copy completes.
ComD3D11Texture2D decoder_dx11_texture_;
// Set to true if RGB is supported by the texture.
// Defaults to true.
bool use_rgb_;
};
// Shares the decoded texture with ANGLE without copying by using an EGL stream.
class EGLStreamPictureBuffer : public DXVAPictureBuffer {
public:
explicit EGLStreamPictureBuffer(const PictureBuffer& buffer);
~EGLStreamPictureBuffer() override;
bool Initialize();
bool ReusePictureBuffer() override;
bool BindSampleToTexture(DXVAVideoDecodeAccelerator* decoder,
Microsoft::WRL::ComPtr<IMFSample> sample) override;
bool AllowOverlay() const override;
bool CanBindSamples() const override;
private:
EGLStreamKHR stream_;
Microsoft::WRL::ComPtr<IMFSample> current_d3d_sample_;
ComD3D11Texture2D dx11_decoding_texture_;
};
// Creates an NV12 texture and copies to it, then shares that with ANGLE.
class EGLStreamCopyPictureBuffer : public DXVAPictureBuffer {
public:
explicit EGLStreamCopyPictureBuffer(const PictureBuffer& buffer);
~EGLStreamCopyPictureBuffer() override;
bool Initialize(const DXVAVideoDecodeAccelerator& decoder);
bool ReusePictureBuffer() override;
bool CopyOutputSampleDataToPictureBuffer(DXVAVideoDecodeAccelerator* decoder,
IDirect3DSurface9* dest_surface,
ID3D11Texture2D* dx11_texture,
int input_buffer_id) override;
bool CopySurfaceComplete(IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface) override;
bool AllowOverlay() const override;
bool CanBindSamples() const override;
private:
EGLStreamKHR stream_;
// This ID3D11Texture2D interface pointer is used to hold a reference to the
// MFT decoder texture during the course of a copy operation. This reference
// is released when the copy completes.
ComD3D11Texture2D dx11_decoding_texture_;
Microsoft::WRL::ComPtr<IDXGIKeyedMutex> egl_keyed_mutex_;
Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_;
HANDLE texture_share_handle_;
// This is the texture (created on ANGLE's device) that will be put in the
// EGLStream.
ComD3D11Texture2D angle_copy_texture_;
// This is another copy of that shared resource that will be copied to from
// the decoder.
ComD3D11Texture2D decoder_copy_texture_;
// This is the last value that was used to release the keyed mutex.
uint64_t keyed_mutex_value_ = 0;
};
} // namespace media
#endif // MEDIA_GPU_WINDOWS_DXVA_PICTURE_BUFFER_WIN_H_

File diff suppressed because it is too large Load Diff

@ -1,627 +0,0 @@
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_WINDOWS_DXVA_VIDEO_DECODE_ACCELERATOR_WIN_H_
#define MEDIA_GPU_WINDOWS_DXVA_VIDEO_DECODE_ACCELERATOR_WIN_H_
#include <d3d11_1.h>
#include <d3d9.h>
#include <dxva2api.h>
#include <initguid.h>
#include <mfidl.h>
#include <stdint.h>
#include <wrl/client.h>
#include <list>
#include <map>
#include <memory>
#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "gpu/config/gpu_preferences.h"
#include "media/base/video_color_space.h"
#include "media/gpu/gpu_video_decode_accelerator_helpers.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/windows/d3d11_com_defs.h"
#include "media/video/video_decode_accelerator.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gl/hdr_metadata_helper_win.h"
interface IMFSample;
interface IDirect3DSurface9;
namespace gl {
class GLContext;
class GLImageEGLStream;
}
namespace gpu {
class GpuDriverBugWorkarounds;
struct GpuPreferences;
} // namespace gpu
typedef HRESULT(WINAPI* CreateDXGIDeviceManager)(
UINT* reset_token,
IMFDXGIDeviceManager** device_manager);
namespace media {
class DXVAPictureBuffer;
class EGLStreamCopyPictureBuffer;
class EGLStreamPictureBuffer;
class MediaLog;
class PbufferPictureBuffer;
class ConfigChangeDetector {
public:
virtual ~ConfigChangeDetector();
virtual bool DetectConfig(const uint8_t* stream, unsigned int size) = 0;
virtual gfx::Rect current_visible_rect(
const gfx::Rect& container_visible_rect) const = 0;
virtual VideoColorSpace current_color_space(
const VideoColorSpace& container_color_space) const = 0;
virtual bool IsYUV420() const;
virtual bool is_vp9_resilient_mode() const;
bool config_changed() const { return config_changed_; }
protected:
// Set to true if we detect a stream configuration change.
bool config_changed_ = false;
};
// Class to provide a DXVA 2.0 based accelerator using the Microsoft Media
// foundation APIs via the VideoDecodeAccelerator interface.
// This class lives on a single thread and DCHECKs that it is never accessed
// from any other.
class MEDIA_GPU_EXPORT DXVAVideoDecodeAccelerator
: public VideoDecodeAccelerator {
public:
enum State {
kUninitialized, // un-initialized.
kNormal, // normal playing state.
kResetting, // upon received Reset(), before ResetDone()
kStopped, // upon output EOS received.
kFlushing, // upon flush request received.
};
// Does not take ownership of |client| which must outlive |*this|.
DXVAVideoDecodeAccelerator(
const GetGLContextCallback& get_gl_context_cb,
const MakeGLContextCurrentCallback& make_context_current_cb,
const BindGLImageCallback& bind_image_cb,
const gpu::GpuDriverBugWorkarounds& workarounds,
const gpu::GpuPreferences& gpu_preferences,
MediaLog* media_log);
DXVAVideoDecodeAccelerator(const DXVAVideoDecodeAccelerator&) = delete;
DXVAVideoDecodeAccelerator& operator=(const DXVAVideoDecodeAccelerator&) =
delete;
~DXVAVideoDecodeAccelerator() override;
// VideoDecodeAccelerator implementation.
bool Initialize(const Config& config, Client* client) override;
void Decode(BitstreamBuffer bitstream) override;
void Decode(scoped_refptr<DecoderBuffer> buffer,
int32_t bitstream_id) override;
void AssignPictureBuffers(const std::vector<PictureBuffer>& buffers) override;
void ReusePictureBuffer(int32_t picture_buffer_id) override;
void Flush() override;
void Reset() override;
void Destroy() override;
bool TryToSetupDecodeOnSeparateSequence(
const base::WeakPtr<Client>& decode_client,
const scoped_refptr<base::SequencedTaskRunner>& decode_task_runner)
override;
GLenum GetSurfaceInternalFormat() const override;
bool SupportsSharedImagePictureBuffers() const override;
static VideoDecodeAccelerator::SupportedProfiles GetSupportedProfiles(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& workarounds);
// Preload dlls required for decoding.
static void PreSandboxInitialization();
private:
friend class DXVAPictureBuffer;
friend class EGLStreamDelayedCopyPictureBuffer;
friend class EGLStreamCopyPictureBuffer;
friend class EGLStreamPictureBuffer;
friend class PbufferPictureBuffer;
typedef void* EGLConfig;
typedef void* EGLSurface;
typedef std::list<Microsoft::WRL::ComPtr<IMFSample>> PendingInputs;
// These are used for histograms, so don't change their numeric value (except
// for kMaxValue as described below).
enum class PictureBufferMechanism {
// Copy to either a BGRA8 or FP16 texture using the video processor.
COPY_TO_RGB = 0,
// Copy to another NV12 texture that can be used in ANGLE.
COPY_TO_NV12 = 1,
// Bind the resulting GLImage to the NV12 texture. If the texture's used
// in a an overlay than use it directly, otherwise copy it to another NV12
// texture when necessary -- no longer used
// DELAYED_COPY_TO_NV12 = 2,
// Bind the NV12 decoder texture directly to the texture used in ANGLE.
BIND = 3,
// For UMA. Must be the last entry. It should be initialized to the
// numerically largest value above; if you add more entries, then please
// update this to be the last one.
kMaxValue = BIND
};
// Creates and initializes an instance of the D3D device and the
// corresponding device manager. The device manager instance is eventually
// passed to the IMFTransform interface implemented by the decoder.
bool CreateD3DDevManager();
// TODO(hubbe): COMMENT
bool CreateVideoProcessor();
// Creates and initializes an instance of the DX11 device and the
// corresponding device manager. The device manager instance is eventually
// passed to the IMFTransform interface implemented by the decoder.
bool CreateDX11DevManager();
// Creates, initializes and sets the media codec types for the decoder.
bool InitDecoder(VideoCodecProfile profile);
// Validates whether the decoder supports hardware video acceleration.
bool CheckDecoderDxvaSupport();
// Returns information about the input and output streams. This includes
// alignment information, decoder support flags, minimum sample size, etc.
bool GetStreamsInfoAndBufferReqs();
// Registers the input and output media types on the decoder. This includes
// the expected input and output formats.
bool SetDecoderMediaTypes();
// Registers the input media type for the decoder.
bool SetDecoderInputMediaType();
// Registers the output media type for the decoder.
bool SetDecoderOutputMediaType(const GUID& subtype);
// Passes a command message to the decoder. This includes commands like
// start of stream, end of stream, flush, drain the decoder, etc.
bool SendMFTMessage(MFT_MESSAGE_TYPE msg, int32_t param);
// The bulk of the decoding happens here. This function handles errors,
// format changes and processes decoded output.
void DoDecode(const gfx::Rect& visible_rect,
const gfx::ColorSpace& color_space);
// Invoked when we have a valid decoded output sample. Retrieves the D3D
// surface and maintains a copy of it which is passed eventually to the
// client when we have a picture buffer to copy the surface contents to.
bool ProcessOutputSample(Microsoft::WRL::ComPtr<IMFSample> sample,
const gfx::Rect& visible_rect,
const gfx::ColorSpace& color_space);
// Processes pending output samples by copying them to available picture
// slots.
void ProcessPendingSamples();
// Helper function to notify the accelerator client about the error.
void StopOnError(VideoDecodeAccelerator::Error error);
// Transitions the decoder to the uninitialized state. The decoder will stop
// accepting requests in this state.
void Invalidate(bool for_config_change = false);
// Stop and join on the decoder thread.
void StopDecoderThread();
// Notifies the client that the input buffer identifed by input_buffer_id has
// been processed.
void NotifyInputBufferRead(int input_buffer_id);
// Notifies the client that the decoder was flushed.
void NotifyFlushDone();
// Notifies the client that the decoder was reset.
void NotifyResetDone();
// Requests picture buffers from the client.
void RequestPictureBuffers(int width, int height);
// Notifies the client about the availability of a picture.
void NotifyPictureReady(int picture_buffer_id,
int input_buffer_id,
const gfx::Rect& visible_rect,
const gfx::ColorSpace& color_space,
bool allow_overlay,
std::vector<scoped_refptr<Picture::ScopedSharedImage>>
shared_images = {});
// Sends pending input buffer processed acks to the client if we don't have
// output samples waiting to be processed.
void NotifyInputBuffersDropped(const PendingInputs& input_buffers);
// Decodes pending input buffers.
void DecodePendingInputBuffers();
// Helper for handling the Flush operation.
void FlushInternal();
// Helper for handling the Decode operation.
void DecodeInternal(const Microsoft::WRL::ComPtr<IMFSample>& input_sample);
// Handles mid stream resolution changes.
void HandleResolutionChanged(int width, int height);
using OutputBuffers = std::map<int32_t, std::unique_ptr<DXVAPictureBuffer>>;
// Tells the client to dismiss the stale picture buffers passed in.
void DismissStaleBuffers(bool force);
// Called after the client indicates we can recycle a stale picture buffer.
void DeferredDismissStaleBuffer(int32_t picture_buffer_id);
// Sets the state of the decoder. Called from the main thread and the decoder
// thread. The state is changed on the main thread.
void SetState(State state);
// Gets the state of the decoder. Can be called from the main thread and
// the decoder thread. Thread safe.
State GetState();
// Starts the thread used for decoding. Returns true on success.
bool StartDecoderThread();
// Returns if we have output samples waiting to be processed. We only
// allow one output sample to be present in the output queue at any given
// time.
bool OutputSamplesPresent();
// Copies the source surface |src_surface| to the destination |dest_surface|.
// The copying is done on the decoder thread.
void CopySurface(IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface,
int picture_buffer_id,
int input_buffer_id,
const gfx::ColorSpace& color_space);
// This is a notification that the source surface |src_surface| was copied to
// the destination |dest_surface|. Received on the main thread.
void CopySurfaceComplete(IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface,
int picture_buffer_id,
int input_buffer_id);
void BindPictureBufferToSample(Microsoft::WRL::ComPtr<IMFSample> sample,
int picture_buffer_id,
int input_buffer_id);
// Copies the source texture |src_texture| to the destination |dest_texture|.
// The copying is done on the decoder thread. Returns true on success.
bool CopyTexture(ID3D11Texture2D* src_texture,
ID3D11Texture2D* dest_texture,
Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dest_keyed_mutex,
uint64_t keyed_mutex_value,
int picture_buffer_id,
int input_buffer_id,
const gfx::ColorSpace& color_space);
// Copies the |video_frame| to the destination |dest_texture|.
void CopyTextureOnDecoderThread(
ID3D11Texture2D* dest_texture,
Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dest_keyed_mutex,
uint64_t keyed_mutex_value,
Microsoft::WRL::ComPtr<IMFSample> input_sample,
int picture_buffer_id,
int input_buffer_id);
// Flushes the decoder device to ensure that the decoded surface is copied
// to the target surface. |iterations| helps to maintain an upper limit on
// the number of times we try to complete the flush operation.
void FlushDecoder(int iterations,
IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface,
int picture_buffer_id,
int input_buffer_id);
// Polls to wait for GPU commands to be finished on the picture buffer
// before reusing it.
void WaitForOutputBuffer(int32_t picture_buffer_id, int count);
// Initialize the DX11 video processor.
// Returns true on success.
bool InitializeID3D11VideoProcessor(int width,
int height,
const gfx::ColorSpace& color_space);
// Some devices require HDR metadata. This will set it if needed, else
// do nothing.
void SetDX11ProcessorHDRMetadataIfNeeded();
// Returns the output video frame dimensions (width, height).
// |sample| :- This is the output sample containing the video frame.
// |width| :- The width is returned here.
// |height| :- The height is returned here.
// Returns true on success.
bool GetVideoFrameDimensions(IMFSample* sample, int* width, int* height);
// Sets the output type on the |transform| to the GUID identified by the
// the |output_type| parameter. The GUID can be MFVideoFormat_RGB32,
// MFVideoFormat_ARGB32, MFVideoFormat_NV12, etc.
// Additionally if the |width| and |height| parameters are non zero, then
// this function also sets the MF_MT_FRAME_SIZE attribute on the type.
// Returns true on success.
bool SetTransformOutputType(IMFTransform* transform,
const GUID& output_type,
int width,
int height);
// Checks if the resolution, bitrate etc of the stream changed. We do this
// by keeping track of the SPS/PPS frames and if they change we assume
// that the configuration changed.
// Returns S_OK or S_FALSE on success.
// The |config_changed| parameter is set to true if we detect a change in the
// stream.
HRESULT CheckConfigChanged(IMFSample* sample, bool* config_changed);
// Called when we detect a stream configuration change. We reinitialize the
// decoder here.
void ConfigChanged(const Config& config);
// Sets |support_share_nv12_textures_| to false and updates
// |num_picture_buffers_requested_|.
void DisableSharedTextureSupport();
// Creates ScopedSharedImages for the provided PictureBuffer. If the buffer
// has a GLImageEGLStream this function will create D3DImageBacking using the
// DX11 texture. Otherwise it will create thin GLImageBacking
// wrappers around the existing textures in |picture_buffer|.
std::vector<scoped_refptr<Picture::ScopedSharedImage>>
GetSharedImagesFromPictureBuffer(DXVAPictureBuffer* picture_buffer);
uint32_t GetTextureTarget() const;
PictureBufferMechanism GetPictureBufferMechanism() const;
bool ShouldUseANGLEDevice() const;
ID3D11Device* D3D11Device() const;
// To expose client callbacks from VideoDecodeAccelerator.
raw_ptr<VideoDecodeAccelerator::Client> client_;
Microsoft::WRL::ComPtr<IMFTransform> decoder_;
Microsoft::WRL::ComPtr<IDirect3D9Ex> d3d9_;
Microsoft::WRL::ComPtr<IDirect3DDevice9Ex> d3d9_device_ex_;
Microsoft::WRL::ComPtr<IDirect3DDeviceManager9> device_manager_;
Microsoft::WRL::ComPtr<IDirect3DQuery9> query_;
ComD3D11Device d3d11_device_;
ComD3D11Device angle_device_;
Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> d3d11_device_manager_;
Microsoft::WRL::ComPtr<ID3D10Multithread> multi_threaded_;
ComD3D11DeviceContext d3d11_device_context_;
ComD3D11Query d3d11_query_;
ComD3D11VideoDevice video_device_;
ComD3D11VideoContext video_context_;
ComD3D11VideoProcessorEnumerator enumerator_;
ComD3D11VideoProcessor d3d11_processor_;
int processor_width_ = 0;
int processor_height_ = 0;
// Used for lifetime progression logging. Have we logged that initialization
// was successful, and nothing since?
bool already_initialized_ = false;
Microsoft::WRL::ComPtr<IDirectXVideoProcessorService>
video_processor_service_;
Microsoft::WRL::ComPtr<IDirectXVideoProcessor> processor_;
DXVA2_ProcAmpValues default_procamp_values_;
// Ideally the reset token would be a stack variable which is used while
// creating the device manager. However it seems that the device manager
// holds onto the token and attempts to access it if the underlying device
// changes.
// TODO(ananta): This needs to be verified.
uint32_t dev_manager_reset_token_;
// Reset token for the DX11 device manager.
uint32_t dx11_dev_manager_reset_token_;
// The EGL config to use for decoded frames.
EGLConfig egl_config_;
// Current state of the decoder.
volatile State state_;
MFT_INPUT_STREAM_INFO input_stream_info_;
MFT_OUTPUT_STREAM_INFO output_stream_info_;
// Contains information about a decoded sample.
struct PendingSampleInfo {
PendingSampleInfo(int32_t buffer_id,
Microsoft::WRL::ComPtr<IMFSample> sample,
const gfx::Rect& visible_rect,
const gfx::ColorSpace& color_space);
PendingSampleInfo(const PendingSampleInfo& other);
~PendingSampleInfo();
int32_t input_buffer_id;
// The target picture buffer id where the frame would be copied to.
// Defaults to -1.
int picture_buffer_id;
gfx::Rect visible_rect;
// The color space of this picture.
gfx::ColorSpace color_space;
Microsoft::WRL::ComPtr<IMFSample> output_sample;
};
typedef std::list<PendingSampleInfo> PendingOutputSamples;
// List of decoded output samples. Protected by |decoder_lock_|.
PendingOutputSamples pending_output_samples_;
// This map maintains the picture buffers passed the client for decoding.
// The key is the picture buffer id.
OutputBuffers output_picture_buffers_;
// After a resolution change there may be a few output buffers which have yet
// to be displayed so they cannot be dismissed immediately. We move them from
// |output_picture_buffers_| to this map so they may be dismissed once they
// become available.
OutputBuffers stale_output_picture_buffers_;
// Set to true if we requested picture slots from the client.
bool pictures_requested_;
// Counter which holds the number of input packets before a successful
// decode.
int inputs_before_decode_;
// Set to true when the drain message is sent to the decoder during a flush
// operation. Used to ensure the message is only sent once after
// |pending_input_buffers_| is drained. Protected by |decoder_lock_|.
bool sent_drain_message_;
// This is the array size of the D3D11 texture that's output to by the
// decoder. It's only used for debugging.
uint32_t output_array_size_ = 0;
// List of input samples waiting to be processed.
PendingInputs pending_input_buffers_;
// Callback to get current GLContext.
GetGLContextCallback get_gl_context_cb_;
// Callback to set the correct gl context.
MakeGLContextCurrentCallback make_context_current_cb_;
BindGLImageCallback bind_image_cb_;
// This may be null, e.g. when not using MojoVideoDecoder.
const raw_ptr<MediaLog> media_log_;
// Which codec we are decoding with hardware acceleration.
VideoCodec codec_;
// Thread on which the decoder operations like passing input frames,
// getting output frames are performed. One instance of this thread
// is created per decoder instance.
base::Thread decoder_thread_;
// Task runner to be used for posting tasks to the decoder thread.
scoped_refptr<base::SingleThreadTaskRunner> decoder_thread_task_runner_;
// Task runner to be used for posting tasks to the main thread.
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
// Used to synchronize access between the decoder thread and the main thread.
base::Lock decoder_lock_;
// Disallow rebinding WeakReference ownership to a different thread by
// keeping a persistent reference. This avoids problems with the
// thread safety of reaching into this class from multiple threads to
// attain a WeakPtr.
base::WeakPtr<DXVAVideoDecodeAccelerator> weak_ptr_;
// Set to true if we are in the context of a Flush operation. Used to prevent
// multiple flush done notifications being sent out.
bool pending_flush_;
// Use CODECAPI_AVLowLatencyMode.
bool enable_low_latency_;
// Supports sharing the decoded NV12 textures with ANGLE
bool support_share_nv12_textures_;
// Number of requested picture buffers from the client which are used to hold
// the decoded samples.
int num_picture_buffers_requested_;
// Supports copying the NV12 texture to another NV12 texture to use in
// ANGLE.
bool support_copy_nv12_textures_;
// Copy video to FP16 scRGB textures.
bool use_fp16_ = false;
// True if decoder's output is P010/P016.
bool decoder_output_p010_or_p016_ = false;
// When converting YUV to RGB, make sure we tell the blitter about the input
// color space so that it can convert it correctly.
bool use_color_info_ = true;
// Defaults to false. Indicates if we should use D3D or DX11 interfaces for
// H/W decoding.
bool use_dx11_;
// True when using Microsoft's VPx HMFT for decoding.
bool using_ms_vpx_mft_ = false;
// True if we should use DXGI keyed mutexes to synchronize between the two
// contexts.
bool use_keyed_mutex_;
// Outputs from the dx11 format converter will be in this color space.
gfx::ColorSpace dx11_converter_output_color_space_;
// Set to true if we are sharing ANGLE's device.
bool using_angle_device_;
bool using_debug_device_;
// Enables hardware acceleration for AV1 video decoding.
const bool enable_accelerated_av1_decode_;
// Enables hardware acceleration for VP8/VP9 video decoding.
const bool enable_accelerated_vp8_decode_;
const bool enable_accelerated_vp9_decode_;
const bool disallow_vp9_resilient_dxva_decoding_;
// The media foundation H.264 decoder has problems handling changes like
// resolution change, bitrate change etc. If we reinitialize the decoder
// when these changes occur then, the decoder works fine. The
// H264ConfigChangeDetector class provides functionality to check if the
// stream configuration changed.
std::unique_ptr<ConfigChangeDetector> config_change_detector_;
// Contains the initialization parameters for the video.
Config config_;
// Set to true if we are processing a video configuration change.
bool processing_config_changed_;
// Contain the visible rect and color space of frames that are currently being
// fed into the decoder. These may change at a config change.
gfx::Rect current_visible_rect_;
VideoColorSpace current_color_space_;
absl::optional<gl::HDRMetadataHelperWin> hdr_metadata_helper_;
bool use_empty_video_hdr_metadata_ = false;
// Have we delivered any decoded frames since the last call to Initialize()?
bool decoded_any_frames_ = false;
// WeakPtrFactory for posting tasks back to |this|.
base::WeakPtrFactory<DXVAVideoDecodeAccelerator> weak_this_factory_{this};
// Function pointer for the MFCreateDXGIDeviceManager API.
static CreateDXGIDeviceManager create_dxgi_device_manager_;
};
} // namespace media
#endif // MEDIA_GPU_WINDOWS_DXVA_VIDEO_DECODE_ACCELERATOR_WIN_H_

@ -1,39 +0,0 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/windows/gl_image_egl_stream.h"
#include <d3d11_1.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_surface_egl.h"
namespace media {
GLImageEGLStream::GLImageEGLStream(const gfx::Size& size, EGLStreamKHR stream)
: size_(size), stream_(stream) {}
gl::GLImage::Type GLImageEGLStream::GetType() const {
return Type::EGL_STREAM;
}
void GLImageEGLStream::SetTexture(
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture,
size_t level) {
texture_ = texture;
level_ = level;
}
GLImageEGLStream::~GLImageEGLStream() {
if (stream_) {
eglDestroyStreamKHR(gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay(),
stream_);
}
}
} // namespace media

@ -1,43 +0,0 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_WINDOWS_GL_IMAGE_EGL_STREAM_H_
#define MEDIA_GPU_WINDOWS_GL_IMAGE_EGL_STREAM_H_
#include <d3d11.h>
#include <wrl/client.h>
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_image.h"
typedef void* EGLStreamKHR;
typedef void* EGLConfig;
typedef void* EGLSurface;
namespace media {
class GLImageEGLStream : public gl::GLImage {
public:
GLImageEGLStream(const gfx::Size& size, EGLStreamKHR stream);
// GLImage implementation.
Type GetType() const override;
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture() { return texture_; }
size_t level() const { return level_; }
void SetTexture(const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture,
size_t level);
protected:
~GLImageEGLStream() override;
gfx::Size size_;
EGLStreamKHR stream_ = nullptr;
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture_;
size_t level_ = 0;
};
} // namespace media
#endif // MEDIA_GPU_WINDOWS_GL_IMAGE_EGL_STREAM_H_

@ -1,29 +0,0 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/windows/gl_image_pbuffer.h"
#include "base/logging.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_surface_egl.h"
namespace media {
GLImagePbuffer::GLImagePbuffer(const gfx::Size& size, EGLSurface surface)
: size_(size), surface_(surface) {}
gl::GLImage::Type GLImagePbuffer::GetType() const {
return gl::GLImage::Type::PBUFFER;
}
void SetColorSpace(const gfx::ColorSpace& color_space) {}
GLImagePbuffer::~GLImagePbuffer() {
EGLDisplay egl_display = gl::GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay();
eglReleaseTexImage(egl_display, surface_, EGL_BACK_BUFFER);
eglDestroySurface(egl_display, surface_);
}
} // namespace media

@ -1,34 +0,0 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_WINDOWS_GL_IMAGE_PBUFFER_H_
#define MEDIA_GPU_WINDOWS_GL_IMAGE_PBUFFER_H_
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_image.h"
namespace media {
// GLImagePbuffer is just used to hold references to the underlying
// image content so it can be destroyed when the textures are.
class GLImagePbuffer final : public gl::GLImage {
public:
GLImagePbuffer(const gfx::Size& size, EGLSurface surface);
// gl::GLImage implementation.
gl::GLImage::Type GetType() const override;
private:
~GLImagePbuffer() override;
gfx::Size size_;
EGLSurface surface_;
};
} // namespace media
#endif // MEDIA_GPU_WINDOWS_GL_IMAGE_PBUFFER_H_

@ -11,7 +11,6 @@
#include "media/base/media_switches.h"
#include "media/base/offloading_audio_encoder.h"
#include "media/filters/win/media_foundation_audio_decoder.h"
#include "media/gpu/ipc/service/vda_video_decoder.h"
#include "media/gpu/windows/d3d11_video_decoder.h"
#include "media/gpu/windows/mf_audio_encoder.h"
#include "ui/gl/direct_composition_support.h"
@ -31,15 +30,7 @@ D3D11VideoDecoder::GetD3D11DeviceCB GetD3D11DeviceCallback() {
std::unique_ptr<VideoDecoder> CreatePlatformVideoDecoder(
VideoDecoderTraits& traits) {
if (traits.gpu_workarounds->disable_d3d11_video_decoder) {
if (traits.gpu_workarounds->disable_dxva_video_decoder ||
!base::FeatureList::IsEnabled(kDXVAVideoDecoding)) {
return nullptr;
}
return VdaVideoDecoder::Create(
traits.task_runner, traits.gpu_task_runner, traits.media_log->Clone(),
*traits.target_color_space, traits.gpu_preferences,
*traits.gpu_workarounds, traits.get_command_buffer_stub_cb,
VideoDecodeAccelerator::Config::OutputMode::ALLOCATE);
return nullptr;
}
// Report that HDR is enabled if any display has HDR enabled.
bool hdr_enabled = false;
@ -74,8 +65,6 @@ GetPlatformSupportedVideoDecoderConfigs(
if (!gpu_workarounds.disable_d3d11_video_decoder) {
supported_configs = D3D11VideoDecoder::GetSupportedVideoDecoderConfigs(
gpu_preferences, gpu_workarounds, GetD3D11DeviceCallback());
} else if (!gpu_workarounds.disable_dxva_video_decoder) {
supported_configs = std::move(get_vda_configs).Run();
}
return supported_configs;
}
@ -90,8 +79,7 @@ VideoDecoderType GetPlatformDecoderImplementationType(
gpu::GpuDriverBugWorkarounds gpu_workarounds,
gpu::GpuPreferences gpu_preferences,
const gpu::GPUInfo& gpu_info) {
return gpu_workarounds.disable_d3d11_video_decoder ? VideoDecoderType::kVda
: VideoDecoderType::kD3D11;
return VideoDecoderType::kD3D11;
}
// There is no CdmFactory on windows, so just stub it out.

@ -22,22 +22,6 @@ GLImageD3D* GLImage::ToGLImageD3D(GLImage* image) {
return reinterpret_cast<GLImageD3D*>(image);
}
// static
// static
media::GLImageEGLStream* GLImage::ToGLImageEGLStream(GLImage* image) {
if (!image || image->GetType() != Type::EGL_STREAM) {
return nullptr;
}
return reinterpret_cast<media::GLImageEGLStream*>(image);
}
// static
media::GLImagePbuffer* GLImage::ToGLImagePbuffer(GLImage* image) {
if (!image || image->GetType() != Type::PBUFFER)
return nullptr;
return reinterpret_cast<media::GLImagePbuffer*>(image);
}
GLImage::Type GLImage::GetType() const {
return Type::NONE;
}

@ -22,12 +22,6 @@ class GLES2DecoderImpl;
class GLES2DecoderPassthroughImpl;
} // namespace gpu::gles2
namespace media {
class GLImageEGLStream;
class GLImagePbuffer;
class DXVAVideoDecodeAccelerator;
}
namespace gl {
class GLImageD3D;
@ -58,15 +52,12 @@ class GL_EXPORT GLImage : public base::RefCounted<GLImage> {
// Safe downcasts. All functions return nullptr if |image| does not exist or
// does not have the specified type.
static GLImageD3D* ToGLImageD3D(GLImage* image);
static media::GLImageEGLStream* ToGLImageEGLStream(GLImage* image);
static media::GLImagePbuffer* ToGLImagePbuffer(GLImage* image);
friend class gpu::D3DImageBacking;
friend class gpu::D3DImageBackingFactoryTest;
friend class gpu::GLTexturePassthroughD3DImageRepresentation;
friend class gpu::gles2::GLES2DecoderImpl;
friend class gpu::gles2::GLES2DecoderPassthroughImpl;
friend class media::DXVAVideoDecodeAccelerator;
FRIEND_TEST_ALL_PREFIXES(gpu::D3DImageBackingFactoryTestSwapChain,
CreateAndPresentSwapChain);