| // Copyright 2024 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef MEDIA_GPU_CHROMEOS_FRAME_RESOURCE_CONVERTER_H_ | 
 | #define MEDIA_GPU_CHROMEOS_FRAME_RESOURCE_CONVERTER_H_ | 
 |  | 
 | #include "base/functional/callback.h" | 
 | #include "base/memory/scoped_refptr.h" | 
 | #include "base/unguessable_token.h" | 
 | #include "media/gpu/media_gpu_export.h" | 
 |  | 
 | namespace base { | 
 | class Location; | 
 | class SequencedTaskRunner; | 
 | }  // namespace base | 
 |  | 
 | namespace media { | 
 |  | 
 | class FrameResource; | 
 | class VideoFrame; | 
 |  | 
 | // This interface is at the end of VideoDecoderPipeline to convert | 
 | // FrameResources to VideoFrames. | 
 | // | 
 | // A FrameResourceConverter is expected to be used as follows: | 
 | // | 
 | // 1) It can be constructed on any sequence. The first method call after | 
 | //    construction must be Initialize() which can happen on any sequence and | 
 | //    should only be called once. | 
 | // | 
 | // 2) Other methods must be called on the |parent_task_runner| passed to | 
 | //    Initialize(). | 
 | // | 
 | // 3) Destruction must occur through | 
 | //    std::default_delete<FrameResourceConverter> on that same | 
 | //    |parent_task_runner| (unless Initialize() was never called, in which case, | 
 | //    the destruction can occur on any sequence). | 
 | class FrameResourceConverter { | 
 |  public: | 
 |   using OutputCB = base::RepeatingCallback<void(scoped_refptr<VideoFrame>)>; | 
 |   using GetOriginalFrameCB = base::RepeatingCallback<FrameResource*( | 
 |       const base::UnguessableToken& tracking_token)>; | 
 |  | 
 |   FrameResourceConverter(); | 
 |   // A |FrameResourceConverter| is not copyable or moveable. | 
 |   FrameResourceConverter(const FrameResourceConverter&) = delete; | 
 |   FrameResourceConverter(FrameResourceConverter&&) = delete; | 
 |   FrameResourceConverter& operator=(const FrameResourceConverter&) = delete; | 
 |   FrameResourceConverter& operator=(FrameResourceConverter&&) = delete; | 
 |  | 
 |   // Initializes the converter. This method must be called before any other | 
 |   // methods. Each of the public methods of the FrameResourceConverter interface | 
 |   // performs DCHECK()s to ensure they are called on |parent_task_runner|. | 
 |   // |output_cb| is called on the |parent_task_runner| to output converted | 
 |   // frames or to indicate an error (in which case, |output_cb| is called with a | 
 |   // nullptr). | 
 |   void Initialize(scoped_refptr<base::SequencedTaskRunner> parent_task_runner, | 
 |                   OutputCB output_cb); | 
 |  | 
 |   // Converts the storage type of |frame|. Conversion may happen asynchronously | 
 |   // or synchronously. Implementers should guarantee that generated frames do | 
 |   // not rely on the incoming frame being kept alive by the caller. I.e. it must | 
 |   // not be invalidated by the client dropping a reference to |frame|. | 
 |   void ConvertFrame(scoped_refptr<FrameResource> frame); | 
 |  | 
 |   // For implementations that queue frames to convert, these interfaces provide | 
 |   // a way to abort or check the status of the queue. | 
 |   void AbortPendingFrames(); | 
 |   bool HasPendingFrames() const; | 
 |  | 
 |   // Sets the callback to unwrap FrameResources provided to ConvertFrame(). If | 
 |   // |get_original_frame_cb| is null or this method is never called at all, | 
 |   // ConvertFrame() assumes it's called with unwrapped FrameResources. | 
 |   // | 
 |   // If used, |get_original_frame_cb| will only be called during a call to | 
 |   // ConvertFrame(). | 
 |   // | 
 |   // Note: if |get_original_frame_cb| is called at all, it will be called on | 
 |   // |parent_task_runner_|. | 
 |   void set_get_original_frame_cb(GetOriginalFrameCB get_original_frame_cb); | 
 |  | 
 |   // Returns true if and only if ConvertFrame() may use the GetOriginalFrameCB | 
 |   // set via set_get_original_frame_cb() (i.e., some implementations don't need | 
 |   // to unwrap incoming frames). | 
 |   bool UsesGetOriginalFrameCB() const; | 
 |  | 
 |  protected: | 
 |   virtual ~FrameResourceConverter(); | 
 |  | 
 |   // Invoked when any error occurs. |msg| is the error message. If a derived | 
 |   // class uses pending frames, it should call AbortPendingFrames before calling | 
 |   // FrameResourceConverter::OnError(). Callers may assume that this method will | 
 |   // post a task to the |parent_task_runner_| to notify the client of the error | 
 |   // such that any tasks posted to that task runner before calling OnError() run | 
 |   // before the notification. | 
 |   virtual void OnError(const base::Location& location, const std::string& msg); | 
 |  | 
 |   // In DmabufVideoFramePool and OOPVideoDecoder, we recycle the unused frames. | 
 |   // This is done a bit differently for each case: | 
 |   // | 
 |   // - For DmabufVideoFramePool: each time a frame is requested from the pool it | 
 |   //   is wrapped inside another frame. A destruction callback is then added to | 
 |   //   this wrapped frame to automatically return it to the pool upon | 
 |   //   destruction. | 
 |   // | 
 |   // - For OOPVideoDecoder: each time we receive a frame from the remote | 
 |   //   decoder, we look it up in a cache of known, previously received buffers | 
 |   //   (or insert it into this cache if it's a new buffer). We wrap the known or | 
 |   //   new frame inside another frame. A destruction callback is then added to | 
 |   //   this wrapped frame to automatically notify the remote decoder that it can | 
 |   //   re-use the underlying buffer upon destruction. | 
 |   // | 
 |   // Unfortunately this means that a new frame is returned each time (i.e., we | 
 |   // receive a new FrameResource::unique_id() each time). Some implementations | 
 |   // need a way to uniquely identify the underlying frame to avoid converting | 
 |   // the same frame multiple times. GetOriginalFrame() is used to get the | 
 |   // original frame. | 
 |   // | 
 |   // This must be called on |parent_task_runner_|. | 
 |   FrameResource* GetOriginalFrame(FrameResource& frame) const; | 
 |  | 
 |   const scoped_refptr<base::SequencedTaskRunner>& parent_task_runner(); | 
 |  | 
 |   // This must be called on |parent_task_runner_|. | 
 |   void Output(scoped_refptr<VideoFrame> frame) const; | 
 |  | 
 |  private: | 
 |   friend struct std::default_delete<FrameResourceConverter>; | 
 |  | 
 |   // Run on the |parent_task_runner| to allow for implementation-specific | 
 |   // clean-up and destruction. The default implementation simply destroys | 
 |   // *|this|. | 
 |   virtual void Destroy(); | 
 |  | 
 |   // The *Impl methods are run by their public counterparts after sequence | 
 |   // validation is run. ConvertFrameImpl() is the private implementation for | 
 |   // ConvertFrame(). Similarly for AbortPendingFramesImpl() and | 
 |   // HasPendingFramesImpl(). | 
 |   virtual void ConvertFrameImpl(scoped_refptr<FrameResource> frame) = 0; | 
 |  | 
 |   // Derived classes should override these if there is a need to asynchronously | 
 |   // convert frames. The base implementations assume that there will never be | 
 |   // a pending frame. | 
 |   virtual void AbortPendingFramesImpl(); | 
 |   virtual bool HasPendingFramesImpl() const; | 
 |  | 
 |   // Derived classes should override UsesGetOriginalFrameCBImpl() if the class | 
 |   // uses the callback stored in |get_original_frame_cb_|. | 
 |   virtual bool UsesGetOriginalFrameCBImpl() const; | 
 |  | 
 |   // |get_original_frame_cb_| is used by GetOriginalFrame() to get the original | 
 |   // frame. | 
 |   // | 
 |   // When |get_original_frame_cb_| is null, we assume it's not necessary to get | 
 |   // the original frames, and we just use them directly. | 
 |   // | 
 |   // TODO(b/195769334): remove the null |get_original_frame_cb_| path because it | 
 |   // shouldn't be used after https://crrev.com/c/4457504. | 
 |   GetOriginalFrameCB get_original_frame_cb_; | 
 |  | 
 |   // The working task runner. Set by Initialize(). Derived classes may access | 
 |   // this via parent_task_runner(). | 
 |   scoped_refptr<base::SequencedTaskRunner> parent_task_runner_; | 
 |  | 
 |   // The callback for passing output frames. Set by Initialize(). Derived | 
 |   // classes should use Output() to write a converted frame. | 
 |   OutputCB output_cb_; | 
 | }; | 
 |  | 
 | }  // namespace media | 
 |  | 
 | namespace std { | 
 |  | 
 | // Specialize std::default_delete to call Destroy(). | 
 | template <> | 
 | struct MEDIA_GPU_EXPORT default_delete<media::FrameResourceConverter> { | 
 |   constexpr default_delete() = default; | 
 |  | 
 |   template <typename U> | 
 |     requires(std::is_convertible_v<U*, media::FrameResourceConverter*>) | 
 |   explicit default_delete(const default_delete<U>& d) {} | 
 |  | 
 |   void operator()(media::FrameResourceConverter* ptr) const; | 
 | }; | 
 |  | 
 | }  // namespace std | 
 |  | 
 | #endif  // MEDIA_GPU_CHROMEOS_FRAME_RESOURCE_CONVERTER_H_ |