| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "media/gpu/windows/d3d11_video_processor_proxy.h" |
| |
| #include "media/base/status_codes.h" |
| #include "media/gpu/windows/hresult_status_debug_device.h" |
| #include "ui/gfx/color_space_win.h" |
| |
| namespace media { |
| |
| VideoProcessorProxy::~VideoProcessorProxy() {} |
| |
| VideoProcessorProxy::VideoProcessorProxy( |
| ComD3D11VideoDevice video_device, |
| ComD3D11DeviceContext d3d11_device_context) |
| : video_device_(video_device), device_context_(d3d11_device_context) {} |
| |
| Status VideoProcessorProxy::Init(uint32_t width, uint32_t height) { |
| processor_enumerator_.Reset(); |
| video_processor_.Reset(); |
| |
| D3D11_VIDEO_PROCESSOR_CONTENT_DESC desc; |
| desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE; |
| desc.InputFrameRate.Numerator = 60; |
| desc.InputFrameRate.Denominator = 1; |
| desc.InputWidth = width; |
| desc.InputHeight = height; |
| desc.OutputFrameRate.Numerator = 60; |
| desc.OutputFrameRate.Denominator = 1; |
| desc.OutputWidth = width; |
| desc.OutputHeight = height; |
| desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL; |
| |
| // Get the device in case we need it for error generation. |
| ComD3D11Device device; |
| device_context_->GetDevice(&device); |
| |
| HRESULT hr = video_device_->CreateVideoProcessorEnumerator( |
| &desc, &processor_enumerator_); |
| if (!SUCCEEDED(hr)) { |
| return Status(StatusCode::kCreateVideoProcessorEnumeratorFailed) |
| .AddCause(D3D11HresultToStatus(hr, device)); |
| } |
| |
| hr = video_device_->CreateVideoProcessor(processor_enumerator_.Get(), 0, |
| &video_processor_); |
| if (!SUCCEEDED(hr)) { |
| return Status(StatusCode::kCreateVideoProcessorFailed) |
| .AddCause(D3D11HresultToStatus(hr, device)); |
| } |
| |
| hr = device_context_.As(&video_context_); |
| if (!SUCCEEDED(hr)) { |
| return Status(StatusCode::kQueryVideoContextFailed) |
| .AddCause(D3D11HresultToStatus(hr, device)); |
| } |
| |
| return OkStatus(); |
| } |
| |
| HRESULT VideoProcessorProxy::CreateVideoProcessorOutputView( |
| ID3D11Texture2D* output_texture, |
| D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* output_view_descriptor, |
| ID3D11VideoProcessorOutputView** output_view) { |
| return video_device_->CreateVideoProcessorOutputView( |
| output_texture, processor_enumerator_.Get(), output_view_descriptor, |
| output_view); |
| } |
| |
| HRESULT VideoProcessorProxy::CreateVideoProcessorInputView( |
| ID3D11Texture2D* input_texture, |
| D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* input_view_descriptor, |
| ID3D11VideoProcessorInputView** input_view) { |
| return video_device_->CreateVideoProcessorInputView( |
| input_texture, processor_enumerator_.Get(), input_view_descriptor, |
| input_view); |
| } |
| |
| void VideoProcessorProxy::SetStreamColorSpace( |
| const gfx::ColorSpace& color_space) { |
| ComD3D11VideoContext1 video_context1; |
| |
| // Try to use the 11.1 interface if possible, else use 11.0. |
| if (FAILED(video_context_.As(&video_context1))) { |
| // Note that if we have an HDR context but no 11.1 device, then this will |
| // likely not work. |
| auto d3d11_color_space = |
| gfx::ColorSpaceWin::GetD3D11ColorSpace(color_space); |
| video_context_->VideoProcessorSetStreamColorSpace(video_processor_.Get(), 0, |
| &d3d11_color_space); |
| } else { |
| video_context1->VideoProcessorSetStreamColorSpace1( |
| video_processor_.Get(), 0, |
| gfx::ColorSpaceWin::GetDXGIColorSpace(color_space)); |
| } |
| } |
| |
| void VideoProcessorProxy::SetOutputColorSpace( |
| const gfx::ColorSpace& color_space) { |
| ComD3D11VideoContext1 video_context1; |
| if (FAILED(video_context_.As(&video_context1))) { |
| // Hopefully, |color_space| is supported, but that's not our problem. |
| auto d3d11_color_space = |
| gfx::ColorSpaceWin::GetD3D11ColorSpace(color_space); |
| video_context_->VideoProcessorSetOutputColorSpace(video_processor_.Get(), |
| &d3d11_color_space); |
| } else { |
| video_context1->VideoProcessorSetOutputColorSpace1( |
| video_processor_.Get(), |
| gfx::ColorSpaceWin::GetDXGIColorSpace(color_space)); |
| } |
| } |
| |
| void VideoProcessorProxy::SetStreamHDRMetadata( |
| const DXGI_HDR_METADATA_HDR10& stream_metadata) { |
| ComD3D11VideoContext2 video_context2; |
| if (FAILED(video_context_.As(&video_context2))) |
| return; |
| |
| // TODO: we shouldn't do this unless we also set the display metadata. |
| video_context2->VideoProcessorSetOutputHDRMetaData( |
| video_processor_.Get(), DXGI_HDR_METADATA_TYPE_HDR10, |
| sizeof(stream_metadata), &stream_metadata); |
| } |
| |
| void VideoProcessorProxy::SetDisplayHDRMetadata( |
| const DXGI_HDR_METADATA_HDR10& display_metadata) { |
| ComD3D11VideoContext2 video_context2; |
| if (FAILED(video_context_.As(&video_context2))) |
| return; |
| |
| video_context2->VideoProcessorSetOutputHDRMetaData( |
| video_processor_.Get(), DXGI_HDR_METADATA_TYPE_HDR10, |
| sizeof(display_metadata), &display_metadata); |
| } |
| |
| HRESULT VideoProcessorProxy::VideoProcessorBlt( |
| ID3D11VideoProcessorOutputView* output_view, |
| UINT output_frameno, |
| UINT stream_count, |
| D3D11_VIDEO_PROCESSOR_STREAM* streams) { |
| return video_context_->VideoProcessorBlt(video_processor_.Get(), output_view, |
| output_frameno, stream_count, |
| streams); |
| } |
| |
| } // namespace media |