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

代码:

/***
***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. 网络相关配置,SSH服务,bash, 元字符
  2. vue实现进度条隐藏_实现带有进度条的Vue延迟加载
  3. 分布式锁在存储系统中的技术实践
  4. [2014.3.23]cse::lab2::partD 简明攻略
  5. websocket传输数据大小限制_WebSocket基础知识笔记
  6. 机器学习实战 k-近邻算法 约会网站
  7. 学习Spring(四) -- Spring的继承与依赖
  8. 小米扫地机器人换了边刷很响_科沃斯除菌地宝N8 PRO VS 小米扫拖一体机,谁更强?...
  9. 贝叶斯回归 matlab,逻辑回归模型的贝叶斯分析
  10. 怎么上传代码到GitHub
  11. Android FileOutputStream FileInputStream 读写问题记录
  12. java文件没有错但是包中错_Eclipse中导入android项目名前有红叉但项目内文件无错误问题解决方法...
  13. 事件绑定,事件类型,事件委托
  14. 浏览器-错误 未能加载 PDF 文档
  15. 网站开发-php开发手机论坛(11)-用户中心
  16. 2020年缴费基数调整
  17. 地址解析(仅供参考与学习)<Java>
  18. java-php-python-ssm蔬菜水果销售系统计算机毕业设计
  19. 打印机无法连接0x000000709
  20. 史上最全的CTF保姆教程 从入门到入狱【带工具】

热门文章

  1. 面试官_vue的这些原理你了解吗_
  2. webservice--CXF发布REST的服务
  3. latex与文章写作心得
  4. rsync远程同步及结合inotify实现实时同步
  5. 公有链、联盟链、私有链及网络配置介绍
  6. veiw pad 7寸 android4.2,优派viewpad7刷机教程以及报价【图解】
  7. 数学之美--分形几何与建筑形式美
  8. tensorflow2中使用ragged.constant()将非矩形列表转为tensor类型
  9. 通信协议标准及其转换芯片(串行接口正在取代并行接口)
  10. 【时间复杂度空间复杂度】