【php精品源码栏目提醒】:本文主要为网学会员提供“开源RTP源代码 - 其它资料”,希望对需要开源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.phpnCS.Jrtplib ,帮助文档:http://research.edm.uhasselt.be/jori/jrtplib/documentation/index.htmlRTPSession ClassReferencehttp://research.edm.uhasselt.be/jori/jrtplib/documentation/classRTPSession.html从他主页上下载完整的 JRTPLIB
源码包下来解压就行了,不过 JRTPLIB 用到了他的JThread 库,在主页上可以找到,也把 JThread 库下载下来就行了。
解压之后再 examples 目录下有几个例子,我试了一下,example2.cpp 和 example4.cpp 两个,刚好一个可以作为客户端,一个作为服务器端,在 vc2003 中测试了一下。
首先建一个 win32 console 项目,把 把 JRTPLIB example2.cpp 和 example4.cpp加进了,再把 JRTPLIB 和 JThread 添加到工程中来。
在 include 目下中指定JRTPLIB 和 JThread 的 src
源码目录。
下一步把工程属性中把 “RuntimeLibrary” 改成“Multi-threaded Debug DLL /MDd” ,需要改成这个 JThread 才能编 最后包含一个 Ws2_32.lib 这个 lib 库,译通过。
我是直接在 example2.cpp 和 example4.cpp前面添加 pragma comment lib quotWs2_32.libquot 这一句了,在工程属性修改应该一样的。
两个例子的代码如下也贴一下吧:pragma comment lib quotWs2_32.libquotinclude quotrtpsession.hquotinclude quotrtppacket.hquotinclude quotrtpudpv4transmitter.hquotinclude quotrtpipv4address.hquotinclude quotrtpsessionparams.hquotinclude quotrtperrors.hquotifndef WIN32include ltnetinet/in.hgtinclude ltarpa/inet.hgtelseinclude ltwinsock2.hgtendif // WIN32include quotrtpsourcedata.hquotinclude ltstdlib.hgtinclude ltstdio.hgtinclude ltiostreamgtinclude ltstringgtifdef RTP_SUPPORT_THREADThis function checks if there was a RTP error. If so it displays an errormessage and exists.void checkerrorint rtperrif rtperr lt 0 std::cout ltlt quotERROR: quot ltlt RTPGetErrorStringrtperr ltlt std::endl exit-1The new class routineclass MyRTPSession : public RTPSessionprotected:void OnPollThreadStepvoid ProcessRTPPacketconst RTPSourceData ampsrcdatconst RTPPacket amprtppackvoid MyRTPSession::OnPollThreadStepBeginDataAccesscheck incoming packetsif GotoFirstSourceWithData do RTPPacket pack RTPSourceData srcdat srcdat GetCurrentSourceInfo while pack GetNextPacket NULL ProcessRTPPacketsrcdatpack DeletePacketpack while GotoNextSourceWithDataEndDataAccessvoid MyRTPSession::ProcessRTPPacketconst RTPSourceData ampsrcdatconst RTPPacketamprtppackYou can inspect the packet and the sources info herestd::cout ltlt quotGot packet quot ltlt rtppack.GetExtendedSequenceNumber ltlt quot from SSRCquot ltlt srcdat.GetSSRC ltlt std::endlThe main routineint mainvoidifdef WIN32WSADATA datWSAStartupMAKEWORD22ampdatendif // WIN32MyRTPSession sessuint16_t portbasestd::string ipstrint statusnum First well ask for the necessary informationstd::cout ltlt quotEnter local portbase:quot ltlt std::endlstd::cin gtgt portbasestd::cout ltlt std::endlstd::cout ltlt std::endlstd::cout ltlt quotNumber of seconds you wish to wait:quot ltlt std::endlstd::cin gtgt numNow well create a RTP session set the destinationand poll for incoming data.RTPUDPv4TransmissionParams transparamsRTPSessionParams sessparamsIMPORTANT: The local timestamp unit MUST be set otherwise RTCP Sender Report info will be calculated wrongIn this case well be just use 8000 samples per second.sessparams.SetOwnTimestampUnit1.0/8000.0transparams.SetPortbaseportbasestatus sess.CreatesessparamsamptransparamscheckerrorstatusWait a number of secondsRTPTime::WaitRTPTimenum0sess.BYEDestroyRTPTime10000ifdef WIN32WSACleanupendif // WIN32return 0elseint mainvoidstd::cerr ltlt quotThread support is required for this examplequot ltlt std::endlreturn 0endif // RTP_SUPPORT_THREADpragma comment lib quotWs2_32.libquotinclude quotrtpsession.hquotinclude quotrtpsessionparams.hquotinclude quotrtpudpv4transmitter.hquotinclude quotrtpipv4address.hquotinclude quotrtptimeutilities.hquotinclude quotrtppacket.hquotinclude ltstdlib.hgtinclude ltiostreamgtint mainvoidifdef WIN32WSADATA datWSAStartupMAKEWORD22ampdatendif // WIN32RTPSession sessionRTPSessionParams sessionparamssessionparams.SetOwnTimestampUnit1.0/8000.0RTPUDPv4TransmissionParams transparamstransparams.SetPortbase8000int status session.Createsessionparamsamptransparamsif status lt 0 std::cerr ltlt RTPGetErrorStringstatus ltlt std::endl exit-1uint8_t localip127001RTPIPv4Address addrlocalip9000status session.AddDestinationaddrif status lt 0 std::cerr ltlt RTPGetErrorStringstatus ltlt std::endl exit-1session.SetDefaultPayloadType96session.SetDefaultMarkfalsesession.SetDefaultTimestampIncrement160uint8_t silencebuffer160for int i 0 i lt 160 i silencebufferi 128//RTPTime delay0.020 RTPTime delay3.000RTPTime starttime RTPTime::CurrentTimebool done falsewhile done status session.SendPacketsilencebuffer160 if status lt 0 std::cerr ltlt RTPGetErrorStringstatus ltlt std::endl exit-1 session.BeginDataAccess if session.GotoFirstSource do RTPPacket packet while packet session.GetNextPacket 0 std::cout ltlt quotGot packet with quot ltlt quotextended sequence number quot ltlt packet-gtGetExtendedSequenceNumber ltlt quot from SSRC quot ltlt packet-gtGetSSRC ltlt std::endl session.DeletePacketpacket while session.GotoNextSource session.EndDataAccess RTPTime::Waitdelay RTPTime t RTPTime::CurrentTime t - starttime if t gt RTPTime60.0 done truedelay RTPTime10.0session.BYEDestroydelayquotTimes upquot9ifdef WIN32WSACleanupendif // WIN32return 0 使用 RTP 发送 h.264 的例子代码分析 2011-08-11 11:50:10 分类: 网络协议 标签: 字号大中小 订阅 参考:http://blog.csdn.net/ren911/article/details/5714901 首先声明,以下代码为帖子http://topic.csdn.net/u/20090725/11/5FBC75B0-1091-4DD4-9154-3E3D59F9B6D1.html 中 ttxk 的,注释是我加的,对 ttxk 和 jessiepan 表示感谢,jessiepan 的钻研精神很不错,很负责任的楼主。
他遇到的问题 估计我也会遇到。
以下是根据 rfc3894 阅读 ttxk 的代码的笔记。
下一阶段可能是用一个 rtp 库将 rtp 传输部分和对应的接受处 理部分完成。
UINT MediaStreamH264::TransportDataPBYTE pData UINT dataSize int pts //当前缓存头 PBYTE p_buffer pData //当前缓存大小 int i_buffer dataSize //已经发送大小 UINT writeSize 0 //寻找第一个头3 BYTE0x000x000x01 while i_buffer gt 4 ampamp p_buffer0 0 p_buffer1 0 p_buffer2 1 i_buffer-- p_buffer / Split nal units / while i_buffer gt 4 int i_offset int i_size i_buffer int i_skip i_buffer / search nal end / for i_offset 4 i_offset2 lt i_buffer i_offset //寻找下一个头来找到当前帧结束位置 if p_bufferi_offset 0 ampamp p_bufferi_offset1 0 ampamp p_bufferi_offset2 1 / we found another startcode /// 判断下一个头是两个还是三个 0x00如果 p_bufferi_offset-1表明下一个头是三个 0x000x01i_size 要多 减一 i_size i_offset - p_bufferi_offset-1 0 1 : 0 i_skip i_offset break / TODO add STAP-A to remove a lot of overhead with small slice/sei/... / //发送当前找到的一帧 UINT iWrite TransportH264Nalp_buffer i_size pts i_size gt i_buffer if iWrite gt 0 writeSize iWrite i_buffer - i_skip p_buffer i_skip return writeSize //发送一帧 264 数据,一般一帧以一个 RTP 包发送,过长帧分为多个 RTP 包传送。
UINT MediaStreamH264::TransportH264Nalconst PBYTE pNal UINT nalSize INT32 pts BOOL isLast //应该是对进程加锁 ATLock atlockampm_tlockRun if m_bRun FALSE return 0 //每帧最小长度至少为 5 if nalSize lt 5 return 0 / mtu 是 MTU,应是个全局变量, 如下介绍,在 IP 网估计可设为 1500 左右的一个值 。
聚 合包是本荷载规范的 NAL 单元聚合安排 本计划的引入是反映两个主要目标网络差异巨大的 MTU:有线 IP 网络MTU 通常被以太网的 MTU 限制 大约 1500 字节 基于无线通信系统的 IP 或非 IP ITU-TH.324/M网络,它的优先传输最大单元是 254 或更少。
为了阻止连个世界媒体的转换以及避免不必要的打 包负担,引入聚合单元安排。
/ UINT 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_hdramp0x1f//前两个 BYTE 中第一个 BYTE 的最后一个 bit 和第二个 BYTE 是 type string sps string pps//对于 nal_unit_type 等于 7,8 指示顺序参数集或图像参数集的 NAL 单元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 - 3//NALNALU 的长度 int writeSize 0 //如果此帧数据长度小于一个 udp 包内容的最大长度直接发送,负责按照 FU 格式发送一帧发送多个包 if i_data lt i_max //单个 NAL 单元的传输顺序必须和 NAL 解码顺序一致。
/ Single NAL unit packet / //writeSize m_pRtpTransport-gtSetRtpDatap_data i_data pts isLast //发送数据 writeSize m_pRtpTransport-gtWritep_data i_data m_nRtpPayloadType pts 0 isLast if writeSize lt 0 return 0 return writeSize else //STAP 类型的包,是 STAP-A 的方式,由后面的 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 lt i_count i , ,//计算每个 NALU DATA 的长度 判断是否是最后一包 不是最后一包时都是 i_max-2最后一包是 i_data也 即最后一包实际的长度 const int i_payload i_data lt i_max-2 i_data : i_max-2 //计算每个 NALU 的长度 const int nalSize 2 i_payload m_Packet.ExtendBuffernalSize / FU indicator / / i_nal_hdr amp 0110 0000 FU 指示字节有以下格式: --------------- 01234567 -------- FNRI Type --------------- FU 指示字节的类型域的 28,29 表示 FU-A 和 FU-B。
F 的使用在 5。
3 描述。
NRI 域的值必须根据分片 NAL 单元的 NRI 域的值设置。
, , ,28 表示是 FU-A 见 rfc3984 5.8即在此对分片单元的处理方式是 FU-A 没有使用交错模式 没有使用 DON / m_Packet.m_pData0 0x00 i_nal_hdr amp 0x60 28 / FU header / / FU 头的格式如下: --------------- 01234567 .
上一篇:
仿亚马逊源码
下一篇:
老弱者应该怎样安度盛夏?