| Index: media/gpu/dxva_picture_buffer_win.cc
|
| diff --git a/media/gpu/dxva_picture_buffer_win.cc b/media/gpu/dxva_picture_buffer_win.cc
|
| index 9aa8ea54ab80f47865d2253ac1a875c91ae0941a..d7df906d922f5184bd97c93d34db7270097154fd 100644
|
| --- a/media/gpu/dxva_picture_buffer_win.cc
|
| +++ b/media/gpu/dxva_picture_buffer_win.cc
|
| @@ -32,7 +32,9 @@ class DummyGLImage : public gl::GLImage {
|
| // gl::GLImage implementation.
|
| gfx::Size GetSize() override { return size_; }
|
| unsigned GetInternalFormat() override { return GL_BGRA_EXT; }
|
| - bool BindTexImage(unsigned target) override { return false; }
|
| + // PbufferPictureBuffer::CopySurfaceComplete does the actual binding, so
|
| + // this doesn't do anything and always succeeds.
|
| + bool BindTexImage(unsigned target) override { return true; }
|
| void ReleaseTexImage(unsigned target) override {}
|
| bool CopyTexImage(unsigned target) override { return false; }
|
| bool CopyTexSubImage(unsigned target,
|
| @@ -102,29 +104,44 @@ linked_ptr<DXVAPictureBuffer> DXVAPictureBuffer::Create(
|
| const DXVAVideoDecodeAccelerator& decoder,
|
| const PictureBuffer& buffer,
|
| EGLConfig egl_config) {
|
| - if (decoder.share_nv12_textures_) {
|
| - linked_ptr<EGLStreamPictureBuffer> picture_buffer(
|
| - new EGLStreamPictureBuffer(buffer));
|
| - if (!picture_buffer->Initialize())
|
| - return linked_ptr<DXVAPictureBuffer>(nullptr);
|
| -
|
| - return picture_buffer;
|
| - }
|
| - if (decoder.copy_nv12_textures_) {
|
| - linked_ptr<EGLStreamCopyPictureBuffer> picture_buffer(
|
| - new EGLStreamCopyPictureBuffer(buffer));
|
| - if (!picture_buffer->Initialize(decoder))
|
| - return linked_ptr<DXVAPictureBuffer>(nullptr);
|
| + switch (decoder.GetPictureBufferMechanism()) {
|
| + case DXVAVideoDecodeAccelerator::PictureBufferMechanism::BIND: {
|
| + linked_ptr<EGLStreamPictureBuffer> picture_buffer(
|
| + new EGLStreamPictureBuffer(buffer));
|
| + if (!picture_buffer->Initialize())
|
| + return linked_ptr<DXVAPictureBuffer>(nullptr);
|
| +
|
| + return picture_buffer;
|
| + }
|
| + case DXVAVideoDecodeAccelerator::PictureBufferMechanism::
|
| + DELAYED_COPY_TO_NV12: {
|
| + linked_ptr<EGLStreamDelayedCopyPictureBuffer> picture_buffer(
|
| + new EGLStreamDelayedCopyPictureBuffer(buffer));
|
| + if (!picture_buffer->Initialize(decoder))
|
| + return linked_ptr<DXVAPictureBuffer>(nullptr);
|
| +
|
| + return picture_buffer;
|
| + }
|
| + case DXVAVideoDecodeAccelerator::PictureBufferMechanism::COPY_TO_NV12: {
|
| + linked_ptr<EGLStreamCopyPictureBuffer> picture_buffer(
|
| + new EGLStreamCopyPictureBuffer(buffer));
|
| + if (!picture_buffer->Initialize(decoder))
|
| + return linked_ptr<DXVAPictureBuffer>(nullptr);
|
|
|
| - return picture_buffer;
|
| - }
|
| - linked_ptr<PbufferPictureBuffer> picture_buffer(
|
| - new PbufferPictureBuffer(buffer));
|
| + return picture_buffer;
|
| + }
|
| + case DXVAVideoDecodeAccelerator::PictureBufferMechanism::COPY_TO_RGB: {
|
| + linked_ptr<PbufferPictureBuffer> picture_buffer(
|
| + new PbufferPictureBuffer(buffer));
|
|
|
| - if (!picture_buffer->Initialize(decoder, egl_config))
|
| - return linked_ptr<DXVAPictureBuffer>(nullptr);
|
| + if (!picture_buffer->Initialize(decoder, egl_config))
|
| + return linked_ptr<DXVAPictureBuffer>(nullptr);
|
|
|
| - return picture_buffer;
|
| + return picture_buffer;
|
| + }
|
| + }
|
| + NOTREACHED();
|
| + return linked_ptr<DXVAPictureBuffer>(nullptr);
|
| }
|
|
|
| DXVAPictureBuffer::~DXVAPictureBuffer() {}
|
| @@ -161,6 +178,7 @@ DXVAPictureBuffer::DXVAPictureBuffer(const PictureBuffer& buffer)
|
| : picture_buffer_(buffer) {}
|
|
|
| bool DXVAPictureBuffer::BindSampleToTexture(
|
| + DXVAVideoDecodeAccelerator* decoder,
|
| base::win::ScopedComPtr<IMFSample> sample) {
|
| NOTREACHED();
|
| return false;
|
| @@ -375,6 +393,10 @@ bool PbufferPictureBuffer::AllowOverlay() const {
|
| return false;
|
| }
|
|
|
| +bool PbufferPictureBuffer::CanBindSamples() const {
|
| + return false;
|
| +}
|
| +
|
| PbufferPictureBuffer::PbufferPictureBuffer(const PictureBuffer& buffer)
|
| : DXVAPictureBuffer(buffer),
|
| decoding_surface_(NULL),
|
| @@ -474,6 +496,7 @@ bool EGLStreamPictureBuffer::ReusePictureBuffer() {
|
| }
|
|
|
| bool EGLStreamPictureBuffer::BindSampleToTexture(
|
| + DXVAVideoDecodeAccelerator* decoder,
|
| base::win::ScopedComPtr<IMFSample> sample) {
|
| DCHECK_EQ(BOUND, state_);
|
| state_ = IN_CLIENT;
|
| @@ -518,6 +541,129 @@ bool EGLStreamPictureBuffer::AllowOverlay() const {
|
| return true;
|
| }
|
|
|
| +bool EGLStreamPictureBuffer::CanBindSamples() const {
|
| + return true;
|
| +}
|
| +
|
| +EGLStreamDelayedCopyPictureBuffer::EGLStreamDelayedCopyPictureBuffer(
|
| + const PictureBuffer& buffer)
|
| + : DXVAPictureBuffer(buffer), stream_(nullptr) {}
|
| +
|
| +EGLStreamDelayedCopyPictureBuffer::~EGLStreamDelayedCopyPictureBuffer() {
|
| + // stream_ will be deleted by gl_image_.
|
| +}
|
| +
|
| +bool EGLStreamDelayedCopyPictureBuffer::Initialize(
|
| + const DXVAVideoDecodeAccelerator& decoder) {
|
| + RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2,
|
| + "Not enough texture ids provided", false);
|
| +
|
| + EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
|
| + const EGLint stream_attributes[] = {
|
| + EGL_CONSUMER_LATENCY_USEC_KHR,
|
| + 0,
|
| + EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR,
|
| + 0,
|
| + EGL_NONE,
|
| + };
|
| + stream_ = eglCreateStreamKHR(egl_display, stream_attributes);
|
| + RETURN_ON_FAILURE(!!stream_, "Could not create stream", false);
|
| + gl::ScopedActiveTexture texture0(GL_TEXTURE0);
|
| + gl::ScopedTextureBinder texture0_binder(
|
| + GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]);
|
| + gl::ScopedActiveTexture texture1(GL_TEXTURE1);
|
| + gl::ScopedTextureBinder texture1_binder(
|
| + GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[1]);
|
| +
|
| + EGLAttrib consumer_attributes[] = {
|
| + EGL_COLOR_BUFFER_TYPE,
|
| + EGL_YUV_BUFFER_EXT,
|
| + EGL_YUV_NUMBER_OF_PLANES_EXT,
|
| + 2,
|
| + EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
|
| + 0,
|
| + EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
|
| + 1,
|
| + EGL_NONE,
|
| + };
|
| + EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
|
| + egl_display, stream_, consumer_attributes);
|
| + RETURN_ON_FAILURE(result, "Could not set stream consumer", false);
|
| +
|
| + EGLAttrib producer_attributes[] = {
|
| + EGL_NONE,
|
| + };
|
| +
|
| + result = eglCreateStreamProducerD3DTextureNV12ANGLE(egl_display, stream_,
|
| + producer_attributes);
|
| + RETURN_ON_FAILURE(result, "Could not create stream producer", false);
|
| + scoped_refptr<gl::CopyingGLImageDXGI> copying_image_ =
|
| + make_scoped_refptr(new gl::CopyingGLImageDXGI(
|
| + base::win::ScopedComPtr<ID3D11Device>(decoder.D3D11Device()), size(),
|
| + stream_));
|
| + gl_image_ = copying_image_;
|
| + return copying_image_->Initialize();
|
| +}
|
| +
|
| +bool EGLStreamDelayedCopyPictureBuffer::ReusePictureBuffer() {
|
| + DCHECK_NE(UNUSED, state_);
|
| +
|
| + static_cast<gl::CopyingGLImageDXGI*>(gl_image_.get())->UnbindFromTexture();
|
| + if (current_d3d_sample_) {
|
| + dx11_decoding_texture_.Reset();
|
| + current_d3d_sample_.Reset();
|
| + }
|
| + state_ = UNUSED;
|
| + return true;
|
| +}
|
| +
|
| +bool EGLStreamDelayedCopyPictureBuffer::BindSampleToTexture(
|
| + DXVAVideoDecodeAccelerator* decoder,
|
| + base::win::ScopedComPtr<IMFSample> sample) {
|
| + DCHECK_EQ(BOUND, state_);
|
| + state_ = IN_CLIENT;
|
| +
|
| + current_d3d_sample_ = sample;
|
| +
|
| + base::win::ScopedComPtr<IMFMediaBuffer> output_buffer;
|
| + HRESULT hr =
|
| + current_d3d_sample_->GetBufferByIndex(0, output_buffer.GetAddressOf());
|
| + RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false);
|
| +
|
| + base::win::ScopedComPtr<IMFDXGIBuffer> dxgi_buffer;
|
| + hr = output_buffer.CopyTo(dxgi_buffer.GetAddressOf());
|
| + RETURN_ON_HR_FAILURE(hr, "Failed to get DXGIBuffer from output sample",
|
| + false);
|
| + hr = dxgi_buffer->GetResource(
|
| + IID_PPV_ARGS(dx11_decoding_texture_.GetAddressOf()));
|
| + RETURN_ON_HR_FAILURE(hr, "Failed to get texture from output sample", false);
|
| + UINT subresource;
|
| + dxgi_buffer->GetSubresourceIndex(&subresource);
|
| + if (!decoder->InitializeID3D11VideoProcessor(size().width(), size().height(),
|
| + color_space_))
|
| + return false;
|
| +
|
| + DCHECK(decoder->d3d11_processor_);
|
| + DCHECK(decoder->enumerator_);
|
| +
|
| + gl::GLImageDXGI* gl_image_dxgi =
|
| + gl::GLImageDXGI::FromGLImage(gl_image_.get());
|
| + DCHECK(gl_image_dxgi);
|
| +
|
| + gl_image_dxgi->SetTexture(dx11_decoding_texture_, subresource);
|
| + return static_cast<gl::CopyingGLImageDXGI*>(gl_image_dxgi)
|
| + ->InitializeVideoProcessor(decoder->d3d11_processor_,
|
| + decoder->enumerator_);
|
| +}
|
| +
|
| +bool EGLStreamDelayedCopyPictureBuffer::AllowOverlay() const {
|
| + return true;
|
| +}
|
| +
|
| +bool EGLStreamDelayedCopyPictureBuffer::CanBindSamples() const {
|
| + return true;
|
| +}
|
| +
|
| EGLStreamCopyPictureBuffer::EGLStreamCopyPictureBuffer(
|
| const PictureBuffer& buffer)
|
| : DXVAPictureBuffer(buffer), stream_(nullptr) {}
|
| @@ -685,4 +831,8 @@ bool EGLStreamCopyPictureBuffer::AllowOverlay() const {
|
| return true;
|
| }
|
|
|
| +bool EGLStreamCopyPictureBuffer::CanBindSamples() const {
|
| + return false;
|
| +}
|
| +
|
| } // namespace media
|
|
|