关于开源的RTP——jrtplib的使用

session.BeginDataAccess();
if (session.GotoFirstSource()){
do{
RTPPacket *packet;
while ((packet = session.GetNextPacket()) != 0){
cout << "Got packet with extended sequence number "
<< packet->GetExtendedSequenceNumber()
<< " from SSRC " << packet->GetSSRC() <<endl;
session.DeletePacket(packet);
}
} while (session.GotoNextSource());
}
session.EndDataAccess();

关于jrtplib环境的建立,能够见我曾经写的总结,如今我主要来谈谈jrtplib3.71下的几个example的学习。 一、sample是一个简单的IPv4的列子,它实现了RTP在本机上的数据的传输。 1、初始化。我们知道RTP是一般是使用UDP协议来实现数据的传输,在windows环境下,当然要用到我们熟悉的套接字的使用,所以我们先要进行初始化,载入套接字库。

函数RTPGetErrorString(…)依据出错返回的一个负数来推断,利用jrtplib採用的统一出错机制返回的是一个C++中标准的字符串std::string,表示出错的信息,比喻我们指定的Portbase不是一个偶数。(为什么,以下要讲)
2、关于RTPSession对象设置
   因为要使用套接字,故我们在使用之前一定要为我们的监听socket指定一个监听端口,也就是这里的portbase的值。我们能够通过调用RTPSession的第二个參数RTPUDPv4TransmissionParams的成员函数来设定,
   transparams.SetPortbase(portbase);
 
   还有就是我们要通过RTPSession的第一个參数来设定以下一些值:
  
sessparams.SetOwnTimestampUnit(1.0/10.0);
//注意这个值我们一定要设置,The local timestamp unit MUST be set, otherwise
//RTCP Sender Report info will be calculated wrong, In this case, we‘ll be sending
//10 samples each second, so we‘ll put the timestamp unit to (1.0/10.0)     
//设置时间戳是一件非常重要的事情,是RTP会话初始化过程所要进行的另外一项重要工
//作,他的单位是秒,如:当使用RTP会话传输8000Hz採样的音频数据时,因为时戳
//每秒钟将递增8000,所以时戳单元对应地应该被设置成1/8000:
sessparams.SetAcceptOwnPackets(true);
//通过这个函数我们能够设置是不是接收我们自己定义的数据包。
 
3、数据发送
   我想当我们要想建立连接的时候,我们就要让发送端知道要发送到的主机的IP地址,在jrtplib中我们能够通过RTPSession成员函数AddDestination()、DeleteDestination()和 ClearDestinations()来完毕。如以下是将数据发送给本机的6000号端口:
 
unsigned long addr = ntohl(inet_addr("127.0.0.1"));
sess.AddDestination(addr, 6000);
 
当然我们还能够这样来完毕添?一个client,
 
RTPIPv4Address addr(destip,destport);//destip为clientIP地址,destport为client//端口号
status = sess.AddDestination(addr);
checkerror(status);  
  
   目标地址全部指定之后,接着就能够调用RTPSession类的SendPacket()方法,向全部的目标地址发送流媒体数据。SendPacket()是RTPSession类提供的一个重载函数,它具有下列多种形式:
