Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "media/gpu/dxva_picture_buffer_win.h" | 5 #include "media/gpu/dxva_picture_buffer_win.h" |
| 6 | 6 |
| 7 #include "media/gpu/dxva_video_decode_accelerator_win.h" | 7 #include "media/gpu/dxva_video_decode_accelerator_win.h" |
| 8 #include "third_party/angle/include/EGL/egl.h" | 8 #include "third_party/angle/include/EGL/egl.h" |
| 9 #include "third_party/angle/include/EGL/eglext.h" | 9 #include "third_party/angle/include/EGL/eglext.h" |
| 10 #include "ui/gl/gl_bindings.h" | 10 #include "ui/gl/gl_bindings.h" |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 | 25 |
| 26 // These GLImage subclasses are just used to hold references to the underlying | 26 // These GLImage subclasses are just used to hold references to the underlying |
| 27 // image content so it can be destroyed when the textures are. | 27 // image content so it can be destroyed when the textures are. |
| 28 class DummyGLImage : public gl::GLImage { | 28 class DummyGLImage : public gl::GLImage { |
| 29 public: | 29 public: |
| 30 DummyGLImage(const gfx::Size& size) : size_(size) {} | 30 DummyGLImage(const gfx::Size& size) : size_(size) {} |
| 31 | 31 |
| 32 // gl::GLImage implementation. | 32 // gl::GLImage implementation. |
| 33 gfx::Size GetSize() override { return size_; } | 33 gfx::Size GetSize() override { return size_; } |
| 34 unsigned GetInternalFormat() override { return GL_BGRA_EXT; } | 34 unsigned GetInternalFormat() override { return GL_BGRA_EXT; } |
| 35 bool BindTexImage(unsigned target) override { return false; } | 35 bool BindTexImage(unsigned target) override { return true; } |
|
sandersd (OOO until July 31)
2017/05/23 23:23:31
I'd like a comment to explain why this makes sense
| |
| 36 void ReleaseTexImage(unsigned target) override {} | 36 void ReleaseTexImage(unsigned target) override {} |
| 37 bool CopyTexImage(unsigned target) override { return false; } | 37 bool CopyTexImage(unsigned target) override { return false; } |
| 38 bool CopyTexSubImage(unsigned target, | 38 bool CopyTexSubImage(unsigned target, |
| 39 const gfx::Point& offset, | 39 const gfx::Point& offset, |
| 40 const gfx::Rect& rect) override { | 40 const gfx::Rect& rect) override { |
| 41 return false; | 41 return false; |
| 42 } | 42 } |
| 43 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, | 43 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
| 44 int z_order, | 44 int z_order, |
| 45 gfx::OverlayTransform transform, | 45 gfx::OverlayTransform transform, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 // The keyed mutex should always be released before the other thread | 95 // The keyed mutex should always be released before the other thread |
| 96 // attempts to acquire it, so AcquireSync should always return immediately. | 96 // attempts to acquire it, so AcquireSync should always return immediately. |
| 97 kAcquireSyncWaitMs = 0, | 97 kAcquireSyncWaitMs = 0, |
| 98 }; | 98 }; |
| 99 | 99 |
| 100 // static | 100 // static |
| 101 linked_ptr<DXVAPictureBuffer> DXVAPictureBuffer::Create( | 101 linked_ptr<DXVAPictureBuffer> DXVAPictureBuffer::Create( |
| 102 const DXVAVideoDecodeAccelerator& decoder, | 102 const DXVAVideoDecodeAccelerator& decoder, |
| 103 const PictureBuffer& buffer, | 103 const PictureBuffer& buffer, |
| 104 EGLConfig egl_config) { | 104 EGLConfig egl_config) { |
| 105 if (decoder.share_nv12_textures_) { | 105 switch (decoder.GetPictureBufferMechanism()) { |
| 106 linked_ptr<EGLStreamPictureBuffer> picture_buffer( | 106 case DXVAVideoDecodeAccelerator::PictureBufferMechanism::BIND: { |
| 107 new EGLStreamPictureBuffer(buffer)); | 107 linked_ptr<EGLStreamPictureBuffer> picture_buffer( |
| 108 if (!picture_buffer->Initialize()) | 108 new EGLStreamPictureBuffer(buffer)); |
| 109 return linked_ptr<DXVAPictureBuffer>(nullptr); | 109 if (!picture_buffer->Initialize()) |
| 110 return linked_ptr<DXVAPictureBuffer>(nullptr); | |
| 110 | 111 |
| 111 return picture_buffer; | 112 return picture_buffer; |
| 113 } | |
| 114 case DXVAVideoDecodeAccelerator::PictureBufferMechanism:: | |
| 115 DELAYED_COPY_TO_NV12: { | |
| 116 linked_ptr<EGLStreamDelayedCopyPictureBuffer> picture_buffer( | |
| 117 new EGLStreamDelayedCopyPictureBuffer(buffer)); | |
| 118 if (!picture_buffer->Initialize(decoder)) | |
| 119 return linked_ptr<DXVAPictureBuffer>(nullptr); | |
| 120 | |
| 121 return picture_buffer; | |
| 122 } | |
| 123 case DXVAVideoDecodeAccelerator::PictureBufferMechanism::COPY_TO_NV12: { | |
| 124 linked_ptr<EGLStreamCopyPictureBuffer> picture_buffer( | |
| 125 new EGLStreamCopyPictureBuffer(buffer)); | |
| 126 if (!picture_buffer->Initialize(decoder)) | |
| 127 return linked_ptr<DXVAPictureBuffer>(nullptr); | |
| 128 | |
| 129 return picture_buffer; | |
| 130 } | |
| 131 case DXVAVideoDecodeAccelerator::PictureBufferMechanism::COPY_TO_RGB: { | |
| 132 linked_ptr<PbufferPictureBuffer> picture_buffer( | |
| 133 new PbufferPictureBuffer(buffer)); | |
| 134 | |
| 135 if (!picture_buffer->Initialize(decoder, egl_config)) | |
| 136 return linked_ptr<DXVAPictureBuffer>(nullptr); | |
| 137 | |
| 138 return picture_buffer; | |
| 139 } | |
| 112 } | 140 } |
| 113 if (decoder.copy_nv12_textures_) { | 141 NOTREACHED(); |
| 114 linked_ptr<EGLStreamCopyPictureBuffer> picture_buffer( | 142 return linked_ptr<DXVAPictureBuffer>(nullptr); |
| 115 new EGLStreamCopyPictureBuffer(buffer)); | |
| 116 if (!picture_buffer->Initialize(decoder)) | |
| 117 return linked_ptr<DXVAPictureBuffer>(nullptr); | |
| 118 | |
| 119 return picture_buffer; | |
| 120 } | |
| 121 linked_ptr<PbufferPictureBuffer> picture_buffer( | |
| 122 new PbufferPictureBuffer(buffer)); | |
| 123 | |
| 124 if (!picture_buffer->Initialize(decoder, egl_config)) | |
| 125 return linked_ptr<DXVAPictureBuffer>(nullptr); | |
| 126 | |
| 127 return picture_buffer; | |
| 128 } | 143 } |
| 129 | 144 |
| 130 DXVAPictureBuffer::~DXVAPictureBuffer() {} | 145 DXVAPictureBuffer::~DXVAPictureBuffer() {} |
| 131 | 146 |
| 132 void DXVAPictureBuffer::ResetReuseFence() { | 147 void DXVAPictureBuffer::ResetReuseFence() { |
| 133 NOTREACHED(); | 148 NOTREACHED(); |
| 134 } | 149 } |
| 135 | 150 |
| 136 bool DXVAPictureBuffer::CopyOutputSampleDataToPictureBuffer( | 151 bool DXVAPictureBuffer::CopyOutputSampleDataToPictureBuffer( |
| 137 DXVAVideoDecodeAccelerator* decoder, | 152 DXVAVideoDecodeAccelerator* decoder, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 154 bool DXVAPictureBuffer::CopySurfaceComplete(IDirect3DSurface9* src_surface, | 169 bool DXVAPictureBuffer::CopySurfaceComplete(IDirect3DSurface9* src_surface, |
| 155 IDirect3DSurface9* dest_surface) { | 170 IDirect3DSurface9* dest_surface) { |
| 156 NOTREACHED(); | 171 NOTREACHED(); |
| 157 return false; | 172 return false; |
| 158 } | 173 } |
| 159 | 174 |
| 160 DXVAPictureBuffer::DXVAPictureBuffer(const PictureBuffer& buffer) | 175 DXVAPictureBuffer::DXVAPictureBuffer(const PictureBuffer& buffer) |
| 161 : picture_buffer_(buffer) {} | 176 : picture_buffer_(buffer) {} |
| 162 | 177 |
| 163 bool DXVAPictureBuffer::BindSampleToTexture( | 178 bool DXVAPictureBuffer::BindSampleToTexture( |
| 179 DXVAVideoDecodeAccelerator* decoder, | |
| 164 base::win::ScopedComPtr<IMFSample> sample) { | 180 base::win::ScopedComPtr<IMFSample> sample) { |
| 165 NOTREACHED(); | 181 NOTREACHED(); |
| 166 return false; | 182 return false; |
| 167 } | 183 } |
| 168 | 184 |
| 169 bool PbufferPictureBuffer::Initialize(const DXVAVideoDecodeAccelerator& decoder, | 185 bool PbufferPictureBuffer::Initialize(const DXVAVideoDecodeAccelerator& decoder, |
| 170 EGLConfig egl_config) { | 186 EGLConfig egl_config) { |
| 171 RETURN_ON_FAILURE(!picture_buffer_.service_texture_ids().empty(), | 187 RETURN_ON_FAILURE(!picture_buffer_.service_texture_ids().empty(), |
| 172 "No service texture ids provided", false); | 188 "No service texture ids provided", false); |
| 173 | 189 |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 | 384 |
| 369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 370 glBindTexture(GL_TEXTURE_2D, current_texture); | 386 glBindTexture(GL_TEXTURE_2D, current_texture); |
| 371 return true; | 387 return true; |
| 372 } | 388 } |
| 373 | 389 |
| 374 bool PbufferPictureBuffer::AllowOverlay() const { | 390 bool PbufferPictureBuffer::AllowOverlay() const { |
| 375 return false; | 391 return false; |
| 376 } | 392 } |
| 377 | 393 |
| 394 bool PbufferPictureBuffer::CanBindSamples() const { | |
| 395 return false; | |
| 396 } | |
| 397 | |
| 378 PbufferPictureBuffer::PbufferPictureBuffer(const PictureBuffer& buffer) | 398 PbufferPictureBuffer::PbufferPictureBuffer(const PictureBuffer& buffer) |
| 379 : DXVAPictureBuffer(buffer), | 399 : DXVAPictureBuffer(buffer), |
| 380 decoding_surface_(NULL), | 400 decoding_surface_(NULL), |
| 381 texture_share_handle_(nullptr), | 401 texture_share_handle_(nullptr), |
| 382 keyed_mutex_value_(0), | 402 keyed_mutex_value_(0), |
| 383 use_rgb_(true) {} | 403 use_rgb_(true) {} |
| 384 | 404 |
| 385 PbufferPictureBuffer::~PbufferPictureBuffer() { | 405 PbufferPictureBuffer::~PbufferPictureBuffer() { |
| 386 // decoding_surface_ will be deleted by gl_image_. | 406 // decoding_surface_ will be deleted by gl_image_. |
| 387 } | 407 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 467 } | 487 } |
| 468 if (current_d3d_sample_) { | 488 if (current_d3d_sample_) { |
| 469 dx11_decoding_texture_.Reset(); | 489 dx11_decoding_texture_.Reset(); |
| 470 current_d3d_sample_.Reset(); | 490 current_d3d_sample_.Reset(); |
| 471 } | 491 } |
| 472 state_ = UNUSED; | 492 state_ = UNUSED; |
| 473 return true; | 493 return true; |
| 474 } | 494 } |
| 475 | 495 |
| 476 bool EGLStreamPictureBuffer::BindSampleToTexture( | 496 bool EGLStreamPictureBuffer::BindSampleToTexture( |
| 497 DXVAVideoDecodeAccelerator* decoder, | |
| 477 base::win::ScopedComPtr<IMFSample> sample) { | 498 base::win::ScopedComPtr<IMFSample> sample) { |
| 478 DCHECK_EQ(BOUND, state_); | 499 DCHECK_EQ(BOUND, state_); |
| 479 state_ = IN_CLIENT; | 500 state_ = IN_CLIENT; |
| 480 | 501 |
| 481 current_d3d_sample_ = sample; | 502 current_d3d_sample_ = sample; |
| 482 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); | 503 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); |
| 483 | 504 |
| 484 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; | 505 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; |
| 485 HRESULT hr = | 506 HRESULT hr = |
| 486 current_d3d_sample_->GetBufferByIndex(0, output_buffer.GetAddressOf()); | 507 current_d3d_sample_->GetBufferByIndex(0, output_buffer.GetAddressOf()); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 511 DCHECK(gl_image_dxgi); | 532 DCHECK(gl_image_dxgi); |
| 512 | 533 |
| 513 gl_image_dxgi->SetTexture(dx11_decoding_texture_, subresource); | 534 gl_image_dxgi->SetTexture(dx11_decoding_texture_, subresource); |
| 514 return true; | 535 return true; |
| 515 } | 536 } |
| 516 | 537 |
| 517 bool EGLStreamPictureBuffer::AllowOverlay() const { | 538 bool EGLStreamPictureBuffer::AllowOverlay() const { |
| 518 return true; | 539 return true; |
| 519 } | 540 } |
| 520 | 541 |
| 542 bool EGLStreamPictureBuffer::CanBindSamples() const { | |
| 543 return true; | |
| 544 } | |
| 545 | |
| 546 EGLStreamDelayedCopyPictureBuffer::EGLStreamDelayedCopyPictureBuffer( | |
| 547 const PictureBuffer& buffer) | |
| 548 : DXVAPictureBuffer(buffer), stream_(nullptr) {} | |
| 549 | |
| 550 EGLStreamDelayedCopyPictureBuffer::~EGLStreamDelayedCopyPictureBuffer() { | |
| 551 // stream_ will be deleted by gl_image_. | |
| 552 } | |
| 553 | |
| 554 bool EGLStreamDelayedCopyPictureBuffer::Initialize( | |
| 555 const DXVAVideoDecodeAccelerator& decoder) { | |
| 556 RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2, | |
| 557 "Not enough texture ids provided", false); | |
| 558 | |
| 559 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); | |
| 560 const EGLint stream_attributes[] = { | |
| 561 EGL_CONSUMER_LATENCY_USEC_KHR, | |
| 562 0, | |
| 563 EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, | |
| 564 0, | |
| 565 EGL_NONE, | |
| 566 }; | |
| 567 stream_ = eglCreateStreamKHR(egl_display, stream_attributes); | |
| 568 RETURN_ON_FAILURE(!!stream_, "Could not create stream", false); | |
| 569 gl::ScopedActiveTexture texture0(GL_TEXTURE0); | |
| 570 gl::ScopedTextureBinder texture0_binder( | |
| 571 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]); | |
| 572 gl::ScopedActiveTexture texture1(GL_TEXTURE1); | |
| 573 gl::ScopedTextureBinder texture1_binder( | |
| 574 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[1]); | |
| 575 | |
| 576 EGLAttrib consumer_attributes[] = { | |
| 577 EGL_COLOR_BUFFER_TYPE, | |
| 578 EGL_YUV_BUFFER_EXT, | |
| 579 EGL_YUV_NUMBER_OF_PLANES_EXT, | |
| 580 2, | |
| 581 EGL_YUV_PLANE0_TEXTURE_UNIT_NV, | |
| 582 0, | |
| 583 EGL_YUV_PLANE1_TEXTURE_UNIT_NV, | |
| 584 1, | |
| 585 EGL_NONE, | |
| 586 }; | |
| 587 EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV( | |
| 588 egl_display, stream_, consumer_attributes); | |
| 589 RETURN_ON_FAILURE(result, "Could not set stream consumer", false); | |
| 590 | |
| 591 EGLAttrib producer_attributes[] = { | |
| 592 EGL_NONE, | |
| 593 }; | |
| 594 | |
| 595 result = eglCreateStreamProducerD3DTextureNV12ANGLE(egl_display, stream_, | |
| 596 producer_attributes); | |
| 597 RETURN_ON_FAILURE(result, "Could not create stream producer", false); | |
| 598 scoped_refptr<gl::CopyingGLImageDXGI> copying_image_ = | |
| 599 make_scoped_refptr(new gl::CopyingGLImageDXGI( | |
| 600 base::win::ScopedComPtr<ID3D11Device>(decoder.D3D11Device()), size(), | |
| 601 stream_)); | |
| 602 gl_image_ = copying_image_; | |
| 603 return copying_image_->Initialize(); | |
| 604 } | |
| 605 | |
| 606 bool EGLStreamDelayedCopyPictureBuffer::ReusePictureBuffer() { | |
| 607 DCHECK_NE(UNUSED, state_); | |
| 608 | |
| 609 static_cast<gl::CopyingGLImageDXGI*>(gl_image_.get())->UnbindFromTexture(); | |
| 610 if (current_d3d_sample_) { | |
| 611 dx11_decoding_texture_.Reset(); | |
| 612 current_d3d_sample_.Reset(); | |
| 613 } | |
| 614 state_ = UNUSED; | |
| 615 return true; | |
| 616 } | |
| 617 | |
| 618 bool EGLStreamDelayedCopyPictureBuffer::BindSampleToTexture( | |
| 619 DXVAVideoDecodeAccelerator* decoder, | |
| 620 base::win::ScopedComPtr<IMFSample> sample) { | |
| 621 DCHECK_EQ(BOUND, state_); | |
| 622 state_ = IN_CLIENT; | |
| 623 | |
| 624 current_d3d_sample_ = sample; | |
| 625 | |
| 626 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; | |
| 627 HRESULT hr = | |
| 628 current_d3d_sample_->GetBufferByIndex(0, output_buffer.GetAddressOf()); | |
| 629 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false); | |
| 630 | |
| 631 base::win::ScopedComPtr<IMFDXGIBuffer> dxgi_buffer; | |
| 632 hr = output_buffer.CopyTo(dxgi_buffer.GetAddressOf()); | |
| 633 RETURN_ON_HR_FAILURE(hr, "Failed to get DXGIBuffer from output sample", | |
| 634 false); | |
| 635 hr = dxgi_buffer->GetResource( | |
| 636 IID_PPV_ARGS(dx11_decoding_texture_.GetAddressOf())); | |
| 637 RETURN_ON_HR_FAILURE(hr, "Failed to get texture from output sample", false); | |
| 638 UINT subresource; | |
| 639 dxgi_buffer->GetSubresourceIndex(&subresource); | |
| 640 if (!decoder->InitializeID3D11VideoProcessor(size().width(), size().height(), | |
| 641 color_space_)) | |
| 642 return false; | |
| 643 | |
| 644 DCHECK(decoder->d3d11_processor_); | |
| 645 DCHECK(decoder->enumerator_); | |
| 646 | |
| 647 gl::GLImageDXGI* gl_image_dxgi = | |
| 648 gl::GLImageDXGI::FromGLImage(gl_image_.get()); | |
| 649 DCHECK(gl_image_dxgi); | |
| 650 | |
| 651 gl_image_dxgi->SetTexture(dx11_decoding_texture_, subresource); | |
| 652 return static_cast<gl::CopyingGLImageDXGI*>(gl_image_dxgi) | |
| 653 ->InitializeVideoProcessor(decoder->d3d11_processor_, | |
| 654 decoder->enumerator_); | |
| 655 } | |
| 656 | |
| 657 bool EGLStreamDelayedCopyPictureBuffer::AllowOverlay() const { | |
| 658 return true; | |
| 659 } | |
| 660 | |
| 661 bool EGLStreamDelayedCopyPictureBuffer::CanBindSamples() const { | |
| 662 return true; | |
| 663 } | |
| 664 | |
| 521 EGLStreamCopyPictureBuffer::EGLStreamCopyPictureBuffer( | 665 EGLStreamCopyPictureBuffer::EGLStreamCopyPictureBuffer( |
| 522 const PictureBuffer& buffer) | 666 const PictureBuffer& buffer) |
| 523 : DXVAPictureBuffer(buffer), stream_(nullptr) {} | 667 : DXVAPictureBuffer(buffer), stream_(nullptr) {} |
| 524 | 668 |
| 525 EGLStreamCopyPictureBuffer::~EGLStreamCopyPictureBuffer() { | 669 EGLStreamCopyPictureBuffer::~EGLStreamCopyPictureBuffer() { |
| 526 // stream_ will be deleted by gl_image_. | 670 // stream_ will be deleted by gl_image_. |
| 527 } | 671 } |
| 528 | 672 |
| 529 bool EGLStreamCopyPictureBuffer::Initialize( | 673 bool EGLStreamCopyPictureBuffer::Initialize( |
| 530 const DXVAVideoDecodeAccelerator& decoder) { | 674 const DXVAVideoDecodeAccelerator& decoder) { |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 EGLBoolean result = eglStreamConsumerReleaseKHR(egl_display, stream_); | 822 EGLBoolean result = eglStreamConsumerReleaseKHR(egl_display, stream_); |
| 679 RETURN_ON_FAILURE(result, "Could not release stream", false); | 823 RETURN_ON_FAILURE(result, "Could not release stream", false); |
| 680 } | 824 } |
| 681 return true; | 825 return true; |
| 682 } | 826 } |
| 683 | 827 |
| 684 bool EGLStreamCopyPictureBuffer::AllowOverlay() const { | 828 bool EGLStreamCopyPictureBuffer::AllowOverlay() const { |
| 685 return true; | 829 return true; |
| 686 } | 830 } |
| 687 | 831 |
| 832 bool EGLStreamCopyPictureBuffer::CanBindSamples() const { | |
| 833 return false; | |
| 834 } | |
| 835 | |
| 688 } // namespace media | 836 } // namespace media |
| OLD | NEW |