| // Copyright 2020 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_CHROMEOS_VDA_VIDEO_FRAME_POOL_H_ |
| #define MEDIA_GPU_CHROMEOS_VDA_VIDEO_FRAME_POOL_H_ |
| |
| #include "base/containers/queue.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/sequenced_task_runner.h" |
| #include "media/base/video_frame.h" |
| #include "media/gpu/chromeos/dmabuf_video_frame_pool.h" |
| #include "media/gpu/chromeos/fourcc.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace base { |
| class WaitableEvent; |
| } |
| |
| namespace media { |
| |
| class GpuBufferLayout; |
| |
| // This class is used by VdVideoDecodeAccelerator, which adapts |
| // VideoDecodeAccelerator to VideoDecoder interface. |
| // The mission is to allocate and manage DMA-buf VideoFrame by delegating the |
| // requests of buffer allocation to a VideoDecodeAccelerator instance, and |
| // provide VideoFrame to the VideoDecoder instance. |
| // The communication with VdVideoDecodeAccelerator, which inherits |
| // VdaDelegate, is executed on |vda_task_runner_|, and the communication with |
| // VideoDecoder instance is on |parent_task_runner_|. |
| class VdaVideoFramePool : public DmabufVideoFramePool { |
| public: |
| class VdaDelegate { |
| public: |
| // Callback for returning the layout of requested buffer. |
| using NotifyLayoutChangedCb = |
| base::OnceCallback<void(absl::optional<GpuBufferLayout>)>; |
| // Callback for importing available frames to this pool. |
| using ImportFrameCb = |
| base::RepeatingCallback<void(scoped_refptr<VideoFrame>)>; |
| |
| // Request new frames from VDA's client. VdaDelegate has to return the |
| // layout of frames by calling |notify_layout_changed_cb|. |
| // After that, VdaDelegate should pass frames by calling |
| // |import_frame_cb|. |
| // Note: RequestFrames(), |notify_layout_changed_cb|, and |import_frame_cb| |
| // should be called on VdaVideoFramePool's |vda_task_runner_|. |
| virtual void RequestFrames(const Fourcc& fourcc, |
| const gfx::Size& coded_size, |
| const gfx::Rect& visible_rect, |
| size_t max_num_frames, |
| NotifyLayoutChangedCb notify_layout_changed_cb, |
| ImportFrameCb import_frame_cb) = 0; |
| }; |
| |
| VdaVideoFramePool(base::WeakPtr<VdaDelegate> vda, |
| scoped_refptr<base::SequencedTaskRunner> vda_task_runner); |
| ~VdaVideoFramePool() override; |
| |
| // DmabufVideoFramePool implementation. |
| StatusOr<GpuBufferLayout> Initialize(const Fourcc& fourcc, |
| const gfx::Size& coded_size, |
| const gfx::Rect& visible_rect, |
| const gfx::Size& natural_size, |
| size_t max_num_frames, |
| bool use_protected) override; |
| scoped_refptr<VideoFrame> GetFrame() override; |
| bool IsExhausted() override; |
| void NotifyWhenFrameAvailable(base::OnceClosure cb) override; |
| void ReleaseAllFrames() override; |
| |
| private: |
| // Update the layout of the buffers. |vda_| calls this as |
| // NotifyLayoutChangedCb. |
| void OnRequestFramesDone(base::WaitableEvent* done, |
| absl::optional<GpuBufferLayout> layout); |
| |
| // Thunk to post ImportFrame() to |task_runner|. |
| // Because this thunk may be called in any thread, We don't want to |
| // dereference WeakPtr. Therefore we wrap the WeakPtr by absl::optional to |
| // avoid the task runner defererencing the WeakPtr. |
| static void ImportFrameThunk( |
| scoped_refptr<base::SequencedTaskRunner> task_runner, |
| absl::optional<base::WeakPtr<VdaVideoFramePool>> weak_this, |
| scoped_refptr<VideoFrame> frame); |
| // Import an available frame. |
| void ImportFrame(scoped_refptr<VideoFrame> frame); |
| |
| // Call |frame_available_cb_| when the pool is not exhausted. |
| void CallFrameAvailableCbIfNeeded(); |
| |
| // WeakPtr of VdaDelegate instance, bound at |vda_task_runner_|. |
| base::WeakPtr<VdaDelegate> vda_; |
| // Task runner that interacts with VdaDelegate. All VdaDelegate's methods |
| // and their callbacks should be called on this task runner. |
| // Note: DmabufVideoFrame's public methods like Initialize() and GetFrame() |
| // should be called on |parent_task_runner_|. |
| scoped_refptr<base::SequencedTaskRunner> vda_task_runner_; |
| |
| // The callback which is called when the pool is not exhausted. |
| base::OnceClosure frame_available_cb_; |
| |
| // The layout of the frames in |frame_pool_|. |
| absl::optional<GpuBufferLayout> layout_; |
| |
| // Data passed from Initialize(). |
| size_t max_num_frames_ = 0; |
| absl::optional<Fourcc> fourcc_; |
| gfx::Size coded_size_; |
| gfx::Rect visible_rect_; |
| gfx::Size natural_size_; |
| |
| base::queue<scoped_refptr<VideoFrame>> frame_pool_; |
| |
| // Sequence checker for |parent_task_runner_|. |
| SEQUENCE_CHECKER(parent_sequence_checker_); |
| |
| // The weak pointer of this, bound at |parent_task_runner_|. |
| base::WeakPtr<VdaVideoFramePool> weak_this_; |
| base::WeakPtrFactory<VdaVideoFramePool> weak_this_factory_{this}; |
| }; |
| |
| } // namespace media |
| |
| #endif // MEDIA_GPU_CHROMEOS_VDA_VIDEO_FRAME_POOL_H_ |