当前位置: 首页 > news >正文

朱老师, 3518e系列,第三季

第一节: ORTP 引入。

1、传输的协议: http, ftp , rtp , rtsp .

2、 ORTP 是C实现的 RTP 库,实质是一个 服务器。

3、 实现局域网传输。

第二节: ORTP 库的移植。

1、 下载+解压。

下载网址。

GitHub - dmonakhov/ortp: mirror of linphone's git tree

上传加解压。

2、 修改源码

主要是增加 h264 的支持。

路径: src/avprofile.c

3、 编译。

注意: 我这里的编译 是在  hi3516cv610 的环境中编译的。

   53  ./autogen.sh54  ./configure --prefix=./tmp/install --host=arm-linux-musleabi55  ./configure --prefix=/home/topeet/source_code/ortp-master/tmp/install --host=arm-linux-musleabi

有报错:

  CC       payloadtype.loCC       rtpprofile.loCC       rtcp.lo
In function 'rtcp_app_init',inlined from 'rtp_session_send_rtcp_APP' at rtcp.c:439:13:
rtcp.c:352:2: error: 'strncpy' specified bound 4 equals destination size [-Werror=stringop-truncation]352 |  strncpy(app->name,name,4);|  ^~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[3]: *** [Makefile:589: rtcp.lo] Error 1
make[3]: Leaving directory '/home/topeet/source_code/ortp-master/src'
make[2]: *** [Makefile:608: all-recursive] Error 1
make[2]: Leaving directory '/home/topeet/source_code/ortp-master/src'
make[1]: *** [Makefile:530: all-recursive] Error 1
make[1]: Leaving directory '/home/topeet/source_code/ortp-master'
make: *** [Makefile:414: all] Error 2
root@topeet:/home/topeet/source_code/ortp-master#
stun.c: In function 'stunCalculateIntegrity_longterm':
stun.c:1275:4: error: 'strncpy' output truncated before terminating nul copying 20 bytes from a string of the same length [-Werror=stringop-truncation]1275 |    strncpy(hmac,"hmac-not-implemented",20);|    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stun.c: In function 'stunCalculateIntegrity_shortterm':
stun.c:1280:4: error: 'strncpy' output truncated before terminating nul copying 20 bytes from a string of the same length [-Werror=stringop-truncation]1280 |    strncpy(hmac,"hmac-not-implemented",20);|    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[3]: *** [Makefile:589: stun.lo] Error 1
make[3]: Leaving directory '/home/topeet/source_code/ortp-master/src'
make[2]: *** [Makefile:608: all-recursive] Error 1
make[2]: Leaving directory '/home/topeet/source_code/ortp-master/src'
make[1]: *** [Makefile:530: all-recursive] Error 1
make[1]: Leaving directory '/home/topeet/source_code/ortp-master'
make: *** [Makefile:414: all] Error 2

解决:

make clean   
./configure --prefix=/home/topeet/source_code/ortp-master/tmp/install --host=arm-linux-musleabi CFLAGS="-Wno-error=array-bounds" CFLAGS="-Wno-stringop-truncation"
make 
make install 

编译成功。

第三节: RTP 传输视频实战。

1、 在 SDK sample 中 添加 rtp 传输的代码。

首先是   Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/sample_venc.c 文件。

视频中  添加了 s32ChnNum 等于1 , 就是 压缩生成一路视频,原来是 生成了三路视频。

但是  这里我就不改了。

然后是,Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/sample_comm_venc.c  文件,

这个文件主要设计到 对 ortp 服务器的 改动。

在 第一个 函数开始之前添加。

#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;}elseiSendLen=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 increasereturn  len;
}
#endif

这段添加 , 我跟 视频中的添加 是一样的。

然后还在 在这个文件中添加。

视频中添加的是  S32 SAMPLE_COMM_VENC_SaVeH264  这个函数。

但是我不应该添加这个函数。

