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");
}
jrtplib使用注意事项的更多相关文章
- jQuery UI resizable使用注意事项、实时等比例拉伸及你不知道的技巧
这篇文章总结的是我在使用resizable插件的过程中,遇到的问题及变通应用的奇思妙想. 一.resizable使用注意事项 以下是我在jsfiddle上写的测试demo:http://jsfiddl ...
- Windows Server 2012 NIC Teaming介绍及注意事项
Windows Server 2012 NIC Teaming介绍及注意事项 转载自:http://www.it165.net/os/html/201303/4799.html Windows Ser ...
- TODO:Golang指针使用注意事项
TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...
- app开发外包注意事项,2017最新资讯
我们见过很多创业者,栽在这app外包上.很多创业者对于app外包这件事情不是特别重视,以为将事情交给app外包公司就完事了,实际上不是的.无论是从选择app外包公司还是签订合同.售后维护等各方面都有许 ...
- favicon.ioc使用以及注意事项
1.效果 2.使用引入方法 2.1 注意事项:(把图标命名为favicon.ico,并且放在根目录下,同时使用Link标签,多重保险) 浏览器默认使用根目录下的favicon.ico 图标(如果你并没 ...
- ORACLE分区表梳理系列(二)- 分区表日常维护及注意事项(红字需要留意)
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
- 【原】Masonry+UIScrollView的使用注意事项
[原]Masonry+UIScrollView的使用注意事项 本文转载请注明出处 —— polobymulberry-博客园 1.问题描述 我想实现的使用在一个UIScrollView依次添加三个UI ...
- 《连载 | 物联网框架ServerSuperIO教程》- 5.轮询通讯模式开发及注意事项。附:网友制作的类库说明(CHM)
1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...
- 《连载 | 物联网框架ServerSuperIO教程》- 6.并发通讯模式开发及注意事项
1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...
随机推荐
- Codeforces 358 D. Dima and Hares
dp[i][0]表示i号兔子先于i-1号兔子喂食,dp[i][1]反过来. 倒着DP D. Dima and Hares time limit per test 2 seconds memory li ...
- VC生成的DLL给QT的EXE调用时lib路径问题小结
VC生成的DLL给QT调用,有两种方式,一种是隐式调用调用(使用.lib文件方式): ① 在*.pro工程文件中添加VC生成的lib文件路径时,或者使用一个绝对路径,如: LIBS += " ...
- Inside Qt Series (全集)
Inside Qt 系列 QObject这个 class 是 QT 对象模型的核心,绝大部分的 QT 类都是从这个类继承而来.这个模型的中心特征就是一个叫做信号和槽(signaland slot)的机 ...
- isapi_rewrite运行在.net framework 4.0+iis 6.0环境下404错误解决方案
今天以前的同事让我帮他上服务器看看,他把页面伪静态之后,出现404错误,为什么会出现这样的问题呢,仔细研究才发现,原因如下: 因为ASP.NET4.0在安装的过程中,已经在IIS6做了一些手脚,让它可 ...
- 记录break和continue的区别
我对break 和 continue 还是有点搞不清除,今天在看<Thinking in Java>,看到这个,学习了一下. break的作用是跳出这个循环(如果这个break ...
- C#使用Redis集群缓存
C#使用Redis集群缓存 本文介绍系统缓存组件,采用NOSQL之Redis作为系统缓存层. 一.背景 系统考虑到高并发的使用场景.对于并发提交场景,通过上一章节介绍的RabbitMQ组件解决.对于系 ...
- 算法起步之动态规划LCS
原文:算法起步之动态规划LCS 前一篇文章我们了解了什么是动态规划问题,这里我们再来看动态规划另一个经典问题,最长公共子序列问题(LCS),什么是子序列,我们定义:一个给定序列将其中的0个或者多个元素 ...
- python安装依赖
yum install zlib zlib-devel openssl openssl-devel bzip2 bzip2-devel ncurses ncurses-devel readline r ...
- hdu4612(双连通缩点+树的直径)
传送门:Warm up 题意:询问如何加一条边,使得剩下的桥的数目最少,输出数目. 分析:tarjan缩点后,重新建图得到一棵树,树上所有边都为桥,那么找出树的直径两个端点连上,必定减少的桥数量最多, ...
- SpringMVC配置+小例子
先加入SpringMVC的jar包,这个官网上有,下载下来放到lib文件夹下. web.xml文件: <?xml version="1.0" encoding="U ...