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 |