视频帧双缓冲区的第一个版本,仅缓冲视频帧,CSharedCriticalSection是临界区保护类
class CFrameCache{ public: CFrameCache() : pop_frame_ptr_(nullptr) , push_frame_ptr_(nullptr) , width_(0), hight_(0), channels_(0){ } ~CFrameCache() { if(pop_frame_ptr_) { delete[] pop_frame_ptr_; pop_frame_ptr_ = nullptr; } if(push_frame_ptr_){ delete[] push_frame_ptr_; push_frame_ptr_ = nullptr; } } void push_frame(const char* frame, int width, int hight, int channels){ if(nullptr == frame || width < 0 || hight < 0 || channels < 0) { return ; } CSharedMutex lock(mutex_); if(push_frame_ptr_ == nullptr && pop_frame_ptr_ == nullptr) { width_ = width; hight_ = hight; channels_ = channels; pop_frame_ptr_ = new char[width_ * hight_ * channels_]; push_frame_ptr_ = new char[width_ * hight_ * channels_]; memset(pop_frame_ptr_, 0x00, width_ * hight_ * channels_); memset(push_frame_ptr_, 0x00, width_ * hight_ * channels_); } if((width != width_ || hight_ != hight || channels_ != channels) && push_frame_ptr_ && pop_frame_ptr_) { width_ = width; hight_ = hight; channels_ = channels; delete[] pop_frame_ptr_; delete[] push_frame_ptr_; pop_frame_ptr_ = new char[width_ * hight_ * channels_]; push_frame_ptr_ = new char[width_ * hight_ * channels_]; memset(pop_frame_ptr_, 0x00, width_ * hight_ * channels_); memset(push_frame_ptr_, 0x00, width_ * hight_ * channels_); } memset(push_frame_ptr_, 0x00, width_ * hight_ * channels_); memcpy(push_frame_ptr_, frame, width_ * hight_ * channels_); } const char* pop_frame(){ CSharedMutex lock(mutex_); std::swap(push_frame_ptr_, pop_frame_ptr_); return pop_frame_ptr_; } int size(){ CSharedMutex lock(mutex_); return width_ * hight_ * channels_; } int Width() { CSharedMutex lock(mutex_); return width_; } int Hight() { CSharedMutex lock(mutex_); return hight_; } int Channels() { CSharedMutex lock(mutex_); return channels_; } protected: CFrameCache(const CFrameCache& rhs){ } CFrameCache& operator=(const CFrameCache& rhs){ return *this; } private: char* pop_frame_ptr_; char* push_frame_ptr_; int width_, hight_, channels_; CSharedCriticalSection mutex_; };
视频帧双缓冲区的第二个版本,缓冲视频帧,并允许保存一些视频的附加信息
// 带EXIF信息的帧缓冲 template <typename ExifClass> class CFrameCacheWithExif{ public: CFrameCacheWithExif() : pop_frame_ptr_(nullptr) , push_frame_ptr_(nullptr) , width_(0), hight_(0), channels_(0){ } ~CFrameCacheWithExif() { if(pop_frame_ptr_) { delete[] pop_frame_ptr_; pop_frame_ptr_ = nullptr; } if(push_frame_ptr_){ delete[] push_frame_ptr_; push_frame_ptr_ = nullptr; } if(pop_exif_ptr_) { delete[] pop_exif_ptr_; pop_exif_ptr_ = nullptr; } if(push_exif_ptr_){ delete[] push_exif_ptr_; push_exif_ptr_ = nullptr; } } void push_frame(const char* frame, const void* exif, int width, int hight, int channels){ if(nullptr == frame || width < 0 || hight < 0 || channels < 0) { return ; } CSharedMutex lock(mutex_); if(push_frame_ptr_ == nullptr && pop_frame_ptr_ == nullptr) { width_ = width; hight_ = hight; channels_ = channels; pop_frame_ptr_ = new char[width_ * hight_ * channels_]; push_frame_ptr_ = new char[width_ * hight_ * channels_]; memset(pop_frame_ptr_, 0x00, width_ * hight_ * channels_); memset(push_frame_ptr_, 0x00, width_ * hight_ * channels_); pop_exif_ptr_ = new unsigned char[sizeof(ExifClass)]; push_exif_ptr_ = new unsigned char[sizeof(ExifClass)]; memset(pop_exif_ptr_, 0x00, sizeof(ExifClass)); memset(push_exif_ptr_, 0x00, sizeof(ExifClass)); } if((width != width_ || hight_ != hight || channels_ != channels) && push_frame_ptr_ && pop_frame_ptr_) { width_ = width; hight_ = hight; channels_ = channels; delete[] pop_frame_ptr_; delete[] push_frame_ptr_; pop_frame_ptr_ = new char[width_ * hight_ * channels_]; push_frame_ptr_ = new char[width_ * hight_ * channels_]; memset(pop_frame_ptr_, 0x00, width_ * hight_ * channels_); memset(push_frame_ptr_, 0x00, width_ * hight_ * channels_); delete[] pop_exif_ptr_; delete[] push_exif_ptr_; pop_exif_ptr_ = new unsigned char[sizeof(ExifClass)]; push_exif_ptr_ = new unsigned char[sizeof(ExifClass)]; memset(pop_exif_ptr_, 0x00, sizeof(ExifClass)); memset(push_exif_ptr_, 0x00, sizeof(ExifClass)); } memset(push_frame_ptr_, 0x00, width_ * hight_ * channels_); memcpy(push_frame_ptr_, frame, width_ * hight_ * channels_); memset(push_exif_ptr_, 0x00, sizeof(ExifClass)); memcpy(push_exif_ptr_, exif, sizeof(ExifClass)); } const char* pop_frame(void** exif){ CSharedMutex lock(mutex_); std::swap(push_frame_ptr_, pop_frame_ptr_); std::swap(push_exif_ptr_, pop_exif_ptr_); if (nullptr != exif) { *exif = pop_exif_ptr_; } return pop_frame_ptr_; } int size(){ CSharedMutex lock(mutex_); return width_ * hight_ * channels_; } int Width() { CSharedMutex lock(mutex_); return width_; } int Hight() { CSharedMutex lock(mutex_); return hight_; } int Channels() { CSharedMutex lock(mutex_); return channels_; } protected: CFrameCacheWithExif(const CFrameCacheWithExif& rhs){ } CFrameCacheWithExif& operator=(const CFrameCacheWithExif& rhs){ return *this; } private: char* pop_frame_ptr_; unsigned char* pop_exif_ptr_; char* push_frame_ptr_; unsigned char* push_exif_ptr_; int width_, hight_, channels_; CSharedCriticalSection mutex_; };