【转载】ORTP移植到Hi3518e,h.264封包rtp发送

【转载】原文地址: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中需要添加的部分:


[objc]  view plain copy
  1. #include <ortp/ortp.h>  
  2. #include <signal.h>  
  3. #include <stdlib.h>  
  4. #include <sys/types.h>  
  5. #include <sys/time.h>  
  6. #include <stdio.h>  
  7. #define Y_PLOAD_TYPE 96 //H.264  
  8. #define MAX_RTP_PKT_LENGTH 1400  
  9. #define DefaultTimestampIncrement 3600 //(90000/25)  
  10. uint32_t g_userts=0;  
  11. RtpSession *pRtpSession = NULL;  
  12. /**  初始化    
  13.  *      
  14.  *   主要用于对ortp以及其它参数进行初始化    
  15.  *   @param:  char * ipStr 目的端IP地址描述串    
  16.  *   @param:  iint port 目的端RTP监听端口    
  17.  *   @return:  RtpSession * 返回指向RtpSession对象的指针,如果为NULL,则初始化失败    
  18.  *   @note:       
  19.  */     
  20. RtpSession * rtpInit( char  * ipStr, int  port)  
  21. {  
  22.     RtpSession *session;   
  23.     char  *ssrc;  
  24.     printf("********oRTP for H.264 Init********\n");  
  25.   
  26.     ortp_init();  
  27.     ortp_scheduler_init();  
  28.     ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR);  
  29.     session=rtp_session_new(RTP_SESSION_SENDONLY);    
  30.   
  31.     rtp_session_set_scheduling_mode(session,1);  
  32.     rtp_session_set_blocking_mode(session,0);  
  33.     //rtp_session_set_connected_mode(session,TRUE);  
  34.     rtp_session_set_remote_addr(session,ipStr,port);  
  35.     rtp_session_set_payload_type(session,Y_PLOAD_TYPE);  
  36.   
  37.     ssrc=getenv("SSRC");  
  38.     if (ssrc!=NULL) {  
  39.         printf("using SSRC=%i.\n",atoi(ssrc));  
  40.         // 设置输出流的SSRC。不做此步的话将会给个随机值   
  41.         rtp_session_set_ssrc(session,atoi(ssrc));  
  42.     }  
  43.     return  session;  
  44. }  
  45. /**  结束ortp的发送,释放资源    
  46.  *      
  47.  *   @param:  RtpSession *session RTP会话对象的指针    
  48.  *   @return:  0表示成功    
  49.  *   @note:        
  50.  */      
  51. int  rtpExit(RtpSession *session)     
  52. {   
  53.     printf("********oRTP for H.264 Exit********\n");    
  54.     g_userts = 0;     
  55.          
  56.     rtp_session_destroy(session);     
  57.     ortp_exit();     
  58.     ortp_global_stats_display();     
  59.     
  60.      return  0;     
  61. }     
  62. /**  发送rtp数据包    
  63.  *      
  64.  *   主要用于发送rtp数据包    
  65.  *   @param:  RtpSession *session RTP会话对象的指针    
  66.  *   @param:  const char *buffer 要发送的数据的缓冲区地址    
  67.   *   @param: int len 要发送的数据长度    
  68.  *   @return:  int 实际发送的数据包数目    
  69.  *   @note:     如果要发送的数据包长度大于BYTES_PER_COUNT,本函数内部会进行分包处理    
  70.  */     
  71. int  rtpSend(RtpSession *session, char  *buffer,  int  len)  
  72. {    
  73.     int  sendBytes = 0;   
  74.     int status;         
  75.     uint32_t valid_len=len-4;  
  76.     unsigned char NALU=buffer[4];  
  77.        
  78.     //printf("send len=%d\n",len);  
  79.   
  80.     //如果数据小于MAX_RTP_PKT_LENGTH字节,直接发送:单一NAL单元模式  
  81.     if(valid_len <= MAX_RTP_PKT_LENGTH)  
  82.     {  
  83.         sendBytes = rtp_session_send_with_ts(session,  
  84.                                              &buffer[4],  
  85.                                              valid_len,  
  86.                                              g_userts);  
  87.         return sendBytes;  
  88.     }  
  89.     else if (valid_len > MAX_RTP_PKT_LENGTH)  
  90.     {  
  91.         //切分为很多个包发送,每个包前要对头进行处理,如第一个包  
  92.         valid_len -= 1;  
  93.         int k=0,l=0;  
  94.         k=valid_len/MAX_RTP_PKT_LENGTH;  
  95.         l=valid_len%MAX_RTP_PKT_LENGTH;  
  96.         int t=0;  
  97.         int pos=5;  
  98.         if(l!=0)  
  99.         {  
  100.             k=k+1;  
  101.         }  
  102.         while(t<k)//||(t==k&&l>0))  
  103.         {  
  104.             if(t<(k-1))//(t<k&&l!=0)||(t<(k-1))&&(l==0))//(0==t)||(t<k&&0!=l))  
  105.             {  
  106.                 buffer[pos-2]=(NALU & 0x60)|28;  
  107.                 buffer[pos-1]=(NALU & 0x1f);  
  108.                 if(0==t)  
  109.                 {  
  110.                     buffer[pos-1]|=0x80;  
  111.                 }  
  112.                 sendBytes = rtp_session_send_with_ts(session,  
  113.                                                      &buffer[pos-2],  
  114.                                                      MAX_RTP_PKT_LENGTH+2,  
  115.                                                      g_userts);  
  116.                 t++;  
  117.                 pos+=MAX_RTP_PKT_LENGTH;  
  118.             }  
  119.             else //if((k==t&&l>0)||((t==k-1)&&l==0))  
  120.             {  
  121.                 int iSendLen;  
  122.                 if(l>0)  
  123.                 {  
  124.                     iSendLen=valid_len-t*MAX_RTP_PKT_LENGTH;  
  125.                 }  
  126.                 else  
  127.                     iSendLen=MAX_RTP_PKT_LENGTH;  
  128.                 buffer[pos-2]=(NALU & 0x60)|28;  
  129.                 buffer[pos-1]=(NALU & 0x1f);  
  130.                 buffer[pos-1]|=0x40;  
  131.                 sendBytes = rtp_session_send_with_ts(session,  
  132.                                                      &buffer[pos-2],  
  133.                                                      iSendLen+2,  
  134.                                                      g_userts);  
  135.                 t++;  
  136.             }  
  137.         }  
  138.     }  
  139.   
  140.     g_userts += DefaultTimestampIncrement;//timestamp increase  
  141.     return  len;  
  142. }  

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

