第三季1:ORTP库的移植与视频的实时传输实验

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

本节内容是移植ORTP库,并使用ORTP库来完成视频的实时传输。

一、ORTP的简介

1、视频网络传输的两种方式

(1)基于下载的方式。比如http(Hyper Text Transfer Protocol 超文件传输协定)、ftp(File Transfer Protocol,文件传输协议)。基于下载的方式传输视频时,如果网速慢就不会实时,如果网速大于播放速率则会缓冲,这能够保证视频质量。

(2)基于实时的方式。比如RTP、RTSP、RTCP(是对RTP的一种补充,因为RTP只有传输而没有控制信息)。多应用于视频监控、直播等行业。

2、ORTP的介绍

(1)RTP(Real-time Transport Protocol,实时传输协议)是一个网络传输协议。它详细说明了在互联网上传递音频和视频的标准数据包格式。

(2)ORTP,即openRTP,它是用C实现的一个RTP库。即RTP是一种协议,而ORTP是协议的软件实现(体现为一个库)。ORTP库实现了RTP和RTCP协议,前者负责传输视频,后者负载视频传输的质量控制、同步、协调等。

(3)实质是一个视频服务器,工作时客户端和服务器实时传递视频数据。VLC播放器在这里充当客户端。

(4)一般认为RTP工作在传输层,但RTP其实比TCP/UDP高一个层次。

(5)RTP的实现由国际标准RFC3550规定,只要符合协议谁都可以写一个RTP的实现。

二、ORTP库的移植

1、准备源码

(1)下载ortp源码。OPTP库里面最关键的是include,src和src/test这三个文件夹,相应的数据结构和头文件存放在include/ortp目录下;src里面实现了一些功能函数;src/test是示例代码。

(2)将ortp-master.zip文件通过共享文件夹存放到ubuntu合适的目录,并解压。

root@ubuntu:/home/xjh/iot/hisi_development/ortp# ls
ortp-master.zip
root@ubuntu:/home/xjh/iot/hisi_development/ortp# unzip ortp-master.zip
//省略解压信息
root@ubuntu:/home/xjh/iot/hisi_development/ortp# ls
ortp-master  ortp-master.zip
root@ubuntu:/home/xjh/iot/hisi_development/ortp# 

2、增加H.264格式的payload支持

在/home/xjh/iot/hisi_development/ortp/ortp-master/src/avprofile.c文件中,av_profile_init函数末尾添加代码如下:

void av_profile_init(RtpProfile *profile)
{
        rtp_profile_clear_all(profile);
        profile->name="AV profile";
        rtp_profile_set_payload(profile,0,&payload_type_pcmu8000);
        rtp_profile_set_payload(profile,1,&payload_type_lpc1016);
        rtp_profile_set_payload(profile,3,&payload_type_gsm);
        rtp_profile_set_payload(profile,7,&payload_type_lpc);
        rtp_profile_set_payload(profile,4,&payload_type_g7231);
        rtp_profile_set_payload(profile,8,&payload_type_pcma8000);
        rtp_profile_set_payload(profile,9,&payload_type_g722);
        rtp_profile_set_payload(profile,10,&payload_type_l16_stereo);
        rtp_profile_set_payload(profile,11,&payload_type_l16_mono);
        rtp_profile_set_payload(profile,18,&payload_type_g729);
        rtp_profile_set_payload(profile,31,&payload_type_h261);
        rtp_profile_set_payload(profile,32,&payload_type_mpv);
        rtp_profile_set_payload(profile,34,&payload_type_h263);
        rtp_profile_set_payload(profile,96,&payload_type_h264);//added by xjh
}

3、配置和编译、安装

(1)进入ortp目录后执行“./autogen.sh”。

root@ubuntu:/home/xjh/iot/hisi_development/ortp/ortp-master# ./autogen.sh

执行该步骤时可能出现的错误及解决方法如下。

1)错误1:./autogen.sh: line 44: libtoolize: command not found

解决方法:执行“sudo apt-get install libtool*”。GNU Libtool 可以在不同的系统中建立动态链接库。它通过一个称为 Libtool 库的抽象,隐藏了不同系统之间的差异,给开发人员提供了一致的的接口。

2)错误2:libtoolize:   error: Please install GNU M4, or 'export M4=/path/to/gnu/m4'.

解决方法:执行“sudo apt-get install m4”。M4是一个宏处理器,将输入拷贝到输出,同时将宏展开。宏可以是内嵌的也可以是用户定义的。除了可以展开宏,M4还有一些内建的函数,用来引用文件,执行Unix命令,整数运算,文本操作,循环等。M4既可以作为编译器的前端也可以单独作为一个宏处理器。

