一种RTP接收和解包的程序
jrtplib
除了自己写udp 接收程序,我们也可以使用jrtplib 的方式去接收数据包,比较简单,jrtplib可以解rtp 的头部,但不适宜解包,一般来说,解包都是要自己解的,我们使用jrtplib来收包,同时自己写解包代码,除此之外,rtf3984是H.264的baseline码流在RTP方式下传输的规范,我们传输实时码流,一般使用baseline。
jrtplib class
jrtplib可以在编译的时候使用thread,也就是编译出thread库,让其启动的时候启动多个线程。
class Service_RTP:public RTPSession
{int status;RTPUDPv4TransmissionParams m_transparams;RTPSessionParams m_sessparams;Service_RTP_Analyse m_rab;
protected:void OnPollThreadStep(){BeginDataAccess();if (GotoFirstSourceWithData()){do{RTPPacket *pack;RTPSourceData * srcdat = GetCurrentSourceInfo();const RTPIPv4Address *addr = (const RTPIPv4Address *)(srcdat->GetRTPDataAddress());if (srcdat->RR_HasInfo()) //如果有收到rr包{std::cout << srcdat->RR_GetPacketsLost() << ":lost" << std::endl;//得到最近会话丢失的包数}while ((pack = GetNextPacket()) != NULL){//这里要分发到不同的线程里面m_rab.insert(addr->GetIP(), addr->GetPort(), pack);//ProcessRTPPacket(addr->GetIP(), addr->GetPort(), *srcdat, pack);DeletePacket(pack);}} while (GotoNextSourceWithData());}EndDataAccess();}
主函数启动RTP接收
int main()
{#ifdef _WIN32WSADATA dat;WSAStartup(MAKEWORD(2, 2), &dat);
#endifMyRTPSession sess;std::string ipstr;int status;RTPUDPv4TransmissionParams transparams;RTPSessionParams sessparams;//6000 端口在InitContext里面配置transparams.SetPortbase(PORT);//设定RTP包的接收缓存transparams.SetRTPReceiveBuffer(2 * 1024 * 1024);sessparams.SetOwnTimestampUnit(1.0 / 90000.0);sessparams.SetAcceptOwnPackets(true);sessparams.SetUsePollThread(true);//sess.SetCallBack(callback_1);status = sess.Create(sessparams, &transparams);// &transparams);checkerror(status);//启动检查程序for(;;){//........//Sleep(INFINITE);}return 0;
}
从jrtplib里面获取payload和长度都是有函数的。下面再说明一下常规解h264和AAC的程序片段:
h264 解包
#define H264 96
#define G711 8
#define AAC 97
#define RTP_HEADLEN 12
// 功能:解码RTP H.264视频
// 参数:1.RTP包缓冲地址 2.RTP包数据大小 3.H264输出地址 4.输出数据大小
// 返回:true:表示一帧结束 false:FU-A分片未结束或帧未结束
bool AnalyseRTPH264(void * bufIn, int len, void ** pBufOut, int * pOutLen)
{*pOutLen = 0;if (len < RTP_HEADLEN){return false;}unsigned char * src = (unsigned char*)bufIn + RTP_HEADLEN;unsigned char head1 = *src; // 获取第一个字节unsigned char head2 = *(src + 1); // 获取第二个字节unsigned char nal = head1 & 0x1f; // 获取FU indicator的类型域,unsigned char flag = head2 & 0xe0; // 获取FU header的前三位,判断当前是分包的开始、中间或结束unsigned char nal_fua = (head1 & 0xe0) | (head2 & 0x1f); // FU_A nalbool bFinishFrame = false;if (nal == 0x1c) // 判断NAL的类型为0x1c=28,说明是FU-A分片{ // fu-aif (flag == 0x80) // 开始{*pBufOut = src - 3;*((int *)(*pBufOut)) = 0x01000000; // zyf:大模式会有问题*((char *)(*pBufOut) + 4) = nal_fua;*pOutLen = len - RTP_HEADLEN + 3;}else if (flag == 0x40) // 结束{*pBufOut = src + 2;*pOutLen = len - RTP_HEADLEN - 2;}else // 中间{*pBufOut = src + 2;*pOutLen = len - RTP_HEADLEN - 2;}}else // 单包数据{*pBufOut = src - 4;*((int *)(*pBufOut)) = 0x01000000; // 大模式会有问题*pOutLen = len - RTP_HEADLEN + 4;}unsigned char * bufTmp = (unsigned char*)bufIn;if (bufTmp[1] & 0x80){bFinishFrame = true; // rtp mark}else{bFinishFrame = false;}return bFinishFrame;
}
AAC解包
AAC是高级音频编码,解RTP AAC音频包,声道和采样频率可以事先知道,否则就要多传输字节。
//参数:1.RTP包缓冲地址 2.RTP包数据大小 3.H264输出地址 4.输出数据大小
//返回:true:表示一帧结束 false:帧未结束 一般AAC音频包比较小,没有分片。
bool AnalyseRTPAAC(void * bufIn, int recvLen, void** pBufOut, int* pOutLen)
{unsigned char* bufRecv = (unsigned char*)bufIn;unsigned char ADTS[] = { 0xFF, 0xF1, 0x00, 0x00, 0x00, 0x00, 0xFC };int audioSamprate = 44100;//音频采样率int audioChannel = 2; //音频声道2,我们在采集端都重采样为双声道int audioBit = 16; //16位 固定switch (audioSamprate){case 16000:ADTS[2] = 0x60;break;case 32000:ADTS[2] = 0x54;break;case 44100:ADTS[2] = 0x50;break;case 48000:ADTS[2] = 0x4C;break;case 96000:ADTS[2] = 0x40;break;default:break;}ADTS[3] = (audioChannel == 2) ? 0x80 : 0x40;int len = recvLen - 16 + 7;len <<= 5;//8bit * 2 - 11 = 5(headerSize 11bit)len |= 0x1F;//5 bit 1 ADTS[4] = len >> 8;ADTS[5] = len & 0xFF;*pBufOut = (char*)bufIn + 16 - 7;memcpy(*pBufOut, ADTS, sizeof(ADTS));*pOutLen = recvLen - 16 + 7;unsigned char* bufTmp = (unsigned char*)bufIn;bool bFinishFrame = false;if (bufTmp[1] & 0x80){//DebugTrace::D("Marker");bFinishFrame = true;}else{bFinishFrame = false;}return true;
}#endif
一种RTP接收和解包的程序相关推荐
- RTP之H264封包和解包
RTP之H264封包和解包 目录 H264打包RTP的方法 打包方式之Single NAL Unit 打包方式之FU-A FU indication FU header 1. H264打包RTP的方法 ...
- rtp h264打包和解包
1.学习思路 在了解rtp对h264数据的打包之前,需要对rtp.h264的一些基本概念有一个初步的了解,然后再使用rtp对h264的打包解包做解析 2.rtp认知 实时传送协议(Real-time ...
- 简单自定义协议的封包和解包
简单自定义协议的封包和解包 一.通信协议 1 百度百科的解释 2 过于简单的通信协议引发的问题 3 通信协议常见内容 1.帧头 2.设备地址/类型 3.命令/指令 4.命令类型/功能码 5.数据长度 ...
- TCP利用封包和解包解决“粘包”问题
本文参考自徐晓鑫<后台开发>,给出一个可实际应用的demo,该demo核心在于封包和解包的思想,以及自定义发送.接收数据. 一.TCP粘包现象 what? TCP是个"流&quo ...
- Linux下几种RTP协议实现的比较和JRTPLIB编程讲解
流媒体指的是在网络中使用流技术传输的连续时基媒体,其特点是在播放前不需要下载整个文件,而是采用边下载边播放的方式,它是视频会议. IP电话等应用场合的技术基础.RTP是进行实时流媒体传输的标准协议和关 ...
- TCP/IP 网络数据封包和解包
这是一个网上的代码:下面列出资料并简略分析代码: TCP/IP 网络数据封包和解包 . TCP/IP 网络数据以流的方式传输,数据流是由包组成,如何判定接收方收到的包是否是一个完整的包就要在发送 ...
- linux收发包内核进程名称,Linux内核IP Queue机制的分析(一)——用户态接收数据包...
序 笔者将会通过包括本文在内的三篇文章,对IP Queue机制从用户态的应用到内核态的模块程序设计进行分析.三篇文章的题目分别是: Linux内核IP Queue机制的分析(一)--用户态接收数据包 ...
- 在Ubuntu 14.04 64位上使用libpcap进行抓包和解包
为了开发需要,我决定使用最新libpcap源码包安装.在Unix环境下安装libpcap库,需要 c编译器,flex,bison等,安装Ubuntu系统时,没有这些包.安装flex需要m4编译环境,否 ...
- Python赋值、打包和解包,90%人不清楚的知识点!
人生苦短,快学Python! 关于赋值.打包和解包这 3个概念,我觉得有必要做一个分享,因为很多朋友确实不清楚. 如果有这样一个元组t: >> t = ('foo', 'bar', ' ...
最新文章
- 单链表建立(头插法,头插法,用数组),求长,插入,删除,输出,释放(递归释放和循环释放),归并(递增和递减)
- 欧拉工程第57题:Square root convergents
- DataFountain训练赛 | 用户逾期行为预测
- C++primer第十章 泛型算法 10.3 定制操作
- 食物链(信息学奥赛一本通-T1390)
- 【案例实战】餐饮企业分店财务数据分析系统解决方案:业务需求
- c语言printf源码浮点数,printf以%d输出浮点数
- hive与mysql对比之max、group by、日志分析
- mac关闭虚拟内存_为什么不应该关闭Mac上的虚拟内存
- Manjaro 配置指南
- 石家庄康业软件科技有限公司
- 云服务器测速脚本_Superspeed.sh:包含很多个测速节点的 VPS 一键测速脚本
- wap精武堂源码php_Showgirl武装秀【精武堂】大奖等你拿
- 用户使用手册与测试报告
- 设备设施管理内容有哪些?
- RocketDock的Mac主题
- 洛谷 P2534 [AHOI2012]铁盘整理
- 利用micro:bit开发板工具写一个小游戏
- CAN设计与应用指南
- AxMath使用教程+常用符号与公式(持续更新中)
热门文章
- Power BI 报表服务器企业一站式全链路解决方案
- python count函数用法 comm_Python学习第六天课后练习案例 (主要针对的内容是python函数的定义和使用)...
- 半夜“逃离上海”?阿里副总裁贾扬清回应:正常差旅回去看病 请不要误解
- 消息称阿里腾讯考虑互相开放生态系统 淘宝能用微信支付了?
- 华为张熙伟:鲲鹏计算产业已汇聚30万开发者
- 花2.9元买一包头绳,收到一张3元好评返现卡,我凌乱了……
- 上海消保委评饿了么“多等5分钟”功能:逻辑上有问题
- 腾讯Q2财报看点:游戏营收同比止跌 B端业务成第二大营收来源
- 小鹏吃相难看,消费者难做“鹏”友
- B站COO李旎:超2000万人在B站看纪录片