JRTPLIB库的使用
文档:
http://research.edm.uhasselt.be/jori/jrtplib/documentation/index.html
一些介绍:

http://doserver.net/read.php?1028
http://doserver.net/read.php/1027.htm
http://doserver.net/read.php/1685.htm
如今開始对几个example分析一下,只是,就没有文档吗?
这里,具体的解释了几个样例:
http://hi.baidu.com/hanyuejun2006/blog/item/8a8ed939a9e344f53b87ce23.html
这里算一个:
http://xiyong8260.blog.163.com/blog/static/665146212008824112748499/
重要的是里面还讲了一些嵌入式方面的内容。
收和发的样例:
http://blog.chinaunix.net/u2/61880/showart_728528.html
比較具体的系列文章:http://www.cnitblog.com/tinnal/archive/2009/01/01/53342.html
PS:关于POLL的问题,发现仅仅有调用者这个函数的时候,才会查询是否有包发过来,才会接收包。
If you're not using the poll thread, this function must be called regularly to process incoming data and to send RTCP data when necessary.

关于例程能够分为下面几个部分:

(一)BASIC USAGE:
1)SET PARAMS
    关于会话的參数
2)SET TRANSPARAMS
    关于传输层的參数
3)CREATE SESSION
    创建会话
4)SET PACKET ATTRIBUTES
    包的属性设置
5)ADD DESTINATION
    加入目的地址 
6)PREPARE DATA
    准备数据
7)SEND PACKET
    发送包
8)DATAACCESS
    数据处理(锁定操作,是指此时POLL线程不能改变正在处理的数据)
9)BYE
    退出会话
example:
#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtpipv4address.h"
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>

void checkerror(int rtperr)
{
    if(rtperr < 0)
    {
        std::cout<<"ERROR:"<<RTPGetErrorString(rtperr)<<std::endl;
        exit(-1);
    }
}

int main()
{
    RTPSession sess;
    uint16_t portbase;
    int status;

//set params

RTPSessionParams sessparams;
    sessparams.SetOwnTimestampUnit(1.0/10.0);
    sessparams.SetAcceptOwnPackets(true);

//set transparams

RTPUDPv4TransmissionParams transparams;
    transparams.SetPortbase(8000);

//create a session

status = sess.Create(sessparams, &transparams);
    checkerror(status);

//set default packet attributes

sess.SetDefaultPayloadType(0);
    sess.SetDefaultMark(false);
    sess.SetDefaultTimestampIncrement(10);

//destination address

uint16_t destport;
    uint32_t destip;
    std::string ipstr;
    std::cout<<"Enter the IP: "<<std::endl;
    std::cin>>ipstr;
    destip = inet_addr(ipstr.c_str());
    if(destip == INADDR_NONE)
    {
        std::cerr<<"Bad IP"<<std::endl;
        exit(-1);
    }
    destip = ntohl(destip);
    //uint8_t localip[] = {192, 168, 0, 3};

RTPIPv4Address addr(destip, 8000);

//add destination

status = sess.AddDestination(addr);
    checkerror(status);

//prepare payload data

uint8_t silencebuffer[160];
    for(int i = 0; i < 160; i++)
    {
        silencebuffer[i] = 128;
    }

//for time checking

RTPTime delay(0.020);
    RTPTime starttime = RTPTime::CurrentTime();

bool done = false;
    sess.Poll();

while(!done)
    {
        status = sess.SendPacket(silencebuffer, 160);
        checkerror(status);

//receive data

sess.BeginDataAccess();
        if(sess.GotoFirstSource())
        {
            do
            {
                RTPPacket *pack;
                while((pack = sess.GetNextPacket()) != NULL)
                {
                    std::cout<<"Got packet!"<<std::endl;
                    std::cout<<"sequence number: "<<pack->GetSequenceNumber()<<std::endl;
                    std::cout<<"Extended SN: "<<pack->GetExtendedSequenceNumber()<<std::endl;
                    std::cout<<"SSRC: "<<pack->GetSSRC()<<std::endl;
                    std::cout<<"Data: "<<pack->GetPayloadData()<<std::endl;
                    sess.DeletePacket(pack);
                }
            }while(sess.GotoNextSource());
        }
        sess.EndDataAccess();
        
        RTPTime::Wait(delay);
    
        RTPTime t = RTPTime::CurrentTime();
        t -= starttime;
        if(t > RTPTime(6, 0))
        {
            done = true;
        }
    }
    
    delay = RTPTime(10.0);
    sess.BYEDestroy(delay, "Time's up", 9);
    return(0);
}

