一、说明

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使用注意事项的更多相关文章

  1. jQuery UI resizable使用注意事项、实时等比例拉伸及你不知道的技巧

    这篇文章总结的是我在使用resizable插件的过程中,遇到的问题及变通应用的奇思妙想. 一.resizable使用注意事项 以下是我在jsfiddle上写的测试demo:http://jsfiddl ...

  2. Windows Server 2012 NIC Teaming介绍及注意事项

    Windows Server 2012 NIC Teaming介绍及注意事项 转载自:http://www.it165.net/os/html/201303/4799.html Windows Ser ...

  3. TODO:Golang指针使用注意事项

    TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...

  4. app开发外包注意事项,2017最新资讯

    我们见过很多创业者,栽在这app外包上.很多创业者对于app外包这件事情不是特别重视,以为将事情交给app外包公司就完事了,实际上不是的.无论是从选择app外包公司还是签订合同.售后维护等各方面都有许 ...

  5. favicon.ioc使用以及注意事项

    1.效果 2.使用引入方法 2.1 注意事项:(把图标命名为favicon.ico,并且放在根目录下,同时使用Link标签,多重保险) 浏览器默认使用根目录下的favicon.ico 图标(如果你并没 ...

  6. ORACLE分区表梳理系列(二)- 分区表日常维护及注意事项(红字需要留意)

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  7. 【原】Masonry+UIScrollView的使用注意事项

    [原]Masonry+UIScrollView的使用注意事项 本文转载请注明出处 —— polobymulberry-博客园 1.问题描述 我想实现的使用在一个UIScrollView依次添加三个UI ...

  8. 《连载 | 物联网框架ServerSuperIO教程》- 5.轮询通讯模式开发及注意事项。附:网友制作的类库说明(CHM)

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

  9. 《连载 | 物联网框架ServerSuperIO教程》- 6.并发通讯模式开发及注意事项

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

随机推荐

  1. LeetCode——Populating Next Right Pointers in Each Node II

    Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...

  2. wake_lock_timeout的用法

    今天实用到用ec43_GPIO的中断来唤醒系统,将系统从深度休眠中唤醒并保证系统wakup 一段时间用过了.方法例如以下.有相同使用的童鞋能够參考一下. 1.   定义一人局部静态变量ec43_wlo ...

  3. JAVA中enum的常见用法

    JAVA中enum的常见用法包括:定义并添加方法.switch.遍历.EnumSet.EnumMap 1.定义enum并添加或覆盖方法 public Interface Behaviour{ void ...

  4. [Android]ADT Run时候报错:The connection to adb is down, and a severe error has occured

    The connection to adb is down, and a severe error has occured. 之 ..\sdk\platform-tools\adb.exe and c ...

  5. Python heapq 模块的实现 - A Geek's Page

    Python heapq 模块的实现 - A Geek's Page Python heapq 模块的实现

  6. GMM的EM算法

    在聚类算法K-Means, K-Medoids, GMM, Spectral clustering,Ncut一文中我们给出了GMM算法的基本模型与似然函数,在EM算法原理中对EM算法的实现与收敛性证明 ...

  7. TR90眼镜_百度百科

    TR90眼镜_百度百科 TR90眼镜

  8. 分享毕业学生“ERP实施project联赛”总结,是肺腑之言——知识是人的价值的体现,每门课程是有意义的学校纪律

    丁.这是我刚刚完成的实习报告,特别是给你一个.阿信,让你知道的真实想法研究生管,我希望你相信在教育管帮助.---雷管1102 刘弈福 以上是刚刚收到(20140427)生邮件,贻富不是我带的毕业设计学 ...

  9. loj1245(数学)

    传送门:Harmonic Number (II) 题意:求sum=n/1+n/2+n/3+...+n/n.(n<2^31) 分析:在一定的区间内n/i的值是一定的,因此要跳过这段区间来加速求解. ...

  10. HTML转义字符大全(转)

    1.常用转义字符 转义字符串(Escape Sequence)也称字符实体(Character Entity).在HTML中,定义转义字符串的原因有两个:第一个原因是像“<”和“>”这类符 ...