Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: content/common/gpu/media/dxva_video_decode_accelerator_win.cc

Issue 1591603002: Attempt to fix a crash in the DXVA decoder in the DXVAVideoDecodeAccelerator::ProcessPendingSamplesā€¦ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address review comments Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/dxva_video_decode_accelerator_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/common/gpu/media/dxva_video_decode_accelerator_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698