(二)Your Own Session:
能够继承session创建MySession加入自己定制的处理, 这些处理是由session的protected methods 定义的。參考文档能够确定要定制的处理。

example:

#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtpsourcedata.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

class MyRTPSession : public RTPSession
{
    protected:

//what to do on new source?
        void OnNewSource(RTPSourceData *dat)
        {
            if(dat->IsOwnSSRC())
            {
                return;
            }
            uint32_t ip;
            uint16_t port;
            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;
            }
            else
            {
                return;
            }
            RTPIPv4Address dest(ip, port);
            AddDestination(dest);

struct in_addr inaddr;
            inaddr.s_addr = htonl(ip);
            std::cout<<"Adding destination"<<std::string(inet_ntoa(inaddr))
                <<":"<<port<<std::endl;
        }
//what to do on byepacket?
        void OnBYEPacket(RTPSourceData *dat)
        {
            std::cout<<"OnBYEPacket"<<std::endl;
            if(dat->IsOwnSSRC())
            {
                return;
            }
            uint32_t ip;
            uint16_t port;
            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;
            }
            else
            {
                return;
            }
            RTPIPv4Address dest(ip, port);
            DeleteDestination(dest);
            
            struct in_addr inaddr;
            inaddr.s_addr = htonl(ip);
            std::cout<<"Deleting destination"
                <<std::string(inet_ntoa(inaddr))
                <<":"<<port<<std::endl;
        }
//what to do on remove source?
        void OnRemoveSource(RTPSourceData *dat)
        {
            std::cout<<"OnRemoveSource"<<std::endl;
            if(dat->IsOwnSSRC())
            {
                return;
            }
            if(dat->ReceivedBYE())
            {
                return;
            }
            uint32_t ip;
            uint16_t port;
            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;
            }
            else
            {
                return;
            }
            RTPIPv4Address dest(ip, port);
            DeleteDestination(dest);
            
            struct in_addr inaddr;
            inaddr.s_addr = htonl(ip);
            std::cout<<"Deleting destination"
                <<std::string(inet_ntoa(inaddr))
                <<":"<<port<<std::endl;
        }
};

(三)Important Classes:
分析參数:RTPSourceData-HOW TO KNOW RTCP?
从(二)中,你可能已经了解到了On...等定义了session在收发包时的动作,而为了分析这些包的參数,你须要的是RTPSourceData这个參数。Source指的是一个会话的參与者,在本地保存了一个參与者列表,和与之相关的信息。这些信息是从该源发送的RTCP信息提取的。
为了便于和理论分析比較,如今将5中RTCP分组报告和它们的实现列出:
指的注意的是:据我眼下的理解是,本地维护一个源的列表,而这些RTCP分组,并没有它们的实体,而是得到这些分组后就分析为和一个源描写叙述符,即RTPSource关联的数据。应该是遍历这个源列表,而获得它们的信息。而怎样遍历的问题,稍后讨论。

发送者报告(SR)

V| P| RC| PT=SR=200| LEN|


发送者SSRC (已关联)


NTP时间戳(高32位) SR_GetNTPTimestamp ()

NTP时间戳(低32位)


RTP时间戳 SR_GetRTPTimestamp ()


发送者分组计数器 SR_GetPacketCount()


发送者字节计数器 SR_GetByteCount ()


...(以下是这个发送者所发送的接收者报告,在以下和RR一起讨论)


附加信息:

这个源是否有发送发送者报告

SR_HasInfo ()

这个发送者报告接收的时间

SR_GetReceiveTime ()

以及以SR_Prev_开头的,获得倒数第二个发送者报告的信息。

接收者报告(RR)

V| P| RC| PT=SR=201| LEN|


SSRC1(第一个接收者报告块所关联的发送者) (已关联)

分组丢失率 | 丢失分组总数|

扩展的最高序号

间隔抖动

最新的发送者报告时间戳(LSR)

SR最新间隔(DLSR)

