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,出現了一堆錯誤,然後需要一一解決。錯誤1:./autogen.sh: line 44: libtoolize: command not found
解決:sudo apt-get install libtool*
錯誤2:libtoolize: error: Please install GNU M4, or 'export M4=/path/to/gnu/m4'.解決:sudo apt-get install m4
錯誤3:Automake - aclocal: command not found解決:sudo apt-get install automake
(2)繼續執行./configure --prefix=/tmp/ortp --host=arm-hisiv300-linux
(3)最後執行 make && make install。
到/tmp/ortp目錄下查看移植好的庫和頭文件,這樣就說明編譯完成了。5、添加代碼
在官方SDK的sample中添加rtp傳輸代碼
(1)venc/sample_venc.c中SAMPLE_VENC_1080P_CLASSIC函數中,添加:s32ChnNum = 1;這裏主要是因爲,我們只是單純的做網絡傳輸,所以用到一路就可以了。(2)common/sample_common_venc.c中,改了很多
#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"
/** 初始化
*
* 主要用於對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,所以windows的網卡地址要設置成這個。
將之前編譯好的lib庫拷貝到nfs文件系統裏面。然後在串口終端那邊拷貝到開發板文件系統/usr/lib中。
(1)部署libortp.so到開發板中/usr/lib目錄下
(2)檢查開發板中原有配置是否正確,譬如sensor是否對應實際
(3)在nfs中運行新的sample程序
(4)vlc中打開配置好的sdp文件,看到實時圖像就證明整個實驗完成了