| 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. |
| 11 #endif // !defined(OS_WIN) | 11 #endif // !defined(OS_WIN) |
| 12 | 12 |
| 13 #include <codecapi.h> | 13 #include <codecapi.h> |
| 14 #include <dxgi1_2.h> | 14 #include <dxgi1_2.h> |
| 15 #include <ks.h> | 15 #include <ks.h> |
| 16 #include <mfapi.h> | 16 #include <mfapi.h> |
| 17 #include <mferror.h> | 17 #include <mferror.h> |
| 18 #include <ntverp.h> | 18 #include <ntverp.h> |
| 19 #include <stddef.h> | 19 #include <stddef.h> |
| 20 #include <string.h> | 20 #include <string.h> |
| 21 #include <wmcodecdsp.h> | 21 #include <wmcodecdsp.h> |
| 22 | 22 |
| 23 #include "base/atomicops.h" | 23 #include "base/atomicops.h" |
| 24 #include "base/base_paths_win.h" | 24 #include "base/base_paths_win.h" |
| 25 #include "base/bind.h" | 25 #include "base/bind.h" |
| 26 #include "base/callback.h" | 26 #include "base/callback.h" |
| 27 #include "base/command_line.h" |
| 27 #include "base/debug/alias.h" | 28 #include "base/debug/alias.h" |
| 28 #include "base/file_version_info.h" | 29 #include "base/file_version_info.h" |
| 29 #include "base/files/file_path.h" | 30 #include "base/files/file_path.h" |
| 30 #include "base/location.h" | 31 #include "base/location.h" |
| 31 #include "base/logging.h" | 32 #include "base/logging.h" |
| 32 #include "base/macros.h" | 33 #include "base/macros.h" |
| 33 #include "base/memory/shared_memory.h" | 34 #include "base/memory/shared_memory.h" |
| 34 #include "base/path_service.h" | 35 #include "base/path_service.h" |
| 35 #include "base/single_thread_task_runner.h" | 36 #include "base/single_thread_task_runner.h" |
| 36 #include "base/stl_util.h" | 37 #include "base/stl_util.h" |
| 37 #include "base/threading/thread_local_storage.h" | 38 #include "base/threading/thread_local_storage.h" |
| 38 #include "base/threading/thread_task_runner_handle.h" | 39 #include "base/threading/thread_task_runner_handle.h" |
| 39 #include "base/trace_event/trace_event.h" | 40 #include "base/trace_event/trace_event.h" |
| 40 #include "base/win/scoped_co_mem.h" | 41 #include "base/win/scoped_co_mem.h" |
| 41 #include "base/win/windows_version.h" | 42 #include "base/win/windows_version.h" |
| 42 #include "build/build_config.h" | 43 #include "build/build_config.h" |
| 43 #include "gpu/command_buffer/service/gpu_preferences.h" | 44 #include "gpu/command_buffer/service/gpu_preferences.h" |
| 44 #include "gpu/config/gpu_driver_bug_workarounds.h" | 45 #include "gpu/config/gpu_driver_bug_workarounds.h" |
| 45 #include "media/base/media_switches.h" | 46 #include "media/base/media_switches.h" |
| 46 #include "media/base/win/mf_helpers.h" | 47 #include "media/base/win/mf_helpers.h" |
| 47 #include "media/base/win/mf_initializer.h" | 48 #include "media/base/win/mf_initializer.h" |
| 48 #include "media/gpu/dxva_picture_buffer_win.h" | 49 #include "media/gpu/dxva_picture_buffer_win.h" |
| 49 #include "media/video/video_decode_accelerator.h" | 50 #include "media/video/video_decode_accelerator.h" |
| 50 #include "third_party/angle/include/EGL/egl.h" | 51 #include "third_party/angle/include/EGL/egl.h" |
| 51 #include "third_party/angle/include/EGL/eglext.h" | 52 #include "third_party/angle/include/EGL/eglext.h" |
| 53 #include "ui/base/ui_base_switches.h" |
| 52 #include "ui/gfx/color_space_win.h" | 54 #include "ui/gfx/color_space_win.h" |
| 53 #include "ui/gl/gl_angle_util_win.h" | 55 #include "ui/gl/gl_angle_util_win.h" |
| 54 #include "ui/gl/gl_bindings.h" | 56 #include "ui/gl/gl_bindings.h" |
| 55 #include "ui/gl/gl_context.h" | 57 #include "ui/gl/gl_context.h" |
| 56 #include "ui/gl/gl_fence.h" | 58 #include "ui/gl/gl_fence.h" |
| 57 #include "ui/gl/gl_surface_egl.h" | 59 #include "ui/gl/gl_surface_egl.h" |
| 58 | 60 |
| 59 namespace { | 61 namespace { |
| 60 | 62 |
| 61 // AMD | 63 // AMD |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 PLATFORM_FAILURE, false); | 558 PLATFORM_FAILURE, false); |
| 557 } | 559 } |
| 558 | 560 |
| 559 if (config.profile == VP9PROFILE_PROFILE2 || | 561 if (config.profile == VP9PROFILE_PROFILE2 || |
| 560 config.profile == VP9PROFILE_PROFILE3 || | 562 config.profile == VP9PROFILE_PROFILE3 || |
| 561 config.profile == H264PROFILE_HIGH10PROFILE) { | 563 config.profile == H264PROFILE_HIGH10PROFILE) { |
| 562 // Input file has more than 8 bits per channel. | 564 // Input file has more than 8 bits per channel. |
| 563 use_fp16_ = true; | 565 use_fp16_ = true; |
| 564 } | 566 } |
| 565 | 567 |
| 568 // Unfortunately, the profile is currently unreliable for |
| 569 // VP9 (crbug.com/592074) so also try to use fp16 if HDR is on. |
| 570 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 571 switches::kEnableHDROutput)) { |
| 572 use_fp16_ = true; |
| 573 } |
| 574 |
| 566 // Not all versions of Windows 7 and later include Media Foundation DLLs. | 575 // Not all versions of Windows 7 and later include Media Foundation DLLs. |
| 567 // Instead of crashing while delay loading the DLL when calling MFStartup() | 576 // Instead of crashing while delay loading the DLL when calling MFStartup() |
| 568 // below, probe whether we can successfully load the DLL now. | 577 // below, probe whether we can successfully load the DLL now. |
| 569 // See http://crbug.com/339678 for details. | 578 // See http://crbug.com/339678 for details. |
| 570 HMODULE dxgi_manager_dll = ::GetModuleHandle(L"MFPlat.dll"); | 579 HMODULE dxgi_manager_dll = ::GetModuleHandle(L"MFPlat.dll"); |
| 571 RETURN_ON_FAILURE(dxgi_manager_dll, "MFPlat.dll is required for decoding", | 580 RETURN_ON_FAILURE(dxgi_manager_dll, "MFPlat.dll is required for decoding", |
| 572 false); | 581 false); |
| 573 | 582 |
| 574 // On Windows 8+ mfplat.dll provides the MFCreateDXGIDeviceManager API. | 583 // On Windows 8+ mfplat.dll provides the MFCreateDXGIDeviceManager API. |
| 575 // On Windows 7 mshtmlmedia.dll provides it. | 584 // On Windows 7 mshtmlmedia.dll provides it. |
| (...skipping 1912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2488 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), | 2497 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
| 2489 "Failed to make context current", | 2498 "Failed to make context current", |
| 2490 PLATFORM_FAILURE, ); | 2499 PLATFORM_FAILURE, ); |
| 2491 | 2500 |
| 2492 DCHECK(!output_picture_buffers_.empty()); | 2501 DCHECK(!output_picture_buffers_.empty()); |
| 2493 | 2502 |
| 2494 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); | 2503 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); |
| 2495 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", | 2504 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", |
| 2496 PLATFORM_FAILURE, ); | 2505 PLATFORM_FAILURE, ); |
| 2497 | 2506 |
| 2498 NotifyPictureReady( | 2507 NotifyPictureReady(picture_buffer->id(), input_buffer_id, |
| 2499 picture_buffer->id(), input_buffer_id, | 2508 picture_buffer->color_space()); |
| 2500 copy_nv12_textures_ ? picture_buffer->color_space() : gfx::ColorSpace()); | |
| 2501 | 2509 |
| 2502 { | 2510 { |
| 2503 base::AutoLock lock(decoder_lock_); | 2511 base::AutoLock lock(decoder_lock_); |
| 2504 if (!pending_output_samples_.empty()) | 2512 if (!pending_output_samples_.empty()) |
| 2505 pending_output_samples_.pop_front(); | 2513 pending_output_samples_.pop_front(); |
| 2506 } | 2514 } |
| 2507 | 2515 |
| 2508 if (pending_flush_ || processing_config_changed_) { | 2516 if (pending_flush_ || processing_config_changed_) { |
| 2509 decoder_thread_task_runner_->PostTask( | 2517 decoder_thread_task_runner_->PostTask( |
| 2510 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, | 2518 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2591 | 2599 |
| 2592 D3D11_TEXTURE2D_DESC source_desc; | 2600 D3D11_TEXTURE2D_DESC source_desc; |
| 2593 src_texture->GetDesc(&source_desc); | 2601 src_texture->GetDesc(&source_desc); |
| 2594 if (!InitializeID3D11VideoProcessor(source_desc.Width, source_desc.Height, | 2602 if (!InitializeID3D11VideoProcessor(source_desc.Width, source_desc.Height, |
| 2595 color_space)) { | 2603 color_space)) { |
| 2596 RETURN_AND_NOTIFY_ON_FAILURE(false, | 2604 RETURN_AND_NOTIFY_ON_FAILURE(false, |
| 2597 "Failed to initialize D3D11 video processor.", | 2605 "Failed to initialize D3D11 video processor.", |
| 2598 PLATFORM_FAILURE, ); | 2606 PLATFORM_FAILURE, ); |
| 2599 } | 2607 } |
| 2600 | 2608 |
| 2609 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); |
| 2610 if (it != output_picture_buffers_.end()) { |
| 2611 it->second->set_color_space(dx11_converter_output_color_space_); |
| 2612 } |
| 2613 |
| 2601 // The input to the video processor is the output sample. | 2614 // The input to the video processor is the output sample. |
| 2602 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; | 2615 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; |
| 2603 { | 2616 { |
| 2604 base::AutoLock lock(decoder_lock_); | 2617 base::AutoLock lock(decoder_lock_); |
| 2605 PendingSampleInfo& sample_info = pending_output_samples_.front(); | 2618 PendingSampleInfo& sample_info = pending_output_samples_.front(); |
| 2606 input_sample_for_conversion = sample_info.output_sample; | 2619 input_sample_for_conversion = sample_info.output_sample; |
| 2607 } | 2620 } |
| 2608 | 2621 |
| 2609 decoder_thread_task_runner_->PostTask( | 2622 decoder_thread_task_runner_->PostTask( |
| 2610 FROM_HERE, | 2623 FROM_HERE, |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2802 // color space on input and output. | 2815 // color space on input and output. |
| 2803 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = {0}; | 2816 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = {0}; |
| 2804 d3d11_color_space.RGB_Range = 1; | 2817 d3d11_color_space.RGB_Range = 1; |
| 2805 d3d11_color_space.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255; | 2818 d3d11_color_space.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255; |
| 2806 | 2819 |
| 2807 video_context_->VideoProcessorSetOutputColorSpace(d3d11_processor_.get(), | 2820 video_context_->VideoProcessorSetOutputColorSpace(d3d11_processor_.get(), |
| 2808 &d3d11_color_space); | 2821 &d3d11_color_space); |
| 2809 | 2822 |
| 2810 video_context_->VideoProcessorSetStreamColorSpace(d3d11_processor_.get(), 0, | 2823 video_context_->VideoProcessorSetStreamColorSpace(d3d11_processor_.get(), 0, |
| 2811 &d3d11_color_space); | 2824 &d3d11_color_space); |
| 2825 dx11_converter_output_color_space_ = color_space; |
| 2812 } else { | 2826 } else { |
| 2827 dx11_converter_output_color_space_ = gfx::ColorSpace::CreateSRGB(); |
| 2813 // Not sure if this call is expensive, let's only do it if the color | 2828 // Not sure if this call is expensive, let's only do it if the color |
| 2814 // space changes. | 2829 // space changes. |
| 2815 gfx::ColorSpace output_color_space = gfx::ColorSpace::CreateSRGB(); | 2830 if ((use_color_info_ || use_fp16_) && |
| 2816 if (use_color_info_ && dx11_converter_color_space_ != color_space) { | 2831 dx11_converter_color_space_ != color_space) { |
| 2817 base::win::ScopedComPtr<ID3D11VideoContext1> video_context1; | 2832 base::win::ScopedComPtr<ID3D11VideoContext1> video_context1; |
| 2818 HRESULT hr = video_context_.QueryInterface(video_context1.Receive()); | 2833 HRESULT hr = video_context_.QueryInterface(video_context1.Receive()); |
| 2819 if (SUCCEEDED(hr)) { | 2834 if (SUCCEEDED(hr)) { |
| 2835 if (use_fp16_ && base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 2836 switches::kEnableHDROutput)) { |
| 2837 dx11_converter_output_color_space_ = |
| 2838 gfx::ColorSpace::CreateSCRGBLinear(); |
| 2839 } |
| 2820 video_context1->VideoProcessorSetStreamColorSpace1( | 2840 video_context1->VideoProcessorSetStreamColorSpace1( |
| 2821 d3d11_processor_.get(), 0, | 2841 d3d11_processor_.get(), 0, |
| 2822 gfx::ColorSpaceWin::GetDXGIColorSpace(color_space)); | 2842 gfx::ColorSpaceWin::GetDXGIColorSpace(color_space)); |
| 2823 video_context1->VideoProcessorSetOutputColorSpace1( | 2843 video_context1->VideoProcessorSetOutputColorSpace1( |
| 2824 d3d11_processor_.get(), | 2844 d3d11_processor_.get(), gfx::ColorSpaceWin::GetDXGIColorSpace( |
| 2825 gfx::ColorSpaceWin::GetDXGIColorSpace(output_color_space)); | 2845 dx11_converter_output_color_space_)); |
| 2826 } else { | 2846 } else { |
| 2827 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = | 2847 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = |
| 2828 gfx::ColorSpaceWin::GetD3D11ColorSpace(color_space); | 2848 gfx::ColorSpaceWin::GetD3D11ColorSpace(color_space); |
| 2829 video_context_->VideoProcessorSetStreamColorSpace( | 2849 video_context_->VideoProcessorSetStreamColorSpace( |
| 2830 d3d11_processor_.get(), 0, &d3d11_color_space); | 2850 d3d11_processor_.get(), 0, &d3d11_color_space); |
| 2831 d3d11_color_space = | 2851 d3d11_color_space = gfx::ColorSpaceWin::GetD3D11ColorSpace( |
| 2832 gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space); | 2852 dx11_converter_output_color_space_); |
| 2833 video_context_->VideoProcessorSetOutputColorSpace( | 2853 video_context_->VideoProcessorSetOutputColorSpace( |
| 2834 d3d11_processor_.get(), &d3d11_color_space); | 2854 d3d11_processor_.get(), &d3d11_color_space); |
| 2835 } | 2855 } |
| 2836 dx11_converter_color_space_ = color_space; | 2856 dx11_converter_color_space_ = color_space; |
| 2837 } | 2857 } |
| 2838 } | 2858 } |
| 2839 return true; | 2859 return true; |
| 2840 } | 2860 } |
| 2841 | 2861 |
| 2842 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions(IMFSample* sample, | 2862 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions(IMFSample* sample, |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2937 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2957 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
| 2938 base::Unretained(this))); | 2958 base::Unretained(this))); |
| 2939 } | 2959 } |
| 2940 | 2960 |
| 2941 uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const { | 2961 uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const { |
| 2942 bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_; | 2962 bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_; |
| 2943 return provide_nv12_textures ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; | 2963 return provide_nv12_textures ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; |
| 2944 } | 2964 } |
| 2945 | 2965 |
| 2946 } // namespace media | 2966 } // namespace media |
| OLD | NEW |