附加信息:
这个源是否有发送接收者报告
接收者报告接收时间
以及以RR_Prev_开头的,获得倒数第二个接收者报告的信息。

源描叙分组(SDES)

V| P| RC| PT=SR=202| LEN|


SSRC/CSRC1 (已关联)


SDES项

由SDES_Get...等描写叙述

能够推断的是存在一种机制,能够在本地定制自己要发送的SDES包括的信息。

BYE分组(BYE)

V| P| RC| PT=SR=202| LEN|


SSRC/CSRC (已关联)


原因长度| 退出会话原因
GetBYEReason (size_t *len)


附加信息(见文档)
依据以上的信息,大概知道了怎样获取一个源的信息;问题是怎样遍历这个源列表来处理一个源?
其实,在大多数的样例里,使用的类仅仅是RTPSession,通过这个类能够管理会话的大部分细节。
管理会话:RTPSession-MANAGE A SESSION
对一次会话的管理,大概有下面几方面:
*创建会话
*退出会话
*管理目的地址(加入,忽略)
*发送和接收数据包(用户仅仅须要关心RTP包),另外,APP包也是由用户负责的
*时间戳设定
*管理SDES信息项
*管理源列表
*管理广播组
...
一般来说,使用一个类都是使用它的public接口,可是你能够像(二)描写叙述的那样,通过继承来定制自己的一些行为。On...
着重讲的是管理源列表。
bool  GotoFirstSource ()
  Starts the iteration over the participants by going to the first member in the table.
bool  GotoNextSource ()
  Sets the current source to be the next source in the table.
bool  GotoPreviousSource ()
  Sets the current source to be the previous source in the table.
bool  GotoFirstSourceWithData ()
  Sets the current source to be the first source in the table which has RTPPacket instances that we haven't extracted yet.
bool  GotoNextSourceWithData ()
  Sets the current source to be the next source in the table which has RTPPacket instances that we haven't extracted yet.
bool  GotoPreviousSourceWithData ()
  Sets the current source to be the previous source in the table which has RTPPacket instances that we haven't extracted yet.
RTPSourceData GetCurrentSourceInfo ()
  Returns the RTPSourceData instance for the currently selected participant.
RTPSourceData GetSourceInfo (uint32_t ssrc)
  Returns the RTPSourceData instance for the participant identified by ssrc, or NULL if no such entry exists. 
bool  GotEntry (uint32_t ssrc)
  Returns true if an entry for participant ssrc exists and false otherwise.
RTPSourceData GetOwnSourceInfo ()
  If present, it returns the RTPSourceData instance of the entry which was created by CreateOwnSSRC. 

迭代的例程:

非常明显,这是C++风格,使用了迭代器的抽象。而GetCurrentSourceInfo ()和GetSourceInfo (uint32_t ssrc)的返回类型-RTPSourceData能够使我们得以获取源列表的RTCP信息。
使用这样的迭代的例程:
 sess.BeginDataAccess();
        if(sess.GotoFirstSource())
        {
            do
            {
                RTPPacket *pack;
                while((pack = sess.GetNextPacket()) != NULL)
                {
            //deal with the packet
                    sess.DeletePacket(pack);
                }
            }while(sess.GotoNextSource());
        }
sess.EndDataAccess();
以上,我们能够获得訪问源的信息的机制。

