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

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

Issue 2503063002: media: Inform VideoBlit/MFTransform of video color information (Closed)
Patch Set: moved enum translation to color_space_win.cc Created 4 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 | « media/gpu/dxva_video_decode_accelerator_win.h ('k') | ui/gfx/BUILD.gn » ('j') | 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 "media/gpu/dxva_video_decode_accelerator_win.h" 5 #include "media/gpu/dxva_video_decode_accelerator_win.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #if !defined(OS_WIN) 9 #if !defined(OS_WIN)
10 #error This file should only be built on Windows. 10 #error This file should only be built on Windows.
(...skipping 17 matching lines...) Expand all
28 #include "base/files/file_path.h" 28 #include "base/files/file_path.h"
29 #include "base/location.h" 29 #include "base/location.h"
30 #include "base/logging.h" 30 #include "base/logging.h"
31 #include "base/macros.h" 31 #include "base/macros.h"
32 #include "base/memory/shared_memory.h" 32 #include "base/memory/shared_memory.h"
33 #include "base/path_service.h" 33 #include "base/path_service.h"
34 #include "base/single_thread_task_runner.h" 34 #include "base/single_thread_task_runner.h"
35 #include "base/stl_util.h" 35 #include "base/stl_util.h"
36 #include "base/threading/thread_task_runner_handle.h" 36 #include "base/threading/thread_task_runner_handle.h"
37 #include "base/trace_event/trace_event.h" 37 #include "base/trace_event/trace_event.h"
38 #include "base/win/scoped_co_mem.h"
38 #include "base/win/windows_version.h" 39 #include "base/win/windows_version.h"
39 #include "build/build_config.h" 40 #include "build/build_config.h"
40 #include "gpu/command_buffer/service/gpu_preferences.h" 41 #include "gpu/command_buffer/service/gpu_preferences.h"
41 #include "gpu/config/gpu_driver_bug_workarounds.h" 42 #include "gpu/config/gpu_driver_bug_workarounds.h"
42 #include "media/base/win/mf_helpers.h" 43 #include "media/base/win/mf_helpers.h"
43 #include "media/base/win/mf_initializer.h" 44 #include "media/base/win/mf_initializer.h"
44 #include "media/gpu/dxva_picture_buffer_win.h" 45 #include "media/gpu/dxva_picture_buffer_win.h"
45 #include "media/video/video_decode_accelerator.h" 46 #include "media/video/video_decode_accelerator.h"
46 #include "third_party/angle/include/EGL/egl.h" 47 #include "third_party/angle/include/EGL/egl.h"
47 #include "third_party/angle/include/EGL/eglext.h" 48 #include "third_party/angle/include/EGL/eglext.h"
49 #include "ui/gfx/color_space_win.h"
48 #include "ui/gl/gl_bindings.h" 50 #include "ui/gl/gl_bindings.h"
49 #include "ui/gl/gl_context.h" 51 #include "ui/gl/gl_context.h"
50 #include "ui/gl/gl_fence.h" 52 #include "ui/gl/gl_fence.h"
51 #include "ui/gl/gl_surface_egl.h" 53 #include "ui/gl/gl_surface_egl.h"
52 54
53 namespace { 55 namespace {
54 56
55 // AMD 57 // AMD
56 // Path is appended on to the PROGRAM_FILES base path. 58 // Path is appended on to the PROGRAM_FILES base path.
57 const wchar_t kAMDVPXDecoderDLLPath[] = 59 const wchar_t kAMDVPXDecoderDLLPath[] =
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 576
575 // On Windows 8+ mfplat.dll provides the MFCreateDXGIDeviceManager API. 577 // On Windows 8+ mfplat.dll provides the MFCreateDXGIDeviceManager API.
576 // On Windows 7 mshtmlmedia.dll provides it. 578 // On Windows 7 mshtmlmedia.dll provides it.
577 579
578 // TODO(ananta) 580 // TODO(ananta)
579 // The code below works, as in we can create the DX11 device manager for 581 // The code below works, as in we can create the DX11 device manager for
580 // Windows 7. However the IMFTransform we use for texture conversion and 582 // Windows 7. However the IMFTransform we use for texture conversion and
581 // copy does not exist on Windows 7. Look into an alternate approach 583 // copy does not exist on Windows 7. Look into an alternate approach
582 // and enable the code below. 584 // and enable the code below.
583 #if defined(ENABLE_DX11_FOR_WIN7) 585 #if defined(ENABLE_DX11_FOR_WIN7)
586 LOG(ERROR) << "DO THIS!";
584 if (base::win::GetVersion() == base::win::VERSION_WIN7) { 587 if (base::win::GetVersion() == base::win::VERSION_WIN7) {
585 dxgi_manager_dll = ::GetModuleHandle(L"mshtmlmedia.dll"); 588 dxgi_manager_dll = ::GetModuleHandle(L"mshtmlmedia.dll");
586 RETURN_ON_FAILURE(dxgi_manager_dll, 589 RETURN_ON_FAILURE(dxgi_manager_dll,
587 "mshtmlmedia.dll is required for decoding", false); 590 "mshtmlmedia.dll is required for decoding", false);
588 } 591 }
589 #endif 592 #endif
590 // If we don't find the MFCreateDXGIDeviceManager API we fallback to D3D9 593 // If we don't find the MFCreateDXGIDeviceManager API we fallback to D3D9
591 // decoding. 594 // decoding.
592 if (dxgi_manager_dll && !create_dxgi_device_manager_) { 595 if (dxgi_manager_dll && !create_dxgi_device_manager_) {
596 LOG(ERROR) << "DX9 DECODING";
jbauman 2016/11/17 01:02:22 Remove these.
hubbe 2016/11/17 18:46:59 Oops, done.
593 create_dxgi_device_manager_ = reinterpret_cast<CreateDXGIDeviceManager>( 597 create_dxgi_device_manager_ = reinterpret_cast<CreateDXGIDeviceManager>(
594 ::GetProcAddress(dxgi_manager_dll, "MFCreateDXGIDeviceManager")); 598 ::GetProcAddress(dxgi_manager_dll, "MFCreateDXGIDeviceManager"));
595 } 599 }
596 600
597 RETURN_AND_NOTIFY_ON_FAILURE( 601 RETURN_AND_NOTIFY_ON_FAILURE(
598 gl::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle, 602 gl::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle,
599 "EGL_ANGLE_surface_d3d_texture_2d_share_handle unavailable", 603 "EGL_ANGLE_surface_d3d_texture_2d_share_handle unavailable",
600 PLATFORM_FAILURE, false); 604 PLATFORM_FAILURE, false);
601 605
602 RETURN_AND_NOTIFY_ON_FAILURE(gl::GLFence::IsSupported(), 606 RETURN_AND_NOTIFY_ON_FAILURE(gl::GLFence::IsSupported(),
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 hr = device_manager_->ResetDevice(d3d9_device_ex_.get(), 697 hr = device_manager_->ResetDevice(d3d9_device_ex_.get(),
694 dev_manager_reset_token_); 698 dev_manager_reset_token_);
695 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); 699 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false);
696 700
697 hr = d3d9_device_ex_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); 701 hr = d3d9_device_ex_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive());
698 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); 702 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false);
699 // Ensure query_ API works (to avoid an infinite loop later in 703 // Ensure query_ API works (to avoid an infinite loop later in
700 // CopyOutputSampleDataToPictureBuffer). 704 // CopyOutputSampleDataToPictureBuffer).
701 hr = query_->Issue(D3DISSUE_END); 705 hr = query_->Issue(D3DISSUE_END);
702 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); 706 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false);
707
708 CreateVideoProcessor();
703 return true; 709 return true;
704 } 710 }
705 711
712 bool DXVAVideoDecodeAccelerator::CreateVideoProcessor() {
713 // TODO(Hubbe): Don't try again if we failed tried and failed already.
714 if (video_processor_service_.get())
715 return true;
716 HRESULT hr = DXVA2CreateVideoService(d3d9_device_ex_.get(),
jbauman 2016/11/17 01:02:22 Might be a good idea to add a finch trial for this
hubbe 2016/11/17 18:46:59 Done.
717 IID_IDirectXVideoProcessorService,
718 video_processor_service_.ReceiveVoid());
719 RETURN_ON_HR_FAILURE(hr, "DXVA2CreateVideoService failed", false);
720
721 // TODO(Hubbe): Use actual video settings.
722 DXVA2_VideoDesc inputDesc;
723 inputDesc.SampleWidth = 1920;
724 inputDesc.SampleHeight = 1080;
725 inputDesc.SampleFormat.VideoChromaSubsampling =
726 DXVA2_VideoChromaSubsampling_MPEG2;
727 inputDesc.SampleFormat.NominalRange = DXVA2_NominalRange_16_235;
728 inputDesc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
729 inputDesc.SampleFormat.VideoLighting = DXVA2_VideoLighting_dim;
730 inputDesc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
731 inputDesc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
732 inputDesc.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
733 inputDesc.Format = (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2');
734 inputDesc.InputSampleFreq.Numerator = 30;
735 inputDesc.InputSampleFreq.Denominator = 1;
736 inputDesc.OutputFrameFreq.Numerator = 30;
737 inputDesc.OutputFrameFreq.Denominator = 1;
738
739 UINT guid_count = 0;
740 base::win::ScopedCoMem<GUID> guids;
741 hr = video_processor_service_->GetVideoProcessorDeviceGuids(
742 &inputDesc, &guid_count, &guids);
743 RETURN_ON_HR_FAILURE(hr, "GetVideoProcessorDeviceGuids failed", false);
744
745 for (UINT g = 0; g < guid_count; g++) {
746 DXVA2_VideoProcessorCaps caps;
747 hr = video_processor_service_->GetVideoProcessorCaps(
748 guids[g], &inputDesc, D3DFMT_X8R8G8B8, &caps);
749 if (hr)
750 continue;
751
752 if (!(caps.VideoProcessorOperations & DXVA2_VideoProcess_YUV2RGB))
753 continue;
754
755 // if (!(caps.VideoProcessorOperations &
756 // DXVA2_VideoProcess_YUV2RGBExtended))
757 // continue;
758
759 base::win::ScopedCoMem<D3DFORMAT> formats;
760 UINT format_count = 0;
761 hr = video_processor_service_->GetVideoProcessorRenderTargets(
762 guids[g], &inputDesc, &format_count, &formats);
763 if (hr)
764 continue;
765
766 UINT f;
767 for (f = 0; f < format_count; f++) {
768 if (formats[f] == D3DFMT_X8R8G8B8) {
769 break;
770 }
771 }
772 if (f == format_count)
773 continue;
774
775 // Create video processor
776 hr = video_processor_service_->CreateVideoProcessor(
777 guids[g], &inputDesc, D3DFMT_X8R8G8B8, 0, processor_.Receive());
778 if (hr)
779 continue;
780
781 DXVA2_ValueRange range;
782 processor_->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &range);
783 default_procamp_values_.Brightness = range.DefaultValue;
784 processor_->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &range);
785 default_procamp_values_.Contrast = range.DefaultValue;
786 processor_->GetProcAmpRange(DXVA2_ProcAmp_Hue, &range);
787 default_procamp_values_.Hue = range.DefaultValue;
788 processor_->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &range);
789 default_procamp_values_.Saturation = range.DefaultValue;
790
791 return true;
792 }
793 return false;
794 }
795
706 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { 796 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() {
707 // The device may exist if the last state was a config change. 797 // The device may exist if the last state was a config change.
708 if (d3d11_device_.get()) 798 if (d3d11_device_.get())
709 return true; 799 return true;
710 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_, 800 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_,
711 d3d11_device_manager_.Receive()); 801 d3d11_device_manager_.Receive());
712 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); 802 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false);
713 803
714 angle_device_ = 804 angle_device_ =
715 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); 805 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE);
(...skipping 1042 matching lines...) Expand 10 before | Expand all | Expand 10 after
1758 HandleResolutionChanged(width, height); 1848 HandleResolutionChanged(width, height);
1759 return; 1849 return;
1760 } 1850 }
1761 1851
1762 pending_sample->picture_buffer_id = index->second->id(); 1852 pending_sample->picture_buffer_id = index->second->id();
1763 index->second->set_bound(); 1853 index->second->set_bound();
1764 1854
1765 // We only propagate the input color space if we can give the raw YUV data 1855 // We only propagate the input color space if we can give the raw YUV data
1766 // back to the browser process. When we cannot return the YUV data, we 1856 // back to the browser process. When we cannot return the YUV data, we
1767 // have to do a copy to an RGBA texture, which makes proper color 1857 // have to do a copy to an RGBA texture, which makes proper color
1768 // management difficult as some fidelity is lost. Also, we currently let 1858 // management difficult as some fidelity is lost. Also, for dx11 we
1769 // the drivers decide how to actually do the YUV to RGB conversion, which 1859 // currently let the drivers decide how to actually do the YUV to RGB
1770 // means that even if we wanted to try to color-adjust the RGB output, we 1860 // conversion, which means that even if we wanted to try to color-adjust
1771 // don't actually know exactly what color space it is in anymore. 1861 // the RGB output, we don't actually know exactly what color space it is
1862 // in anymore.
1772 // TODO(hubbe): Figure out a way to always return the raw YUV data. 1863 // TODO(hubbe): Figure out a way to always return the raw YUV data.
1773 if (share_nv12_textures_ || copy_nv12_textures_) { 1864 if (share_nv12_textures_ || copy_nv12_textures_ || !use_dx11_) {
1774 index->second->set_color_space(pending_sample->color_space); 1865 index->second->set_color_space(pending_sample->color_space);
1775 } 1866 }
1776 1867
1777 if (share_nv12_textures_) { 1868 if (share_nv12_textures_) {
1778 main_thread_task_runner_->PostTask( 1869 main_thread_task_runner_->PostTask(
1779 FROM_HERE, 1870 FROM_HERE,
1780 base::Bind(&DXVAVideoDecodeAccelerator::BindPictureBufferToSample, 1871 base::Bind(&DXVAVideoDecodeAccelerator::BindPictureBufferToSample,
1781 weak_ptr_, pending_sample->output_sample, 1872 weak_ptr_, pending_sample->output_sample,
1782 pending_sample->picture_buffer_id, 1873 pending_sample->picture_buffer_id,
1783 pending_sample->input_buffer_id)); 1874 pending_sample->input_buffer_id));
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
2216 decoder_thread_.init_com_with_mta(false); 2307 decoder_thread_.init_com_with_mta(false);
2217 decoder_thread_.Start(); 2308 decoder_thread_.Start();
2218 decoder_thread_task_runner_ = decoder_thread_.task_runner(); 2309 decoder_thread_task_runner_ = decoder_thread_.task_runner();
2219 } 2310 }
2220 2311
2221 bool DXVAVideoDecodeAccelerator::OutputSamplesPresent() { 2312 bool DXVAVideoDecodeAccelerator::OutputSamplesPresent() {
2222 base::AutoLock lock(decoder_lock_); 2313 base::AutoLock lock(decoder_lock_);
2223 return !pending_output_samples_.empty(); 2314 return !pending_output_samples_.empty();
2224 } 2315 }
2225 2316
2226 void DXVAVideoDecodeAccelerator::CopySurface(IDirect3DSurface9* src_surface, 2317 void DXVAVideoDecodeAccelerator::CopySurface(
2227 IDirect3DSurface9* dest_surface, 2318 IDirect3DSurface9* src_surface,
2228 int picture_buffer_id, 2319 IDirect3DSurface9* dest_surface,
2229 int input_buffer_id) { 2320 int picture_buffer_id,
2321 int input_buffer_id,
2322 const gfx::ColorSpace& color_space) {
2230 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopySurface"); 2323 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopySurface");
2231 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { 2324 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) {
2232 decoder_thread_task_runner_->PostTask( 2325 decoder_thread_task_runner_->PostTask(
2233 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurface, 2326 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurface,
2234 base::Unretained(this), src_surface, dest_surface, 2327 base::Unretained(this), src_surface, dest_surface,
2235 picture_buffer_id, input_buffer_id)); 2328 picture_buffer_id, input_buffer_id, color_space));
2236 return; 2329 return;
2237 } 2330 }
2238 2331
2239 HRESULT hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface, 2332 HRESULT hr;
2240 NULL, D3DTEXF_NONE); 2333 if (processor_) {
2241 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", ); 2334 D3DSURFACE_DESC src_desc;
2335 src_surface->GetDesc(&src_desc);
2336 int width = src_desc.Width;
2337 int height = src_desc.Height;
2338 RECT rect = {0, 0, width, height};
2339 DXVA2_VideoSample sample = {0};
2340 sample.End = 1000;
2341 sample.SampleFormat = gfx::ColorSpaceWin::GetExtendedFormat(color_space);
2342 sample.SrcSurface = src_surface;
2343 sample.SrcRect = rect;
2344 sample.DstRect = rect;
2345 sample.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha();
2242 2346
2347 DXVA2_VideoProcessBltParams params = {0};
2348 params.TargetFrame = 0;
2349 params.TargetRect = rect;
2350 params.ConstrictionSize = {width, height};
2351 params.BackgroundColor = {0, 0, 0, 0xFFFF};
2352 params.ProcAmpValues = default_procamp_values_;
2353
2354 params.Alpha = DXVA2_Fixed32OpaqueAlpha();
2355
2356 hr = processor_->VideoProcessBlt(dest_surface, &params, &sample, 1, NULL);
2357 if (hr != S_OK) {
2358 LOG(ERROR) << "VideoProcessBlt failed with code " << hr
2359 << " E_INVALIDARG= " << E_INVALIDARG;
2360
2361 // Release the processor and fall back to StretchRect()
2362 processor_ = NULL;
2363 }
2364 }
2365
2366 if (!processor_) {
2367 hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface, NULL,
2368 D3DTEXF_NONE);
2369 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", );
2370 }
2243 // Ideally, this should be done immediately before the draw call that uses 2371 // Ideally, this should be done immediately before the draw call that uses
2244 // the texture. Flush it once here though. 2372 // the texture. Flush it once here though.
2245 hr = query_->Issue(D3DISSUE_END); 2373 hr = query_->Issue(D3DISSUE_END);
2246 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", ); 2374 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", );
2247 2375
2248 // If we are sharing the ANGLE device we don't need to wait for the Flush to 2376 // If we are sharing the ANGLE device we don't need to wait for the Flush to
2249 // complete. 2377 // complete.
2250 if (using_angle_device_) { 2378 if (using_angle_device_) {
2251 main_thread_task_runner_->PostTask( 2379 main_thread_task_runner_->PostTask(
2252 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, 2380 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
2730 SetState(kConfigChange); 2858 SetState(kConfigChange);
2731 Invalidate(); 2859 Invalidate();
2732 Initialize(config_, client_); 2860 Initialize(config_, client_);
2733 decoder_thread_task_runner_->PostTask( 2861 decoder_thread_task_runner_->PostTask(
2734 FROM_HERE, 2862 FROM_HERE,
2735 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, 2863 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
2736 base::Unretained(this))); 2864 base::Unretained(this)));
2737 } 2865 }
2738 2866
2739 } // namespace media 2867 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/dxva_video_decode_accelerator_win.h ('k') | ui/gfx/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698