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

Side by Side Diff: media/gpu/dxva_picture_buffer_win.cc

Issue 2859723002: Copy NV12 picture buffers on demand on the main thread. (Closed)
Patch Set: share video processors Created 3 years, 7 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
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698