Chromium Code Reviews| 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 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 use_keyed_mutex_(false), | 513 use_keyed_mutex_(false), |
| 511 dx11_video_format_converter_media_type_needs_init_(true), | 514 dx11_video_format_converter_media_type_needs_init_(true), |
| 512 using_angle_device_(false), | 515 using_angle_device_(false), |
| 513 enable_accelerated_vpx_decode_( | 516 enable_accelerated_vpx_decode_( |
| 514 gpu_preferences.enable_accelerated_vpx_decode), | 517 gpu_preferences.enable_accelerated_vpx_decode), |
| 515 processing_config_changed_(false), | 518 processing_config_changed_(false), |
| 516 weak_this_factory_(this) { | 519 weak_this_factory_(this) { |
| 517 weak_ptr_ = weak_this_factory_.GetWeakPtr(); | 520 weak_ptr_ = weak_this_factory_.GetWeakPtr(); |
| 518 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); | 521 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); |
| 519 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); | 522 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); |
| 523 use_color_info_ = base::FeatureList::IsEnabled(kVideoBlitColorAccuracy); | |
| 520 } | 524 } |
| 521 | 525 |
| 522 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { | 526 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { |
| 523 client_ = NULL; | 527 client_ = NULL; |
| 524 } | 528 } |
| 525 | 529 |
| 526 bool DXVAVideoDecodeAccelerator::Initialize(const Config& config, | 530 bool DXVAVideoDecodeAccelerator::Initialize(const Config& config, |
| 527 Client* client) { | 531 Client* client) { |
| 528 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { | 532 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { |
| 529 NOTREACHED() << "GL callbacks are required for this VDA"; | 533 NOTREACHED() << "GL callbacks are required for this VDA"; |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 if (!use_color_info_) | |
| 714 return false; | |
| 715 | |
| 716 // TODO(Hubbe): Don't try again if we failed tried and failed already. | |
| 717 if (video_processor_service_.get()) | |
| 718 return true; | |
| 719 HRESULT hr = DXVA2CreateVideoService(d3d9_device_ex_.get(), | |
| 720 IID_IDirectXVideoProcessorService, | |
| 721 video_processor_service_.ReceiveVoid()); | |
| 722 RETURN_ON_HR_FAILURE(hr, "DXVA2CreateVideoService failed", false); | |
| 723 | |
| 724 // TODO(Hubbe): Use actual video settings. | |
| 725 DXVA2_VideoDesc inputDesc; | |
| 726 inputDesc.SampleWidth = 1920; | |
| 727 inputDesc.SampleHeight = 1080; | |
| 728 inputDesc.SampleFormat.VideoChromaSubsampling = | |
| 729 DXVA2_VideoChromaSubsampling_MPEG2; | |
| 730 inputDesc.SampleFormat.NominalRange = DXVA2_NominalRange_16_235; | |
| 731 inputDesc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709; | |
| 732 inputDesc.SampleFormat.VideoLighting = DXVA2_VideoLighting_dim; | |
| 733 inputDesc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709; | |
| 734 inputDesc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709; | |
| 735 inputDesc.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame; | |
| 736 inputDesc.Format = (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2'); | |
| 737 inputDesc.InputSampleFreq.Numerator = 30; | |
| 738 inputDesc.InputSampleFreq.Denominator = 1; | |
| 739 inputDesc.OutputFrameFreq.Numerator = 30; | |
| 740 inputDesc.OutputFrameFreq.Denominator = 1; | |
| 741 | |
| 742 UINT guid_count = 0; | |
| 743 base::win::ScopedCoMem<GUID> guids; | |
| 744 hr = video_processor_service_->GetVideoProcessorDeviceGuids( | |
| 745 &inputDesc, &guid_count, &guids); | |
| 746 RETURN_ON_HR_FAILURE(hr, "GetVideoProcessorDeviceGuids failed", false); | |
| 747 | |
| 748 for (UINT g = 0; g < guid_count; g++) { | |
| 749 DXVA2_VideoProcessorCaps caps; | |
| 750 hr = video_processor_service_->GetVideoProcessorCaps( | |
| 751 guids[g], &inputDesc, D3DFMT_X8R8G8B8, &caps); | |
| 752 if (hr) | |
| 753 continue; | |
| 754 | |
| 755 if (!(caps.VideoProcessorOperations & DXVA2_VideoProcess_YUV2RGB)) | |
| 756 continue; | |
| 757 | |
| 758 base::win::ScopedCoMem<D3DFORMAT> formats; | |
| 759 UINT format_count = 0; | |
| 760 hr = video_processor_service_->GetVideoProcessorRenderTargets( | |
| 761 guids[g], &inputDesc, &format_count, &formats); | |
| 762 if (hr) | |
| 763 continue; | |
| 764 | |
| 765 UINT f; | |
| 766 for (f = 0; f < format_count; f++) { | |
| 767 if (formats[f] == D3DFMT_X8R8G8B8) { | |
| 768 break; | |
| 769 } | |
| 770 } | |
| 771 if (f == format_count) | |
| 772 continue; | |
| 773 | |
| 774 // Create video processor | |
| 775 hr = video_processor_service_->CreateVideoProcessor( | |
| 776 guids[g], &inputDesc, D3DFMT_X8R8G8B8, 0, processor_.Receive()); | |
| 777 if (hr) | |
| 778 continue; | |
| 779 | |
| 780 DXVA2_ValueRange range; | |
| 781 processor_->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &range); | |
| 782 default_procamp_values_.Brightness = range.DefaultValue; | |
| 783 processor_->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &range); | |
| 784 default_procamp_values_.Contrast = range.DefaultValue; | |
| 785 processor_->GetProcAmpRange(DXVA2_ProcAmp_Hue, &range); | |
| 786 default_procamp_values_.Hue = range.DefaultValue; | |
| 787 processor_->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &range); | |
| 788 default_procamp_values_.Saturation = range.DefaultValue; | |
| 789 | |
| 790 return true; | |
| 791 } | |
| 792 return false; | |
| 793 } | |
| 794 | |
| 706 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { | 795 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
| 707 // The device may exist if the last state was a config change. | 796 // The device may exist if the last state was a config change. |
| 708 if (d3d11_device_.get()) | 797 if (d3d11_device_.get()) |
| 709 return true; | 798 return true; |
| 710 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_, | 799 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_, |
| 711 d3d11_device_manager_.Receive()); | 800 d3d11_device_manager_.Receive()); |
| 712 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); | 801 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); |
| 713 | 802 |
| 714 angle_device_ = | 803 angle_device_ = |
| 715 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); | 804 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); |
| (...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1754 } | 1843 } |
| 1755 | 1844 |
| 1756 if (width != index->second->size().width() || | 1845 if (width != index->second->size().width() || |
| 1757 height != index->second->size().height()) { | 1846 height != index->second->size().height()) { |
| 1758 HandleResolutionChanged(width, height); | 1847 HandleResolutionChanged(width, height); |
| 1759 return; | 1848 return; |
| 1760 } | 1849 } |
| 1761 | 1850 |
| 1762 pending_sample->picture_buffer_id = index->second->id(); | 1851 pending_sample->picture_buffer_id = index->second->id(); |
| 1763 index->second->set_bound(); | 1852 index->second->set_bound(); |
| 1764 | 1853 index->second->set_color_space(pending_sample->color_space); |
| 1765 // 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 | |
| 1767 // 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 | |
| 1769 // the drivers decide how to actually do the YUV to RGB conversion, which | |
| 1770 // means that even if we wanted to try to color-adjust the RGB output, we | |
| 1771 // don't actually know exactly what color space it is in anymore. | |
| 1772 // TODO(hubbe): Figure out a way to always return the raw YUV data. | |
| 1773 if (share_nv12_textures_ || copy_nv12_textures_) { | |
| 1774 index->second->set_color_space(pending_sample->color_space); | |
| 1775 } | |
| 1776 | 1854 |
| 1777 if (share_nv12_textures_) { | 1855 if (share_nv12_textures_) { |
| 1778 main_thread_task_runner_->PostTask( | 1856 main_thread_task_runner_->PostTask( |
| 1779 FROM_HERE, | 1857 FROM_HERE, |
| 1780 base::Bind(&DXVAVideoDecodeAccelerator::BindPictureBufferToSample, | 1858 base::Bind(&DXVAVideoDecodeAccelerator::BindPictureBufferToSample, |
| 1781 weak_ptr_, pending_sample->output_sample, | 1859 weak_ptr_, pending_sample->output_sample, |
| 1782 pending_sample->picture_buffer_id, | 1860 pending_sample->picture_buffer_id, |
| 1783 pending_sample->input_buffer_id)); | 1861 pending_sample->input_buffer_id)); |
| 1784 continue; | 1862 continue; |
| 1785 } | 1863 } |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2216 decoder_thread_.init_com_with_mta(false); | 2294 decoder_thread_.init_com_with_mta(false); |
| 2217 decoder_thread_.Start(); | 2295 decoder_thread_.Start(); |
| 2218 decoder_thread_task_runner_ = decoder_thread_.task_runner(); | 2296 decoder_thread_task_runner_ = decoder_thread_.task_runner(); |
| 2219 } | 2297 } |
| 2220 | 2298 |
| 2221 bool DXVAVideoDecodeAccelerator::OutputSamplesPresent() { | 2299 bool DXVAVideoDecodeAccelerator::OutputSamplesPresent() { |
| 2222 base::AutoLock lock(decoder_lock_); | 2300 base::AutoLock lock(decoder_lock_); |
| 2223 return !pending_output_samples_.empty(); | 2301 return !pending_output_samples_.empty(); |
| 2224 } | 2302 } |
| 2225 | 2303 |
| 2226 void DXVAVideoDecodeAccelerator::CopySurface(IDirect3DSurface9* src_surface, | 2304 void DXVAVideoDecodeAccelerator::CopySurface( |
| 2227 IDirect3DSurface9* dest_surface, | 2305 IDirect3DSurface9* src_surface, |
| 2228 int picture_buffer_id, | 2306 IDirect3DSurface9* dest_surface, |
| 2229 int input_buffer_id) { | 2307 int picture_buffer_id, |
| 2308 int input_buffer_id, | |
| 2309 const gfx::ColorSpace& color_space) { | |
| 2230 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopySurface"); | 2310 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopySurface"); |
| 2231 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { | 2311 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { |
| 2232 decoder_thread_task_runner_->PostTask( | 2312 decoder_thread_task_runner_->PostTask( |
| 2233 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurface, | 2313 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurface, |
| 2234 base::Unretained(this), src_surface, dest_surface, | 2314 base::Unretained(this), src_surface, dest_surface, |
| 2235 picture_buffer_id, input_buffer_id)); | 2315 picture_buffer_id, input_buffer_id, color_space)); |
| 2236 return; | 2316 return; |
| 2237 } | 2317 } |
| 2238 | 2318 |
| 2239 HRESULT hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface, | 2319 HRESULT hr; |
| 2240 NULL, D3DTEXF_NONE); | 2320 if (processor_) { |
| 2241 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", ); | 2321 D3DSURFACE_DESC src_desc; |
| 2322 src_surface->GetDesc(&src_desc); | |
| 2323 int width = src_desc.Width; | |
| 2324 int height = src_desc.Height; | |
| 2325 RECT rect = {0, 0, width, height}; | |
| 2326 DXVA2_VideoSample sample = {0}; | |
| 2327 sample.End = 1000; | |
| 2328 if (use_color_info_) { | |
| 2329 sample.SampleFormat = gfx::ColorSpaceWin::GetExtendedFormat(color_space); | |
| 2330 } else { | |
| 2331 sample.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame; | |
| 2332 } | |
| 2242 | 2333 |
| 2334 sample.SrcSurface = src_surface; | |
| 2335 sample.SrcRect = rect; | |
| 2336 sample.DstRect = rect; | |
| 2337 sample.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha(); | |
| 2338 | |
| 2339 DXVA2_VideoProcessBltParams params = {0}; | |
| 2340 params.TargetFrame = 0; | |
| 2341 params.TargetRect = rect; | |
| 2342 params.ConstrictionSize = {width, height}; | |
| 2343 params.BackgroundColor = {0, 0, 0, 0xFFFF}; | |
| 2344 params.ProcAmpValues = default_procamp_values_; | |
| 2345 | |
| 2346 params.Alpha = DXVA2_Fixed32OpaqueAlpha(); | |
| 2347 | |
| 2348 hr = processor_->VideoProcessBlt(dest_surface, ¶ms, &sample, 1, NULL); | |
| 2349 if (hr != S_OK) { | |
| 2350 LOG(ERROR) << "VideoProcessBlt failed with code " << hr | |
| 2351 << " E_INVALIDARG= " << E_INVALIDARG; | |
| 2352 | |
| 2353 // Release the processor and fall back to StretchRect() | |
| 2354 processor_ = NULL; | |
| 2355 } | |
| 2356 } | |
| 2357 | |
| 2358 if (!processor_) { | |
| 2359 hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface, NULL, | |
| 2360 D3DTEXF_NONE); | |
| 2361 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", ); | |
| 2362 } | |
| 2243 // Ideally, this should be done immediately before the draw call that uses | 2363 // Ideally, this should be done immediately before the draw call that uses |
| 2244 // the texture. Flush it once here though. | 2364 // the texture. Flush it once here though. |
| 2245 hr = query_->Issue(D3DISSUE_END); | 2365 hr = query_->Issue(D3DISSUE_END); |
| 2246 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", ); | 2366 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", ); |
| 2247 | 2367 |
| 2248 // If we are sharing the ANGLE device we don't need to wait for the Flush to | 2368 // If we are sharing the ANGLE device we don't need to wait for the Flush to |
| 2249 // complete. | 2369 // complete. |
| 2250 if (using_angle_device_) { | 2370 if (using_angle_device_) { |
| 2251 main_thread_task_runner_->PostTask( | 2371 main_thread_task_runner_->PostTask( |
| 2252 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, | 2372 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2289 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), | 2409 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
| 2290 "Failed to make context current", | 2410 "Failed to make context current", |
| 2291 PLATFORM_FAILURE, ); | 2411 PLATFORM_FAILURE, ); |
| 2292 | 2412 |
| 2293 DCHECK(!output_picture_buffers_.empty()); | 2413 DCHECK(!output_picture_buffers_.empty()); |
| 2294 | 2414 |
| 2295 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); | 2415 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); |
| 2296 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", | 2416 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", |
| 2297 PLATFORM_FAILURE, ); | 2417 PLATFORM_FAILURE, ); |
| 2298 | 2418 |
| 2299 NotifyPictureReady(picture_buffer->id(), input_buffer_id, | 2419 NotifyPictureReady( |
| 2300 picture_buffer->color_space()); | 2420 picture_buffer->id(), input_buffer_id, |
| 2421 copy_nv12_textures_ ? picture_buffer->color_space() : gfx::ColorSpace()); | |
| 2301 | 2422 |
| 2302 { | 2423 { |
| 2303 base::AutoLock lock(decoder_lock_); | 2424 base::AutoLock lock(decoder_lock_); |
| 2304 if (!pending_output_samples_.empty()) | 2425 if (!pending_output_samples_.empty()) |
| 2305 pending_output_samples_.pop_front(); | 2426 pending_output_samples_.pop_front(); |
| 2306 } | 2427 } |
| 2307 | 2428 |
| 2308 if (pending_flush_ || processing_config_changed_) { | 2429 if (pending_flush_ || processing_config_changed_) { |
| 2309 decoder_thread_task_runner_->PostTask( | 2430 decoder_thread_task_runner_->PostTask( |
| 2310 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, | 2431 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2369 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2490 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
| 2370 base::Unretained(this))); | 2491 base::Unretained(this))); |
| 2371 } | 2492 } |
| 2372 | 2493 |
| 2373 void DXVAVideoDecodeAccelerator::CopyTexture( | 2494 void DXVAVideoDecodeAccelerator::CopyTexture( |
| 2374 ID3D11Texture2D* src_texture, | 2495 ID3D11Texture2D* src_texture, |
| 2375 ID3D11Texture2D* dest_texture, | 2496 ID3D11Texture2D* dest_texture, |
| 2376 base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex, | 2497 base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex, |
| 2377 uint64_t keyed_mutex_value, | 2498 uint64_t keyed_mutex_value, |
| 2378 int picture_buffer_id, | 2499 int picture_buffer_id, |
| 2379 int input_buffer_id) { | 2500 int input_buffer_id, |
| 2501 const gfx::ColorSpace& color_space) { | |
| 2380 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopyTexture"); | 2502 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopyTexture"); |
| 2381 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 2503 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
| 2382 | 2504 |
| 2383 DCHECK(use_dx11_); | 2505 DCHECK(use_dx11_); |
| 2384 | 2506 |
| 2385 // The media foundation H.264 decoder outputs YUV12 textures which we | 2507 // The media foundation H.264 decoder outputs YUV12 textures which we |
| 2386 // cannot copy into ANGLE as they expect ARGB textures. In D3D land | 2508 // cannot copy into ANGLE as they expect ARGB textures. In D3D land |
| 2387 // the StretchRect API in the IDirect3DDevice9Ex interface did the color | 2509 // the StretchRect API in the IDirect3DDevice9Ex interface did the color |
| 2388 // space conversion for us. Sadly in DX11 land the API does not provide | 2510 // space conversion for us. Sadly in DX11 land the API does not provide |
| 2389 // a straightforward way to do this. | 2511 // a straightforward way to do this. |
| 2390 // We use the video processor MFT. | 2512 // We use the video processor MFT. |
| 2391 // https://msdn.microsoft.com/en-us/library/hh162913(v=vs.85).aspx | 2513 // https://msdn.microsoft.com/en-us/library/hh162913(v=vs.85).aspx |
| 2392 // This object implements a media foundation transform (IMFTransform) | 2514 // This object implements a media foundation transform (IMFTransform) |
| 2393 // which follows the same contract as the decoder. The color space | 2515 // which follows the same contract as the decoder. The color space |
| 2394 // conversion as per msdn is done in the GPU. | 2516 // conversion as per msdn is done in the GPU. |
| 2395 | 2517 |
| 2396 D3D11_TEXTURE2D_DESC source_desc; | 2518 D3D11_TEXTURE2D_DESC source_desc; |
| 2397 src_texture->GetDesc(&source_desc); | 2519 src_texture->GetDesc(&source_desc); |
| 2398 | 2520 |
| 2399 // Set up the input and output types for the video processor MFT. | 2521 // Set up the input and output types for the video processor MFT. |
| 2400 if (!InitializeDX11VideoFormatConverterMediaType(source_desc.Width, | 2522 if (!InitializeDX11VideoFormatConverterMediaType( |
| 2401 source_desc.Height)) { | 2523 source_desc.Width, source_desc.Height, color_space)) { |
| 2402 RETURN_AND_NOTIFY_ON_FAILURE( | 2524 RETURN_AND_NOTIFY_ON_FAILURE( |
| 2403 false, "Failed to initialize media types for convesion.", | 2525 false, "Failed to initialize media types for convesion.", |
| 2404 PLATFORM_FAILURE, ); | 2526 PLATFORM_FAILURE, ); |
| 2405 } | 2527 } |
| 2406 | 2528 |
| 2407 // The input to the video processor is the output sample. | 2529 // The input to the video processor is the output sample. |
| 2408 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; | 2530 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; |
| 2409 { | 2531 { |
| 2410 base::AutoLock lock(decoder_lock_); | 2532 base::AutoLock lock(decoder_lock_); |
| 2411 PendingSampleInfo& sample_info = pending_output_samples_.front(); | 2533 PendingSampleInfo& sample_info = pending_output_samples_.front(); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2556 } | 2678 } |
| 2557 | 2679 |
| 2558 main_thread_task_runner_->PostTask( | 2680 main_thread_task_runner_->PostTask( |
| 2559 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, | 2681 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, |
| 2560 weak_ptr_, src_surface, dest_surface, | 2682 weak_ptr_, src_surface, dest_surface, |
| 2561 picture_buffer_id, input_buffer_id)); | 2683 picture_buffer_id, input_buffer_id)); |
| 2562 } | 2684 } |
| 2563 | 2685 |
| 2564 bool DXVAVideoDecodeAccelerator::InitializeDX11VideoFormatConverterMediaType( | 2686 bool DXVAVideoDecodeAccelerator::InitializeDX11VideoFormatConverterMediaType( |
| 2565 int width, | 2687 int width, |
| 2566 int height) { | 2688 int height, |
| 2689 const gfx::ColorSpace& color_space) { | |
| 2567 if (!dx11_video_format_converter_media_type_needs_init_) | 2690 if (!dx11_video_format_converter_media_type_needs_init_) |
| 2568 return true; | 2691 return true; |
|
jbauman
2016/11/22 22:16:59
We may need to reinitialize this if the color spac
hubbe
2016/11/23 21:21:26
Done.
| |
| 2569 | 2692 |
| 2570 CHECK(video_format_converter_mft_.get()); | 2693 CHECK(video_format_converter_mft_.get()); |
| 2571 | 2694 |
| 2572 HRESULT hr = video_format_converter_mft_->ProcessMessage( | 2695 HRESULT hr = video_format_converter_mft_->ProcessMessage( |
| 2573 MFT_MESSAGE_SET_D3D_MANAGER, | 2696 MFT_MESSAGE_SET_D3D_MANAGER, |
| 2574 reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.get())); | 2697 reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.get())); |
| 2575 | 2698 |
| 2576 if (FAILED(hr)) | 2699 if (FAILED(hr)) |
| 2577 DCHECK(false); | 2700 DCHECK(false); |
| 2578 | 2701 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2593 PLATFORM_FAILURE, false); | 2716 PLATFORM_FAILURE, false); |
| 2594 | 2717 |
| 2595 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); | 2718 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); |
| 2596 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", | 2719 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", |
| 2597 PLATFORM_FAILURE, false); | 2720 PLATFORM_FAILURE, false); |
| 2598 | 2721 |
| 2599 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); | 2722 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); |
| 2600 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", | 2723 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", |
| 2601 PLATFORM_FAILURE, false); | 2724 PLATFORM_FAILURE, false); |
| 2602 | 2725 |
| 2726 if (use_color_info_) { | |
| 2727 DXVA2_ExtendedFormat format = | |
| 2728 gfx::ColorSpaceWin::GetExtendedFormat(color_space); | |
| 2729 media_type->SetUINT32(MF_MT_YUV_MATRIX, format.VideoTransferMatrix); | |
| 2730 media_type->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, format.NominalRange); | |
| 2731 media_type->SetUINT32(MF_MT_VIDEO_PRIMARIES, format.VideoPrimaries); | |
| 2732 media_type->SetUINT32(MF_MT_TRANSFER_FUNCTION, | |
| 2733 format.VideoTransferFunction); | |
| 2734 } | |
| 2735 | |
| 2603 hr = video_format_converter_mft_->SetInputType(0, media_type.get(), 0); | 2736 hr = video_format_converter_mft_->SetInputType(0, media_type.get(), 0); |
| 2604 if (FAILED(hr)) | 2737 if (FAILED(hr)) |
| 2605 DCHECK(false); | 2738 DCHECK(false); |
| 2606 | 2739 |
| 2607 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type", | 2740 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type", |
| 2608 PLATFORM_FAILURE, false); | 2741 PLATFORM_FAILURE, false); |
| 2609 | 2742 |
| 2610 // It appears that we fail to set MFVideoFormat_ARGB32 as the output media | 2743 // It appears that we fail to set MFVideoFormat_ARGB32 as the output media |
| 2611 // type in certain configurations. Try to fallback to MFVideoFormat_RGB32 | 2744 // type in certain configurations. Try to fallback to MFVideoFormat_RGB32 |
| 2612 // in such cases. If both fail, then bail. | 2745 // in such cases. If both fail, then bail. |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2730 SetState(kConfigChange); | 2863 SetState(kConfigChange); |
| 2731 Invalidate(); | 2864 Invalidate(); |
| 2732 Initialize(config_, client_); | 2865 Initialize(config_, client_); |
| 2733 decoder_thread_task_runner_->PostTask( | 2866 decoder_thread_task_runner_->PostTask( |
| 2734 FROM_HERE, | 2867 FROM_HERE, |
| 2735 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2868 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
| 2736 base::Unretained(this))); | 2869 base::Unretained(this))); |
| 2737 } | 2870 } |
| 2738 | 2871 |
| 2739 } // namespace media | 2872 } // namespace media |
| OLD | NEW |