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

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

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

Powered by Google App Engine
This is Rietveld 408576698