继上一篇的优化改进,将主控制权交给外部调用者。

代码:

/***
***20181221 canok
***  brief : Combine data fragments into complete frames
*** input : Continuous data flow, support fix length data input;
*** output: complete frames
**/
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>#include <string.h>
#include <errno.h>#include <pthread.h>
typedef unsigned char   uint8_t;     //无符号8位数
#define ERRO_INFO(fmt, args...) do {printf("[%s,%s,%d]",__FILE__,__FUNCTION__,__LINE__);printf(fmt,##args);} while(0)
#if 0
#define DEBUG(fmt, args...)     do {printf("[%s,%s,%d]",__FILE__,__FUNCTION__,__LINE__);printf(fmt,##args);} while(0)
#else
#define DEBUG(fmt, args...)
#endif
typedef int (*FUN_GETINPUTDATA)(void *pclass,uint8_t *buf,int buflen);
typedef int (*FUN_PUTOUTDATA)(void *pclass,uint8_t *buf,int buflen);#define DATALINK_IN_BACK(classtype,callfun) static int intput (void* pclass ,uint8_t *buf,int buflen)\{                                         \classtype *pCall = (classtype *)pclass;   \if(pCall)                              \{                                      \return pCall->callfun(buf,buflen);  \}                                      \}#define DATALINK_OUT_BACK(classtype,callfun) static int output (void* pclass ,uint8_t *buf,int buflen)\{                                          \classtype *pCall = (classtype *)pclass;   \if(pCall)                              \{                                      \return pCall->callfun(buf,buflen);  \}                                      \}#define MAX(a,b) (a)>(b)?(a):(b)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 ClearBuffer();int pushData(int buflen);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,int len);private:FUN_GETINPUTDATA fun_getInputData;FUN_PUTOUTDATA fun_putOutData;void *pclassInput;void *pclassOut;uint8_t *mBuffer;uint8_t *mMark;uint8_t *mBuffInputadd;uint8_t *mBuffOutadd;int mBufferlen;int mMarklen;int mBuffaddlen;int mBuffadddatalen;int mBuffOutlen;int mNalu;int readOffset;bool bFirst ;bool bFull ;//是否溢出int checkbaklen ;uint8_t *checkbak;};inline  bool CDataLinkup::checkHead(uint8_t *buffer, int offset)
{if(NULL == mMark){   ERRO_INFO("erro !please setMark firstly\n");return 0;}return !memcmp(buffer+offset,mMark,mMarklen);
}inline int CDataLinkup::findHead(uint8_t *buffer, int offset, int len)
{int i;if (len < mMarklen) {DEBUG("too short len %d \n",len);return 0;}int maxoffset = offset+len;//DEBUG("len %d %d\n",len,maxoffset);for (i = offset; i <= maxoffset - mMarklen; i++) {if (checkHead(buffer, i)){return i;}}return 0;
}CDataLinkup::CDataLinkup(int maxframelen,int maxreadlen)
{fun_getInputData =  NULL;fun_putOutData = NULL;  mBufferlen = maxframelen*8;//最长帧内容倍数mMarklen = 0;mBuffaddlen = maxreadlen;mBuffOutlen = maxframelen;mMark = NULL;mBuffer = (uint8_t*)malloc(mBufferlen);mBuffInputadd = (uint8_t*)malloc(mBuffaddlen);mBuffOutadd = (uint8_t*)malloc(mBuffOutlen);if(NULL == mBuffer || NULL == mBuffInputadd || NULL == mBuffOutadd){ERRO_INFO("erro to malloc! mBufferlen %d,mBuffaddlen,%d, mBuffOutlen %d \n",mBufferlen,mBuffaddlen,mBuffOutlen);}memset(mBuffer,0,mBufferlen);memset(mBuffInputadd,0,mBuffaddlen);memset(mBuffOutadd,0,mBuffOutlen);
}CDataLinkup::~CDataLinkup()
{if(mBuffer){free(mBuffer);}if(mBuffInputadd){free(mBuffInputadd);}if(mMark){free(mMark);}if(mBuffOutadd){free(mBuffOutadd);}
}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 :%d\n",marklen);}memcpy(mMark,mark,marklen);mMarklen = marklen;checkbaklen = 2 * (mMarklen-1);checkbak = (uint8_t*)malloc(checkbaklen);if(checkbak == mMark){ERRO_INFO("malloc erro marklen :%d\n",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;
}//调用输入接口读取指定长度数据到mBuffer缓冲区
//如果缓冲区已经溢出,溢出部分数据会被存储在mBuffInputadd 特定位置,且mBuffadddatalen被设置
int CDataLinkup::getData(int offset,int len)
{int remainlen = mBufferlen- offset;int copylen = remainlen<len?remainlen:len;int ret = 0;if(copylen < len){if(len>mBuffaddlen){ERRO_INFO("input too large !lost data len:%d,mBuffaddlen:%d \n ",len,mBuffaddlen);}ret = fun_getInputData(pclassInput,mBuffInputadd,len);if(ret < len){//mbrun = false;DEBUG("getinput %d len %d\n",ret,len);return 0;}//DEBUG("full !\n");memcpy(mBuffer+offset,mBuffInputadd,copylen);mBuffadddatalen = len - copylen;}else {    //DEBUG("offset %d \n",offset);ret = fun_getInputData(pclassInput,mBuffer+offset,len);if(ret < len){//mbrun = false;DEBUG("getinput %d len %d\n",ret,len);return 0;}mBuffadddatalen = 0;}return copylen;}
void CDataLinkup::ClearBuffer()
{mNalu =0;mNalu =0;readOffset =0;bFirst = true;bFull = false;//是否溢出
}
int CDataLinkup::pushData(int buflen)
{uint8_t *framebuffer = mBuffer;int ret = getData(readOffset,buflen);if(ret == 0){DEBUG("getData erro!\n");return -1;}if (bFirst) {int naulflag = findHead(mBuffer,MAX(readOffset-(mMarklen-1),0), ret);if(naulflag>0){bFirst = false;mNalu= naulflag;}readOffset +=ret;}else{if(!bFull){int naulflag  = findHead(framebuffer, readOffset-(mMarklen-1), ret);if (naulflag > 0) {// //找到一完整帧,输出int framelen = naulflag - mNalu;fun_putOutData(pclassOut,framebuffer+mNalu,framelen);mNalu = naulflag;} if(mBuffadddatalen>0){// 溢出bFull = true;//溢出的数据拷贝回来memcpy(framebuffer,mBuffInputadd+ret,mBuffadddatalen);readOffset= mBuffadddatalen;// 避免出现跨端区的NALL漏检memcpy(checkbak,framebuffer+mBufferlen-(mMarklen-1),mMarklen-1);}else{readOffset += ret;}}else{// 上次溢出,数据不连续, 跨断memcpy(checkbak+mMarklen-1,framebuffer,mMarklen-1);//uint8_t temp[4]={0x0,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]);int naulflag  = findHead(checkbak, 0, checkbaklen);if(naulflag >0 ){naulflag+=mBufferlen-mMarklen-1;fun_putOutData(pclassOut,framebuffer+mNalu,naulflag-mNalu);DEBUG("specific\n");mNalu = naulflag;}naulflag = findHead(framebuffer, 0, readOffset+ret);if(naulflag>0){int olddatalen = mBufferlen - mNalu;// //找到一完整帧,输出if(naulflag+olddatalen>mBuffOutlen){ERRO_INFO("maxframlen too short mBuffOutlen %d\n",mBuffOutlen);}memcpy(mBuffOutadd,framebuffer+mNalu,olddatalen);memcpy(mBuffOutadd+olddatalen,framebuffer,naulflag);fun_putOutData(pclassOut,mBuffOutadd,olddatalen+naulflag);bFull = false;mNalu = naulflag;}readOffset += ret;}}return ret;
}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* work();DATALINK_IN_BACK(CTest,readdata);DATALINK_OUT_BACK(CTest,putdata);/*static int intput (void* pclass ,uint8_t *buf,int buflen){CTest *pCall= (CTest *)pclass;//DEBUG("pclass %p\n",pclass);if(pCall){return pCall->readdata(buf,buflen);}}static int output (void* pclass ,uint8_t *buf,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 ,uint8_t *buf,int buflen)
{CTest *pCall= (CTest *)pclass;//DEBUG("pclass %p\n",pclass);if(pCall){return pCall->readdata(buf,buflen);}return 0;
}int CTest::output(void* pclass ,uint8_t *buf,int buflen)
{CTest *pCall= (CTest *)pclass;if(pCall){return pCall->putdata(buf,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::work()
{uint8_t mark[3]={0x0,0x0,0x01};datalink = new CDataLinkup(200*1024,1024*80);datalink->setDataInputCallback(this,intput);datalink->setDataOutputCallback(this,output);datalink->setDataMark(mark,sizeof(mark));datalink->ClearBuffer();while(datalink->pushData(1046) != -1);delete datalink;datalink = NULL;return this;
}
int CTest::readdata(uint8_t * buf,int buflen)
{int ret = fread(buf,1,buflen,mfpin);DEBUG("input  %d\n",ret);return ret;
}
int CTest::putdata(uint8_t * buf,int buflen)
{int ret = fwrite(buf,1,buflen,mfpout);DEBUG("output  %d buflen %d\n",ret,buflen);return ret;}#if 1//for c++
int main(int argc, const char* argv[])
{if(argc != 3){printf("usage :input file, output file!\n");return -1;}CTest *pTest = new CTest(argv[1],argv[2]);pTest->work();pthread_exit(NULL);//一定要在pthread_exit之后,保证回调里面调用时这个pTest对象还存在delete pTest;
}
#endif

网络数据包片段拼合(连续h264片段拼接成完整h264 slice)(三)循环体移到外部调用,便于调用者控制相关推荐

  1. 网络数据包片段拼合(连续h264片段拼接成完整h264帧)--纠正下,是h264 slice,不是图像帧

    最近项目用的网络摄像头,从网络层获取到连续的h264片段数据,于是写了一个将连续输入数据按 指定字符串分割成一个slice数据的 class, 稍作改动,也可以用来处理 文本文件中查找 替换等等功能, ...

  2. Packet Chasing:通过缓存侧信道监视网络数据包

    摘要 本文介绍了一种对网络的攻击–Packet Chasing,这种攻击不需要访问网络,无论接收数据包的进程的特权级别如何,都能发挥作用.一个间谍进程可以很容易地探测和发现网络驱动程序使用的每个缓冲区 ...

  3. linux接收网络数据并存存储,linux网络数据包数据结构 Socket Buffer

    Linux网络核心数据结构是套接字缓存(socket buffer),简称skb.它代表一个要发送或处理的报文,并贯穿于整个协议栈.1.套接字缓存skb由两部分组成:(1)报文数据:它保存了实际在网络 ...

  4. tcpdump 网络数据包分析工具

    简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...

  5. 【php毕业设计】基于php+mysql+apache的网络数据包分析工具设计与实现(毕业论文+程序源码)——网络数据包分析工具

    基于php+mysql+apache的网络数据包分析工具设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于php+mysql+apache的网络数据包分析工具设计与实现,文章末尾附有本毕业设 ...

  6. 常用网络数据包丢失的分析与处理

    网络管理维护过程中,经常会遇到数据包丢失的情况.用Ping命令进行连接测试,会发现Ping包的延迟远远超过正常值,甚至无法到达,同时伴随着网络服务应用的障碍,比如打开网站的速度太慢,严重时甚至无法打开 ...

  7. Jpcap JAVA捕捉并分析网络数据包

    读书时候,曾经做过一个sniffer软件.主要的开发语言是JAVA.主要的作用有很多,但是我个人测试的效果估计要比臭名远扬的绿坝要好了.主要的设计不是用于控制人家上网,这个软件业做技术统计,主要是用来 ...

  8. 网络数据包分析软件Wireshark简介

    Wireshark是被广泛使用的免费开源的网络协议分析软件(network protocol analyzer)或网络数据包分析软件,它可以让你在微观层面上查看网络上发生的事情,它的功能是截取网络数据 ...

  9. 一个最简单的通过WireShark破解SSL加密网络数据包的方法

    原文地址: http://article.yeeyan.org/view/530101/444688 一般来说,我们用WireShark来抓取包进行分析是没有多大问题的.但这里有个问题是,如果你碰到的 ...

最新文章

  1. CVPR2019 日程安排
  2. 【美国】谷歌重返机器人背后有何深意?
  3. 修改Eclipse中项目在Apache Tomcat中的部署路径
  4. IBM等创建开放虚拟化联盟对抗VMware
  5. AI修复技术为何这么强?原来背后的技术是……
  6. (转)getElementByID getElementsByName getElementsByTagName用法详解
  7. iOS自动布局之autoresizingi
  8. 稳定=死亡!废掉一个人的最好办法,就是让他瞎努力......
  9. Lingo软件使用教程
  10. 如何生成一个QRCode(二维码)
  11. C#网络编程技术教程pdf 文档分享
  12. DateFormat的使用
  13. 3DGIS城市规划信息管理系统
  14. win系统分区表丢失后如何恢复
  15. 4g内存php一般开多少个进程,Linux_4G内存服务器epoll并发量最大能达到多少?,按照题主的意思 是根据内存去 - phpStudy...
  16. CAD在画线的过程中显示长度和角度
  17. jetty9 Form too large 异常解决方案
  18. GPA计算器beta1
  19. avcodec_receive_frame
  20. 希尔顿荣誉客会与FLYERT飞客宣布建立合作伙伴关系,为忠诚会员提供超值奖励...

热门文章

  1. onvif工具使用简介
  2. 音视频流程 - 语音/短视频 :录制(编码)和播放(解码)
  3. 安卓WebView在线预览office文档功能实现
  4. Python——蓝桥杯
  5. PAT出现段错误怎么办
  6. 175.纯 CSS 实现视频转场特效
  7. 神经网络训练解决loss、validation loss(损失函数)波动或不收敛问题
  8. kafka | 消费者组到底是什么?
  9. 绩效管理不可缺失的一环 —— 绩效面谈
  10. 网站标志设计的操作步骤