[objc]  view plain copy
  1. /***rtp init****/  
  2. pRtpSession = rtpInit( "129.1.4.196" ,8080);    
  3. if (pRtpSession==NULL)     
  4. {     
  5.     printf( "error rtpInit" );   
  6.     exit(-1);    
  7.     return  0;     
  8. }   
  9.   
  10. /****************************************** 
  11.  step 2:  Start to get streams of each channel. 
  12. ******************************************/  

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

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

[objc]  view plain copy
  1. /***************************************************************************** 
  2. * funciton : save H264 stream 
  3. ******************************************************************************/  
  4. HI_S32 SAMPLE_COMM_VENC_SaveH264(FILE* fpH264File, VENC_STREAM_S *pstStream)  
  5. {  
  6.     HI_S32 i;  
  7.   
  8.     for (i = 0; i < pstStream->u32PackCount; i++)  
  9.     {  
  10.         #if 0  
  11.         fwrite(pstStream->pstPack[i].pu8Addr[0],  
  12.                pstStream->pstPack[i].u32Len[0], 1, fpH264File);  
  13.   
  14.         fflush(fpH264File);  
  15.   
  16.         if (pstStream->pstPack[i].u32Len[1] > 0)  
  17.         {  
  18.             fwrite(pstStream->pstPack[i].pu8Addr[1],  
  19.                    pstStream->pstPack[i].u32Len[1], 1, fpH264File);  
  20.   
  21.             fflush(fpH264File);  
  22.         }  
  23.         #else  
  24.         rtpSend(pRtpSession,  
  25.                 pstStream->pstPack[i].pu8Addr[0],  
  26.                 pstStream->pstPack[i].u32Len[0]);  
  27.         if (pstStream->pstPack[i].u32Len[1] > 0)  
  28.         {  
  29.             rtpSend(pRtpSession,  
  30.                     pstStream->pstPack[i].pu8Addr[1],  
  31.                     pstStream->pstPack[i].u32Len[1]);  
  32.         }  
  33.         #endif  
  34.     }  
  35.       
  36.     return HI_SUCCESS;  
  37. }  

这样编译获得 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如下:

[plain]  view plain copy
  1. m=video 8080 RTP/AVP 96  
  2. a=rtpmap:96 H264/90000;  
  3. a=decode_buf=300;  
  4. a=framerate:25  
  5. c=IN IP4 129.1.4.196  
这里 129.1.4.196 即为 PC IP Port8080 为监控 rtp 使用端口, payloadtype 96 ,即 h.264.

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值