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

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

Issue 1553603002: Use IDXGIKeyedMutex to synchronize between DXVA decoder and main context (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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 // Maximum number of iterations we allow before aborting the attempt to flush 159 // 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 160 // the batched queries to the driver and allow torn/corrupt frames to be
161 // rendered. 161 // rendered.
162 kFlushDecoderSurfaceTimeoutMs = 1, 162 kFlushDecoderSurfaceTimeoutMs = 1,
163 // Maximum iterations where we try to flush the d3d device. 163 // Maximum iterations where we try to flush the d3d device.
164 kMaxIterationsForD3DFlush = 4, 164 kMaxIterationsForD3DFlush = 4,
165 // We only request 5 picture buffers from the client which are used to hold 165 // 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 166 // the decoded samples. These buffers are then reused when the client tells
167 // us that it is done with the buffer. 167 // us that it is done with the buffer.
168 kNumPictureBuffers = 5, 168 kNumPictureBuffers = 5,
169 // The keyed mutex should always be released before the other thread
170 // attempts to acquire it, so AcquireSync should always return immediately.
171 kAcquireSyncWaitMs = 0,
169 }; 172 };
170 173
171 static IMFSample* CreateEmptySample() { 174 static IMFSample* CreateEmptySample() {
172 base::win::ScopedComPtr<IMFSample> sample; 175 base::win::ScopedComPtr<IMFSample> sample;
173 HRESULT hr = MFCreateSample(sample.Receive()); 176 HRESULT hr = MFCreateSample(sample.Receive());
174 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL); 177 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL);
175 return sample.Detach(); 178 return sample.Detach();
176 } 179 }
177 180
178 // Creates a Media Foundation sample with one buffer of length |buffer_length| 181 // Creates a Media Foundation sample with one buffer of length |buffer_length|
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 // Maintains information about a DXVA picture buffer, i.e. whether it is 345 // Maintains information about a DXVA picture buffer, i.e. whether it is
343 // available for rendering, the texture information, etc. 346 // available for rendering, the texture information, etc.
344 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { 347 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer {
345 public: 348 public:
346 static linked_ptr<DXVAPictureBuffer> Create( 349 static linked_ptr<DXVAPictureBuffer> Create(
347 const DXVAVideoDecodeAccelerator& decoder, 350 const DXVAVideoDecodeAccelerator& decoder,
348 const media::PictureBuffer& buffer, 351 const media::PictureBuffer& buffer,
349 EGLConfig egl_config); 352 EGLConfig egl_config);
350 ~DXVAPictureBuffer(); 353 ~DXVAPictureBuffer();
351 354
352 void ReusePictureBuffer(); 355 bool InitializeTexture(const DXVAVideoDecodeAccelerator& decoder,
356 bool use_rgb);
357
358 bool ReusePictureBuffer();
353 // Copies the output sample data to the picture buffer provided by the 359 // Copies the output sample data to the picture buffer provided by the
354 // client. 360 // client.
355 // The dest_surface parameter contains the decoded bits. 361 // The dest_surface parameter contains the decoded bits.
356 bool CopyOutputSampleDataToPictureBuffer( 362 bool CopyOutputSampleDataToPictureBuffer(
357 DXVAVideoDecodeAccelerator* decoder, 363 DXVAVideoDecodeAccelerator* decoder,
358 IDirect3DSurface9* dest_surface, 364 IDirect3DSurface9* dest_surface,
359 ID3D11Texture2D* dx11_texture, 365 ID3D11Texture2D* dx11_texture,
360 int input_buffer_id); 366 int input_buffer_id);
361 367
362 bool available() const { 368 bool available() const {
363 return available_; 369 return available_;
364 } 370 }
365 371
366 void set_available(bool available) { 372 void set_available(bool available) {
367 available_ = available; 373 available_ = available;
368 } 374 }
369 375
370 int id() const { 376 int id() const {
371 return picture_buffer_.id(); 377 return picture_buffer_.id();
372 } 378 }
373 379
374 gfx::Size size() const { 380 gfx::Size size() const {
375 return picture_buffer_.size(); 381 return picture_buffer_.size();
376 } 382 }
377 383
378 // Called when the source surface |src_surface| is copied to the destination 384 // Called when the source surface |src_surface| is copied to the destination
379 // |dest_surface| 385 // |dest_surface|
380 void CopySurfaceComplete(IDirect3DSurface9* src_surface, 386 bool CopySurfaceComplete(IDirect3DSurface9* src_surface,
381 IDirect3DSurface9* dest_surface); 387 IDirect3DSurface9* dest_surface);
382 388
383 private: 389 private:
384 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer); 390 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer);
385 391
386 bool available_; 392 bool available_;
387 media::PictureBuffer picture_buffer_; 393 media::PictureBuffer picture_buffer_;
388 EGLSurface decoding_surface_; 394 EGLSurface decoding_surface_;
395
396 HANDLE texture_share_handle_;
389 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_; 397 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_;
390 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_; 398 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_;
391 399
400 base::win::ScopedComPtr<IDXGIKeyedMutex> egl_keyed_mutex_;
401 base::win::ScopedComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_;
402
403 // This is the last value that was used to release the keyed mutex.
404 uint64_t keyed_mutex_value_;
405
392 // The following |IDirect3DSurface9| interface pointers are used to hold 406 // The following |IDirect3DSurface9| interface pointers are used to hold
393 // references on the surfaces during the course of a StretchRect operation 407 // references on the surfaces during the course of a StretchRect operation
394 // to copy the source surface to the target. The references are released 408 // to copy the source surface to the target. The references are released
395 // when the StretchRect operation i.e. the copy completes. 409 // when the StretchRect operation i.e. the copy completes.
396 base::win::ScopedComPtr<IDirect3DSurface9> decoder_surface_; 410 base::win::ScopedComPtr<IDirect3DSurface9> decoder_surface_;
397 base::win::ScopedComPtr<IDirect3DSurface9> target_surface_; 411 base::win::ScopedComPtr<IDirect3DSurface9> target_surface_;
398 412
399 // This ID3D11Texture2D interface pointer is used to hold a reference to the 413 // This ID3D11Texture2D interface pointer is used to hold a reference to the
400 // decoder texture during the course of a copy operation. This reference is 414 // decoder texture during the course of a copy operation. This reference is
401 // released when the copy completes. 415 // released when the copy completes.
(...skipping 13 matching lines...) Expand all
415 const media::PictureBuffer& buffer, 429 const media::PictureBuffer& buffer,
416 EGLConfig egl_config) { 430 EGLConfig egl_config) {
417 linked_ptr<DXVAPictureBuffer> picture_buffer(new DXVAPictureBuffer(buffer)); 431 linked_ptr<DXVAPictureBuffer> picture_buffer(new DXVAPictureBuffer(buffer));
418 432
419 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 433 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
420 434
421 EGLint use_rgb = 1; 435 EGLint use_rgb = 1;
422 eglGetConfigAttrib(egl_display, egl_config, EGL_BIND_TO_TEXTURE_RGB, 436 eglGetConfigAttrib(egl_display, egl_config, EGL_BIND_TO_TEXTURE_RGB,
423 &use_rgb); 437 &use_rgb);
424 438
439 if (!picture_buffer->InitializeTexture(decoder, !!use_rgb))
440 return linked_ptr<DXVAPictureBuffer>(nullptr);
441
425 EGLint attrib_list[] = { 442 EGLint attrib_list[] = {
426 EGL_WIDTH, buffer.size().width(), 443 EGL_WIDTH, buffer.size().width(),
427 EGL_HEIGHT, buffer.size().height(), 444 EGL_HEIGHT, buffer.size().height(),
428 EGL_TEXTURE_FORMAT, use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA, 445 EGL_TEXTURE_FORMAT, use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA,
429 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, 446 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
430 EGL_NONE 447 EGL_NONE
431 }; 448 };
432 449
433 picture_buffer->decoding_surface_ = eglCreatePbufferSurface( 450 picture_buffer->decoding_surface_ = eglCreatePbufferFromClientBuffer(
434 egl_display, 451 egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
435 egl_config, 452 picture_buffer->texture_share_handle_, egl_config, attrib_list);
436 attrib_list);
437 RETURN_ON_FAILURE(picture_buffer->decoding_surface_, 453 RETURN_ON_FAILURE(picture_buffer->decoding_surface_,
438 "Failed to create surface", 454 "Failed to create surface",
439 linked_ptr<DXVAPictureBuffer>(NULL)); 455 linked_ptr<DXVAPictureBuffer>(NULL));
440 456 if (decoder.d3d11_device_ && decoder.use_keyed_mutex_) {
441 HANDLE share_handle = NULL; 457 void* keyed_mutex = nullptr;
442 EGLBoolean ret = eglQuerySurfacePointerANGLE( 458 EGLBoolean ret = eglQuerySurfacePointerANGLE(
443 egl_display, 459 egl_display, picture_buffer->decoding_surface_,
444 picture_buffer->decoding_surface_, 460 EGL_DXGI_KEYED_MUTEX_ANGLE, &keyed_mutex);
445 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, 461 RETURN_ON_FAILURE(keyed_mutex && ret == EGL_TRUE,
446 &share_handle); 462 "Failed to query ANGLE keyed mutex",
447 463 linked_ptr<DXVAPictureBuffer>(nullptr));
448 RETURN_ON_FAILURE(share_handle && ret == EGL_TRUE, 464 picture_buffer->egl_keyed_mutex_ = base::win::ScopedComPtr<IDXGIKeyedMutex>(
449 "Failed to query ANGLE surface pointer", 465 static_cast<IDXGIKeyedMutex*>(keyed_mutex));
450 linked_ptr<DXVAPictureBuffer>(NULL));
451
452 HRESULT hr = E_FAIL;
453 if (decoder.d3d11_device_) {
454 base::win::ScopedComPtr<ID3D11Resource> resource;
455 hr = decoder.d3d11_device_->OpenSharedResource(
456 share_handle,
457 __uuidof(ID3D11Resource),
458 reinterpret_cast<void**>(resource.Receive()));
459 RETURN_ON_HR_FAILURE(hr, "Failed to open shared resource",
460 linked_ptr<DXVAPictureBuffer>(NULL));
461 hr = picture_buffer->dx11_decoding_texture_.QueryFrom(resource.get());
462 } else {
463 hr = decoder.d3d9_device_ex_->CreateTexture(
464 buffer.size().width(),
465 buffer.size().height(),
466 1,
467 D3DUSAGE_RENDERTARGET,
468 use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
469 D3DPOOL_DEFAULT,
470 picture_buffer->decoding_texture_.Receive(),
471 &share_handle);
472 } 466 }
473 RETURN_ON_HR_FAILURE(hr, "Failed to create texture",
474 linked_ptr<DXVAPictureBuffer>(NULL));
475 picture_buffer->use_rgb_ = !!use_rgb; 467 picture_buffer->use_rgb_ = !!use_rgb;
476 return picture_buffer; 468 return picture_buffer;
477 } 469 }
478 470
471 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::InitializeTexture(
472 const DXVAVideoDecodeAccelerator& decoder,
473 bool use_rgb) {
474 DCHECK(!texture_share_handle_);
475 if (decoder.d3d11_device_) {
476 D3D11_TEXTURE2D_DESC desc;
477 desc.Width = picture_buffer_.size().width();
478 desc.Height = picture_buffer_.size().height();
479 desc.MipLevels = 1;
480 desc.ArraySize = 1;
481 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
482 desc.SampleDesc.Count = 1;
483 desc.SampleDesc.Quality = 0;
484 desc.Usage = D3D11_USAGE_DEFAULT;
485 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
486 desc.CPUAccessFlags = 0;
487 desc.MiscFlags = decoder.use_keyed_mutex_
488 ? D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
489 : D3D11_RESOURCE_MISC_SHARED;
490
491 HRESULT hr = decoder.d3d11_device_->CreateTexture2D(
492 &desc, nullptr, dx11_decoding_texture_.Receive());
493 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
494 if (decoder.use_keyed_mutex_) {
495 hr = dx11_keyed_mutex_.QueryFrom(dx11_decoding_texture_.get());
496 RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", false);
497 }
498
499 base::win::ScopedComPtr<IDXGIResource> resource;
500 hr = resource.QueryFrom(dx11_decoding_texture_.get());
501 DCHECK(SUCCEEDED(hr));
502 hr = resource->GetSharedHandle(&texture_share_handle_);
503 RETURN_ON_FAILURE(SUCCEEDED(hr) && texture_share_handle_,
504 "Failed to query shared handle", false);
505
506 } else {
507 HRESULT hr = E_FAIL;
508 hr = decoder.d3d9_device_ex_->CreateTexture(
509 picture_buffer_.size().width(), picture_buffer_.size().height(), 1,
510 D3DUSAGE_RENDERTARGET, use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
511 D3DPOOL_DEFAULT, decoding_texture_.Receive(), &texture_share_handle_);
512 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
513 RETURN_ON_FAILURE(texture_share_handle_, "Failed to query shared handle",
514 false);
515 }
516 return true;
517 }
518
479 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( 519 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer(
480 const media::PictureBuffer& buffer) 520 const media::PictureBuffer& buffer)
481 : available_(true), 521 : available_(true),
482 picture_buffer_(buffer), 522 picture_buffer_(buffer),
483 decoding_surface_(NULL), 523 decoding_surface_(NULL),
484 use_rgb_(true) { 524 texture_share_handle_(nullptr),
485 } 525 keyed_mutex_value_(0),
526 use_rgb_(true) {}
486 527
487 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() { 528 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() {
488 if (decoding_surface_) { 529 if (decoding_surface_) {
489 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 530 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
490 531
491 eglReleaseTexImage( 532 eglReleaseTexImage(
492 egl_display, 533 egl_display,
493 decoding_surface_, 534 decoding_surface_,
494 EGL_BACK_BUFFER); 535 EGL_BACK_BUFFER);
495 536
496 eglDestroySurface( 537 eglDestroySurface(
497 egl_display, 538 egl_display,
498 decoding_surface_); 539 decoding_surface_);
499 decoding_surface_ = NULL; 540 decoding_surface_ = NULL;
500 } 541 }
501 } 542 }
502 543
503 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() { 544 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() {
504 DCHECK(decoding_surface_); 545 DCHECK(decoding_surface_);
505 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 546 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
506 eglReleaseTexImage( 547 eglReleaseTexImage(
507 egl_display, 548 egl_display,
508 decoding_surface_, 549 decoding_surface_,
509 EGL_BACK_BUFFER); 550 EGL_BACK_BUFFER);
510 decoder_surface_.Release(); 551 decoder_surface_.Release();
511 target_surface_.Release(); 552 target_surface_.Release();
512 decoder_dx11_texture_.Release(); 553 decoder_dx11_texture_.Release();
513 set_available(true); 554 set_available(true);
555 if (egl_keyed_mutex_) {
556 HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_);
557 RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false);
558 }
559 return true;
514 } 560 }
515 561
516 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer:: 562 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
517 CopyOutputSampleDataToPictureBuffer( 563 CopyOutputSampleDataToPictureBuffer(
518 DXVAVideoDecodeAccelerator* decoder, 564 DXVAVideoDecodeAccelerator* decoder,
519 IDirect3DSurface9* dest_surface, 565 IDirect3DSurface9* dest_surface,
520 ID3D11Texture2D* dx11_texture, 566 ID3D11Texture2D* dx11_texture,
521 int input_buffer_id) { 567 int input_buffer_id) {
522 DCHECK(dest_surface || dx11_texture); 568 DCHECK(dest_surface || dx11_texture);
523 if (dx11_texture) { 569 if (dx11_texture) {
524 // Grab a reference on the decoder texture. This reference will be released 570 // Grab a reference on the decoder texture. This reference will be released
525 // when we receive a notification that the copy was completed or when the 571 // when we receive a notification that the copy was completed or when the
526 // DXVAPictureBuffer instance is destroyed. 572 // DXVAPictureBuffer instance is destroyed.
527 decoder_dx11_texture_ = dx11_texture; 573 decoder_dx11_texture_ = dx11_texture;
528 decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(), NULL, 574 decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(),
529 id(), input_buffer_id); 575 dx11_keyed_mutex_, keyed_mutex_value_, NULL, id(),
576 input_buffer_id);
530 return true; 577 return true;
531 } 578 }
532 D3DSURFACE_DESC surface_desc; 579 D3DSURFACE_DESC surface_desc;
533 HRESULT hr = dest_surface->GetDesc(&surface_desc); 580 HRESULT hr = dest_surface->GetDesc(&surface_desc);
534 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); 581 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
535 582
536 D3DSURFACE_DESC texture_desc; 583 D3DSURFACE_DESC texture_desc;
537 decoding_texture_->GetLevelDesc(0, &texture_desc); 584 decoding_texture_->GetLevelDesc(0, &texture_desc);
538 585
539 if (texture_desc.Width != surface_desc.Width || 586 if (texture_desc.Width != surface_desc.Width ||
(...skipping 19 matching lines...) Expand all
559 hr = decoding_texture_->GetSurfaceLevel(0, target_surface_.Receive()); 606 hr = decoding_texture_->GetSurfaceLevel(0, target_surface_.Receive());
560 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false); 607 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);
561 608
562 decoder_surface_ = dest_surface; 609 decoder_surface_ = dest_surface;
563 610
564 decoder->CopySurface(decoder_surface_.get(), target_surface_.get(), id(), 611 decoder->CopySurface(decoder_surface_.get(), target_surface_.get(), id(),
565 input_buffer_id); 612 input_buffer_id);
566 return true; 613 return true;
567 } 614 }
568 615
569 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete( 616 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete(
570 IDirect3DSurface9* src_surface, 617 IDirect3DSurface9* src_surface,
571 IDirect3DSurface9* dest_surface) { 618 IDirect3DSurface9* dest_surface) {
572 DCHECK(!available()); 619 DCHECK(!available());
573 620
574 GLint current_texture = 0; 621 GLint current_texture = 0;
575 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture); 622 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
576 623
577 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id()); 624 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id());
578 625
579 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 626 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
580 627
581 if (src_surface && dest_surface) { 628 if (src_surface && dest_surface) {
582 DCHECK_EQ(src_surface, decoder_surface_.get()); 629 DCHECK_EQ(src_surface, decoder_surface_.get());
583 DCHECK_EQ(dest_surface, target_surface_.get()); 630 DCHECK_EQ(dest_surface, target_surface_.get());
584 decoder_surface_.Release(); 631 decoder_surface_.Release();
585 target_surface_.Release(); 632 target_surface_.Release();
586 } else { 633 } else {
587 DCHECK(decoder_dx11_texture_.get()); 634 DCHECK(decoder_dx11_texture_.get());
588 decoder_dx11_texture_.Release(); 635 decoder_dx11_texture_.Release();
589 } 636 }
637 if (egl_keyed_mutex_) {
638 keyed_mutex_value_++;
639 HRESULT result =
640 egl_keyed_mutex_->AcquireSync(keyed_mutex_value_, kAcquireSyncWaitMs);
641 RETURN_ON_FAILURE(result == S_OK, "Could not acquire sync mutex", false);
642 }
590 643
591 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 644 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
592 eglBindTexImage( 645 eglBindTexImage(
593 egl_display, 646 egl_display,
594 decoding_surface_, 647 decoding_surface_,
595 EGL_BACK_BUFFER); 648 EGL_BACK_BUFFER);
596 649
597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 650 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
598 glBindTexture(GL_TEXTURE_2D, current_texture); 651 glBindTexture(GL_TEXTURE_2D, current_texture);
652 return true;
599 } 653 }
600 654
601 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( 655 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo(
602 int32_t buffer_id, 656 int32_t buffer_id,
603 IMFSample* sample) 657 IMFSample* sample)
604 : input_buffer_id(buffer_id), picture_buffer_id(-1) { 658 : input_buffer_id(buffer_id), picture_buffer_id(-1) {
605 output_sample.Attach(sample); 659 output_sample.Attach(sample);
606 } 660 }
607 661
608 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} 662 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {}
609 663
610 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( 664 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator(
611 const base::Callback<bool(void)>& make_context_current, 665 const base::Callback<bool(void)>& make_context_current,
612 gfx::GLContext* gl_context) 666 gfx::GLContext* gl_context)
613 : client_(NULL), 667 : client_(NULL),
614 dev_manager_reset_token_(0), 668 dev_manager_reset_token_(0),
615 dx11_dev_manager_reset_token_(0), 669 dx11_dev_manager_reset_token_(0),
616 egl_config_(NULL), 670 egl_config_(NULL),
617 state_(kUninitialized), 671 state_(kUninitialized),
618 pictures_requested_(false), 672 pictures_requested_(false),
619 inputs_before_decode_(0), 673 inputs_before_decode_(0),
620 sent_drain_message_(false), 674 sent_drain_message_(false),
621 make_context_current_(make_context_current), 675 make_context_current_(make_context_current),
622 codec_(media::kUnknownVideoCodec), 676 codec_(media::kUnknownVideoCodec),
623 decoder_thread_("DXVAVideoDecoderThread"), 677 decoder_thread_("DXVAVideoDecoderThread"),
624 pending_flush_(false), 678 pending_flush_(false),
625 use_dx11_(false), 679 use_dx11_(false),
680 use_keyed_mutex_(false),
626 dx11_video_format_converter_media_type_needs_init_(true), 681 dx11_video_format_converter_media_type_needs_init_(true),
627 gl_context_(gl_context), 682 gl_context_(gl_context),
628 using_angle_device_(false), 683 using_angle_device_(false),
629 weak_this_factory_(this) { 684 weak_this_factory_(this) {
630 weak_ptr_ = weak_this_factory_.GetWeakPtr(); 685 weak_ptr_ = weak_this_factory_.GetWeakPtr();
631 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); 686 memset(&input_stream_info_, 0, sizeof(input_stream_info_));
632 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); 687 memset(&output_stream_info_, 0, sizeof(output_stream_info_));
633 } 688 }
634 689
635 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { 690 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() {
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 it = stale_output_picture_buffers_.find(picture_buffer_id); 1014 it = stale_output_picture_buffers_.find(picture_buffer_id);
960 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), 1015 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
961 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); 1016 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
962 main_thread_task_runner_->PostTask( 1017 main_thread_task_runner_->PostTask(
963 FROM_HERE, 1018 FROM_HERE,
964 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, 1019 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
965 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); 1020 weak_this_factory_.GetWeakPtr(), picture_buffer_id));
966 return; 1021 return;
967 } 1022 }
968 1023
969 it->second->ReusePictureBuffer(); 1024 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(),
1025 "Failed to reuse picture buffer",
1026 PLATFORM_FAILURE, );
1027
970 ProcessPendingSamples(); 1028 ProcessPendingSamples();
971 if (pending_flush_) { 1029 if (pending_flush_) {
972 decoder_thread_task_runner_->PostTask( 1030 decoder_thread_task_runner_->PostTask(
973 FROM_HERE, 1031 FROM_HERE,
974 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, 1032 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
975 base::Unretained(this))); 1033 base::Unretained(this)));
976 } 1034 }
977 } 1035 }
978 1036
979 void DXVAVideoDecodeAccelerator::Flush() { 1037 void DXVAVideoDecodeAccelerator::Flush() {
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1236 // this. This should always be true for Windows 8+. 1294 // this. This should always be true for Windows 8+.
1237 // 3. ANGLE is using DX11. 1295 // 3. ANGLE is using DX11.
1238 DCHECK(gl_context_); 1296 DCHECK(gl_context_);
1239 if (create_dxgi_device_manager_ && 1297 if (create_dxgi_device_manager_ &&
1240 (gl_context_->GetGLRenderer().find("Direct3D11") != 1298 (gl_context_->GetGLRenderer().find("Direct3D11") !=
1241 std::string::npos)) { 1299 std::string::npos)) {
1242 UINT32 dx11_aware = 0; 1300 UINT32 dx11_aware = 0;
1243 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware); 1301 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware);
1244 use_dx11_ = !!dx11_aware; 1302 use_dx11_ = !!dx11_aware;
1245 } 1303 }
1304
1305 use_keyed_mutex_ =
1306 use_dx11_ && gfx::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex");
1307
1246 return true; 1308 return true;
1247 } 1309 }
1248 1310
1249 bool DXVAVideoDecodeAccelerator::SetDecoderMediaTypes() { 1311 bool DXVAVideoDecodeAccelerator::SetDecoderMediaTypes() {
1250 RETURN_ON_FAILURE(SetDecoderInputMediaType(), 1312 RETURN_ON_FAILURE(SetDecoderInputMediaType(),
1251 "Failed to set decoder input media type", false); 1313 "Failed to set decoder input media type", false);
1252 return SetDecoderOutputMediaType(MFVideoFormat_NV12); 1314 return SetDecoderOutputMediaType(MFVideoFormat_NV12);
1253 } 1315 }
1254 1316
1255 bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() { 1317 bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() {
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after
1933 // was a Reset operation which dropped the output frame. 1995 // was a Reset operation which dropped the output frame.
1934 DXVAPictureBuffer* picture_buffer = it->second.get(); 1996 DXVAPictureBuffer* picture_buffer = it->second.get();
1935 if (picture_buffer->available()) 1997 if (picture_buffer->available())
1936 return; 1998 return;
1937 1999
1938 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), 2000 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
1939 "Failed to make context current", PLATFORM_FAILURE,); 2001 "Failed to make context current", PLATFORM_FAILURE,);
1940 2002
1941 DCHECK(!output_picture_buffers_.empty()); 2003 DCHECK(!output_picture_buffers_.empty());
1942 2004
1943 picture_buffer->CopySurfaceComplete(src_surface, 2005 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface);
1944 dest_surface); 2006 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface",
2007 PLATFORM_FAILURE, );
1945 2008
1946 NotifyPictureReady(picture_buffer->id(), input_buffer_id); 2009 NotifyPictureReady(picture_buffer->id(), input_buffer_id);
1947 2010
1948 { 2011 {
1949 base::AutoLock lock(decoder_lock_); 2012 base::AutoLock lock(decoder_lock_);
1950 if (!pending_output_samples_.empty()) 2013 if (!pending_output_samples_.empty())
1951 pending_output_samples_.pop_front(); 2014 pending_output_samples_.pop_front();
1952 } 2015 }
1953 2016
1954 if (pending_flush_) { 2017 if (pending_flush_) {
1955 decoder_thread_task_runner_->PostTask( 2018 decoder_thread_task_runner_->PostTask(
1956 FROM_HERE, 2019 FROM_HERE,
1957 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, 2020 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
1958 base::Unretained(this))); 2021 base::Unretained(this)));
1959 return; 2022 return;
1960 } 2023 }
1961 decoder_thread_task_runner_->PostTask( 2024 decoder_thread_task_runner_->PostTask(
1962 FROM_HERE, 2025 FROM_HERE,
1963 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, 2026 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
1964 base::Unretained(this))); 2027 base::Unretained(this)));
1965 } 2028 }
1966 2029
1967 void DXVAVideoDecodeAccelerator::CopyTexture(ID3D11Texture2D* src_texture, 2030 void DXVAVideoDecodeAccelerator::CopyTexture(
1968 ID3D11Texture2D* dest_texture, 2031 ID3D11Texture2D* src_texture,
1969 IMFSample* video_frame, 2032 ID3D11Texture2D* dest_texture,
1970 int picture_buffer_id, 2033 base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex,
1971 int input_buffer_id) { 2034 uint64_t keyed_mutex_value,
2035 IMFSample* video_frame,
2036 int picture_buffer_id,
2037 int input_buffer_id) {
1972 HRESULT hr = E_FAIL; 2038 HRESULT hr = E_FAIL;
1973 2039
1974 DCHECK(use_dx11_); 2040 DCHECK(use_dx11_);
1975 2041
1976 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { 2042 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) {
1977 // The media foundation H.264 decoder outputs YUV12 textures which we 2043 // The media foundation H.264 decoder outputs YUV12 textures which we
1978 // cannot copy into ANGLE as they expect ARGB textures. In D3D land 2044 // cannot copy into ANGLE as they expect ARGB textures. In D3D land
1979 // the StretchRect API in the IDirect3DDevice9Ex interface did the color 2045 // the StretchRect API in the IDirect3DDevice9Ex interface did the color
1980 // space conversion for us. Sadly in DX11 land the API does not provide 2046 // space conversion for us. Sadly in DX11 land the API does not provide
1981 // a straightforward way to do this. 2047 // a straightforward way to do this.
(...skipping 16 matching lines...) Expand all
1998 2064
1999 // The input to the video processor is the output sample. 2065 // The input to the video processor is the output sample.
2000 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; 2066 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion;
2001 { 2067 {
2002 base::AutoLock lock(decoder_lock_); 2068 base::AutoLock lock(decoder_lock_);
2003 PendingSampleInfo& sample_info = pending_output_samples_.front(); 2069 PendingSampleInfo& sample_info = pending_output_samples_.front();
2004 input_sample_for_conversion = sample_info.output_sample; 2070 input_sample_for_conversion = sample_info.output_sample;
2005 } 2071 }
2006 2072
2007 decoder_thread_task_runner_->PostTask( 2073 decoder_thread_task_runner_->PostTask(
2008 FROM_HERE, 2074 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture,
2009 base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture, 2075 base::Unretained(this), src_texture, dest_texture,
2010 base::Unretained(this), 2076 dest_keyed_mutex, keyed_mutex_value,
2011 src_texture, 2077 input_sample_for_conversion.Detach(),
2012 dest_texture, 2078 picture_buffer_id, input_buffer_id));
2013 input_sample_for_conversion.Detach(),
2014 picture_buffer_id,
2015 input_buffer_id));
2016 return; 2079 return;
2017 } 2080 }
2018 2081
2019 DCHECK(video_frame); 2082 DCHECK(video_frame);
2020 2083
2021 base::win::ScopedComPtr<IMFSample> input_sample; 2084 base::win::ScopedComPtr<IMFSample> input_sample;
2022 input_sample.Attach(video_frame); 2085 input_sample.Attach(video_frame);
2023 2086
2024 DCHECK(video_format_converter_mft_.get()); 2087 DCHECK(video_format_converter_mft_.get());
2025 2088
2089 if (dest_keyed_mutex) {
2090 HRESULT hr =
2091 dest_keyed_mutex->AcquireSync(keyed_mutex_value, kAcquireSyncWaitMs);
2092 RETURN_AND_NOTIFY_ON_FAILURE(
2093 hr == S_OK, "D3D11 failed to acquire keyed mutex for texture.",
2094 PLATFORM_FAILURE, );
2095 }
2026 // The video processor MFT requires output samples to be allocated by the 2096 // The video processor MFT requires output samples to be allocated by the
2027 // caller. We create a sample with a buffer backed with the ID3D11Texture2D 2097 // caller. We create a sample with a buffer backed with the ID3D11Texture2D
2028 // interface exposed by ANGLE. This works nicely as this ensures that the 2098 // interface exposed by ANGLE. This works nicely as this ensures that the
2029 // video processor coverts the color space of the output frame and copies 2099 // video processor coverts the color space of the output frame and copies
2030 // the result into the ANGLE texture. 2100 // the result into the ANGLE texture.
2031 base::win::ScopedComPtr<IMFSample> output_sample; 2101 base::win::ScopedComPtr<IMFSample> output_sample;
2032 hr = MFCreateSample(output_sample.Receive()); 2102 hr = MFCreateSample(output_sample.Receive());
2033 if (FAILED(hr)) { 2103 if (FAILED(hr)) {
2034 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2104 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2035 "Failed to create output sample.", PLATFORM_FAILURE,); 2105 "Failed to create output sample.", PLATFORM_FAILURE,);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2070 if (FAILED(hr)) { 2140 if (FAILED(hr)) {
2071 base::debug::Alias(&hr); 2141 base::debug::Alias(&hr);
2072 // TODO(ananta) 2142 // TODO(ananta)
2073 // Remove this CHECK when the change to use DX11 for H/W decoding 2143 // Remove this CHECK when the change to use DX11 for H/W decoding
2074 // stablizes. 2144 // stablizes.
2075 CHECK(false); 2145 CHECK(false);
2076 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2146 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2077 "Failed to convert output sample format.", PLATFORM_FAILURE,); 2147 "Failed to convert output sample format.", PLATFORM_FAILURE,);
2078 } 2148 }
2079 2149
2080 d3d11_device_context_->Flush(); 2150 if (dest_keyed_mutex) {
2081 d3d11_device_context_->End(d3d11_query_.get()); 2151 HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1);
2152 RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.",
2153 PLATFORM_FAILURE, );
2082 2154
2083 decoder_thread_task_runner_->PostDelayedTask( 2155 main_thread_task_runner_->PostTask(
2084 FROM_HERE, 2156 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
2085 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 2157 weak_this_factory_.GetWeakPtr(), nullptr, nullptr,
2086 base::Unretained(this), 0, 2158 picture_buffer_id, input_buffer_id));
2087 reinterpret_cast<IDirect3DSurface9*>(NULL), 2159 } else {
2088 reinterpret_cast<IDirect3DSurface9*>(NULL), 2160 d3d11_device_context_->Flush();
2089 picture_buffer_id, input_buffer_id), 2161 d3d11_device_context_->End(d3d11_query_.get());
2090 base::TimeDelta::FromMilliseconds( 2162
2091 kFlushDecoderSurfaceTimeoutMs)); 2163 decoder_thread_task_runner_->PostDelayedTask(
2164 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
2165 base::Unretained(this), 0,
2166 reinterpret_cast<IDirect3DSurface9*>(NULL),
2167 reinterpret_cast<IDirect3DSurface9*>(NULL),
2168 picture_buffer_id, input_buffer_id),
2169 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
2170 }
2092 } 2171 }
2093 2172
2094 void DXVAVideoDecodeAccelerator::FlushDecoder( 2173 void DXVAVideoDecodeAccelerator::FlushDecoder(
2095 int iterations, 2174 int iterations,
2096 IDirect3DSurface9* src_surface, 2175 IDirect3DSurface9* src_surface,
2097 IDirect3DSurface9* dest_surface, 2176 IDirect3DSurface9* dest_surface,
2098 int picture_buffer_id, 2177 int picture_buffer_id,
2099 int input_buffer_id) { 2178 int input_buffer_id) {
2100 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 2179 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2101 2180
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
2298 } 2377 }
2299 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); 2378 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false);
2300 return true; 2379 return true;
2301 } 2380 }
2302 media_type.Release(); 2381 media_type.Release();
2303 } 2382 }
2304 return false; 2383 return false;
2305 } 2384 }
2306 2385
2307 } // namespace content 2386 } // 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