| 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 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 hr = d3d11_device_->CreateQuery(&query_desc, d3d11_query_.Receive()); | 822 hr = d3d11_device_->CreateQuery(&query_desc, d3d11_query_.Receive()); |
| 823 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false); | 823 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false); |
| 824 | 824 |
| 825 HMODULE video_processor_dll = ::GetModuleHandle(L"msvproc.dll"); | 825 HMODULE video_processor_dll = ::GetModuleHandle(L"msvproc.dll"); |
| 826 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor", | 826 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor", |
| 827 false); | 827 false); |
| 828 | 828 |
| 829 hr = CreateCOMObjectFromDll(video_processor_dll, CLSID_VideoProcessorMFT, | 829 hr = CreateCOMObjectFromDll(video_processor_dll, CLSID_VideoProcessorMFT, |
| 830 __uuidof(IMFTransform), | 830 __uuidof(IMFTransform), |
| 831 video_format_converter_mft_.ReceiveVoid()); | 831 video_format_converter_mft_.ReceiveVoid()); |
| 832 if (FAILED(hr)) { | |
| 833 base::debug::Alias(&hr); | |
| 834 // TODO(ananta) | |
| 835 // Remove this CHECK when the change to use DX11 for H/W decoding | |
| 836 // stablizes. | |
| 837 CHECK(false); | |
| 838 } | |
| 839 | |
| 840 RETURN_ON_HR_FAILURE(hr, "Failed to create video format converter", false); | 832 RETURN_ON_HR_FAILURE(hr, "Failed to create video format converter", false); |
| 841 | 833 |
| 842 base::win::ScopedComPtr<IMFAttributes> converter_attributes; | 834 base::win::ScopedComPtr<IMFAttributes> converter_attributes; |
| 843 hr = video_format_converter_mft_->GetAttributes( | 835 hr = video_format_converter_mft_->GetAttributes( |
| 844 converter_attributes.Receive()); | 836 converter_attributes.Receive()); |
| 845 RETURN_ON_HR_FAILURE(hr, "Failed to get converter attributes", false); | 837 RETURN_ON_HR_FAILURE(hr, "Failed to get converter attributes", false); |
| 846 | 838 |
| 847 hr = converter_attributes->SetUINT32(MF_XVP_PLAYBACK_MODE, TRUE); | 839 hr = converter_attributes->SetUINT32(MF_XVP_PLAYBACK_MODE, TRUE); |
| 848 RETURN_ON_HR_FAILURE( | 840 RETURN_ON_HR_FAILURE( |
| 849 hr, "Failed to set MF_XVP_PLAYBACK_MODE attribute on converter", false); | 841 hr, "Failed to set MF_XVP_PLAYBACK_MODE attribute on converter", false); |
| (...skipping 1540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2390 hr = MFCreateSample(output_sample.Receive()); | 2382 hr = MFCreateSample(output_sample.Receive()); |
| 2391 if (FAILED(hr)) { | 2383 if (FAILED(hr)) { |
| 2392 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to create output sample.", | 2384 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to create output sample.", |
| 2393 PLATFORM_FAILURE, ); | 2385 PLATFORM_FAILURE, ); |
| 2394 } | 2386 } |
| 2395 | 2387 |
| 2396 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; | 2388 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; |
| 2397 hr = MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), dest_texture, 0, | 2389 hr = MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), dest_texture, 0, |
| 2398 FALSE, output_buffer.Receive()); | 2390 FALSE, output_buffer.Receive()); |
| 2399 if (FAILED(hr)) { | 2391 if (FAILED(hr)) { |
| 2400 base::debug::Alias(&hr); | |
| 2401 // TODO(ananta) | |
| 2402 // Remove this CHECK when the change to use DX11 for H/W decoding | |
| 2403 // stablizes. | |
| 2404 CHECK(false); | |
| 2405 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to create output sample.", | 2392 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to create output sample.", |
| 2406 PLATFORM_FAILURE, ); | 2393 PLATFORM_FAILURE, ); |
| 2407 } | 2394 } |
| 2408 | 2395 |
| 2409 output_sample->AddBuffer(output_buffer.get()); | 2396 output_sample->AddBuffer(output_buffer.get()); |
| 2410 | 2397 |
| 2411 hr = video_format_converter_mft_->ProcessInput(0, video_frame, 0); | 2398 hr = video_format_converter_mft_->ProcessInput(0, video_frame, 0); |
| 2412 if (FAILED(hr)) { | 2399 if (FAILED(hr)) { |
| 2413 DCHECK(false); | 2400 DCHECK(false); |
| 2414 RETURN_AND_NOTIFY_ON_HR_FAILURE( | 2401 RETURN_AND_NOTIFY_ON_HR_FAILURE( |
| 2415 hr, "Failed to convert output sample format.", PLATFORM_FAILURE, ); | 2402 hr, "Failed to convert output sample format.", PLATFORM_FAILURE, ); |
| 2416 } | 2403 } |
| 2417 | 2404 |
| 2418 DWORD status = 0; | 2405 DWORD status = 0; |
| 2419 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; | 2406 MFT_OUTPUT_DATA_BUFFER format_converter_output = {}; |
| 2420 format_converter_output.pSample = output_sample.get(); | 2407 format_converter_output.pSample = output_sample.get(); |
| 2421 hr = video_format_converter_mft_->ProcessOutput( | 2408 hr = video_format_converter_mft_->ProcessOutput( |
| 2422 0, // No flags | 2409 0, // No flags |
| 2423 1, // # of out streams to pull from | 2410 1, // # of out streams to pull from |
| 2424 &format_converter_output, &status); | 2411 &format_converter_output, &status); |
| 2425 | 2412 |
| 2426 if (FAILED(hr)) { | 2413 if (FAILED(hr)) { |
| 2427 base::debug::Alias(&hr); | 2414 DCHECK(false); |
| 2428 // TODO(ananta) | |
| 2429 // Remove this CHECK when the change to use DX11 for H/W decoding | |
| 2430 // stablizes. | |
| 2431 CHECK(false); | |
| 2432 RETURN_AND_NOTIFY_ON_HR_FAILURE( | 2415 RETURN_AND_NOTIFY_ON_HR_FAILURE( |
| 2433 hr, "Failed to convert output sample format.", PLATFORM_FAILURE, ); | 2416 hr, "Failed to convert output sample format.", PLATFORM_FAILURE, ); |
| 2434 } | 2417 } |
| 2435 | 2418 |
| 2436 if (dest_keyed_mutex) { | 2419 if (dest_keyed_mutex) { |
| 2437 HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1); | 2420 HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1); |
| 2438 RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.", | 2421 RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.", |
| 2439 PLATFORM_FAILURE, ); | 2422 PLATFORM_FAILURE, ); |
| 2440 | 2423 |
| 2441 main_thread_task_runner_->PostTask( | 2424 main_thread_task_runner_->PostTask( |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2476 // return success occassionally on multi core machines, leading to an | 2459 // return success occassionally on multi core machines, leading to an |
| 2477 // infinite loop. | 2460 // infinite loop. |
| 2478 // Workaround is to have an upper limit of 4 on the number of iterations to | 2461 // Workaround is to have an upper limit of 4 on the number of iterations to |
| 2479 // wait for the Flush to finish. | 2462 // wait for the Flush to finish. |
| 2480 | 2463 |
| 2481 HRESULT hr = E_FAIL; | 2464 HRESULT hr = E_FAIL; |
| 2482 if (use_dx11_) { | 2465 if (use_dx11_) { |
| 2483 BOOL query_data = 0; | 2466 BOOL query_data = 0; |
| 2484 hr = d3d11_device_context_->GetData(d3d11_query_.get(), &query_data, | 2467 hr = d3d11_device_context_->GetData(d3d11_query_.get(), &query_data, |
| 2485 sizeof(BOOL), 0); | 2468 sizeof(BOOL), 0); |
| 2486 if (FAILED(hr)) { | 2469 if (FAILED(hr)) |
| 2487 base::debug::Alias(&hr); | 2470 DCHECK(false); |
| 2488 // TODO(ananta) | |
| 2489 // Remove this CHECK when the change to use DX11 for H/W decoding | |
| 2490 // stablizes. | |
| 2491 CHECK(false); | |
| 2492 } | |
| 2493 } else { | 2471 } else { |
| 2494 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH); | 2472 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH); |
| 2495 } | 2473 } |
| 2496 | 2474 |
| 2497 if ((hr == S_FALSE) && (++iterations < kMaxIterationsForD3DFlush)) { | 2475 if ((hr == S_FALSE) && (++iterations < kMaxIterationsForD3DFlush)) { |
| 2498 decoder_thread_task_runner_->PostDelayedTask( | 2476 decoder_thread_task_runner_->PostDelayedTask( |
| 2499 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, | 2477 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, |
| 2500 base::Unretained(this), iterations, src_surface, | 2478 base::Unretained(this), iterations, src_surface, |
| 2501 dest_surface, picture_buffer_id, input_buffer_id), | 2479 dest_surface, picture_buffer_id, input_buffer_id), |
| 2502 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); | 2480 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2514 int height) { | 2492 int height) { |
| 2515 if (!dx11_video_format_converter_media_type_needs_init_) | 2493 if (!dx11_video_format_converter_media_type_needs_init_) |
| 2516 return true; | 2494 return true; |
| 2517 | 2495 |
| 2518 CHECK(video_format_converter_mft_.get()); | 2496 CHECK(video_format_converter_mft_.get()); |
| 2519 | 2497 |
| 2520 HRESULT hr = video_format_converter_mft_->ProcessMessage( | 2498 HRESULT hr = video_format_converter_mft_->ProcessMessage( |
| 2521 MFT_MESSAGE_SET_D3D_MANAGER, | 2499 MFT_MESSAGE_SET_D3D_MANAGER, |
| 2522 reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.get())); | 2500 reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.get())); |
| 2523 | 2501 |
| 2524 if (FAILED(hr)) { | 2502 if (FAILED(hr)) |
| 2525 base::debug::Alias(&hr); | 2503 DCHECK(false); |
| 2526 // TODO(ananta) | 2504 |
| 2527 // Remove this CHECK when the change to use DX11 for H/W decoding | |
| 2528 // stablizes. | |
| 2529 CHECK(false); | |
| 2530 } | |
| 2531 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2505 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
| 2532 "Failed to initialize video format converter", | 2506 "Failed to initialize video format converter", |
| 2533 PLATFORM_FAILURE, false); | 2507 PLATFORM_FAILURE, false); |
| 2534 | 2508 |
| 2535 video_format_converter_mft_->ProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, | 2509 video_format_converter_mft_->ProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, |
| 2536 0); | 2510 0); |
| 2537 | 2511 |
| 2538 base::win::ScopedComPtr<IMFMediaType> media_type; | 2512 base::win::ScopedComPtr<IMFMediaType> media_type; |
| 2539 hr = MFCreateMediaType(media_type.Receive()); | 2513 hr = MFCreateMediaType(media_type.Receive()); |
| 2540 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "MFCreateMediaType failed", | 2514 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "MFCreateMediaType failed", |
| 2541 PLATFORM_FAILURE, false); | 2515 PLATFORM_FAILURE, false); |
| 2542 | 2516 |
| 2543 hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 2517 hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
| 2544 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set major input type", | 2518 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set major input type", |
| 2545 PLATFORM_FAILURE, false); | 2519 PLATFORM_FAILURE, false); |
| 2546 | 2520 |
| 2547 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); | 2521 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); |
| 2548 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", | 2522 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", |
| 2549 PLATFORM_FAILURE, false); | 2523 PLATFORM_FAILURE, false); |
| 2550 | 2524 |
| 2551 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); | 2525 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); |
| 2552 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", | 2526 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", |
| 2553 PLATFORM_FAILURE, false); | 2527 PLATFORM_FAILURE, false); |
| 2554 | 2528 |
| 2555 hr = video_format_converter_mft_->SetInputType(0, media_type.get(), 0); | 2529 hr = video_format_converter_mft_->SetInputType(0, media_type.get(), 0); |
| 2556 if (FAILED(hr)) { | 2530 if (FAILED(hr)) |
| 2557 base::debug::Alias(&hr); | 2531 DCHECK(false); |
| 2558 // TODO(ananta) | 2532 |
| 2559 // Remove this CHECK when the change to use DX11 for H/W decoding | |
| 2560 // stablizes. | |
| 2561 CHECK(false); | |
| 2562 } | |
| 2563 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type", | 2533 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type", |
| 2564 PLATFORM_FAILURE, false); | 2534 PLATFORM_FAILURE, false); |
| 2565 | 2535 |
| 2566 // It appears that we fail to set MFVideoFormat_ARGB32 as the output media | 2536 // It appears that we fail to set MFVideoFormat_ARGB32 as the output media |
| 2567 // type in certain configurations. Try to fallback to MFVideoFormat_RGB32 | 2537 // type in certain configurations. Try to fallback to MFVideoFormat_RGB32 |
| 2568 // in such cases. If both fail, then bail. | 2538 // in such cases. If both fail, then bail. |
| 2569 bool media_type_set = SetTransformOutputType( | 2539 bool media_type_set = SetTransformOutputType( |
| 2570 video_format_converter_mft_.get(), MFVideoFormat_ARGB32, width, height); | 2540 video_format_converter_mft_.get(), MFVideoFormat_ARGB32, width, height); |
| 2571 if (!media_type_set) { | 2541 if (!media_type_set) { |
| 2572 media_type_set = SetTransformOutputType(video_format_converter_mft_.get(), | 2542 media_type_set = SetTransformOutputType(video_format_converter_mft_.get(), |
| 2573 MFVideoFormat_RGB32, width, height); | 2543 MFVideoFormat_RGB32, width, height); |
| 2574 } | 2544 } |
| 2575 | 2545 |
| 2576 if (!media_type_set) { | 2546 if (!media_type_set) { |
| 2577 // Remove this once this stabilizes in the field. | |
| 2578 CHECK(false); | |
| 2579 LOG(ERROR) << "Failed to find a matching RGB output type in the converter"; | 2547 LOG(ERROR) << "Failed to find a matching RGB output type in the converter"; |
| 2580 return false; | 2548 return false; |
| 2581 } | 2549 } |
| 2582 | 2550 |
| 2583 dx11_video_format_converter_media_type_needs_init_ = false; | 2551 dx11_video_format_converter_media_type_needs_init_ = false; |
| 2584 return true; | 2552 return true; |
| 2585 } | 2553 } |
| 2586 | 2554 |
| 2587 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions(IMFSample* sample, | 2555 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions(IMFSample* sample, |
| 2588 int* width, | 2556 int* width, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2677 DismissStaleBuffers(true); | 2645 DismissStaleBuffers(true); |
| 2678 Invalidate(); | 2646 Invalidate(); |
| 2679 Initialize(config_, client_); | 2647 Initialize(config_, client_); |
| 2680 decoder_thread_task_runner_->PostTask( | 2648 decoder_thread_task_runner_->PostTask( |
| 2681 FROM_HERE, | 2649 FROM_HERE, |
| 2682 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2650 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
| 2683 base::Unretained(this))); | 2651 base::Unretained(this))); |
| 2684 } | 2652 } |
| 2685 | 2653 |
| 2686 } // namespace media | 2654 } // namespace media |
| OLD | NEW |