zoukankan      html  css  js  c++  java
  • H.264视频流的传输与载荷——将H264码流打包成RTP包

    http://blog.csdn.net/bytxl/article/details/50393198

    从摄像头获取的视频数据,经过编码后(当然,也可以不编码,如果你觉得也很ok的话),可以视频录制,同时如果需要,当然也可以视频远程传输咯,而实时传输协议(Real-time Transport Protocol,RTP)是在Internet上处理多媒体数据流的一种网络协议,利用它能够在一对一(unicast,单播)或者一对多(multicast,多播)的网络环境中实现传流媒体数据的实时传输(不需要下载完毕后才能看视频)。RTP通常使用UDP来进行多媒体数据的传输,但如果需要的话可以使用TCP等其它协议,整个RTP协议由两个密切相关的部分组成:RTP数据协议和RTCP控制协议。

       RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,每一个RTP数据报都由头部(Header)和负载(Payload)两个部分组成,其中头部前12个字节的含义是固定的,而负载则可以是音频或者视频数据。

       RTCP 控制协议需要与RTP数据协议一起配合使用,当应用程序启动一个RTP会话时将同时占用两个端口,分别供RTP和RTCP使用RTP本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制,这些都由RTCP来负责完成。通常RTCP会采用与RTP相同的分发机制,向会话中的所有成员周期性地发送控制信息,应用程序通过接收这些数据,从中获取会话参与者的相关资料,以及网络状况、分组丢失概率等反馈信息,从而能 够对服务质量进行控制或者对网络状况进行诊断。

       实时流协议(RealTime Streaming Protocol,RTSP),它的意义在于使得实时流媒体数据的受控和点播变得可能。总的说来,RTSP是一个流媒体表示协议,  主要用来控制具有实时特性的数据发送,但它本身并不传输数据,而是必须依赖于下层传输协议所提供的某些服务。RTSP 可以对流媒体提供诸如播放、暂停、快进等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与RTP间的交互操作。

    一、JRTPLIB库的安装

    Linux:

    rtp的运行当然少不了JRTPLIB库的支持,JRTPLIB是一个面向对象的RTP封装库,安装过程如下:

        1)下载开发包解压。这里用的是jrtplib-3.7.1,下载地址:http://download.csdn.net/detail/huangminqiang201209/4925142 。

        2)  解压后出现两个目录,一个是jrtplib-3.7.1,一个是jthread-1.2.1。JRTPLib是一个开源的RTP库。JThread是一个开源的线程类。

        3)进入jthead解压目录,运行./configure配置环境. 配置完毕后运行make,  接着安装make install。

        4)jrtplib安装同上。装好以后系统环境如下,静态动态库安装到了/usr/local/lib目录下,包括libjrtplib-3.7.1.so和libjthread-1.2.1.so等。头文件在/usr/local/include目录jrtplib*目录下。

        5)linux默认会在路径为/lib和/usr/lib下的库文件收缩,而上面的库文件在/usr/local/lib下,可以在/lib或者在/usr/lib下创建该库的快捷方式: ln -s /usr/local/lib/libjrtp-3.7.1.so /usr/lib/libjrtp-3.7.1.so
        6)在jrtplib源代码目录里有例子程序,make文件都是写好的,试验一下编译example1.cpp,使用静态库libjrtp.a链接,编译语句如下:g++ -o example1 example1.cpp -I /usr/local/include/jrtplib3/ -ljrtp

        7)最后执行命令:ldconfig,更新库的信息,这样执行文件./example1,就可以了

    Windows: 

        1)解压 jrtplib-3.7.1和 jthread-1.2.1

        2)用 VC打开工程文件jthread.dsw

        3)编译 jrtplib.lib和jthread.lib需要注意VC6要求安装Vs6sp6,在编译jrtplib.lib和jthread.lib前,在  project——settings——C/C++——Codegeneration:use run-time library中,对于 debug,选择:DebugMultithreaded DLL,对于release,则选择:Multithreaded DLL。

        4)首先编译 jthread 库,然后将 jthread-1.2.1src内的"jmutex.h"和"jthread.h"两个头文件放入jrtplib-3.7.1src目录下,然后将 jrtplib-3.7.1src 文件夹下所有头文件中的和语句修改为"jmutex.h"和"jthread.h",需要修改的文件为 rtpudpv4transmitter.h、rtpsession.h和 rtppollthread.h。编译时注意编译方式和 jthread.lib一致。

        5)编译生成的 jthread.lib 和 jrtplib.lib 拷贝到系统目录:C:Program  FilesMicrosoft Visual StudioVC98Lib 下,将 jrtplib-3.7.1src下所有的.h 头文件复制到 C:Program FilesMicrosoftVisual StudioVC98Include,以便以后使用。

        6)现在我们就可以编译 jrtplib-3.7.1examples 下的实例程序了。建立 VC 工程,打开example1.c,在 Project  Settings 的 link 页添加 jthread.lib  jrtplib.lib ws2_32.lib,在project——settings——C/C++——Code  generation:use  run-time library 中,对于 debug,选择:DebugMultithreaded DLL,对于 release,则选择:Multithreaded DLL。

        7)编译源程序,运行就OK 啦

    二、H.264 RTP PAYLOAD 载荷

      在传输前,先要了解H.264 RTP PAYLOAD 格式(负载格式):

    1. 网络抽象层单元类型 (NALU)

    NALU 头由一个字节组成, 它的语法如下:

          +---------------+
          |0|1|2|3|4|5|6|7|
          +-+-+-+-+-+-+-+-+
          |F|NRI|  Type   |
          +---------------+

    F: 1 个比特.
      forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.

    NRI: 2 个比特.
      nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性, 如 00 的 NALU 解码器可以丢弃它而不影响图像的回放. 不过一般情况下不太关心这个属性.

    Type: 5 个比特.
      nal_unit_type. 这个 NALU 单元的类型. 简述如下:

      0     没有定义
      1-23  NAL单元   单个 NAL 单元包.
      24    STAP-A   单一时间的组合包
      25    STAP-B   单一时间的组合包
      26    MTAP16   多个时间的组合包
      27    MTAP24   多个时间的组合包
      28    FU-A     分片的单元
      29    FU-B     分片的单元
      30-31 没有定义

    2. 打包模式

      下面是 RFC 3550 中规定的 RTP 头的结构.

           0                   1                   2                   3
           0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |V=2|P|X|  CC   |M|     PT      |       sequence number         |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |                           timestamp                           |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |           synchronization source (SSRC) identifier            |
          +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
          |            contributing source (CSRC) identifiers             |
          |                             ....                              |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      负载类型 Payload type (PT): 7 bits
      序列号 Sequence number (SN): 16 bits
      时间戳 Timestamp: 32 bits
      
      H.264 Payload 格式定义了三种不同的基本的负载(Payload)结构. 接收端可通过 RTP Payload 的第一个字节来识别它们. 这一个字节类似 NALU 头的格式, 而这个头结构的 NAL 单元类型字段则指出了代表的是哪一种结构。这个字节的结构如下, 可以看出它和 H.264 的 NALU 头结构是一样的:

          +---------------+
          |0|1|2|3|4|5|6|7|
          +-+-+-+-+-+-+-+-+
          |F|NRI|  Type   |
          +---------------+
      字段 Type: 这个 RTP payload 中 NAL 单元的类型. 

      这个字段和 H.264 中类型字段的区别是, 当 type 的值为 24 ~ 31 表示这是一个特别格式的 NAL 单元, 而 H.264 中, 只取 1~23 是有效的值.
       
      24    STAP-A   单一时间的组合包
      25    STAP-B   单一时间的组合包
      26    MTAP16   多个时间的组合包
      27    MTAP24   多个时间的组合包
      28    FU-A     分片的单元
      29    FU-B     分片的单元
      30-31 没有定义

      可能的结构类型分别有:

      1. 单一 NAL 单元模式
         即一个 RTP 包仅由一个完整的 NALU 组成. 这种情况下 RTP NAL 头类型字段和原始的 H.264的 NALU 头类型字段是一样的.

      2. 组合封包模式
        即可能是由多个 NAL 单元组成一个 RTP 包. 分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24.
      那么这里的类型值分别是 24, 25, 26 以及 27.

      3. 分片封包模式
        用于把一个 NALU 单元封装成多个 RTP 包. 存在两种类型 FU-A 和 FU-B. 类型值分别是 28 和 29.

    2.1 单一 NAL 单元模式

      对于 NALU 的长度小于 MTU 大小的包, 一般采用单一 NAL 单元模式.
      对于一个原始的 H.264 NALU 单元常由 [Start Code] [NALU Header] [NALU Payload] 三部分组成, 其中 Start Code 用于标示这是一个 NALU 单元的开始, 必须是 "00 00 00 01" 或 "00 00 01", NALU 头仅一个字节, 其后都是 NALU 单元内容.

      打包时去除 "00 00 01" 或 "00 00 00 01" 的开始码, 把其他数据封装成 RTP 包即可.

           0                   1                   2                   3
           0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |F|NRI|  type   |                                               |
          +-+-+-+-+-+-+-+-+                                               |
          |                                                               |
          |               Bytes 2..n of a Single NAL unit                 |
          |                                                               |
          |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |                               :...OPTIONAL RTP padding        |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


      如有一个 H.264 的 NALU 是这样的:

      [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]

      这是一个序列参数集 NAL 单元. [00 00 00 01] 是四个字节的开始码, 67 是 NALU 头, 42 开始的数据是 NALU 内容.

      封装成 RTP 包将如下:

      [ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]

      即只要去掉 4 个字节的开始码就可以了.

    2.2 组合封包模式

      当 NALU 的长度特别小时, 可以把几个 NALU 单元封在一个 RTP 包中.

      
           0                   1                   2                   3
           0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |                          RTP Header                           |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |STAP-A NAL HDR |         NALU 1 Size           | NALU 1 HDR    |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |                         NALU 1 Data                           |
          :                                                               :
          +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |               | NALU 2 Size                   | NALU 2 HDR    |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |                         NALU 2 Data                           |
          :                                                               :
          |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |                               :...OPTIONAL RTP padding        |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    2.3 Fragmentation Units (FUs).

      当 NALU 的长度超过 MTU 时, 就必须对 NALU 单元进行分片封包. 也称为 Fragmentation Units (FUs).
      
           0                   1                   2                   3
           0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          | FU indicator  |   FU header   |                               |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
          |                                                               |
          |                         FU payload                            |
          |                                                               |
          |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          |                               :...OPTIONAL RTP padding        |
          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

          Figure 14.  RTP payload format for FU-A

       The FU indicator octet has the following format:

          +---------------+
          |0|1|2|3|4|5|6|7|
          +-+-+-+-+-+-+-+-+
          |F|NRI|  Type   |
          +---------------+

       The FU header has the following format:

          +---------------+
          |0|1|2|3|4|5|6|7|
          +-+-+-+-+-+-+-+-+
          |S|E|R|  Type   |
          +---------------+

    FU indicator和FU header参考下面的例子的计算。

    3. SDP 参数

      下面描述了如何在 SDP 中表示一个 H.264 流:

      . "m=" 行中的媒体名必须是 "video"
      . "a=rtpmap" 行中的编码名称必须是 "H264".
      . "a=rtpmap" 行中的时钟频率必须是 90000.
      . 其他参数都包括在 "a=fmtp" 行中.

      如:

      m=video 49170 RTP/AVP 98
      a=rtpmap:98 H264/90000
      a=fmtp:98 profile-level-id=42A01E; sprop-parameter-sets=Z0IACpZTBYmI,aMljiA==

      下面介绍一些常用的参数.

    3.1 packetization-mode:

      表示支持的封包模式. 
      当 packetization-mode 的值为 0 时或不存在时, 必须使用单一 NALU 单元模式.
      当 packetization-mode 的值为 1 时必须使用非交错(non-interleaved)封包模式.
      当 packetization-mode 的值为 2 时必须使用交错(interleaved)封包模式.
      这个参数不可以取其他的值.

    3.2 sprop-parameter-sets:

      这个参数可以用于传输 H.264 的序列参数集和图像参数 NAL 单元. 这个参数的值采用 Base64 进行编码. 不同的参数集间用","号隔开.
      

    3.3 profile-level-id:

      这个参数用于指示 H.264 流的 profile 类型和级别. 由 Base16(十六进制) 表示的 3 个字节. 第一个字节表示 H.264 的 Profile 类型, 第

    三个字节表示 H.264 的 Profile 级别:
      

    3.4 max-mbps:

      这个参数的值是一个整型, 指出了每一秒最大的宏块处理速度.

    三、数据(无摄像头,即黑屏数据)

    1)H.246部分数据:

     

     

      这是一个序列参数集 NAL 单元. [00 00 00 01] 是四个字节的开始码, 67 是 NALU 头, 42 开始的数据是NALU内容.

    2)rtp,即sendpacket()发送的部分数据:

     

     

     

      FU indicator0x7c  = ( NALU_header & 0x60 ) | 28  ==  (0110 0111 & 0110 0000) | 28  ==  01100000 | 0001 1100  ==  0111 1100  ==  0x7c

      FU header0x87  = ( NALU_header & 0x1f ) | 0x80  ==  (0110 0111 &0001 1111) | 0x80  ==  0000 0111 | 1000 0000  ==  1000 0111 == 0x87

      这2个字节取代了开始码[00 00 00 01] 。其他的都一样。

     

      NALU:0x67:  0 11 00111(7)

      FU indicator:0x7C:0 11 11100(28)

    3)网络抓包数据

     

     

    14 E6 E4 1C C9 7A06 ED B5 C3 AA 23 0800 45 00 00 30 00 00 40 00 40 11 B6 B8 C0 A8 01 42 C0 A801 72 3E D0 04 D200 1CF5 DA 80E2 A8C1 8C 94F8 DD 31 1F06 D7 61 E2 0B 14 28 00 C6 30(62字节)

    14 E6 E4 1C C9 7A06 ED B5 C3 AA 23 0800 45 00 00 31 00 00 40 00 40 11 B6B7 C0 A8 01 42 C0 A8 01 72 3E D0 04 D2 00 1D CE BE 80 E2 A8 D4 8C 96 04 0D 31 1F 06 D7 61E8 01 5C 50 A003 18 C0(63字节) 

    14 E6 E4 1C C9 7A06 ED B5 C3 AA 23 0800 45 00 04 29 00 00 40 00 40 11 B2 BF C0 A8 01 42 C0 A8 01 72 3E D0 04 D2 04 15 5A 5B 80 62 A8 C08C 94 EA CD 31 1F 06 D77C 8742E0 1E DB 02 C0 49 1000 00 00 01 68 CE 30 A4 80 0000 00 01 06 E5 01 DB 80 00 00 00 01 65 B8 00 02 7C 80 6C50 A2 62 80 00 90 3D F7 DF 7DF7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF7D F7 DF 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75(第一个包,1079字节)

    四、RTP视频传输代码

    #define PLOAD_TYPE 98
    #define DefaultTimestampIncrement 90000/25
    static RTPSession sess;

    //创建rtp会话
    static int  RtpSetup( uint16_t portbase)
    {
        int status;
        ******************************* 
        *******************************
        status = sess.Create(sessparams,&transparams);
        checkerror(status);
        return status;
    }

    //错误判断
    void checkerror(int err)

          if (err < 0)
          {   
             char* errstr = RTPGetErrorString(err);  
             printf("Error:%s\n", errstr);   
             exit(-1); 
          }
    }

    //增加rtp传输目标ip地址,参数为目标ip和端口
    int AddDestination(uint32_t ipaddr, uint16_t destport)
    {
        int status;
     
        RTPIPv4Address addr(ipaddr,destport);
        status = sess.AddDestination(addr);
        checkerror(status);
        return status;
    }

    //rtp视频传输,val为一帧数据流(264的原始数据),包含0x00 0x00 0x00 0x01信息,length为数据的长度

    int H264SendPacket(unsigned char *val, uint32_t length)
    {
        int status=0;
        uint32_t  TimestampIncrement;
        uint32_t send_length,valid_len=length-4;
        char NALU=val[4]
    ,*sendStartAddr=NULL;
        #define  MAX_STREAM_SLICE 1024

       //获取默认设置
       TimestampIncrement=sess.GetDefaultTimestampIncrement();
       //如果数据小于1024字节,直接发送:单一NAL单元模式
        if(valid_len <= MAX_STREAM_SLICE)
        {
            status = sess.SendPacket((void *)&val[4],valid_len,PLOAD_TYPE,true,DefaultTimestampIncrement);
            checkerror(status);
        }
        else
        {
                 //切分为很多个包发送,每个包前要对头进行处理,如第一个包

                 sendStartAddr=(char *)(val+4);//发送数据的起始地址
                 sendStartAddr[pos-1]=(NALU&0x60)|28;//FU indicator
                 sendStartAddr[pos]=(NALU&0x1f)|0x80;//FU header
                 send_length=MAX_STREAM_SLICE+1;//要发送数据的长度,1025字节

                      ………………………………

                      //第二个至倒数第二个包

                      ………………………………

                      //最后一个包

        }

        checkerror(status);
    end:
        return status;
    }

     对了,记得要连接rtp库哦!!!!

     

    五、SDP参数

        因为程序是在Hi35XX开发板上运行,所以我的工作是把编码后的视频发送出去就ok了偷笑

    在windows下,写了一个脚本xxx.dsp,内容如下:
         m=video 1234 RTP/AVP 98
         a=rtpmap:98 H264/90000;
         a=decode_buf=300;

         a=framerate:15
         c=IN IP4 192.168.2.105   //板子的ip

    注:

        1)"m=" 行中的媒体名必须是 "video",端口为1234.
        2)"a=rtpmap" 行中的编码名称必须是 "H264".时钟频率必须是 90000.

        然后把脚本拖到VLCPortable.exe软件中(VLC是一个标准),就能显示摄像头获取的视频,就说明rtp传输没问题,我的工作就完成了再见

    http://blog.sina.com.cn/s/blog_8795b0970101ifun.html

    http://www.cppblog.com/czanyou/archive/2009/12/25/67940.html

  • 相关阅读:
    vim实用技巧总结
    configure, make, make install都做了什么
    替换ubuntu 14.04的源
    从源码Build vim以及打包.deb
    Vimperator技巧
    搭建Gitlab
    [转] 你真的会写单例模式吗——Java实现
    笔记本开临时Wifi
    Ubuntu 12.04 修改键盘映射
    oracle查看用户所在的表空间
  • 原文地址:https://www.cnblogs.com/stnlcd/p/7266797.html
Copyright © 2011-2022 走看看