我添加的地方是。  sample_comm_venc_save_stream  这个函数。

     7 td_s32 sample_comm_venc_save_stream(FILE *fd, ot_venc_stream *stream)6 {5     td_u32 i;43     for (i = 0; i < stream->pack_cnt; i++) {2        #if ORTP_ENABLE1         rtpSend(pRtpSession,pstStream->pstPack[i].pu8Addr, pstStream->pstPack[i].u32Len);659         #else1         (td_void)fwrite(stream->pack[i].addr + stream->pack[i].offset,2                         stream->pack[i].len - stream->pack[i].offset, 1, fd);3         (td_void)fflush(fd);4        #endif5     }67     return TD_SUCCESS;8 }9

然后还要再这个 文件中改一个地方,

视频中是这个文件, SAMPLE_COMM_VENC_GetVencStreamProc(HI VOID *p)  。

我自己的改的是这个文件,

     7 static td_s32 sample_comm_get_stream_from_one_channl(sample_comm_venc_stream_proc_info *stream_proc_info, td_s32 index,6     ot_venc_stream_buf_info *stream_buf_info, ot_payload_type *payload_type)5 {4     td_s32 ret;3     ot_venc_stream stream;2     ot_venc_chn_status stat;127961    #if ORTP_ENABLE2     /***rtp init****/3     pRtpSession = rtpInit( LOCAL_HOST_IP ,8080);4     if (pRtpSession==NULL)5     {6         printf( "error rtpInit" );7         exit(-1);8         return  0;9     }10     #endif111213     /* step 2.1 : query how many packs in one-frame stream. */14     if (memset_s(&stream, sizeof(stream), 0, sizeof(stream)) != EOK) {15         printf("call memset_s error\n");16     }1718     ret = ss_mpi_venc_query_status(index, &stat);19     if (ret != TD_SUCCESS) {20         sample_print("ss_mpi_venc_query_status chn[%d] failed with %#x!\n", index, ret);21         return SAMPLE_RETURN_BREAK;22     }2324     if (stat.cur_packs == 0) {25         sample_print("NOTE: current  frame is TD_NULL!\n");26         return SAMPLE_RETURN_CONTINUE;27     }

到这里 就改完了。

2、 从新编译sample

首先是, ortp 头文件的复制。

ortp 库的链接。

我自己是这个添加的,因为我没有 找到 头文件的设置,直接再 make 中添加的。

修改的文件是,Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/smp_linux.mak

   1413 # target source12 OBJS  := $(SMP_SRCS:%.c=%.o)1110 CFLAGS += $(COMM_INC)98 MPI_LIBS += $(LIBS_LD_CFLAGS)76 .PHONY : clean all54 all: $(TARGET)32 $(TARGET):$(COMM_OBJ) $(OBJS)1     @$(CC) $(CFLAGS) -o $(TARGET_PATH)/$@ $^ -Wl,--start-group $(MPI_LIBS) $(SENSOR_LIBS) $(AUDIO_LIBA) $(REL_LIB)/libsecurec.a -I/home/topeet/source_code/ortp-master/tmp/install/includ      e/ -L/home/topeet/source_code/ortp-master/tmp/install/lib -lortp  -lm -lc -Wl,--end-group151 clean:2     @rm -f $(TARGET_PATH)/$(TARGET)3     @rm -f $(OBJS)4     @rm -f $(COMM_OBJ)56 cleanstream:7     @rm -f *.h2648     @rm -f *.h2659     @rm -f *.jpg10     @rm -f *.mjp11     @rm -f *.mp4
~

编译测试一下看看。

有报错

_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -DVER_X=1 -DVER_Y=0 -DVER_Z=0 -DVER_P=0 -DVER_B=10 -DUSER_BIT_32 -DKERNEL_BIT_32 -DOT_RELEASE -Wno-date-time -DSENSOR0_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DSENSOR1_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DBOARD_TYPE=DMEB_QFN -DOT_ACODEC_TYPE_INNER -DOT_VQE_USE_STATIC_MODULE_REGISTER -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../audio/adp   -c -o /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common/sample_comm_venc.o /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common/sample_comm_venc.c
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common/sample_comm_venc.c:45:10: fatal error: ortp/ortp.h: No such file or directory45 | #include <ortp/ortp.h>|          ^~~~~~~~~~~~~
compilation terminated.

解决:

我一共做了 三次 makfile 的修改。

首先是 common/  目录下, 因为源文件再这个目录。

目录下的makefile 成了 这样。

param_file=$(realpath $(dir $(firstword $(MAKEFILE_LIST))))/../Makefile.param
include $(param_file)
DEF_FLAGS := _GNU_SOURCE
#topeet wang  added
WFLAGS += -I/home/topeet/source_code/ortp-master/tmp/install/include
WCOMM_INC += -L/home/topeet/source_code/ortp-master/tmp/install/lib
.PHONY : clean all
all:$(COMM_OBJ)clean:@rm $(COMM_OBJ) -f%.o:%.c@$(CC) $(COMM_INC) $(CFLAGS)  $(WFLAGS) $(WCOMM_INC) -c $< -o $@ -lortp

然后是 sample 目录下的, makefile.param

这是我的添加。

    9 INC_FLAGS := -I$(REL_INC)8 INC_FLAGS += -I$(REL_INC)7 INC_FLAGS += -I$(SDK_PATH)/$(EXTDRV)/es838865 ISP_VERSION := ISP_V243 CFLAGS += -Wall $(INC_FLAGS) -D$(OT_ARCH) -D$(OT_FPGA) -D$(ISP_VERSION)21 #topeet wang added94  CFLAGS += -I/home/topeet/source_code/ortp-master/tmp/install/include1 CFLAGS += -L/home/topeet/source_code/ortp-master/tmp/install/lib2345 CFLAGS += -lstdc++6 ifneq ($(CONFIG_LLVM), y)7 CFLAGS += -lpthread -lm -ldl8 endif9 CFLAGS += $(LIBS_CFLAGS)10 CFLAGS += $(LIBS_EXEC_CFLAGS)11 CFLAGS += $(MPP_CFLAGS)12 CFLAGS += -DSENSOR0_TYPE=$(SENSOR0_TYPE)13 CFLAGS += -DSENSOR1_TYPE=$(SENSOR1_TYPE)14 CFLAGS += -DBOARD_TYPE=$(BOARD_TYPE)15

然后是 sample 下的 smp_linux_mk

1312 # target source11 OBJS  := $(SMP_SRCS:%.c=%.o)109 CFLAGS += $(COMM_INC)87 MPI_LIBS += $(LIBS_LD_CFLAGS)65 .PHONY : clean all43 all: $(TARGET)21 $(TARGET):$(COMM_OBJ) $(OBJS)14      @$(CC) $(CFLAGS) -o $(TARGET_PATH)/$@ $^ -Wl,--start-group $(MPI_LIBS) $(SENSOR_LIBS) $(AUDIO_LIBA) $(REL_LIB)/libsecurec.a -lortp  -lm -lc -Wl,--end-group12 clean:3     @rm -f $(TARGET_PATH)/$(TARGET)4     @rm -f $(OBJS)5     @rm -f $(COMM_OBJ)67 cleanstream:8     @rm -f *.h2649     @rm -f *.h26510     @rm -f *.jpg11     @rm -f *.mjp12     @rm -f *.mp4
~
~
~
~

目前 我编译 整个sample 的话,会报错。

~~~~~~~~~~Start build bcd~~~~~~~~~~
make[1]: Entering directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/bcd'
arm-v01c02-linux-musleabi-gcc -DSC4336P_MIPI_4M_30FPS_10BIT_SELECT=y -DSC4336P_MIPI_4M_30FPS_10BIT_SELECT=y -Wall -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/vendor/extdrv/es8388 -Dhi3516cv610 -DOT_XXXX -DISP_V2 -I/home/topeet/source_code/ortp-master/tmp/install/include -L/home/topeet/source_code/ortp-master/tmp/install/lib -lstdc++ -lpthread -lm -ldl -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fsigned-char -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/osal/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/platform/securec/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -fstack-protector-strong -fPIC -ffunction-sections -fdata-sections -Os -mthumb -fno-aggressive-loop-optimizations -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -fPIE -pie -s -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fsigned-char -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/osal/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/platform/securec/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -DVER_X=1 -DVER_Y=0 -DVER_Z=0 -DVER_P=0 -DVER_B=10 -DUSER_BIT_32 -DKERNEL_BIT_32 -DOT_RELEASE -Wno-date-time -DSENSOR0_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DSENSOR1_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DBOARD_TYPE=DMEB_QFN -DOT_ACODEC_TYPE_INNER -DOT_VQE_USE_STATIC_MODULE_REGISTER -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/bcd/../common -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/bcd/../audio/adp   -c -o sample_bcd.o sample_bcd.c
make[1]: Leaving directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/bcd'
~~~~~~~~~~Start build calcflicker~~~~~~~~~~
make[1]: Entering directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/calcflicker'
arm-v01c02-linux-musleabi-gcc -DSC4336P_MIPI_4M_30FPS_10BIT_SELECT=y -DSC4336P_MIPI_4M_30FPS_10BIT_SELECT=y -Wall -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/vendor/extdrv/es8388 -Dhi3516cv610 -DOT_XXXX -DISP_V2 -I/home/topeet/source_code/ortp-master/tmp/install/include -L/home/topeet/source_code/ortp-master/tmp/install/lib -lstdc++ -lpthread -lm -ldl -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fsigned-char -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/osal/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/platform/securec/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -fstack-protector-strong -fPIC -ffunction-sections -fdata-sections -Os -mthumb -fno-aggressive-loop-optimizations -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -fPIE -pie -s -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fsigned-char -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/osal/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/platform/securec/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -DVER_X=1 -DVER_Y=0 -DVER_Z=0 -DVER_P=0 -DVER_B=10 -DUSER_BIT_32 -DKERNEL_BIT_32 -DOT_RELEASE -Wno-date-time -DSENSOR0_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DSENSOR1_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DBOARD_TYPE=DMEB_QFN -DOT_ACODEC_TYPE_INNER -DOT_VQE_USE_STATIC_MODULE_REGISTER -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/calcflicker/../common -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/calcflicker/../audio/adp   -c -o /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/calcflicker/sample_calcflicker.o /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/calcflicker/sample_calcflicker.c
make[1]: Leaving directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/calcflicker'
~~~~~~~~~~Start build fast_ae~~~~~~~~~~
make[1]: Entering directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae'
arm-v01c02-linux-musleabi-gcc -DSC4336P_MIPI_4M_30FPS_10BIT_SELECT=y -DSC4336P_MIPI_4M_30FPS_10BIT_SELECT=y -Wall -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/vendor/extdrv/es8388 -Dhi3516cv610 -DOT_XXXX -DISP_V2 -I/home/topeet/source_code/ortp-master/tmp/install/include -L/home/topeet/source_code/ortp-master/tmp/install/lib -lstdc++ -lpthread -lm -ldl -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fsigned-char -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/osal/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/platform/securec/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -fstack-protector-strong -fPIC -ffunction-sections -fdata-sections -Os -mthumb -fno-aggressive-loop-optimizations -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -fPIE -pie -s -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fsigned-char -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/osal/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/platform/securec/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -DVER_X=1 -DVER_Y=0 -DVER_Z=0 -DVER_P=0 -DVER_B=10 -DUSER_BIT_32 -DKERNEL_BIT_32 -DOT_RELEASE -Wno-date-time -DSENSOR0_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DSENSOR1_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DBOARD_TYPE=DMEB_QFN -DOT_ACODEC_TYPE_INNER -DOT_VQE_USE_STATIC_MODULE_REGISTER -static -ffunction-sections -fdata-sections -Wl,--gc-sections -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae/../common -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae/../audio/adp   -c -o /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae/sample_fast_ae.o /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae/sample_fast_ae.c
arm-v01c02-linux-musleabi-gcc -DSC4336P_MIPI_4M_30FPS_10BIT_SELECT=y -DSC4336P_MIPI_4M_30FPS_10BIT_SELECT=y -Wall -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/vendor/extdrv/es8388 -Dhi3516cv610 -DOT_XXXX -DISP_V2 -I/home/topeet/source_code/ortp-master/tmp/install/include -L/home/topeet/source_code/ortp-master/tmp/install/lib -lstdc++ -lpthread -lm -ldl -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fsigned-char -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/osal/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/platform/securec/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -fstack-protector-strong -fPIC -ffunction-sections -fdata-sections -Os -mthumb -fno-aggressive-loop-optimizations -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -fPIE -pie -s -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fsigned-char -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/osal/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/platform/securec/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -DVER_X=1 -DVER_Y=0 -DVER_Z=0 -DVER_P=0 -DVER_B=10 -DUSER_BIT_32 -DKERNEL_BIT_32 -DOT_RELEASE -Wno-date-time -DSENSOR0_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DSENSOR1_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DBOARD_TYPE=DMEB_QFN -DOT_ACODEC_TYPE_INNER -DOT_VQE_USE_STATIC_MODULE_REGISTER -static -ffunction-sections -fdata-sections -Wl,--gc-sections -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae/../common -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae/../audio/adp   -c -o /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae/sc4336p_sensor_init.o /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae/sc4336p_sensor_init.c
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musleabi/bin/ld: cannot find -lortp: No such file or directory
collect2: error: ld returned 1 exit status
make[1]: *** [/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae/../smp_linux.mak:14: sample_fast_ae] Error 1
make[1]: Leaving directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/fast_ae'
make: *** [Makefile:31: fast_ae] Error 2

这意思是 我编译 某个 目录的话,编译不成功。

但是 我测试 , common 目录 + venc 目录可以编译成功,

具体原因不清楚,可能与 因为是动态链接有关系, 因为有的 文件,依赖 common 文件夹。

报错也是 ld 的错误,而不是 gcc 的错误。

先不管了,先测试。

3、将编译出来的 ortp 的源码 拷贝到 开发板。

将Lib 库中的 so 文件 全部拷贝到 开发板的 usr/lib 目录下。

运行程序后有报错。

如果是 不运行 uvc 摄像头的程序的话,是这个报错。

~ # ./sample_venc 0
open sys: No such file or directory
sample_comm_vpss_get_wrap_cfg: get buf line failed
open sys: No such file or directory
open err
: No such file or directory
open err
: No such file or directory
[sample_comm_sys_init_with_vb_supplement]-289: ss_mpi_vb_set_conf failed!
[sample_venc_online_wrap_sys_init]-999: sample_venc_sys_init failed!
open sys: No such file or directory
[sample_comm_vi_set_vi_vpss_mode]-871: set vi vpss mode failed!
open sys: No such file or directory
open err
: No such file or directory
[sample_venc_online_wrap_start_sys_vi_vpss]-1093: Init SYS err for 0xffffffff!
program exit abnormally!
~ #

运行 uvc 程序之后 是这个报错。

~ # ./sample_venc 0
wrap online is 1, buf line is 128, buf size is 458544[MPP] Version: [HI3516CV610_MPP_V1.0.1.0 B040 Release], Build Time[Sep  7 2024, 17:51:12]linear mode
===================================================================================
vi_pipe:0,== SC4336P_MIPI_27Minput_2lane_10bit_630Mbps_2560x1440_30fps Init OK! ==
===================================================================================
ISP Dev 0 running !
please input choose gop mode!0) normal p.1) dual p.2) smart p.
random: crng init done
0
please input choose rc mode!c) cbr.v) vbr.b) abr.a) avbr.x) cvbr.q) qvbr.f) fix_qp
c
********oRTP for H.264 Init********
please press twice ENTER to exit this sample
ortp-message-Setting random local addresses.
ortp-message-Using permissive algorithm
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23
ortp-warning-Error sending rtp packet: Network unreachable ; socket=23