3)错误3:Automake - aclocal: command not found 

解决方法:执行“sudo apt-get install automake”,主要用于创建makefile。

(2)接着执行“./configure --prefix=/tmp/ortp --host=arm-hisiv300-linux”。

1)--host=arm-hisiv300-linux,指定了交叉编译工具链,因此要正确安装交叉编译工具链。

2)--prefix=/tmp/ortp表示最后安装到/tmp/ortp此目录下(不用事先创建,后面自动生成)。

(3)接着执行一条命令“make && make install”。

4、查看移植完的库和头文件

在/tmp/ortp目录下如果有以下内容,则说明移植完成。

root@ubuntu:/tmp/ortp# ls
include  lib
root@ubuntu:/tmp/ortp# cd include/
root@ubuntu:/tmp/ortp/include# ls
ortp
root@ubuntu:/tmp/ortp/include# cd ortp/
root@ubuntu:/tmp/ortp/include/ortp# ls
b64.h      ortp.h         port.h  rtpprofile.h      sessionset.h  stun_udp.h
event.h    ortp_srtp.h    rtcp.h  rtpsession.h      str_utils.h   telephonyevents.h
logging.h  payloadtype.h  rtp.h   rtpsignaltable.h  stun.h        zrtp.h
root@ubuntu:/tmp/ortp/include/ortp# cd ../../lib/
root@ubuntu:/tmp/ortp/lib# ls
libortp.la  libortp.so  libortp.so.9  libortp.so.9.0.0  pkgconfig
root@ubuntu:/tmp/ortp/lib# 

三、利用RTP协议实现局域网实时视频传输

1、在SDK的sample中添加rtp传输代码

