5、HI3518E平台移植ORTP库

1、准备源码

       首先下载ortp源码:https://github.com/dmonakhov/ortp

       下载完成后,存放到ubuntu临时工作目录并解压,这里我随便找了个地方解压了。
 

2、解压源码

       这里我下载完成后,是一个zip文件,使用unzip ortp-master.zip命令解压到当前目录下。
 

3、源码修改

       增加H.264的payload支持,在src/avprofile.c的av_profile_init函数中357行添加:

rtp_profile_set_payload(profile,96,&payload_type_h264);

4、配置和编译、安装

       (1) 进入ortp目录执行./autogen.sh,这步工作是对ortp库进行最原始的配置。出现了一堆错误,然后需要一一解决。

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

       解决:sudo apt-get install libtool*

       扩展:GNU Libtool 可以容易的在不同的系统中建立动态链接库。它通过一个称为 Libtool 库的抽象,隐藏了不同系统之间的         差异,给开发人员提供了一致的的接口。

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

       解决:sudo apt-get install m4

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

       错误3:Automake - aclocal: command not found 

       解决:sudo apt-get install automake

      扩展:主要用于创建makefile

       (2) 继续对ortp库进行配置,执行./configure --prefix=/tmp/ortp --host=arm-hisiv300-linux

       (3) 最后执行 make && make install

 

5、添加代码

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

  (1)venc/sample_venc.c中SAMPLE_VENC_1080P_CLASSIC函数中,添加:s32ChnNum = 1;这里主要是因为,我们只是单纯的做网络传输,所以用到一路就可以了。

(2)common/sample_common_venc.c中,改了很多

主要是三个函数:

 

  1. RtpSession * rtpInit( char * ipStr, int port)
  2. int rtpExit(RtpSession *session)
  3. int rtpSend(RtpSession *session, char *buffer, int len)
#define ORTP_ENABLE  1        //定义了一个控制ortp的开关宏
#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"
 
/**  初始化   
 *     
 *   主要用于对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

然后在SAMPLE_COMM_VENC_SaveH264函数中的for循环中添加

#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

在SAMPLE_COMM_VENC_GetVencStreamProc函数中的step2之前,添加以下代码

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

6、重新编译sample

       复制ortp头文件,到mpp文件夹里面的include文件夹中

 修改sample/venc中Makefile,添加libortp的链接支持,添加-lortp -L/tmp/ortp/lib

7、开发板中部署

搭建好网络环境,用开发板ping 虚拟机和windows都要能通,这里要注意一点,由于测试代码固定成192.168.1.20,该这是文件在Hi3518E_SDK_V1.0.3.0\package\mpp\sample\common\sample_comm_venc.c,所以windows的网卡地址要设置成这个。

       将之前编译好的lib库拷贝到nfs文件系统里面,目的是将ortp库部署到开发板的文件系统中。

然后在串口终端那边拷贝到开发板文件系统/usr/lib中

8、测试运行程序

  1. 在控制台运行编译好的应用程序,VLC中 媒体->打开文件,选择做好的sdp配置文件,
  2. 设置主机IP地址为192.168.1.20
  3. 如果需要进要关闭windows防火墙

最终看到的实验现象如下所示

注意:sdp文件解读

m=video 8080 RTP/AVP 96     //端口为8080,96表示h.264   
a=rtpmap:96 H264
a=framerate:25             //帧率为25
c=IN IP4 192.168.1.20      //主机IP地址

参考:https://blog.csdn.net/tainjau/article/details/80399872

OPTP库API使用:https://blog.csdn.net/bill611/article/details/77726429

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值