以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。
本节内容是移植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 hi3518ev201145 s32ChnNum = 1;146 #endif147 s32ChnNum = 1;//added by xjh148 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);#elsefwrite(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发送实验的源码分析。
rtpInitortp_init//以下都是ORTP的库函数ortp_scheduler_initortp_set_log_level_maskrtp_session_newrtp_session_set_scheduling_modertp_session_set_blocking_modertp_session_set_remote_addrrtp_session_set_payload_typertp_session_set_ssrc rtpSendrtp_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)此时如果能看到实时图像(有延迟)就证明整个实验完成了。