其他分享
首页 > 其他分享> > ORTP库局域网图传和VLC实时预览(1)

ORTP库局域网图传和VLC实时预览(1)

作者:互联网

目录

一、ORTP的引入

1、对之前两季文章内容的回顾

(1)搭建了SDK开发环境,编译系统,部署并测试环境
(2)详解了sample源码,编译运行,测试录像,验证硬件

2、视频网络传输的2种方式

(1)基于下载:http or ftp(下载下来再去播放,网速不好则会影响观看,比如我们看电影时,通常网络不好显示缓冲)

  **HTTP,超文本传输协议(Hyper Text Transfer Protocol)**是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。HTTP是应用层协议,是基于B/S架构进行通信的,而HTTP的服务器端实现程序有httpd、nginx等,其客户端的实现程序主要是Web浏览器,例如Firefox、Internet Explorer、Google Chrome、Safari、Opera等

  FTP,文件传输协议(File Transfer Protocol)是用于在网络上进行文件传输的一套标准协议,它工作在 OSI 模型的第七层, TCP 模型的第四层, 即应用层, 使用 TCP 传输而不是 UDP, 客户在和服务器建立连接前要经过一个“三次握手”的过程, 保证客户与服务器之间的连接是可靠的, 而且是面向连接, 为数据传输提供可靠保证。

  FTP允许用户以文件操作的方式(如文件的增、删、改、查、传送等)与另一主机相互通信。然而, 用户并不真正登录到自己想要存取的计算机上面而成为完全用户, 可用FTP程序访问远程资源, 实现用户往返传输文件、目录管理以及访问电子邮件等等, 即使双方计算机可能配有不同的操作系统和文件存储方式。 [1]

(2)基于实时:RTP/RTSP/RTCP(如果网速不好,则牺牲画面质量来实现实时传输,监控这种一般就要实时)

  RTP(Real-time Transport Protocol)RTP一般指实时传输协议。 实时传输协议(Real-time Transport Protocol或简写RTP)是一个网络传输协议,它是由IETF的多媒体传输工作小组1996年在RFC 1889中公布的。

  RTSP(Real Time Streaming Protocol),RFC2326,实时流传输协议,是TCP/IP协议体系中的一个应用层协议

  RTCP(Real-time Transport Control Protocol或RTP Control Protocol或简写RTCP)是实时传输协议(RTP)的一个姐妹协议。RTCP由RFC 3550定义(取代作废的RFC 1889)。RTP 使用一个 偶数 UDP port ;而RTCP 则使用 RTP 的下一个 port,也就是一个奇数 port。RTCP与RTP联合工作,RTP实施实际数据的传输,RTCP则负责将控制包送至电话中的每个人。其主要功能是就RTP正在提供的服务质量做出反馈。

  RTSP发起/终结流媒体、RTP传输流媒体数据 、RTCP对RTP进行控制,同步。

详解:https://blog.csdn.net/frankiewang008/article/details/7665547/

3、ORTP的介绍

(1)openRTP,用C实现的一个RTP库(其实还有C++实现的,JAVA等实现的)

(2)实质是一个视频服务器,工作时客户端和服务器实时传递视频数据,使用UDP协议,因为TCP是基于连接的,要经过三次握手,比较消耗性能,在实时传输中并不是很好。

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

(4)RTP(及RTCP)的实现有国际标准RFC3550规定,只要符合协议谁都可以自己写一个

(5)本季(篇)文章重点在于使用ORTP来实现局域网视频实时传输

二、ORTP库的移植

1、准备源码

(1)下载ortp源码:https://github.com/dmonakhov/ortp

我将自己下好的网盘链接也提供给大家:
链接:https://pan.baidu.com/s/1UML_evRZL6D8JV8aoW1UqA 
提取码:ckko 
--来自百度网盘超级会员V5的分享

(2)存放到ubuntu中的临时工作目录并解压,比如放到~/sambashare/目录下

(3)解压源码,进入源码目录

unzip ortp-master.zip

2、源码修改

(1)增加H.264的payload支持。

