1、开源RTP源代码开源RTP库JRTPLIB初学转(2008-12-10 18:58:00)转载标签:it分类:技术无限RTP是一个实时通讯网络协议,网络上的音视频传输可以用它来做,像QQ的语音聊天等都是使用这个。real 开发 的在线rm文件播放协议 rstp也是基于RTP协议,可以自己搜索一下, 在网上可找到“RTP 实时网络协议rfc3550.pdf” 文档,有详细介绍。JRTPLIB 是一个开源的 RTP协议实现库,支持Windows和unix平台,应该也很多人用了,封装的类方式很不错。他的主页是http:/research.edm.uhasselt.be/jori/page/index
2、.php?n=CS.Jrtplib,帮助文档:http:/research.edm.uhasselt.be/jori/jrtplib/documentation/index.htmlRTPSession Class Referencehttp:/research.edm.uhasselt.be/jori/jrtplib/documentation/classRTPSession.html从他主页上下载完整的 JRTPLIB源码包下来解压就行了,不过JRTPLIB 用到了他的JThread库,在主页上可以找到,也把JThread 库下载下来就行了。解压之后再examples 目录下有几个例子,我
3、试了一下,example2.cpp 和example4.cpp 两个,刚好一个可以作为客户端,一个作为服务器端,在vc2003 中测试了一下。首先建一个win32 console 项目,把 把JRTPLIB example2.cpp和 example4.cpp 加进了,再把JRTPLIB和JThread 添加到工程中来。 在 include 目下中指定JRTPLIB和JThread 的src源码目录。下一步把工程属性中把 “Runtime Library” 改成“Multi-threaded Debug DLL (/MDd)” ,需要改成这个JThread 才能编译通过。最后包含一个 Ws2_
4、32.lib 这个lib库,我是直接在example2.cpp 和example4.cpp 前面添加 #pragma comment (lib, Ws2_32.lib) 这一句了,在工程属性修改应该一样的。两个例子的代码如下也贴一下吧:#pragma comment (lib, Ws2_32.lib)#include rtpsession.h#include rtppacket.h#include rtpudpv4transmitter.h#include rtpipv4address.h#include rtpsessionparams.h#include rtperrors.h#ifnde
5、f WIN32#include #include #else#include #endif / WIN32#include rtpsourcedata.h#include #include #include #include #ifdef RTP_SUPPORT_THREADThis function checks if there was a RTP error. If so, it displays an errormessage and exists.void checkerror(int rtperr)if (rtperr 0)std:cout ERROR: RTPGetErrorSt
6、ring(rtperr) std:endl;exit(-1);The new class routineclass MyRTPSession : public RTPSessionprotected:void OnPollThreadStep();void ProcessRTPPacket(const RTPSourceData &srcdat,const RTPPacket &rtppack);void MyRTPSession:OnPollThreadStep()BeginDataAccess();check incoming packetsif (GotoFirstSourceWithD
7、ata()doRTPPacket *pack;RTPSourceData *srcdat;srcdat = GetCurrentSourceInfo();while (pack = GetNextPacket() != NULL)ProcessRTPPacket(*srcdat,*pack);DeletePacket(pack); while (GotoNextSourceWithData();EndDataAccess();void MyRTPSession:ProcessRTPPacket(const RTPSourceData &srcdat,const RTPPacket &rtppa
8、ck)You can inspect the packet and the sources info herestd:cout Got packet rtppack.GetExtendedSequenceNumber() from SSRC srcdat.GetSSRC() std:endl;The main routineint main(void)#ifdef WIN32WSADATA dat;WSAStartup(MAKEWORD(2,2),&dat);#endif / WIN32MyRTPSession sess;uint16_t portbase;std:string ipstr;i
9、nt status,num;First, well ask for the necessary informationstd:cout Enter local portbase: portbase;std:cout std:endl;std:cout std:endl;std:cout Number of seconds you wish to wait: num;Now, well create a RTP session, set the destinationand poll for incoming data.RTPUDPv4TransmissionParams transparams
10、;RTPSessionParams sessparams;IMPORTANT: The local timestamp unit MUST be set, otherwiseRTCP Sender Report info will be calculated wrongIn this case, well be just use 8000 samples per second.sessparams.SetOwnTimestampUnit(1.0/8000.0);transparams.SetPortbase(portbase);status = sess.Create(sessparams,&
11、transparams);checkerror(status);Wait a number of secondsRTPTime:Wait(RTPTime(num,0);sess.BYEDestroy(RTPTime(10,0),0,0);#ifdef WIN32WSACleanup();#endif / WIN32return 0;#elseint main(void)std:cerr Thread support is required for this example std:endl;return 0;#endif / RTP_SUPPORT_THREAD=#pragma comment
12、 (lib, Ws2_32.lib)#include rtpsession.h#include rtpsessionparams.h#include rtpudpv4transmitter.h#include rtpipv4address.h#include rtptimeutilities.h#include rtppacket.h#include #include int main(void)#ifdef WIN32WSADATA dat;WSAStartup(MAKEWORD(2,2),&dat);#endif / WIN32RTPSession session;RTPSessionPa
13、rams sessionparams;sessionparams.SetOwnTimestampUnit(1.0/8000.0);RTPUDPv4TransmissionParams transparams;transparams.SetPortbase(8000);int status = session.Create(sessionparams,&transparams);if (status 0)std:cerr RTPGetErrorString(status) std:endl;exit(-1);uint8_t localip=127,0,0,1;RTPIPv4Address add
14、r(localip,9000);status = session.AddDestination(addr);if (status 0)std:cerr RTPGetErrorString(status) std:endl;exit(-1);session.SetDefaultPayloadType(96);session.SetDefaultMark(false);session.SetDefaultTimestampIncrement(160);uint8_t silencebuffer160;for (int i = 0 ; i 160 ; i+)silencebufferi = 128;
15、/RTPTime delay(0.020);RTPTime delay(3.000);RTPTime starttime = RTPTime:CurrentTime();bool done = false;while (!done)status = session.SendPacket(silencebuffer,160);if (status 0)std:cerr RTPGetErrorString(status) std:endl;exit(-1);session.BeginDataAccess();if (session.GotoFirstSource()doRTPPacket *pac
16、ket;while (packet = session.GetNextPacket() != 0)std:cout Got packet with extended sequence number GetExtendedSequenceNumber() from SSRC GetSSRC() RTPTime(60.0)done = true;delay = RTPTime(10.0);session.BYEDestroy(delay,Times up,9);#ifdef WIN32WSACleanup();#endif / WIN32return 0;使用RTP发送h.264的例子代码分析20
17、11-08-11 11:50:10|分类: 网络+协议 |标签: |字号大中小订阅 参考:首先声明,以下代码为帖子 中ttxk的,注释是我加的,对ttxk和jessiepan表示感谢,jessiepan的钻研精神很不错,很负责任的楼主。他遇到的问题估计我也会遇到。以下是根据rfc3894阅读ttxk的代码的笔记。下一阶段可能是用一个rtp库将rtp传输部分和对应的接受处理部分完成。UINT MediaStreamH264:TransportData(PBYTE pData, UINT dataSize, int pts) /当前缓存头 PBYTE p_buffer = pData; /当前缓存
18、大小 int i_buffer = dataSize;/已经发送大小 UINT writeSize = 0;/寻找第一个头3 BYTE,0x00,0x00,0x01 while( i_buffer 4 & ( p_buffer0 != 0 | p_buffer1 != 0 | p_buffer2 != 1 ) ) i_buffer-; p_buffer+; /* Split nal units */ while( i_buffer 4 ) int i_offset; int i_size = i_buffer; int i_skip = i_buffer;/* search nal end *
19、/ for( i_offset = 4; i_offset+2 = i_buffer) ); if (iWrite 0 ) writeSize += iWrite;i_buffer -= i_skip; p_buffer += i_skip; return writeSize; /发送一帧264数据,一般一帧以一个RTP包发送,过长帧分为多个RTP包传送。 UINT MediaStreamH264:TransportH264Nal(const PBYTE pNal, UINT nalSize, INT32 pts, BOOL isLast) /应该是对进程加锁 ATLock atlock(&m
20、_tlockRun);if (m_bRun = FALSE) return 0;/每帧最小长度至少为5 if( nalSize 5 ) return 0;/* mtu是MTU,应是个全局变量, 如下介绍,在IP网估计可设为1500左右的一个值 聚 合包是本荷载规范的NAL单元聚合安排。本计划的引入是反映两个主要目标网络差异巨大的MTU:有线IP网络(MTU 通常被以太网的MTU限制; 大约1500 字节), 基于无线通信系统的IP或非IP (ITU-T H.324/M)网络,它的优先传输最大单元是254或更少。为了阻止连个世界媒体的转换以及避免不必要的打包负担,引入聚合单元安排。 */ UIN
21、T mtu = m_nMTU;/按照opal的经验可以将i_max设为1400 const int i_max = mtu - RTP_HEADER_SIZE; /* payload max in one packet */ int i_nal_hdr;/NAL的头 int i_nal_type;i_nal_hdr = pNal3; i_nal_type = i_nal_hdr&0x1f;/前两个BYTE中第一个BYTE的最后一个bit和第二个BYTE是typestring sps; string pps;/对于nal_unit_type等于7,8 (指示顺序参数集或图像参数集)的NAL单元,
22、H.264编码器应该设置NRI为11 (二进制格式) if( i_nal_type = 7 | i_nal_type = 8 ) /* XXX Why do you want to remove them ? It will break streaming with * SPS/PPS change (broadcast) ? */ return 0; /* Skip start code */ PBYTE p_data = pNal; int i_data = nalSize;/跳过头部的3个BYTE的h264帧头(0x00 0x00 0x01) p_data += 3; i_data -=
23、 3;/NAL+NALU的长度int writeSize = 0;/如果此帧数据长度小于一个udp包内容的最大长度直接发送,负责按照FU格式发送一帧发送多个包 if( i_data SetRtpData(p_data, i_data, pts, isLast); /发送数据 writeSize = m_pRtpTransport-Write(p_data, i_data, m_nRtpPayloadType, pts, 0, isLast); if (writeSize = 0) return 0; return writeSize; else /STAP 类型的包,是STAP-A的方式,由后
24、面的28决定 /* FU-A Fragmentation Unit without interleaving */ const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);/需要分多少个包 int i;p_data+; i_data-;for( i = 0; i i_count; i+ ) /计算每个NALU DATA的长度,判断是否是最后一包,不是最后一包时都是i_max-2,最后一包是i_data(也即最后一包实际的长度) const int i_payload = (i_data (i_max-2) ? i_data : (i_max-2); /计算每个NALU的长度 const int nalSize = 2 + i_payload;m_Packet.ExtendBuffer(nalSize);/* FU indicator */ /* i_nal_hdr & 0110 0000 FU指示字节有以下格式: +-+ |0|1|2|3|4|5|6|7| +-+-+-+-+-+-+-+-+ |F|NRI| Type | +-+ FU指示字节的类型域的28,29表示FU-A和FU-B。F的使用在5。3描述。NRI域的值必
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1