Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: content/common/gpu/media/dxva_video_decode_accelerator_win.cc

Issue 1505353005: Stop using the ANGLE D3D11 device for H/W decoding on Windows 8+ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed comment Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/dxva_video_decode_accelerator_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
130 } // namespace 112 } // namespace
131 113
132 namespace content { 114 namespace content {
133 115
134 static const media::VideoCodecProfile kSupportedProfiles[] = { 116 static const media::VideoCodecProfile kSupportedProfiles[] = {
135 media::H264PROFILE_BASELINE, 117 media::H264PROFILE_BASELINE,
136 media::H264PROFILE_MAIN, 118 media::H264PROFILE_MAIN,
137 media::H264PROFILE_HIGH, 119 media::H264PROFILE_HIGH,
138 media::VP8PROFILE_ANY, 120 media::VP8PROFILE_ANY,
139 media::VP9PROFILE_ANY 121 media::VP9PROFILE_ANY
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 hr = query_->Issue(D3DISSUE_END); 778 hr = query_->Issue(D3DISSUE_END);
797 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); 779 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false);
798 return true; 780 return true;
799 } 781 }
800 782
801 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { 783 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() {
802 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_, 784 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_,
803 d3d11_device_manager_.Receive()); 785 d3d11_device_manager_.Receive());
804 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); 786 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false);
805 787
806 base::win::ScopedComPtr<ID3D11Device> angle_device = 788 // This array defines the set of DirectX hardware feature levels we support.
807 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); 789 // The ordering MUST be preserved. All applications are assumed to support
808 RETURN_ON_FAILURE( 790 // 9.1 unless otherwise stated by the application.
809 angle_device.get(), 791 D3D_FEATURE_LEVEL feature_levels[] = {
810 "Failed to query DX11 device object from ANGLE", 792 D3D_FEATURE_LEVEL_11_1,
811 false); 793 D3D_FEATURE_LEVEL_11_0,
794 D3D_FEATURE_LEVEL_10_1,
795 D3D_FEATURE_LEVEL_10_0,
796 D3D_FEATURE_LEVEL_9_3,
797 D3D_FEATURE_LEVEL_9_2,
798 D3D_FEATURE_LEVEL_9_1
799 };
812 800
813 using_angle_device_ = true; 801 UINT flags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
814 d3d11_device_ = angle_device; 802
803 #if defined _DEBUG
804 flags |= D3D11_CREATE_DEVICE_DEBUG;
805 #endif
806
807 D3D_FEATURE_LEVEL feature_level_out = D3D_FEATURE_LEVEL_11_0;
808 hr = D3D11CreateDevice(NULL,
809 D3D_DRIVER_TYPE_HARDWARE,
810 NULL,
811 flags,
812 feature_levels,
813 arraysize(feature_levels),
814 D3D11_SDK_VERSION,
815 d3d11_device_.Receive(),
816 &feature_level_out,
817 d3d11_device_context_.Receive());
818 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device", false);
815 819
816 // Enable multithreaded mode on the device. This ensures that accesses to 820 // Enable multithreaded mode on the device. This ensures that accesses to
817 // context are synchronized across threads. We have multiple threads 821 // context are synchronized across threads. We have multiple threads
818 // accessing the context, the media foundation decoder threads and the 822 // accessing the context, the media foundation decoder threads and the
819 // decoder thread via the video format conversion transform. 823 // decoder thread via the video format conversion transform.
820 hr = multi_threaded_.QueryFrom(angle_device.get()); 824 hr = multi_threaded_.QueryFrom(d3d11_device_.get());
821 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false); 825 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false);
822 multi_threaded_->SetMultithreadProtected(TRUE); 826 multi_threaded_->SetMultithreadProtected(TRUE);
823 827
824 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(), 828 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(),
825 dx11_dev_manager_reset_token_); 829 dx11_dev_manager_reset_token_);
826 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); 830 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false);
827 831
832 D3D11_QUERY_DESC query_desc;
833 query_desc.Query = D3D11_QUERY_EVENT;
834 query_desc.MiscFlags = 0;
835 hr = d3d11_device_->CreateQuery(
836 &query_desc,
837 d3d11_query_.Receive());
838 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false);
839
828 HMODULE video_processor_dll = ::GetModuleHandle(L"msvproc.dll"); 840 HMODULE video_processor_dll = ::GetModuleHandle(L"msvproc.dll");
829 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor", 841 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor",
830 false); 842 false);
831 843
832 hr = CreateCOMObjectFromDll( 844 hr = CreateCOMObjectFromDll(
833 video_processor_dll, 845 video_processor_dll,
834 CLSID_VideoProcessorMFT, 846 CLSID_VideoProcessorMFT,
835 __uuidof(IMFTransform), 847 __uuidof(IMFTransform),
836 video_format_converter_mft_.ReceiveVoid()); 848 video_format_converter_mft_.ReceiveVoid());
837 if (FAILED(hr)) { 849 if (FAILED(hr)) {
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after
1525 pending_output_samples_.clear(); 1537 pending_output_samples_.clear();
1526 pending_input_buffers_.clear(); 1538 pending_input_buffers_.clear();
1527 decoder_.Release(); 1539 decoder_.Release();
1528 1540
1529 if (use_dx11_) { 1541 if (use_dx11_) {
1530 if (video_format_converter_mft_.get()) { 1542 if (video_format_converter_mft_.get()) {
1531 video_format_converter_mft_->ProcessMessage( 1543 video_format_converter_mft_->ProcessMessage(
1532 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); 1544 MFT_MESSAGE_NOTIFY_END_STREAMING, 0);
1533 video_format_converter_mft_.Release(); 1545 video_format_converter_mft_.Release();
1534 } 1546 }
1547 d3d11_device_context_.Release();
1535 d3d11_device_.Release(); 1548 d3d11_device_.Release();
1536 d3d11_device_manager_.Release(); 1549 d3d11_device_manager_.Release();
1550 d3d11_query_.Release();
1537 dx11_video_format_converter_media_type_needs_init_ = true; 1551 dx11_video_format_converter_media_type_needs_init_ = true;
1538 } else { 1552 } else {
1539 d3d9_.Release(); 1553 d3d9_.Release();
1540 d3d9_device_ex_.Release(); 1554 d3d9_device_ex_.Release();
1541 device_manager_.Release(); 1555 device_manager_.Release();
1542 query_.Release(); 1556 query_.Release();
1543 } 1557 }
1544 1558
1545 SetState(kUninitialized); 1559 SetState(kUninitialized);
1546 } 1560 }
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
2027 // TODO(ananta) 2041 // TODO(ananta)
2028 // Remove this CHECK when the change to use DX11 for H/W decoding 2042 // Remove this CHECK when the change to use DX11 for H/W decoding
2029 // stablizes. 2043 // stablizes.
2030 CHECK(false); 2044 CHECK(false);
2031 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2045 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2032 "Failed to create output sample.", PLATFORM_FAILURE,); 2046 "Failed to create output sample.", PLATFORM_FAILURE,);
2033 } 2047 }
2034 2048
2035 output_sample->AddBuffer(output_buffer.get()); 2049 output_sample->AddBuffer(output_buffer.get());
2036 2050
2037 // Lock the device here as we are accessing the DX11 video context and the
2038 // texture which need to be synchronized with the main thread.
2039 AutoDX11DeviceLock device_lock(multi_threaded_.get());
2040
2041 hr = video_format_converter_mft_->ProcessInput(0, video_frame, 0); 2051 hr = video_format_converter_mft_->ProcessInput(0, video_frame, 0);
2042 if (FAILED(hr)) { 2052 if (FAILED(hr)) {
2043 DCHECK(false); 2053 DCHECK(false);
2044 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2054 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2045 "Failed to convert output sample format.", PLATFORM_FAILURE,); 2055 "Failed to convert output sample format.", PLATFORM_FAILURE,);
2046 } 2056 }
2047 2057
2048 DWORD status = 0; 2058 DWORD status = 0;
2049 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; 2059 MFT_OUTPUT_DATA_BUFFER format_converter_output = {};
2050 format_converter_output.pSample = output_sample.get(); 2060 format_converter_output.pSample = output_sample.get();
2051 hr = video_format_converter_mft_->ProcessOutput( 2061 hr = video_format_converter_mft_->ProcessOutput(
2052 0, // No flags 2062 0, // No flags
2053 1, // # of out streams to pull from 2063 1, // # of out streams to pull from
2054 &format_converter_output, 2064 &format_converter_output,
2055 &status); 2065 &status);
2056 2066
2057 if (FAILED(hr)) { 2067 if (FAILED(hr)) {
2058 base::debug::Alias(&hr); 2068 base::debug::Alias(&hr);
2059 // TODO(ananta) 2069 // TODO(ananta)
2060 // Remove this CHECK when the change to use DX11 for H/W decoding 2070 // Remove this CHECK when the change to use DX11 for H/W decoding
2061 // stablizes. 2071 // stablizes.
2062 CHECK(false); 2072 CHECK(false);
2063 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2073 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2064 "Failed to convert output sample format.", PLATFORM_FAILURE,); 2074 "Failed to convert output sample format.", PLATFORM_FAILURE,);
2065 } 2075 }
2066 2076
2067 main_thread_task_runner_->PostTask( 2077 d3d11_device_context_->Flush();
2078 d3d11_device_context_->End(d3d11_query_.get());
2079
2080 decoder_thread_task_runner_->PostDelayedTask(
2068 FROM_HERE, 2081 FROM_HERE,
2069 base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, 2082 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
2070 weak_this_factory_.GetWeakPtr(), 2083 base::Unretained(this), 0,
2071 nullptr, 2084 reinterpret_cast<IDirect3DSurface9*>(NULL),
2072 nullptr, 2085 reinterpret_cast<IDirect3DSurface9*>(NULL),
2073 picture_buffer_id, 2086 picture_buffer_id, input_buffer_id),
2074 input_buffer_id)); 2087 base::TimeDelta::FromMilliseconds(
2088 kFlushDecoderSurfaceTimeoutMs));
2075 } 2089 }
2076 2090
2077 void DXVAVideoDecodeAccelerator::FlushDecoder( 2091 void DXVAVideoDecodeAccelerator::FlushDecoder(
2078 int iterations, 2092 int iterations,
2079 IDirect3DSurface9* src_surface, 2093 IDirect3DSurface9* src_surface,
2080 IDirect3DSurface9* dest_surface, 2094 IDirect3DSurface9* dest_surface,
2081 int picture_buffer_id, 2095 int picture_buffer_id,
2082 int input_buffer_id) { 2096 int input_buffer_id) {
2083 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 2097 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2084 2098
2085 // The DXVA decoder has its own device which it uses for decoding. ANGLE 2099 // The DXVA decoder has its own device which it uses for decoding. ANGLE
2086 // has its own device which we don't have access to. 2100 // has its own device which we don't have access to.
2087 // The above code attempts to copy the decoded picture into a surface 2101 // The above code attempts to copy the decoded picture into a surface
2088 // which is owned by ANGLE. As there are multiple devices involved in 2102 // which is owned by ANGLE. As there are multiple devices involved in
2089 // this, the StretchRect call above is not synchronous. 2103 // this, the StretchRect call above is not synchronous.
2090 // We attempt to flush the batched operations to ensure that the picture is 2104 // We attempt to flush the batched operations to ensure that the picture is
2091 // copied to the surface owned by ANGLE. 2105 // copied to the surface owned by ANGLE.
2092 // We need to do this in a loop and call flush multiple times. 2106 // We need to do this in a loop and call flush multiple times.
2093 // We have seen the GetData call for flushing the command buffer fail to 2107 // We have seen the GetData call for flushing the command buffer fail to
2094 // return success occassionally on multi core machines, leading to an 2108 // return success occassionally on multi core machines, leading to an
2095 // infinite loop. 2109 // infinite loop.
2096 // Workaround is to have an upper limit of 4 on the number of iterations to 2110 // Workaround is to have an upper limit of 4 on the number of iterations to
2097 // wait for the Flush to finish. 2111 // wait for the Flush to finish.
2098 DCHECK(!use_dx11_);
2099 2112
2100 HRESULT hr = E_FAIL; 2113 HRESULT hr = E_FAIL;
2101 2114 if (use_dx11_) {
2102 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH); 2115 BOOL query_data = 0;
2116 hr = d3d11_device_context_->GetData(d3d11_query_.get(), &query_data,
2117 sizeof(BOOL), 0);
2118 if (FAILED(hr)) {
2119 base::debug::Alias(&hr);
2120 // TODO(ananta)
2121 // Remove this CHECK when the change to use DX11 for H/W decoding
2122 // stablizes.
2123 CHECK(false);
2124 }
2125 } else {
2126 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH);
2127 }
2103 2128
2104 if ((hr == S_FALSE) && (++iterations < kMaxIterationsForD3DFlush)) { 2129 if ((hr == S_FALSE) && (++iterations < kMaxIterationsForD3DFlush)) {
2105 decoder_thread_task_runner_->PostDelayedTask( 2130 decoder_thread_task_runner_->PostDelayedTask(
2106 FROM_HERE, 2131 FROM_HERE,
2107 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 2132 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
2108 base::Unretained(this), iterations, src_surface, 2133 base::Unretained(this), iterations, src_surface,
2109 dest_surface, picture_buffer_id, input_buffer_id), 2134 dest_surface, picture_buffer_id, input_buffer_id),
2110 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); 2135 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
2111 return; 2136 return;
2112 } 2137 }
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
2275 D3DSURFACE_DESC surface_desc; 2300 D3DSURFACE_DESC surface_desc;
2276 hr = surface->GetDesc(&surface_desc); 2301 hr = surface->GetDesc(&surface_desc);
2277 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); 2302 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
2278 *width = surface_desc.Width; 2303 *width = surface_desc.Width;
2279 *height = surface_desc.Height; 2304 *height = surface_desc.Height;
2280 } 2305 }
2281 return true; 2306 return true;
2282 } 2307 }
2283 2308
2284 } // namespace content 2309 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/dxva_video_decode_accelerator_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698