数据的读取和写入管理,可以通过列表和环型列表来实现,文本使用环型列表来实现数据的读取和写入操作,当写数据超过缓冲区大小时,通过读写位置重复利用已读取的区域写入数据值。
代码:
/*
描述: 环型缓存区操作类
说明:
本类对内存做环型缓存区管理
*/
#ifndef __CircleBuffer_H__
#define __CircleBuffer_H__
#pragma once
#include <boost/thread/shared_mutex.hpp>
#include <Windows.h>
using namespace std;
#define Max_Video_Width 1024 //视频宽度
#define Max_Video_Height 720 //视频高度
#define Max_Video_FrameNum 500 //视频最大帧数
//帧类型
typedef enum e_FrameType
{
FrameType_Invalid_Frame = 0, //无效帧
FrameType_Header_Frame = 0x68643030, //头帧('00hd')
FrameType_Video_IFrame = 0x62643030, //视频主帧('00db')
FrameType_Video_VFrame = 0x63643030, //视频虚帧('00dc')
FrameType_Audio_Frame = 0x62773030, //音频帧('00wb')
}FrameType;
//帧数据
typedef struct tagFrameData{
unsigned long long ullTimeStamp; //时间戳
int nFrameType; //帧类型
int nFrameDataLength; //帧数据长度
int nDataBlock1StartPos; //数据块1开始位置(针对m_pBufferData)
int nDataBlock1StopPos; //数据块1结束位置
int nDataBlock2StartPos; //数据块2开始位置
int nDataBlock2StopPos; //数据块2结束位置
}FrameData;
class CircleBuffer
{
public:
CircleBuffer(void);
virtual ~CircleBuffer(void);
//初始化
BOOL Init(int nTotalDataBufferLength,int nFrameSize=Max_Video_FrameNum);
//反初始化
void UnInit();
//剩余可写空间(多少帧)
int RemainWriteFrameNum();
//剩余可读空间(多少帧)
int RemainReadFrameNum();
//获取获取buffer中帧的持续时间
unsigned int GetBufferFrameTime();
//重置帧
void Reset();
//重置帧(保留最后视频I帧之后的数据)
void ResetToSaveVideoIFrame();
//读取一帧数据
int ReadFrameData(int & nFrameType,unsigned char *pFrameData,int & nFrameDataLength);
//写入一帧数据
int WriteFrameData(int nFrameType,unsigned char *pFrameData,int nFrameDataLength);
static int iabs(int x);
protected:
FrameData * m_pAllFrameData; //FrameData指针
int m_nFrameSize; //FrameData个数
int m_nFrameReadPos; //FrameData写位置
int m_nFrameWritePos; //FrameData读位置
int m_nFrameEmptySize; //FrameData剩余大小
unsigned char *m_pBufferData; //内存缓存区指针
int m_nBufferSize; //内存缓存区大小
int m_nBufferReadPos; //内存缓存区读位置
int m_nBufferWritePos; //内存缓存区写位置
int m_nBufferEmptySize; //内存缓存区剩余大小
int m_nLastVideoIFramePos; //最后视频I帧索引
int m_nLastAudioIFramePos; //最后音频帧索引
boost::shared_mutex m_mutexFrameData; //资源列表控制锁
};
#endif
#include "stdafx.h"
#include "CircleBuffer.h"
#include <math.h>
#include <boost/thread.hpp>
#include <boost/function.hpp>
typedef boost::shared_lock<boost::shared_mutex> boost_share_lock;
typedef boost::unique_lock<boost::shared_mutex> boost_unique_lock;
CircleBuffer::CircleBuffer(void)
{
m_nFrameReadPos = 0;
m_nFrameWritePos = 0;
m_nFrameEmptySize = 0;
m_pAllFrameData = NULL;
m_pBufferData = NULL;
m_nBufferReadPos = 0;
m_nBufferWritePos = 0;
m_nBufferEmptySize = 0;
m_nLastVideoIFramePos = -1;
m_nLastAudioIFramePos = -1;
}
CircleBuffer::~CircleBuffer(void)
{
UnInit();
}
int CircleBuffer::iabs(int x)
{
return x>0 ? x:-x;
}
//初始化
BOOL CircleBuffer::Init(int nTotalDataBufferLength,int nFrameSize)
{
if(m_pBufferData)
{
delete []m_pBufferData;
m_pBufferData = NULL;
}
m_pBufferData = new unsigned char[nTotalDataBufferLength];
if(!m_pBufferData)
{
return FALSE;
}
m_nBufferSize = nTotalDataBufferLength;
m_nBufferEmptySize = nTotalDataBufferLength;
m_nBufferReadPos = 0;
m_nBufferWritePos = 0;
m_nFrameSize = nFrameSize;
m_nFrameEmptySize = m_nFrameSize;
m_nFrameReadPos = 0;
m_nFrameWritePos = 0;
m_pAllFrameData = new FrameData[m_nFrameSize];
for(int j=0; j<m_nFrameSize; j++)
{
m_pAllFrameData[j].ullTimeStamp = 0;
m_pAllFrameData[j].nFrameType = 0;
m_pAllFrameData[j].nFrameDataLength = 0;
m_pAllFrameData[j].nDataBlock1StartPos = 0;
m_pAllFrameData[j].nDataBlock1StopPos = 0;
m_pAllFrameData[j].nDataBlock2StartPos = 0;
m_pAllFrameData[j].nDataBlock2StopPos = 0;
}
m_nLastVideoIFramePos = -1;
m_nLastAudioIFramePos = -1;
return TRUE;
}
//反初始化
void CircleBuffer::UnInit()
{
if(m_pBufferData != NULL)
{
delete []m_pBufferData;
m_pBufferData = NULL;
}
if(m_pAllFrameData != NULL)
{
delete [] m_pAllFrameData;
m_pAllFrameData = NULL;
}
}
//剩余可写空间(多少帧)
int CircleBuffer::RemainWriteFrameNum()
{
boost_share_lock lockReader(m_mutexFrameData);
return m_nFrameEmptySize;
}
//剩余可读空间(多少帧)
int CircleBuffer::RemainReadFrameNum()
{
boost_share_lock lockReader(m_mutexFrameData);
return m_nFrameSize - m_nFrameEmptySize;
}
unsigned int CircleBuffer::GetBufferFrameTime()
{
boost_share_lock lockReader(m_mutexFrameData);
unsigned int uiDiffTime = 0;
if(m_nFrameWritePos == m_nFrameReadPos)
{
return 0;
}
else if(m_nFrameWritePos > m_nFrameReadPos)
{
if(m_nFrameReadPos >0)
{
uiDiffTime = m_pAllFrameData[m_nFrameWritePos-1].ullTimeStamp - m_pAllFrameData[m_nFrameReadPos-1].ullTimeStamp;
}
}
else
{
if((m_nFrameWritePos-1) < 0)
{
uiDiffTime = m_pAllFrameData[m_nFrameSize-1].ullTimeStamp - m_pAllFrameData[m_nFrameReadPos-1].ullTimeStamp;
}
else
{
uiDiffTime = m_pAllFrameData[m_nFrameWritePos-1].ullTimeStamp - m_pAllFrameData[m_nFrameReadPos-1].ullTimeStamp;
}
}
return uiDiffTime;
}
//重置帧
void CircleBuffer::Reset()
{
boost_unique_lock lockWriter(m_mutexFrameData);
m_nFrameReadPos = m_nFrameWritePos = 0;
m_nBufferReadPos = m_nBufferWritePos = 0;
m_nBufferEmptySize = m_nBufferSize;
m_nFrameEmptySize = m_nFrameSize;
for(int j=0; j<m_nFrameSize; j++)
{
m_pAllFrameData[j].ullTimeStamp = 0;
m_pAllFrameData[j].nFrameType = 0;
m_pAllFrameData[j].nFrameDataLength = 0;
m_pAllFrameData[j].nDataBlock1StartPos = 0;
m_pAllFrameData[j].nDataBlock1StopPos = 0;
m_pAllFrameData[j].nDataBlock2StartPos = 0;
m_pAllFrameData[j].nDataBlock2StopPos = 0;
}
m_nLastVideoIFramePos = -1;
m_nLastAudioIFramePos = -1;
}
//重置帧(保留最后视频I帧之后的数据)
void CircleBuffer::ResetToSaveVideoIFrame()
{
boost_unique_lock lockWriter(m_mutexFrameData);
if(m_nLastVideoIFramePos != -1)
{
int nFrameNumTmp = 0;
m_nFrameReadPos = m_nLastVideoIFramePos;
if(m_nLastVideoIFramePos > m_nFrameWritePos)
{
nFrameNumTmp = m_nFrameWritePos + m_nFrameSize - m_nLastVideoIFramePos;
}
else
{
nFrameNumTmp = m_nFrameWritePos - m_nLastVideoIFramePos;
}
m_nFrameEmptySize = m_nFrameSize - nFrameNumTmp;
}
else
{
m_nFrameReadPos = m_nFrameWritePos = 0;
m_nBufferReadPos = m_nBufferWritePos = 0;
m_nBufferEmptySize = m_nBufferSize;
m_nFrameEmptySize = m_nFrameSize;
for(int j=0; j<m_nFrameSize; j++)
{
m_pAllFrameData[j].ullTimeStamp = 0;
m_pAllFrameData[j].nFrameType = 0;
m_pAllFrameData[j].nFrameDataLength = 0;
m_pAllFrameData[j].nDataBlock1StartPos = 0;
m_pAllFrameData[j].nDataBlock1StopPos = 0;
m_pAllFrameData[j].nDataBlock2StartPos = 0;
m_pAllFrameData[j].nDataBlock2StopPos = 0;
}
m_nLastVideoIFramePos = -1;
m_nLastAudioIFramePos = -1;
}
}
//读取一帧数据
int CircleBuffer::ReadFrameData(int & nFrameType,unsigned char *pFrameData,int & nFrameDataLength)
{
boost_unique_lock lockWriter(m_mutexFrameData);
int nRemainFrameNum = 0;
nRemainFrameNum = m_nFrameSize - m_nFrameEmptySize;
if(nRemainFrameNum < 1)
{
//没有数据帧,可读
return -1;
}
if(nFrameDataLength < m_pAllFrameData[m_nFrameReadPos].nFrameDataLength)
{
return -2;//数据缓冲区空间不够
}
nFrameType = m_pAllFrameData[m_nFrameReadPos].nFrameType;
nFrameDataLength = m_pAllFrameData[m_nFrameReadPos].nFrameDataLength;
int nLen1 = m_pAllFrameData[m_nFrameReadPos].nDataBlock1StopPos - m_pAllFrameData[m_nFrameReadPos].nDataBlock1StartPos;
if(nLen1 != 0 && nLen1 == nFrameDataLength)
{
memcpy(pFrameData,m_pBufferData+m_pAllFrameData[m_nFrameReadPos].nDataBlock1StartPos,nLen1);
}
else
{
int nLen2 = m_pAllFrameData[m_nFrameReadPos].nDataBlock2StopPos - m_pAllFrameData[m_nFrameReadPos].nDataBlock2StartPos;
if(nLen2 != 0)
{
memcpy(pFrameData,m_pBufferData+m_pAllFrameData[m_nFrameReadPos].nDataBlock1StartPos,nLen1);
memcpy(pFrameData+nLen1,m_pBufferData,nLen2);
}
}
if(m_pAllFrameData[m_nFrameReadPos].nDataBlock1StopPos == m_nBufferSize && m_pAllFrameData[m_nFrameReadPos].nDataBlock2StopPos != 0)
{
m_nBufferReadPos = m_pAllFrameData[m_nFrameReadPos].nDataBlock2StopPos;
}
else
{
m_nBufferReadPos = m_pAllFrameData[m_nFrameReadPos].nDataBlock1StopPos;
}
m_nBufferEmptySize +=nFrameDataLength;
if(m_nBufferEmptySize >= m_nBufferSize)
{
m_nBufferEmptySize = m_nBufferSize;
}
if(m_nLastVideoIFramePos != -1 && m_nFrameReadPos == m_nLastVideoIFramePos)
{
m_nLastVideoIFramePos = -1;
}
if(m_nLastAudioIFramePos != -1 && m_nFrameReadPos == m_nLastAudioIFramePos)
{
m_nLastAudioIFramePos = -1;
}
m_nFrameReadPos++;
if(m_nFrameReadPos >= m_nFrameSize)
{
m_nFrameReadPos = 0;
}
m_nFrameEmptySize++;
if(m_nFrameEmptySize >= m_nFrameSize)
{
m_nFrameEmptySize = m_nFrameSize;
}
return 0;
}
//写入一帧数据
int CircleBuffer::WriteFrameData(int nFrameType,unsigned char *pFrameData,int nFrameDataLength)
{
boost_unique_lock lockWriter(m_mutexFrameData);
if(m_nFrameEmptySize < 1)
{
//超过帧最大数,不可写入
return -1;
}
if(m_nBufferEmptySize < nFrameDataLength)
{
return -2;//数据缓冲区空间不够
}
memcpy((void *)&m_pAllFrameData[m_nFrameWritePos].ullTimeStamp,(void *)pFrameData,8);//时间戳
m_pAllFrameData[m_nFrameWritePos].nFrameType = nFrameType;
m_pAllFrameData[m_nFrameWritePos].nFrameDataLength = nFrameDataLength;
if((m_nBufferSize - m_nBufferWritePos) >= nFrameDataLength)
{
memcpy(m_pBufferData+m_nBufferWritePos,pFrameData,nFrameDataLength);
m_pAllFrameData[m_nFrameWritePos].nDataBlock1StartPos = m_nBufferWritePos;
m_pAllFrameData[m_nFrameWritePos].nDataBlock1StopPos = m_nBufferWritePos+nFrameDataLength;
m_pAllFrameData[m_nFrameWritePos].nDataBlock2StartPos = 0;
m_pAllFrameData[m_nFrameWritePos].nDataBlock2StopPos = 0;
m_nBufferEmptySize -=nFrameDataLength;
m_nBufferWritePos +=nFrameDataLength;
}
else
{
int len1 = m_nBufferSize - m_nBufferWritePos;
int len2 = nFrameDataLength - len1;
memcpy(m_pBufferData+m_nBufferWritePos,pFrameData,len1);
memcpy(m_pBufferData,pFrameData,len2);
m_pAllFrameData[m_nFrameWritePos].nDataBlock1StartPos = m_nBufferWritePos;
m_pAllFrameData[m_nFrameWritePos].nDataBlock1StopPos = m_nBufferWritePos+len1;
m_pAllFrameData[m_nFrameWritePos].nDataBlock2StartPos = 0;
m_pAllFrameData[m_nFrameWritePos].nDataBlock2StopPos = len2;
m_nBufferEmptySize -=nFrameDataLength;
m_nBufferWritePos = len2;
}
//记录最后音频,视频帧
if(nFrameType == FrameType_Video_IFrame)
{
m_nLastVideoIFramePos = m_nFrameWritePos;
}
else if(nFrameType == FrameType_Audio_Frame)
{
m_nLastAudioIFramePos = m_nFrameWritePos;
}
m_nFrameWritePos++;
if(m_nFrameWritePos >= m_nFrameSize)
{
m_nFrameWritePos = 0;
}
m_nFrameEmptySize--;
if(m_nFrameEmptySize <= 0)
{
m_nFrameEmptySize = 0;
}
if(m_nBufferEmptySize <= 0)
{
m_nBufferEmptySize = 0;
}
return 0;
}