但是 感觉这个报错 应该好改。

目前 更改了应用程序的ip , VLC的ip

可以出图了,但是 画面看不清。

结果是这样的。

第四节 , ortp 的源码的分析一:

ORTP 是一个 开源库,

里面有一个test 目录。

就从 测试 案例入手。

ortp  实现了 rtp , rtcp 协议。

rtp 负责传输。

rtcp 负责 控制。

首先找到 main 函数。

然后看一下 ortp_init()函数

这个函数 最重要的是 av_profile_init,  这里面 有各种压缩协议。

ortp_global_stats_reset , 初始化了全局变量,就是清零。

init_random_number_generator, 这是一个 随机数发生器。

然后是  ortp_scheduler_init 函数。

这个函数是一个定时器,时间到了 ,这里就是对定时器的初始化。

就会轮流执行 session.

一个session 就是一个 网络链接。

这里就开始 创建会话了。

rtp_session_new , 创建了一个session, 并且 初始化了 这个结构体。

下面的这几句,依然是在对 结构体的设置。

这里, SSRC 的目的是为了是 接收端,区分出不同的session。

这个变量可有可无,就看你 是不是需要 拿出一包数据,并且想知道 这包数据是哪个session 的。

这里 fopen 打开的是一个文件。

signal ,这里再定义一个 信号的 回调函数。

fread 这里 读一次 发一次。

rtp_session_send_with_ts  是发送函数。

这里 rtp_session_create_packet, 会创建好, packet,  就是再信息上加上头。

rtp_session_sendm_with_ts , 最终会 调用 sendto 函数 使用 socket 发送出去。

utils.c 实现了双向链表。

str_util.c 实现了队列的管理。

rtpparse.c rtcpparse.c 实现了 ortp 的 解包。

jitterctrl.c 实现了 jitter buffer 的防抖,因为再 3G  , wifi 环境下容易断链 , 通过 防抖实现 音视频的传输的平滑。

默认的延时是比较大的, 如果要想修改成延时小的,就要 修改这些 数据结构。

但是我暂时不去看这些。

第六节, ORTP的发送实验的源码的  解析一  +   解析二。

sample_venc.c   他改的 是编码的通道, 改的是 s32ChnNum 的值。

改动的主要地方 在文件 sample_comm_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;}elseiSendLen=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 increasereturn  len;
}
#endif

这里 添加了一个 宏定义, ORTP_ENABLE ,  只要设置为0 , 所有的代码就不执行了。可以学习一下这个。

主要的函数有 rtpinit() , rtpexit() , rtpsend()

然后 在 getvencstream 中 添加了  rtpinit .

看看 rtpinit() .

ortP_init()  , 分配 结构体,并对结构体 赋初值。

ortp_scheduler_init(), 初始化了一个定时器。用于不同的session 的调度。

rtp_session_new, 创建了一个session, 只是 用于发送。

rtp_session_set_scheduling_mode ,   就是 决定 是否 使用这种调度。

这里 注释掉了 rtp_session_set_connected_mode , 它的作用是, 使用 udp 还是 tcp, 默认应该是 udp.

rtp_session_set_remote-addr , 这是在设置 发送目的地的 ip+端口。

rtp_session_set_payloard_type ,这是在配置 264 的格式。

rtp_sessoin_set_ssrc , 在对 SSRC进行配置。

然后还在 函数  sample_comm_venc_saveh264 函数中 做了修改。

/******************************************************************************
* 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 ORTP_ENABLErtpSend(pRtpSession,pstStream->pstPack[i].pu8Addr, pstStream->pstPack[i].u32Len);#elsefwrite(pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset, 1, fpH264File);fflush(fpH264File);#endif}return HI_SUCCESS;
}

这里 主要就是 把 本来应该 写到 文件里的内容 , 通过socket 发送出去了。

之所以 在 fwrite 的时候 多了个 pstStream->pstPack[i].u32Offset  这个 offset 是因为, 对于文件,每次写, 都要移动 指针,否则会覆盖, 但是 socket 发送就不用了。

关键的函数是 rtpsend 函数。

 
/**  发送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;}elseiSendLen=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 increasereturn  len;
}

这个函数 主要考虑了  包的拆开发送。

这里发送的长度最大是 MAX_RTP_PKT_LENGTH

这里的 1400 是经验值, 如果网络好,就可以大一点,如果网络不好就要小一点,如果丢包了,还可以重传。

这里 为什么是 buffer[4] 呢, 因为,如果是 一包不到最大值的话,那么就不需要 NAL了, NAL 正好是 4个字节。

对于需要拆包的包,就到了这个循环。 这里主要在计算 有几个完整的包, 最后剩下了几个字节。

这里 如果是 分包了, 那么就要加上 NAL了, NAL是一个字节的长度。加上 两个NAL。

NAL 具体的 位定义 先不去管。

NAL & 60 | 28 , 这里就是 设置了优先级, 并且 设置了 h264

NAL & 0x1f , 这里 是保存了 最原始的 NAL。

一共添加了 两个NAL。

总结:

在buffer 中, 

buffer[0], buffer[1],buffer[2],buffer[3]  。

buffer[4] 。

他发送 是 从 buffer[3] 开始发送的。

这里理解的有些乱, 先过。

最终使用 rtp_session_send_with_ts 发送出去。

这里是在操作 最后 剩下的 一个包。

这里对 buffer[pos-1 ] 操作了两次,

看来只要 对 后5位 保持原装就可以了。

第八节, vlc 的使用。

主要是 sdp 文件的配置。

这里需要注意, 114 ,是 ortp 的 发送目的的ip , 这里的 vlc 有点 截流的意思。

第九节, 这里就是 我自己在 3516  的SDK 中的改动了。

依然是使用的是 ortp .

改动如下。

sample_venc.c 中 并没有做改动。

所有的改动 都在  sample_comm_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;}elseiSendLen=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 increasereturn  len;
}
#endif

然后再 save_stream 中添加这些。

    23 td_s32 sample_comm_venc_save_stream(FILE *fd, ot_venc_stream *stream)22 {21     td_u32 i;2019     for (i = 0; i < stream->pack_cnt; i++) {18        #if ORTP_ENABLE17         rtpSend(pRtpSession,stream->pack[i].addr, stream->pack[i].len);16        #else15         (td_void)fwrite(stream->pack[i].addr + stream->pack[i].offset,14                         stream->pack[i].len - stream->pack[i].offset, 1, fd);13         (td_void)fflush(fd);12        #endif11     }109     return TD_SUCCESS;8 }7

然后再 save_stream 中 添加 rtpsend, 取代写文件。

     1 td_s32 sample_comm_venc_save_stream(FILE *fd, ot_venc_stream *stream)2 {3     td_u32 i;45     for (i = 0; i < stream->pack_cnt; i++) {6        #if ORTP_ENABLE7         rtpSend(pRtpSession,stream->pack[i].addr, stream->pack[i].len);8        #else9         (td_void)fwrite(stream->pack[i].addr + stream->pack[i].offset,10                         stream->pack[i].len - stream->pack[i].offset, 1, fd);11         (td_void)fflush(fd);12        #endif13     }1415     return TD_SUCCESS;16 }17

比较关键的还有这一条。 如果 既有 h264, 又有 h265的话, 会将两种压缩的pack 都发出去,这跟我的 rtpsend 的添加的位置有关.

这里如果 我 不去掉 h265 的话,就会出现前面的 虽然传输成功,但是 花屏的 效果,会有前面的传输的报错。

所以 这里 就使能了一路 venc

    22 static td_void sample_comm_fd_isset(sample_comm_venc_stream_proc_info *stream_proc_info, fd_set *read_fds,21     ot_venc_stream_buf_info *stream_buf_info, ot_payload_type *payload_type, sample_venc_getstream_para *para)20 {19     td_s32 i, ret;1817 //    for (i = 0; (i < stream_proc_info->chn_total) && (i < OT_VENC_MAX_CHN_NUM); i++) {16     //15 //topeet wang added14     for (i = 1; (i < stream_proc_info->chn_total) && (i < OT_VENC_MAX_CHN_NUM); i++) {13         if (FD_ISSET(stream_proc_info->venc_fd[i], read_fds)) {12             stream_proc_info->venc_chn = para->venc_chn[i];11             ret = sample_comm_get_stream_from_one_channl(stream_proc_info, i, stream_buf_info, payload_type);10             if (ret == SAMPLE_RETURN_CONTINUE) {9                 continue;8             } else if (ret == SAMPLE_RETURN_BREAK) {7                 break;6             }5         }4     }3 }2

编译+烧写,

再编译的时候, 会有报错,参考前面的 记录。

然后再次执行

~ # ./sample_venc 0
wrap online is 1, buf line is 128, buf size is 458544[MPP] Version: [HI3516CV610_MPP_V1.0.1.0 B040 Release], Build Time[Sep  7 2024, 17:51:12]linear mode
===================================================================================
vi_pipe:0,== SC4336P_MIPI_27Minput_2lane_10bit_630Mbps_2560x1440_30fps Init OK! ==
===================================================================================
ISP Dev 0 running !
please input choose gop mode!0) normal p.1) dual p.2) smart p.
0
please input choose rc mode!c) cbr.v) vbr.b) abr.a) avbr.x) cvbr.q) qvbr.f) fix_qp
c
********oRTP for H.264 Init********
ortp-message-Setting random local addresses.
ortp-message-Using permissive algorithm
please press twice ENTER to exit this sample
^C^Cprogram exit normally!
~ #

vlc 的配置。

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

便可以 出图。

问题依然是延迟比较严重。

但是 不管它,反正 通了。

http://www.xdnf.cn/news/450091.html

相关文章:

  • 【Python】杂乱-[代码]Python 替换字符串中相关字符的方法
  • 容器安全-核心概述
  • OpenCV人脸识别LBPH算法原理、案例解析
  • Codeforces Round 1003 (Div. 4)
  • 分布式一致性协议Raft
  • 动物乐园-第16届蓝桥第5次STEMA测评Scratch真题第5题
  • 11-SGM41299-TEC驱动芯片--40℃至+125℃-3A
  • 1. Go 语言环境安装
  • 数据清洗的艺术:如何为AI模型准备高质量数据集?
  • 《Python星球日记》 第71天:命名实体识别(NER)与关系抽取
  • 拓展篇、github的账号创建
  • Oracle中的select1条、几条、指定范围的语句
  • 【证书与信任机制​】证书透明度(Certificate Transparency):如何防止恶意证书颁发?​​
  • 【1000以内具有12个以上因子的整数并输出它的因子】2021-12-27
  • 如何在Mac电脑上的VScode去配置C/C++环境
  • 生成式AI:人工智能的新纪元
  • 请求内存算法题
  • 综述:拓扑材料的热磁性质
  • WordPress 和 GPL – 您需要了解的一切
  • 【leetcode】349. 两个数组的交集
  • WindTerm终端工具功能与优缺点分析
  • mysql的一个缺点
  • libmemcached库api接口讲解一
  • 开发者的测试复盘:架构分层测试策略与工具链闭环设计实战
  • c++之 sort()排序
  • Unity 小提示与小技巧[特殊字符]
  • 基于C#实现中央定位服务器的 P2P 网络聊天系统
  • 大二java第一面小厂(挂)
  • C++【STL】(2)string
  • 直流电机风速仪