| 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 "content/common/gpu/media/dxva_video_decode_accelerator_win.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator_win.h" |
| 6 | 6 |
| 7 #if !defined(OS_WIN) | 7 #if !defined(OS_WIN) |
| 8 #error This file should only be built on Windows. | 8 #error This file should only be built on Windows. |
| 9 #endif // !defined(OS_WIN) | 9 #endif // !defined(OS_WIN) |
| 10 | 10 |
| (...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 video_format_converter_mft_.ReceiveVoid()); | 852 video_format_converter_mft_.ReceiveVoid()); |
| 853 if (FAILED(hr)) { | 853 if (FAILED(hr)) { |
| 854 base::debug::Alias(&hr); | 854 base::debug::Alias(&hr); |
| 855 // TODO(ananta) | 855 // TODO(ananta) |
| 856 // Remove this CHECK when the change to use DX11 for H/W decoding | 856 // Remove this CHECK when the change to use DX11 for H/W decoding |
| 857 // stablizes. | 857 // stablizes. |
| 858 CHECK(false); | 858 CHECK(false); |
| 859 } | 859 } |
| 860 | 860 |
| 861 RETURN_ON_HR_FAILURE(hr, "Failed to create video format converter", false); | 861 RETURN_ON_HR_FAILURE(hr, "Failed to create video format converter", false); |
| 862 |
| 863 base::win::ScopedComPtr<IMFAttributes> converter_attributes; |
| 864 hr = video_format_converter_mft_->GetAttributes( |
| 865 converter_attributes.Receive()); |
| 866 RETURN_ON_HR_FAILURE(hr, "Failed to get converter attributes", false); |
| 867 |
| 868 hr = converter_attributes->SetUINT32(MF_XVP_PLAYBACK_MODE, TRUE); |
| 869 RETURN_ON_HR_FAILURE( |
| 870 hr, |
| 871 "Failed to set MF_XVP_PLAYBACK_MODE attribute on converter", |
| 872 false); |
| 873 |
| 874 hr = converter_attributes->SetUINT32(MF_LOW_LATENCY, FALSE); |
| 875 RETURN_ON_HR_FAILURE( |
| 876 hr, |
| 877 "Failed to set MF_LOW_LATENCY attribute on converter", |
| 878 false); |
| 862 return true; | 879 return true; |
| 863 } | 880 } |
| 864 | 881 |
| 865 void DXVAVideoDecodeAccelerator::Decode( | 882 void DXVAVideoDecodeAccelerator::Decode( |
| 866 const media::BitstreamBuffer& bitstream_buffer) { | 883 const media::BitstreamBuffer& bitstream_buffer) { |
| 867 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 884 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
| 868 | 885 |
| 869 State state = GetState(); | 886 State state = GetState(); |
| 870 RETURN_AND_NOTIFY_ON_FAILURE((state == kNormal || state == kStopped || | 887 RETURN_AND_NOTIFY_ON_FAILURE((state == kNormal || state == kStopped || |
| 871 state == kFlushing), | 888 state == kFlushing), |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 MFVideoInterlace_MixedInterlaceOrProgressive); | 1278 MFVideoInterlace_MixedInterlaceOrProgressive); |
| 1262 RETURN_ON_HR_FAILURE(hr, "Failed to set interlace mode", false); | 1279 RETURN_ON_HR_FAILURE(hr, "Failed to set interlace mode", false); |
| 1263 | 1280 |
| 1264 hr = decoder_->SetInputType(0, media_type.get(), 0); // No flags | 1281 hr = decoder_->SetInputType(0, media_type.get(), 0); // No flags |
| 1265 RETURN_ON_HR_FAILURE(hr, "Failed to set decoder input type", false); | 1282 RETURN_ON_HR_FAILURE(hr, "Failed to set decoder input type", false); |
| 1266 return true; | 1283 return true; |
| 1267 } | 1284 } |
| 1268 | 1285 |
| 1269 bool DXVAVideoDecodeAccelerator::SetDecoderOutputMediaType( | 1286 bool DXVAVideoDecodeAccelerator::SetDecoderOutputMediaType( |
| 1270 const GUID& subtype) { | 1287 const GUID& subtype) { |
| 1271 base::win::ScopedComPtr<IMFMediaType> out_media_type; | 1288 return SetTransformOutputType(decoder_.get(), subtype, 0, 0); |
| 1272 | |
| 1273 for (uint32_t i = 0; SUCCEEDED( | |
| 1274 decoder_->GetOutputAvailableType(0, i, out_media_type.Receive())); | |
| 1275 ++i) { | |
| 1276 GUID out_subtype = {0}; | |
| 1277 HRESULT hr = out_media_type->GetGUID(MF_MT_SUBTYPE, &out_subtype); | |
| 1278 RETURN_ON_HR_FAILURE(hr, "Failed to get output major type", false); | |
| 1279 | |
| 1280 if (out_subtype == subtype) { | |
| 1281 hr = decoder_->SetOutputType(0, out_media_type.get(), 0); // No flags | |
| 1282 RETURN_ON_HR_FAILURE(hr, "Failed to set decoder output type", false); | |
| 1283 return true; | |
| 1284 } | |
| 1285 out_media_type.Release(); | |
| 1286 } | |
| 1287 return false; | |
| 1288 } | 1289 } |
| 1289 | 1290 |
| 1290 bool DXVAVideoDecodeAccelerator::SendMFTMessage(MFT_MESSAGE_TYPE msg, | 1291 bool DXVAVideoDecodeAccelerator::SendMFTMessage(MFT_MESSAGE_TYPE msg, |
| 1291 int32_t param) { | 1292 int32_t param) { |
| 1292 HRESULT hr = decoder_->ProcessMessage(msg, param); | 1293 HRESULT hr = decoder_->ProcessMessage(msg, param); |
| 1293 return SUCCEEDED(hr); | 1294 return SUCCEEDED(hr); |
| 1294 } | 1295 } |
| 1295 | 1296 |
| 1296 // Gets the minimum buffer sizes for input and output samples. The MFT will not | 1297 // Gets the minimum buffer sizes for input and output samples. The MFT will not |
| 1297 // allocate buffer for input nor output, so we have to do it ourselves and make | 1298 // allocate buffer for input nor output, so we have to do it ourselves and make |
| (...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2179 PLATFORM_FAILURE, false); | 2180 PLATFORM_FAILURE, false); |
| 2180 | 2181 |
| 2181 hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 2182 hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
| 2182 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set major input type", | 2183 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set major input type", |
| 2183 PLATFORM_FAILURE, false); | 2184 PLATFORM_FAILURE, false); |
| 2184 | 2185 |
| 2185 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); | 2186 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); |
| 2186 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", | 2187 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set input sub type", |
| 2187 PLATFORM_FAILURE, false); | 2188 PLATFORM_FAILURE, false); |
| 2188 | 2189 |
| 2189 hr = media_type->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); | |
| 2190 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | |
| 2191 "Failed to set attributes on media type", PLATFORM_FAILURE, false); | |
| 2192 | |
| 2193 hr = media_type->SetUINT32(MF_MT_INTERLACE_MODE, | |
| 2194 MFVideoInterlace_Progressive); | |
| 2195 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | |
| 2196 "Failed to set attributes on media type", PLATFORM_FAILURE, false); | |
| 2197 | |
| 2198 base::win::ScopedComPtr<IMFAttributes> converter_attributes; | |
| 2199 hr = video_format_converter_mft_->GetAttributes( | |
| 2200 converter_attributes.Receive()); | |
| 2201 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get converter attributes", | |
| 2202 PLATFORM_FAILURE, false); | |
| 2203 | |
| 2204 hr = converter_attributes->SetUINT32(MF_XVP_PLAYBACK_MODE, TRUE); | |
| 2205 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter attributes", | |
| 2206 PLATFORM_FAILURE, false); | |
| 2207 | |
| 2208 hr = converter_attributes->SetUINT32(MF_LOW_LATENCY, FALSE); | |
| 2209 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter attributes", | |
| 2210 PLATFORM_FAILURE, false); | |
| 2211 | |
| 2212 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); | 2190 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, height); |
| 2213 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", | 2191 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set media type attributes", |
| 2214 PLATFORM_FAILURE, false); | 2192 PLATFORM_FAILURE, false); |
| 2215 | 2193 |
| 2216 hr = video_format_converter_mft_->SetInputType(0, media_type.get(), 0); | 2194 hr = video_format_converter_mft_->SetInputType(0, media_type.get(), 0); |
| 2217 if (FAILED(hr)) { | 2195 if (FAILED(hr)) { |
| 2218 base::debug::Alias(&hr); | 2196 base::debug::Alias(&hr); |
| 2219 // TODO(ananta) | 2197 // TODO(ananta) |
| 2220 // Remove this CHECK when the change to use DX11 for H/W decoding | 2198 // Remove this CHECK when the change to use DX11 for H/W decoding |
| 2221 // stablizes. | 2199 // stablizes. |
| 2222 CHECK(false); | 2200 CHECK(false); |
| 2223 } | 2201 } |
| 2224 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type", | 2202 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to set converter input type", |
| 2225 PLATFORM_FAILURE, false); | 2203 PLATFORM_FAILURE, false); |
| 2226 | 2204 |
| 2227 base::win::ScopedComPtr<IMFMediaType> out_media_type; | 2205 // It appears that we fail to set MFVideoFormat_ARGB32 as the output media |
| 2206 // type in certain configurations. Try to fallback to MFVideoFormat_RGB32 |
| 2207 // in such cases. If both fail, then bail. |
| 2208 bool media_type_set = |
| 2209 SetTransformOutputType(video_format_converter_mft_.get(), |
| 2210 MFVideoFormat_ARGB32, |
| 2211 width, |
| 2212 height); |
| 2213 if (!media_type_set) { |
| 2214 media_type_set = |
| 2215 SetTransformOutputType(video_format_converter_mft_.get(), |
| 2216 MFVideoFormat_RGB32, |
| 2217 width, |
| 2218 height); |
| 2219 } |
| 2228 | 2220 |
| 2229 for (uint32_t i = 0; | 2221 if (!media_type_set) { |
| 2230 SUCCEEDED(video_format_converter_mft_->GetOutputAvailableType( | 2222 // Remove this once this stabilizes in the field. |
| 2231 0, i, out_media_type.Receive())); | 2223 CHECK(false); |
| 2232 ++i) { | 2224 LOG(ERROR) << "Failed to find a matching RGB output type in the converter"; |
| 2233 GUID out_subtype = {0}; | 2225 return false; |
| 2234 hr = out_media_type->GetGUID(MF_MT_SUBTYPE, &out_subtype); | 2226 } |
| 2235 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get output major type", | |
| 2236 PLATFORM_FAILURE, false); | |
| 2237 | 2227 |
| 2238 if (out_subtype == MFVideoFormat_ARGB32) { | 2228 dx11_video_format_converter_media_type_needs_init_ = false; |
| 2239 hr = out_media_type->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); | 2229 return true; |
| 2240 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | |
| 2241 "Failed to set attributes on media type", PLATFORM_FAILURE, false); | |
| 2242 | |
| 2243 hr = out_media_type->SetUINT32(MF_MT_INTERLACE_MODE, | |
| 2244 MFVideoInterlace_Progressive); | |
| 2245 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | |
| 2246 "Failed to set attributes on media type", PLATFORM_FAILURE, false); | |
| 2247 | |
| 2248 hr = MFSetAttributeSize(out_media_type.get(), MF_MT_FRAME_SIZE, width, | |
| 2249 height); | |
| 2250 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | |
| 2251 "Failed to set media type attributes", PLATFORM_FAILURE, false); | |
| 2252 | |
| 2253 hr = video_format_converter_mft_->SetOutputType( | |
| 2254 0, out_media_type.get(), 0); // No flags | |
| 2255 if (FAILED(hr)) { | |
| 2256 base::debug::Alias(&hr); | |
| 2257 // TODO(ananta) | |
| 2258 // Remove this CHECK when the change to use DX11 for H/W decoding | |
| 2259 // stablizes. | |
| 2260 CHECK(false); | |
| 2261 } | |
| 2262 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | |
| 2263 "Failed to set converter output type", PLATFORM_FAILURE, false); | |
| 2264 | |
| 2265 dx11_video_format_converter_media_type_needs_init_ = false; | |
| 2266 return true; | |
| 2267 } | |
| 2268 out_media_type.Release(); | |
| 2269 } | |
| 2270 return false; | |
| 2271 } | 2230 } |
| 2272 | 2231 |
| 2273 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions( | 2232 bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions( |
| 2274 IMFSample* sample, | 2233 IMFSample* sample, |
| 2275 int* width, | 2234 int* width, |
| 2276 int* height) { | 2235 int* height) { |
| 2277 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; | 2236 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; |
| 2278 HRESULT hr = sample->GetBufferByIndex(0, output_buffer.Receive()); | 2237 HRESULT hr = sample->GetBufferByIndex(0, output_buffer.Receive()); |
| 2279 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false); | 2238 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false); |
| 2280 | 2239 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2301 false); | 2260 false); |
| 2302 D3DSURFACE_DESC surface_desc; | 2261 D3DSURFACE_DESC surface_desc; |
| 2303 hr = surface->GetDesc(&surface_desc); | 2262 hr = surface->GetDesc(&surface_desc); |
| 2304 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); | 2263 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); |
| 2305 *width = surface_desc.Width; | 2264 *width = surface_desc.Width; |
| 2306 *height = surface_desc.Height; | 2265 *height = surface_desc.Height; |
| 2307 } | 2266 } |
| 2308 return true; | 2267 return true; |
| 2309 } | 2268 } |
| 2310 | 2269 |
| 2270 bool DXVAVideoDecodeAccelerator::SetTransformOutputType( |
| 2271 IMFTransform* transform, |
| 2272 const GUID& output_type, |
| 2273 int width, |
| 2274 int height) { |
| 2275 HRESULT hr = E_FAIL; |
| 2276 base::win::ScopedComPtr<IMFMediaType> media_type; |
| 2277 |
| 2278 for (uint32_t i = 0; |
| 2279 SUCCEEDED(transform->GetOutputAvailableType( |
| 2280 0, i, media_type.Receive())); |
| 2281 ++i) { |
| 2282 GUID out_subtype = {0}; |
| 2283 hr = media_type->GetGUID(MF_MT_SUBTYPE, &out_subtype); |
| 2284 RETURN_ON_HR_FAILURE(hr, "Failed to get output major type", false); |
| 2285 |
| 2286 if (out_subtype == output_type) { |
| 2287 if (width && height) { |
| 2288 hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, |
| 2289 height); |
| 2290 RETURN_ON_HR_FAILURE(hr, "Failed to set media type attributes", false); |
| 2291 } |
| 2292 hr = transform->SetOutputType(0, media_type.get(), 0); // No flags |
| 2293 if (FAILED(hr)) { |
| 2294 base::debug::Alias(&hr); |
| 2295 // TODO(ananta) |
| 2296 // Remove this CHECK when this stabilizes in the field. |
| 2297 CHECK(false); |
| 2298 } |
| 2299 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); |
| 2300 return true; |
| 2301 } |
| 2302 media_type.Release(); |
| 2303 } |
| 2304 return false; |
| 2305 } |
| 2306 |
| 2311 } // namespace content | 2307 } // namespace content |
| OLD | NEW |