Index: content/common/gpu/media/dxva_video_decode_accelerator_win.cc |
diff --git a/content/common/gpu/media/dxva_video_decode_accelerator_win.cc b/content/common/gpu/media/dxva_video_decode_accelerator_win.cc |
index 21bdb8b2e11d9b0962c0dfb3198b76673d4b1168..40a3239cb2581f977a6cbb5a58df23ff176ad0f0 100644 |
--- a/content/common/gpu/media/dxva_video_decode_accelerator_win.cc |
+++ b/content/common/gpu/media/dxva_video_decode_accelerator_win.cc |
@@ -859,6 +859,23 @@ bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
} |
RETURN_ON_HR_FAILURE(hr, "Failed to create video format converter", false); |
+ |
+ base::win::ScopedComPtr<IMFAttributes> converter_attributes; |
+ hr = video_format_converter_mft_->GetAttributes( |
+ converter_attributes.Receive()); |
+ RETURN_ON_HR_FAILURE(hr, "Failed to get converter attributes", false); |
+ |
+ hr = converter_attributes->SetUINT32(MF_XVP_PLAYBACK_MODE, TRUE); |
+ RETURN_ON_HR_FAILURE( |
+ hr, |
+ "Failed to set MF_XVP_PLAYBACK_MODE attribute on converter", |
+ false); |
+ |
+ hr = converter_attributes->SetUINT32(MF_LOW_LATENCY, FALSE); |
+ RETURN_ON_HR_FAILURE( |
+ hr, |
+ "Failed to set MF_LOW_LATENCY attribute on converter", |
+ false); |
return true; |
} |
@@ -1268,23 +1285,7 @@ bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() { |
bool DXVAVideoDecodeAccelerator::SetDecoderOutputMediaType( |
const GUID& subtype) { |
- base::win::ScopedComPtr<IMFMediaType> out_media_type; |
- |
- for (uint32_t i = 0; SUCCEEDED( |
- decoder_->GetOutputAvailableType(0, i, out_media_type.Receive())); |
- ++i) { |
- GUID out_subtype = {0}; |
- HRESULT hr = out_media_type->GetGUID(MF_MT_SUBTYPE, &out_subtype); |
- RETURN_ON_HR_FAILURE(hr, "Failed to get output major type", false); |
- |
- if (out_subtype == subtype) { |
- hr = decoder_->SetOutputType(0, out_media_type.get(), 0); // No flags |
- RETURN_ON_HR_FAILURE(hr, "Failed to set decoder output type", false); |
- return true; |
- } |
- out_media_type.Release(); |
- } |
- return false; |
+ return SetTransformOutputType(decoder_.get(), subtype, 0, 0); |
} |
bool DXVAVideoDecodeAccelerator::SendMFTMessage(MFT_MESSAGE_TYPE msg, |
@@ -2186,29 +2187,6 @@ bool DXVAVideoDecodeAccelerator::InitializeDX11VideoFormatConverterMediaType( |
RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", |
PLATFORM_FAILURE, false); |
- hr = media_type->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
- "Failed to set attributes on media type", PLATFORM_FAILURE, false); |
- |
- hr = media_type->SetUINT32(MF_MT_INTERLACE_MODE, |
- MFVideoInterlace_Progressive); |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
- "Failed to set attributes on media type", PLATFORM_FAILURE, false); |
- |
- base::win::ScopedComPtr<IMFAttributes> converter_attributes; |
- hr = video_format_converter_mft_->GetAttributes( |
- converter_attributes.Receive()); |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get converter attributes", |
- PLATFORM_FAILURE, false); |
- |
- hr = converter_attributes->SetUINT32(MF_XVP_PLAYBACK_MODE, TRUE); |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter attributes", |
- PLATFORM_FAILURE, false); |
- |
- hr = converter_attributes->SetUINT32(MF_LOW_LATENCY, FALSE); |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter attributes", |
- PLATFORM_FAILURE, false); |
- |
hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); |
RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", |
PLATFORM_FAILURE, false); |
@@ -2224,50 +2202,31 @@ bool DXVAVideoDecodeAccelerator::InitializeDX11VideoFormatConverterMediaType( |
RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type", |
PLATFORM_FAILURE, false); |
- base::win::ScopedComPtr<IMFMediaType> out_media_type; |
- |
- for (uint32_t i = 0; |
- SUCCEEDED(video_format_converter_mft_->GetOutputAvailableType( |
- 0, i, out_media_type.Receive())); |
- ++i) { |
- GUID out_subtype = {0}; |
- hr = out_media_type->GetGUID(MF_MT_SUBTYPE, &out_subtype); |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get output major type", |
- PLATFORM_FAILURE, false); |
- |
- if (out_subtype == MFVideoFormat_ARGB32) { |
- hr = out_media_type->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
- "Failed to set attributes on media type", PLATFORM_FAILURE, false); |
- |
- hr = out_media_type->SetUINT32(MF_MT_INTERLACE_MODE, |
- MFVideoInterlace_Progressive); |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
- "Failed to set attributes on media type", PLATFORM_FAILURE, false); |
- |
- hr = MFSetAttributeSize(out_media_type.get(), MF_MT_FRAME_SIZE, width, |
- height); |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
- "Failed to set media type attributes", PLATFORM_FAILURE, false); |
- |
- hr = video_format_converter_mft_->SetOutputType( |
- 0, out_media_type.get(), 0); // No flags |
- if (FAILED(hr)) { |
- base::debug::Alias(&hr); |
- // TODO(ananta) |
- // Remove this CHECK when the change to use DX11 for H/W decoding |
- // stablizes. |
- CHECK(false); |
- } |
- RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
- "Failed to set converter output type", PLATFORM_FAILURE, false); |
- |
- dx11_video_format_converter_media_type_needs_init_ = false; |
- return true; |
- } |
- out_media_type.Release(); |
+ // It appears that we fail to set MFVideoFormat_ARGB32 as the output media |
+ // type in certain configurations. Try to fallback to MFVideoFormat_RGB32 |
+ // in such cases. If both fail, then bail. |
+ bool media_type_set = |
+ SetTransformOutputType(video_format_converter_mft_.get(), |
+ MFVideoFormat_ARGB32, |
+ width, |
+ height); |
+ if (!media_type_set) { |
+ media_type_set = |
+ SetTransformOutputType(video_format_converter_mft_.get(), |
+ MFVideoFormat_RGB32, |
+ width, |
+ height); |
+ } |
+ |
+ if (!media_type_set) { |
+ // Remove this once this stabilizes in the field. |
+ CHECK(false); |
+ LOG(ERROR) << "Failed to find a matching RGB output type in the converter"; |
+ return false; |
} |
- return false; |
+ |
+ dx11_video_format_converter_media_type_needs_init_ = false; |
+ return true; |
} |
bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions( |
@@ -2308,4 +2267,41 @@ bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions( |
return true; |
} |
+bool DXVAVideoDecodeAccelerator::SetTransformOutputType( |
+ IMFTransform* transform, |
+ const GUID& output_type, |
+ int width, |
+ int height) { |
+ HRESULT hr = E_FAIL; |
+ base::win::ScopedComPtr<IMFMediaType> media_type; |
+ |
+ for (uint32_t i = 0; |
+ SUCCEEDED(transform->GetOutputAvailableType( |
+ 0, i, media_type.Receive())); |
+ ++i) { |
+ GUID out_subtype = {0}; |
+ hr = media_type->GetGUID(MF_MT_SUBTYPE, &out_subtype); |
+ RETURN_ON_HR_FAILURE(hr, "Failed to get output major type", false); |
+ |
+ if (out_subtype == output_type) { |
+ if (width && height) { |
+ hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, |
+ height); |
+ RETURN_ON_HR_FAILURE(hr, "Failed to set media type attributes", false); |
+ } |
+ hr = transform->SetOutputType(0, media_type.get(), 0); // No flags |
+ if (FAILED(hr)) { |
+ base::debug::Alias(&hr); |
+ // TODO(ananta) |
+ // Remove this CHECK when this stabilizes in the field. |
+ CHECK(false); |
+ } |
+ RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); |
+ return true; |
+ } |
+ media_type.Release(); |
+ } |
+ return false; |
+} |
+ |
} // namespace content |