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

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

Issue 1688993002: Wait on fence before reusing DXVA picture buffer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 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 23 matching lines...) Expand all
34 #include "base/trace_event/trace_event.h" 34 #include "base/trace_event/trace_event.h"
35 #include "base/win/windows_version.h" 35 #include "base/win/windows_version.h"
36 #include "build/build_config.h" 36 #include "build/build_config.h"
37 #include "content/public/common/content_switches.h" 37 #include "content/public/common/content_switches.h"
38 #include "media/base/win/mf_initializer.h" 38 #include "media/base/win/mf_initializer.h"
39 #include "media/video/video_decode_accelerator.h" 39 #include "media/video/video_decode_accelerator.h"
40 #include "third_party/angle/include/EGL/egl.h" 40 #include "third_party/angle/include/EGL/egl.h"
41 #include "third_party/angle/include/EGL/eglext.h" 41 #include "third_party/angle/include/EGL/eglext.h"
42 #include "ui/gl/gl_bindings.h" 42 #include "ui/gl/gl_bindings.h"
43 #include "ui/gl/gl_context.h" 43 #include "ui/gl/gl_context.h"
44 #include "ui/gl/gl_fence.h"
44 #include "ui/gl/gl_surface_egl.h" 45 #include "ui/gl/gl_surface_egl.h"
45 #include "ui/gl/gl_switches.h" 46 #include "ui/gl/gl_switches.h"
46 47
47 namespace { 48 namespace {
48 49
49 // Path is appended on to the PROGRAM_FILES base path. 50 // Path is appended on to the PROGRAM_FILES base path.
50 const wchar_t kVPXDecoderDLLPath[] = L"Intel\\Media SDK\\"; 51 const wchar_t kVPXDecoderDLLPath[] = L"Intel\\Media SDK\\";
51 52
52 const wchar_t kVP8DecoderDLLName[] = 53 const wchar_t kVP8DecoderDLLName[] =
53 #if defined(ARCH_CPU_X86) 54 #if defined(ARCH_CPU_X86)
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 log << ", HRESULT: 0x" << std::hex << result, \ 156 log << ", HRESULT: 0x" << std::hex << result, \
156 error_code, ret); 157 error_code, ret);
157 158
158 enum { 159 enum {
159 // Maximum number of iterations we allow before aborting the attempt to flush 160 // Maximum number of iterations we allow before aborting the attempt to flush
160 // the batched queries to the driver and allow torn/corrupt frames to be 161 // the batched queries to the driver and allow torn/corrupt frames to be
161 // rendered. 162 // rendered.
162 kFlushDecoderSurfaceTimeoutMs = 1, 163 kFlushDecoderSurfaceTimeoutMs = 1,
163 // Maximum iterations where we try to flush the d3d device. 164 // Maximum iterations where we try to flush the d3d device.
164 kMaxIterationsForD3DFlush = 4, 165 kMaxIterationsForD3DFlush = 4,
166 // Maximum iterations where we try to flush the ANGLE device before reusing
167 // the texture.
168 kMaxIterationsForANGLEReuseFlush = 16,
165 // We only request 5 picture buffers from the client which are used to hold 169 // We only request 5 picture buffers from the client which are used to hold
166 // the decoded samples. These buffers are then reused when the client tells 170 // the decoded samples. These buffers are then reused when the client tells
167 // us that it is done with the buffer. 171 // us that it is done with the buffer.
168 kNumPictureBuffers = 5, 172 kNumPictureBuffers = 5,
169 // The keyed mutex should always be released before the other thread 173 // The keyed mutex should always be released before the other thread
170 // attempts to acquire it, so AcquireSync should always return immediately. 174 // attempts to acquire it, so AcquireSync should always return immediately.
171 kAcquireSyncWaitMs = 0, 175 kAcquireSyncWaitMs = 0,
172 }; 176 };
173 177
174 static IMFSample* CreateEmptySample() { 178 static IMFSample* CreateEmptySample() {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 static linked_ptr<DXVAPictureBuffer> Create( 357 static linked_ptr<DXVAPictureBuffer> Create(
354 const DXVAVideoDecodeAccelerator& decoder, 358 const DXVAVideoDecodeAccelerator& decoder,
355 const media::PictureBuffer& buffer, 359 const media::PictureBuffer& buffer,
356 EGLConfig egl_config); 360 EGLConfig egl_config);
357 ~DXVAPictureBuffer(); 361 ~DXVAPictureBuffer();
358 362
359 bool InitializeTexture(const DXVAVideoDecodeAccelerator& decoder, 363 bool InitializeTexture(const DXVAVideoDecodeAccelerator& decoder,
360 bool use_rgb); 364 bool use_rgb);
361 365
362 bool ReusePictureBuffer(); 366 bool ReusePictureBuffer();
367 void ResetReuseFence();
363 // Copies the output sample data to the picture buffer provided by the 368 // Copies the output sample data to the picture buffer provided by the
364 // client. 369 // client.
365 // The dest_surface parameter contains the decoded bits. 370 // The dest_surface parameter contains the decoded bits.
366 bool CopyOutputSampleDataToPictureBuffer( 371 bool CopyOutputSampleDataToPictureBuffer(
367 DXVAVideoDecodeAccelerator* decoder, 372 DXVAVideoDecodeAccelerator* decoder,
368 IDirect3DSurface9* dest_surface, 373 IDirect3DSurface9* dest_surface,
369 ID3D11Texture2D* dx11_texture, 374 ID3D11Texture2D* dx11_texture,
370 int input_buffer_id); 375 int input_buffer_id);
371 376
372 bool available() const { 377 bool available() const {
373 return available_; 378 return available_;
374 } 379 }
375 380
376 void set_available(bool available) { 381 void set_available(bool available) {
377 available_ = available; 382 available_ = available;
378 } 383 }
379 384
380 int id() const { 385 int id() const {
381 return picture_buffer_.id(); 386 return picture_buffer_.id();
382 } 387 }
383 388
384 gfx::Size size() const { 389 gfx::Size size() const {
385 return picture_buffer_.size(); 390 return picture_buffer_.size();
386 } 391 }
387 392
393 bool waiting_to_reuse() const { return waiting_to_reuse_; }
394
395 gfx::GLFence* reuse_fence() { return reuse_fence_.get(); }
396
388 // Called when the source surface |src_surface| is copied to the destination 397 // Called when the source surface |src_surface| is copied to the destination
389 // |dest_surface| 398 // |dest_surface|
390 bool CopySurfaceComplete(IDirect3DSurface9* src_surface, 399 bool CopySurfaceComplete(IDirect3DSurface9* src_surface,
391 IDirect3DSurface9* dest_surface); 400 IDirect3DSurface9* dest_surface);
392 401
393 private: 402 private:
394 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer); 403 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer);
395 404
396 bool available_; 405 bool available_;
406
407 // This is true if the decoder is currently waiting on the fence before
408 // reusing the buffer.
409 bool waiting_to_reuse_;
397 media::PictureBuffer picture_buffer_; 410 media::PictureBuffer picture_buffer_;
398 EGLSurface decoding_surface_; 411 EGLSurface decoding_surface_;
412 scoped_ptr<gfx::GLFence> reuse_fence_;
399 413
400 HANDLE texture_share_handle_; 414 HANDLE texture_share_handle_;
401 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_; 415 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_;
402 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_; 416 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_;
403 417
404 base::win::ScopedComPtr<IDXGIKeyedMutex> egl_keyed_mutex_; 418 base::win::ScopedComPtr<IDXGIKeyedMutex> egl_keyed_mutex_;
405 base::win::ScopedComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_; 419 base::win::ScopedComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_;
406 420
407 // This is the last value that was used to release the keyed mutex. 421 // This is the last value that was used to release the keyed mutex.
408 uint64_t keyed_mutex_value_; 422 uint64_t keyed_mutex_value_;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false); 530 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
517 RETURN_ON_FAILURE(texture_share_handle_, "Failed to query shared handle", 531 RETURN_ON_FAILURE(texture_share_handle_, "Failed to query shared handle",
518 false); 532 false);
519 } 533 }
520 return true; 534 return true;
521 } 535 }
522 536
523 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( 537 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer(
524 const media::PictureBuffer& buffer) 538 const media::PictureBuffer& buffer)
525 : available_(true), 539 : available_(true),
540 waiting_to_reuse_(false),
526 picture_buffer_(buffer), 541 picture_buffer_(buffer),
527 decoding_surface_(NULL), 542 decoding_surface_(NULL),
528 texture_share_handle_(nullptr), 543 texture_share_handle_(nullptr),
529 keyed_mutex_value_(0), 544 keyed_mutex_value_(0),
530 use_rgb_(true) {} 545 use_rgb_(true) {}
531 546
532 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() { 547 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() {
533 if (decoding_surface_) { 548 if (decoding_surface_) {
534 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 549 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
535 550
(...skipping 12 matching lines...) Expand all
548 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() { 563 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() {
549 DCHECK(decoding_surface_); 564 DCHECK(decoding_surface_);
550 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 565 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
551 eglReleaseTexImage( 566 eglReleaseTexImage(
552 egl_display, 567 egl_display,
553 decoding_surface_, 568 decoding_surface_,
554 EGL_BACK_BUFFER); 569 EGL_BACK_BUFFER);
555 decoder_surface_.Release(); 570 decoder_surface_.Release();
556 target_surface_.Release(); 571 target_surface_.Release();
557 decoder_dx11_texture_.Release(); 572 decoder_dx11_texture_.Release();
573 waiting_to_reuse_ = false;
558 set_available(true); 574 set_available(true);
559 if (egl_keyed_mutex_) { 575 if (egl_keyed_mutex_) {
560 HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_); 576 HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_);
561 RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false); 577 RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false);
562 } 578 }
563 return true; 579 return true;
564 } 580 }
565 581
582 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ResetReuseFence() {
583 if (!reuse_fence_ || !reuse_fence_->ResetSupported())
584 reuse_fence_.reset(gfx::GLFence::Create());
585 else
586 reuse_fence_->ResetState();
587 waiting_to_reuse_ = true;
588 }
589
566 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer:: 590 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
567 CopyOutputSampleDataToPictureBuffer( 591 CopyOutputSampleDataToPictureBuffer(
568 DXVAVideoDecodeAccelerator* decoder, 592 DXVAVideoDecodeAccelerator* decoder,
569 IDirect3DSurface9* dest_surface, 593 IDirect3DSurface9* dest_surface,
570 ID3D11Texture2D* dx11_texture, 594 ID3D11Texture2D* dx11_texture,
571 int input_buffer_id) { 595 int input_buffer_id) {
572 DCHECK(dest_surface || dx11_texture); 596 DCHECK(dest_surface || dx11_texture);
573 if (dx11_texture) { 597 if (dx11_texture) {
574 // Grab a reference on the decoder texture. This reference will be released 598 // Grab a reference on the decoder texture. This reference will be released
575 // when we receive a notification that the copy was completed or when the 599 // when we receive a notification that the copy was completed or when the
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 create_dxgi_device_manager_ = reinterpret_cast<CreateDXGIDeviceManager>( 771 create_dxgi_device_manager_ = reinterpret_cast<CreateDXGIDeviceManager>(
748 ::GetProcAddress(dxgi_manager_dll, "MFCreateDXGIDeviceManager")); 772 ::GetProcAddress(dxgi_manager_dll, "MFCreateDXGIDeviceManager"));
749 } 773 }
750 774
751 RETURN_AND_NOTIFY_ON_FAILURE( 775 RETURN_AND_NOTIFY_ON_FAILURE(
752 gfx::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle, 776 gfx::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle,
753 "EGL_ANGLE_surface_d3d_texture_2d_share_handle unavailable", 777 "EGL_ANGLE_surface_d3d_texture_2d_share_handle unavailable",
754 PLATFORM_FAILURE, 778 PLATFORM_FAILURE,
755 false); 779 false);
756 780
781 RETURN_AND_NOTIFY_ON_FAILURE(gfx::GLFence::IsSupported(),
782 "GL fences are unsupported", PLATFORM_FAILURE,
783 false);
784
757 State state = GetState(); 785 State state = GetState();
758 RETURN_AND_NOTIFY_ON_FAILURE((state == kUninitialized), 786 RETURN_AND_NOTIFY_ON_FAILURE((state == kUninitialized),
759 "Initialize: invalid state: " << state, ILLEGAL_STATE, false); 787 "Initialize: invalid state: " << state, ILLEGAL_STATE, false);
760 788
761 media::InitializeMediaFoundation(); 789 media::InitializeMediaFoundation();
762 790
763 RETURN_AND_NOTIFY_ON_FAILURE(InitDecoder(config.profile), 791 RETURN_AND_NOTIFY_ON_FAILURE(InitDecoder(config.profile),
764 "Failed to initialize decoder", PLATFORM_FAILURE, false); 792 "Failed to initialize decoder", PLATFORM_FAILURE, false);
765 793
766 RETURN_AND_NOTIFY_ON_FAILURE(GetStreamsInfoAndBufferReqs(), 794 RETURN_AND_NOTIFY_ON_FAILURE(GetStreamsInfoAndBufferReqs(),
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 it = stale_output_picture_buffers_.find(picture_buffer_id); 1046 it = stale_output_picture_buffers_.find(picture_buffer_id);
1019 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), 1047 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
1020 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); 1048 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
1021 main_thread_task_runner_->PostTask( 1049 main_thread_task_runner_->PostTask(
1022 FROM_HERE, 1050 FROM_HERE,
1023 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, 1051 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
1024 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); 1052 weak_this_factory_.GetWeakPtr(), picture_buffer_id));
1025 return; 1053 return;
1026 } 1054 }
1027 1055
1028 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(), 1056 if (it->second->available() || it->second->waiting_to_reuse())
1057 return;
1058
1059 if (use_keyed_mutex_ || using_angle_device_) {
1060 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(),
1061 "Failed to reuse picture buffer",
1062 PLATFORM_FAILURE, );
1063
1064 ProcessPendingSamples();
1065 if (pending_flush_) {
1066 decoder_thread_task_runner_->PostTask(
1067 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
1068 base::Unretained(this)));
1069 }
1070 } else {
1071 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
1072 "Failed to make context current",
1073 PLATFORM_FAILURE, );
1074 it->second->ResetReuseFence();
1075
1076 WaitForOutputBuffer(picture_buffer_id, 0);
1077 }
1078 }
1079
1080 void DXVAVideoDecodeAccelerator::WaitForOutputBuffer(int32_t picture_buffer_id,
1081 int count) {
1082 DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
1083 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id);
1084 if (it == output_picture_buffers_.end())
1085 return;
1086
1087 DXVAPictureBuffer* picture_buffer = it->second.get();
1088
1089 DCHECK(!picture_buffer->available());
1090 DCHECK(picture_buffer->waiting_to_reuse());
1091
1092 gfx::GLFence* fence = picture_buffer->reuse_fence();
1093 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
1094 "Failed to make context current",
1095 PLATFORM_FAILURE, );
1096 if (count <= kMaxIterationsForANGLEReuseFlush && !fence->HasCompleted()) {
1097 main_thread_task_runner_->PostDelayedTask(
1098 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::WaitForOutputBuffer,
1099 weak_this_factory_.GetWeakPtr(),
1100 picture_buffer_id, count + 1),
1101 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
1102 return;
1103 }
1104 RETURN_AND_NOTIFY_ON_FAILURE(picture_buffer->ReusePictureBuffer(),
1029 "Failed to reuse picture buffer", 1105 "Failed to reuse picture buffer",
1030 PLATFORM_FAILURE, ); 1106 PLATFORM_FAILURE, );
1031 1107
1032 ProcessPendingSamples(); 1108 ProcessPendingSamples();
1033 if (pending_flush_) { 1109 if (pending_flush_) {
1034 decoder_thread_task_runner_->PostTask( 1110 decoder_thread_task_runner_->PostTask(
1035 FROM_HERE, 1111 FROM_HERE,
1036 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, 1112 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
1037 base::Unretained(this))); 1113 base::Unretained(this)));
1038 } 1114 }
(...skipping 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after
2381 } 2457 }
2382 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); 2458 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false);
2383 return true; 2459 return true;
2384 } 2460 }
2385 media_type.Release(); 2461 media_type.Release();
2386 } 2462 }
2387 return false; 2463 return false;
2388 } 2464 }
2389 2465
2390 } // namespace content 2466 } // 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