diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc index b6f70f46850864..66dc1b05c82962 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool.cc @@ -172,13 +172,22 @@ class GpuMemoryBufferVideoFramePool::PoolImpl scoped_refptr video_frame, FrameResources* frame_resources); - // Prepares GL resources, mailboxes and calls |frame_ready_cb| with the new - // VideoFrame. This has to be run on |media_task_runner_| where - // |frame_ready_cb| associated with video_frame will also be run. - void BindAndCreateMailboxesHardwareFrameResources( - bool copy_failed, - scoped_refptr video_frame, - FrameResources* frame_resources); + // Called on the media thread when all data has been copied. + void OnCopiesDoneOnMediaThread(bool copy_failed, + scoped_refptr video_frame, + FrameResources* frame_resources); + + // Prepares GL resources, mailboxes and allocates the new VideoFrame. This has + // to be run on `media_task_runner_`. On failure, this will release + // `frame_resources` and return nullptr. + scoped_refptr BindAndCreateMailboxesHardwareFrameResources( + FrameResources* frame_resources, + const gfx::Size& coded_size, + const gfx::Rect& visible_rect, + const gfx::Size& natural_size, + const gfx::ColorSpace& color_space, + base::TimeDelta timestamp, + bool allow_i420_overlay); // Return true if |resources| can be used to represent a frame for // specific |format| and |size|. @@ -840,9 +849,8 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone( media_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&PoolImpl::BindAndCreateMailboxesHardwareFrameResources, - this, copy_failed, std::move(video_frame), - frame_resources)); + base::BindOnce(&PoolImpl::OnCopiesDoneOnMediaThread, this, copy_failed, + std::move(video_frame), frame_resources)); } void GpuMemoryBufferVideoFramePool::PoolImpl::StartCopy() { @@ -1018,11 +1026,11 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( } } -void GpuMemoryBufferVideoFramePool::PoolImpl:: - BindAndCreateMailboxesHardwareFrameResources( - bool copy_failed, - scoped_refptr video_frame, - FrameResources* frame_resources) { +void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDoneOnMediaThread( + bool copy_failed, + scoped_refptr video_frame, + FrameResources* frame_resources) { + DCHECK(media_task_runner_->BelongsToCurrentThread()); if (copy_failed) { // Drop the resources if there was an error with them. auto it = std::find(resources_pool_.begin(), resources_pool_.end(), @@ -1036,14 +1044,42 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: return; } + scoped_refptr frame = + BindAndCreateMailboxesHardwareFrameResources( + frame_resources, CodedSize(video_frame.get(), output_format_), + gfx::Rect(video_frame->visible_rect().size()), + video_frame->natural_size(), video_frame->ColorSpace(), + video_frame->timestamp(), video_frame->metadata().allow_overlay); + if (!frame) { + CompleteCopyRequestAndMaybeStartNextCopy(std::move(video_frame)); + return; + } + + bool new_allow_overlay = frame->metadata().allow_overlay; + bool new_read_lock_fences_enabled = + frame->metadata().read_lock_fences_enabled; + frame->metadata().MergeMetadataFrom(video_frame->metadata()); + frame->metadata().allow_overlay = new_allow_overlay; + frame->metadata().read_lock_fences_enabled = new_read_lock_fences_enabled; + CompleteCopyRequestAndMaybeStartNextCopy(std::move(frame)); +} + +scoped_refptr GpuMemoryBufferVideoFramePool::PoolImpl:: + BindAndCreateMailboxesHardwareFrameResources( + FrameResources* frame_resources, + const gfx::Size& coded_size, + const gfx::Rect& visible_rect, + const gfx::Size& natural_size, + const gfx::ColorSpace& color_space, + base::TimeDelta timestamp, + bool allow_i420_overlay) { + DCHECK(media_task_runner_->BelongsToCurrentThread()); gpu::SharedImageInterface* sii = gpu_factories_->SharedImageInterface(); if (!sii) { frame_resources->MarkUnused(tick_clock_->NowTicks()); - CompleteCopyRequestAndMaybeStartNextCopy(std::move(video_frame)); - return; + return nullptr; } - const gfx::Size coded_size = CodedSize(video_frame.get(), output_format_); gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; // Set up the planes creating the mailboxes needed to refer to the textures. for (size_t plane = 0; plane < NumSharedImages(output_format_); plane++) { @@ -1065,9 +1101,8 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT; plane_resource.mailbox = sii->CreateSharedImage( gpu_memory_buffer, gpu_factories_->GpuMemoryBufferManager(), - GetSharedImageBufferPlane(output_format_, plane), - video_frame->ColorSpace(), kTopLeft_GrSurfaceOrigin, - kPremul_SkAlphaType, usage); + GetSharedImageBufferPlane(output_format_, plane), color_space, + kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage); } else if (!plane_resource.mailbox.IsZero()) { sii->UpdateSharedImage(frame_resources->sync_token, plane_resource.mailbox); @@ -1086,22 +1121,19 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: VideoPixelFormat frame_format = VideoFormat(output_format_); // Create the VideoFrame backed by native textures. - gfx::Size visible_size = video_frame->visible_rect().size(); scoped_refptr frame = VideoFrame::WrapNativeTextures( frame_format, mailbox_holders, VideoFrame::ReleaseMailboxCB(), coded_size, - gfx::Rect(visible_size), video_frame->natural_size(), - video_frame->timestamp()); + visible_rect, natural_size, timestamp); if (!frame) { frame_resources->MarkUnused(tick_clock_->NowTicks()); MailboxHoldersReleased(frame_resources, sync_token); - CompleteCopyRequestAndMaybeStartNextCopy(std::move(video_frame)); - return; + return nullptr; } frame->SetReleaseMailboxCB( base::BindOnce(&PoolImpl::MailboxHoldersReleased, this, frame_resources)); - frame->set_color_space(video_frame->ColorSpace()); + frame->set_color_space(color_space); bool allow_overlay = false; #if defined(OS_WIN) @@ -1111,7 +1143,7 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: #else switch (output_format_) { case GpuVideoAcceleratorFactories::OutputFormat::I420: - allow_overlay = video_frame->metadata().allow_overlay; + allow_overlay = allow_i420_overlay; break; case GpuVideoAcceleratorFactories::OutputFormat::P010: case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB: @@ -1125,13 +1157,13 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: // TODO(mcasas): Enable this for ChromeOS https://crbug.com/776093. allow_overlay = false; #if defined(OS_MAC) - allow_overlay = IOSurfaceCanSetColorSpace(video_frame->ColorSpace()); + allow_overlay = IOSurfaceCanSetColorSpace(color_space); #endif // We've converted the YUV to RGB, fix the color space. // TODO(hubbe): The libyuv YUV to RGB conversion may not have // honored the color space conversion 100%. We should either fix // libyuv or find a way for later passes to make up the difference. - frame->set_color_space(video_frame->ColorSpace().GetAsRGB()); + frame->set_color_space(color_space.GetAsRGB()); break; case GpuVideoAcceleratorFactories::OutputFormat::RGBA: case GpuVideoAcceleratorFactories::OutputFormat::BGRA: @@ -1141,11 +1173,9 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: break; } #endif // OS_WIN - frame->metadata().MergeMetadataFrom(video_frame->metadata()); frame->metadata().allow_overlay = allow_overlay; frame->metadata().read_lock_fences_enabled = true; - - CompleteCopyRequestAndMaybeStartNextCopy(std::move(frame)); + return frame; } // Destroy all the resources posting one task per FrameResources