(HLS播放器之三)播放数据缓存机制之环形buffer

来源:互联网 发布:出国留学数据统计 编辑:程序博客网 时间:2024/05/22 13:14

    Loop buffer, 主要是获取到的播放数据进行缓存。对于HLS播放器的播放数据的处理有比较多的处理模式,如映射文件、LoopBuffer、切片存储等。就要看具体需要了。

 

现在来看这是我自定的LoopBuffer类

class CLoopBuffer{private:CRITICAL_SECTIONm_mutex;__int64m_iBufferSize;/*当前数据管理缓冲区的大小 */__int64m_iVaildLength;/*当前数据缓冲区中有效数据长度*/unsigned char   *m_pBuffer;unsigned char*m_pBufTail;unsigned char*m_pCurRead;unsigned char*m_pCurWrite;boolm_bInterrupt;HANDLEhMutex;boolm_downloadEnd_flag;boolm_isRead;// 阅读判断符boolm_isStop;// 强制终止标记public:CLoopBuffer(__int64 iBufferSize);~CLoopBuffer();__int64_buffer_read(unsigned char* pData, __int64 iDataLen, bool bForceEnough);void_buffer_write(unsigned char* pData, __int64 iDataLen);void_buffer_interrupt();void_buffer_reset();void_buffer_reset_readBegin();__int64 _buffer_getVaildLength();//获取剩余量void_buffer_setReadPos(__int64 pos);        //设置播放位置__int64 _buffer_readLength();void_buffer_stopRead();        //停止读取工作};

 

其中最重要就是标记位置的四个指针:

m_pBuffer:         缓存的头指针

m_pBufTail:       缓存的尾指针

m_pCurRead:    读取位置指针

m_pCurWrite:    写入位置指针

 

现在针对特殊的几个函数进行分析:

 

1、__int64 CLoopBuffer::_buffer_read(unsigned char* pData, __int64 iDataLen, bool bForceEnough)   读取LoopBuffer缓存数据函数

入参分析:

unsigned char* pData :待填充的Buffer

_int64 iDataLen :         需要存储的数据大小

bool  bForceEnough:  是否满填充,true 表示必须填充iDataLen大小的数据,false 反之

 

分析:

1、设定可提供的数据量。如果bForceEnough = true,则表示满数据量填充。不足则需要等待

2、拷贝数据到pData中。如果m_pCurRead到m_pBufTail的数据量小于可读取量,则需要取到尾部数据,和头部到剩余大小的数据。

注意: 等待数据足够时,小心死循环了。其中应该有强制退出标记。

 

__int64CLoopBuffer::_buffer_read(unsigned char* pData, __int64 iDataLen, bool bForceEnough){if (NULL == m_pBuffer){return 0;}__int64 iActualReadLen = iDataLen;__int64 iCurrToEndLen = 0;//1、得到需要提供的数据的长度if(true == bForceEnough){//必须等待有足够的数据可读while(m_iVaildLength < iDataLen){......Sleep(50);}}else{// 能满足条件尽量满足条件,不满足条件时有多少数据读多少数据if(m_iVaildLength < iDataLen){iActualReadLen = m_iVaildLength;}}WaitForSingleObject(hMutex, 1L); //2、根据实际情况Copy数据//得到当前位置距离队列尾的长度iCurrToEndLen = (__int64)(m_pBufTail - m_pCurRead);if(iCurrToEndLen >= iActualReadLen){//如果剩余长度足够,则直接copy并返回memcpy(pData,m_pCurRead, iActualReadLen);m_pCurRead += iActualReadLen;}else{//Step 1:有多少读多少memcpy(pData, m_pCurRead, iCurrToEndLen);//Step 2:移动到头部继续读剩余的数据memcpy(pData+iCurrToEndLen, m_pBuffer, iActualReadLen-iCurrToEndLen);m_pCurRead = m_pBuffer + (iActualReadLen - iCurrToEndLen);}//3、减少当前Buf的长度EnterCriticalSection(&m_mutex);m_iVaildLength -= iActualReadLen;LeaveCriticalSection(&m_mutex);return iActualReadLen;}


2、void CLoopBuffer::_buffer_write(unsigned char* pData, __int64 iDataLen)  写入数据到Loop buffer中

不细说了,和读取有些道理相通的。

void CLoopBuffer::_buffer_write(unsigned char* pData, __int64 iDataLen){__int64 iActualWriteLen = iDataLen;__int64 iCurrToEndLen = 0;//判断写入数据长度有效性if(iActualWriteLen > m_iBufferSize){return;}//等待有足够空间可用于写数据while( (m_iBufferSize - m_iVaildLength) < iDataLen){.....Sleep(100);}//将数据Copy到Buffer中iCurrToEndLen = (__int64)(m_pBufTail - m_pCurWrite); if(iCurrToEndLen >= iDataLen ){//如果剩余长度足够,则直接copy并返回memcpy(m_pCurWrite, pData, iDataLen);m_pCurWrite += iDataLen;}else{//Step 1:能填充多少数据先填充多少数据memcpy(m_pCurWrite, pData, iCurrToEndLen);//Step 2:移动到头部继续填充剩余的数据memcpy(m_pBuffer, pData+iCurrToEndLen, iDataLen-iCurrToEndLen);m_pCurWrite = m_pBuffer + (iDataLen-iCurrToEndLen);}//增加当前buf的长度EnterCriticalSection(&m_mutex);m_iVaildLength += iDataLen;LeaveCriticalSection(&m_mutex);}


其他的函数只要起到控制功能、清空数据等处理。

 

大家一定要注意别出现死循环了。其中有一些While循环,特别关照它呀!

 

 


 

 

原创粉丝点击