jrtplib介绍[通俗易懂]

jrtplib介绍[通俗易懂]程序流程发送:获得接收端的IP地址和端口号创建RTP会话指定RTP数据接收端设置RTP会话默认参数发送流媒体数据接收:获得用户指定的端口号创建RTP会话设置接收模式接受RTP数据检索RTP数据源获取RTP数据报删除RTP数据报1.初始化I、在使用JRTPLIB进行实时流媒体数据传输之前,首先应该生成R…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

程序流程
发送:获得接收端的 IP 地址和端口号        创建 RTP 会话        指定 RTP 数据接收端 设置 RTP 会话 默认参数   发送流媒体数据
接收:获得用户指定的端口号  创建RTP会话  设置接收模式  接受RTP数据  检索RTP数据源  获取RTP数据报 删除RTP数据报

1.初始化

I、在使用 JRTPLIB 进行实时流媒体数据传输之前,首先应该生成 RTPSession 类的一个实例来表示此次 RTP会话,然后调用 Create() 方法来对其进行初始化操作。RTPSession 类的 Create() 方法只有一个参数,用来指明此次 RTP 会话所采用的端口号。

RTPSession sess;  
sess.Create(5000);

JRTPLIB-3.11中已经修改了Create(prot)方法。新的Create方法被修改为Create(sessparams,&transparams)。其中的两个参数需要如下先定义:

RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;

sessparams.SetOwnTimestampUnit(1.0/8000.0);/*设置时间戳,1/8000表示1秒钟采样8000次,即录音时的8KHz*/

sessparams.SetAcceptOwnPackets(true);

transparams.SetPortbase(portbase);/*本地通讯端口*/

II、设置恰当的时戳单元,是 RTP 会话初始化过程所要进行的另外一项重要工作,这是通过调用 RTPSession类的 SetTimestampUnit() 方法来实现的,前面已经提过。

 

2.数据发送

I、当 RTP 会话成功建立起来之后,接下去就可以开始进行流媒体数据的实时传输了。首先需要设置好数据发送的目标地址,RTP 协议允许同一会话存在多个目标地址,这可以通过调用 RTPSession 类的AddDestination()、DeleteDestination() 和 ClearDestinations() 方法来完成。例如,下面的语句表示的是让 RTP 会话将数据发送到本地主机的 6000 端口:

unsigned long addr = ntohl(inet_addr("127.0.0.1")); 
sess.AddDestination(addr, 6000);

II、目标地址全部指定之后,接着就可以调用 RTPSession 类的 SendPacket() 方法,向所有的目标地址发送流媒体数据。SendPacket() 是 RTPSession 类提供的一个重载函数对于同一个 RTP 会话来讲,负载类型、标识和时戳增量通常来讲都是相同的,JRTPLIB 允许将它们设置为会话的默认参数,这是通过调用 RTPSession 类的 SetDefaultPayloadType()、SetDefaultMark() 和SetDefaultTimeStampIncrement() 方法来完成的。为 RTP 会话设置这些默认参数的好处是可以简化数据的发送,例如,如果为 RTP 会话设置了默认参数:

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

之后在进行数据发送时只需指明要发送的数据及其长度就可以了:

sess.SendPacket(buffer, 5);

在真正的语音传输中,上面的buffer就是我们录音时所得到的buffer。使用上面的函数可以简单的发送,但无法真正的实现RTP传输,我们需要调用另一个接口:sess.SendPacket((void *)buffer,sizeof(buffer),0,false,8000);详细的说明可以查看JRTPLIB的说明文档。

 

3.数据接收

对于流媒体数据的接收端,首先需要调用 RTPSession 类的 PollData() 方法来接收发送过来的 RTP 或者RTCP 数据报。

JRTPLIB-3.11中修改PollData()方法为Poll(),使用都一样

由于同一个 RTP 会话中允许有多个参与者(源),你既可以通过调用 RTPSession 类的

GotoFirstSource() 和 GotoNextSource() 方法来遍历所有的源,也可以通过调用 RTPSession 类的GotoFirstSourceWithData() 和 GotoNextSourceWithData() 方法来遍历那些携带有数据的源。在从 RTP 会话中检测出有效的数据源之后,接下去就可以调用 RTPSession 类的 GetNextPacket() 方法从中抽取 RTP 数据报,当接收到的 RTP 数据报处理完之后,一定要记得及时释放。

JRTPLIB 为 RTP 数据报定义了三种接收模式,其中每种接收模式都具体规定了哪些到达的 RTP 数据报将会被接受,而哪些到达的 RTP 数据报将会被拒绝。通过调用 RTPSession 类的 SetReceiveMode() 方法可以设置下列这些接收模式: 
RECEIVEMODE_ALL  缺省的接收模式,所有到达的 RTP 数据报都将被接受; 
RECEIVEMODE_IGNORESOME  除了某些特定的发送者之外,所有到达的 RTP 数据报都将被接受,而被拒绝的发送者列表可以通过调用 AddToIgnoreList()、DeleteFromIgnoreList() 和 ClearIgnoreList() 方法来进行设置; 
RECEIVEMODE_ACCEPTSOME  除了某些特定的发送者之外,所有到达的 RTP 数据报都将被拒绝,而被接受的发送者列表可以通过调用 AddToAcceptList ()、DeleteFromAcceptList 和 ClearAcceptList () 方法来进行设置。 下面是采用第三种接收模式的程序示例。

