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

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: Rename member variable 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 using_angle_device_(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 base::win::ScopedComPtr<IDirect3DDevice9> angle_device =
729 switches::kDisableD3D11)) { 730 QueryDeviceObjectFromANGLE<IDirect3DDevice9>(EGL_D3D9_DEVICE_ANGLE);
730 base::win::ScopedComPtr<IDirect3DDevice9> angle_device = 731 if (angle_device.get())
731 QueryDeviceObjectFromANGLE<IDirect3DDevice9>(EGL_D3D9_DEVICE_ANGLE); 732 using_angle_device_ = true;
732 RETURN_ON_FAILURE(
733 angle_device.get(),
734 "Failed to query D3D9 device object from ANGLE",
735 false);
736 733
734 if (using_angle_device_) {
737 hr = d3d9_device_ex_.QueryFrom(angle_device.get()); 735 hr = d3d9_device_ex_.QueryFrom(angle_device.get());
738 RETURN_ON_HR_FAILURE(hr, 736 RETURN_ON_HR_FAILURE(hr,
739 "QueryInterface for IDirect3DDevice9Ex from angle device failed", 737 "QueryInterface for IDirect3DDevice9Ex from angle device failed",
740 false); 738 false);
741 } else { 739 } else {
742 D3DPRESENT_PARAMETERS present_params = {0}; 740 D3DPRESENT_PARAMETERS present_params = {0};
743 present_params.BackBufferWidth = 1; 741 present_params.BackBufferWidth = 1;
744 present_params.BackBufferHeight = 1; 742 present_params.BackBufferHeight = 1;
745 present_params.BackBufferFormat = D3DFMT_UNKNOWN; 743 present_params.BackBufferFormat = D3DFMT_UNKNOWN;
746 present_params.BackBufferCount = 1; 744 present_params.BackBufferCount = 1;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 d3d11_device_manager_.Receive()); 784 d3d11_device_manager_.Receive());
787 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); 785 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false);
788 786
789 base::win::ScopedComPtr<ID3D11Device> angle_device = 787 base::win::ScopedComPtr<ID3D11Device> angle_device =
790 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); 788 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE);
791 RETURN_ON_FAILURE( 789 RETURN_ON_FAILURE(
792 angle_device.get(), 790 angle_device.get(),
793 "Failed to query DX11 device object from ANGLE", 791 "Failed to query DX11 device object from ANGLE",
794 false); 792 false);
795 793
794 using_angle_device_ = true;
796 d3d11_device_ = angle_device; 795 d3d11_device_ = angle_device;
797 d3d11_device_->GetImmediateContext(d3d11_device_context_.Receive()); 796 d3d11_device_->GetImmediateContext(d3d11_device_context_.Receive());
798 RETURN_ON_FAILURE( 797 RETURN_ON_FAILURE(
799 d3d11_device_context_.get(), 798 d3d11_device_context_.get(),
800 "Failed to query DX11 device context from ANGLE device", 799 "Failed to query DX11 device context from ANGLE device",
801 false); 800 false);
802 801
803 // Enable multithreaded mode on the context. This ensures that accesses to 802 // Enable multithreaded mode on the context. This ensures that accesses to
804 // context are synchronized across threads. We have multiple threads 803 // context are synchronized across threads. We have multiple threads
805 // accessing the context, the media foundation decoder threads and the 804 // accessing the context, the media foundation decoder threads and the
806 // decoder thread via the video format conversion transform. 805 // decoder thread via the video format conversion transform.
807 base::win::ScopedComPtr<ID3D10Multithread> multi_threaded; 806 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); 807 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false);
810 multi_threaded->SetMultithreadProtected(TRUE); 808 multi_threaded_->SetMultithreadProtected(TRUE);
811 809
812 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(), 810 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(),
813 dx11_dev_manager_reset_token_); 811 dx11_dev_manager_reset_token_);
814 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); 812 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false);
815 813
816 D3D11_QUERY_DESC query_desc; 814 D3D11_QUERY_DESC query_desc;
817 query_desc.Query = D3D11_QUERY_EVENT; 815 query_desc.Query = D3D11_QUERY_EVENT;
818 query_desc.MiscFlags = 0; 816 query_desc.MiscFlags = 0;
819 hr = d3d11_device_->CreateQuery( 817 hr = d3d11_device_->CreateQuery(
820 &query_desc, 818 &query_desc,
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 client_ = NULL; 1489 client_ = NULL;
1492 1490
1493 if (GetState() != kUninitialized) { 1491 if (GetState() != kUninitialized) {
1494 Invalidate(); 1492 Invalidate();
1495 } 1493 }
1496 } 1494 }
1497 1495
1498 void DXVAVideoDecodeAccelerator::Invalidate() { 1496 void DXVAVideoDecodeAccelerator::Invalidate() {
1499 if (GetState() == kUninitialized) 1497 if (GetState() == kUninitialized)
1500 return; 1498 return;
1499
1501 decoder_thread_.Stop(); 1500 decoder_thread_.Stop();
1502 weak_this_factory_.InvalidateWeakPtrs(); 1501 weak_this_factory_.InvalidateWeakPtrs();
1503 output_picture_buffers_.clear(); 1502 output_picture_buffers_.clear();
1504 stale_output_picture_buffers_.clear(); 1503 stale_output_picture_buffers_.clear();
1505 pending_output_samples_.clear(); 1504 pending_output_samples_.clear();
1506 pending_input_buffers_.clear(); 1505 pending_input_buffers_.clear();
1507 decoder_.Release(); 1506 decoder_.Release();
1508 1507
1509 if (use_dx11_) { 1508 if (use_dx11_) {
1510 if (video_format_converter_mft_.get()) { 1509 if (video_format_converter_mft_.get()) {
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
1847 1846
1848 HRESULT hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface, 1847 HRESULT hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface,
1849 NULL, D3DTEXF_NONE); 1848 NULL, D3DTEXF_NONE);
1850 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed",); 1849 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed",);
1851 1850
1852 // Ideally, this should be done immediately before the draw call that uses 1851 // Ideally, this should be done immediately before the draw call that uses
1853 // the texture. Flush it once here though. 1852 // the texture. Flush it once here though.
1854 hr = query_->Issue(D3DISSUE_END); 1853 hr = query_->Issue(D3DISSUE_END);
1855 RETURN_ON_HR_FAILURE(hr, "Failed to issue END",); 1854 RETURN_ON_HR_FAILURE(hr, "Failed to issue END",);
1856 1855
1856 // If we are sharing the ANGLE device we don't need to wait for the Flush to
1857 // complete.
1858 if (using_angle_device_) {
1859 main_thread_task_runner_->PostTask(
1860 FROM_HERE,
1861 base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
1862 weak_this_factory_.GetWeakPtr(),
1863 src_surface,
1864 dest_surface,
1865 picture_buffer_id,
1866 input_buffer_id));
1867 return;
1868 }
1869
1857 // Flush the decoder device to ensure that the decoded frame is copied to the 1870 // Flush the decoder device to ensure that the decoded frame is copied to the
1858 // target surface. 1871 // target surface.
1859 decoder_thread_task_runner_->PostDelayedTask( 1872 decoder_thread_task_runner_->PostDelayedTask(
1860 FROM_HERE, 1873 FROM_HERE,
1861 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 1874 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
1862 base::Unretained(this), 0, src_surface, dest_surface, 1875 base::Unretained(this), 0, src_surface, dest_surface,
1863 picture_buffer_id, input_buffer_id), 1876 picture_buffer_id, input_buffer_id),
1864 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); 1877 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
1865 } 1878 }
1866 1879
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2004 // TODO(ananta) 2017 // TODO(ananta)
2005 // Remove this CHECK when the change to use DX11 for H/W decoding 2018 // Remove this CHECK when the change to use DX11 for H/W decoding
2006 // stablizes. 2019 // stablizes.
2007 CHECK(false); 2020 CHECK(false);
2008 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2021 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2009 "Failed to create output sample.", PLATFORM_FAILURE,); 2022 "Failed to create output sample.", PLATFORM_FAILURE,);
2010 } 2023 }
2011 2024
2012 output_sample->AddBuffer(output_buffer.get()); 2025 output_sample->AddBuffer(output_buffer.get());
2013 2026
2027 // Lock the device here as we are accessing the destination texture created
2028 // on the main thread.
2029 multi_threaded_->Enter();
2030
2014 DWORD status = 0; 2031 DWORD status = 0;
2015 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; 2032 MFT_OUTPUT_DATA_BUFFER format_converter_output = {};
2016 format_converter_output.pSample = output_sample.get(); 2033 format_converter_output.pSample = output_sample.get();
2017 hr = video_format_converter_mft_->ProcessOutput( 2034 hr = video_format_converter_mft_->ProcessOutput(
2018 0, // No flags 2035 0, // No flags
2019 1, // # of out streams to pull from 2036 1, // # of out streams to pull from
2020 &format_converter_output, 2037 &format_converter_output,
2021 &status); 2038 &status);
2022 2039
2023 d3d11_device_context_->Flush(); 2040 d3d11_device_context_->Flush();
2024 d3d11_device_context_->End(d3d11_query_.get()); 2041 d3d11_device_context_->End(d3d11_query_.get());
2025 2042
2043 multi_threaded_->Leave();
2044
2026 if (FAILED(hr)) { 2045 if (FAILED(hr)) {
2027 base::debug::Alias(&hr); 2046 base::debug::Alias(&hr);
2028 // TODO(ananta) 2047 // TODO(ananta)
2029 // Remove this CHECK when the change to use DX11 for H/W decoding 2048 // Remove this CHECK when the change to use DX11 for H/W decoding
2030 // stablizes. 2049 // stablizes.
2031 CHECK(false); 2050 CHECK(false);
2032 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2051 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2033 "Failed to convert output sample format.", PLATFORM_FAILURE,); 2052 "Failed to convert output sample format.", PLATFORM_FAILURE,);
2034 } 2053 }
2035 2054
2036 decoder_thread_task_runner_->PostDelayedTask( 2055 main_thread_task_runner_->PostTask(
2037 FROM_HERE, 2056 FROM_HERE,
2038 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 2057 base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
2039 base::Unretained(this), 0, 2058 weak_this_factory_.GetWeakPtr(),
2040 reinterpret_cast<IDirect3DSurface9*>(NULL), 2059 nullptr,
2041 reinterpret_cast<IDirect3DSurface9*>(NULL), 2060 nullptr,
2042 picture_buffer_id, input_buffer_id), 2061 picture_buffer_id,
2043 base::TimeDelta::FromMilliseconds( 2062 input_buffer_id));
2044 kFlushDecoderSurfaceTimeoutMs));
2045 } 2063 }
2046 2064
2047 void DXVAVideoDecodeAccelerator::FlushDecoder( 2065 void DXVAVideoDecodeAccelerator::FlushDecoder(
2048 int iterations, 2066 int iterations,
2049 IDirect3DSurface9* src_surface, 2067 IDirect3DSurface9* src_surface,
2050 IDirect3DSurface9* dest_surface, 2068 IDirect3DSurface9* dest_surface,
2051 int picture_buffer_id, 2069 int picture_buffer_id,
2052 int input_buffer_id) { 2070 int input_buffer_id) {
2053 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 2071 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2054 2072
2055 // The DXVA decoder has its own device which it uses for decoding. ANGLE 2073 // 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. 2074 // has its own device which we don't have access to.
2057 // The above code attempts to copy the decoded picture into a surface 2075 // 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 2076 // which is owned by ANGLE. As there are multiple devices involved in
2059 // this, the StretchRect call above is not synchronous. 2077 // this, the StretchRect call above is not synchronous.
2060 // We attempt to flush the batched operations to ensure that the picture is 2078 // We attempt to flush the batched operations to ensure that the picture is
2061 // copied to the surface owned by ANGLE. 2079 // copied to the surface owned by ANGLE.
2062 // We need to do this in a loop and call flush multiple times. 2080 // 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 2081 // We have seen the GetData call for flushing the command buffer fail to
2064 // return success occassionally on multi core machines, leading to an 2082 // return success occassionally on multi core machines, leading to an
2065 // infinite loop. 2083 // infinite loop.
2066 // Workaround is to have an upper limit of 4 on the number of iterations to 2084 // Workaround is to have an upper limit of 4 on the number of iterations to
2067 // wait for the Flush to finish. 2085 // wait for the Flush to finish.
2086 DCHECK(!use_dx11_);
2087
2068 HRESULT hr = E_FAIL; 2088 HRESULT hr = E_FAIL;
2069 2089
2070 if (use_dx11_) { 2090 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH);
2071 BOOL query_data = 0; 2091
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)) { 2092 if ((hr == S_FALSE) && (++iterations < kMaxIterationsForD3DFlush)) {
2085 decoder_thread_task_runner_->PostDelayedTask( 2093 decoder_thread_task_runner_->PostDelayedTask(
2086 FROM_HERE, 2094 FROM_HERE,
2087 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 2095 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
2088 base::Unretained(this), iterations, src_surface, 2096 base::Unretained(this), iterations, src_surface,
2089 dest_surface, picture_buffer_id, input_buffer_id), 2097 dest_surface, picture_buffer_id, input_buffer_id),
2090 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); 2098 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
2091 return; 2099 return;
2092 } 2100 }
2093 2101
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
2265 D3DSURFACE_DESC surface_desc; 2273 D3DSURFACE_DESC surface_desc;
2266 hr = surface->GetDesc(&surface_desc); 2274 hr = surface->GetDesc(&surface_desc);
2267 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); 2275 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
2268 *width = surface_desc.Width; 2276 *width = surface_desc.Width;
2269 *height = surface_desc.Height; 2277 *height = surface_desc.Height;
2270 } 2278 }
2271 return true; 2279 return true;
2272 } 2280 }
2273 2281
2274 } // namespace content 2282 } // 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