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

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: merged Created 4 years 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"
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
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
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
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
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, &params, &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
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
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
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
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
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
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