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

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

Issue 2696963002: Replace IMFTransform with ID3D11VideoProcessor (Closed)
Patch Set: fixed initialization Created 3 years, 10 months 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/color_space_win.h » ('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 482 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 codec_(kUnknownVideoCodec), 493 codec_(kUnknownVideoCodec),
494 decoder_thread_("DXVAVideoDecoderThread"), 494 decoder_thread_("DXVAVideoDecoderThread"),
495 pending_flush_(false), 495 pending_flush_(false),
496 enable_low_latency_(gpu_preferences.enable_low_latency_dxva), 496 enable_low_latency_(gpu_preferences.enable_low_latency_dxva),
497 share_nv12_textures_(gpu_preferences.enable_zero_copy_dxgi_video && 497 share_nv12_textures_(gpu_preferences.enable_zero_copy_dxgi_video &&
498 !workarounds.disable_dxgi_zero_copy_video), 498 !workarounds.disable_dxgi_zero_copy_video),
499 copy_nv12_textures_(gpu_preferences.enable_nv12_dxgi_video && 499 copy_nv12_textures_(gpu_preferences.enable_nv12_dxgi_video &&
500 !workarounds.disable_nv12_dxgi_video), 500 !workarounds.disable_nv12_dxgi_video),
501 use_dx11_(false), 501 use_dx11_(false),
502 use_keyed_mutex_(false), 502 use_keyed_mutex_(false),
503 dx11_video_format_converter_media_type_needs_init_(true),
504 using_angle_device_(false), 503 using_angle_device_(false),
505 enable_accelerated_vpx_decode_( 504 enable_accelerated_vpx_decode_(
506 gpu_preferences.enable_accelerated_vpx_decode), 505 gpu_preferences.enable_accelerated_vpx_decode),
507 processing_config_changed_(false), 506 processing_config_changed_(false),
508 weak_this_factory_(this) { 507 weak_this_factory_(this) {
509 weak_ptr_ = weak_this_factory_.GetWeakPtr(); 508 weak_ptr_ = weak_this_factory_.GetWeakPtr();
510 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); 509 memset(&input_stream_info_, 0, sizeof(input_stream_info_));
511 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); 510 memset(&output_stream_info_, 0, sizeof(output_stream_info_));
512 use_color_info_ = base::FeatureList::IsEnabled(kVideoBlitColorAccuracy); 511 use_color_info_ = base::FeatureList::IsEnabled(kVideoBlitColorAccuracy);
513 } 512 }
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 RETURN_ON_HR_FAILURE(hr, "Failed to create debug DX11 device", false); 822 RETURN_ON_HR_FAILURE(hr, "Failed to create debug DX11 device", false);
824 } 823 }
825 #endif 824 #endif
826 if (!d3d11_device_context_) { 825 if (!d3d11_device_context_) {
827 hr = D3D11CreateDevice( 826 hr = D3D11CreateDevice(
828 NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, feature_levels, 827 NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, feature_levels,
829 arraysize(feature_levels), D3D11_SDK_VERSION, d3d11_device_.Receive(), 828 arraysize(feature_levels), D3D11_SDK_VERSION, d3d11_device_.Receive(),
830 &feature_level_out, d3d11_device_context_.Receive()); 829 &feature_level_out, d3d11_device_context_.Receive());
831 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device", false); 830 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device", false);
832 } 831 }
832
833 hr = d3d11_device_.QueryInterface(video_device_.Receive());
834 RETURN_ON_HR_FAILURE(hr, "Failed to get video device", false);
835
836 hr = d3d11_device_context_.QueryInterface(video_context_.Receive());
837 RETURN_ON_HR_FAILURE(hr, "Failed to get video context", false);
833 } 838 }
834 839
835 D3D11_FEATURE_DATA_D3D11_OPTIONS options; 840 D3D11_FEATURE_DATA_D3D11_OPTIONS options;
836 hr = d3d11_device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, 841 hr = d3d11_device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options,
837 sizeof(options)); 842 sizeof(options));
838 RETURN_ON_HR_FAILURE(hr, "Failed to retrieve D3D11 options", false); 843 RETURN_ON_HR_FAILURE(hr, "Failed to retrieve D3D11 options", false);
839 844
840 // Need extended resource sharing so we can share the NV12 texture between 845 // Need extended resource sharing so we can share the NV12 texture between
841 // ANGLE and the decoder context. 846 // ANGLE and the decoder context.
842 if (!options.ExtendedResourceSharing) 847 if (!options.ExtendedResourceSharing)
(...skipping 18 matching lines...) Expand all
861 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(), 866 hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(),
862 dx11_dev_manager_reset_token_); 867 dx11_dev_manager_reset_token_);
863 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); 868 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false);
864 869
865 D3D11_QUERY_DESC query_desc; 870 D3D11_QUERY_DESC query_desc;
866 query_desc.Query = D3D11_QUERY_EVENT; 871 query_desc.Query = D3D11_QUERY_EVENT;
867 query_desc.MiscFlags = 0; 872 query_desc.MiscFlags = 0;
868 hr = d3d11_device_->CreateQuery(&query_desc, d3d11_query_.Receive()); 873 hr = d3d11_device_->CreateQuery(&query_desc, d3d11_query_.Receive());
869 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false); 874 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false);
870 875
871 HMODULE video_processor_dll = ::GetModuleHandle(L"msvproc.dll");
872 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor",
873 false);
874
875 hr = CreateCOMObjectFromDll(video_processor_dll, CLSID_VideoProcessorMFT,
876 __uuidof(IMFTransform),
877 video_format_converter_mft_.ReceiveVoid());
878 RETURN_ON_HR_FAILURE(hr, "Failed to create video format converter", false);
879
880 base::win::ScopedComPtr<IMFAttributes> converter_attributes;
881 hr = video_format_converter_mft_->GetAttributes(
882 converter_attributes.Receive());
883 RETURN_ON_HR_FAILURE(hr, "Failed to get converter attributes", false);
884
885 hr = converter_attributes->SetUINT32(MF_XVP_PLAYBACK_MODE, TRUE);
886 RETURN_ON_HR_FAILURE(
887 hr, "Failed to set MF_XVP_PLAYBACK_MODE attribute on converter", false);
888
889 hr = converter_attributes->SetUINT32(MF_LOW_LATENCY, FALSE);
890 RETURN_ON_HR_FAILURE(
891 hr, "Failed to set MF_LOW_LATENCY attribute on converter", false);
892 return true; 876 return true;
893 } 877 }
894 878
895 void DXVAVideoDecodeAccelerator::Decode( 879 void DXVAVideoDecodeAccelerator::Decode(
896 const BitstreamBuffer& bitstream_buffer) { 880 const BitstreamBuffer& bitstream_buffer) {
897 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::Decode"); 881 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::Decode");
898 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); 882 DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
899 883
900 // SharedMemory will take over the ownership of handle. 884 // SharedMemory will take over the ownership of handle.
901 base::SharedMemory shm(bitstream_buffer.handle(), true); 885 base::SharedMemory shm(bitstream_buffer.handle(), true);
(...skipping 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after
1960 // resolution changes. We already handle that in the 1944 // resolution changes. We already handle that in the
1961 // HandleResolutionChanged() function. 1945 // HandleResolutionChanged() function.
1962 if (GetState() != kConfigChange) { 1946 if (GetState() != kConfigChange) {
1963 output_picture_buffers_.clear(); 1947 output_picture_buffers_.clear();
1964 stale_output_picture_buffers_.clear(); 1948 stale_output_picture_buffers_.clear();
1965 // We want to continue processing pending input after detecting a config 1949 // We want to continue processing pending input after detecting a config
1966 // change. 1950 // change.
1967 pending_input_buffers_.clear(); 1951 pending_input_buffers_.clear();
1968 pictures_requested_ = false; 1952 pictures_requested_ = false;
1969 if (use_dx11_) { 1953 if (use_dx11_) {
1970 if (video_format_converter_mft_.get()) { 1954 d3d11_processor_.Release();
1971 video_format_converter_mft_->ProcessMessage( 1955 enumerator_.Release();
1972 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); 1956 video_context_.Release();
1973 video_format_converter_mft_.Release(); 1957 video_device_.Release();
1974 }
1975 d3d11_device_context_.Release(); 1958 d3d11_device_context_.Release();
1976 d3d11_device_.Release(); 1959 d3d11_device_.Release();
1977 d3d11_device_manager_.Release(); 1960 d3d11_device_manager_.Release();
1978 d3d11_query_.Release(); 1961 d3d11_query_.Release();
1979 multi_threaded_.Release(); 1962 multi_threaded_.Release();
1980 dx11_video_format_converter_media_type_needs_init_ = true; 1963 processor_width_ = processor_height_ = 0;
1981 } else { 1964 } else {
1982 d3d9_.Release(); 1965 d3d9_.Release();
1983 d3d9_device_ex_.Release(); 1966 d3d9_device_ex_.Release();
1984 device_manager_.Release(); 1967 device_manager_.Release();
1985 query_.Release(); 1968 query_.Release();
1986 } 1969 }
1987 } 1970 }
1988 sent_drain_message_ = false; 1971 sent_drain_message_ = false;
1989 SetState(kUninitialized); 1972 SetState(kUninitialized);
1990 } 1973 }
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
2271 // decoder to emit an output packet for every input packet. 2254 // decoder to emit an output packet for every input packet.
2272 // http://code.google.com/p/chromium/issues/detail?id=108121 2255 // http://code.google.com/p/chromium/issues/detail?id=108121
2273 // http://code.google.com/p/chromium/issues/detail?id=150925 2256 // http://code.google.com/p/chromium/issues/detail?id=150925
2274 main_thread_task_runner_->PostTask( 2257 main_thread_task_runner_->PostTask(
2275 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::NotifyInputBufferRead, 2258 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::NotifyInputBufferRead,
2276 weak_ptr_, input_buffer_id)); 2259 weak_ptr_, input_buffer_id));
2277 } 2260 }
2278 2261
2279 void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width, 2262 void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width,
2280 int height) { 2263 int height) {
2281 dx11_video_format_converter_media_type_needs_init_ = true;
2282
2283 main_thread_task_runner_->PostTask( 2264 main_thread_task_runner_->PostTask(
2284 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::DismissStaleBuffers, 2265 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::DismissStaleBuffers,
2285 weak_ptr_, false)); 2266 weak_ptr_, false));
2286 2267
2287 main_thread_task_runner_->PostTask( 2268 main_thread_task_runner_->PostTask(
2288 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::RequestPictureBuffers, 2269 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::RequestPictureBuffers,
2289 weak_ptr_, width, height)); 2270 weak_ptr_, width, height));
2290 } 2271 }
2291 2272
2292 void DXVAVideoDecodeAccelerator::DismissStaleBuffers(bool force) { 2273 void DXVAVideoDecodeAccelerator::DismissStaleBuffers(bool force) {
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
2562 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopyTexture"); 2543 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopyTexture");
2563 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); 2544 DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
2564 2545
2565 DCHECK(use_dx11_); 2546 DCHECK(use_dx11_);
2566 2547
2567 // The media foundation H.264 decoder outputs YUV12 textures which we 2548 // The media foundation H.264 decoder outputs YUV12 textures which we
2568 // cannot copy into ANGLE as they expect ARGB textures. In D3D land 2549 // cannot copy into ANGLE as they expect ARGB textures. In D3D land
2569 // the StretchRect API in the IDirect3DDevice9Ex interface did the color 2550 // the StretchRect API in the IDirect3DDevice9Ex interface did the color
2570 // space conversion for us. Sadly in DX11 land the API does not provide 2551 // space conversion for us. Sadly in DX11 land the API does not provide
2571 // a straightforward way to do this. 2552 // a straightforward way to do this.
2572 // We use the video processor MFT.
2573 // https://msdn.microsoft.com/en-us/library/hh162913(v=vs.85).aspx
2574 // This object implements a media foundation transform (IMFTransform)
2575 // which follows the same contract as the decoder. The color space
2576 // conversion as per msdn is done in the GPU.
2577 2553
2578 D3D11_TEXTURE2D_DESC source_desc; 2554 D3D11_TEXTURE2D_DESC source_desc;
2579 src_texture->GetDesc(&source_desc); 2555 src_texture->GetDesc(&source_desc);
2580 2556 if (!InitializeID3D11VideoProcessor(source_desc.Width, source_desc.Height,
2581 // Set up the input and output types for the video processor MFT. 2557 color_space)) {
2582 if (!InitializeDX11VideoFormatConverterMediaType( 2558 RETURN_AND_NOTIFY_ON_FAILURE(false,
2583 source_desc.Width, source_desc.Height, color_space)) { 2559 "Failed to initialize D3D11 video processor.",
2584 RETURN_AND_NOTIFY_ON_FAILURE( 2560 PLATFORM_FAILURE, );
2585 false, "Failed to initialize media types for convesion.",
2586 PLATFORM_FAILURE, );
2587 } 2561 }
2588 2562
2589 // The input to the video processor is the output sample. 2563 // The input to the video processor is the output sample.
2590 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; 2564 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion;
2591 { 2565 {
2592 base::AutoLock lock(decoder_lock_); 2566 base::AutoLock lock(decoder_lock_);
2593 PendingSampleInfo& sample_info = pending_output_samples_.front(); 2567 PendingSampleInfo& sample_info = pending_output_samples_.front();
2594 input_sample_for_conversion = sample_info.output_sample; 2568 input_sample_for_conversion = sample_info.output_sample;
2595 } 2569 }
2596 2570
(...skipping 12 matching lines...) Expand all
2609 base::win::ScopedComPtr<IMFSample> input_sample, 2583 base::win::ScopedComPtr<IMFSample> input_sample,
2610 int picture_buffer_id, 2584 int picture_buffer_id,
2611 int input_buffer_id) { 2585 int input_buffer_id) {
2612 TRACE_EVENT0("media", 2586 TRACE_EVENT0("media",
2613 "DXVAVideoDecodeAccelerator::CopyTextureOnDecoderThread"); 2587 "DXVAVideoDecodeAccelerator::CopyTextureOnDecoderThread");
2614 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 2588 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2615 HRESULT hr = E_FAIL; 2589 HRESULT hr = E_FAIL;
2616 2590
2617 DCHECK(use_dx11_); 2591 DCHECK(use_dx11_);
2618 DCHECK(!!input_sample); 2592 DCHECK(!!input_sample);
2619 DCHECK(video_format_converter_mft_.get()); 2593 DCHECK(d3d11_processor_.get());
2620 2594
2621 if (dest_keyed_mutex) { 2595 if (dest_keyed_mutex) {
2622 HRESULT hr = 2596 HRESULT hr =
2623 dest_keyed_mutex->AcquireSync(keyed_mutex_value, kAcquireSyncWaitMs); 2597 dest_keyed_mutex->AcquireSync(keyed_mutex_value, kAcquireSyncWaitMs);
2624 RETURN_AND_NOTIFY_ON_FAILURE( 2598 RETURN_AND_NOTIFY_ON_FAILURE(
2625 hr == S_OK, "D3D11 failed to acquire keyed mutex for texture.", 2599 hr == S_OK, "D3D11 failed to acquire keyed mutex for texture.",
2626 PLATFORM_FAILURE, ); 2600 PLATFORM_FAILURE, );
2627 } 2601 }
2628 // The video processor MFT requires output samples to be allocated by the
2629 // caller. We create a sample with a buffer backed with the ID3D11Texture2D
2630 // interface exposed by ANGLE. This works nicely as this ensures that the
2631 // video processor coverts the color space of the output frame and copies
2632 // the result into the ANGLE texture.
2633 base::win::ScopedComPtr<IMFSample> output_sample;
2634 hr = MFCreateSample(output_sample.Receive());
2635 if (FAILED(hr)) {
2636 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to create output sample.",
2637 PLATFORM_FAILURE, );
2638 }
2639 2602
2640 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; 2603 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer;
2641 hr = MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), dest_texture, 0, 2604 hr = input_sample->GetBufferByIndex(0, output_buffer.Receive());
2642 FALSE, output_buffer.Receive()); 2605 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get buffer from output sample",
2643 if (FAILED(hr)) { 2606 PLATFORM_FAILURE, );
2644 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to create output sample.",
2645 PLATFORM_FAILURE, );
2646 }
2647 2607
2648 output_sample->AddBuffer(output_buffer.get()); 2608 base::win::ScopedComPtr<IMFDXGIBuffer> dxgi_buffer;
2609 hr = dxgi_buffer.QueryFrom(output_buffer.get());
2610 RETURN_AND_NOTIFY_ON_HR_FAILURE(
2611 hr, "Failed to get DXGIBuffer from output sample", PLATFORM_FAILURE, );
2612 UINT index = 0;
2613 hr = dxgi_buffer->GetSubresourceIndex(&index);
2614 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get resource index",
2615 PLATFORM_FAILURE, );
2649 2616
2650 hr = video_format_converter_mft_->ProcessInput(0, input_sample.get(), 0); 2617 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture;
2651 if (FAILED(hr)) { 2618 hr = dxgi_buffer->GetResource(IID_PPV_ARGS(dx11_decoding_texture.Receive()));
2652 DCHECK(false); 2619 RETURN_AND_NOTIFY_ON_HR_FAILURE(
2653 RETURN_AND_NOTIFY_ON_HR_FAILURE( 2620 hr, "Failed to get resource from output sample", PLATFORM_FAILURE, );
2654 hr, "Failed to convert output sample format.", PLATFORM_FAILURE, );
2655 }
2656 2621
2657 input_sample.Release(); 2622 D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC output_view_desc = {
2623 D3D11_VPOV_DIMENSION_TEXTURE2D};
2624 output_view_desc.Texture2D.MipSlice = 0;
2625 base::win::ScopedComPtr<ID3D11VideoProcessorOutputView> output_view;
2626 hr = video_device_->CreateVideoProcessorOutputView(
2627 dest_texture, enumerator_.get(), &output_view_desc,
2628 output_view.Receive());
2629 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get output view",
2630 PLATFORM_FAILURE, );
2658 2631
2659 DWORD status = 0; 2632 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC input_view_desc = {0};
2660 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; 2633 input_view_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
2661 format_converter_output.pSample = output_sample.get(); 2634 input_view_desc.Texture2D.ArraySlice = index;
2662 hr = video_format_converter_mft_->ProcessOutput( 2635 input_view_desc.Texture2D.MipSlice = 0;
2663 0, // No flags 2636 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> input_view;
2664 1, // # of out streams to pull from 2637 hr = video_device_->CreateVideoProcessorInputView(
2665 &format_converter_output, &status); 2638 dx11_decoding_texture.get(), enumerator_.get(), &input_view_desc,
2639 input_view.Receive());
2640 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get input view",
2641 PLATFORM_FAILURE, );
2666 2642
2667 if (FAILED(hr)) { 2643 D3D11_VIDEO_PROCESSOR_STREAM streams = {0};
2668 DCHECK(false); 2644 streams.Enable = TRUE;
2669 RETURN_AND_NOTIFY_ON_HR_FAILURE( 2645 streams.pInputSurface = input_view.get();
2670 hr, "Failed to convert output sample format.", PLATFORM_FAILURE, ); 2646
2671 } 2647 hr = video_context_->VideoProcessorBlt(d3d11_processor_.get(),
2648 output_view.get(), 0, 1, &streams);
2649
2650 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "VideoProcessBlit failed",
2651 PLATFORM_FAILURE, );
2672 2652
2673 if (dest_keyed_mutex) { 2653 if (dest_keyed_mutex) {
2674 HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1); 2654 HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1);
2675 RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.", 2655 RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.",
2676 PLATFORM_FAILURE, ); 2656 PLATFORM_FAILURE, );
2677 2657
2678 main_thread_task_runner_->PostTask( 2658 main_thread_task_runner_->PostTask(
2679 FROM_HERE, 2659 FROM_HERE,
2680 base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, weak_ptr_, 2660 base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, weak_ptr_,
2681 nullptr, nullptr, picture_buffer_id, input_buffer_id)); 2661 nullptr, nullptr, picture_buffer_id, input_buffer_id));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2734 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); 2714 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
2735 return; 2715 return;
2736 } 2716 }
2737 2717
2738 main_thread_task_runner_->PostTask( 2718 main_thread_task_runner_->PostTask(
2739 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, 2719 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
2740 weak_ptr_, src_surface, dest_surface, 2720 weak_ptr_, src_surface, dest_surface,
2741 picture_buffer_id, input_buffer_id)); 2721 picture_buffer_id, input_buffer_id));
2742 } 2722 }
2743 2723
2744 bool DXVAVideoDecodeAccelerator::InitializeDX11VideoFormatConverterMediaType( 2724 bool DXVAVideoDecodeAccelerator::InitializeID3D11VideoProcessor(
2745 int width, 2725 int width,
2746 int height, 2726 int height,
2747 const gfx::ColorSpace& color_space) { 2727 const gfx::ColorSpace& color_space) {
2748 if (!dx11_video_format_converter_media_type_needs_init_ && 2728 if (width < processor_width_ || height != processor_height_) {
2749 (!use_color_info_ || color_space == dx11_converter_color_space_)) { 2729 d3d11_processor_.Release();
2750 return true; 2730 enumerator_.Release();
2731 processor_width_ = 0;
2732 processor_height_ = 0;
2733
2734 D3D11_VIDEO_PROCESSOR_CONTENT_DESC desc;
2735 desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
2736 desc.InputFrameRate.Numerator = 60;
2737 desc.InputFrameRate.Denominator = 1;
2738 desc.InputWidth = width;
2739 desc.InputHeight = height;
2740 desc.OutputFrameRate.Numerator = 60;
2741 desc.OutputFrameRate.Denominator = 1;
2742 desc.OutputWidth = width;
2743 desc.OutputHeight = height;
2744 desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
2745
2746 HRESULT hr = video_device_->CreateVideoProcessorEnumerator(
2747 &desc, enumerator_.Receive());
2748 RETURN_ON_HR_FAILURE(hr, "Failed to enumerate video processors", false);
2749
2750 // TODO(Hubbe): Find correct index
2751 hr = video_device_->CreateVideoProcessor(enumerator_.get(), 0,
2752 d3d11_processor_.Receive());
2753 RETURN_ON_HR_FAILURE(hr, "Failed to create video processor.", false);
2754 processor_width_ = width;
2755 processor_height_ = height;
2756
2757 video_context_->VideoProcessorSetStreamAutoProcessingMode(
2758 d3d11_processor_.get(), 0, false);
2751 } 2759 }
2752 2760
2753 CHECK(video_format_converter_mft_.get()); 2761 if (copy_nv12_textures_) {
2762 // If we're copying NV12 textures, make sure we set the same
2763 // color space on input and output.
2764 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = {0};
2765 d3d11_color_space.RGB_Range = 1;
2766 d3d11_color_space.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255;
2754 2767
2755 HRESULT hr = video_format_converter_mft_->ProcessMessage( 2768 video_context_->VideoProcessorSetOutputColorSpace(d3d11_processor_.get(),
2756 MFT_MESSAGE_SET_D3D_MANAGER, 2769 &d3d11_color_space);
2757 reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.get()));
2758 2770
2759 if (FAILED(hr)) 2771 video_context_->VideoProcessorSetStreamColorSpace(d3d11_processor_.get(), 0,
2760 DCHECK(false); 2772 &d3d11_color_space);
2761 2773 } else {
2762 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2774 // Not sure if this call is expensive, let's only do it if the color
2763 "Failed to initialize video format converter", 2775 // space changes.
2764 PLATFORM_FAILURE, false); 2776 gfx::ColorSpace output_color_space = gfx::ColorSpace::CreateSRGB();
2765 2777 if (use_color_info_ && dx11_converter_color_space_ != color_space) {
2766 video_format_converter_mft_->ProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 2778 base::win::ScopedComPtr<ID3D11VideoContext1> video_context1;
2767 0); 2779 HRESULT hr = video_context_.QueryInterface(video_context1.Receive());
2768 2780 if (SUCCEEDED(hr)) {
2769 base::win::ScopedComPtr<IMFMediaType> media_type; 2781 video_context1->VideoProcessorSetStreamColorSpace1(
2770 hr = MFCreateMediaType(media_type.Receive()); 2782 d3d11_processor_.get(), 0,
2771 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "MFCreateMediaType failed", 2783 gfx::ColorSpaceWin::GetDXGIColorSpace(color_space));
2772 PLATFORM_FAILURE, false); 2784 video_context1->VideoProcessorSetOutputColorSpace1(
2773 2785 d3d11_processor_.get(),
2774 hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); 2786 gfx::ColorSpaceWin::GetDXGIColorSpace(output_color_space));
2775 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set major input type", 2787 } else {
2776 PLATFORM_FAILURE, false); 2788 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space =
2777 2789 gfx::ColorSpaceWin::GetD3D11ColorSpace(color_space);
2778 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); 2790 video_context_->VideoProcessorSetStreamColorSpace(
2779 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", 2791 d3d11_processor_.get(), 0, &d3d11_color_space);
2780 PLATFORM_FAILURE, false); 2792 d3d11_color_space =
2781 2793 gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space);
2782 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); 2794 video_context_->VideoProcessorSetOutputColorSpace(
2783 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", 2795 d3d11_processor_.get(), &d3d11_color_space);
2784 PLATFORM_FAILURE, false); 2796 }
2785 2797 dx11_converter_color_space_ = color_space;
2786 if (use_color_info_) { 2798 }
2787 DXVA2_ExtendedFormat format =
2788 gfx::ColorSpaceWin::GetExtendedFormat(color_space);
2789 media_type->SetUINT32(MF_MT_YUV_MATRIX, format.VideoTransferMatrix);
2790 media_type->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, format.NominalRange);
2791 media_type->SetUINT32(MF_MT_VIDEO_PRIMARIES, format.VideoPrimaries);
2792 media_type->SetUINT32(MF_MT_TRANSFER_FUNCTION,
2793 format.VideoTransferFunction);
2794 dx11_converter_color_space_ = color_space;
2795 } 2799 }
2796
2797 hr = video_format_converter_mft_->SetInputType(0, media_type.get(), 0);
2798 if (FAILED(hr))
2799 DCHECK(false);
2800
2801 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type",
2802 PLATFORM_FAILURE, false);
2803
2804 // It appears that we fail to set MFVideoFormat_ARGB32 as the output media
2805 // type in certain configurations. Try to fallback to MFVideoFormat_RGB32
2806 // in such cases. If both fail, then bail.
2807
2808 bool media_type_set = false;
2809 if (copy_nv12_textures_) {
2810 media_type_set = SetTransformOutputType(video_format_converter_mft_.get(),
2811 MFVideoFormat_NV12, width, height);
2812 RETURN_AND_NOTIFY_ON_FAILURE(media_type_set,
2813 "Failed to set NV12 converter output type",
2814 PLATFORM_FAILURE, false);
2815 }
2816
2817 if (!media_type_set) {
2818 media_type_set = SetTransformOutputType(
2819 video_format_converter_mft_.get(), MFVideoFormat_ARGB32, width, height);
2820 }
2821 if (!media_type_set) {
2822 media_type_set = SetTransformOutputType(video_format_converter_mft_.get(),
2823 MFVideoFormat_RGB32, width, height);
2824 }
2825
2826 if (!media_type_set) {
2827 LOG(ERROR) << "Failed to find a matching RGB output type in the converter";
2828 return false;
2829 }
2830
2831 dx11_video_format_converter_media_type_needs_init_ = false;
2832 return true; 2800 return true;
2833 } 2801 }
2834 2802
2835 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions(IMFSample* sample, 2803 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions(IMFSample* sample,
2836 int* width, 2804 int* width,
2837 int* height) { 2805 int* height) {
2838 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; 2806 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer;
2839 HRESULT hr = sample->GetBufferByIndex(0, output_buffer.Receive()); 2807 HRESULT hr = sample->GetBufferByIndex(0, output_buffer.Receive());
2840 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false); 2808 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false);
2841 2809
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2930 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, 2898 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
2931 base::Unretained(this))); 2899 base::Unretained(this)));
2932 } 2900 }
2933 2901
2934 uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const { 2902 uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const {
2935 bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_; 2903 bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_;
2936 return provide_nv12_textures ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; 2904 return provide_nv12_textures ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
2937 } 2905 }
2938 2906
2939 } // namespace media 2907 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/dxva_video_decode_accelerator_win.h ('k') | ui/gfx/color_space_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698