特性缓冲区

    技术2022-05-19  18

    现在要处理这样的事:

    从网络中收到未解码的h264裸数据; 解码;然后用 draw 画出来。

     

    如果解码一帧画一帧,图像看起来会走走停停。为了有流畅体验,把解码,显示分开线程处理。

    这就涉及到解码后的数据要先存起来,由于视频数据大小不一,如果每次存数据都直接向系统申请内存,用完后释放,长久运行,会产生内存碎片,造成内存上升的现象。所以,我写了一个缓冲区,类似内存池。

     

    本程序是依据固有特性写的,不通用,不要理解为普通的内存池。

     

    特性:

    1.视频数据,先解码出来的,必将先使用,然后释放;即说明 向 本缓冲区 申请较早的内存,必先于后申请的内存释放,有严格的先后顺序。

    2.本缓冲区是连续的,在使用时,只是用标识符标记起始位置;

     

    #ifndef _MEMMGR_H #define _MEMMGR_H #pragma once #include "OSMutex.h" #include <assert.h> //int gg1 = 0; //int gg11 = 0; //int gg2 = 0; //int gg22 = 0; //int gg3 = 0; //int gg33 =0; template<class T> class CMgrData { public: bool bPool; int iBeginPos; int iEndPos; T* pData; int pDataLen; }; template<class T> class CMemMgr { public: CMemMgr(void) :mDataModule(false) ,mDataBegin(0) ,mDataEnd(0) { } ~CMemMgr(void) { mLargeMemLock.Lock(); if (mLargeMem) free(mLargeMem); } bool Init(int nBlock) { OSMutexLocker _g(&mLargeMemLock); mLargeMem = (T*) malloc(sizeof(T)*nBlock); if (!mLargeMem) return false; mMaxBlock = nBlock; mDataEnd = 0; mDiscardSize = 1024; return true; } bool Malloc(CMgrData<T>* pData,int nElem) { OSMutexLocker _g(&mLargeMemLock); //负载数据处于开模式 if (mDataModule) { if (mDataBegin<mDataEnd) assert(0); if ( nElem <= (mDataBegin - mDataEnd ) ) { pData->bPool = true; pData->iBeginPos = mDataEnd+1; pData->iEndPos = pData->iBeginPos + nElem-1; pData->pData = mLargeMem + pData->iBeginPos; pData->pDataLen = nElem; mDataEnd = pData->iEndPos; gg1++; gg11+=nElem; return true; } } //负载数据处于闭模式 else { if ( nElem <= (mMaxBlock - mDataEnd) ) { pData->bPool = true; pData->iBeginPos = mDataEnd; pData->iEndPos = pData->iBeginPos + nElem-1; pData->pData = mLargeMem + pData->iBeginPos; pData->pDataLen = nElem; mDataEnd = pData->iEndPos+1; gg2++; gg22+=nElem; return true; } if ( mMaxBlock - mDataEnd < mDiscardSize)// 小于一定量,不使用 { mDataEnd = 0; mDataModule = true; } } pData->bPool = false; pData->iBeginPos = 0; pData->iEndPos = 0; pData->pData = (T*)malloc(sizeof(T)*nElem); pData->pDataLen = nElem; gg3++; gg33+=nElem; return false; } bool Free(CMgrData<T>* pData) { OSMutexLocker _g(&mLargeMemLock); if (pData->bPool) { mDataBegin = pData->iEndPos; if ( (mMaxBlock - mDataBegin) < mDiscardSize ) { mDataModule = false; mDataBegin = 0; } //处于头部这一块一定会被重复用到的 if (pData->iBeginPos == 0) mDataModule = false; } else { free(pData->pData); pData->pDataLen = 0; } return true; } private: OSMutex mLargeMemLock; T* mLargeMem; int mMaxBlock; bool mDataModule; int mDataBegin; int mDataEnd; int mDiscardSize; }; #endif /********************************************************** 测试用例 #include "stdafx.h" #include <iostream> #include <stdio.h> #include <list> #include "MemMgr.h" CMemMgr<char> *mem = NULL; OSMutex gListLock; std::list<CMgrData<char>*> gList; DWORD WINAPI fun(void* p) { Sleep(2000); int S = 1000; while(1) { { OSMutexLocker _g(&gListLock); std::list<CMgrData<char>*>::iterator iter = gList.begin(); if (iter != gList.end()) { CMgrData<char>* tmp = (*iter); gList.pop_front(); printf("%s/r/n",tmp->pData); mem->Free(tmp); delete[] tmp; } if (gList.size()>200) S = 50; else if (gList.size()<10) S = 1000; } Sleep(S); } return 0; } void main(void) { mem = new CMemMgr<char>(); int nBlock = 1024*1024*10;//100M mem->Init(nBlock); CMgrData<char> m; char* p = "abc"; mem->Malloc(&m,strlen(p)+1); memcpy(m.pData, p ,strlen(p)+1); printf(":::%s/r/n",m.pData); DWORD id; CreateThread(0,0,&fun,0,0,&id); int i=0; while(1) { int len = rand()2456; CMgrData<char>* m = new CMgrData<char>; assert(m); mem->Malloc(m,len); int t = ++i$; memset(m->pData, 65+t ,1); *(m->pData+1) = '/0'; { OSMutexLocker _g(&gListLock); gList.push_back(m); } Sleep(100); } } **********************************************************/

     


    最新回复(0)