网络数据包片段拼合(连续h264片段拼接成完整h264帧)(二支持c++调用)

网络数据包片段拼合(连续h264片段拼接成完整h264帧)(二支持c++调用),第1张

概述本文章向大家介绍网络数据包片段拼合(连续h264片段拼接成完整h264帧)(二支持c++调用),主要包括网络数据包片段拼合(连续h264片段拼接成完整h264帧)(二支持c++调用)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

上一篇的改进,支持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++调用)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1264369.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存