if (sess.GotoFirstSourceWithData()) {   
 do {   
          sess.AddToAcceptList(remoteIP, allports,portbase);
           sess.SetReceiveMode(RECEIVEMODE_ACCEPTSOME);

           RTPPacket *pack;         
          pack = sess.GetNextPacket();            // 处理接收到的数据    
           delete pack;   } 
 while (sess.GotoNextSourceWithData()); 
 }

完整的代码中,首先需调用Poll()方法接收RTP数据报,然后在BeginDataAccess()和EndDataAccess()之间进行数据接收的操作。此时,我们设定程序一直do-while等待并处理数据

do{

#ifndef RTP_SUPPORT_THREAD
                error_status = sess_client.Poll();
                checkerror(error_status);
#endif // RTP_SUPPORT_THREAD
                sess_client.BeginDataAccess();

                // check incoming packets
                if (sess_client.GotoFirstSourceWithData())
                {
                         printf("Begin play/n");
                        do
                        {
                                RTPPacket *pack;

                                while ((pack = sess_client.GetNextPacket()) != NULL)
                                {
                                        // You can examine the data here
                                        printf("Got packet !/n");
                                        timestamp1 = pack->GetTimestamp();
                                        lengh=pack->GetPayloadLength();
                                        RawData=pack->GetPayloadData();   //得到数据

printf("  timestamp: %dlengh=%d/n",timestamp1,lengh);


                                            int fd = open("/dev/dsp", O_RDWR);
                                            int status = write(fd, RawData,lengh );
                                            printf("Play bytes:%d/n",status);
                                            if (status != lengh)
                                              perror("wrote wrong number of bytes");

                                            status = ioctl(fd, SOUND_PCM_SYNC, 0);
                                            if (status == -1)
                                            perror("SOUND_PCM_SYNC ioctl failed");
                                            printf("Play end/n");
                                             close(fd);
                                        sess_client.DeletePacket(pack);

                                }
                        } while (sess_client.GotoNextSourceWithData());
                         //return 0;

                }

                sess_client.EndDataAccess();
            }while(1);

说明 : jrtp-3.x 中有两种数据接收方式:

第一种是用 jthread 库提供的线程自动在后台执行对数据的接收。

第二种是用户自己调用 RTPSession 中的 Poll 方法。

如果采取第一种方法则要安装 jthread 库,则安装 jthread-1.x.tar.gz ,而且 jthread-1.x 必须先与 jrtp-3.x 的安装。因为在 jrtp-3.x 的 configure 中,会查找系统是否有编译了 jthread 库,如果有,那么编译的 jrtp 库会开启对 jthread 的支持。因此如果先编译jrtp 在编译 jthread ,编译出来的 jrtp 是没有开启对 jthread 的支持的。如果采用第二种方法,那么可以不用编译 jthread 库,而直接编译 jrtp 库。

 

可以加入环境变量 export LD_LIBRARY_PATH=/XXX/lib,避免将所有lib都放入/usr下

./ example

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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/164744.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 汇编语言王爽第四版实验4答案_王爽汇编语言实验11

    汇编语言王爽第四版实验4答案_王爽汇编语言实验11汇编语言王爽第四版课后检测点课后实验持续更新~~实验4[bx]和loop的使用1编程,向内存0:200~0:23f依次传送数据0~63(3fh)assumecs:codecodesegment movax,0 movds,ax;设置ds=0 movbx,200h;设置从200h开始 movcx,64;循环64次 moval,0;传送的数据 s: mov[bx],al incbx incal loops movax,4c00h

    2025年6月21日
    0
  • python中dtype object_python的dtype有几种

    python中dtype object_python的dtype有几种NumPy中定义的不同标量数据类型。云海天教程网,大量的免费python教程,欢迎在线学习!NumPy数字类型是dtype(数据类型)对象的实例,每个对象具有唯一的特征。这些类型可以是np.bool_,np.float32等。数据类型对象(dtype)数据类型对象描述了对应于数组的固定内存块的解释,取决于以下方面:数据类型(整数、浮点或者Python对象)数据大小字节序(小端或大端)在结…

    2022年6月2日
    74
  • SplitContainer容器控件左右Panel大小调整「建议收藏」

    SplitContainer容器控件左右Panel大小调整「建议收藏」1、新建一个Winform窗体,从上图中选择SplitContainer空间,拖拽到Form到上,如下图:2、你会发现,随便点击Panel1或者Panel2,会显示出粗框,但怎么调整两个Panel的大小呢?两个Panel之间的那条线,是选不中的,哈哈,不信可以试试。那么如何才能调整两个Form的大小呢?==》随便单击一个Panel,再按一下Esc,会出现下图:这时,

    2022年7月18日
    93
  • 极大似然估计和贝叶斯估计的联系(似然估计和最大似然估计)

    1.什么是参数在机器学习中,我们经常使用一个模型来描述生成观察数据的过程。例如,我们可以使用一个随机森林模型来分类客户是否会取消订阅服务(称为流失建模),或者我们可以用线性模型根据公司的广告支出来预测公司的收入(这是一个线性回归的例子)。每个模型都包含自己的一组参数,这些参数最终定义了模型本身。我们可以把线性模型写成y=mx+c的形式。在广告预测收入的例子中,x可以表示广告支…

    2022年4月9日
    93
  • vba中find的用法_vba筛选符合条件的数据到数组

    vba中find的用法_vba筛选符合条件的数据到数组                 

    2022年10月14日
    0
  • Hibernate二级缓存提升性能(注解方式)

    Hibernate二级缓存提升性能(注解方式)合理的缓存应用可以极大地提高系统性能

    2022年5月10日
    31

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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