转自:http://blog.csdn.net/suer0101/article/details/7333267

再补充一个代码走读:http://www.xuebuyuan.com/1863409.html

我们知道, RTP(Real-timeTransportProtocol)是用于Internet上针对多媒体数据流的一种传输协议,做流媒体传输方面的应用离不开RTP协议的实现及使用,为了更加快速地在项目中应用RTP协议实现流媒体的传输,我们一般会选择使用一些RTP库,例如使用c++语言编写的JRTPLIB库,网上关于RTP协议以及JRTPLIB库的介绍已经很多了,在此我也不再赘述,文本主要介绍实现了RTP协议的另一种开源库——ORTP库,这个库是纯使用c语言编写,由于我们的项目是基于Linux下的c语言编程,故我们选择了ortp作为我们的第三方库,在此我也对该库进行一个简单地介绍,希望对其他ortp的初学者有所帮助。

一、简介
ORTP是一个支持RTP以及RFC3550协议的库,有如下的特性:
(1)使用C语言编写,可以工作于windows, Linux, 以及 Unix平台
(2)实现了RFC3550协议,提供简单易用的API。支持多种配置,RFC3551为默认的配置。
(3)支持单线程下的多个RTP会话,支持自适应抖动处理。
(4)基于GPL版权声明。
ORTP可以在其官方网站上(http://www.linphone.org/index.php/eng/code_review/ortp)下载,下载解压后得到ORTP的源码包和示例程序(tests)。其帮助文档在docs目录下,也可以在http://download.savannah.gnu.org/releases/linphone/ortp/docs/在线查看。

关于ORTP的资料并不多,主要是其源码、帮助文档以及示例程序,关于示例程序说明如下:
rtprecv.c 和rtpsend.c 展示了如何接收和发送单RTP数据流。
mrtprecv.c mrtpsend.c 展示了如何同时接收和发送多个RTP数据流。

二、主要函数介绍
 rtp_session_init
函数原型:void rtp_session_init (RtpSession * session, int mode)
函数功能:执行rtp会话的一些必要的初始化工作
参数含义:
session: rtp会话结构体,含有一些rtp会话的基本信息
mode:   传输模式,有以下几种,决定本会话的一些特性。
RTP_SESSION_RECVONLY:只进行rtp数据的接收
RTP_SESSION_SENDONLY:只进行rtp数据的发送
RTP_SESSION_SENDRECV:可以进行rtp数据的接收和发送
 
执行的操作:
1.       设置rtp包缓冲队列的最大长度
2.       根据传输模式设置标志变量的值
3.       随机产生SSRC和同步源描述信息
4.       传入全局的av_profile,即使用默认的profile配置
5.       初始化rtp包缓冲区队列
6.       发送负载类型默认设置为0(pcmu音频),接收负载类型默认设置为-1(未定义)
7.       将session的其他成员的值均设置一个默认值。
 
rtp_session_set_scheduling_mode
函数原型:void rtp_session_set_scheduling_mode (RtpSession * session, int yesno)
函数功能: RtpScheduler管理多个session的调度和收发的控制,本函数设置是否使用该session调度管理功能。
参数含义:
session: rtp会话结构体
yesno:   是否使用rtp session的系统调度功能
说明:
如果yesno为1,则表明使用系统的session调度管理功能,意味着可以使用以下功能:
1. 可以使用session_set_select在多个rtp会话之间进行选择,根据时间戳判定某个会话是否到达了收发的时间。
2. 可以使用rtp_session_set_blocking_mode()设置是否使用阻塞模式来进行rtp包的发送和接收。
如果yesno为0,则表明该会话不受系统管理和调度。
关于rtp session的管理和调度,由全局的变量RtpScheduler *__ortp_scheduler来负责,该变量必须通过ortp_scheduler_init() 来进行初始化操作。
 
rtp_session_set_blocking_mode
函数原型:void rtp_session_set_blocking_mode (RtpSession * session, int yesno)
函数功能:设置是否使用阻塞模式,
参数含义:
session: rtp会话结构体
yesno:  是否使用阻塞模式
说明:
阻塞模式只有在scheduling mode被开启的情况下才能使用,本函数决定了rtp_session_recv_with_ts() 和 rtp_session_send_with_ts()两个函数的行为,如果启用了阻塞模式,则rtp_session_recv_with_ts()会一直阻塞直到接收RTP包的时间点到达(这个时间点由该函数参数中所定义的时间戳来决定),当接收完RTP数据包后,该函数才会返回。同样,rtp_session_send_with_ts()也会一直阻塞直到需要被发送的RTP包的时间点到达,发送结束后,函数才返回。
 
rtp_session_signal_connect
函数原型:int rtp_session_signal_connect (RtpSession * session, const char *signal,   RtpCallback cb, unsigned long user_data)
函数功能:本函数提供一种方式,用于通知应用程序各种可能发生的RTP事件(信号)。可能通过注册回调函数的形式来实现本功能。
参数含义:
session: rtp会话结构体
signal: 信号的名称
cb:     回调函数
user_data:传递给回调函数的数据
返回值:0表示成功,-EOPNOTSUPP表示信号名称不存在,-1表示回调函数绑定错误
说明:
信号的名称必须是以下字符串中的一种:
"ssrc_changed" : 数据流的同步源标识改变
"payload_type_changed" : 数据流的负载类型改变
"telephone-event_packet" : telephone-event RTP包(RFC2833)被接收
"telephone-event" : telephone event 发生
"network_error" : 网络错误产生,传递给回调函数的是描述错误的字符串(const char *型)或者错误码(int型)
"timestamp_jump" : 接收到的数据包发生了时间戳的跳跃。
要取消事件(信号)的监听,可以使用下面这个函数
int rtp_session_signal_disconnect_by_callback ( RtpSession * session, const char * signal_name, RtpCallback cb )
 
rtp_session_set_local_addr
函数原型:int rtp_session_set_local_addr( RtpSession * session, const char * addr,int port)
函数功能:设置本地rtp数据监听地址
参数含义:
session: rtp会话结构体
addr: 本地IP地址,例如127.0.0.1,如果为NULL,则系统分配0.0.0.0
port:   监听端口,如果设置为-1,则系统为其自动分配端口
返回值: 0表示成功
说明:
如果是RTP_SESSION_SENDONLY(只发送)型会话,则不需要进行本设置,而必须设置rtp_session_set_remote_addr() 来设置远程目的地址。
如果采用了系统自动分配监听端口,则可以通过int rtp_session_get_local_port(const RtpSession *session) 来获取系统分配的监听端口号。
 
rtp_session_set_remote_addr
函数原型:int rtp_session_set_remote_addr (RtpSession * session, const char * addr, int port)
函数功能:设置RTP发送的目的地址
参数含义:
session: rtp会话结构体
addr: 目的IP地址
port:   目的地址的监听端口号
返回值: 0表示成功
 
rtp_session_set_send_payload_type
函数原型:int rtp_session_set_send_payload_type (RtpSession * session, int paytype)
函数功能:设置RTP发送数据的负载类型
参数含义:
session: rtp会话结构体
paytype:负载类型
返回值: 0表示成功,-1表示负载未定义
说明:
负载类型在payloadtype.h文件中有详细的定义,RTP接收端有着类似的负载类型设置函数,int rtp_session_set_recv_payload_type ( RtpSession * session, int paytype ) ,注意,发送的负载类型必须与接收的负载类型一致才能正常完成收发。
 
rtp_session_send_with_ts
函数原型:int rtp_session_send_with_ts (RtpSession * session, const char * buffer, int len,uint32_t userts)
函数功能:发送RTP数据包
参数含义:
session: rtp会话结构体
buffer: 需要发送的RTP数据的缓冲区
len:    需要发送的RTP数据的长度
userts: 本RTP数据包的时间戳
返回值: 成功发送到网络中的字节数
说明:
发送RTP数据需要自己管理时间戳的递增,每调用一次本函数,请根据实际情况对userts进行递增,具体递增的规则见RTP协议中的说明。
例如:如果发送的是采样率为90000Hz的视频数据包,每秒25帧,则时间戳的增量为:90000/25 = 3600
时间戳的起始值为随机值,建议设置为0 。
 
rtp_session_recv_with_ts
函数原型:int rtp_session_recv_with_ts (RtpSession * session, char * buffer,int len, uint32_t time, int * have_more)
函数功能:接收RTP数据包
参数含义:
session: rtp会话结构体
buffer: 存放接收的RTP数据的缓冲区
len:    期望接收的RTP数据的长度
time:   期望接收的RTP数据的时间戳
have_more:标识接收缓冲区是否还有数据没有传递完。当用户给出的缓冲区不够大时,为了标识缓冲区数据未取完,则have_more指向的数据为1,期望用户以同样的时间戳再次调用本函数;否则为0,标识取完。
rtp_session_destroy
【原型】: void rtp_session_destroy(RtpSession *session)
【功能】:摧毁rtp会话对象,释放资源
【参数】:session已经创建的RTP会话对象
 
三、程序示例
      下面,我简单地通过程序演示了怎么使用ortp进行rtp数据包的发送,接收端的程序待以后有时间再整理出来吧。

    1. //////////////////////////////////////////////////////////////////////////
    2. 1   /// COPYRIGHT NOTICE
    3. 2    // Copyright (c) 2009, 华中科技大学ticktick Group
    4. 3   /// All rights reserved.
    5. 4   ///
    6. 5   /// @file    ortpSend.c
    7. 6   /// @brief   ortpSend的测试
    8. 7   ///
    9. 8   /// 本文件示例使用ortp库进行rtp数据包的发送
    10. 9   ///
    11. 10  /// @version 1.0
    12. 11  /// @author  tickTick
    13. 12  /// @date    2010/07/07
    14. 13  /// @E-mail  lujun.hust@gmail.com
    15. 14  ///
    16. 15  /// 修订说明:创建文件
    17. 16  //////////////////////////////////////////////////////////////////////////
    18. 17
    19. 18  #include <ortp/ortp.h>
    20. 19  #include <signal.h>
    21. 20  #include <stdlib.h>
    22. 21
    23. 22  #ifndef _WIN32
    24. 23  #include <sys/types.h>
    25. 24  #include <sys/time.h>
    26. 25  #include <stdio.h>
    27. 26  #endif
    28. 27
    29. 28  // 时间戳增量
    30. 29  #define TIME_STAMP_INC  160
    31. 30  #define BYTES_PER_COUNT 65535
    32. 31  // 时间戳
    33. 32  uint32_t g_user_ts;
    34. 33
    35. 34  /**  初始化
    36. 35   *
    37. 36   *   主要用于对ortp以及其它参数进行初始化
    38. 37   *   @param:  char * ipStr 目的端IP地址描述串
    39. 38   *   @param:  iint port 目的端RTP监听端口
    40. 39   *   @return:  RtpSession * 返回指40   向RtpSession对象的指41   针,如果为NULL,42    则初始化失败
    41. 43   *   @note:
    42. 44   */
    43. 45  RtpSession * rtpInit(char * ipStr,int port)
    44. 46  {
    45. 47      // Rtp会话对象
    46. 48      RtpSession *session;
    47. 49      char *ssrc;
    48. 50
    49. 51      // 时间戳初始化
    50. 52      g_user_ts = 0;
    51. 53
    52. 54      // ortp的一些基本初始化操作
    53. 55      ortp_init();
    54. 56      ortp_scheduler_init();
    55. 57      // 创建新的rtp会话对象
    56. 58      session=rtp_session_new(RTP_SESSION_SENDONLY);
    57. 59
    58. 60      rtp_session_set_scheduling_mode(session,1);
    59. 61      rtp_session_set_blocking_mode(session,1);
    60. 62      // 设置远程RTP客户端的的IP和监听端口(即本rtp数据包的发送目的地址)
    61. 63      rtp_session_set_remote_addr(session,ipStr,port);
    62. 64      // 设置负载类型
    63. 65      rtp_session_set_payload_type(session,0);
    64. 66
    65. 67      // 获取同68    步源标69   识
    66. 70      ssrc=getenv("SSRC");
    67. 71      if (ssrc!=NULL)
    68. 72      {
    69. 73          printf("using SSRC=%i.\n",atoi(ssrc));
    70. 74          rtp_session_set_ssrc(session,atoi(ssrc));
    71. 75      }
    72. 76
    73. 77      return session;
    74. 78
    75. 79  }
    76. 80
    77. 81  /**  发送rtp数据包
    78. 82   *
    79. 83   *   主要用于发送rtp数据包
    80. 84   *   @param:  RtpSession *session RTP会话对象的指85   针
    81. 86   *   @param:  const char *buffer 要发送的数据的缓冲区地址
    82. 87   *   @param: int len 要发送的数据长度
    83. 88   *   @return:  int 实际发送的数据包数目
    84. 89   *   @note:     如果要发送的数据包长度大于BYTES_PER_COUNT,90 本函数内部会进行分包处理
    85. 91   */
    86. 92  int rtpSend(RtpSession *session,const char *buffer, int len)
    87. 93  {
    88. 94      int curOffset = 0;
    89. 95      int sendBytes = 0;
    90. 96      int clockslide=500;
    91. 97      // 发送包的个数
    92. 98      int sendCount = 0;
    93. 99
    94. 100     ortp_message("send data len %i\n ",len);
    95. 101
    96. 102     // 是否全部发送完毕
    97. 103     while(curOffset < len )
    98. 104     {
    99. 105     // 如果需要发送的数据长度小于等于阙值,106    则直接发送
    100. 107         if( len <= BYTES_PER_COUNT )
    101. 108         {
    102. 109             sendBytes = len;
    103. 110         }
    104. 111         else
    105. 112         {
    106. 113             // 如果当前偏移 + 阈值 小于等于 总长度,114 则发送阈值大小的数据
    107. 115             if( curOffset + BYTES_PER_COUNT <= len )
    108. 116             {
    109. 117                 sendBytes = BYTES_PER_COUNT;
    110. 118             }
    111. 119             // 否则就发送剩余长度的数据
    112. 120             else
    113. 121             {
    114. 122                 sendBytes = len - curOffset;
    115. 123             }
    116. 124         }
    117. 125
    118. 126         ortp_message("send data bytes %i\n ",sendBytes);
    119. 127
    120. 128         rtp_session_send_with_ts(session,(char *)(buffer+curOffset),sendBytes,g_user_ts);
    121. 129
    122. 130         // 累加
    123. 131         sendCount ++;
    124. 132         curOffset += sendBytes;
    125. 133         g_user_ts += TIME_STAMP_INC;
    126. 134
    127. 135         // 发送一定数据包后休眠一会
    128. 136         if (sendCount%10==0)
    129. 137         {
    130. 138             usleep(20000);
    131. 139         }
    132. 140     }
    133. 141     return 0;
    134. 142 }
    135. 143
    136. 144 /**  结束ortp的发送,145  释放资源
    137. 146  *
    138. 147  *   @param:  RtpSession *session RTP会话对象的指148  针
    139. 149  *   @return:  0表示成功
    140. 150  *   @note:
    141. 151  */
    142. 152 int rtpExit(RtpSession *session)
    143. 153 {
    144. 154     g_user_ts = 0;
    145. 155
    146. 156     rtp_session_destroy(session);
    147. 157     ortp_exit();
    148. 158     ortp_global_stats_display();
    149. 159
    150. 160     return 0;
    151. 161 }
    152. 162
    153. 163 // 主函数,164  进行测试
    154. 165 int main()
    155. 166 {
    156. 167     // 待发送的数据缓冲区
    157. 168     char * pBuffer = "123445356234134234532523654323413453425236244123425234";
    158. 169
    159. 170     RtpSession * pRtpSession = NULL;
    160. 171     // 向(192.201.0.51,172   8000)目的地址发送rtp包
    161. 173     pRtpSession = rtpInit("192.201.0.51",8000);
    162. 174     if(pRtpSession==NULL)
    163. 175     {
    164. 176         printf("error rtpInit");
    165. 177         return 0;
    166. 178     }
    167. 179
    168. 180     // 循环发送
    169. 181     while(1)
    170. 182     {
    171. 183         if( rtpSend(pRtpSession,pBuffer,20) != 0)
    172. 184         {
    173. 185             printf("error rtpInit");
    174. 186             break;
    175. 187         }
    176. 188         usleep(10000);
    177. 189         printf("sleep");
    178. 190     }
    179. 191
    180. 192     // 退出
    181. 193     rtpExit(pRtpSession);
    182. 194
    183. 195     return 0;
    184. 196 }

ortp库入门的更多相关文章

  1. ortp库使用入门

    我们知道, RTP(Real-timeTransportProtocol)是用于Internet上针对多媒体数据流的一种传输协议,做流媒体传输方面的应用离不开RTP协议的实现及使用,为了更加快速地在项 ...

  2. 数据分析与展示——NumPy库入门

    这是我学习北京理工大学嵩天老师的<Python数据分析与展示>课程的笔记.嵩老师的课程重点突出.层次分明,在这里特别感谢嵩老师的精彩讲解. NumPy库入门 数据的维度 维度是一组数据的组 ...

  3. 数据分析与展示——Matplotlib库入门

    Matplotlib库入门 Matplotlib库介绍 Matliotlib库是Python优秀的数据可视化第三方库. Matliotlib库的效果见:http://matplotlib.org/ga ...

  4. ORTP库移植

    转载,侵删 1.ORTP的引入 为什么要使用RTP:http://blog.51cto.com/ticktick/462746RTP协议分析:http://www.xuebuyuan.com/7399 ...

  5. Python数据分析与展示(1)-数据分析之表示(1)-NumPy库入门

    Numpy库入门 从一个数据到一组数据 维度:一组数据的组织形式 一维数据:由对等关系的有序或无序数据构成,采用线性方式组织. 可用类型:对应列表.数组和集合 不同点: 列表:数据类型可以不同 数组: ...

  6. Requests库主要方法解析以及Requests库入门需要掌握的框架

    Requests库主要方法解析以及Requests库入门 1.requests.request(method,url,**kwargs) **kwargs:控制访问的参数,均为可选项 params:字 ...

  7. requests库入门-16-Session和Cookie

    分类专栏: Python接口自动化测试之requests库入门 作者 | Anthony_tester ,300w+访问量博主,Oracle测试开发工程师. 地址 | https://blog.csd ...

  8. ORTP库API使用入门

    一.简介 ORTP是一个支持RTP以及RFC3550协议的库,有如下的特性: (1)使用C语言编写,可以工作于windows, Linux, 以及 Unix平台 (2)实现了RFC3550协议,提供简 ...

  9. Facebook React.js库 入门实例教程

    作者: 阮一峰 日期: 2015年3月31日 现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩 ...

随机推荐

  1. document.documentElement.scrollTop || document.body.scrollTop

    如果有doctype的声明,需要用document.documentElement.scrollTop没有doctype的声明,用document.body.scrollTop

  2. selenium 配合sikuli script操作高德地图

    会不会使用工具,是一般QA和高级QA的区别 ---To be crazy Java就是好,开源框架遍地都是,各种niubility的jar包,各种神器,真是不亦乐乎. 今天研究一下基于图片识别作为对象 ...

  3. 内存管理_JAVA内存管理

    Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽各个硬件平台和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果.那 ...

  4. WebRequest 获取网页乱码

    问题:在用WebRequest获取网页源码时得到的源码是乱码. 原因:1,编码不对 解决办法:设置对应编码 WebRequest request = WebRequest.Create(Url);We ...

  5. Greedy:Sum of Consecutive Prime Numbers(POJ 2739)

     素数之和 题目大意:一些整数可以表示成一个连续素数之和,给定一个整数要你找出可以表示这一个整数的连续整数序列的个数 方法:打表,然后用游标卡尺法即可 #include <iostream> ...

  6. zookeeper windows 入门安装和测试

    一.序言       以下是我对zookeeper 的一些理解:       zookeeper 作为一个服务注册信息存储的管理工具,好吧,这样说得很抽象,我们举个“栗子”. 栗子1号: 假设我是一家 ...

  7. 【python】词法语法解析模块ply

    官方手册:http://www.dabeaz.com/ply/ply.html 以下例子都来自官方手册: 以四则运算为例: x = 3 + 42 * (s - t) 词法分析: 需要将其分解为: 'x ...

  8. Qt 添加启动项

    QString application_name = QApplication::applicationName(); QSettings *settings = new QSettings(&quo ...

  9. September 18th 2016 Week 39th Sunday

    Be the king of the spiritual kingdom that is your heart. 在心灵的国土上,做自己的国王. Most often we are not able ...

  10. Linux mpstat字段解析

    mpstat是Multiprocessor Statistics的缩写,是实时系统监控工具.其报告与CPU的一些统计信息,这些信息存放在/proc/stat文件中.在多CPUs系统里,其不但能查看所有 ...