jrtplib的使用的更多相关文章

  1. jrtplib跨网络通讯NAT穿透问题解决方法

    前几篇文章讲了使用jrtplib在Android和pc端进行通讯的方法 在实际项目中,手机端和pc端一般不会在同一个子网内,两者之间联络可能要走路由器之类的NAT(网络地址转换 Network Add ...

  2. 流媒體】jrtplib—VS2010下RTP开源协议库JRTPLIB3.9.1编译

    一.JRTPLIB简介 老外用C++编写的开源RTP协议库,用来进行实时数据传输,可以运行在 Windows.Linux. FreeBSD.Solaris.Unix和VxWorks 等多种操作系统上, ...

  3. 关于开源的RTP——jrtplib的使用

    session.BeginDataAccess(); if (session.GotoFirstSource()){ do{ RTPPacket *packet; while ((packet = s ...

  4. jrtplib使用注意事项

    一.说明 RTP 现在的问题是要解决的流媒体的实时传输的问题的最佳方法.和JRTPLIB 是一个用C++语言实现的RTP库.包含UDP通讯.刚使用JRTPLIB,对JRTPLIB的理解还不够深,当做使 ...

  5. 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(一)概览

    myRTSPClient主要可以分成3个部分: 1. RTSPClient用户接口层: 2. RTP 音视频传输解析层: 3. RTP传输层. "RTSPClient用户接口层": ...

  6. 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——收流篇:(一)简介

    关于实时流媒体传输的开源库,目前流行的主要有两个:live555和jrtplib. 其中live555将rtp.rtcp和rtsp的传输协议实现集于一身,功能齐全,是个超强的集合体.但是对于嵌入式系统 ...

  7. 测试库的接收到的数据是否完整(jrtplib为列)

    最近使用jrtplib来接收RTP包,然后解码播放 发现解码出来的是绿屏,马赛克 于是开始排查 首先直接用wireshark抓进来的包,转为可以被vlc播放的文件 操作如下 http://blog.c ...

  8. 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(十)使用JRTPLIB传输RTP数据

    myRtspClient通过简单修改JRTPLIB的官方例程作为其RTP传输层实现.因为JRTPLIB使用的是CMAKE编译工具,这就是为什么编译myRtspClient时需要预装CMAKE. 该部分 ...

  9. hi3516a arm-hisiv300-linux-gcc jrtplib交叉编译

    1.进入JThread-1.2.1文件夹 2../configure --prefix=/home/suxuandong/Documents/qth264/hi3516/jrtpjthreadhisi ...

随机推荐

  1. 第十二章——SQLServer统计信息(2)——非索引键上统计信息的影响

    原文:第十二章--SQLServer统计信息(2)--非索引键上统计信息的影响 前言: 索引对性能方面总是扮演着一个重要的角色,实际上,查询优化器首先检查谓词上的统计信息,然后才决定用什么索引.一般情 ...

  2. java得到clientIP地址和MAC住址

    最近的项目应该得到client的mac住址. 服务器移植centos制,arm建筑箱.client手机和移动设备.(其他方案也应该是一流的似的) 首先,要获得ip住址: 依据client的http请求 ...

  3. Unity3d C# Socket 下载文件 (同步到)

    续篇 Unity3d C# HttpWebRequest 异步下载文件 ,由于project编译为IL2CPP的情况下仍然无效.提示HttpWebrequest 在当前版本号不支持.所以还是寻求其他的 ...

  4. POJ 2208 已知边四面体六个长度,计算体积

    Pyramids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2718   Accepted: 886   Special ...

  5. 使用Heroku,需要locale至zh_CN,代替zh-CN

    使用Heroku.需要locale至zh_CN,代替zh-CN 我认为这是由于在application.rb于,config.i18n.default_locale默认接受值这是Symbol, 而当我 ...

  6. SQL Server 内存泄露(memory leak)——游标导致的内存问题

    原文:SQL Server 内存泄露(memory leak)--游标导致的内存问题 转自:http://blogs.msdn.com/b/apgcdsd/archive/2011/07/01/sql ...

  7. IOS总结_IOS经常使用的方法集合、调用系统电话、设备区分、APP内永不锁屏

    调用系统打电话的功能 打电话功能仅仅有iPhone支持,对于其它设备相应button应该禁用. //直接调用系统电话呼叫功能,挂断电话后不能回到应用程序 [UIApplication sharedAp ...

  8. 提高duilib的richedit控制的一些特征

    转载请注明原始出处.谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41208207 假设要使用透明异形窗口功能,首先要改进duilib库让他 ...

  9. 实现键值对存储(三):Kyoto Cabinet 和LevelDB的架构比較分析

    译自  Emmanuel Goossaert (CodeCapsule.com) 在本文中,我将会逐组件地把Kyoto Cabinet 和 LevelDB的架构过一遍.目标和本系列第二部分讲的差点儿相 ...

  10. angularjs从零开始(一)

    简介   AngularJS是为了克服HTML在构建应用上的不足而设计的.HTML是一门很好的为静态文本展示设计的声明式语言,但要构建WEB应用的话它就显得乏力了.所以我做了一些工作(你也可以觉得是小 ...