int SendPacket(void *data,int len)
int SendPacket(void *data,int len,unsigned char pt,bool mark,
unsigned long timestampinc)
int SendPacket(void *data,int len,unsigned short hdrextID,void *hdrextdata,
int numhdrextwords)
int SendPacket(void *data,int len,unsigned char pt,bool mark,
unsigned long timestampinc,unsigned short hdrextID,
void *hdrextdata,int numhdrextwords)
SendPacket()最典型的使用方法是相似于以下的语句,当中第一个參数是要被发送的数据,而第二个參数则指明将要发送数据的长度,再往后依次是RTP负载类型、标识和时戳增量。例如以下所看到的:
status = sess.SendPacket((void *)"1234567890",10,0,false,10);
checkerror(status);
对于同一个RTP会话来讲,负载类型、标识和时戳增量通常来讲都是同样的,JRTPLIB同意将它们设置为会话的默认參数,这是通过调用 RTPSession类的SetDefaultPayloadType()、SetDefaultMark()和 SetDefaultTimeStampIncrement()方法来完毕的。为RTP会话设置这些默认參数的优点是能够简化数据的发送,比如,假设为 RTP会话设置了默认參数:
session.SetDefaultPayloadType(96);//注意这个參数不能随便设置,參考RFC3551
session.SetDefaultMark(false);
session.SetDefaultTimestampIncrement(160);
在设置了以上的值后,我们能够这样来发送数据:
status = sess.SendPacket((void *)"1234567890",10);
3、数据接收
对于流媒体数据的接收端,首先须要调用RTPSession类的PollData()方法来接收发送过来的RTP或者RTCP数据报。因为同一个 RTP会话中同意有多个參与者(源),你既能够通过调用RTPSession类的GotoFirstSource()和GotoNextSource() 方法来遍历全部的源,也能够通过调用RTPSession类的GotoFirstSourceWithData()和 GotoNextSourceWithData()方法来遍历那些携带有数据的源。在从RTP会话中检測出有效的数据源之后,接下去就能够调用 RTPSession类的GetNextPacket()方法从中抽取RTP数据报,当接收到的RTP数据报处理完之后,一定要记得及时释放。以下的代码示范了该怎样对接收到的RTP数据报进行处理:

#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
RTPSession sess;

#ifdef WIN32
WSACleanup();
#endif // WIN32

#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
//RTPUDPv4TransmissionParams
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"

void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}

JRTPLIB为RTP数据报定义了三种接收模式,当中每种接收模式都详细规定了哪些到达的RTP数据报将会被接受,而哪些到达的RTP数据报将会被拒绝。通过调用RTPSession类的SetReceiveMode()方法能够设置下列这些接收模式:
① RECEIVEMODE_ALL 缺省的接收模式,全部到达的RTP数据报都将被接受;
② RECEIVEMODE_IGNORESOME  除了某些特定的发送者之外,全部到达的RTP数据报都将被接受,而被拒绝的发送者列表能够通过调用AddToIgnoreList()、ClearIgnoreList()     和DeleteFromIgnoreList()方法来进行设置;
③ RECEIVEMODE_ACCEPTSOME  除了某些特定的发送者之外,全部到达的RTP数据报都将被拒绝,而被接受的发送者列表能够通过调用AddToAcceptList ()、ClearAcceptList ()和eleteFromAcceptList方法来进行设置。
4、执行程序
   在执行程序之前,我们要知道,这是基于UDP协议的数据报服务。我们的example1是在本机上实现的RTP传输,而且仅仅有一个RTPSession对象,所以我们的监听和接收的port是同一个,所以此时我们的portBase要和我们添?到RTPSession对象中的client的port一致,如上面我们能够都设置成6000.可是假设是在两个线程中,我们就要注意了,serverport和客户port一定不一样,这也是主要的知识,用的时候要注意,多思考。

1.设置基本參数
RTPSession m_RTPSocket;
m_RTPSocket.Create(m_SPort);
m_RTPSocket.SetTimestampUnit(1.0/25.0);
m_RTPSocket.SetSessionBandwidth(900.0);
m_RTPSocket.SetMaxPacketSize(65535);
m_RTPSocket.SetDefaultPayloadType(0);
m_RTPSocket.SetDefaultMark(false);
m_RTPSocket.SetDefaultTimeStampIncrement(10);
2.发送
int status = m_RTPSocket.SendPacket(pFrame,wSize,1,name,10);
3,接收
int size = 0;
SOCKET sockRtp,sockRtcp;
struct timeval rttprev = {0,0},rtt,tv;
fd_set fdset;
bool frist = true;
int port = ((CRNetVideoCtrl*)m_pMainClass)-> m_destport;
if(port == -1)
StopThread();
RTPSession m_RTPSocket;
m_RTPSocket.Create(port);
m_RTPSocket.SetSessionBandwidth(64);

