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

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

Issue 1766183002: Wait on fence before reusing DXVA picture buffer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2661
Patch Set: Created 4 years, 9 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 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 static linked_ptr<DXVAPictureBuffer> Create( 342 static linked_ptr<DXVAPictureBuffer> Create(
339 const DXVAVideoDecodeAccelerator& decoder, 343 const DXVAVideoDecodeAccelerator& decoder,
340 const media::PictureBuffer& buffer, 344 const media::PictureBuffer& buffer,
341 EGLConfig egl_config); 345 EGLConfig egl_config);
342 ~DXVAPictureBuffer(); 346 ~DXVAPictureBuffer();
343 347
344 bool InitializeTexture(const DXVAVideoDecodeAccelerator& decoder, 348 bool InitializeTexture(const DXVAVideoDecodeAccelerator& decoder,
345 bool use_rgb); 349 bool use_rgb);
346 350
347 bool ReusePictureBuffer(); 351 bool ReusePictureBuffer();
352 void ResetReuseFence();
348 // Copies the output sample data to the picture buffer provided by the 353 // Copies the output sample data to the picture buffer provided by the
349 // client. 354 // client.
350 // The dest_surface parameter contains the decoded bits. 355 // The dest_surface parameter contains the decoded bits.
351 bool CopyOutputSampleDataToPictureBuffer( 356 bool CopyOutputSampleDataToPictureBuffer(
352 DXVAVideoDecodeAccelerator* decoder, 357 DXVAVideoDecodeAccelerator* decoder,
353 IDirect3DSurface9* dest_surface, 358 IDirect3DSurface9* dest_surface,
354 ID3D11Texture2D* dx11_texture, 359 ID3D11Texture2D* dx11_texture,
355 int input_buffer_id); 360 int input_buffer_id);
356 361
357 bool available() const { 362 bool available() const {
358 return available_; 363 return available_;
359 } 364 }
360 365
361 void set_available(bool available) { 366 void set_available(bool available) {
362 available_ = available; 367 available_ = available;
363 } 368 }
364 369
365 int id() const { 370 int id() const {
366 return picture_buffer_.id(); 371 return picture_buffer_.id();
367 } 372 }
368 373
369 gfx::Size size() const { 374 gfx::Size size() const {
370 return picture_buffer_.size(); 375 return picture_buffer_.size();
371 } 376 }
372 377
378 bool waiting_to_reuse() const { return waiting_to_reuse_; }
379
380 gfx::GLFence* reuse_fence() { return reuse_fence_.get(); }
381
373 // Called when the source surface |src_surface| is copied to the destination 382 // Called when the source surface |src_surface| is copied to the destination
374 // |dest_surface| 383 // |dest_surface|
375 bool CopySurfaceComplete(IDirect3DSurface9* src_surface, 384 bool CopySurfaceComplete(IDirect3DSurface9* src_surface,
376 IDirect3DSurface9* dest_surface); 385 IDirect3DSurface9* dest_surface);
377 386
378 private: 387 private:
379 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer); 388 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer);
380 389
381 bool available_; 390 bool available_;
391
392 // This is true if the decoder is currently waiting on the fence before
393 // reusing the buffer.
394 bool waiting_to_reuse_;
382 media::PictureBuffer picture_buffer_; 395 media::PictureBuffer picture_buffer_;
383 EGLSurface decoding_surface_; 396 EGLSurface decoding_surface_;
397 scoped_ptr<gfx::GLFence> reuse_fence_;
384 398
385 HANDLE texture_share_handle_; 399 HANDLE texture_share_handle_;
386 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_; 400 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_;
387 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_; 401 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_;
388 402
389 base::win::ScopedComPtr<IDXGIKeyedMutex> egl_keyed_mutex_; 403 base::win::ScopedComPtr<IDXGIKeyedMutex> egl_keyed_mutex_;
390 base::win::ScopedComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_; 404 base::win::ScopedComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_;
391 405
392 // This is the last value that was used to release the keyed mutex. 406 // This is the last value that was used to release the keyed mutex.
393 uint64_t keyed_mutex_value_; 407 uint64_t keyed_mutex_value_;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false); 515 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
502 RETURN_ON_FAILURE(texture_share_handle_, "Failed to query shared handle", 516 RETURN_ON_FAILURE(texture_share_handle_, "Failed to query shared handle",
503 false); 517 false);
504 } 518 }
505 return true; 519 return true;
506 } 520 }
507 521
508 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( 522 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer(
509 const media::PictureBuffer& buffer) 523 const media::PictureBuffer& buffer)
510 : available_(true), 524 : available_(true),
525 waiting_to_reuse_(false),
511 picture_buffer_(buffer), 526 picture_buffer_(buffer),
512 decoding_surface_(NULL), 527 decoding_surface_(NULL),
513 texture_share_handle_(nullptr), 528 texture_share_handle_(nullptr),
514 keyed_mutex_value_(0), 529 keyed_mutex_value_(0),
515 use_rgb_(true) {} 530 use_rgb_(true) {}
516 531
517 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() { 532 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() {
518 if (decoding_surface_) { 533 if (decoding_surface_) {
519 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 534 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
520 535
(...skipping 12 matching lines...) Expand all
533 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() { 548 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() {
534 DCHECK(decoding_surface_); 549 DCHECK(decoding_surface_);
535 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 550 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
536 eglReleaseTexImage( 551 eglReleaseTexImage(
537 egl_display, 552 egl_display,
538 decoding_surface_, 553 decoding_surface_,
539 EGL_BACK_BUFFER); 554 EGL_BACK_BUFFER);
540 decoder_surface_.Release(); 555 decoder_surface_.Release();
541 target_surface_.Release(); 556 target_surface_.Release();
542 decoder_dx11_texture_.Release(); 557 decoder_dx11_texture_.Release();
558 waiting_to_reuse_ = false;
543 set_available(true); 559 set_available(true);
544 if (egl_keyed_mutex_) { 560 if (egl_keyed_mutex_) {
545 HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_); 561 HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_);
546 RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false); 562 RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false);
547 } 563 }
548 return true; 564 return true;
549 } 565 }
550 566
567 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ResetReuseFence() {
568 if (!reuse_fence_ || !reuse_fence_->ResetSupported())
569 reuse_fence_.reset(gfx::GLFence::Create());
570 else
571 reuse_fence_->ResetState();
572 waiting_to_reuse_ = true;
573 }
574
551 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer:: 575 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
552 CopyOutputSampleDataToPictureBuffer( 576 CopyOutputSampleDataToPictureBuffer(
553 DXVAVideoDecodeAccelerator* decoder, 577 DXVAVideoDecodeAccelerator* decoder,
554 IDirect3DSurface9* dest_surface, 578 IDirect3DSurface9* dest_surface,
555 ID3D11Texture2D* dx11_texture, 579 ID3D11Texture2D* dx11_texture,
556 int input_buffer_id) { 580 int input_buffer_id) {
557 DCHECK(dest_surface || dx11_texture); 581 DCHECK(dest_surface || dx11_texture);
558 if (dx11_texture) { 582 if (dx11_texture) {
559 // Grab a reference on the decoder texture. This reference will be released 583 // Grab a reference on the decoder texture. This reference will be released
560 // when we receive a notification that the copy was completed or when the 584 // 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
732 create_dxgi_device_manager_ = reinterpret_cast<CreateDXGIDeviceManager>( 756 create_dxgi_device_manager_ = reinterpret_cast<CreateDXGIDeviceManager>(
733 ::GetProcAddress(dxgi_manager_dll, "MFCreateDXGIDeviceManager")); 757 ::GetProcAddress(dxgi_manager_dll, "MFCreateDXGIDeviceManager"));
734 } 758 }
735 759
736 RETURN_AND_NOTIFY_ON_FAILURE( 760 RETURN_AND_NOTIFY_ON_FAILURE(
737 gfx::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle, 761 gfx::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle,
738 "EGL_ANGLE_surface_d3d_texture_2d_share_handle unavailable", 762 "EGL_ANGLE_surface_d3d_texture_2d_share_handle unavailable",
739 PLATFORM_FAILURE, 763 PLATFORM_FAILURE,
740 false); 764 false);
741 765
766 RETURN_AND_NOTIFY_ON_FAILURE(gfx::GLFence::IsSupported(),
767 "GL fences are unsupported", PLATFORM_FAILURE,
768 false);
769
742 State state = GetState(); 770 State state = GetState();
743 RETURN_AND_NOTIFY_ON_FAILURE((state == kUninitialized), 771 RETURN_AND_NOTIFY_ON_FAILURE((state == kUninitialized),
744 "Initialize: invalid state: " << state, ILLEGAL_STATE, false); 772 "Initialize: invalid state: " << state, ILLEGAL_STATE, false);
745 773
746 media::InitializeMediaFoundation(); 774 media::InitializeMediaFoundation();
747 775
748 RETURN_AND_NOTIFY_ON_FAILURE(InitDecoder(config.profile), 776 RETURN_AND_NOTIFY_ON_FAILURE(InitDecoder(config.profile),
749 "Failed to initialize decoder", PLATFORM_FAILURE, false); 777 "Failed to initialize decoder", PLATFORM_FAILURE, false);
750 778
751 RETURN_AND_NOTIFY_ON_FAILURE(GetStreamsInfoAndBufferReqs(), 779 RETURN_AND_NOTIFY_ON_FAILURE(GetStreamsInfoAndBufferReqs(),
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 it = stale_output_picture_buffers_.find(picture_buffer_id); 1044 it = stale_output_picture_buffers_.find(picture_buffer_id);
1017 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), 1045 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
1018 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); 1046 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
1019 main_thread_task_runner_->PostTask( 1047 main_thread_task_runner_->PostTask(
1020 FROM_HERE, 1048 FROM_HERE,
1021 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, 1049 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
1022 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); 1050 weak_this_factory_.GetWeakPtr(), picture_buffer_id));
1023 return; 1051 return;
1024 } 1052 }
1025 1053
1026 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(), 1054 if (it->second->available() || it->second->waiting_to_reuse())
1055 return;
1056
1057 if (use_keyed_mutex_ || using_angle_device_) {
1058 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(),
1059 "Failed to reuse picture buffer",
1060 PLATFORM_FAILURE, );
1061
1062 ProcessPendingSamples();
1063 if (pending_flush_) {
1064 decoder_thread_task_runner_->PostTask(
1065 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
1066 base::Unretained(this)));
1067 }
1068 } else {
1069 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
1070 "Failed to make context current",
1071 PLATFORM_FAILURE, );
1072 it->second->ResetReuseFence();
1073
1074 WaitForOutputBuffer(picture_buffer_id, 0);
1075 }
1076 }
1077
1078 void DXVAVideoDecodeAccelerator::WaitForOutputBuffer(int32_t picture_buffer_id,
1079 int count) {
1080 DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
1081 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id);
1082 if (it == output_picture_buffers_.end())
1083 return;
1084
1085 DXVAPictureBuffer* picture_buffer = it->second.get();
1086
1087 DCHECK(!picture_buffer->available());
1088 DCHECK(picture_buffer->waiting_to_reuse());
1089
1090 gfx::GLFence* fence = picture_buffer->reuse_fence();
1091 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
1092 "Failed to make context current",
1093 PLATFORM_FAILURE, );
1094 if (count <= kMaxIterationsForANGLEReuseFlush && !fence->HasCompleted()) {
1095 main_thread_task_runner_->PostDelayedTask(
1096 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::WaitForOutputBuffer,
1097 weak_this_factory_.GetWeakPtr(),
1098 picture_buffer_id, count + 1),
1099 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
1100 return;
1101 }
1102 RETURN_AND_NOTIFY_ON_FAILURE(picture_buffer->ReusePictureBuffer(),
1027 "Failed to reuse picture buffer", 1103 "Failed to reuse picture buffer",
1028 PLATFORM_FAILURE, ); 1104 PLATFORM_FAILURE, );
1029 1105
1030 ProcessPendingSamples(); 1106 ProcessPendingSamples();
1031 if (pending_flush_) { 1107 if (pending_flush_) {
1032 decoder_thread_task_runner_->PostTask( 1108 decoder_thread_task_runner_->PostTask(
1033 FROM_HERE, 1109 FROM_HERE,
1034 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, 1110 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
1035 base::Unretained(this))); 1111 base::Unretained(this)));
1036 } 1112 }
(...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after
2380 } 2456 }
2381 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); 2457 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false);
2382 return true; 2458 return true;
2383 } 2459 }
2384 media_type.Release(); 2460 media_type.Release();
2385 } 2461 }
2386 return false; 2462 return false;
2387 } 2463 }
2388 2464
2389 } // namespace content 2465 } // 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