diff options
Diffstat (limited to 'chromium/media/gpu/ipc/service')
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_; } |