您的位置:首页 > 理论基础 > 计算机网络

RTP协议--RR,SR,实例程序 并附有RTCP控制协议解释

2010-08-11 11:35 483 查看
RTCP默认5秒发送一次大概。

RTCP控制协议
RTCP控制协议需要与RTP数据协议一起配合使用,当应用程序启动一个RTP会话时将同时占用两个端口,分别供RTP和RTCP使用。RTP本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制,这些都由RTCP来负责完成。通常RTCP会采用与RTP相同的分发机制,向会话中的所有成员周期性地发送控制信息,应用程序通过接收这些数据,从中获取会话参与者的相关资料,以及网络状况、分组丢失概率等反馈信息,从而能够对服务质量进行控制或者对网络状况进行诊断。

RTCP协议的功能是通过不同的RTCP数据报来实现的,主要有如下几种类型:
SR  发送端报告,所谓发送端是指发出RTP数据报的应用程序或者终端,发送端同时也可以是接收端。
RR  接收端报告,所谓接收端是指仅接收但不发送RTP数据报的应用程序或者终端。
SDES  源描述,主要功能是作为会话成员有关标识信息的载体,如用户名、邮件地址、电话号码等,此外还具有向会话成员传达会话控制信息的功能。
BYE  通知离开,主要功能是指示某一个或者几个源不再有效,即通知会话中的其他成员自己将退出会话。
APP  由应用程序自己定义,解决了RTCP的扩展性问题,并且为协议的实现者提供了很大的灵活性。
RTCP数据报携带有服务质量监控的必要信息,能够对服务质量进行动态的调整,并能够对网络拥塞进行有效的控制。由于RTCP数据报采用的是多播方式,因此会话中的所有成员都可以通过RTCP数据报返回的控制信息,来了解其他参与者的当前情况。
在一个典型的应用场合下,发送媒体流的应用程序将周期性地产生发送端报告SR,该RTCP数据报含有不同媒体流间的同步信息,以及已经发送的数据报和字节的计数,接收端根据这些信息可以估计出实际的数据传输速率。另一方面,接收端会向所有已知的发送端发送接收端报告RR,该RTCP数据报含有已接收数据报的最大序列号、丢失的数据报数目、延时抖动和时间戳等重要信息,发送端应用根据这些信息可以估计出往返时延,并且可以根据数据报丢失概率和时延抖动情况动态调整发送速率,以改善网络拥塞状况,或者根据网络状况平滑地调整应用程序的服务质量。

//RR例子:

#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtpsourcedata.h"
#include "rtcpsrpacket.h"
#include "rtcprrpacket.h"
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif // WIN32
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

//添加库
#pragma comment(lib, "jrtplib.lib")
#pragma comment(lib, "jthread.lib")
#pragma comment(lib, "WS2_32.lib")
using namespace std;
int total= 0;

#ifdef RTP_SUPPORT_THREAD
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
class MyRTPSession : public RTPSession
{
protected:
void OnPollThreadStep();
};
void MyRTPSession::OnPollThreadStep() //重载虚函数,线程函数
{
BeginDataAccess();

if (GotoFirstSource())
{
do
{
RTPSourceData *srcdat;

srcdat = GetCurrentSourceInfo();
if(srcdat->RR_HasInfo())//打印RR信息
{
cout<<"RR Info:";
cout<<total++<<endl;
cout << " GetSSRC: "<<srcdat->GetSSRC()<<endl;
cout << " Fraction lost: " << srcdat->RR_GetFractionLost() <<endl;
cout << " Packets lost: " << srcdat->RR_GetPacketsLost() <<endl;
cout << " Ext.High.Seq: " << srcdat->RR_GetExtendedHighestSequenceNumber() <<endl;
cout << " Jitter: " << srcdat->RR_GetJitter() << endl;
cout << " LSR: " << srcdat->RR_GetLastSRTimestamp() <<endl;
cout << " DLSR: " << srcdat->RR_GetDelaySinceLastSR() <<endl;
cout << " Receive time: " << srcdat->RR_GetReceiveTime().GetSeconds() <<endl;
}
srcdat->FlushPackets();
} while (GotoNextSource());
}
EndDataAccess();
}

int main(void)
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32

int status,num;

std::cout << std::endl;
std::cout << "Number of packets you wish to be sent:" << std::endl;
std::cin >> num;

MyRTPSession sess;
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;

sessparams.SetOwnTimestampUnit(1.0/10.0);

sessparams.SetAcceptOwnPackets(true);
sessparams.SetUsePollThread(true);//默认是开启的,为确保开启再设置下
transparams.SetPortbase(7000);
status = sess.Create(sessparams,&transparams);
checkerror(status);

uint8_t ip[]= {127,0,0,1};
RTPIPv4Address addr(ip,6006);
status = sess.AddDestination(addr);
checkerror(status);

unsigned long ssrc= sess.GetLocalSSRC();//获取同步源标示
cout<<ssrc<<endl;
while(1)
{
RTPTime::Wait(RTPTime(1,0));
status = sess.SendPacket((void *)"1234567890",10,0,false,10);
checkerror(status);
}

sess.BYEDestroy(RTPTime(10,0),0,0);
#ifdef WIN32
WSACleanup();
#endif // WIN32
return 0;
}
#endif // RTP_SUPPORT_THREAD

//SR 接收端例子

#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtcpsrpacket.h"
#include "rtcprrpacket.h"
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif // WIN32
#include "rtpsourcedata.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#pragma comment(lib, "jrtplib.lib")
#pragma comment(lib, "jthread.lib")
#pragma comment(lib, "WS2_32.lib")
using namespace std;
#ifdef RTP_SUPPORT_THREAD //支持多线程
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
//
// The new class routine
//
class MyRTPSession : public RTPSession//重载类
{
protected:
void OnPollThreadStep();
void ProcessRTPPacket(const RTPSourceData &srcdat,const RTPPacket &rtppack);
};
void MyRTPSession::OnPollThreadStep() //重载虚函数,线程函数
{
BeginDataAccess();

// check incoming packets
if (GotoFirstSourceWithData())
{
do
{
RTPPacket *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 &rtppack)
{
if(srcdat.SR_HasInfo())//打印SR信息
{
cout<<"SR Info:/n";
cout << "Got packet GetExtendedSequenceNumber:" << rtppack.GetExtendedSequenceNumber()<<endl;
cout<<"Recv PacketCount:"<<srcdat.SR_GetPacketCount()<<endl;
cout<< "from SSRC: " << srcdat.GetSSRC() << std::endl;
cout<<"GetFractionLost:"<<srcdat.SR_Prev_GetPacketCount();
cout<<endl;
}
}
// The main routine
int main(void)
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32

MyRTPSession sess;//这里用的重载类
int status,num;

RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/8000.0);

transparams.SetPortbase(6006);
sessparams.SetUsePollThread(true);//默认是开启的
status = sess.Create(sessparams,&transparams);
checkerror(status);
uint8_t ip[]= {127,0,0,1};//要加入发送端的IP,用于返回信息
RTPIPv4Address addr(ip,7000);

status = sess.AddDestination(addr);
checkerror(status);
cout<<"Waiting recv data!/n";
while(1)
{
}
sess.BYEDestroy(RTPTime(10,0),0,0);
#ifdef WIN32
WSACleanup();
#endif // WIN32
return 0;
}
#else
int main(void)
{
std::cerr << "Thread support is required for this example" << std::endl;
return 0;
}
#endif // RTP_SUPPORT_THREAD

注意:jrtplib.lib和jthread.lib要放到工程或程序能找到的地方
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: