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 |