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.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator.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 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
782 | 800 |
783 base::win::ScopedComPtr<ID3D11Device> angle_device = | 801 base::win::ScopedComPtr<ID3D11Device> angle_device = |
784 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); | 802 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); |
785 RETURN_ON_FAILURE( | 803 RETURN_ON_FAILURE( |
786 angle_device.get(), | 804 angle_device.get(), |
787 "Failed to query DX11 device object from ANGLE", | 805 "Failed to query DX11 device object from ANGLE", |
788 false); | 806 false); |
789 | 807 |
790 using_angle_device_ = true; | 808 using_angle_device_ = true; |
791 d3d11_device_ = angle_device; | 809 d3d11_device_ = angle_device; |
792 d3d11_device_->GetImmediateContext(d3d11_device_context_.Receive()); | |
793 RETURN_ON_FAILURE( | |
794 d3d11_device_context_.get(), | |
795 "Failed to query DX11 device context from ANGLE device", | |
796 false); | |
797 | 810 |
798 // Enable multithreaded mode on the device. This ensures that accesses to | 811 // Enable multithreaded mode on the device. This ensures that accesses to |
799 // context are synchronized across threads. We have multiple threads | 812 // context are synchronized across threads. We have multiple threads |
800 // accessing the context, the media foundation decoder threads and the | 813 // accessing the context, the media foundation decoder threads and the |
801 // decoder thread via the video format conversion transform. | 814 // decoder thread via the video format conversion transform. |
802 hr = multi_threaded_.QueryFrom(angle_device.get()); | 815 hr = multi_threaded_.QueryFrom(angle_device.get()); |
803 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false); | 816 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false); |
804 multi_threaded_->SetMultithreadProtected(TRUE); | 817 multi_threaded_->SetMultithreadProtected(TRUE); |
805 | 818 |
806 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(), | 819 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(), |
807 dx11_dev_manager_reset_token_); | 820 dx11_dev_manager_reset_token_); |
808 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); | 821 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); |
809 | 822 |
810 D3D11_QUERY_DESC query_desc; | |
811 query_desc.Query = D3D11_QUERY_EVENT; | |
812 query_desc.MiscFlags = 0; | |
813 hr = d3d11_device_->CreateQuery( | |
814 &query_desc, | |
815 d3d11_query_.Receive()); | |
816 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false); | |
817 | |
818 HMODULE video_processor_dll = ::GetModuleHandle(L"msvproc.dll"); | 823 HMODULE video_processor_dll = ::GetModuleHandle(L"msvproc.dll"); |
819 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor", | 824 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor", |
820 false); | 825 false); |
821 | 826 |
822 hr = CreateCOMObjectFromDll( | 827 hr = CreateCOMObjectFromDll( |
823 video_processor_dll, | 828 video_processor_dll, |
824 CLSID_VideoProcessorMFT, | 829 CLSID_VideoProcessorMFT, |
825 __uuidof(IMFTransform), | 830 __uuidof(IMFTransform), |
826 video_format_converter_mft_.ReceiveVoid()); | 831 video_format_converter_mft_.ReceiveVoid()); |
827 if (FAILED(hr)) { | 832 if (FAILED(hr)) { |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1515 pending_output_samples_.clear(); | 1520 pending_output_samples_.clear(); |
1516 pending_input_buffers_.clear(); | 1521 pending_input_buffers_.clear(); |
1517 decoder_.Release(); | 1522 decoder_.Release(); |
1518 | 1523 |
1519 if (use_dx11_) { | 1524 if (use_dx11_) { |
1520 if (video_format_converter_mft_.get()) { | 1525 if (video_format_converter_mft_.get()) { |
1521 video_format_converter_mft_->ProcessMessage( | 1526 video_format_converter_mft_->ProcessMessage( |
1522 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); | 1527 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); |
1523 video_format_converter_mft_.Release(); | 1528 video_format_converter_mft_.Release(); |
1524 } | 1529 } |
1525 d3d11_device_context_.Release(); | |
1526 d3d11_device_.Release(); | 1530 d3d11_device_.Release(); |
1527 d3d11_device_manager_.Release(); | 1531 d3d11_device_manager_.Release(); |
1528 d3d11_query_.Release(); | |
1529 dx11_video_format_converter_media_type_needs_init_ = true; | 1532 dx11_video_format_converter_media_type_needs_init_ = true; |
1530 } else { | 1533 } else { |
1531 d3d9_.Release(); | 1534 d3d9_.Release(); |
1532 d3d9_device_ex_.Release(); | 1535 d3d9_device_ex_.Release(); |
1533 device_manager_.Release(); | 1536 device_manager_.Release(); |
1534 query_.Release(); | 1537 query_.Release(); |
1535 } | 1538 } |
1536 | 1539 |
1537 SetState(kUninitialized); | 1540 SetState(kUninitialized); |
1538 } | 1541 } |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1991 return; | 1994 return; |
1992 } | 1995 } |
1993 | 1996 |
1994 DCHECK(video_frame); | 1997 DCHECK(video_frame); |
1995 | 1998 |
1996 base::win::ScopedComPtr<IMFSample> input_sample; | 1999 base::win::ScopedComPtr<IMFSample> input_sample; |
1997 input_sample.Attach(video_frame); | 2000 input_sample.Attach(video_frame); |
1998 | 2001 |
1999 DCHECK(video_format_converter_mft_.get()); | 2002 DCHECK(video_format_converter_mft_.get()); |
2000 | 2003 |
2001 // d3d11_device_context_->Begin(d3d11_query_.get()); | |
2002 | |
2003 hr = video_format_converter_mft_->ProcessInput(0, video_frame, 0); | |
2004 if (FAILED(hr)) { | |
2005 DCHECK(false); | |
2006 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | |
2007 "Failed to convert output sample format.", PLATFORM_FAILURE,); | |
2008 } | |
2009 | |
2010 // The video processor MFT requires output samples to be allocated by the | 2004 // The video processor MFT requires output samples to be allocated by the |
2011 // caller. We create a sample with a buffer backed with the ID3D11Texture2D | 2005 // caller. We create a sample with a buffer backed with the ID3D11Texture2D |
2012 // interface exposed by ANGLE. This works nicely as this ensures that the | 2006 // interface exposed by ANGLE. This works nicely as this ensures that the |
2013 // video processor coverts the color space of the output frame and copies | 2007 // video processor coverts the color space of the output frame and copies |
2014 // the result into the ANGLE texture. | 2008 // the result into the ANGLE texture. |
2015 base::win::ScopedComPtr<IMFSample> output_sample; | 2009 base::win::ScopedComPtr<IMFSample> output_sample; |
2016 hr = MFCreateSample(output_sample.Receive()); | 2010 hr = MFCreateSample(output_sample.Receive()); |
2017 if (FAILED(hr)) { | 2011 if (FAILED(hr)) { |
2018 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2012 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
2019 "Failed to create output sample.", PLATFORM_FAILURE,); | 2013 "Failed to create output sample.", PLATFORM_FAILURE,); |
2020 } | 2014 } |
2021 | 2015 |
2022 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; | 2016 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; |
2023 hr = MFCreateDXGISurfaceBuffer( | 2017 hr = MFCreateDXGISurfaceBuffer( |
2024 __uuidof(ID3D11Texture2D), dest_texture, 0, FALSE, | 2018 __uuidof(ID3D11Texture2D), dest_texture, 0, FALSE, |
2025 output_buffer.Receive()); | 2019 output_buffer.Receive()); |
2026 if (FAILED(hr)) { | 2020 if (FAILED(hr)) { |
2027 base::debug::Alias(&hr); | 2021 base::debug::Alias(&hr); |
2028 // TODO(ananta) | 2022 // TODO(ananta) |
2029 // Remove this CHECK when the change to use DX11 for H/W decoding | 2023 // Remove this CHECK when the change to use DX11 for H/W decoding |
2030 // stablizes. | 2024 // stablizes. |
2031 CHECK(false); | 2025 CHECK(false); |
2032 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2026 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
2033 "Failed to create output sample.", PLATFORM_FAILURE,); | 2027 "Failed to create output sample.", PLATFORM_FAILURE,); |
2034 } | 2028 } |
2035 | 2029 |
2036 output_sample->AddBuffer(output_buffer.get()); | 2030 output_sample->AddBuffer(output_buffer.get()); |
2037 | 2031 |
2038 // Lock the device here as we are accessing the destination texture created | 2032 // Lock the device here as we are accessing the DX11 video context and the |
2039 // on the main thread. | 2033 // texture which need to be synchronized with the main thread. |
2040 multi_threaded_->Enter(); | 2034 AutoDX11DeviceLock device_lock(multi_threaded_.get()); |
DaleCurtis
2015/12/03 22:09:24
This will hold the lock for all the calls below to
ananta
2015/12/03 22:11:02
ProcessInput and ProcessOutput.
| |
2035 | |
2036 hr = video_format_converter_mft_->ProcessInput(0, video_frame, 0); | |
2037 if (FAILED(hr)) { | |
2038 DCHECK(false); | |
2039 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | |
2040 "Failed to convert output sample format.", PLATFORM_FAILURE,); | |
2041 } | |
2041 | 2042 |
2042 DWORD status = 0; | 2043 DWORD status = 0; |
2043 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; | 2044 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; |
2044 format_converter_output.pSample = output_sample.get(); | 2045 format_converter_output.pSample = output_sample.get(); |
2045 hr = video_format_converter_mft_->ProcessOutput( | 2046 hr = video_format_converter_mft_->ProcessOutput( |
2046 0, // No flags | 2047 0, // No flags |
2047 1, // # of out streams to pull from | 2048 1, // # of out streams to pull from |
2048 &format_converter_output, | 2049 &format_converter_output, |
2049 &status); | 2050 &status); |
2050 | 2051 |
2051 d3d11_device_context_->Flush(); | |
2052 d3d11_device_context_->End(d3d11_query_.get()); | |
2053 | |
2054 multi_threaded_->Leave(); | |
2055 | |
2056 if (FAILED(hr)) { | 2052 if (FAILED(hr)) { |
2057 base::debug::Alias(&hr); | 2053 base::debug::Alias(&hr); |
2058 // TODO(ananta) | 2054 // TODO(ananta) |
2059 // Remove this CHECK when the change to use DX11 for H/W decoding | 2055 // Remove this CHECK when the change to use DX11 for H/W decoding |
2060 // stablizes. | 2056 // stablizes. |
2061 CHECK(false); | 2057 CHECK(false); |
2062 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2058 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
2063 "Failed to convert output sample format.", PLATFORM_FAILURE,); | 2059 "Failed to convert output sample format.", PLATFORM_FAILURE,); |
2064 } | 2060 } |
2065 | 2061 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2227 if (FAILED(hr)) { | 2223 if (FAILED(hr)) { |
2228 base::debug::Alias(&hr); | 2224 base::debug::Alias(&hr); |
2229 // TODO(ananta) | 2225 // TODO(ananta) |
2230 // Remove this CHECK when the change to use DX11 for H/W decoding | 2226 // Remove this CHECK when the change to use DX11 for H/W decoding |
2231 // stablizes. | 2227 // stablizes. |
2232 CHECK(false); | 2228 CHECK(false); |
2233 } | 2229 } |
2234 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2230 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
2235 "Failed to set converter output type", PLATFORM_FAILURE, false); | 2231 "Failed to set converter output type", PLATFORM_FAILURE, false); |
2236 | 2232 |
2237 hr = video_format_converter_mft_->ProcessMessage( | |
2238 MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); | |
2239 if (FAILED(hr)) { | |
2240 // TODO(ananta) | |
2241 // Remove this CHECK when the change to use DX11 for H/W decoding | |
2242 // stablizes. | |
2243 RETURN_AND_NOTIFY_ON_FAILURE( | |
2244 false, "Failed to initialize video converter.", PLATFORM_FAILURE, | |
2245 false); | |
2246 } | |
2247 dx11_video_format_converter_media_type_needs_init_ = false; | 2233 dx11_video_format_converter_media_type_needs_init_ = false; |
2248 return true; | 2234 return true; |
2249 } | 2235 } |
2250 out_media_type.Release(); | 2236 out_media_type.Release(); |
2251 } | 2237 } |
2252 return false; | 2238 return false; |
2253 } | 2239 } |
2254 | 2240 |
2255 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions( | 2241 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions( |
2256 IMFSample* sample, | 2242 IMFSample* sample, |
(...skipping 27 matching lines...) Expand all Loading... | |
2284 D3DSURFACE_DESC surface_desc; | 2270 D3DSURFACE_DESC surface_desc; |
2285 hr = surface->GetDesc(&surface_desc); | 2271 hr = surface->GetDesc(&surface_desc); |
2286 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); | 2272 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); |
2287 *width = surface_desc.Width; | 2273 *width = surface_desc.Width; |
2288 *height = surface_desc.Height; | 2274 *height = surface_desc.Height; |
2289 } | 2275 } |
2290 return true; | 2276 return true; |
2291 } | 2277 } |
2292 | 2278 |
2293 } // namespace content | 2279 } // namespace content |
OLD | NEW |