嵌入式 RTP通话:视频流(H.264)的传输

从摄像头获取的视频数据,经过编码后(当然,也可以不编码,如果你觉得也很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.1\src内的"jmutex.h"和"jthread.h"两个头文件放入jrtplib-3.7.1\src目录下,然后将 jrtplib-3.7.1\src 文件夹下所有头文件中的和语句修改为"jmutex.h"和"jthread.h",需要修改的文件为 rtpudpv4transmitter.h、rtpsession.h和 rtppollthread.h。编译时注意编译方式和 jthread.lib一致。

    5)编译生成的 jthread.lib 和 jrtplib.lib 拷贝到系统目录:C:\Program  Files\Microsoft  Visual Studio\VC98\Lib 下,将 jrtplib-3.7.1\src下所有的.h 头文件复制到 C:\Program  Files\MicrosoftVisual Studio\VC98\Include,以便以后使用。

    6)现在我们就可以编译 jrtplib-3.7.1\examples 下的实例程序了。建立 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 格式(负载格式):

2.分片封包模式(核心代码即为该模式,以及单个NAL单元包):    而当 NALU 的长度超过 MTU (1024)时, 就必须对 NALU 单元进行分片封包. 也称为 Fragmentation Units (FUs).

详情见本文作者原文http://www.cppblog.com/czanyou/archive/2009/12/25/67940.html

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

1)H.246部分数据:

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

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

 

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

      FU header0x87   (NALU&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传输没问题,我的工作就完成了

时间: 2024-10-30 16:19:59

嵌入式 RTP通话:视频流(H.264)的传输的相关文章

ffmpeg解码RTSP/TCP视频流H.264(QT界面显示视频画面)

源码下载地址: http://download.csdn.net/detail/liukang325/9489952 我用的ffmpeg版本为 ffmpeg-2.1.8.tar.bz2 版本低了恐怕有些头文件和API找不到. 在Linux下解压后编译,Linux下编译很简单,我这里生成的动态库: ./configure –enable-shared make 就能找到各个so动态库文件. 移动位置后,记得手动链接 一下: ln -s libavcodec.so.55 libavcodec.so

H.264 RTPpayload 格式------ H.264 视频 RTP 负载格式(包含AAC部分解析)

H.264 RTPpayload 格式------ H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) NALU 头由一个字节组成, 它的语法如下:      +---------------+      |0|1|2|3|4|5|6|7|      +-+-+-+-+-+-+-+-+      |F|NRI|  Type   |      +---------------+ F: 1 个比特(禁止位).  forbidden_zero_bit. 在 H.264 规范中规

H.264视频的RTP荷载格式

Status of This Memo    This document specifies an Internet standards track protocol for the   Internet community, and requests discussion and suggestions for   improvements.  Please refer to the current edition of the "Internet   Official Protocol St

嵌入式-Linux下,如何将H.264的帧文件,保存为视频文件,可供播放?

问题描述 Linux下,如何将H.264的帧文件,保存为视频文件,可供播放? 我目前是在嵌入式Linux下,将H.264编码后的视频帧,通过网络传输至另外一端.请部,作为接收端,应该通过哪种方式或工具,将视频帧保存为视频文件,可供电脑播放? 发送端大约每秒发送25帧,通过无线传输,有可能中间有丢失帧.而保存的文件,需要将丢失帧也考虑进保存的文件中,谢谢了!! 解决方案 http://bbs.csdn.net/topics/390041128 解决方案二: 看看这个帖子可有用http://bbs.

FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法

FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法 RFC3984是H.264的baseline码流在RTP方式下传输的规范,这里只讨论FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法.   H.264的NAL层处理 H264以NALU(NALunit)为单位来支持编码数据在基于分组交换技术网络中传输. NALU定义了可用于基于分组和基于比特流系统的基本格式,同时给出头信息,从而提供了视频编码和外部事件的接口. H264编码过程中的三种不同的数据形式

H.264 RTP 封包格式

H.264 视频 RTP 负载格式 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_r

H.264中NAL、Slice与frame意思及相互关系

H.264中NAL.Slice与frame意思及相互关系 NAL nal_unit_type中的1(非IDR图像的编码条带).2(编码条带数据分割块A).3(编码条带数据分割块B).4(编码条带数据分割块C).5(IDR图像的编码条带)种类型 与 Slice种的三种编码模式:I_slice.P_slice.B_slice 还有frame的3种类型:I frame.P frame. B frame之间有什么映射关系么? 最后,NAL nal_unit_type中的6(SEI).7(SPS).8(P

Matrox Maevex H.264编码器/解码器现推出新软件、固件和API

http://www.aliyun.com/zixun/aggregation/33721.html">2014年7月23日蒙特利尔消息:Matrox® Graphics Inc.(迈创图形产品部)今天宣布用于Matrox Maevex 5100系列H.264编码器/解码器的1.03版固件发货,提供多项可通过最 新的PowerStream 1.03软件或是新的API控制的新的AV-over-IP功能.    Maevex PowerStream 软件为管理员提供直观的用户界面,以远程检测并

获得H.264视频分辨率的方法

在使用ffmpeg解码播放TS流的时候(例如之前写过的UDP组播流),在连接时往往需要耗费大量时间.经过debug发现是av_find_stream_info(已抛弃,现在使用的是avformat_find_stream_info)这个方法十分耗时,而且是阻塞的.av_find_stream_info方法主要是获得相应的流信息,其中对我的应用最有用的就是视频的分辨率.在av_find_stream_info中是要不断的读取数据包,解码获得相应的信息,而其中除了分辨率信息以外的东西对我的应用中是无