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.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator.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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 StopOnError(error_code); \ | 65 StopOnError(error_code); \ |
66 return ret; \ | 66 return ret; \ |
67 } \ | 67 } \ |
68 } while (0) | 68 } while (0) |
69 | 69 |
70 #define RETURN_AND_NOTIFY_ON_HR_FAILURE(result, log, error_code, ret) \ | 70 #define RETURN_AND_NOTIFY_ON_HR_FAILURE(result, log, error_code, ret) \ |
71 RETURN_AND_NOTIFY_ON_FAILURE(SUCCEEDED(result), \ | 71 RETURN_AND_NOTIFY_ON_FAILURE(SUCCEEDED(result), \ |
72 log << ", HRESULT: 0x" << std::hex << result, \ | 72 log << ", HRESULT: 0x" << std::hex << result, \ |
73 error_code, ret); | 73 error_code, ret); |
74 | 74 |
75 // Maximum number of iterations we allow before aborting the attempt to flush | |
76 // the batched queries to the driver. | |
Ami GONE FROM CHROMIUM
2012/11/15 21:57:49
s/driver/driver (and allow torn/corrupt frames to
ananta
2012/11/15 23:13:45
Done.
| |
77 enum { kMaxIterationsForD3DFlush = 10 }; | |
78 | |
75 static IMFSample* CreateEmptySample() { | 79 static IMFSample* CreateEmptySample() { |
76 base::win::ScopedComPtr<IMFSample> sample; | 80 base::win::ScopedComPtr<IMFSample> sample; |
77 HRESULT hr = MFCreateSample(sample.Receive()); | 81 HRESULT hr = MFCreateSample(sample.Receive()); |
78 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL); | 82 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL); |
79 return sample.Detach(); | 83 return sample.Detach(); |
80 } | 84 } |
81 | 85 |
82 // Creates a Media Foundation sample with one buffer of length |buffer_length| | 86 // Creates a Media Foundation sample with one buffer of length |buffer_length| |
83 // on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0. | 87 // on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0. |
84 static IMFSample* CreateEmptySampleWithBuffer(int buffer_length, int align) { | 88 static IMFSample* CreateEmptySampleWithBuffer(int buffer_length, int align) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
229 | 233 |
230 HRESULT hr = DXVAVideoDecodeAccelerator::device_->CreateTexture( | 234 HRESULT hr = DXVAVideoDecodeAccelerator::device_->CreateTexture( |
231 buffer.size().width(), | 235 buffer.size().width(), |
232 buffer.size().height(), | 236 buffer.size().height(), |
233 1, | 237 1, |
234 D3DUSAGE_RENDERTARGET, | 238 D3DUSAGE_RENDERTARGET, |
235 D3DFMT_X8R8G8B8, | 239 D3DFMT_X8R8G8B8, |
236 D3DPOOL_DEFAULT, | 240 D3DPOOL_DEFAULT, |
237 picture_buffer->decoding_texture_.Receive(), | 241 picture_buffer->decoding_texture_.Receive(), |
238 &share_handle); | 242 &share_handle); |
243 | |
239 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", | 244 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", |
240 linked_ptr<DXVAPictureBuffer>(NULL)); | 245 linked_ptr<DXVAPictureBuffer>(NULL)); |
241 return picture_buffer; | 246 return picture_buffer; |
242 } | 247 } |
243 | 248 |
244 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( | 249 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( |
245 const media::PictureBuffer& buffer) | 250 const media::PictureBuffer& buffer) |
246 : available_(true), | 251 : available_(true), |
247 picture_buffer_(buffer), | 252 picture_buffer_(buffer), |
248 decoding_surface_(NULL) { | 253 decoding_surface_(NULL) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 d3d_surface, | 322 d3d_surface, |
318 NULL, | 323 NULL, |
319 D3DTEXF_NONE); | 324 D3DTEXF_NONE); |
320 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", | 325 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", |
321 false); | 326 false); |
322 | 327 |
323 // Ideally, this should be done immediately before the draw call that uses | 328 // Ideally, this should be done immediately before the draw call that uses |
324 // the texture. Flush it once here though. | 329 // the texture. Flush it once here though. |
325 hr = query_->Issue(D3DISSUE_END); | 330 hr = query_->Issue(D3DISSUE_END); |
326 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false); | 331 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false); |
327 do { | 332 |
328 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH); | 333 // The DXVA decoder has its own device which it uses for decoding. ANGLE |
329 if (hr == S_FALSE) | 334 // has its own device which we don't have access to. |
330 Sleep(1); // Poor-man's Yield(). | 335 // The above code attempts to copy the decoded picture into a surface |
331 } while (hr == S_FALSE); | 336 // which is owned by ANGLE. As there are multiple devices involved in |
337 // this, the StretchRect call above is not synchronous. | |
338 // We attempt to flush the batched operations to ensure that the picture is | |
339 // copied to the surface owned by ANGLE. | |
340 // We need to do this in a loop and call flush multiple times. | |
341 // We have seen the GetData call for flushing the command buffer fail to | |
342 // return success occassionally on multi core machines, leading to an | |
343 // infinite loop. | |
344 // Workaround is to have a upper limit of 10 on the number of iterations we | |
Ami GONE FROM CHROMIUM
2012/11/15 21:57:49
s/a upper/an upper/
ananta
2012/11/15 23:13:45
Done.
| |
345 // wait for the Flush to finish. | |
346 int iterations = 0; | |
347 while ((query_->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE) && | |
348 ++iterations < kMaxIterationsForD3DFlush) { | |
349 Sleep(1); // Poor-man's Yield(). | |
350 } | |
332 eglBindTexImage( | 351 eglBindTexImage( |
333 static_cast<EGLDisplay*>(eglGetDisplay(EGL_DEFAULT_DISPLAY)), | 352 static_cast<EGLDisplay*>(eglGetDisplay(EGL_DEFAULT_DISPLAY)), |
334 decoding_surface_, | 353 decoding_surface_, |
335 EGL_BACK_BUFFER); | 354 EGL_BACK_BUFFER); |
336 | |
337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
338 glBindTexture(GL_TEXTURE_2D, current_texture); | 356 glBindTexture(GL_TEXTURE_2D, current_texture); |
339 return true; | 357 return true; |
340 } | 358 } |
341 | 359 |
342 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( | 360 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( |
343 int32 buffer_id, IMFSample* sample) | 361 int32 buffer_id, IMFSample* sample) |
344 : input_buffer_id(buffer_id) { | 362 : input_buffer_id(buffer_id) { |
345 output_sample.Attach(sample); | 363 output_sample.Attach(sample); |
346 } | 364 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 | 426 |
409 hr = device_manager_->ResetDevice(device_, dev_manager_reset_token_); | 427 hr = device_manager_->ResetDevice(device_, dev_manager_reset_token_); |
410 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); | 428 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); |
411 | 429 |
412 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, &query_); | 430 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, &query_); |
413 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); | 431 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); |
414 // Ensure query_ API works (to avoid an infinite loop later in | 432 // Ensure query_ API works (to avoid an infinite loop later in |
415 // CopyOutputSampleDataToPictureBuffer). | 433 // CopyOutputSampleDataToPictureBuffer). |
416 hr = query_->Issue(D3DISSUE_END); | 434 hr = query_->Issue(D3DISSUE_END); |
417 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); | 435 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); |
418 | |
419 return true; | 436 return true; |
420 } | 437 } |
421 | 438 |
422 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( | 439 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( |
423 media::VideoDecodeAccelerator::Client* client, | 440 media::VideoDecodeAccelerator::Client* client, |
424 const base::Callback<bool(void)>& make_context_current) | 441 const base::Callback<bool(void)>& make_context_current) |
425 : client_(client), | 442 : client_(client), |
426 egl_config_(NULL), | 443 egl_config_(NULL), |
427 state_(kUninitialized), | 444 state_(kUninitialized), |
428 pictures_requested_(false), | 445 pictures_requested_(false), |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1056 return; | 1073 return; |
1057 } | 1074 } |
1058 | 1075 |
1059 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 1076 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
1060 &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this))); | 1077 &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this))); |
1061 | 1078 |
1062 state_ = kNormal; | 1079 state_ = kNormal; |
1063 } | 1080 } |
1064 | 1081 |
1065 } // namespace content | 1082 } // namespace content |
OLD | NEW |