ORTP移植到Hi3518e,h.264封包rtp发送

来源:互联网 发布:python rawurlencode 编辑:程序博客网 时间:2024/06/06 00:48

转自:http://blog.csdn.net/jiaozi07/article/details/41749943


看到ORTP是纯C实现的rtp库,于是移植到3518e试用一下.

1.下载源码

http://www.linphone.org/technical-corner/ortp/downloads

里面有个tar res跳转链接跳转入

http://download.savannah.gnu.org/releases/linphone/ortp/sources/


下载最新的ortp-0.23.0.tar.gz,并解压

2.编译

之前露写了h.264类型的添加,即需先修改src/avprofile.c文件中av_profile_init函数,在最后添加上:

rtp_profile_set_payload(profile,96,&payload_type_h264);

这里的96也就是为h.264指定的负载类型,也就是后面rtp_session_set_payload_type需要设置的类型,以及VLC配置文件中的类型,这样就支持了H.264协议.然后在配置编译如下:

./configure --prefix=/work/hi3518/ortp --host=arm-hisiv100nptl-linux

make

make install

配置只需指定安装目录prefix,编译平台host即可,这里host直接赋值arm-hisiv100nptl-linux-gcc前缀即可,注意不是arm-hisiv100nptl-linux-而是arm-hisiv100nptl-linux。

3.部署到开发板

将编译生成的库/work/hi3518/ortp/lib/libortp.so.9复制到开发板/usr/lib

4.添加ortp库到mpp2

在海思SDK mpp2目录下新建rtp目录,将/work/hi3518/ortp/下全部内容复制到该目录下,

修改mpp2/sample/Makefile.param,添加:

INC_FLAGS += -I$(MPP_PATH)/rtp/include -L$(MPP_PATH)/rtp/lib/ -lortp

5.修改代码

示例程序venc中有将视频进行264编码并保存为文件(nfs挂载),这里一步步分析sample_venc.c即可找到最终的保存是通过sample_comm_venc.c中的SAMPLE_COMM_VENC_SaveH264函数完成的,这里只要修改该函数为封包发送即可。

下面是sample_comm_venc.c中需要添加的部分:

#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;/**  初始化    *      *   主要用于对ortp以及其它参数进行初始化    *   @param:  char * ipStr 目的端IP地址描述串    *   @param:  iint 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];         //printf("send len=%d\n",len);    //如果数据小于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);        return sendBytes;    }    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;}


在实现调用前需要进行ortp加载初始化,我们在该文件中的函数SAMPLE_COMM_VENC_GetVencStreamProc中添加初始化即可:

    /***rtp init****/    pRtpSession = rtpInit( "129.1.4.196" ,8080);      if (pRtpSession==NULL)       {           printf( "error rtpInit" );         exit(-1);          return  0;       }     /******************************************     step 2:  Start to get streams of each channel.    ******************************************/


注:这里为了简便在程序中写死了发送目标为129.1.4.196:8080,这要与下面的cfg.sdp对应.

然后修改SAMPLE_COMM_VENC_SaveH264函数调用rtp发送:

/****************************************************************************** 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 0        fwrite(pstStream->pstPack[i].pu8Addr[0],               pstStream->pstPack[i].u32Len[0], 1, fpH264File);        fflush(fpH264File);        if (pstStream->pstPack[i].u32Len[1] > 0)        {            fwrite(pstStream->pstPack[i].pu8Addr[1],                   pstStream->pstPack[i].u32Len[1], 1, fpH264File);            fflush(fpH264File);        }        #else        rtpSend(pRtpSession,                pstStream->pstPack[i].pu8Addr[0],                pstStream->pstPack[i].u32Len[0]);        if (pstStream->pstPack[i].u32Len[1] > 0)        {            rtpSend(pRtpSession,                    pstStream->pstPack[i].pu8Addr[1],                    pstStream->pstPack[i].u32Len[1]);        }        #endif    }        return HI_SUCCESS;}

这样编译获得 sample_venc.

6.运行

sample_venc加载到开发板并运行,

#./sample_venc 0

please press twice ENTER to exit this sample

********oRTP for H.264 Init********

Av profile add H.264

ortp-message-Setting random local addresses.

ortp-message-rtp session [0x1c95758] set to rtp [129.1.4.196:8080] rtcp [129.1.4.196:8081]

ortp-message-Using permissive algorithm

ortp-message-Sending RTCP SR compound message on session [0x1c95758].

ortp-message-Sending RTCP SR compound message on session [0x1c95758].

......

7.VLC播放

PC端使用VLC来播放,编写cfg.sdp如下:

m=video 8080 RTP/AVP 96a=rtpmap:96 H264/90000;a=decode_buf=300;a=framerate:25c=IN IP4 129.1.4.196

这里129.1.4.196即为PCIPPort8080为监控rtp使用端口,payloadtype96,即h.264.

VLC能够正常播放,但有延时。



0 0