// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef MEDIA_GPU_ANDROID_VIDEO_FRAME_FACTORY_IMPL_H_ #define MEDIA_GPU_ANDROID_VIDEO_FRAME_FACTORY_IMPL_H_ #include #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "gpu/config/gpu_preferences.h" #include "media/base/video_frame.h" #include "media/gpu/android/codec_buffer_wait_coordinator.h" #include "media/gpu/android/codec_image.h" #include "media/gpu/android/codec_wrapper.h" #include "media/gpu/android/frame_info_helper.h" #include "media/gpu/android/maybe_render_early_manager.h" #include "media/gpu/android/shared_image_video_provider.h" #include "media/gpu/android/video_frame_factory.h" #include "media/gpu/media_gpu_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gl/gl_bindings.h" namespace media { class CodecImageGroup; class MaybeRenderEarlyManager; // VideoFrameFactoryImpl creates CodecOutputBuffer backed VideoFrames and tries // to eagerly render them to their surface to release the buffers back to the // decoder as soon as possible. It's not thread safe; it should be created, used // and destructed on a single sequence. It's implemented by proxying calls // to a helper class hosted on the gpu thread. class MEDIA_GPU_EXPORT VideoFrameFactoryImpl : public VideoFrameFactory, public gpu::RefCountedLockHelperDrDc { public: // Callback used to return a mailbox and release callback for an image. The // release callback may be dropped without being run, and the image will be // cleaned up properly. The release callback may be called from any thread. using ImageReadyCB = base::OnceCallback; using ImageWithInfoReadyCB = base::OnceCallback, FrameInfoHelper::FrameInfo, SharedImageVideoProvider::ImageRecord)>; // |get_stub_cb| will be run on |gpu_task_runner|. VideoFrameFactoryImpl( scoped_refptr gpu_task_runner, const gpu::GpuPreferences& gpu_preferences, std::unique_ptr image_provider, std::unique_ptr mre_manager, std::unique_ptr frame_info_helper, scoped_refptr drdc_lock); ~VideoFrameFactoryImpl() override; void Initialize(OverlayMode overlay_mode, InitCB init_cb) override; void SetSurfaceBundle( scoped_refptr surface_bundle) override; void CreateVideoFrame( std::unique_ptr output_buffer, base::TimeDelta timestamp, gfx::Size natural_size, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb, OnceOutputCB output_cb) override; void RunAfterPendingVideoFrames(base::OnceClosure closure) override; // This should be only used for testing. void SetCodecBufferWaitCorrdinatorForTesting( scoped_refptr codec_buffer_wait_coordinator) { codec_buffer_wait_coordinator_ = std::move(codec_buffer_wait_coordinator); } private: void RequestImage(std::unique_ptr buffer_renderer, ImageWithInfoReadyCB image_ready_cb); // ImageReadyCB that will construct a VideoFrame, and forward it to // |output_cb| if construction succeeds. This is static for two reasons. // First, we want to snapshot the state of the world when the request is made, // in case things like the texture owner change before it's returned. While // it's unclear that MCVD would actually do this (it drains output buffers // before switching anything, which guarantees that the VideoFrame has been // created and sent to the renderer), it's still much simpler to think about // if this uses the same state as the CreateVideoFrame call. // // Second, this way we don't care about the lifetime of |this|; |output_cb| // can worry about it. static void CreateVideoFrame_OnImageReady( base::WeakPtr thiz, OnceOutputCB output_cb, base::TimeDelta timestamp, gfx::Size natural_size, bool is_texture_owner_backed, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb, VideoPixelFormat pixel_format, OverlayMode overlay_mode, const absl::optional& copy_mode, scoped_refptr gpu_task_runner, std::unique_ptr output_buffer_renderer, FrameInfoHelper::FrameInfo frame_info, SharedImageVideoProvider::ImageRecord record); void CreateVideoFrame_OnFrameInfoReady( ImageWithInfoReadyCB image_ready_cb, std::unique_ptr output_buffer_renderer, FrameInfoHelper::FrameInfo frame_info); MaybeRenderEarlyManager* mre_manager() const { return mre_manager_.get(); } std::unique_ptr image_provider_; scoped_refptr gpu_task_runner_; // The CodecBufferWaitCoordintor that video frames should use, or nullptr. scoped_refptr codec_buffer_wait_coordinator_; OverlayMode overlay_mode_ = OverlayMode::kDontRequestPromotionHints; // Indicates how video frame needs to be copied when required. absl::optional copy_mode_; // Current group that new CodecImages should belong to. Do not use this on // our thread; everything must be posted to the gpu main thread, including // destruction of it. scoped_refptr image_group_; std::unique_ptr mre_manager_; // Helper to get coded_size and optional Vulkan YCbCrInfo. std::unique_ptr frame_info_helper_; // The current image spec that we'll use to request images. SharedImageVideoProvider::ImageSpec image_spec_; SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(VideoFrameFactoryImpl); }; } // namespace media #endif // MEDIA_GPU_ANDROID_VIDEO_FRAME_FACTORY_IMPL_H_