jrtplib使用注意事项

时间:2022-11-13 20:58:33

一、说明

RTP 现在的问题是要解决的流媒体的实时传输的问题的最佳方法。和JRTPLIB 是一个用C++语言实现的RTP库。包含UDP通讯。刚使用JRTPLIB,对JRTPLIB的理解还不够深,当做使用时,积累的一些经验写个笔记吧。

二、RTP协议

实时传送协议(Real-time
Transport Protocol或简写RTP,也能够写成RTTP)是一个网络传输协议,RTP协议具体说明了在互联网上传递音频和视频的标准数据包格式。它一開始被设计为一个多播协议。但后来被用在非常多单播应用中。

RTP协议经常使用于流媒体系统(配合RTCP协议或者RTSP协议)。由于RTP自身具有Time
stamp所以在ffmpeg 中被用做一种formate。

RTP协议的具体介绍,请參考这篇文章http://www.360doc.com/content/11/1009/15/496343_154624612.shtml

三、RTPSession类

这里不介绍jrtplib的编译安装。这个非常easy,网上非常多地方都有解说。

jrtplib的使用中,主要是环绕这个类来实现的,因此大家有必要去查看源代码,看这类的实现。为了方便使用,我在这做了RTPSession的继承封装。以下直接贴代码了。

RTPSessionUtils.h

#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.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> //jrtplib应用需链接的lib
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib, "jrtplib_d.lib")
#pragma comment(lib,"jthread_d.lib") namespace jrtplib
{
class RTPSessionUtils : public RTPSession
{
typedef RTPSession base_type;
public:
RTPSessionUtils();
~RTPSessionUtils(); int AddDestination(const std::string& ip, uint16_t port);
int DeleteDestination(const std::string& ip, uint16_t port);
int CreateDefault(uint16_t port);
protected:
void OnNewSource(RTPSourceData *dat);
void OnBYEPacket(RTPSourceData *dat);
void OnRemoveSource(RTPSourceData *dat);
void OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnPollThreadStep();
private:
int GetAddrFromSource(RTPSourceData *dat, uint32_t& ip, uint16_t& port);
};
} //整形的ip转成字符串ip
static std::string IPToString(const unsigned int iIP)
{
struct in_addr inaddr;
inaddr.s_addr = htonl(iIP);
return std::string(inet_ntoa(inaddr));
} //字符串ip转成整形ip
static unsigned int IPToInt(const std::string& sIP)
{
return inet_addr(sIP.c_str());
}

RTPSessionUtils.cpp

#include "RTPSessionUtils.h"

namespace jrtplib{
RTPSessionUtils::RTPSessionUtils()
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
} RTPSessionUtils::~RTPSessionUtils()
{
#ifdef WIN32
WSACleanup();
#endif // WIN32
} int RTPSessionUtils::CreateDefault(uint16_t port)
{
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/10.0);//必须设置
transparams.SetPortbase(port);//port必须是偶数
return base_type::Create(sessparams, &transparams); base_type::SetDefaultPayloadType(0);
base_type::SetDefaultTimestampIncrement(0);
base_type::SetDefaultMark(false);
} int RTPSessionUtils::AddDestination(const std::string& ip, uint16_t port)
{
return base_type::AddDestination(RTPIPv4Address(ntohl(inet_addr(ip.c_str())), port));
} int RTPSessionUtils::DeleteDestination(const std::string& ip, uint16_t port)
{
return base_type::DeleteDestination(RTPIPv4Address(ntohl(inet_addr(ip.c_str())), port));
} int RTPSessionUtils::GetAddrFromSource(RTPSourceData *dat, uint32_t& ip, uint16_t& port)
{
if (dat->IsOwnSSRC())
return -1; if (dat->GetRTPDataAddress() != 0)
{
const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());
ip = addr->GetIP();
port = addr->GetPort();
}
else if (dat->GetRTCPDataAddress() != 0)
{
const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());
ip = addr->GetIP();
port = addr->GetPort()-1;
} return 0;
} void RTPSessionUtils::OnNewSource(RTPSourceData *dat)
{
uint32_t ip;
uint16_t port; if (GetAddrFromSource(dat, ip, port))
return; RTPIPv4Address dest(ip,port);
base_type::AddDestination(dest); std::cout << "OnNewSource Adding destination " << IPToString(ip) << ":" << port << std::endl;
} void RTPSessionUtils::OnRemoveSource(RTPSourceData *dat)
{
if (dat->ReceivedBYE())
return; uint32_t ip;
uint16_t port; if (GetAddrFromSource(dat, ip, port))
return; RTPIPv4Address dest(ip,port);
base_type::DeleteDestination(dest); std::cout << "OnRemoveSource Deleting destination " << IPToString(ip) << ":" << port << std::endl;
} void RTPSessionUtils::OnBYEPacket(RTPSourceData *dat)
{
uint32_t ip;
uint16_t port; if (GetAddrFromSource(dat, ip, port))
return; RTPIPv4Address dest(ip,port);
base_type::DeleteDestination(dest); std::cout << "OnBYEPacket Deleting destination " << IPToString(ip) << ":" << port << std::endl;
} //仅仅要有rtp包就会触发
void RTPSessionUtils::OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress)
{
std::cout << "OnRTPPacket: data:" << pack->GetPayloadData() << std::endl;
} //收到rtcp包触发
void RTPSessionUtils::OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress)
{
std::cout << "OnRTCPCompoundPacket: data:" << pack->GetCompoundPacketData() << std::endl;
} //隔段时间就会触发,也能够用于收包回调函数
//void RTPSessionUtils::OnPollThreadStep()
//{
// BeginDataAccess(); // // check incoming packets
// if (GotoFirstSourceWithData())
// {
// do
// {
// RTPPacket *pack;
// RTPSourceData *srcdat; // srcdat = GetCurrentSourceInfo(); // while ((pack = GetNextPacket()) != NULL)
// {
// std::cout << "Got packet " << pack->GetExtendedSequenceNumber() << " from SSRC " << srcdat->GetSSRC() << std::endl;
// DeletePacket(pack);
// }
// } while (GotoNextSourceWithData());
// } // EndDataAccess();
//}
}

server.cpp

#include <iostream>
#include "RTPSessionUtils.h"
using namespace jrtplib;
void main()
{
int status;
RTPSessionUtils sess;
status = sess.CreateDefault(8888);
if(status)
{
std::cout << "RTP error:" << RTPGetErrorString(status) << std::endl;
return;
} while (1)
{
std::string buf;
std::cout << "Input send data:" ;
std::cin >> buf; sess.SendPacket((void*)buf.c_str(), buf.length(), 0, false, 0);
if(status)
{
std::cout << "RTP error:" << RTPGetErrorString(status) << std::endl;
continue;
}
} system("pause");
}

client.cpp

#include <iostream>
#include "RTPSessionUtils.h"
using namespace jrtplib; void main()
{
int status;
RTPSessionUtils sess;
status = sess.CreateDefault(6666);
if(status)
{
std::cout << "RTP error:" << RTPGetErrorString(status) << std::endl;
return;
}
status = sess.AddDestination("127.0.0.1", 8888);
if(status)
{
std::cout << "RTP error:" << RTPGetErrorString(status) << std::endl;
return;
} while (1)
{
std::string buf;
std::cout << "Input send data:" ;
std::cin >> buf; sess.SendPacket((void*)buf.c_str(), buf.length(), 0, false, 0);
if(status)
{
std::cout << "RTP error:" << RTPGetErrorString(status) << std::endl;
continue;
}
} system("pause");
}