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

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

Issue 1427213002: Lock the decoder device (Angle) device from the decoder thread before copying the decoded frame to … (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove the wait for Flush for dx11 and disable-d3d11 Created 5 years, 1 month 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.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.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 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 pictures_requested_(false), 614 pictures_requested_(false),
615 inputs_before_decode_(0), 615 inputs_before_decode_(0),
616 sent_drain_message_(false), 616 sent_drain_message_(false),
617 make_context_current_(make_context_current), 617 make_context_current_(make_context_current),
618 codec_(media::kUnknownVideoCodec), 618 codec_(media::kUnknownVideoCodec),
619 decoder_thread_("DXVAVideoDecoderThread"), 619 decoder_thread_("DXVAVideoDecoderThread"),
620 pending_flush_(false), 620 pending_flush_(false),
621 use_dx11_(false), 621 use_dx11_(false),
622 dx11_video_format_converter_media_type_needs_init_(true), 622 dx11_video_format_converter_media_type_needs_init_(true),
623 gl_context_(gl_context), 623 gl_context_(gl_context),
624 dx11_disabled_(false),
624 weak_this_factory_(this) { 625 weak_this_factory_(this) {
625 weak_ptr_ = weak_this_factory_.GetWeakPtr(); 626 weak_ptr_ = weak_this_factory_.GetWeakPtr();
626 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); 627 memset(&input_stream_info_, 0, sizeof(input_stream_info_));
627 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); 628 memset(&output_stream_info_, 0, sizeof(output_stream_info_));
628 } 629 }
629 630
630 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { 631 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() {
631 client_ = NULL; 632 client_ = NULL;
632 } 633 }
633 634
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 } 719 }
719 720
720 bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { 721 bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() {
721 TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager"); 722 TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager");
722 723
723 HRESULT hr = E_FAIL; 724 HRESULT hr = E_FAIL;
724 725
725 hr = Direct3DCreate9Ex(D3D_SDK_VERSION, d3d9_.Receive()); 726 hr = Direct3DCreate9Ex(D3D_SDK_VERSION, d3d9_.Receive());
726 RETURN_ON_HR_FAILURE(hr, "Direct3DCreate9Ex failed", false); 727 RETURN_ON_HR_FAILURE(hr, "Direct3DCreate9Ex failed", false);
727 728
728 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 729 dx11_disabled_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
jbauman 2015/11/02 22:55:43 I'm not sure why we're checking this command line
ananta 2015/11/02 23:11:54 Done.
729 switches::kDisableD3D11)) { 730 switches::kDisableD3D11);
731 if (dx11_disabled_) {
730 base::win::ScopedComPtr<IDirect3DDevice9> angle_device = 732 base::win::ScopedComPtr<IDirect3DDevice9> angle_device =
731 QueryDeviceObjectFromANGLE<IDirect3DDevice9>(EGL_D3D9_DEVICE_ANGLE); 733 QueryDeviceObjectFromANGLE<IDirect3DDevice9>(EGL_D3D9_DEVICE_ANGLE);
732 RETURN_ON_FAILURE( 734 RETURN_ON_FAILURE(
733 angle_device.get(), 735 angle_device.get(),
734 "Failed to query D3D9 device object from ANGLE", 736 "Failed to query D3D9 device object from ANGLE",
735 false); 737 false);
736 738
737 hr = d3d9_device_ex_.QueryFrom(angle_device.get()); 739 hr = d3d9_device_ex_.QueryFrom(angle_device.get());
738 RETURN_ON_HR_FAILURE(hr, 740 RETURN_ON_HR_FAILURE(hr,
739 "QueryInterface for IDirect3DDevice9Ex from angle device failed", 741 "QueryInterface for IDirect3DDevice9Ex from angle device failed",
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 d3d11_device_->GetImmediateContext(d3d11_device_context_.Receive()); 799 d3d11_device_->GetImmediateContext(d3d11_device_context_.Receive());
798 RETURN_ON_FAILURE( 800 RETURN_ON_FAILURE(
799 d3d11_device_context_.get(), 801 d3d11_device_context_.get(),
800 "Failed to query DX11 device context from ANGLE device", 802 "Failed to query DX11 device context from ANGLE device",
801 false); 803 false);
802 804
803 // Enable multithreaded mode on the context. This ensures that accesses to 805 // Enable multithreaded mode on the context. This ensures that accesses to
804 // context are synchronized across threads. We have multiple threads 806 // context are synchronized across threads. We have multiple threads
805 // accessing the context, the media foundation decoder threads and the 807 // accessing the context, the media foundation decoder threads and the
806 // decoder thread via the video format conversion transform. 808 // decoder thread via the video format conversion transform.
807 base::win::ScopedComPtr<ID3D10Multithread> multi_threaded; 809 hr = multi_threaded_.QueryFrom(d3d11_device_context_.get());
808 hr = multi_threaded.QueryFrom(d3d11_device_context_.get());
809 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false); 810 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false);
810 multi_threaded->SetMultithreadProtected(TRUE); 811 multi_threaded_->SetMultithreadProtected(TRUE);
811 812
812 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(), 813 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(),
813 dx11_dev_manager_reset_token_); 814 dx11_dev_manager_reset_token_);
814 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); 815 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false);
815 816
816 D3D11_QUERY_DESC query_desc; 817 D3D11_QUERY_DESC query_desc;
817 query_desc.Query = D3D11_QUERY_EVENT; 818 query_desc.Query = D3D11_QUERY_EVENT;
818 query_desc.MiscFlags = 0; 819 query_desc.MiscFlags = 0;
819 hr = d3d11_device_->CreateQuery( 820 hr = d3d11_device_->CreateQuery(
820 &query_desc, 821 &query_desc,
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 client_ = NULL; 1492 client_ = NULL;
1492 1493
1493 if (GetState() != kUninitialized) { 1494 if (GetState() != kUninitialized) {
1494 Invalidate(); 1495 Invalidate();
1495 } 1496 }
1496 } 1497 }
1497 1498
1498 void DXVAVideoDecodeAccelerator::Invalidate() { 1499 void DXVAVideoDecodeAccelerator::Invalidate() {
1499 if (GetState() == kUninitialized) 1500 if (GetState() == kUninitialized)
1500 return; 1501 return;
1502
1501 decoder_thread_.Stop(); 1503 decoder_thread_.Stop();
1502 weak_this_factory_.InvalidateWeakPtrs(); 1504 weak_this_factory_.InvalidateWeakPtrs();
1503 output_picture_buffers_.clear(); 1505 output_picture_buffers_.clear();
1504 stale_output_picture_buffers_.clear(); 1506 stale_output_picture_buffers_.clear();
1505 pending_output_samples_.clear(); 1507 pending_output_samples_.clear();
1506 pending_input_buffers_.clear(); 1508 pending_input_buffers_.clear();
1507 decoder_.Release(); 1509 decoder_.Release();
1508 1510
1509 if (use_dx11_) { 1511 if (use_dx11_) {
1510 if (video_format_converter_mft_.get()) { 1512 if (video_format_converter_mft_.get()) {
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
1847 1849
1848 HRESULT hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface, 1850 HRESULT hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface,
1849 NULL, D3DTEXF_NONE); 1851 NULL, D3DTEXF_NONE);
1850 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed",); 1852 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed",);
1851 1853
1852 // Ideally, this should be done immediately before the draw call that uses 1854 // Ideally, this should be done immediately before the draw call that uses
1853 // the texture. Flush it once here though. 1855 // the texture. Flush it once here though.
1854 hr = query_->Issue(D3DISSUE_END); 1856 hr = query_->Issue(D3DISSUE_END);
1855 RETURN_ON_HR_FAILURE(hr, "Failed to issue END",); 1857 RETURN_ON_HR_FAILURE(hr, "Failed to issue END",);
1856 1858
1859 // If we are running in pure D3D9 mode we don't need to wait for the Flush to
1860 // complete as we are sharing the ANGLE device.
1861 if (dx11_disabled_) {
1862 main_thread_task_runner_->PostTask(
1863 FROM_HERE,
1864 base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
1865 weak_this_factory_.GetWeakPtr(),
1866 src_surface,
1867 dest_surface,
1868 picture_buffer_id,
1869 input_buffer_id));
1870 return;
1871 }
1872
1857 // Flush the decoder device to ensure that the decoded frame is copied to the 1873 // Flush the decoder device to ensure that the decoded frame is copied to the
1858 // target surface. 1874 // target surface.
1859 decoder_thread_task_runner_->PostDelayedTask( 1875 decoder_thread_task_runner_->PostDelayedTask(
1860 FROM_HERE, 1876 FROM_HERE,
1861 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 1877 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
1862 base::Unretained(this), 0, src_surface, dest_surface, 1878 base::Unretained(this), 0, src_surface, dest_surface,
1863 picture_buffer_id, input_buffer_id), 1879 picture_buffer_id, input_buffer_id),
1864 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); 1880 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
1865 } 1881 }
1866 1882
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2004 // TODO(ananta) 2020 // TODO(ananta)
2005 // Remove this CHECK when the change to use DX11 for H/W decoding 2021 // Remove this CHECK when the change to use DX11 for H/W decoding
2006 // stablizes. 2022 // stablizes.
2007 CHECK(false); 2023 CHECK(false);
2008 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2024 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2009 "Failed to create output sample.", PLATFORM_FAILURE,); 2025 "Failed to create output sample.", PLATFORM_FAILURE,);
2010 } 2026 }
2011 2027
2012 output_sample->AddBuffer(output_buffer.get()); 2028 output_sample->AddBuffer(output_buffer.get());
2013 2029
2030 // Lock the device here as we are accessing the destination texture created
2031 // on the main thread.
2032 multi_threaded_->Enter();
2033
2014 DWORD status = 0; 2034 DWORD status = 0;
2015 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; 2035 MFT_OUTPUT_DATA_BUFFER format_converter_output = {};
2016 format_converter_output.pSample = output_sample.get(); 2036 format_converter_output.pSample = output_sample.get();
2017 hr = video_format_converter_mft_->ProcessOutput( 2037 hr = video_format_converter_mft_->ProcessOutput(
2018 0, // No flags 2038 0, // No flags
2019 1, // # of out streams to pull from 2039 1, // # of out streams to pull from
2020 &format_converter_output, 2040 &format_converter_output,
2021 &status); 2041 &status);
2022 2042
2023 d3d11_device_context_->Flush(); 2043 d3d11_device_context_->Flush();
2024 d3d11_device_context_->End(d3d11_query_.get()); 2044 d3d11_device_context_->End(d3d11_query_.get());
2025 2045
2046 multi_threaded_->Leave();
2047
2026 if (FAILED(hr)) { 2048 if (FAILED(hr)) {
2027 base::debug::Alias(&hr); 2049 base::debug::Alias(&hr);
2028 // TODO(ananta) 2050 // TODO(ananta)
2029 // Remove this CHECK when the change to use DX11 for H/W decoding 2051 // Remove this CHECK when the change to use DX11 for H/W decoding
2030 // stablizes. 2052 // stablizes.
2031 CHECK(false); 2053 CHECK(false);
2032 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2054 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2033 "Failed to convert output sample format.", PLATFORM_FAILURE,); 2055 "Failed to convert output sample format.", PLATFORM_FAILURE,);
2034 } 2056 }
2035 2057
2036 decoder_thread_task_runner_->PostDelayedTask( 2058 main_thread_task_runner_->PostTask(
2037 FROM_HERE, 2059 FROM_HERE,
2038 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 2060 base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
2039 base::Unretained(this), 0, 2061 weak_this_factory_.GetWeakPtr(),
2040 reinterpret_cast<IDirect3DSurface9*>(NULL), 2062 nullptr,
2041 reinterpret_cast<IDirect3DSurface9*>(NULL), 2063 nullptr,
2042 picture_buffer_id, input_buffer_id), 2064 picture_buffer_id,
2043 base::TimeDelta::FromMilliseconds( 2065 input_buffer_id));
2044 kFlushDecoderSurfaceTimeoutMs));
2045 } 2066 }
2046 2067
2047 void DXVAVideoDecodeAccelerator::FlushDecoder( 2068 void DXVAVideoDecodeAccelerator::FlushDecoder(
2048 int iterations, 2069 int iterations,
2049 IDirect3DSurface9* src_surface, 2070 IDirect3DSurface9* src_surface,
2050 IDirect3DSurface9* dest_surface, 2071 IDirect3DSurface9* dest_surface,
2051 int picture_buffer_id, 2072 int picture_buffer_id,
2052 int input_buffer_id) { 2073 int input_buffer_id) {
2053 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 2074 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2054 2075
2055 // The DXVA decoder has its own device which it uses for decoding. ANGLE 2076 // The DXVA decoder has its own device which it uses for decoding. ANGLE
2056 // has its own device which we don't have access to. 2077 // has its own device which we don't have access to.
2057 // The above code attempts to copy the decoded picture into a surface 2078 // The above code attempts to copy the decoded picture into a surface
2058 // which is owned by ANGLE. As there are multiple devices involved in 2079 // which is owned by ANGLE. As there are multiple devices involved in
2059 // this, the StretchRect call above is not synchronous. 2080 // this, the StretchRect call above is not synchronous.
2060 // We attempt to flush the batched operations to ensure that the picture is 2081 // We attempt to flush the batched operations to ensure that the picture is
2061 // copied to the surface owned by ANGLE. 2082 // copied to the surface owned by ANGLE.
2062 // We need to do this in a loop and call flush multiple times. 2083 // We need to do this in a loop and call flush multiple times.
2063 // We have seen the GetData call for flushing the command buffer fail to 2084 // We have seen the GetData call for flushing the command buffer fail to
2064 // return success occassionally on multi core machines, leading to an 2085 // return success occassionally on multi core machines, leading to an
2065 // infinite loop. 2086 // infinite loop.
2066 // Workaround is to have an upper limit of 4 on the number of iterations to 2087 // Workaround is to have an upper limit of 4 on the number of iterations to
2067 // wait for the Flush to finish. 2088 // wait for the Flush to finish.
2089 DCHECK(!use_dx11_);
2090
2068 HRESULT hr = E_FAIL; 2091 HRESULT hr = E_FAIL;
2069 2092
2070 if (use_dx11_) { 2093 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH);
2071 BOOL query_data = 0; 2094
2072 hr = d3d11_device_context_->GetData(d3d11_query_.get(), &query_data,
2073 sizeof(BOOL), 0);
2074 if (FAILED(hr)) {
2075 base::debug::Alias(&hr);
2076 // TODO(ananta)
2077 // Remove this CHECK when the change to use DX11 for H/W decoding
2078 // stablizes.
2079 CHECK(false);
2080 }
2081 } else {
2082 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH);
2083 }
2084 if ((hr == S_FALSE) && (++iterations < kMaxIterationsForD3DFlush)) { 2095 if ((hr == S_FALSE) && (++iterations < kMaxIterationsForD3DFlush)) {
2085 decoder_thread_task_runner_->PostDelayedTask( 2096 decoder_thread_task_runner_->PostDelayedTask(
2086 FROM_HERE, 2097 FROM_HERE,
2087 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 2098 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
2088 base::Unretained(this), iterations, src_surface, 2099 base::Unretained(this), iterations, src_surface,
2089 dest_surface, picture_buffer_id, input_buffer_id), 2100 dest_surface, picture_buffer_id, input_buffer_id),
2090 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); 2101 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
2091 return; 2102 return;
2092 } 2103 }
2093 2104
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
2265 D3DSURFACE_DESC surface_desc; 2276 D3DSURFACE_DESC surface_desc;
2266 hr = surface->GetDesc(&surface_desc); 2277 hr = surface->GetDesc(&surface_desc);
2267 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); 2278 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
2268 *width = surface_desc.Width; 2279 *width = surface_desc.Width;
2269 *height = surface_desc.Height; 2280 *height = surface_desc.Height;
2270 } 2281 }
2271 return true; 2282 return true;
2272 } 2283 }
2273 2284
2274 } // namespace content 2285 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/dxva_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698