#pragma once #include "api/video/video_frame.h" #include "api/video/video_sink_interface.h" #include "callback.h" using I420FrameReadyCallback = Callback; using ARGBFrameReadyCallback = Callback< const uint8_t*,int, const uint8_t*,int, const uint8_t*, int, const int,const int, const int>; //根据图像的高度和每行数据的字节数,计算出整个图像数据所需的总字节数 constexpr inline size_t ArgbDataSize(int height, int stride) { return static_cast(height) * stride * 4; } /* 自定义的视频帧缓冲区管理类 */ class ArgbBuffer : public webrtc::VideoFrameBuffer { public: // Create a new buffer. /* 静态方法用于创建一个新的 ArgbBuffer实例 该方法接收视频帧的宽度和高度,并计算出所需的缓冲区大小 返回类型是rtc::scoped_refptr,它是一个智能指针,用于管理 ArgbBuffer 的生命周期 */ static inline rtc::scoped_refptr Create(int width, int height) { return new rtc::RefCountedObject(width, height, width * 4); } //// Create a new buffer and copy the pixel data. // static rtc::scoped_refptr Copy(const I010BufferInterface& // buffer); //// Convert and put I420 buffer into a new buffer. // static rtc::scoped_refptr Copy(const I420BufferInterface& // buffer); //// Return a rotated copy of |src|. // static rtc::scoped_refptr Rotate(const I010BufferInterface& // src, // VideoRotation rotation); // VideoFrameBuffer implementation. inline Type type() const override { return VideoFrameBuffer::Type::kNative; } inline int width() const override { return width_; } inline int height() const override { return height_; } rtc::scoped_refptr ToI420() override; inline uint8_t* Data() { return data_.get(); } inline const uint8_t* Data() const { return data_.get(); } inline int Stride() const { return stride_; } inline constexpr size_t Size() const { return ArgbDataSize(height_, stride_); } protected: ArgbBuffer(int width, int height, int stride) ; ~ArgbBuffer() override = default; private: const int width_; const int height_; const int stride_; //指向视频数据的智能指针,使用 webrtc::AlignedFreeDeleter 来管理内存释放 const std::unique_ptr data_; }; /* 管理视频帧的接口类 */ /// Video frame observer to get notified of newly available video frames. class VideoFrameObserver : public rtc::VideoSinkInterface { public: /// Register a callback to get notified on frame available, /// and received that frame as a I420-encoded buffer. /// This is not exclusive and can be used along another ARGB callback. void SetCallback(I420FrameReadyCallback callback) ; /// Register a callback to get notified on frame available, /// and received that frame as a raw decoded ARGB buffer. /// This is not exclusive and can be used along another I420 callback. void SetCallback(ARGBFrameReadyCallback callback) ; protected: //获取一个足够容纳指定大小图像数据的缓冲区(ArgbBuffer),如果已有的缓冲区足够大,则直接返回;否则,创建一个新的缓冲区并返回 ArgbBuffer* GetArgbScratchBuffer(int width, int height); // VideoSinkInterface interface void OnFrame(const webrtc::VideoFrame& frame) override; private: /// Registered callback for receiving I420-encoded frame. I420FrameReadyCallback i420_callback_; /// Registered callback for receiving raw decoded ARGB frame. ARGBFrameReadyCallback argb_callback_; /// Mutex protecting all callbacks. std::mutex mutex_; /// Reusable ARGB scratch buffer to avoid per-frame allocation. //定义一个名为argb_scratch_buffer_ 的ArgbBuffer类型的智能指针,指向ARGB暂存缓冲区 rtc::scoped_refptr argb_scratch_buffer_; };