OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/media/dxva_video_decode_accelerator_win.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator_win.h" |
6 | 6 |
7 #if !defined(OS_WIN) | 7 #if !defined(OS_WIN) |
8 #error This file should only be built on Windows. | 8 #error This file should only be built on Windows. |
9 #endif // !defined(OS_WIN) | 9 #endif // !defined(OS_WIN) |
10 | 10 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 #endif | 102 #endif |
103 | 103 |
104 // MF_XVP_PLAYBACK_MODE | 104 // MF_XVP_PLAYBACK_MODE |
105 // Data type: UINT32 (treat as BOOL) | 105 // Data type: UINT32 (treat as BOOL) |
106 // If this attribute is TRUE, the video processor will run in playback mode | 106 // If this attribute is TRUE, the video processor will run in playback mode |
107 // where it allows callers to allocate output samples and allows last frame | 107 // where it allows callers to allocate output samples and allows last frame |
108 // regeneration (repaint). | 108 // regeneration (repaint). |
109 DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, | 109 DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, |
110 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); | 110 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); |
111 | 111 |
| 112 // Helper class to automatically lock unlock the DX11 device in a scope. |
| 113 class AutoDX11DeviceLock { |
| 114 public: |
| 115 explicit AutoDX11DeviceLock(ID3D10Multithread* multi_threaded) |
| 116 : multi_threaded_(multi_threaded) { |
| 117 multi_threaded_->Enter(); |
| 118 } |
| 119 |
| 120 ~AutoDX11DeviceLock() { |
| 121 multi_threaded_->Leave(); |
| 122 } |
| 123 |
| 124 private: |
| 125 base::win::ScopedComPtr<ID3D10Multithread> multi_threaded_; |
| 126 |
| 127 DISALLOW_COPY_AND_ASSIGN(AutoDX11DeviceLock); |
| 128 }; |
| 129 |
112 } // namespace | 130 } // namespace |
113 | 131 |
114 namespace content { | 132 namespace content { |
115 | 133 |
116 static const media::VideoCodecProfile kSupportedProfiles[] = { | 134 static const media::VideoCodecProfile kSupportedProfiles[] = { |
117 media::H264PROFILE_BASELINE, | 135 media::H264PROFILE_BASELINE, |
118 media::H264PROFILE_MAIN, | 136 media::H264PROFILE_MAIN, |
119 media::H264PROFILE_HIGH, | 137 media::H264PROFILE_HIGH, |
120 media::VP8PROFILE_ANY, | 138 media::VP8PROFILE_ANY, |
121 media::VP9PROFILE_ANY | 139 media::VP9PROFILE_ANY |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 | 805 |
788 base::win::ScopedComPtr<ID3D11Device> angle_device = | 806 base::win::ScopedComPtr<ID3D11Device> angle_device = |
789 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); | 807 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); |
790 RETURN_ON_FAILURE( | 808 RETURN_ON_FAILURE( |
791 angle_device.get(), | 809 angle_device.get(), |
792 "Failed to query DX11 device object from ANGLE", | 810 "Failed to query DX11 device object from ANGLE", |
793 false); | 811 false); |
794 | 812 |
795 using_angle_device_ = true; | 813 using_angle_device_ = true; |
796 d3d11_device_ = angle_device; | 814 d3d11_device_ = angle_device; |
797 d3d11_device_->GetImmediateContext(d3d11_device_context_.Receive()); | |
798 RETURN_ON_FAILURE( | |
799 d3d11_device_context_.get(), | |
800 "Failed to query DX11 device context from ANGLE device", | |
801 false); | |
802 | 815 |
803 // Enable multithreaded mode on the device. This ensures that accesses to | 816 // Enable multithreaded mode on the device. This ensures that accesses to |
804 // context are synchronized across threads. We have multiple threads | 817 // context are synchronized across threads. We have multiple threads |
805 // accessing the context, the media foundation decoder threads and the | 818 // accessing the context, the media foundation decoder threads and the |
806 // decoder thread via the video format conversion transform. | 819 // decoder thread via the video format conversion transform. |
807 hr = multi_threaded_.QueryFrom(angle_device.get()); | 820 hr = multi_threaded_.QueryFrom(angle_device.get()); |
808 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false); | 821 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false); |
809 multi_threaded_->SetMultithreadProtected(TRUE); | 822 multi_threaded_->SetMultithreadProtected(TRUE); |
810 | 823 |
811 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(), | 824 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(), |
812 dx11_dev_manager_reset_token_); | 825 dx11_dev_manager_reset_token_); |
813 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); | 826 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); |
814 | 827 |
815 D3D11_QUERY_DESC query_desc; | |
816 query_desc.Query = D3D11_QUERY_EVENT; | |
817 query_desc.MiscFlags = 0; | |
818 hr = d3d11_device_->CreateQuery( | |
819 &query_desc, | |
820 d3d11_query_.Receive()); | |
821 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false); | |
822 | |
823 HMODULE video_processor_dll = ::GetModuleHandle(L"msvproc.dll"); | 828 HMODULE video_processor_dll = ::GetModuleHandle(L"msvproc.dll"); |
824 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor", | 829 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor", |
825 false); | 830 false); |
826 | 831 |
827 hr = CreateCOMObjectFromDll( | 832 hr = CreateCOMObjectFromDll( |
828 video_processor_dll, | 833 video_processor_dll, |
829 CLSID_VideoProcessorMFT, | 834 CLSID_VideoProcessorMFT, |
830 __uuidof(IMFTransform), | 835 __uuidof(IMFTransform), |
831 video_format_converter_mft_.ReceiveVoid()); | 836 video_format_converter_mft_.ReceiveVoid()); |
832 if (FAILED(hr)) { | 837 if (FAILED(hr)) { |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1520 pending_output_samples_.clear(); | 1525 pending_output_samples_.clear(); |
1521 pending_input_buffers_.clear(); | 1526 pending_input_buffers_.clear(); |
1522 decoder_.Release(); | 1527 decoder_.Release(); |
1523 | 1528 |
1524 if (use_dx11_) { | 1529 if (use_dx11_) { |
1525 if (video_format_converter_mft_.get()) { | 1530 if (video_format_converter_mft_.get()) { |
1526 video_format_converter_mft_->ProcessMessage( | 1531 video_format_converter_mft_->ProcessMessage( |
1527 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); | 1532 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); |
1528 video_format_converter_mft_.Release(); | 1533 video_format_converter_mft_.Release(); |
1529 } | 1534 } |
1530 d3d11_device_context_.Release(); | |
1531 d3d11_device_.Release(); | 1535 d3d11_device_.Release(); |
1532 d3d11_device_manager_.Release(); | 1536 d3d11_device_manager_.Release(); |
1533 d3d11_query_.Release(); | |
1534 dx11_video_format_converter_media_type_needs_init_ = true; | 1537 dx11_video_format_converter_media_type_needs_init_ = true; |
1535 } else { | 1538 } else { |
1536 d3d9_.Release(); | 1539 d3d9_.Release(); |
1537 d3d9_device_ex_.Release(); | 1540 d3d9_device_ex_.Release(); |
1538 device_manager_.Release(); | 1541 device_manager_.Release(); |
1539 query_.Release(); | 1542 query_.Release(); |
1540 } | 1543 } |
1541 | 1544 |
1542 SetState(kUninitialized); | 1545 SetState(kUninitialized); |
1543 } | 1546 } |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1996 return; | 1999 return; |
1997 } | 2000 } |
1998 | 2001 |
1999 DCHECK(video_frame); | 2002 DCHECK(video_frame); |
2000 | 2003 |
2001 base::win::ScopedComPtr<IMFSample> input_sample; | 2004 base::win::ScopedComPtr<IMFSample> input_sample; |
2002 input_sample.Attach(video_frame); | 2005 input_sample.Attach(video_frame); |
2003 | 2006 |
2004 DCHECK(video_format_converter_mft_.get()); | 2007 DCHECK(video_format_converter_mft_.get()); |
2005 | 2008 |
2006 // d3d11_device_context_->Begin(d3d11_query_.get()); | |
2007 | |
2008 hr = video_format_converter_mft_->ProcessInput(0, video_frame, 0); | |
2009 if (FAILED(hr)) { | |
2010 DCHECK(false); | |
2011 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | |
2012 "Failed to convert output sample format.", PLATFORM_FAILURE,); | |
2013 } | |
2014 | |
2015 // The video processor MFT requires output samples to be allocated by the | 2009 // The video processor MFT requires output samples to be allocated by the |
2016 // caller. We create a sample with a buffer backed with the ID3D11Texture2D | 2010 // caller. We create a sample with a buffer backed with the ID3D11Texture2D |
2017 // interface exposed by ANGLE. This works nicely as this ensures that the | 2011 // interface exposed by ANGLE. This works nicely as this ensures that the |
2018 // video processor coverts the color space of the output frame and copies | 2012 // video processor coverts the color space of the output frame and copies |
2019 // the result into the ANGLE texture. | 2013 // the result into the ANGLE texture. |
2020 base::win::ScopedComPtr<IMFSample> output_sample; | 2014 base::win::ScopedComPtr<IMFSample> output_sample; |
2021 hr = MFCreateSample(output_sample.Receive()); | 2015 hr = MFCreateSample(output_sample.Receive()); |
2022 if (FAILED(hr)) { | 2016 if (FAILED(hr)) { |
2023 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2017 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
2024 "Failed to create output sample.", PLATFORM_FAILURE,); | 2018 "Failed to create output sample.", PLATFORM_FAILURE,); |
2025 } | 2019 } |
2026 | 2020 |
2027 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; | 2021 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; |
2028 hr = MFCreateDXGISurfaceBuffer( | 2022 hr = MFCreateDXGISurfaceBuffer( |
2029 __uuidof(ID3D11Texture2D), dest_texture, 0, FALSE, | 2023 __uuidof(ID3D11Texture2D), dest_texture, 0, FALSE, |
2030 output_buffer.Receive()); | 2024 output_buffer.Receive()); |
2031 if (FAILED(hr)) { | 2025 if (FAILED(hr)) { |
2032 base::debug::Alias(&hr); | 2026 base::debug::Alias(&hr); |
2033 // TODO(ananta) | 2027 // TODO(ananta) |
2034 // Remove this CHECK when the change to use DX11 for H/W decoding | 2028 // Remove this CHECK when the change to use DX11 for H/W decoding |
2035 // stablizes. | 2029 // stablizes. |
2036 CHECK(false); | 2030 CHECK(false); |
2037 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2031 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
2038 "Failed to create output sample.", PLATFORM_FAILURE,); | 2032 "Failed to create output sample.", PLATFORM_FAILURE,); |
2039 } | 2033 } |
2040 | 2034 |
2041 output_sample->AddBuffer(output_buffer.get()); | 2035 output_sample->AddBuffer(output_buffer.get()); |
2042 | 2036 |
2043 // Lock the device here as we are accessing the destination texture created | 2037 // Lock the device here as we are accessing the DX11 video context and the |
2044 // on the main thread. | 2038 // texture which need to be synchronized with the main thread. |
2045 multi_threaded_->Enter(); | 2039 AutoDX11DeviceLock device_lock(multi_threaded_.get()); |
| 2040 |
| 2041 hr = video_format_converter_mft_->ProcessInput(0, video_frame, 0); |
| 2042 if (FAILED(hr)) { |
| 2043 DCHECK(false); |
| 2044 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
| 2045 "Failed to convert output sample format.", PLATFORM_FAILURE,); |
| 2046 } |
2046 | 2047 |
2047 DWORD status = 0; | 2048 DWORD status = 0; |
2048 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; | 2049 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; |
2049 format_converter_output.pSample = output_sample.get(); | 2050 format_converter_output.pSample = output_sample.get(); |
2050 hr = video_format_converter_mft_->ProcessOutput( | 2051 hr = video_format_converter_mft_->ProcessOutput( |
2051 0, // No flags | 2052 0, // No flags |
2052 1, // # of out streams to pull from | 2053 1, // # of out streams to pull from |
2053 &format_converter_output, | 2054 &format_converter_output, |
2054 &status); | 2055 &status); |
2055 | 2056 |
2056 d3d11_device_context_->Flush(); | |
2057 d3d11_device_context_->End(d3d11_query_.get()); | |
2058 | |
2059 multi_threaded_->Leave(); | |
2060 | |
2061 if (FAILED(hr)) { | 2057 if (FAILED(hr)) { |
2062 base::debug::Alias(&hr); | 2058 base::debug::Alias(&hr); |
2063 // TODO(ananta) | 2059 // TODO(ananta) |
2064 // Remove this CHECK when the change to use DX11 for H/W decoding | 2060 // Remove this CHECK when the change to use DX11 for H/W decoding |
2065 // stablizes. | 2061 // stablizes. |
2066 CHECK(false); | 2062 CHECK(false); |
2067 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2063 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
2068 "Failed to convert output sample format.", PLATFORM_FAILURE,); | 2064 "Failed to convert output sample format.", PLATFORM_FAILURE,); |
2069 } | 2065 } |
2070 | 2066 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 if (FAILED(hr)) { | 2228 if (FAILED(hr)) { |
2233 base::debug::Alias(&hr); | 2229 base::debug::Alias(&hr); |
2234 // TODO(ananta) | 2230 // TODO(ananta) |
2235 // Remove this CHECK when the change to use DX11 for H/W decoding | 2231 // Remove this CHECK when the change to use DX11 for H/W decoding |
2236 // stablizes. | 2232 // stablizes. |
2237 CHECK(false); | 2233 CHECK(false); |
2238 } | 2234 } |
2239 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2235 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
2240 "Failed to set converter output type", PLATFORM_FAILURE, false); | 2236 "Failed to set converter output type", PLATFORM_FAILURE, false); |
2241 | 2237 |
2242 hr = video_format_converter_mft_->ProcessMessage( | |
2243 MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); | |
2244 if (FAILED(hr)) { | |
2245 // TODO(ananta) | |
2246 // Remove this CHECK when the change to use DX11 for H/W decoding | |
2247 // stablizes. | |
2248 RETURN_AND_NOTIFY_ON_FAILURE( | |
2249 false, "Failed to initialize video converter.", PLATFORM_FAILURE, | |
2250 false); | |
2251 } | |
2252 dx11_video_format_converter_media_type_needs_init_ = false; | 2238 dx11_video_format_converter_media_type_needs_init_ = false; |
2253 return true; | 2239 return true; |
2254 } | 2240 } |
2255 out_media_type.Release(); | 2241 out_media_type.Release(); |
2256 } | 2242 } |
2257 return false; | 2243 return false; |
2258 } | 2244 } |
2259 | 2245 |
2260 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions( | 2246 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions( |
2261 IMFSample* sample, | 2247 IMFSample* sample, |
(...skipping 27 matching lines...) Expand all Loading... |
2289 D3DSURFACE_DESC surface_desc; | 2275 D3DSURFACE_DESC surface_desc; |
2290 hr = surface->GetDesc(&surface_desc); | 2276 hr = surface->GetDesc(&surface_desc); |
2291 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); | 2277 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); |
2292 *width = surface_desc.Width; | 2278 *width = surface_desc.Width; |
2293 *height = surface_desc.Height; | 2279 *height = surface_desc.Height; |
2294 } | 2280 } |
2295 return true; | 2281 return true; |
2296 } | 2282 } |
2297 | 2283 |
2298 } // namespace content | 2284 } // namespace content |
OLD | NEW |