免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1792 | 回复: 0
打印 上一主题 下一主题

JRTPLIB库的使用 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-31 17:33 |只看该作者 |倒序浏览

                                                                                                                                                                                                                文档:http://research.edm.uhasselt.be/jori/jrtplib/documentation/index.html一些介绍:
http://doserver.net/read.php?1028http://doserver.net/read.php/1027.htmhttp://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 = 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[color="#0000CC"]:
#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:
[color="#0000CC"]//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))
                ":"portstd::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))
                ":"portstd::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))
                ":"portstd::endl;
        }
};[color="#0000FF"]

(三)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)
[color="#0000CC"]V|        P|        RC|        PT=SR=201|        LEN|
SSRC1(第一个接收者报告块所关联的发送者)        (已关联)分组丢失率                |        丢失分组总数|       
RR_GetFractionLost

()|
RR_GetPacketsLost

()扩展的最高序号
RR_GetExtendedHighestSequenceNumber

()间隔抖动
RR_GetJitter

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

()SR最新间隔(DLSR)
RR_GetLastSRTimestamp

()附加信息:这个源是否有发送接收者报告       
RR_HasInfo

()接收者报告接收时间       
RR_GetReceiveTime

()以及以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.
[/url]
bool
[url=http://research.edm.uhasselt.be/jori/jrtplib/documentation/classRTPSources.html#65bd8698115d3b763b5ac38fc3b42f6c]GotoNextSource


()

Sets the current source to be the next source in the table.
[/url]
bool
[url=http://research.edm.uhasselt.be/jori/jrtplib/documentation/classRTPSources.html#69f37b0e4d481a59f635fc1649e28e43]GotoPreviousSource


()

Sets the current source to be the previous source in the
table.
[/url]
bool
[url=http://research.edm.uhasselt.be/jori/jrtplib/documentation/classRTPSources.html#966a98e4afea3abada097c01735e4e67]GotoFirstSourceWithData


()

Sets the current source to be the first source in the table
which has
RTPPacket
instances that we
haven't extracted yet.
[/url]
bool
[url=http://research.edm.uhasselt.be/jori/jrtplib/documentation/classRTPSources.html#46ddc7441d44b7227d5baf3574e1d33d]GotoNextSourceWithData


()

Sets the current source to be the next source in the table
which has
RTPPacket
instances that we
haven't extracted yet.
[/url]
bool
[url=http://research.edm.uhasselt.be/jori/jrtplib/documentation/classRTPSources.html#53dc16afd0189a5b1c67426be7708386]GotoPreviousSourceWithData


()

Sets the current source to be the previous source in the
table which has
RTPPacket
instances
that we haven't extracted yet.
[/url]
[url=http://research.edm.uhasselt.be/jori/jrtplib/documentation/classRTPSourceData.html]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();
以上,我们可以获得访问源的信息的机制。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/93494/showart_1886539.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP