看流星社区

 找回密码
 注册账号
查看: 2179|回复: 0

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

[复制链接]

该用户从未签到

发表于 2017-6-3 14:25:49 | 显示全部楼层 |阅读模式
数据的读取和写入管理,可以通过列表和环型列表来实现,文本使用环型列表来实现数据的读取和写入操作,当写数据超过缓冲区大小时,通过读写位置重复利用已读取的区域写入数据值。
代码:

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

#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 &amp; nFrameType,unsigned char *pFrameData,int &amp; 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 &amp; nFrameType,unsigned char *pFrameData,int &amp; 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 &amp;&amp; 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 &amp;&amp; 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 &amp;&amp; m_nFrameReadPos == m_nLastVideoIFramePos)
        {
                m_nLastVideoIFramePos = -1;
        }
        if(m_nLastAudioIFramePos != -1 &amp;&amp; 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 *)&amp;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;
}
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-4-20 05:22

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表