上一篇的改进,支持c++,主要是对 C++ 类成员函数作为外部回调的处理。
关于这个c++ 类成员函数作为回调函数,还是有点意思的,有其他博文介绍的好几种方法,后续再论。
代码:
/***
***20181221 canok
*** brIEf : Combine data fragments into complete frames
*** input : Continuous data flow,support fix length data input;
*** output: complete frames
**/
#include
#include
#include
#include
#include
#include
typedef unsigned char uint8_t; //无符号8位数
#define ERRO_INFO(fmt,args...) do {printf("[%s,%s,%d]",__file__,__FUNCTION__,__liNE__);printf(fmt,##args);} while(0)
#define DEBUG(fmt,args...) do {printf("[%s,##args);} while(0)
typedef int (*FUN_GETinputDATA)(voID *pclass,uint8_t *buf,int buflen);
typedef int (*FUN_PUTOUTDATA)(voID *pclass,int buflen);
typedef int (*FUN_StopCALLED)(voID *pclass,voID*pram);
#define DATAlink_IN_BACK(classtype,callfun) static int intput (voID* pclass,int buflen)
{
classtype *pCall = (classtype *)pclass;
if(pCall)
{
return pCall->callfun(buf,buflen);
}
}
#define DATAlink_OUT_BACK(classtype,callfun) static int output (voID* pclass,buflen);
}
}
#define DATAlink_Stop_BACK(classtype,callfun) static int stop (voID* pclass,voID *pram)
{
classtype *pCall = (classtype *)pclass;
if(pCall)
{
return pCall->callfun(buf,buflen);
}
}
class cdatalinkup
{
public:
cdatalinkup(int maxframelen,int fixreadlen);
~cdatalinkup();
voID setDatainputCallback(voID *pclass,FUN_GETinputDATA input);
voID setDataOutputCallback(voID *pclass,FUN_PUTOUTDATA output);
voID setDataMark(uint8_t *mark,int marklen);
voID start();
voID stop();
voID setStopCallback(voID *pclass,FUN_StopCALLED stopcallback);
voID *workThread(voID *pParam);
private:
inline bool checkhead(uint8_t *buffer,int offset);
inline int findhead(uint8_t *buffer,int offset,int len);
voID initBuffer(int *mNaluold,int* mNaluNew,int *readOffsetold,int*readOffsetCur);
int getData(int offset);
private:
FUN_GETinputDATA fun_getinputData;
FUN_PUTOUTDATA fun_putOutData;
FUN_StopCALLED fun_stopcalled;
voID *pclassinput;
voID *pclassOut;
voID *pclassstop;
uint8_t *mBuffer;
uint8_t *mMark;
uint8_t *mBuffadd;
int mBufferlen;
int mMarklen;
int mBuffaddlen;
int mBuffadddatalen;
int mfixreadlen;//每次输入数据长度
bool mbrun;
};
static voID *ThreadBody(voID *pdat)
{
cdatalinkup *pDatalink = (cdatalinkup *)pdat;
if(pDatalink)
{
pDatalink->workThread(NulL);
}
return NulL;
}
inline bool cdatalinkup::checkhead(uint8_t *buffer,int offset)
{
if(NulL == mMark)
{
ERRO_INFO("erro !please setMark firstlyn");
return 0;
}
return !memcmp(buffer+offset,mMark,mMarklen);
}
inline int cdatalinkup::findhead(uint8_t *buffer,int len)
{
int i;
if (len < mMarklen) {
DEBUG("too short len %d n",len);
return 0;
}
int maxoffset = offset+len;
//DEBUG("len %d %dn",len,maxoffset);
for (i = offset; i <= maxoffset - mMarklen; i++) {
if (checkhead(buffer,i)){
return i;
}
}
return 0;
}
cdatalinkup::cdatalinkup(int maxframelen,int fixreadlen)
{
fun_getinputData = NulL;
fun_putOutData = NulL;
fun_stopcalled = NulL;
mbrun = false;
mBufferlen = maxframelen*8;//最长帧内容倍数
mMarklen = 0;
mBuffaddlen = fixreadlen;
mfixreadlen = fixreadlen;
mMark = NulL;
mBuffer = (uint8_t*)malloc(mBufferlen);
mBuffadd = (uint8_t*)malloc(mBuffaddlen);
if(NulL == mBuffer || NulL == mBuffadd)
{
ERRO_INFO("erro to malloc! mBufferlen %d,mBuffaddlen,%dn",mBufferlen,mBuffaddlen);
}
memset(mBuffer,mBufferlen);
memset(mBuffadd,mBuffaddlen);
}
cdatalinkup::~cdatalinkup()
{
if(mBuffer)
{
free(mBuffer);
}
}
voID cdatalinkup::setDataMark(uint8_t *mark,int marklen)
{
if(NulL==mark)
{
ERRO_INFO("parm erro n");
return ;
}
if(mMark)
{
free(mMark);
}
mMark = (uint8_t*)malloc(marklen);
if(NulL == mMark)
{
ERRO_INFO("malloc erro marklen :%dn",marklen);
}
memcpy(mMark,mark,marklen);
mMarklen = marklen;
};
voID cdatalinkup::setDatainputCallback(voID *pclass,FUN_GETinputDATA input)
{
pclassinput = pclass;
fun_getinputData = input;
}
voID cdatalinkup::setDataOutputCallback(voID *pclass,FUN_PUTOUTDATA output)
{
pclassOut = pclass;
fun_putOutData = output;
}
voID cdatalinkup::setStopCallback(voID *pclass,FUN_StopCALLED stopcallback)
{
pclassstop = pclass;
fun_stopcalled = stopcallback;
}
voID cdatalinkup::start()
{
if(fun_getinputData == NulL || fun_putOutData == NulL || mMark == NulL)
{
DEBUG("erro to start,please check init!");
return ;
}
mbrun = true;
int iRet;
pthread_t pID;
//iRet = pthread_create(&pID,NulL,(voID* (*)(voID*))&cdatalinkup::workThread,0);
iRet = pthread_create(&pID,ThreadBody,this);
if (iRet != 0)
{
printf("[%d %s]pthread_create Failed (%d)n",__liNE__,iRet);
}
else
{
pthread_detach(pID);
}
}
voID cdatalinkup::stop()
{//加锁等待完全退出才返回
mbrun = false;
}
voID cdatalinkup::initBuffer(int *mNaluold,int*readOffsetCur)
{
int naulflag =0;
int datalen =0;
while(naulflag<=0)
{
int ret = getData(datalen);
if(ret > 0)
{
datalen +=ret;
naulflag = findhead(mBuffer,datalen);
}
else
{
break;
}
}
*mNaluold= naulflag;
*readOffsetold = datalen;
*readOffsetCur = *readOffsetold;
DEBUG("init %d %d n",*readOffsetCur,*readOffsetold);
}
//调用输入接口读取固定长度数据到mBuffer缓冲区
//如果缓冲区已经溢出,溢出部分数据会被存储在mBuffadd 特定位置,且mBuffadddatalen被设置
int cdatalinkup::getData(int offset)
{
int fixreadlen = mfixreadlen;
int remainlen = mBufferlen- offset;
int copylen = remainlen int ret = 0; if(copylen < fixreadlen) { ret = fun_getinputData(pclassinput,mBuffadd,fixreadlen); if(ret < fixreadlen) { mbrun = false; DEBUG("getinput %d fixreadlen %dn",ret,fixreadlen); return 0; } //DEBUG("full !n"); memcpy(mBuffer+offset,copylen); mBuffadddatalen = fixreadlen - copylen; } else { //DEBUG("offset %d n",offset); ret = fun_getinputData(pclassinput,mBuffer+offset,fixreadlen); return 0; } mBuffadddatalen = 0; } return copylen; } voID *cdatalinkup::workThread(voID *pParam) { int mNaluold = 0; int mNaluNew =0; int readOffsetold = 0; int readOffsetCur =0; bool bFirst = true; bool bFull = false;//是否溢出 int checkbaklen = 2 * (mMarklen-1); uint8_t *checkbak = (uint8_t*)malloc(checkbaklen); uint8_t *framebuffer = mBuffer; int readdata = 0; if(framebuffer == NulL) { ERRO_INFO("erro,mBuffer NulL n"); return NulL; } while(mbrun) { //usleep(100);// if (bFirst) { initBuffer(&mNaluold,&mNaluNew,&readOffsetold,&readOffsetCur); bFirst =false; } //printf("wang %d %s readOffsetold %d n",readOffsetold); if(!bFull) { readdata = getData(readOffsetold); if(readdata == 0) { mbrun = false; DEBUG("getdata erron"); break; } readOffsetCur += readdata; } // 从帧缓冲中找 h264 NALU 开始标记 if (bFull) { // 已经溢出,数据不连续,跨断 memcpy(checkbak+mMarklen-1,framebuffer,mMarklen-1); //uint8_t temp[4]={0x0,0x0,0x01}; //memcpy(checkbak,temp,checkbaklen); //printf("%#x %#x %#x %#x n",checkbak[0],checkbak[1],checkbak[2],checkbak[3]); //printf("%#x %#x %#x n",mMark[0],mMark[1],mMark[2]); mNaluNew = findhead(checkbak,checkbaklen); if(mNaluNew >0 ) { mNaluNew+=mBufferlen-mMarklen-1; fun_putOutData(pclassOut,framebuffer+mNaluold,mNaluNew-mNaluold); DEBUG("specificn"); mNaluold = mNaluNew; } { mNaluNew = findhead(framebuffer,readOffsetold); while(!mNaluNew) { readdata = getData(readOffsetold); if(readdata == 0) { mbrun = false; DEBUG("getdata erron"); break; } readOffsetCur += readdata; mNaluNew = findhead(framebuffer,readOffsetold-(mMarklen-1),readOffsetCur - readOffsetold); readOffsetold = readOffsetCur; } } int olddatalen = mBufferlen - mNaluold; // //找到一完整帧,输出 uint8_t *ptemp =(uint8_t*)malloc(olddatalen+mNaluNew); memset(ptemp,olddatalen+mNaluNew); if(ptemp == NulL) { //printf("wang %d %s malloc fialed len :%d n",olddatalen+mNaluNew); return NulL; } memcpy(ptemp,olddatalen); memcpy(ptemp+olddatalen,mNaluNew); fun_putOutData(pclassOut,ptemp,olddatalen+mNaluNew); free(ptemp); bFull = false; mNaluold = mNaluNew; } else { //TRACK("readOffsetold %d readOffsetcur %dn",readOffsetold,readOffsetCur); mNaluNew = findhead(framebuffer,readOffsetCur - readOffsetold); if (mNaluNew > 0) { // //找到一完整帧,输出 int framelen = mNaluNew - mNaluold; fun_putOutData(pclassOut,framelen); mNaluold = mNaluNew; } if(readOffsetCur >= mBufferlen) { // 已经溢出,需要拿新的数据 readOffsetCur = 0; readOffsetold = 0; bFull = true; if(mBuffadddatalen>0) {//溢出的数据拷贝回来 memcpy(framebuffer,mBuffadd+(mfixreadlen-mBuffadddatalen),mBuffadddatalen); readOffsetCur = mBuffadddatalen; //fun_putOutData(pclassOut,mBuffadddatalen); //break; } else { readdata = getData(readOffsetold); if(readdata == 0) { mbrun = false; DEBUG("getdata erron"); break; } readOffsetCur += readdata; } readOffsetold = readOffsetCur; // 避免出现跨端区的NALL漏检 memcpy(checkbak,framebuffer+mBufferlen-(mMarklen-1),mMarklen-1); } else { readOffsetold = readOffsetCur; } } } free(checkbak); if(fun_stopcalled) { fun_stopcalled(pclassstop,NulL); } return NulL; } class CTest { public : CTest(const char*fin,const char*fout); ~Ctest(); int readdata(uint8_t * buf,int buflen); int putdata(uint8_t * buf,int buflen); voID* init(); DATAlink_IN_BACK(CTest,readdata); DATAlink_OUT_BACK(CTest,putdata); /* static int intput (voID* pclass,int buflen) { CTest *pCall= (CTest *)pclass; //DEBUG("pclass %pn",pclass); if(pCall) { return pCall->readdata(buf,buflen); } } static int output (voID* pclass,int buflen) { CTest *pCall= (CTest *)pclass; if(pCall) { return pCall->putdata(buf,buflen); } }*/ private: file *mfpin; file *mfpout; cdatalinkup *datalink; }; /* int CTest::intput (voID* pclass,buflen); } return 0; } int CTest::output(voID* pclass,buflen); } }*/ CTest::CTest(const char*fin,const char*fout) { mfpin= fopen(fin,"rb"); mfpout = fopen(fout,"w+"); if(mfpin == NulL || mfpout == NulL) { ERRO_INFO("fopen erro n"); } } CTest::~Ctest() { if(mfpin) { fclose(mfpin); } if(mfpout) { fclose(mfpout); } } voID* CTest::init() { uint8_t mark[3]={0x0,0x01}; datalink = new cdatalinkup(200*1024,1024*80); datalink->setDatainputCallback(this,intput); datalink->setDataOutputCallback(this,output); datalink->setDataMark(mark,sizeof(mark)); datalink->start(); return this; } int CTest::readdata(uint8_t * buf,int buflen) { int ret = fread(buf,1,buflen,mfpin); DEBUG("input %dn",ret); return ret; } int CTest::putdata(uint8_t * buf,int buflen) { int ret = fwrite(buf,mfpout); DEBUG("output %d buflen %dn",buflen); return ret; } #if 0 //for c file*fpin = NulL; file*fpout = NulL; uint8_t count =0; int maxlen =0; int datainput(voID * pclass,uint8_t * buf,fpin); //DEBUG("input %dn",ret); return ret; } int dataoutput(voID * pclass,int buflen) { count ++; if(buflen >maxlen) { maxlen = buflen; } fwrite(&count,fpout); int ret = fwrite(buf,fpout); DEBUG("output %d buflen %dn",buflen); return ret; } int fileclose(voID * pclass,voID *pram) { DEBUG("over maxlen %d n",maxlen); fclose(fpin); fclose(fpout); } int main(int argc,const char* argv[]) { if(argc != 3){ printf("usage :input file,output file!n"); return -1; } fpin = fopen(argv[1],"rb"); fpout = fopen(argv[2],"w+"); if(fpin == NulL || fpout == NulL){ printf("fopen erro n"); return -1; } uint8_t mark[3]={0x0,0x01}; cdatalinkup *datalink = new cdatalinkup(200*1024,1024*80); datalink->setDatainputCallback(NulL,datainput); datalink->setDataOutputCallback(NulL,dataoutput); datalink->setDataMark(mark,sizeof(mark)); datalink->setStopCallback(NulL,fileclose); datalink->start(); //while(1); //主线程退出,如果直接return则会导致调用eixt把整个进程结束 pthread_exit(NulL); } #endif #if 1//for c++ int main(int argc,output file!n"); return -1; } CTest *pTest = new CTest(argv[1],argv[2]); pTest->init(); pthread_exit(NulL); //一定要在pthread_exit之后,保证回调里面调用时这个pTest对象还存在 delete pTest; } #endif 以上是内存溢出为你收集整理的网络数据包片段拼合(连续h264片段拼接成完整h264帧)(二支持c++调用)全部内容,希望文章能够帮你解决网络数据包片段拼合(连续h264片段拼接成完整h264帧)(二支持c++调用)所遇到的程序开发问题。 如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。 欢迎分享,转载请注明来源:内存溢出
评论列表(0条)