zoukankan      html  css  js  c++  java
  • jrtplib使用注意事项

    一、说明

    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");
    }


  • 相关阅读:
    Vue 中的无状态组件
    如何在 Vue 中使用 JSX 以及使用它的原因
    webpack打包优化的四种方法(多进程打包,多进程压缩,资源 CDN,动态 polyfill)
    watch监听对象
    微信小程序动态设置图片大小
    Flutter的生命周期和路由
    两个字符串的编辑距离学习[转载]
    系统进化树怎么看[转载]
    感知机PLA算法实现[转载]
    余弦相似度计算[转载]
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4565530.html
Copyright © 2011-2022 走看看