开源RTP源代码.docx

上传人:b****8 文档编号:9138826 上传时间:2023-02-03 格式:DOCX 页数:27 大小:100.25KB
下载 相关 举报
开源RTP源代码.docx_第1页
第1页 / 共27页
开源RTP源代码.docx_第2页
第2页 / 共27页
开源RTP源代码.docx_第3页
第3页 / 共27页
开源RTP源代码.docx_第4页
第4页 / 共27页
开源RTP源代码.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

开源RTP源代码.docx

《开源RTP源代码.docx》由会员分享,可在线阅读,更多相关《开源RTP源代码.docx(27页珍藏版)》请在冰豆网上搜索。

开源RTP源代码.docx

开源RTP源代码

开源RTP库JRTPLIB 初学 [转]

 (2008-12-1018:

58:

00)

转载

标签:

 

it

分类:

 技术无限

    RTP是一个实时通讯网络协议,网络上的音视频传输可以用它来做,像QQ的语音聊天等都是使用这个。

real开发的在线rm文件播放协议rstp也是基于RTP协议,可以自己搜索一下,在网上可找到“RTP实时网络协议rfc3550.pdf”文档,有详细介绍。

JRTPLIB是一个开源的RTP协议实现库,支持Windows和unix平台,应该也很多人用了,封装的类方式很不错。

他的主页是 http:

//research.edm.uhasselt.be/~jori/page/index.php?

n=CS.Jrtplib ,

帮助文档:

http:

//research.edm.uhasselt.be/jori/jrtplib/documentation/index.html

RTPSessionClassReferencehttp:

//research.edm.uhasselt.be/jori/jrtplib/documentation/classRTPSession.html

从他主页上下载完整的JRTPLIB   源码包下来解压就行了,不过JRTPLIB用到了他的JThread库,在主页上可以找到,也把JThread库下载下来就行了。

解压之后再examples目录下有几个例子,我试了一下,example2.cpp和example4.cpp两个,刚好一个可以作为客户端,一个作为服务器端,在vc2003中测试了一下。

首先建一个win32console项目,把把JRTPLIBexample2.cpp    和example4.cpp加进了,再把JRTPLIB   和 JThread添加到工程中来。

在include目下中指定JRTPLIB    和 JThread的src源码目录。

下一步把工程属性中把“RuntimeLibrary”改成“Multi-threadedDebugDLL(/MDd)”,需要改成这个JThread才能编译通过。

最后包含一个Ws2_32.lib这个lib库,我是直接在example2.cpp和example4.cpp前面添加#pragmacomment(lib,"Ws2_32.lib")这一句了,在工程属性修改应该一样的。

 

两个例子的代码如下也贴一下吧:

 

#pragmacomment(lib,"Ws2_32.lib")

#include"rtpsession.h"

#include"rtppacket.h"

#include"rtpudpv4transmitter.h"

#include"rtpipv4address.h"

#include"rtpsessionparams.h"

#include"rtperrors.h"

#ifndefWIN32

#include

#include

#else

#include

#endif//WIN32

#include"rtpsourcedata.h"

#include

#include

#include

#include

#ifdefRTP_SUPPORT_THREAD

ThisfunctionchecksiftherewasaRTPerror.Ifso,itdisplaysanerror

messageandexists.

voidcheckerror(intrtperr)

{

if(rtperr<0)

{

   std:

:

cout<<"ERROR:

"<

:

endl;

   exit(-1);

}

}

Thenewclassroutine

classMyRTPSession:

publicRTPSession

{

protected:

voidOnPollThreadStep();

voidProcessRTPPacket(constRTPSourceData&srcdat,constRTPPacket&rtppack);

};

voidMyRTPSession:

:

OnPollThreadStep()

{

BeginDataAccess();

  

checkincomingpackets

if(GotoFirstSourceWithData())

{

   do

   {

    RTPPacket*pack;

    RTPSourceData*srcdat;

   

    srcdat=GetCurrentSourceInfo();

   

    while((pack=GetNextPacket())!

=NULL)

    {

     ProcessRTPPacket(*srcdat,*pack);

     DeletePacket(pack);

    }

   }while(GotoNextSourceWithData());

}

  

EndDataAccess();

}

voidMyRTPSession:

:

ProcessRTPPacket(constRTPSourceData&srcdat,constRTPPacket&rtppack)

{

Youcaninspectthepacketandthesource'sinfohere

std:

:

cout<<"Gotpacket"<

:

endl;

}

Themainroutine

intmain(void)

