视频帧双缓冲区的两个版本
视频帧双缓冲区的第一个版本,仅缓冲视频帧,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_;
};