summaryrefslogtreecommitdiff
path: root/chromium/media/gpu/ipc/service
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/gpu/ipc/service')
-rw-r--r--chromium/media/gpu/ipc/service/BUILD.gn2
-rw-r--r--chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.cc2
-rw-r--r--chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.h2
-rw-r--r--chromium/media/gpu/ipc/service/media_gpu_channel.cc2
-rw-r--r--chromium/media/gpu/ipc/service/media_gpu_channel.h2
-rw-r--r--chromium/media/gpu/ipc/service/media_gpu_channel_manager.cc2
-rw-r--r--chromium/media/gpu/ipc/service/media_gpu_channel_manager.h2
-rw-r--r--chromium/media/gpu/ipc/service/picture_buffer_manager.cc141
-rw-r--r--chromium/media/gpu/ipc/service/picture_buffer_manager.h28
-rw-r--r--chromium/media/gpu/ipc/service/picture_buffer_manager_unittest.cc16
-rw-r--r--chromium/media/gpu/ipc/service/vda_video_decoder.cc118
-rw-r--r--chromium/media/gpu/ipc/service/vda_video_decoder.h34
-rw-r--r--chromium/media/gpu/ipc/service/vda_video_decoder_unittest.cc8
13 files changed, 272 insertions, 87 deletions
diff --git a/chromium/media/gpu/ipc/service/BUILD.gn b/chromium/media/gpu/ipc/service/BUILD.gn
index 90d8ccdb66f..8542b352c23 100644
--- a/chromium/media/gpu/ipc/service/BUILD.gn
+++ b/chromium/media/gpu/ipc/service/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
+# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
diff --git a/chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.cc b/chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
index 0c203bef158..05816d5cb90 100644
--- a/chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
+++ b/chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.h b/chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.h
index f45fa83f8e5..75472c9acb0 100644
--- a/chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.h
+++ b/chromium/media/gpu/ipc/service/gpu_video_decode_accelerator.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/chromium/media/gpu/ipc/service/media_gpu_channel.cc b/chromium/media/gpu/ipc/service/media_gpu_channel.cc
index 885d9db8d36..75b7296de64 100644
--- a/chromium/media/gpu/ipc/service/media_gpu_channel.cc
+++ b/chromium/media/gpu/ipc/service/media_gpu_channel.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/chromium/media/gpu/ipc/service/media_gpu_channel.h b/chromium/media/gpu/ipc/service/media_gpu_channel.h
index 41b48a38ec0..cd91d970130 100644
--- a/chromium/media/gpu/ipc/service/media_gpu_channel.h
+++ b/chromium/media/gpu/ipc/service/media_gpu_channel.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/chromium/media/gpu/ipc/service/media_gpu_channel_manager.cc b/chromium/media/gpu/ipc/service/media_gpu_channel_manager.cc
index abe2700d9a0..4a5d387f098 100644
--- a/chromium/media/gpu/ipc/service/media_gpu_channel_manager.cc
+++ b/chromium/media/gpu/ipc/service/media_gpu_channel_manager.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/chromium/media/gpu/ipc/service/media_gpu_channel_manager.h b/chromium/media/gpu/ipc/service/media_gpu_channel_manager.h
index c9ebef04022..fbc76409769 100644
--- a/chromium/media/gpu/ipc/service/media_gpu_channel_manager.h
+++ b/chromium/media/gpu/ipc/service/media_gpu_channel_manager.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/chromium/media/gpu/ipc/service/picture_buffer_manager.cc b/chromium/media/gpu/ipc/service/picture_buffer_manager.cc
index 47229a7365a..933ae35b8e0 100644
--- a/chromium/media/gpu/ipc/service/picture_buffer_manager.cc
+++ b/chromium/media/gpu/ipc/service/picture_buffer_manager.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -15,6 +15,11 @@
#include "base/thread_annotations.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
+#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
+#include "media/gpu/chromeos/platform_video_frame_utils.h"
+#endif // BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
namespace media {
@@ -29,9 +34,10 @@ int32_t NextID(int32_t* counter) {
class PictureBufferManagerImpl : public PictureBufferManager {
public:
- explicit PictureBufferManagerImpl(
- ReusePictureBufferCB reuse_picture_buffer_cb)
- : reuse_picture_buffer_cb_(std::move(reuse_picture_buffer_cb)) {
+ PictureBufferManagerImpl(bool allocate_gpu_memory_buffers,
+ ReusePictureBufferCB reuse_picture_buffer_cb)
+ : allocate_gpu_memory_buffers_(allocate_gpu_memory_buffers),
+ reuse_picture_buffer_cb_(std::move(reuse_picture_buffer_cb)) {
DVLOG(1) << __func__;
}
PictureBufferManagerImpl(const PictureBufferManagerImpl&) = delete;
@@ -71,7 +77,8 @@ class PictureBufferManagerImpl : public PictureBufferManager {
return !has_assigned_picture_buffer;
}
- std::vector<PictureBuffer> CreatePictureBuffers(
+ std::vector<std::pair<PictureBuffer, gfx::GpuMemoryBufferHandle>>
+ CreatePictureBuffers(
uint32_t count,
VideoPixelFormat pixel_format,
uint32_t planes,
@@ -84,6 +91,9 @@ class PictureBufferManagerImpl : public PictureBufferManager {
DCHECK(count);
DCHECK(planes);
DCHECK_LE(planes, static_cast<uint32_t>(VideoFrame::kMaxPlanes));
+ DCHECK(!allocate_gpu_memory_buffers_ ||
+ mode == VideoDecodeAccelerator::TextureAllocationMode::
+ kDoNotAllocateGLTextures);
// TODO(sandersd): Consider requiring that CreatePictureBuffers() is
// called with the context current.
@@ -91,11 +101,12 @@ class PictureBufferManagerImpl : public PictureBufferManager {
VideoDecodeAccelerator::TextureAllocationMode::kAllocateGLTextures) {
if (!command_buffer_helper_->MakeContextCurrent()) {
DVLOG(1) << "Failed to make context current";
- return std::vector<PictureBuffer>();
+ return {};
}
}
- std::vector<PictureBuffer> picture_buffers;
+ std::vector<std::pair<PictureBuffer, gfx::GpuMemoryBufferHandle>>
+ picture_buffers_and_gmbs;
for (uint32_t i = 0; i < count; i++) {
PictureBufferData picture_data = {pixel_format, texture_size};
if (mode ==
@@ -132,6 +143,46 @@ class PictureBufferManagerImpl : public PictureBufferManager {
}
}
+ gfx::GpuMemoryBufferHandle gmb_handle;
+ if (allocate_gpu_memory_buffers_) {
+#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
+ scoped_refptr<VideoFrame> gpu_memory_buffer_video_frame =
+ CreateGpuMemoryBufferVideoFrame(
+ pixel_format, texture_size, gfx::Rect(texture_size),
+ texture_size, base::TimeDelta(),
+ gfx::BufferUsage::SCANOUT_VDA_WRITE);
+ if (!gpu_memory_buffer_video_frame)
+ return {};
+ if (gpu_memory_buffer_video_frame->format() != pixel_format) {
+ // There is a mismatch (maybe deliberate) between
+ // VideoPixelFormatToGfxBufferFormat() and
+ // GfxBufferFormatToVideoPixelFormat(). For PIXEL_FORMAT_XBGR, the
+ // former returns gfx::BufferFormat::RGBX_8888, but for
+ // gfx::BufferFormat::RGBX_8888, the latter returns PIXEL_FORMAT_XRGB.
+ // Just fail if the allocated format doesn't match the requested
+ // format.
+ //
+ // TODO(andrescj): does this mismatch need to be fixed or is it
+ // intentional?
+ return {};
+ }
+
+ gfx::GpuMemoryBuffer* gmb =
+ gpu_memory_buffer_video_frame->GetGpuMemoryBuffer();
+ DCHECK(gmb);
+ gmb_handle = gmb->CloneHandle();
+ if (gmb_handle.type != gfx::NATIVE_PIXMAP ||
+ gmb_handle.native_pixmap_handle.planes.empty()) {
+ return {};
+ }
+ picture_data.gpu_memory_buffer_video_frame =
+ std::move(gpu_memory_buffer_video_frame);
+#else
+ NOTREACHED();
+ return {};
+#endif // BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
+ }
+
// Generate a picture buffer ID and record the picture buffer.
int32_t picture_buffer_id = NextID(&picture_buffer_id_);
{
@@ -145,12 +196,13 @@ class PictureBufferManagerImpl : public PictureBufferManager {
//
// TODO(sandersd): Refactor the bind image callback to use service IDs so
// that we can get rid of the client IDs altogether.
- picture_buffers.emplace_back(
- picture_buffer_id, texture_size, picture_data.texture_sizes,
- picture_data.service_ids, picture_data.service_ids, texture_target,
- pixel_format);
+ picture_buffers_and_gmbs.emplace_back(
+ PictureBuffer{picture_buffer_id, texture_size,
+ picture_data.texture_sizes, picture_data.service_ids,
+ picture_data.service_ids, texture_target, pixel_format},
+ std::move(gmb_handle));
}
- return picture_buffers;
+ return picture_buffers_and_gmbs;
}
bool DismissPictureBuffer(int32_t picture_buffer_id) override {
@@ -236,15 +288,31 @@ class PictureBufferManagerImpl : public PictureBufferManager {
}
// Create and return a VideoFrame for the picture buffer.
- scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
- picture_buffer_data.pixel_format, picture_buffer_data.mailbox_holders,
- base::BindOnce(&PictureBufferManagerImpl::OnVideoFrameDestroyed, this,
- picture_buffer_id),
- picture_buffer_data.texture_size, visible_rect, natural_size,
- timestamp);
- if (!frame) {
- DLOG(ERROR) << "Failed to create VideoFrame for picture.";
- return nullptr;
+ scoped_refptr<VideoFrame> frame;
+ if (picture_buffer_data.gpu_memory_buffer_video_frame) {
+ frame = VideoFrame::WrapVideoFrame(
+ picture_buffer_data.gpu_memory_buffer_video_frame,
+ picture_buffer_data.gpu_memory_buffer_video_frame->format(),
+ visible_rect, natural_size);
+ if (!frame) {
+ DLOG(ERROR) << "Failed to create VideoFrame for picture.";
+ return nullptr;
+ }
+ frame->set_timestamp(timestamp);
+ frame->AddDestructionObserver(
+ base::BindOnce(&PictureBufferManagerImpl::OnVideoFrameDestroyed, this,
+ picture_buffer_id, gpu::SyncToken()));
+ } else {
+ frame = VideoFrame::WrapNativeTextures(
+ picture_buffer_data.pixel_format, picture_buffer_data.mailbox_holders,
+ base::BindOnce(&PictureBufferManagerImpl::OnVideoFrameDestroyed, this,
+ picture_buffer_id),
+ picture_buffer_data.texture_size, visible_rect, natural_size,
+ timestamp);
+ if (!frame) {
+ DLOG(ERROR) << "Failed to create VideoFrame for picture.";
+ return nullptr;
+ }
}
frame->set_color_space(picture.color_space());
@@ -263,7 +331,8 @@ class PictureBufferManagerImpl : public PictureBufferManager {
private:
~PictureBufferManagerImpl() override {
DVLOG(1) << __func__;
- DCHECK(picture_buffers_.empty() || !command_buffer_helper_->HasStub());
+ DCHECK(picture_buffers_.empty() ||
+ (!command_buffer_helper_ || !command_buffer_helper_->HasStub()));
}
void OnVideoFrameDestroyed(int32_t picture_buffer_id,
@@ -280,14 +349,21 @@ class PictureBufferManagerImpl : public PictureBufferManager {
it->second.output_count--;
it->second.waiting_for_synctoken_count++;
- // Wait for the SyncToken release.
- gpu_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &CommandBufferHelper::WaitForSyncToken, command_buffer_helper_,
- sync_token,
- base::BindOnce(&PictureBufferManagerImpl::OnSyncTokenReleased, this,
- picture_buffer_id)));
+ if (command_buffer_helper_) {
+ // Wait for the SyncToken release.
+ gpu_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &CommandBufferHelper::WaitForSyncToken, command_buffer_helper_,
+ sync_token,
+ base::BindOnce(&PictureBufferManagerImpl::OnSyncTokenReleased,
+ this, picture_buffer_id)));
+ } else {
+ gpu_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&PictureBufferManagerImpl::OnSyncTokenReleased, this,
+ picture_buffer_id));
+ }
}
void OnSyncTokenReleased(int32_t picture_buffer_id) {
@@ -353,6 +429,7 @@ class PictureBufferManagerImpl : public PictureBufferManager {
command_buffer_helper_->DestroyTexture(service_id);
}
+ const bool allocate_gpu_memory_buffers_;
ReusePictureBufferCB reuse_picture_buffer_cb_;
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
@@ -369,6 +446,7 @@ class PictureBufferManagerImpl : public PictureBufferManager {
std::array<scoped_refptr<Picture::ScopedSharedImage>,
VideoFrame::kMaxPlanes>
scoped_shared_images;
+ scoped_refptr<VideoFrame> gpu_memory_buffer_video_frame;
bool dismissed = false;
// The same picture buffer can be output from the VDA multiple times
@@ -393,9 +471,10 @@ class PictureBufferManagerImpl : public PictureBufferManager {
// static
scoped_refptr<PictureBufferManager> PictureBufferManager::Create(
+ bool allocate_gpu_memory_buffers,
ReusePictureBufferCB reuse_picture_buffer_cb) {
return base::MakeRefCounted<PictureBufferManagerImpl>(
- std::move(reuse_picture_buffer_cb));
+ allocate_gpu_memory_buffers, std::move(reuse_picture_buffer_cb));
}
} // namespace media
diff --git a/chromium/media/gpu/ipc/service/picture_buffer_manager.h b/chromium/media/gpu/ipc/service/picture_buffer_manager.h
index 20452605397..dd6cbb20853 100644
--- a/chromium/media/gpu/ipc/service/picture_buffer_manager.h
+++ b/chromium/media/gpu/ipc/service/picture_buffer_manager.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -22,6 +22,10 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
+namespace gfx {
+struct GpuMemoryBufferHandle;
+} // namespace gfx
+
namespace media {
class PictureBufferManager
@@ -33,9 +37,14 @@ class PictureBufferManager
// Creates a PictureBufferManager.
//
+ // |allocate_gpu_memory_buffers|: If true, the PictureBufferManager will
+ // allocate a GpuMemoryBuffer for each PictureBuffer in
+ // CreatePictureBuffers(), and CreateVideoFrame() will return VideoFrames
+ // backed by the allocated GpuMemoryBuffers.
// |reuse_picture_buffer_cb|: Called when a picture is returned to the pool
// after its VideoFrame has been destructed.
static scoped_refptr<PictureBufferManager> Create(
+ bool allocate_gpu_memory_buffers,
ReusePictureBufferCB reuse_picture_buffer_cb);
// Provides access to a CommandBufferHelper. This must be done before calling
@@ -53,7 +62,8 @@ class PictureBufferManager
// preroll than to hang waiting for an output that can never come.
virtual bool CanReadWithoutStalling() = 0;
- // Creates and returns a vector of picture buffers, or an empty vector on
+ // Creates and returns a vector of picture buffers and the corresponding
+ // GpuMemoryBuffer (if applicable, see constructor), or an empty vector on
// failure.
//
// |count|: Number of picture buffers to create.
@@ -72,13 +82,13 @@ class PictureBufferManager
// are not automatically allocated.)
// TODO(sandersd): The current implementation makes the context current.
// Consider requiring that the context is already current.
- virtual std::vector<PictureBuffer> CreatePictureBuffers(
- uint32_t count,
- VideoPixelFormat pixel_format,
- uint32_t planes,
- gfx::Size texture_size,
- uint32_t texture_target,
- VideoDecodeAccelerator::TextureAllocationMode mode) = 0;
+ virtual std::vector<std::pair<PictureBuffer, gfx::GpuMemoryBufferHandle>>
+ CreatePictureBuffers(uint32_t count,
+ VideoPixelFormat pixel_format,
+ uint32_t planes,
+ gfx::Size texture_size,
+ uint32_t texture_target,
+ VideoDecodeAccelerator::TextureAllocationMode mode) = 0;
// Dismisses a picture buffer from the pool.
//
diff --git a/chromium/media/gpu/ipc/service/picture_buffer_manager_unittest.cc b/chromium/media/gpu/ipc/service/picture_buffer_manager_unittest.cc
index ef2098bb70e..0a12715412d 100644
--- a/chromium/media/gpu/ipc/service/picture_buffer_manager_unittest.cc
+++ b/chromium/media/gpu/ipc/service/picture_buffer_manager_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -22,7 +22,8 @@ class PictureBufferManagerImplTest : public testing::Test {
// TODO(sandersd): Use a separate thread for the GPU task runner.
cbh_ = base::MakeRefCounted<FakeCommandBufferHelper>(
environment_.GetMainThreadTaskRunner());
- pbm_ = PictureBufferManager::Create(reuse_cb_.Get());
+ pbm_ = PictureBufferManager::Create(/*allocate_gpu_memory_buffers=*/false,
+ reuse_cb_.Get());
}
PictureBufferManagerImplTest(const PictureBufferManagerImplTest&) = delete;
@@ -47,8 +48,15 @@ class PictureBufferManagerImplTest : public testing::Test {
uint32_t count,
VideoDecodeAccelerator::TextureAllocationMode mode =
VideoDecodeAccelerator::TextureAllocationMode::kAllocateGLTextures) {
- return pbm_->CreatePictureBuffers(count, PIXEL_FORMAT_ARGB, 1,
- gfx::Size(320, 240), GL_TEXTURE_2D, mode);
+ std::vector<std::pair<PictureBuffer, gfx::GpuMemoryBufferHandle>>
+ picture_buffers_and_gmbs = pbm_->CreatePictureBuffers(
+ count, PIXEL_FORMAT_ARGB, 1, gfx::Size(320, 240), GL_TEXTURE_2D,
+ mode);
+ std::vector<PictureBuffer> picture_buffers;
+ for (const auto& picture_buffer_and_gmb : picture_buffers_and_gmbs) {
+ picture_buffers.push_back(picture_buffer_and_gmb.first);
+ }
+ return picture_buffers;
}
PictureBuffer CreateARGBPictureBuffer(
diff --git a/chromium/media/gpu/ipc/service/vda_video_decoder.cc b/chromium/media/gpu/ipc/service/vda_video_decoder.cc
index ccf7b1fd7f6..73633231502 100644
--- a/chromium/media/gpu/ipc/service/vda_video_decoder.cc
+++ b/chromium/media/gpu/ipc/service/vda_video_decoder.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -74,14 +74,19 @@ std::unique_ptr<VideoDecodeAccelerator> CreateAndInitializeVda(
MediaLog* media_log,
const VideoDecodeAccelerator::Config& config) {
GpuVideoDecodeGLClient gl_client;
- gl_client.get_context = base::BindRepeating(
- &CommandBufferHelper::GetGLContext, command_buffer_helper);
- gl_client.make_context_current = base::BindRepeating(
- &CommandBufferHelper::MakeContextCurrent, command_buffer_helper);
- gl_client.bind_image = base::BindRepeating(&BindImage, command_buffer_helper);
- gl_client.is_passthrough = command_buffer_helper->IsPassthrough();
- gl_client.supports_arb_texture_rectangle =
- command_buffer_helper->SupportsTextureRectangle();
+ // |command_buffer_helper| is nullptr in IMPORT mode in which case, we
+ // shouldn't need to do any GL calls.
+ if (command_buffer_helper) {
+ gl_client.get_context = base::BindRepeating(
+ &CommandBufferHelper::GetGLContext, command_buffer_helper);
+ gl_client.make_context_current = base::BindRepeating(
+ &CommandBufferHelper::MakeContextCurrent, command_buffer_helper);
+ gl_client.bind_image =
+ base::BindRepeating(&BindImage, command_buffer_helper);
+ gl_client.is_passthrough = command_buffer_helper->IsPassthrough();
+ gl_client.supports_arb_texture_rectangle =
+ command_buffer_helper->SupportsTextureRectangle();
+ }
std::unique_ptr<GpuVideoDecodeAcceleratorFactory> factory =
GpuVideoDecodeAcceleratorFactory::Create(gl_client);
@@ -119,17 +124,23 @@ std::unique_ptr<VideoDecoder> VdaVideoDecoder::Create(
const gfx::ColorSpace& target_color_space,
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
- GetStubCB get_stub_cb) {
+ GetStubCB get_stub_cb,
+ VideoDecodeAccelerator::Config::OutputMode output_mode) {
auto* decoder = new VdaVideoDecoder(
std::move(parent_task_runner), std::move(gpu_task_runner),
std::move(media_log), target_color_space,
- base::BindOnce(&PictureBufferManager::Create),
- base::BindOnce(&CreateCommandBufferHelper, std::move(get_stub_cb)),
+ base::BindOnce(&PictureBufferManager::Create,
+ /*allocate_gpu_memory_buffers=*/output_mode ==
+ VideoDecodeAccelerator::Config::OutputMode::IMPORT),
+ output_mode == VideoDecodeAccelerator::Config::OutputMode::ALLOCATE
+ ? base::BindOnce(&CreateCommandBufferHelper, std::move(get_stub_cb))
+ : base::NullCallback(),
base::BindRepeating(&CreateAndInitializeVda, gpu_preferences,
gpu_workarounds),
GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities(
- gpu_preferences, gpu_workarounds)));
+ gpu_preferences, gpu_workarounds)),
+ output_mode);
return std::make_unique<AsyncDestroyVideoDecoder<VdaVideoDecoder>>(
base::WrapUnique(decoder));
@@ -143,7 +154,8 @@ VdaVideoDecoder::VdaVideoDecoder(
CreatePictureBufferManagerCB create_picture_buffer_manager_cb,
CreateCommandBufferHelperCB create_command_buffer_helper_cb,
CreateAndInitializeVdaCB create_and_initialize_vda_cb,
- const VideoDecodeAccelerator::Capabilities& vda_capabilities)
+ const VideoDecodeAccelerator::Capabilities& vda_capabilities,
+ VideoDecodeAccelerator::Config::OutputMode output_mode)
: parent_task_runner_(std::move(parent_task_runner)),
gpu_task_runner_(std::move(gpu_task_runner)),
media_log_(std::move(media_log)),
@@ -152,6 +164,7 @@ VdaVideoDecoder::VdaVideoDecoder(
std::move(create_command_buffer_helper_cb)),
create_and_initialize_vda_cb_(std::move(create_and_initialize_vda_cb)),
vda_capabilities_(vda_capabilities),
+ output_mode_(output_mode),
timestamps_(128) {
DVLOG(1) << __func__;
DCHECK(parent_task_runner_->BelongsToCurrentThread());
@@ -262,7 +275,10 @@ void VdaVideoDecoder::Initialize(const VideoDecoderConfig& config,
// TODO(sandersd): Change this to a capability if any VDA starts supporting
// alpha channels. This is believed to be impossible right now because VPx
// alpha channel data is passed in side data, which isn't sent to VDAs.
- if (config.alpha_mode() != VideoDecoderConfig::AlphaMode::kIsOpaque) {
+ // HEVC is the codec that only has platform hardware decoder support, and
+ // macOS currently support HEVC with alpha, so don't block HEVC here.
+ if (config.alpha_mode() != VideoDecoderConfig::AlphaMode::kIsOpaque &&
+ config.codec() != VideoCodec::kHEVC) {
MEDIA_LOG(INFO, media_log_) << "Alpha formats are not supported";
EnterErrorState();
return;
@@ -339,13 +355,16 @@ void VdaVideoDecoder::InitializeOnGpuThread() {
// Set up |command_buffer_helper_|.
if (!reinitializing_) {
- command_buffer_helper_ = std::move(create_command_buffer_helper_cb_).Run();
- if (!command_buffer_helper_) {
- parent_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&VdaVideoDecoder::InitializeDone, parent_weak_this_,
- DecoderStatus::Codes::kFailed));
- return;
+ if (output_mode_ == VideoDecodeAccelerator::Config::OutputMode::ALLOCATE) {
+ command_buffer_helper_ =
+ std::move(create_command_buffer_helper_cb_).Run();
+ if (!command_buffer_helper_) {
+ parent_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VdaVideoDecoder::InitializeDone, parent_weak_this_,
+ DecoderStatus::Codes::kFailed));
+ return;
+ }
}
picture_buffer_manager_->Initialize(gpu_task_runner_,
@@ -365,7 +384,7 @@ void VdaVideoDecoder::InitializeOnGpuThread() {
vda_config.hdr_metadata = config_.hdr_metadata();
// vda_config.sps = [Only used by AVDA]
// vda_config.pps = [Only used by AVDA]
- // vda_config.output_mode = [Only used by ARC]
+ vda_config.output_mode = output_mode_;
// vda_config.supported_output_formats = [Only used by PPAPI]
// Create and initialize the VDA.
@@ -505,6 +524,13 @@ int VdaVideoDecoder::GetMaxDecodeRequests() const {
return 4;
}
+bool VdaVideoDecoder::FramesHoldExternalResources() const {
+ DVLOG(3) << __func__;
+ DCHECK(parent_task_runner_->BelongsToCurrentThread());
+
+ return output_mode_ == VideoDecodeAccelerator::Config::OutputMode::IMPORT;
+}
+
void VdaVideoDecoder::NotifyInitializationComplete(DecoderStatus status) {
DVLOG(2) << __func__ << "(" << static_cast<int>(status.code()) << ")";
DCHECK(gpu_task_runner_->BelongsToCurrentThread());
@@ -531,6 +557,27 @@ void VdaVideoDecoder::ProvidePictureBuffers(uint32_t requested_num_of_buffers,
textures_per_buffer, dimensions, texture_target));
}
+void VdaVideoDecoder::ProvidePictureBuffersWithVisibleRect(
+ uint32_t requested_num_of_buffers,
+ VideoPixelFormat format,
+ uint32_t textures_per_buffer,
+ const gfx::Size& dimensions,
+ const gfx::Rect& visible_rect,
+ uint32_t texture_target) {
+ if (output_mode_ == VideoDecodeAccelerator::Config::OutputMode::IMPORT) {
+ // In IMPORT mode, we (as the client of the underlying VDA) are responsible
+ // for buffer allocation with no textures (i.e., |texture_target| is
+ // irrelevant). Therefore, the logic in the base version of
+ // ProvidePictureBuffersWithVisibleRect() is not applicable.
+ ProvidePictureBuffers(requested_num_of_buffers, format, textures_per_buffer,
+ dimensions, texture_target);
+ return;
+ }
+ VideoDecodeAccelerator::Client::ProvidePictureBuffersWithVisibleRect(
+ requested_num_of_buffers, format, textures_per_buffer, dimensions,
+ visible_rect, texture_target);
+}
+
void VdaVideoDecoder::ProvidePictureBuffersAsync(uint32_t count,
VideoPixelFormat pixel_format,
uint32_t planes,
@@ -547,11 +594,14 @@ void VdaVideoDecoder::ProvidePictureBuffersAsync(uint32_t count,
if (pixel_format == PIXEL_FORMAT_UNKNOWN)
pixel_format = PIXEL_FORMAT_XRGB;
- std::vector<PictureBuffer> picture_buffers =
- picture_buffer_manager_->CreatePictureBuffers(
+ std::vector<std::pair<PictureBuffer, gfx::GpuMemoryBufferHandle>>
+ picture_buffers_and_gmbs = picture_buffer_manager_->CreatePictureBuffers(
count, pixel_format, planes, texture_size, texture_target,
- vda_->GetSharedImageTextureAllocationMode());
- if (picture_buffers.empty()) {
+ output_mode_ == VideoDecodeAccelerator::Config::OutputMode::IMPORT
+ ? VideoDecodeAccelerator::TextureAllocationMode::
+ kDoNotAllocateGLTextures
+ : vda_->GetSharedImageTextureAllocationMode());
+ if (picture_buffers_and_gmbs.empty()) {
parent_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VdaVideoDecoder::EnterErrorState, parent_weak_this_));
@@ -559,7 +609,19 @@ void VdaVideoDecoder::ProvidePictureBuffersAsync(uint32_t count,
}
DCHECK(gpu_weak_vda_);
+ std::vector<PictureBuffer> picture_buffers;
+ for (const auto& picture_buffer_and_gmb : picture_buffers_and_gmbs) {
+ picture_buffers.push_back(picture_buffer_and_gmb.first);
+ }
vda_->AssignPictureBuffers(std::move(picture_buffers));
+
+ if (output_mode_ == VideoDecodeAccelerator::Config::OutputMode::IMPORT) {
+ for (auto& picture_buffer_and_gmb : picture_buffers_and_gmbs) {
+ vda_->ImportBufferForPicture(picture_buffer_and_gmb.first.id(),
+ pixel_format,
+ std::move(picture_buffer_and_gmb.second));
+ }
+ }
}
void VdaVideoDecoder::DismissPictureBuffer(int32_t picture_buffer_id) {
@@ -771,10 +833,12 @@ void VdaVideoDecoder::NotifyError(VideoDecodeAccelerator::Error error) {
}
gpu::SharedImageStub* VdaVideoDecoder::GetSharedImageStub() const {
+ DCHECK_EQ(output_mode_, VideoDecodeAccelerator::Config::OutputMode::ALLOCATE);
return command_buffer_helper_->GetSharedImageStub();
}
CommandBufferHelper* VdaVideoDecoder::GetCommandBufferHelper() const {
+ DCHECK_EQ(output_mode_, VideoDecodeAccelerator::Config::OutputMode::ALLOCATE);
return command_buffer_helper_.get();
}
diff --git a/chromium/media/gpu/ipc/service/vda_video_decoder.h b/chromium/media/gpu/ipc/service/vda_video_decoder.h
index 83b8653094c..12f0b1ac23e 100644
--- a/chromium/media/gpu/ipc/service/vda_video_decoder.h
+++ b/chromium/media/gpu/ipc/service/vda_video_decoder.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -59,8 +59,9 @@ class VdaVideoDecoder : public VideoDecoder,
// unique_ptr<VideoDecoder>.
//
// |get_stub_cb|: Callback to retrieve the CommandBufferStub that should be
- // used for allocating textures and mailboxes. This callback will be
- // called on the GPU thread.
+ // used for allocating textures and mailboxes. This is only used when
+ // |output_mode| is ALLOCATE. This callback will be called on the GPU
+ // thread.
//
// See VdaVideoDecoder() for other arguments.
static std::unique_ptr<VideoDecoder> Create(
@@ -70,7 +71,8 @@ class VdaVideoDecoder : public VideoDecoder,
const gfx::ColorSpace& target_color_space,
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
- GetStubCB get_stub_cb);
+ GetStubCB get_stub_cb,
+ VideoDecodeAccelerator::Config::OutputMode output_mode);
VdaVideoDecoder(const VdaVideoDecoder&) = delete;
VdaVideoDecoder& operator=(const VdaVideoDecoder&) = delete;
@@ -90,6 +92,7 @@ class VdaVideoDecoder : public VideoDecoder,
bool NeedsBitstreamConversion() const override;
bool CanReadWithoutStalling() const override;
int GetMaxDecodeRequests() const override;
+ bool FramesHoldExternalResources() const override;
private:
friend class VdaVideoDecoderTest;
@@ -102,10 +105,21 @@ class VdaVideoDecoder : public VideoDecoder,
// |media_log|: MediaLog object to log to.
// |target_color_space|: Color space of the output device.
// |create_picture_buffer_manager_cb|: PictureBufferManager factory.
- // |create_command_buffer_helper_cb|: CommandBufferHelper factory.
+ // |create_command_buffer_helper_cb|: CommandBufferHelper factory. This is
+ // only used when |output_mode| is ALLOCATE.
// |create_and_initialize_vda_cb|: VideoDecodeAccelerator factory.
// |vda_capabilities|: Capabilities of the VDA that
// |create_and_initialize_vda_cb| will produce.
+ // |output_mode|: How to manage memory for output frames:
+ // - ALLOCATE: output buffer allocation is expected to be done by a
+ // combination of the PictureBufferManager (for texture allocation,
+ // possibly) and the VDA when AssignPictureBuffers() is called. In this
+ // case, the VdaVideoDecoder will output Mailbox-backed VideoFrames.
+ // - IMPORT, output buffer allocation is done by the PictureBufferManager
+ // (to allocate GpuMemoryBuffers without textures) and these buffers are
+ // imported into the VDA by calling ImportBufferForPicture(). In this
+ // case, the VdaVideoDecoder will output GpuMemoryBuffer-backed
+ // VideoFrames.
VdaVideoDecoder(
scoped_refptr<base::SingleThreadTaskRunner> parent_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
@@ -114,7 +128,8 @@ class VdaVideoDecoder : public VideoDecoder,
CreatePictureBufferManagerCB create_picture_buffer_manager_cb,
CreateCommandBufferHelperCB create_command_buffer_helper_cb,
CreateAndInitializeVdaCB create_and_initialize_vda_cb,
- const VideoDecodeAccelerator::Capabilities& vda_capabilities);
+ const VideoDecodeAccelerator::Capabilities& vda_capabilities,
+ VideoDecodeAccelerator::Config::OutputMode output_mode);
// media::VideoDecodeAccelerator::Client implementation.
void NotifyInitializationComplete(DecoderStatus status) override;
@@ -123,6 +138,12 @@ class VdaVideoDecoder : public VideoDecoder,
uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) override;
+ void ProvidePictureBuffersWithVisibleRect(uint32_t requested_num_of_buffers,
+ VideoPixelFormat format,
+ uint32_t textures_per_buffer,
+ const gfx::Size& dimensions,
+ const gfx::Rect& visible_rect,
+ uint32_t texture_target) override;
void DismissPictureBuffer(int32_t picture_buffer_id) override;
void PictureReady(const Picture& picture) override;
void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) override;
@@ -167,6 +188,7 @@ class VdaVideoDecoder : public VideoDecoder,
CreateCommandBufferHelperCB create_command_buffer_helper_cb_;
CreateAndInitializeVdaCB create_and_initialize_vda_cb_;
const VideoDecodeAccelerator::Capabilities vda_capabilities_;
+ const VideoDecodeAccelerator::Config::OutputMode output_mode_;
//
// Parent thread state.
diff --git a/chromium/media/gpu/ipc/service/vda_video_decoder_unittest.cc b/chromium/media/gpu/ipc/service/vda_video_decoder_unittest.cc
index 4755884b259..0a97765164c 100644
--- a/chromium/media/gpu/ipc/service/vda_video_decoder_unittest.cc
+++ b/chromium/media/gpu/ipc/service/vda_video_decoder_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -107,7 +107,8 @@ class VdaVideoDecoderTest : public testing::TestWithParam<bool> {
base::Unretained(this)),
base::BindRepeating(&VdaVideoDecoderTest::CreateAndInitializeVda,
base::Unretained(this)),
- GetCapabilities());
+ GetCapabilities(),
+ VideoDecodeAccelerator::Config::OutputMode::ALLOCATE);
vdavd_ = std::make_unique<AsyncDestroyVideoDecoder<VdaVideoDecoder>>(
base::WrapUnique(vdavd));
client_ = vdavd;
@@ -280,7 +281,8 @@ class VdaVideoDecoderTest : public testing::TestWithParam<bool> {
scoped_refptr<PictureBufferManager> CreatePictureBufferManager(
PictureBufferManager::ReusePictureBufferCB reuse_cb) {
DCHECK(!pbm_);
- pbm_ = PictureBufferManager::Create(std::move(reuse_cb));
+ pbm_ = PictureBufferManager::Create(/*allocate_gpu_memory_buffers=*/false,
+ std::move(reuse_cb));
return pbm_;
}