jrtplib使用笔记[通俗易懂]

一、简述RTP是目前解决流媒体实时传输问题的最好办法,而JRTPLIB是一个用C++语言实现的RTP库,包括UDP通讯。刚使用JRTPLIB,对JRTPLIB的理解还不够深,当做使用时,积累的一些经验写个笔记吧。二、RTP协议实时传送协议(Real-timeTransportProtocol或简写RTP,也可以写成RTTP)是一个网络传输协议,RTP协议详细说明了在互联

大家好,又见面了,我是你们的朋友全栈君。

一、简述

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的编译安装,这个很简单,网上很多地方都有讲解。

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/125825.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 大数据–商品推荐系统介绍(上)

    这次我们介绍商品推荐系统:推荐系统是什么推荐引擎的分类常见的推荐算法混合的推荐机制(重要)推荐系统架构协同过滤的实现推荐引擎解决的几个问题主动的用户,通过类目和搜索进行引导,对结果页进行干预被动的用户,通过用户的历史行为分析,推荐用户可能感兴趣的商品。对商家来讲,帮助商家卖出更多的东西推荐系统是什么目的为了解决信息过载和用户无明确需求的问题,找到用户感兴趣的物品…

  • 详解汇编语言B和LDR指令与相对跳转和绝对跳转的关系[通俗易懂]

    详解汇编语言B和LDR指令与相对跳转和绝对跳转的关系[通俗易懂]相对跳转和绝对跳转为什么要有相对跳转和绝对跳转?B和LDR跳转范围为什么两者的跳转范围不同?如何区分?

  • 茅台抢购脚本详细教程, 另已将茅台抢购做成了一个软件

    今天对软件进行了升级,公众号上重新回复茅台获取最新软件!!最新软件解压后如图!以管理员方式运行main.exe软件最后抢购成功是不会主动付款的,要自己去APP支付注意使用茅台软件版抢购的朋友需要自己先去app上预约抢购!!!预约完之后,运行软件,输入2按回车键!,等待到指定时间开始抢购!!!别再问我为什么没动了!因为还没到抢购时间!!别再问我为什么没动了!因为还没到抢购时间!!别再问我为什么没动了!因为还没到抢购时间!!文章上有详细说明的,就不要再问我了!!看文章就对了,问我也

  • 计算机基础知识[通俗易懂]

    计算机基础知识[通俗易懂]一、为何要学习计算机基础?好多人觉得自己有点基础就都想着直接敲代码,觉得基础知识很容易,很简单,就不怎么用心去学。然而,我觉得基础知识很重要。就像盖一栋楼房一样,你先要打好地基,再去盖房。Pyth

  • dsp运动控制卡_营销行动方案控制

    dsp运动控制卡_营销行动方案控制ARM+FPGA运动控制卡运动控制卡方案运动控制卡方案运动控制卡方案由于ARM源码核心运动控制算法部分缺失,因此便宜出售此资料,拍前请了解好,不接受退货,资料包含此运动控制卡原理图,PCB图,FPGA源码,ARM去掉算法后的框架源码,拍下后发邮箱。本运动控制卡采用ARM单片机+FPGA架构;ARM单片机是基于Cortex-M3内核的LM3S6911,插补核心算法均在该ARM内完成,一方面通过以太网与上位机界面交换加工数据,另一方面与FPGA(ALTERA的EP1C3)交换加工脉冲计数与IO

    2022年10月15日
  • 优先级队列默认最小值优先吗_低优先级队列要等几局

    优先级队列默认最小值优先吗_低优先级队列要等几局1.优先级队列是什么??首先,优先级队列是一个队列,队列所有的性质,它也有。其次,优先级队列每次取出的是优先级最高的元素。优先级队列的内部是用堆来维护的。将优先级最高的排在前面。2.什么时候用这个队列呢??看完优先级队列的定义,好像看懂了,又好像没看懂。这队列,什么用它呢?1)排序的对象和排序时比较的对象常见的排序方法(插入、快排等),排序的对象和比较的对象是一样的,根据数本身的大小进行排序。优先级队列可以对排序对象和比较对象相同的进行排序,也可以对排序的对象和排序时比较的对象不同的

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号