数据读取/写入——环型缓存区

    数据的读取和写入管理,可以通过列表和环型列表来实现,文本使用环型列表来实现数据的读取和写入操作,当写数据超过缓冲区大小时,通过读写位置重复利用已读取的区域写入数据值。

    代码:

/*
描述: 环型缓存区操作类
说明:
	本类对内存做环型缓存区管理
*/

#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;
}


参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:技术工厂 设计师:CSDN官方博客 返回首页

打赏作者

byxdaz

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值