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 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |