看到ORTP是純C實現(xiàn)的rtp庫,于是移植到3518e試用一下. 1.下載源碼里面有個tar res跳轉(zhuǎn)鏈接跳轉(zhuǎn)入 下載最新的ortp-0.23.0.tar.gz,并解壓 2.編譯./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.部署到開發(fā)板將編譯生成的庫/work/hi3518/ortp/lib/libortp.so.9復制到開發(fā)板/usr/lib中 4.添加ortp庫到mpp2中在海思SDK mpp2目錄下新建rtp目錄,將/work/hi3518/ortp/下全部內(nèi)容復制到該目錄下, 修改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函數(shù)完成的,這里只要修改該函數(shù)為封包發(fā)送即可。 下面是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以及其它參數(shù)進行初始化 * @param: char * ipStr 目的端IP地址描述串 * @param: iint port 目的端RTP監(jiān)聽端口 * @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的發(fā)送,釋放資源 * * @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; } /** 發(fā)送rtp數(shù)據(jù)包 * * 主要用于發(fā)送rtp數(shù)據(jù)包 * @param: RtpSession *session RTP會話對象的指針 * @param: const char *buffer 要發(fā)送的數(shù)據(jù)的緩沖區(qū)地址 * @param: int len 要發(fā)送的數(shù)據(jù)長度 * @return: int 實際發(fā)送的數(shù)據(jù)包數(shù)目 * @note: 如果要發(fā)送的數(shù)據(jù)包長度大于BYTES_PER_COUNT,本函數(shù)內(nèi)部會進行分包處理 */ 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); //如果數(shù)據(jù)小于MAX_RTP_PKT_LENGTH字節(jié),直接發(fā)送:單一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) { //切分為很多個包發(fā)送,每個包前要對頭進行處理,如第一個包 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; } 在實現(xiàn)調(diào)用前需要進行ortp加載初始化,我們在該文件中的函數(shù)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. ******************************************/ 注:這里為了簡便在程序中寫死了發(fā)送目標為129.1.4.196:8080,這要與下面的cfg.sdp對應. 然后修改SAMPLE_COMM_VENC_SaveH264函數(shù)調(diào)用rtp發(fā)送:/***************************************************************************** * 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加載到開發(fā)板并運行, #./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 96 a=rtpmap:96 H264/90000; a=decode_buf=300; a=framerate:25 c=IN IP4 129.1.4.196這里 129.1.4.196 即為 PC 的 IP , Port8080 為監(jiān)控 rtp 使用端口, payloadtype 為 96 ,即 h.264. VLC能夠正常播放,但有延時。
|
|