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:

committed by
Chromium LUCI CQ

parent
895988a8d3
commit
51f418c2a3
base/trace_event
content
gpu
test
gpu
gpu_tests
gpu/config
media
ui/gl
@ -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, ¤t_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);
|
||||
|
||||
|
Reference in New Issue
Block a user