在src/avprofile.c中357行添加:
rtp_profile_set_payload(profile,96,&payload_type_h264);
从而增加对h.264的支持,这里payload绑定的数字是个标准,h.264对应的就是96
payload:负载

在这里插入图片描述
在这里插入图片描述

3、配置和编译、安装

(1)进入ortp目录执行./autogen.sh

(2)错误1:./autogen.sh: line 44: libtoolize: command not found
   解决:sudo apt-get install libtool*

(2)错误2:libtoolize:   error: Please install GNU M4, or 'export M4=/path/to/gnu/m4'.
   解决:sudo apt-get install m4

(3)错误3:Automake - aclocal: command not found 
   解决:sudo apt-get install automake

(4)继续执行
./autogen.sh
./configure --prefix=/tmp/ortp --host=arm-hisiv300-linux
make && make install

4、到/tmp/ortp目录下查看移植好的库和头文件

在这里插入图片描述

三、RTP传输视频实战

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

(1)venc/sample_venc.c中,添加:s32ChnNum = 1;
在这里插入图片描述

三路改一路,我们只发送一路数据。

(2)common/sample_common_venc.c中,我们需要修改很多东西,我将修改后的文件提供给大家:

理解下列代码,参考学习(必看):
https://blog.csdn.net/tq08g2z/article/details/77528335
https://blog.csdn.net/zhang_danf/article/details/51037572

#define ORTP_ENABLE  1

#if ORTP_ENABLE
#include <ortp/ortp.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#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"//根据自己的电脑ip进行设定

/**  初始化   
 *     
 *   主要用于对ortp以及其它参数进行初始化   
 *   @param:  char * ipStr 目的端IP地址描述串   
 *   @param:  int port 目的端RTP监听端口   
 *   @return:  RtpSession * 返回指向RtpSession对象的指针,如果为NULL,则初始化失败   
 *   @note:      
 */   
RtpSession * rtpInit( char  * ipStr, int  port)
{
    RtpSession *session; 
    char  *ssrc;
    printf("********oRTP for H.264 Init********\n");

    ortp_init();
    ortp_scheduler_init();
    ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR);
    session=rtp_session_new(RTP_SESSION_SENDONLY);//创建会话

    rtp_session_set_scheduling_mode(session,1);
    rtp_session_set_blocking_mode(session,0);
    //rtp_session_set_connected_mode(session,TRUE);
    rtp_session_set_remote_addr(session,ipStr,port);
    rtp_session_set_payload_type(session,Y_PLOAD_TYPE);

    ssrc=getenv("SSRC");//得到环境变量
    if (ssrc!=NULL) {//一根线中有很多个会话传输,通过添加源标志位区分各个会话
        printf("using SSRC=%i.\n",atoi(ssrc));
        // 设置输出流的SSRC。不做此步的话将会给个随机值 
        rtp_session_set_ssrc(session,atoi(ssrc));
    }
    return  session;
}
/**  结束ortp的发送,释放资源   
 *     
 *   @param:  RtpSession *session RTP会话对象的指针   
 *   @return:  0表示成功   
 *   @note:       
 */    
int  rtpExit(RtpSession *session)   
{ 
    printf("********oRTP for H.264 Exit********\n");  
    g_userts = 0;   
       
    rtp_session_destroy(session);   
    ortp_exit();   
    ortp_global_stats_display();   
  
     return  0;   
}   
/**  发送rtp数据包   
 *     
 *   主要用于发送rtp数据包   
 *   @param:  RtpSession *session RTP会话对象的指针   
 *   @param:  const char *buffer 要发送的数据的缓冲区地址   
  *   @param: int len 要发送的数据长度   
 *   @return:  int 实际发送的数据包数目   
 *   @note:     如果要发送的数据包长度大于BYTES_PER_COUNT,本函数内部会进行分包处理   
 */   