{

#ifdefWIN32

WSADATAdat;

WSAStartup(MAKEWORD(2,2),&dat);

#endif//WIN32

MyRTPSessionsess;

uint16_tportbase;

std:

:

stringipstr;

intstatus,num;

         First,we'llaskforthenecessaryinformation

  

std:

:

cout<<"Enterlocalportbase:

"<

:

endl;

std:

:

cin>>portbase;

std:

:

cout<

:

endl;

std:

:

cout<

:

endl;

std:

:

cout<<"Numberofsecondsyouwishtowait:

"<

:

endl;

std:

:

cin>>num;

Now,we'llcreateaRTPsession,setthedestination

andpollforincomingdata.

RTPUDPv4TransmissionParamstransparams;

RTPSessionParamssessparams;

IMPORTANT:

ThelocaltimestampunitMUSTbeset,otherwise

             RTCPSenderReportinfowillbecalculatedwrong

Inthiscase,we'llbejustuse8000samplespersecond.

sessparams.SetOwnTimestampUnit(1.0/8000.0);  

transparams.SetPortbase(portbase);

status=sess.Create(sessparams,&transparams);

checkerror(status);

Waitanumberofseconds

RTPTime:

:

Wait(RTPTime(num,0));

sess.BYEDestroy(RTPTime(10,0),0,0);

#ifdefWIN32

WSACleanup();

#endif//WIN32

return0;

}

#else

intmain(void)

{

std:

:

cerr<<"Threadsupportisrequiredforthisexample"<

:

endl;

return0;

}

#endif//RTP_SUPPORT_THREAD

 

 

=============================================================================

#pragmacomment(lib,"Ws2_32.lib")

#include"rtpsession.h"

#include"rtpsessionparams.h"

#include"rtpudpv4transmitter.h"

#include"rtpipv4address.h"

#include"rtptimeutilities.h"

#include"rtppacket.h"

#include

#include

intmain(void)

{

#ifdefWIN32

WSADATAdat;

WSAStartup(MAKEWORD(2,2),&dat);

#endif//WIN32

  

RTPSessionsession;

RTPSessionParamssessionparams;

sessionparams.SetOwnTimestampUnit(1.0/8000.0);

   

RTPUDPv4TransmissionParamstransparams;

transparams.SetPortbase(8000);

   

intstatus=session.Create(sessionparams,&transparams);

if(status<0)

{

   std:

:

cerr<

:

endl;

   exit(-1);

}

uint8_tlocalip[]={127,0,0,1};

RTPIPv4Addressaddr(localip,9000);

status=session.AddDestination(addr);

if(status<0)

{

   std:

:

cerr<

:

endl;

   exit(-1);

}

session.SetDefaultPayloadType(96);

session.SetDefaultMark(false);

session.SetDefaultTimestampIncrement(160);

uint8_tsilencebuffer[160];

for(inti=0;i<160;i++)

   silencebuffer[i]=128;

//RTPTimedelay(0.020);

   RTPTimedelay(3.000);

RTPTimestarttime=RTPTime:

:

CurrentTime();

booldone=false;

while(!

done)

{

   status=session.SendPacket(silencebuffer,160);

   if(status<0)

   {

    std:

:

cerr<

:

endl;

    exit(-1);

   }

  

   session.BeginDataAccess();

   if(session.GotoFirstSource())

   {

    do

    {

     RTPPacket*packet;

     while((packet=session.GetNextPacket())!

=0)

     {

      std:

:

cout<<"Gotpacketwith"

               <<"extendedsequencenumber"

               <GetExtendedSequenceNumber()

               <<"fromSSRC"<GetSSRC()

               <

:

endl;

      session.DeletePacket(packet);

     }

    }while(session.GotoNextSource());

   }

   session.EndDataAccess();

   

   RTPTime:

:

Wait(delay);

  

   RTPTimet=RTPTime:

:

CurrentTime();

   t-=starttime;

   if(t>RTPTime(60.0))

    done=true;

}

delay=RTPTime(10.0);

session.BYEDestroy(delay,"Time'sup",9);

#ifdefWIN32

WSACleanup();

#endif//WIN32

return0;

}

使用RTP发送h.264的例子代码分析  

2011-08-1111:

50:

10|  分类:

网络+协议|  标签:

|字号大中小 订阅

参考:

首先声明,以下代码为帖子中ttxk的,注释是我加的,对ttxk和jessiepan表示感谢,jessiepan的钻研精神很不错,很负责任的楼主。

他遇到的问题估计我也会遇到。

以下是根据rfc3894阅读ttxk的代码的笔记。

下一阶段可能是用一个rtp库将rtp传输部分和对应的接受处理部分完成。

 

UINTMediaStreamH264:

:

TransportData(PBYTEpData,UINTdataSize,intpts)