m_RTPSocket.GetRTPSocket(&sockRtp);
m_RTPSocket.GetRTCPSocket(&sockRtcp);

m_pDecoder = new CVideoDecode();
m_pDecoder-> dec_init(1);

unsigned char* pBuffer = new unsigned char [320*240*2];

while(!m_bClose){
tv.tv_sec = 0;
tv.tv_usec = 100000;
FD_ZERO(&fdset);
FD_SET(sockRtcp,&fdset);
FD_SET(sockRtp,&fdset);
int maxSize = max(sockRtp, sockRtcp);
int selectRet = select(maxSize + 1,&fdset,NULL,NULL,&tv);
if (-1 == selectRet || 0 == selectRet)
continue;
/* poll for incoming data *///调用这个,这样才可以获得数据
m_RTPSocket.PollData();
/* check incoming packets *///原来是rtp数据包
if (FD_ISSET(sockRtp, &fdset)){

if (m_RTPSocket.GotoFirstSourceWithData()){
RTPPacket *pack;
while ((pack = m_RTPSocket.GetNextPacket()) != NULL){
if(frist){
//检查是否是关键帧
if(pack-> IsMarked()){
if((CRNetVideoCtrl*)m_pMainClass){
m_pDecoder-> dec_main(pack-> GetPayload(),pBuffer,pack-> GetPayloadLength(),&size);
((CRNetVideoCtrl*)m_pMainClass)-> DecodeVideo(pBuffer,size);
TRACE( "Client Received IFrame/n ");
frist = false;
}
}
}
else{
//解码并显示
m_pDecoder-> dec_main(pack-> GetPayload(),pBuffer,pack-> GetPayloadLength(),&size);
((CRNetVideoCtrl*)m_pMainClass)-> DecodeVideo(pBuffer,size);
}
delete pack;
}
}
}
if (FD_ISSET(sockRtcp, &fdset)){
if (m_RTPSocket.GotoFirstSource())
{
do
{
RTPSourceData *srcdat;
srcdat = m_RTPSocket.GetCurrentSourceInfo();
if (NULL != srcdat)
{
rtt = srcdat-> INF_GetRoundTripTime();
if (rtt.tv_sec != 0 || rtt.tv_usec != 0)
{
double t;
t = (double)rtt.tv_sec;
t += ((double)rtt.tv_usec)/1000000.0;
t *= 1000.0; // we want milliseconds;
TRACE( "rtt: %f ms/n ", (float)t);
rttprev = rtt;
}
if (parent-> m_canSend)
{
sprintf(msg, "丢包: %f/n ", srcdat-> RR_GetPacketsLost());
sprintf(msg, "包序号: %d/n ", srcdat-> RR_GetExtendedHighestSequenceNumber());
sprintf(msg, "jitter: %d/n ", srcdat-> RR_GetJitter());
reportNum = 0;
}
srcdat-> FlushPackets(); // we don ‘t need the actual data
}
srcdat = NULL;
} while (m_RTPSocket.GotoNextSource());
}

}

}

if(m_pDecoder)
delete m_pDecoder;
m_pDecoder = NULL;

delete []pBuffer;

return 1L;

关于开源的RTP——jrtplib的使用

时间: 2024-08-04 12:46:42

关于开源的RTP——jrtplib的使用的相关文章

流媒体技术:VS2012下RTP开源协议库JRTPLIB 3.9.1编译

一. JRTPLIB简介 RTP 是目前解决流媒体实时传输问题的最好办法,而JRTPLIB是一个用C++语言实现的RTP库,它完全遵循RFC 1889设计,目前已经可以运行在Windows.Linux.FreeBSD.Solaris.Unix和 VxWorks等多种操作系统上.在使用JRTPLIB之前,需要对其进行编译. 二. 使用的平台与软件 操作系统:windows 7 软件:CMake 3.2.3 + Visual Studio 2012 二. 下载链接 由于要对jrtplib进行编译,且

RTP RTCP在音视频传输与同步方面的使用

