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 "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 Loading... | |
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" |
43 #include "media/base/media_switches.h" | |
42 #include "media/base/win/mf_helpers.h" | 44 #include "media/base/win/mf_helpers.h" |
43 #include "media/base/win/mf_initializer.h" | 45 #include "media/base/win/mf_initializer.h" |
44 #include "media/gpu/dxva_picture_buffer_win.h" | 46 #include "media/gpu/dxva_picture_buffer_win.h" |
45 #include "media/video/video_decode_accelerator.h" | 47 #include "media/video/video_decode_accelerator.h" |
46 #include "third_party/angle/include/EGL/egl.h" | 48 #include "third_party/angle/include/EGL/egl.h" |
47 #include "third_party/angle/include/EGL/eglext.h" | 49 #include "third_party/angle/include/EGL/eglext.h" |
50 #include "ui/gfx/color_space_win.h" | |
48 #include "ui/gl/gl_bindings.h" | 51 #include "ui/gl/gl_bindings.h" |
49 #include "ui/gl/gl_context.h" | 52 #include "ui/gl/gl_context.h" |
50 #include "ui/gl/gl_fence.h" | 53 #include "ui/gl/gl_fence.h" |
51 #include "ui/gl/gl_surface_egl.h" | 54 #include "ui/gl/gl_surface_egl.h" |
52 | 55 |
53 namespace { | 56 namespace { |
54 | 57 |
55 // AMD | 58 // AMD |
56 // Path is appended on to the PROGRAM_FILES base path. | 59 // Path is appended on to the PROGRAM_FILES base path. |
57 const wchar_t kAMDVPXDecoderDLLPath[] = | 60 const wchar_t kAMDVPXDecoderDLLPath[] = |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
512 use_keyed_mutex_(false), | 515 use_keyed_mutex_(false), |
513 dx11_video_format_converter_media_type_needs_init_(true), | 516 dx11_video_format_converter_media_type_needs_init_(true), |
514 using_angle_device_(false), | 517 using_angle_device_(false), |
515 enable_accelerated_vpx_decode_( | 518 enable_accelerated_vpx_decode_( |
516 gpu_preferences.enable_accelerated_vpx_decode), | 519 gpu_preferences.enable_accelerated_vpx_decode), |
517 processing_config_changed_(false), | 520 processing_config_changed_(false), |
518 weak_this_factory_(this) { | 521 weak_this_factory_(this) { |
519 weak_ptr_ = weak_this_factory_.GetWeakPtr(); | 522 weak_ptr_ = weak_this_factory_.GetWeakPtr(); |
520 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); | 523 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); |
521 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); | 524 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); |
525 use_color_info_ = base::FeatureList::IsEnabled(kVideoBlitColorAccuracy); | |
522 } | 526 } |
523 | 527 |
524 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { | 528 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { |
525 client_ = NULL; | 529 client_ = NULL; |
526 } | 530 } |
527 | 531 |
528 bool DXVAVideoDecodeAccelerator::Initialize(const Config& config, | 532 bool DXVAVideoDecodeAccelerator::Initialize(const Config& config, |
529 Client* client) { | 533 Client* client) { |
530 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { | 534 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { |
531 NOTREACHED() << "GL callbacks are required for this VDA"; | 535 NOTREACHED() << "GL callbacks are required for this VDA"; |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
695 hr = device_manager_->ResetDevice(d3d9_device_ex_.get(), | 699 hr = device_manager_->ResetDevice(d3d9_device_ex_.get(), |
696 dev_manager_reset_token_); | 700 dev_manager_reset_token_); |
697 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); | 701 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); |
698 | 702 |
699 hr = d3d9_device_ex_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); | 703 hr = d3d9_device_ex_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); |
700 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); | 704 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); |
701 // Ensure query_ API works (to avoid an infinite loop later in | 705 // Ensure query_ API works (to avoid an infinite loop later in |
702 // CopyOutputSampleDataToPictureBuffer). | 706 // CopyOutputSampleDataToPictureBuffer). |
703 hr = query_->Issue(D3DISSUE_END); | 707 hr = query_->Issue(D3DISSUE_END); |
704 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); | 708 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); |
709 | |
710 CreateVideoProcessor(); | |
705 return true; | 711 return true; |
706 } | 712 } |
707 | 713 |
714 bool DXVAVideoDecodeAccelerator::CreateVideoProcessor() { | |
715 if (!use_color_info_) | |
716 return false; | |
717 | |
718 // TODO(Hubbe): Don't try again if we tried and failed already. | |
719 if (video_processor_service_.get()) | |
720 return true; | |
721 HRESULT hr = DXVA2CreateVideoService(d3d9_device_ex_.get(), | |
722 IID_IDirectXVideoProcessorService, | |
723 video_processor_service_.ReceiveVoid()); | |
724 RETURN_ON_HR_FAILURE(hr, "DXVA2CreateVideoService failed", false); | |
725 | |
726 // TODO(Hubbe): Use actual video settings. | |
727 DXVA2_VideoDesc inputDesc; | |
728 inputDesc.SampleWidth = 1920; | |
729 inputDesc.SampleHeight = 1080; | |
730 inputDesc.SampleFormat.VideoChromaSubsampling = | |
731 DXVA2_VideoChromaSubsampling_MPEG2; | |
732 inputDesc.SampleFormat.NominalRange = DXVA2_NominalRange_16_235; | |
733 inputDesc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709; | |
734 inputDesc.SampleFormat.VideoLighting = DXVA2_VideoLighting_dim; | |
735 inputDesc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709; | |
736 inputDesc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709; | |
737 inputDesc.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame; | |
738 inputDesc.Format = (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2'); | |
739 inputDesc.InputSampleFreq.Numerator = 30; | |
740 inputDesc.InputSampleFreq.Denominator = 1; | |
741 inputDesc.OutputFrameFreq.Numerator = 30; | |
742 inputDesc.OutputFrameFreq.Denominator = 1; | |
743 | |
744 UINT guid_count = 0; | |
745 base::win::ScopedCoMem<GUID> guids; | |
746 hr = video_processor_service_->GetVideoProcessorDeviceGuids( | |
747 &inputDesc, &guid_count, &guids); | |
748 RETURN_ON_HR_FAILURE(hr, "GetVideoProcessorDeviceGuids failed", false); | |
749 | |
750 for (UINT g = 0; g < guid_count; g++) { | |
751 DXVA2_VideoProcessorCaps caps; | |
752 hr = video_processor_service_->GetVideoProcessorCaps( | |
753 guids[g], &inputDesc, D3DFMT_X8R8G8B8, &caps); | |
754 if (hr) | |
brucedawson
2016/12/06 21:41:15
The experimental VC++ /analyze builder gives the f
hubbe
2016/12/06 21:46:34
Will fix in a followup CL.
| |
755 continue; | |
756 | |
757 if (!(caps.VideoProcessorOperations & DXVA2_VideoProcess_YUV2RGB)) | |
758 continue; | |
759 | |
760 base::win::ScopedCoMem<D3DFORMAT> formats; | |
761 UINT format_count = 0; | |
762 hr = video_processor_service_->GetVideoProcessorRenderTargets( | |
763 guids[g], &inputDesc, &format_count, &formats); | |
764 if (hr) | |
765 continue; | |
766 | |
767 UINT f; | |
768 for (f = 0; f < format_count; f++) { | |
769 if (formats[f] == D3DFMT_X8R8G8B8) { | |
770 break; | |
771 } | |
772 } | |
773 if (f == format_count) | |
774 continue; | |
775 | |
776 // Create video processor | |
777 hr = video_processor_service_->CreateVideoProcessor( | |
778 guids[g], &inputDesc, D3DFMT_X8R8G8B8, 0, processor_.Receive()); | |
779 if (hr) | |
780 continue; | |
781 | |
782 DXVA2_ValueRange range; | |
783 processor_->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &range); | |
784 default_procamp_values_.Brightness = range.DefaultValue; | |
785 processor_->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &range); | |
786 default_procamp_values_.Contrast = range.DefaultValue; | |
787 processor_->GetProcAmpRange(DXVA2_ProcAmp_Hue, &range); | |
788 default_procamp_values_.Hue = range.DefaultValue; | |
789 processor_->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &range); | |
790 default_procamp_values_.Saturation = range.DefaultValue; | |
791 | |
792 return true; | |
793 } | |
794 return false; | |
795 } | |
796 | |
708 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { | 797 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
709 // The device may exist if the last state was a config change. | 798 // The device may exist if the last state was a config change. |
710 if (d3d11_device_.get()) | 799 if (d3d11_device_.get()) |
711 return true; | 800 return true; |
712 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_, | 801 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_, |
713 d3d11_device_manager_.Receive()); | 802 d3d11_device_manager_.Receive()); |
714 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); | 803 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); |
715 | 804 |
716 angle_device_ = | 805 angle_device_ = |
717 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); | 806 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); |
(...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1778 } | 1867 } |
1779 | 1868 |
1780 if (width != index->second->size().width() || | 1869 if (width != index->second->size().width() || |
1781 height != index->second->size().height()) { | 1870 height != index->second->size().height()) { |
1782 HandleResolutionChanged(width, height); | 1871 HandleResolutionChanged(width, height); |
1783 return; | 1872 return; |
1784 } | 1873 } |
1785 | 1874 |
1786 pending_sample->picture_buffer_id = index->second->id(); | 1875 pending_sample->picture_buffer_id = index->second->id(); |
1787 index->second->set_bound(); | 1876 index->second->set_bound(); |
1788 | 1877 index->second->set_color_space(pending_sample->color_space); |
1789 // We only propagate the input color space if we can give the raw YUV data | |
1790 // back to the browser process. When we cannot return the YUV data, we | |
1791 // have to do a copy to an RGBA texture, which makes proper color | |
1792 // management difficult as some fidelity is lost. Also, we currently let | |
1793 // the drivers decide how to actually do the YUV to RGB conversion, which | |
1794 // means that even if we wanted to try to color-adjust the RGB output, we | |
1795 // don't actually know exactly what color space it is in anymore. | |
1796 // TODO(hubbe): Figure out a way to always return the raw YUV data. | |
1797 if (share_nv12_textures_ || copy_nv12_textures_) { | |
1798 index->second->set_color_space(pending_sample->color_space); | |
1799 } | |
1800 | 1878 |
1801 if (share_nv12_textures_) { | 1879 if (share_nv12_textures_) { |
1802 main_thread_task_runner_->PostTask( | 1880 main_thread_task_runner_->PostTask( |
1803 FROM_HERE, | 1881 FROM_HERE, |
1804 base::Bind(&DXVAVideoDecodeAccelerator::BindPictureBufferToSample, | 1882 base::Bind(&DXVAVideoDecodeAccelerator::BindPictureBufferToSample, |
1805 weak_ptr_, pending_sample->output_sample, | 1883 weak_ptr_, pending_sample->output_sample, |
1806 pending_sample->picture_buffer_id, | 1884 pending_sample->picture_buffer_id, |
1807 pending_sample->input_buffer_id)); | 1885 pending_sample->input_buffer_id)); |
1808 continue; | 1886 continue; |
1809 } | 1887 } |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2240 decoder_thread_.init_com_with_mta(true); | 2318 decoder_thread_.init_com_with_mta(true); |
2241 decoder_thread_.Start(); | 2319 decoder_thread_.Start(); |
2242 decoder_thread_task_runner_ = decoder_thread_.task_runner(); | 2320 decoder_thread_task_runner_ = decoder_thread_.task_runner(); |
2243 } | 2321 } |
2244 | 2322 |
2245 bool DXVAVideoDecodeAccelerator::OutputSamplesPresent() { | 2323 bool DXVAVideoDecodeAccelerator::OutputSamplesPresent() { |
2246 base::AutoLock lock(decoder_lock_); | 2324 base::AutoLock lock(decoder_lock_); |
2247 return !pending_output_samples_.empty(); | 2325 return !pending_output_samples_.empty(); |
2248 } | 2326 } |
2249 | 2327 |
2250 void DXVAVideoDecodeAccelerator::CopySurface(IDirect3DSurface9* src_surface, | 2328 void DXVAVideoDecodeAccelerator::CopySurface( |
2251 IDirect3DSurface9* dest_surface, | 2329 IDirect3DSurface9* src_surface, |
2252 int picture_buffer_id, | 2330 IDirect3DSurface9* dest_surface, |
2253 int input_buffer_id) { | 2331 int picture_buffer_id, |
2332 int input_buffer_id, | |
2333 const gfx::ColorSpace& color_space) { | |
2254 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopySurface"); | 2334 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopySurface"); |
2255 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { | 2335 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { |
2256 decoder_thread_task_runner_->PostTask( | 2336 decoder_thread_task_runner_->PostTask( |
2257 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurface, | 2337 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurface, |
2258 base::Unretained(this), src_surface, dest_surface, | 2338 base::Unretained(this), src_surface, dest_surface, |
2259 picture_buffer_id, input_buffer_id)); | 2339 picture_buffer_id, input_buffer_id, color_space)); |
2260 return; | 2340 return; |
2261 } | 2341 } |
2262 | 2342 |
2263 HRESULT hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface, | 2343 HRESULT hr; |
2264 NULL, D3DTEXF_NONE); | 2344 if (processor_) { |
2265 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", ); | 2345 D3DSURFACE_DESC src_desc; |
2346 src_surface->GetDesc(&src_desc); | |
2347 int width = src_desc.Width; | |
2348 int height = src_desc.Height; | |
2349 RECT rect = {0, 0, width, height}; | |
2350 DXVA2_VideoSample sample = {0}; | |
2351 sample.End = 1000; | |
2352 if (use_color_info_) { | |
2353 sample.SampleFormat = gfx::ColorSpaceWin::GetExtendedFormat(color_space); | |
2354 } else { | |
2355 sample.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame; | |
2356 } | |
2266 | 2357 |
2358 sample.SrcSurface = src_surface; | |
2359 sample.SrcRect = rect; | |
2360 sample.DstRect = rect; | |
2361 sample.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha(); | |
2362 | |
2363 DXVA2_VideoProcessBltParams params = {0}; | |
2364 params.TargetFrame = 0; | |
2365 params.TargetRect = rect; | |
2366 params.ConstrictionSize = {width, height}; | |
2367 params.BackgroundColor = {0, 0, 0, 0xFFFF}; | |
2368 params.ProcAmpValues = default_procamp_values_; | |
2369 | |
2370 params.Alpha = DXVA2_Fixed32OpaqueAlpha(); | |
2371 | |
2372 hr = processor_->VideoProcessBlt(dest_surface, ¶ms, &sample, 1, NULL); | |
2373 if (hr != S_OK) { | |
2374 LOG(ERROR) << "VideoProcessBlt failed with code " << hr | |
2375 << " E_INVALIDARG= " << E_INVALIDARG; | |
2376 | |
2377 // Release the processor and fall back to StretchRect() | |
2378 processor_ = NULL; | |
2379 } | |
2380 } | |
2381 | |
2382 if (!processor_) { | |
2383 hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface, NULL, | |
2384 D3DTEXF_NONE); | |
2385 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", ); | |
2386 } | |
2267 // Ideally, this should be done immediately before the draw call that uses | 2387 // Ideally, this should be done immediately before the draw call that uses |
2268 // the texture. Flush it once here though. | 2388 // the texture. Flush it once here though. |
2269 hr = query_->Issue(D3DISSUE_END); | 2389 hr = query_->Issue(D3DISSUE_END); |
2270 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", ); | 2390 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", ); |
2271 | 2391 |
2272 // If we are sharing the ANGLE device we don't need to wait for the Flush to | 2392 // If we are sharing the ANGLE device we don't need to wait for the Flush to |
2273 // complete. | 2393 // complete. |
2274 if (using_angle_device_) { | 2394 if (using_angle_device_) { |
2275 main_thread_task_runner_->PostTask( | 2395 main_thread_task_runner_->PostTask( |
2276 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, | 2396 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2313 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), | 2433 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
2314 "Failed to make context current", | 2434 "Failed to make context current", |
2315 PLATFORM_FAILURE, ); | 2435 PLATFORM_FAILURE, ); |
2316 | 2436 |
2317 DCHECK(!output_picture_buffers_.empty()); | 2437 DCHECK(!output_picture_buffers_.empty()); |
2318 | 2438 |
2319 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); | 2439 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); |
2320 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", | 2440 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", |
2321 PLATFORM_FAILURE, ); | 2441 PLATFORM_FAILURE, ); |
2322 | 2442 |
2323 NotifyPictureReady(picture_buffer->id(), input_buffer_id, | 2443 NotifyPictureReady( |
2324 picture_buffer->color_space()); | 2444 picture_buffer->id(), input_buffer_id, |
2445 copy_nv12_textures_ ? picture_buffer->color_space() : gfx::ColorSpace()); | |
2325 | 2446 |
2326 { | 2447 { |
2327 base::AutoLock lock(decoder_lock_); | 2448 base::AutoLock lock(decoder_lock_); |
2328 if (!pending_output_samples_.empty()) | 2449 if (!pending_output_samples_.empty()) |
2329 pending_output_samples_.pop_front(); | 2450 pending_output_samples_.pop_front(); |
2330 } | 2451 } |
2331 | 2452 |
2332 if (pending_flush_ || processing_config_changed_) { | 2453 if (pending_flush_ || processing_config_changed_) { |
2333 decoder_thread_task_runner_->PostTask( | 2454 decoder_thread_task_runner_->PostTask( |
2334 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, | 2455 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2393 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2514 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
2394 base::Unretained(this))); | 2515 base::Unretained(this))); |
2395 } | 2516 } |
2396 | 2517 |
2397 void DXVAVideoDecodeAccelerator::CopyTexture( | 2518 void DXVAVideoDecodeAccelerator::CopyTexture( |
2398 ID3D11Texture2D* src_texture, | 2519 ID3D11Texture2D* src_texture, |
2399 ID3D11Texture2D* dest_texture, | 2520 ID3D11Texture2D* dest_texture, |
2400 base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex, | 2521 base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex, |
2401 uint64_t keyed_mutex_value, | 2522 uint64_t keyed_mutex_value, |
2402 int picture_buffer_id, | 2523 int picture_buffer_id, |
2403 int input_buffer_id) { | 2524 int input_buffer_id, |
2525 const gfx::ColorSpace& color_space) { | |
2404 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopyTexture"); | 2526 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopyTexture"); |
2405 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 2527 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
2406 | 2528 |
2407 DCHECK(use_dx11_); | 2529 DCHECK(use_dx11_); |
2408 | 2530 |
2409 // The media foundation H.264 decoder outputs YUV12 textures which we | 2531 // The media foundation H.264 decoder outputs YUV12 textures which we |
2410 // cannot copy into ANGLE as they expect ARGB textures. In D3D land | 2532 // cannot copy into ANGLE as they expect ARGB textures. In D3D land |
2411 // the StretchRect API in the IDirect3DDevice9Ex interface did the color | 2533 // the StretchRect API in the IDirect3DDevice9Ex interface did the color |
2412 // space conversion for us. Sadly in DX11 land the API does not provide | 2534 // space conversion for us. Sadly in DX11 land the API does not provide |
2413 // a straightforward way to do this. | 2535 // a straightforward way to do this. |
2414 // We use the video processor MFT. | 2536 // We use the video processor MFT. |
2415 // https://msdn.microsoft.com/en-us/library/hh162913(v=vs.85).aspx | 2537 // https://msdn.microsoft.com/en-us/library/hh162913(v=vs.85).aspx |
2416 // This object implements a media foundation transform (IMFTransform) | 2538 // This object implements a media foundation transform (IMFTransform) |
2417 // which follows the same contract as the decoder. The color space | 2539 // which follows the same contract as the decoder. The color space |
2418 // conversion as per msdn is done in the GPU. | 2540 // conversion as per msdn is done in the GPU. |
2419 | 2541 |
2420 D3D11_TEXTURE2D_DESC source_desc; | 2542 D3D11_TEXTURE2D_DESC source_desc; |
2421 src_texture->GetDesc(&source_desc); | 2543 src_texture->GetDesc(&source_desc); |
2422 | 2544 |
2423 // Set up the input and output types for the video processor MFT. | 2545 // Set up the input and output types for the video processor MFT. |
2424 if (!InitializeDX11VideoFormatConverterMediaType(source_desc.Width, | 2546 if (!InitializeDX11VideoFormatConverterMediaType( |
2425 source_desc.Height)) { | 2547 source_desc.Width, source_desc.Height, color_space)) { |
2426 RETURN_AND_NOTIFY_ON_FAILURE( | 2548 RETURN_AND_NOTIFY_ON_FAILURE( |
2427 false, "Failed to initialize media types for convesion.", | 2549 false, "Failed to initialize media types for convesion.", |
2428 PLATFORM_FAILURE, ); | 2550 PLATFORM_FAILURE, ); |
2429 } | 2551 } |
2430 | 2552 |
2431 // The input to the video processor is the output sample. | 2553 // The input to the video processor is the output sample. |
2432 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; | 2554 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; |
2433 { | 2555 { |
2434 base::AutoLock lock(decoder_lock_); | 2556 base::AutoLock lock(decoder_lock_); |
2435 PendingSampleInfo& sample_info = pending_output_samples_.front(); | 2557 PendingSampleInfo& sample_info = pending_output_samples_.front(); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2580 } | 2702 } |
2581 | 2703 |
2582 main_thread_task_runner_->PostTask( | 2704 main_thread_task_runner_->PostTask( |
2583 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, | 2705 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, |
2584 weak_ptr_, src_surface, dest_surface, | 2706 weak_ptr_, src_surface, dest_surface, |
2585 picture_buffer_id, input_buffer_id)); | 2707 picture_buffer_id, input_buffer_id)); |
2586 } | 2708 } |
2587 | 2709 |
2588 bool DXVAVideoDecodeAccelerator::InitializeDX11VideoFormatConverterMediaType( | 2710 bool DXVAVideoDecodeAccelerator::InitializeDX11VideoFormatConverterMediaType( |
2589 int width, | 2711 int width, |
2590 int height) { | 2712 int height, |
2591 if (!dx11_video_format_converter_media_type_needs_init_) | 2713 const gfx::ColorSpace& color_space) { |
2714 if (!dx11_video_format_converter_media_type_needs_init_ && | |
2715 (!use_color_info_ || color_space == dx11_converter_color_space_)) { | |
2592 return true; | 2716 return true; |
2717 } | |
2593 | 2718 |
2594 CHECK(video_format_converter_mft_.get()); | 2719 CHECK(video_format_converter_mft_.get()); |
2595 | 2720 |
2596 HRESULT hr = video_format_converter_mft_->ProcessMessage( | 2721 HRESULT hr = video_format_converter_mft_->ProcessMessage( |
2597 MFT_MESSAGE_SET_D3D_MANAGER, | 2722 MFT_MESSAGE_SET_D3D_MANAGER, |
2598 reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.get())); | 2723 reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.get())); |
2599 | 2724 |
2600 if (FAILED(hr)) | 2725 if (FAILED(hr)) |
2601 DCHECK(false); | 2726 DCHECK(false); |
2602 | 2727 |
(...skipping 14 matching lines...) Expand all Loading... | |
2617 PLATFORM_FAILURE, false); | 2742 PLATFORM_FAILURE, false); |
2618 | 2743 |
2619 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); | 2744 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); |
2620 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", | 2745 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", |
2621 PLATFORM_FAILURE, false); | 2746 PLATFORM_FAILURE, false); |
2622 | 2747 |
2623 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); | 2748 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); |
2624 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", | 2749 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", |
2625 PLATFORM_FAILURE, false); | 2750 PLATFORM_FAILURE, false); |
2626 | 2751 |
2752 if (use_color_info_) { | |
2753 DXVA2_ExtendedFormat format = | |
2754 gfx::ColorSpaceWin::GetExtendedFormat(color_space); | |
2755 media_type->SetUINT32(MF_MT_YUV_MATRIX, format.VideoTransferMatrix); | |
2756 media_type->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, format.NominalRange); | |
2757 media_type->SetUINT32(MF_MT_VIDEO_PRIMARIES, format.VideoPrimaries); | |
2758 media_type->SetUINT32(MF_MT_TRANSFER_FUNCTION, | |
2759 format.VideoTransferFunction); | |
2760 dx11_converter_color_space_ = color_space; | |
2761 } | |
2762 | |
2627 hr = video_format_converter_mft_->SetInputType(0, media_type.get(), 0); | 2763 hr = video_format_converter_mft_->SetInputType(0, media_type.get(), 0); |
2628 if (FAILED(hr)) | 2764 if (FAILED(hr)) |
2629 DCHECK(false); | 2765 DCHECK(false); |
2630 | 2766 |
2631 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type", | 2767 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type", |
2632 PLATFORM_FAILURE, false); | 2768 PLATFORM_FAILURE, false); |
2633 | 2769 |
2634 // It appears that we fail to set MFVideoFormat_ARGB32 as the output media | 2770 // It appears that we fail to set MFVideoFormat_ARGB32 as the output media |
2635 // type in certain configurations. Try to fallback to MFVideoFormat_RGB32 | 2771 // type in certain configurations. Try to fallback to MFVideoFormat_RGB32 |
2636 // in such cases. If both fail, then bail. | 2772 // in such cases. If both fail, then bail. |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2759 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2895 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
2760 base::Unretained(this))); | 2896 base::Unretained(this))); |
2761 } | 2897 } |
2762 | 2898 |
2763 uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const { | 2899 uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const { |
2764 bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_; | 2900 bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_; |
2765 return provide_nv12_textures ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; | 2901 return provide_nv12_textures ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; |
2766 } | 2902 } |
2767 | 2903 |
2768 } // namespace media | 2904 } // namespace media |
OLD | NEW |