HI3516EV200 ORTP

本文详细介绍了如何将ORTP库移植到特定平台,包括源码获取、修改、配置、编译和安装过程。接着,展示了如何使用ORTP库实现实时视频传输,包括初始化、发送RTP数据包的函数实现。此外,还提供了在Windows端通过VLC接收开发板视频流的配置方法。
摘要由CSDN通过智能技术生成

ORTP的介绍

  1. openRTP,用C实现的一个RTP库(其实还有C++实现的,JAVA等实现的)
  2. 实质是一个视频服务器,工作时客户端和服务器实时传递视频数据
  3. 一般认为RTP工作在传输层,但是其实RTP比TCP/UDP高一个层次
  4. RTP(及RTCP)的实现有国际标准RFC3550规定,只要符合协议谁都可以自己写一个
  5. 本季课程重点在于使用ORTP来实现局域网视频实时传输

ORTP库的移植

  • 准备源码
  1. 下载ortp源码:https://github.com/dmonakhov/ortp
  2. 存放到临时工作目录并解压
  • 源码修改
  1. 增加H.264的payload支持。
    在src/avprofile.c中357行添加:
    rtp_profile_set_payload(profile,96,&payload_type_h264);
  • 配置和编译、安装
  1. 进入ortp目录执行./autogen.sh
  2. 错误1:./autogen.sh: line 44: libtoolize: command not found
    解决:sudo apt-get install libtool*
  3. 错误2:libtoolize: error: Please install GNU M4, or ‘export M4=/path/to/gnu/m4’.
    解决:sudo apt-get install m4
  4. 错误3:Automake - aclocal: command not found
    解决:sudo apt-get install automake
  5. 继续执行./configure --prefix=/tmp/ortp --host=arm-himix100-linux
    • /tmp/ortp是安装目录
    • arm-himix100-linux:指定编译器,3516用的arm-himix100-linux-gcc 朱友鹏老师的3518E用的是arm-hisiv300-linux要注意替换。
  6. make && make install
  • 到/tmp/ortp目录下查看移植好的库和头文件

RTP传输视频实战

  • 在官方SDK的sample中添加rtp传输代码
    • 在sample_comm_venc.c中的SAMPLE_COMM_VENC_MemConfig()函数之前添加如下代码
#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.100"

 

/**  初始化   

 *     

 *   主要用于对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_venc.c中的
VideoChn[2]    = {0,2};  ->  VideoChn[2]    = {2,0};

表示会先传输视频通道2,因为视频通道2是H.64协议的通道

  • 修改sample_venc.c中
SAMPLE_COMM_VENC_StartGetStream(VideoChn, 2);
->
SAMPLE_COMM_VENC_StartGetStream(VideoChn, 1);

表示只传输一个通道那就是H.264

  • 在sample_comm_venc.c中SAMPLE_COMM_VENC_GetVencStreamProc()添加
 #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.前面添加初始化ORTP的代码

  • LOCAL_HOST_IP :表示数据流推送的目的IP
  • 8080:我们打开电脑监视的IP
  • SAMPLE_COMM_VENC_SaveStream()中添加
	    #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

如果 开启了ORTP传输就把数据推送出去,而不写在本地文件夹

  • 复制 /tmp/otrp/文件夹到 mpp/include/文件夹下
  • 修改 up_linux.mak编译文件
从:
$(TARGET):$(COMM_OBJ) $(OBJS)
	@$(CC) $(CFLAGS) -lpthread -lm  -o $(TARGET_PATH)/$@ $^ -Wl,--start-group $(MPI_LIBS) $(SENSOR_LIBS) $(AUDIO_LIBA) $(REL_LIB)/libsecurec.a -Wl,--end-group
	$(waring $(cc))
至	
$(TARGET):$(COMM_OBJ) $(OBJS)
	@$(CC) $(CFLAGS) -lpthread -lm -lortp -o $(TARGET_PATH)/$@ $^ -L/tmp/ortp/lib -Wl,--start-group $(MPI_LIBS) $(SENSOR_LIBS) $(AUDIO_LIBA) $(REL_LIB)/libsecurec.a -Wl,--end-group
	$(waring $(cc))

添加了ORTP的so文件。让编译器找libortp.so文件

  • 执行make.生成sample_venc

  • 复制/tmp/ortp/lib 目下下的libortp.so,libortp.so.9,libortp.so.9.0.0到开发板的/usr/lib目录下

  • 复制刚刚生成的 sample_venc文件到开发板执行

  • 在windows端写一个VLC配置文件命名为demo.sdp

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

*用VLC打开demo.sdp 就可以看到开发板传递过来的图像了
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值