转自:http://blog.csdn.net/kof98765/article/details/17733701 1 音视频实时传输 1.1 Jrtplib库介绍 本系统采用开源库Jrtplib进行RTP传输模块的开发.Jrtplib库是由比利时Hasselt大学EDM(Expertise Centre for Digital Media)开发的一个用C++语言实现的完全开源的RTP库,目前已经可以运行在Windows.Linux.FreeBSD.Solaris.Unix和VxWorks等多种

音视频文件分析工具

一个mp4文件分析工具 http://blog.chinaunix.net/uid-11857489-id-2814505.html http://www.cnblogs.com/aHuner/p/3629709.html 1.视频源下载 MPEG-2 Transport Stream Test Patterns and Tools:http://www.w6rz.net/HEVC/H.265, AVC/H.264, MPEG-4, MPEG-2 video:http://www.elecard

vs2008 下编译jrtplib-3.9.0成功

jrtplib-3.9.0的编译,终于搞通了.网上搜集了很多资料,自己也调试了很久. 首先,jrtplib-3.9.0是什么不用多说吧,它是一个很牛的老外用C++写的一个开源的RTP协议库,用它可以进行数据的实时传输.RTP是实时传输协议的简称,由最新的RFC3550文档进行规范. 1.从http://research.edm.uhasselt.be/~jori/page/index.php?n=CS.Jrtplib下载最新的jrtplib-3.9.0和jthread-1.3.0. 2.从htt

基于SIP和RTP协议的开源VOIP之QuteCom简介

*************************************************************************************************************************** 作者:EasyWave                                                                              时间:2014.10.30 类别:Linux应用-基于oSIP协议的开源V

使用jrtplib(RTP)传输H.264视频文件(2)

上一篇我们介绍了RTP协议的一些基本知识,下面我们介绍如何使用jrtplib这个库传输H264编码. JRTP传输: 好了,下面是我写的使用JRTP进行发送H264数据包的例子,具体解释可以看注释.发送端也可以接收接收端发送过来的RTCP数据包. #define MAX_RTP_PKT_LENGTH 1360 #define H264               96 bool CheckError(int rtperr); class CRTPSender : public RTPSessio

基于JRTPLib的rtp编程例程

这里演示了在linux环境下使用JRTPlib库完成rtp协议的封装,此例程可以作为流媒体传输的基本例程. 这里只给出源码(这些在JRtplib的官方文件中都可以找到) 发送端: /** 发送端程序(windows,linux通用)* 基于IPv4的传输例程,需要提供一个端口号和目的地址* 参考:http://blog.csdn.net/ipromiseu/article/details/4531656*/#include "rtpsession.h" //定义了rtpsession的

EasyDarwin开源社区流媒体视频课程:流媒体传输控制协议(RTSP RTP SDP)详解之RTSP

视频课程及相关文档代码地址:https://github.com/EasyDarwin/Course#course-3 流媒体传输协议介绍 一.RTSP协议介绍 什么是rtsp? RTSP协议以客户服务器方式工作,,如:暂停/继续.后退.前进等.它是一个多媒体播放控制协议,用来使用户在播放从因特网下载的实时数据时能够进行控制, 因此 RTSP 又称为"因特网录像机遥控协议". RTSP(Real-Time Stream Protocol)是一种基于文本的应用层协议,在语法及一些消息参数

一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(六)RTP音视频传输解析层之音视频数据传输格式

一.差异 本地音视频数据格式和用来传输的音视频数据格式存在些许差异,由于音视频数据流到达客户端时,需要考虑数据流的数据边界.分包.组包顺序等问题,所以传输中的音视频数据往往会多一些字节. 举个例子,有时候一个媒体分包数据量很大(比如H264的一个分包常常会有2-4K),而大多数网络的MTU(最大传输单元)基本都是1500字节. 如果频繁收发这么大的数据包,会额外增添路由器的负担,甚至会导致网络阻塞,不利于网络的稳定. 于是服务器就自行对H264进行了分包以适应MTU,每个分包的开始处往往会多出一