(1)在mpp/sample/venc/sample_venc.c文件中的SAMPLE_VENC_1080P_CLASSIC函数里修改代码如下(对于/sample_venc.c文件,仅做这一步修改而已,这修改表示原来有三路码流输出,但为了简单演示而设置为一路输出)。

 144 #ifdef hi3518ev201
 145         s32ChnNum = 1;
 146 #endif
 147         s32ChnNum = 1;//added by xjh
 148         printf("s32ChnNum = %d\n",s32ChnNum);
 149     
 150     stVbConf.u32MaxPoolCnt = 128;
 151     
 152     /*video buffer*/ 
 153         if(s32ChnNum >= 1)
 154     {

(2)接下来所有的修改,在mpp/sample/common/sample_common_venc.c文件中进行。

将完成修改的sample_common_venc.c文件替代原文件即可。

(3)这里补充说一下(2)中修改的思路。

A、使用ORTP库的sample和第二季的sample,它们的步骤相同,只是在“ 如何处理编码得到的码流 ”这个问题上不同。第二季的sample中是将码流保存为裸流文件,而使用 ORTP库的 sample是将码流数据以包的形式在网络上传输。因此修改点就在第二季的sample中将码流保存为裸流文件的代码处。

B、根据第二季8:保存编码得到的码流,我们应该在“ step2_5 :SAMPLE_COMM_VENC_SaveStream ”函数里修改(为了简单没有修改这个函数名,但功能已经改变了),使它完成将码流数据以包的形式在网上传输的功能。我们在这个函数之前进行一些初始化,因此在step2之前添加以下代码。我们以宏的方式定义 LOCAL_HOST_IP 为192.168.1.20,而8080是端口号。这也是VLC的sdp文件内容(见本文最后)为什么是那样的原因。

   #if ORTP_ENABLE
    /***rtp init****/
    pRtpSession = rtpInit( LOCAL_HOST_IP ,8080);  
    if (pRtpSession==NULL)   
    {   
        printf( "error rtpInit" ); 
        exit(-1);  
        return  0;   
    } 
   #endif

    /******************************************
     step 2:  Start to get streams of each channel.
    ******************************************/
    while (HI_TRUE == pstPara->bThreadStart)
    {
     //……
    }

C、修改SAMPLE_COMM_VENC_SaveStream函数,落实到最后,是修改SAMPLE_COMM_VENC_SaveH264函数。
 

/******************************************************************************
* funciton : save H264 stream
******************************************************************************/
HI_S32 SAMPLE_COMM_VENC_SaveH264(FILE* fpH264File, VENC_STREAM_S *pstStream)
{
    HI_S32 i;
    
    for (i = 0; i < pstStream->u32PackCount; i++)
    {
        #if ORTP_ENABLE  //添加这个
		    rtpSend(pRtpSession,pstStream->pstPack[i].pu8Addr, pstStream->pstPack[i].u32Len);
        #else
        	fwrite(pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,
               pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset, 1, fpH264File);
        	fflush(fpH264File);
        #endif
    }
    
    return HI_SUCCESS;
}

D、其中B和C中 rtpInit、rtpSend函数,是我们在sampl_comm_ven.c文件中新添加的函数,它们的调用关系如下。

这些函数的详细分析见博客第三季2:ORTP库与RTP发送实验的源码分析

rtpInit
    ortp_init//以下都是ORTP的库函数
    ortp_scheduler_init
    ortp_set_log_level_mask
    rtp_session_new
    rtp_session_set_scheduling_mode
    rtp_session_set_blocking_mode
    rtp_session_set_remote_addr
    rtp_session_set_payload_type
    rtp_session_set_ssrc
rtpSend
    rtp_session_send_with_ts//这个是ORTP的库函数

2、重新编译sample

(1)将/tmp/ortp/include/ortp这个目录复制到mpp/include/目录中。切记,复制的是目录而不是里面的文件!如果复制里面的文件,因为一些文件包含是以“ortp/xxx.h”方式的,会提示找不到xxx.h文件。

root@ubuntu:/home/xjh/iot/hisi_development/Hi3518E_SDK/Hi3518E_SDK_V1.0.3.0/mpp/include# cp /tmp/ortp/include/ortp ./ -rf
root@ubuntu:/home/xjh/iot/hisi_development/Hi3518E_SDK/Hi3518E_SDK_V1.0.3.0/mpp/include# 

(2)修改mpp/sample/venc/目录下的Makefile,即添加libortp的链接支持。

$(TARGET):%:%.o $(COMM_OBJ)
#    $(CC) $(CFLAGS) -lpthread -lm -o $@ $^ $(MPI_LIBS) $(AUDIO_LIBA) $(SENSOR_LIBS)
    $(CC) $(CFLAGS) -lpthread -lm -lortp -o $@ $^ $(MPI_LIBS) $(AUDIO_LIBA) $(SENSOR_LIBS) -L/tmp/ortp/lib
clean:
    @rm -f $(TARGET)
    @rm -f $(OBJ)
    @rm -f $(COMM_OBJ)

(3)在mpp/sample/venc/目录下执行“make”,可得到sample_venc可执行文件。

root@ubuntu:/home/xjh/iot/hisi_development/Hi3518E_SDK/Hi3518E_SDK_V1.0.3.0/mpp/sample/venc# ls
Makefile  sample_venc  sample_venc.c  sample_venc.o
root@ubuntu:/home/xjh/iot/hisi_development/Hi3518E_SDK/Hi3518E_SDK_V1.0.3.0/mpp/sample/venc# 

3、开发板中部署并运行测试

(1)将/tmp/ortp/lib/libortp.so*这些文件复制到开发板中/usr/lib目录中。

(2)检查开发板中的配置是否正确,比如/mpp/sample/Makefile.param中的sensor等内容是否对应实际。

(3)将生成的sample_venc文件拷贝到虚拟机/home/xjh/iot/hisi_development/hisi_rootfs/目录中,然后将该目录挂载到板载系统的/mnt目录,在板载系统的/mnt目录下执行“./sample_venc 0”,然后输入c,此时SCRT中显示如下。

(4)在VLC播放器中,选择媒体,打开文件,选择sdp文件(提取码ms4a)

m=video 8080 RTP/AVP 96
a=rtpmap:96 H264
a=framerate:25
c=IN IP4 192.168.1.20

# sdp文件是VLC软件的配置文件,它告诉VLC播放器接收到的数据是怎样的。
# m=vidio,表示这是视频信息;8080是端口;
# RTP/AVP 96,表明传输过来的网络协议;96表示是h264的。
# a=framerate:25 这表示帧率;
# c=IN IP4 192.168.1.20 表示VLC所在主机的IP地址(window的ip地址)

注意这里之所以是192.168.1.20,是因为sample_common_venc.c文件中规定windows主机的ip地址就是这个(我们自己添加与修改的),因此我们要将主机的ip地址手动设置成这个。

#define Y_PLOAD_TYPE 96 //H.264
#define MAX_RTP_PKT_LENGTH 1400
#define DefaultTimestampIncrement 3600 //(90000/25)
uint32_t g_userts=0;
RtpSession *pRtpSession = NULL;

#define LOCAL_HOST_IP  "192.168.1.20" //这里我们自己添加的

(5)此时如果能看到实时图像(有延迟)就证明整个实验完成了。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天糊土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值