Index: media/gpu/dxva_video_decode_accelerator_win.cc |
diff --git a/media/gpu/dxva_video_decode_accelerator_win.cc b/media/gpu/dxva_video_decode_accelerator_win.cc |
index 13e3af05bd14f0b51a00fb94baf9706c9349d889..01d2655876620a0465db015d220fd891cd83eae6 100644 |
--- a/media/gpu/dxva_video_decode_accelerator_win.cc |
+++ b/media/gpu/dxva_video_decode_accelerator_win.cc |
@@ -496,10 +496,11 @@ DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( |
decoder_thread_("DXVAVideoDecoderThread"), |
pending_flush_(false), |
enable_low_latency_(gpu_preferences.enable_low_latency_dxva), |
- share_nv12_textures_(gpu_preferences.enable_zero_copy_dxgi_video && |
- !workarounds.disable_dxgi_zero_copy_video), |
- copy_nv12_textures_(gpu_preferences.enable_nv12_dxgi_video && |
- !workarounds.disable_nv12_dxgi_video), |
+ support_share_nv12_textures_( |
+ gpu_preferences.enable_zero_copy_dxgi_video && |
+ !workarounds.disable_dxgi_zero_copy_video), |
+ support_copy_nv12_textures_(gpu_preferences.enable_nv12_dxgi_video && |
+ !workarounds.disable_nv12_dxgi_video), |
use_dx11_(false), |
use_keyed_mutex_(false), |
using_angle_device_(false), |
@@ -543,8 +544,8 @@ bool DXVAVideoDecodeAccelerator::Initialize(const Config& config, |
if (!config.supported_output_formats.empty() && |
!base::ContainsValue(config.supported_output_formats, |
PIXEL_FORMAT_NV12)) { |
- share_nv12_textures_ = false; |
- copy_nv12_textures_ = false; |
+ support_share_nv12_textures_ = false; |
+ support_copy_nv12_textures_ = false; |
} |
bool profile_supported = false; |
@@ -806,15 +807,19 @@ bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); |
angle_device_ = gl::QueryD3D11DeviceObjectFromANGLE(); |
- if (!angle_device_) |
- copy_nv12_textures_ = false; |
- if (share_nv12_textures_) { |
+ if (!angle_device_) { |
+ support_copy_nv12_textures_ = false; |
+ } |
+ if (ShouldUseANGLEDevice()) { |
RETURN_ON_FAILURE(angle_device_.Get(), "Failed to get d3d11 device", false); |
using_angle_device_ = true; |
- } |
+ DCHECK(!use_fp16_); |
+ angle_device_->GetImmediateContext(d3d11_device_context_.GetAddressOf()); |
- if (use_fp16_ || !share_nv12_textures_) { |
+ hr = angle_device_.CopyTo(video_device_.GetAddressOf()); |
+ RETURN_ON_HR_FAILURE(hr, "Failed to get video device", false); |
+ } else { |
// This array defines the set of DirectX hardware feature levels we support. |
// The ordering MUST be preserved. All applications are assumed to support |
// 9.1 unless otherwise stated by the application. |
@@ -853,11 +858,11 @@ bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
hr = d3d11_device_.CopyTo(video_device_.GetAddressOf()); |
RETURN_ON_HR_FAILURE(hr, "Failed to get video device", false); |
- |
- hr = d3d11_device_context_.CopyTo(video_context_.GetAddressOf()); |
- RETURN_ON_HR_FAILURE(hr, "Failed to get video context", false); |
} |
+ hr = d3d11_device_context_.CopyTo(video_context_.GetAddressOf()); |
+ RETURN_ON_HR_FAILURE(hr, "Failed to get video context", false); |
+ |
D3D11_FEATURE_DATA_D3D11_OPTIONS options; |
hr = D3D11Device()->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, |
sizeof(options)); |
@@ -866,7 +871,7 @@ bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
// Need extended resource sharing so we can share the NV12 texture between |
// ANGLE and the decoder context. |
if (!options.ExtendedResourceSharing) |
- copy_nv12_textures_ = false; |
+ support_copy_nv12_textures_ = false; |
UINT nv12_format_support = 0; |
hr = |
@@ -874,7 +879,7 @@ bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
RETURN_ON_HR_FAILURE(hr, "Failed to check NV12 format support", false); |
if (!(nv12_format_support & D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_OUTPUT)) |
- copy_nv12_textures_ = false; |
+ support_copy_nv12_textures_ = false; |
UINT fp16_format_support = 0; |
hr = D3D11Device()->CheckFormatSupport(DXGI_FORMAT_R16G16B16A16_FLOAT, |
@@ -979,7 +984,7 @@ void DXVAVideoDecodeAccelerator::AssignPictureBuffers( |
// texture ids. This call just causes the texture manager to hold a |
// reference to the GLImage as long as either texture exists. |
bind_image_cb_.Run(client_id, GetTextureTarget(), |
- picture_buffer->gl_image(), true); |
+ picture_buffer->gl_image(), false); |
} |
} |
@@ -1040,6 +1045,16 @@ void DXVAVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { |
RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(), |
"Failed to reuse picture buffer", |
PLATFORM_FAILURE, ); |
+ if (bind_image_cb_ && (GetPictureBufferMechanism() == |
+ PictureBufferMechanism::DELAYED_COPY_TO_NV12)) { |
+ // Unbind the image to ensure it will be copied again the next time it's |
+ // needed. |
+ for (uint32_t client_id : |
+ it->second->picture_buffer().client_texture_ids()) { |
+ bind_image_cb_.Run(client_id, GetTextureTarget(), |
+ it->second->gl_image(), false); |
+ } |
+ } |
ProcessPendingSamples(); |
if (pending_flush_) { |
@@ -1590,8 +1605,8 @@ bool DXVAVideoDecodeAccelerator::InitDecoder(VideoCodecProfile profile) { |
if (use_fp16_) { |
// TODO(hubbe): Share/copy P010/P016 textures. |
- share_nv12_textures_ = false; |
- copy_nv12_textures_ = false; |
+ support_share_nv12_textures_ = false; |
+ support_copy_nv12_textures_ = false; |
} |
return SetDecoderMediaTypes(); |
@@ -1643,15 +1658,15 @@ bool DXVAVideoDecodeAccelerator::CheckDecoderDxvaSupport() { |
!gl::g_driver_egl.ext.b_EGL_KHR_stream || |
!gl::g_driver_egl.ext.b_EGL_KHR_stream_consumer_gltexture || |
!gl::g_driver_egl.ext.b_EGL_NV_stream_consumer_gltexture_yuv) { |
- share_nv12_textures_ = false; |
- copy_nv12_textures_ = false; |
+ support_share_nv12_textures_ = false; |
+ support_copy_nv12_textures_ = false; |
} |
// The MS VP9 MFT doesn't pass through the bind flags we specify, so |
// textures aren't created with D3D11_BIND_SHADER_RESOURCE and can't be used |
// from ANGLE. |
if (using_ms_vp9_mft_) |
- share_nv12_textures_ = false; |
+ support_share_nv12_textures_ = false; |
return true; |
} |
@@ -1710,7 +1725,7 @@ bool DXVAVideoDecodeAccelerator::SetDecoderOutputMediaType( |
const GUID& subtype) { |
bool result = SetTransformOutputType(decoder_.Get(), subtype, 0, 0); |
- if (share_nv12_textures_) { |
+ if (GetPictureBufferMechanism() == PictureBufferMechanism::BIND) { |
base::win::ScopedComPtr<IMFAttributes> out_attributes; |
HRESULT hr = |
decoder_->GetOutputStreamAttributes(0, out_attributes.GetAddressOf()); |
@@ -1938,7 +1953,7 @@ void DXVAVideoDecodeAccelerator::ProcessPendingSamples() { |
index->second->set_bound(); |
index->second->set_color_space(pending_sample->color_space); |
- if (share_nv12_textures_) { |
+ if (index->second->CanBindSamples()) { |
main_thread_task_runner_->PostTask( |
FROM_HERE, |
base::Bind(&DXVAVideoDecodeAccelerator::BindPictureBufferToSample, |
@@ -2109,7 +2124,8 @@ void DXVAVideoDecodeAccelerator::RequestPictureBuffers(int width, int height) { |
// per picture buffer, 1 for the Y channel and 1 for the UV channels. |
// They're shared to ANGLE using EGL_NV_stream_consumer_gltexture_yuv, so |
// they need to be GL_TEXTURE_EXTERNAL_OES. |
- bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_; |
+ bool provide_nv12_textures = |
+ GetPictureBufferMechanism() != PictureBufferMechanism::COPY_TO_RGB; |
client_->ProvidePictureBuffers( |
kNumPictureBuffers, |
provide_nv12_textures ? PIXEL_FORMAT_NV12 : PIXEL_FORMAT_UNKNOWN, |
@@ -2589,7 +2605,7 @@ void DXVAVideoDecodeAccelerator::BindPictureBufferToSample( |
DCHECK(!output_picture_buffers_.empty()); |
- bool result = picture_buffer->BindSampleToTexture(sample); |
+ bool result = picture_buffer->BindSampleToTexture(this, sample); |
RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", |
PLATFORM_FAILURE, ); |
@@ -2847,7 +2863,9 @@ bool DXVAVideoDecodeAccelerator::InitializeID3D11VideoProcessor( |
d3d11_processor_.Get(), 0, false); |
} |
- if (copy_nv12_textures_) { |
+ if (GetPictureBufferMechanism() == PictureBufferMechanism::COPY_TO_NV12 || |
+ GetPictureBufferMechanism() == |
+ PictureBufferMechanism::DELAYED_COPY_TO_NV12) { |
// If we're copying NV12 textures, make sure we set the same |
// color space on input and output. |
D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = {0}; |
@@ -3022,12 +3040,46 @@ void DXVAVideoDecodeAccelerator::ConfigChanged(const Config& config) { |
} |
uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const { |
- bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_; |
- return provide_nv12_textures ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; |
+ switch (GetPictureBufferMechanism()) { |
+ case PictureBufferMechanism::BIND: |
+ case PictureBufferMechanism::DELAYED_COPY_TO_NV12: |
+ case PictureBufferMechanism::COPY_TO_NV12: |
+ return GL_TEXTURE_EXTERNAL_OES; |
+ case PictureBufferMechanism::COPY_TO_RGB: |
+ return GL_TEXTURE_2D; |
+ } |
+ NOTREACHED(); |
+ return 0; |
+} |
+ |
+DXVAVideoDecodeAccelerator::PictureBufferMechanism |
+DXVAVideoDecodeAccelerator::GetPictureBufferMechanism() const { |
+ if (use_fp16_) |
+ return PictureBufferMechanism::COPY_TO_RGB; |
+ if (support_share_nv12_textures_) |
+ return PictureBufferMechanism::BIND; |
+ if (base::FeatureList::IsEnabled(kDelayCopyNV12Textures) && |
+ support_copy_nv12_textures_) |
+ return PictureBufferMechanism::DELAYED_COPY_TO_NV12; |
+ if (support_copy_nv12_textures_) |
+ return PictureBufferMechanism::COPY_TO_NV12; |
+ return PictureBufferMechanism::COPY_TO_RGB; |
+} |
+ |
+bool DXVAVideoDecodeAccelerator::ShouldUseANGLEDevice() const { |
+ switch (GetPictureBufferMechanism()) { |
+ case PictureBufferMechanism::BIND: |
+ case PictureBufferMechanism::DELAYED_COPY_TO_NV12: |
+ return true; |
+ case PictureBufferMechanism::COPY_TO_NV12: |
+ case PictureBufferMechanism::COPY_TO_RGB: |
+ return false; |
+ } |
+ NOTREACHED(); |
+ return false; |
} |
- |
ID3D11Device* DXVAVideoDecodeAccelerator::D3D11Device() const { |
- return share_nv12_textures_ ? angle_device_.Get() : d3d11_device_.Get(); |
+ return ShouldUseANGLEDevice() ? angle_device_.Get() : d3d11_device_.Get(); |
} |
} // namespace media |