{

//当前缓存头

PBYTEp_buffer=pData;

//当前缓存大小

inti_buffer=dataSize;

//已经发送大小

UINTwriteSize=0;

//寻找第一个头[3BYTE,0x00,0x00,0x01]

while(i_buffer>4&&(p_buffer[0]!

=0||p_buffer[1]!

=0||p_buffer[2]!

=1))

{

i_buffer--;

p_buffer++;

}

/*Splitnalunits*/

while(i_buffer>4)

{

inti_offset;

inti_size=i_buffer;

inti_skip=i_buffer;

/*searchnalend*/

for(i_offset=4;i_offset+2

{

//寻找下一个头来找到当前帧结束位置

if(p_buffer[i_offset]==0&&p_buffer[i_offset+1]==0&&p_buffer[i_offset+2]==1)

{

/*wefoundanotherstartcode*/

//判断下一个头是两个还是三个0x00,如果p_buffer[i_offset-1]表明下一个头是三个0x00+0x01,i_size要多减一

i_size=i_offset-(p_buffer[i_offset-1]==0?

1:

0);

i_skip=i_offset;

break;

}

/*TODOaddSTAP-Atoremovealotofoverheadwithsmallslice/sei/...*/

//发送当前找到的一帧

UINTiWrite=TransportH264Nal(p_buffer,i_size,pts,(i_size>=i_buffer));

if(iWrite>0)

writeSize+=iWrite;

i_buffer-=i_skip;

p_buffer+=i_skip;

}

returnwriteSize;

}

//发送一帧264数据,一般一帧以一个RTP包发送,过长帧分为多个RTP包传送。

UINTMediaStreamH264:

:

TransportH264Nal(constPBYTEpNal,UINTnalSize,INT32pts,BOOLisLast)

{

//应该是对进程加锁

ATLockatlock(&m_tlockRun);

if(m_bRun==FALSE)

return0;

//每帧最小长度至少为5

if(nalSize<5)

return0;

/*mtu是MTU,应是个全局变量,如下介绍,在IP网估计可设为1500左右的一个值

聚合包是本荷载规范的NAL单元聚合安排。

本计划的引入是反映两个主要目标网络差异巨大的MTU:

有线IP网络(MTU通常被以太网的MTU限制;大约1500字节),基于无线通信系统的IP或非IP(ITU-TH.324/M)网络,它的优先传输最大单元是254或更少。

为了阻止连个世界媒体的转换以及避免不必要的打包负担,引入聚合单元安排。

*/

UINTmtu=m_nMTU;

//按照opal的经验可以将i_max设为1400

constinti_max=mtu-RTP_HEADER_SIZE;/*payloadmaxinonepacket*/

inti_nal_hdr;//NAL的头

inti_nal_type;

i_nal_hdr=pNal[3];

i_nal_type=i_nal_hdr&0x1f;//前两个BYTE中第一个BYTE的最后一个bit和第二个BYTE是type

stringsps;

stringpps;

//对于nal_unit_type等于7,8(指示顺序参数集或图像参数集)的NAL单元,H.264编码器应该设置NRI为11(二进制格式)

if(i_nal_type==7||i_nal_type==8)

{

/*XXXWhydoyouwanttoremovethem?

Itwillbreakstreamingwith 

*SPS/PPSchange(broadcast)?

*/

return0;

}

/*Skipstartcode*/

PBYTEp_data=pNal;

inti_data=nalSize;

//跳过头部的3个BYTE的h264帧头(0x000x000x01)

p_data+=3;

i_data-=3;//NAL+NALU的长度

intwriteSize=0;

//如果此帧数据长度小于一个udp包内容的最大长度直接发送,负责按照FU格式发送一帧发送多个包

if(i_data<=i_max)

//单个NAL单元的传输顺序必须和NAL解码顺序一致。

{

/*SingleNALunitpacket*/

//writeSize=m_pRtpTransport->SetRtpData(p_data,i_data,pts,isLast);

//发送数据

writeSize=m_pRtpTransport->Write(p_data,i_data,m_nRtpPayloadType,pts,0,isLast);

if(writeSize<=0)

return0;

returnwriteSize;

}

else

//STAP类型的包,是STAP-A的方式,由后面的28决定

{

/*FU-AFragmentationUnitwithoutinterleaving*/

constinti_count=(i_data-1+i_max-2-1)/(i_max-2);//需要分多少个包

inti;

p_data++;

i_data--;

for(i=0;i

{

//计算每个NALUDATA的长度,判断是否是最后一包,不是最后一包时都是i_max-2,最后一包是i_data(也即最后一包实际的长度)

constinti_payload=(i_data<(i_max-2))?

i_data:

(i_max-2);

//计算每个NALU的长度

constintnalSize=2+i_payload;

m_Packet.ExtendBuffer(nalSize);

/*FUindicator*/

/*i_nal_hdr&01100000

  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