int  rtpSend(RtpSession *session, char  *buffer,  int  len)
{  
    int  sendBytes = 0; 
    int status;       
    uint32_t valid_len=len-4;
    unsigned char NALU=buffer[4];
     
    //如果数据小于MAX_RTP_PKT_LENGTH字节,直接发送:单一NAL单元模式
    if(valid_len <= MAX_RTP_PKT_LENGTH)
    {
        sendBytes = rtp_session_send_with_ts(session,
                                             &buffer[4],
                                             valid_len,
                                             g_userts);
    }
    else if (valid_len > MAX_RTP_PKT_LENGTH)
    {
        //切分为很多个包发送,每个包前要对头进行处理,如第一个包
        valid_len -= 1;
        int k=0,l=0;
        k=valid_len/MAX_RTP_PKT_LENGTH;
        l=valid_len%MAX_RTP_PKT_LENGTH;
        int t=0;
        int pos=5;
        if(l!=0)
        {
            k=k+1;
        }
        while(t<k)//||(t==k&&l>0))
        {
            if(t<(k-1))//(t<k&&l!=0)||(t<(k-1))&&(l==0))//(0==t)||(t<k&&0!=l))
            {
                buffer[pos-2]=(NALU & 0x60)|28;
                buffer[pos-1]=(NALU & 0x1f);
                if(0==t)
                {
                    buffer[pos-1]|=0x80;
                }
                sendBytes = rtp_session_send_with_ts(session,
                                                     &buffer[pos-2],
                                                     MAX_RTP_PKT_LENGTH+2,
                                                     g_userts);
                t++;
                pos+=MAX_RTP_PKT_LENGTH;
            }
            else //if((k==t&&l>0)||((t==k-1)&&l==0))
            {
                int iSendLen;
                if(l>0)
                {
                    iSendLen=valid_len-t*MAX_RTP_PKT_LENGTH;
                }
                else
                    iSendLen=MAX_RTP_PKT_LENGTH;
                buffer[pos-2]=(NALU & 0x60)|28;
                buffer[pos-1]=(NALU & 0x1f);
                buffer[pos-1]|=0x40;
                sendBytes = rtp_session_send_with_ts(session,
                                                     &buffer[pos-2],
                                                     iSendLen+2,
                                                     g_userts);
                t++;
            }
        }
    }

    g_userts += DefaultTimestampIncrement;//timestamp increase
    return  len;
}
#endif
/******************************************************************************
* 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;
}
   #if ORTP_ENABLE
    /***rtp init****/
    pRtpSession = rtpInit( LOCAL_HOST_IP ,8080);  
    if (pRtpSession==NULL)   
    {   
        printf( "error rtpInit" ); 
        exit(-1);  
        return  0;   
    } 
    #endif

修改好的文件:
链接:https://pan.baidu.com/s/1FNZ09-E2ERsjIVDmNxqOiw
提取码:dveu
–来自百度网盘超级会员V5的分享

2、重新编译sample

(1)复制ortp头文件,因为上边添加的代码使用ortp中的源码。将ortp编译生成的include目录下的文件夹复制到Hi3518E_SDK_V1.0.3.0/mpp/include/目录下

cp /tmp/ortp/include/ortp  ~/sambashare/Hi3518E_SDK_V1.0.3.0/mpp/include/ -rf

(2)修改venc中Makefile,添加libortp的链接支持
在这里插入图片描述
(3)make进行编译

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

(1)开发板开机并通过nfs挂载到主机时,部署libortp.so到开发板中/usr/lib目录下

(2)检查开发板中原有配置是否正确,譬如sensor是否对应实际

(3)通过nfs挂载方式得到新的sample程序测试运行

(4)vlc中打开配置好的sdp文件,看到实时图像就证明整个实验完成了,以下是这个文件的链接:

链接:https://pan.baidu.com/s/1VRuPLWw4r8MWhGgTWGWSJw
提取码:gqhy
–来自百度网盘超级会员V5的分享

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

注:本资料大部分由朱老师物联网大讲堂课程笔记整理而来,并且引用了部分他人博客的内容,如有侵权,联系删除!水平有限,如有错误,欢迎各位在评论区交流。

标签:VLC,ortp,传输,session,RTP,图传,ORTP,rtp
来源: https://blog.csdn.net/weixin_45842280/article/details/121643265