diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 29cd9e9..16237c9 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -2,7 +2,8 @@ "permissions": { "allow": [ "Read(//c/Windows/Fonts//**)", - "Read(//z/work/**)" + "Read(//z/work/**)", + "Read(//z/work/lsh-SS524V100_SDK_V1.0/mpp/include/**)" ], "deny": [ "Edit", diff --git a/mpp/sample/vdec_udp_h265/sample_vdec.c b/mpp/sample/vdec_udp_h265/sample_vdec.c index 9e85453..5bed4d7 100644 --- a/mpp/sample/vdec_udp_h265/sample_vdec.c +++ b/mpp/sample/vdec_udp_h265/sample_vdec.c @@ -48,16 +48,25 @@ #define REF_NUM 2 #define DISPLAY_NUM 2 -#if 0 - +/*占位图要求:1920*1200 NV21 不压缩 yuv图片 + *生成命令:ffmpeg -i nosignal.png -vf scale=1920:1200 -pix_fmt nv21 -f rawvideo nosignal.yuv*/ #define NOSIGNAL_YUV_PATH "./nosignal.yuv" -static ot_video_frame_info g_nosignal_src; /* 1920x1200 源图(VGS 输入) */ -static ot_vb_pool g_nosignal_src_pool = OT_VB_INVALID_POOL_ID; -static ot_vb_blk g_nosignal_src_blk = OT_VB_INVALID_HANDLE; -static td_bool g_nosignal_src_valid = TD_FALSE; +/* 用户图片必须是"非压缩"帧,而公共池 0 是按 SEG 压缩模式算块大小的, + * 装不下 1920x1200 YUV420 未压缩的 3.4MB,所以单独开一个非压缩公共池给它。 */ +#define NOSIGNAL_POOL_IDX 1 +#define NOSIGNAL_STRIDE OT_ALIGN_UP((td_u32)(STREAN_WIDTH), 16) +#define NOSIGNAL_STRIDED_SIZE (((NOSIGNAL_STRIDE) * (STREAM_HEIGHT) * 3) / 2) +#define NOSIGNAL_BLK_SIZE OT_ALIGN_UP((td_u32)(NOSIGNAL_STRIDED_SIZE), 0x100000) +#define NOSIGNAL_CHN_NUM 2 /* 只有 chn 0-1 用占位图,其余通道断流时保持黑屏 */ + +static const td_bool g_nosignal_chn_enable[OT_VDEC_MAX_CHN_NUM] = { [0 ... (NOSIGNAL_CHN_NUM - 1)] = TD_TRUE }; + +static ot_video_frame_info g_nosignal_src; /* 1920x1200 占位图帧信息 */ +static ot_vb_blk g_nosignal_src_blk = OT_VB_INVALID_HANDLE; +td_bool g_nosignal_src_valid = TD_FALSE; /* udp_get_nal_frame.c 里 extern 引用,不能加 static */ +td_bool g_nosignal_pic_set[OT_VDEC_MAX_CHN_NUM] = {TD_FALSE}; /* 每个通道占位图是否已 set 成功*/ -#endif static ot_vo_intf_sync g_intf_sync = OT_VO_OUT_3840x2160_30; @@ -92,9 +101,6 @@ pthread_cond_t vid_au_cond; pthread_mutex_t vid_au_mutex; dqueue vid_au_q; -// static ot_vb_pool g_usrpic_pool = OT_VB_INVALID_POOL_ID; -// static ot_video_frame_info g_usrpic_info; - int do_exit_inner = 0; int vid_q_len = 0; @@ -224,9 +230,12 @@ static td_s32 sample_init_sys_and_vb(sample_vdec_attr *sample_vdec, td_u32 vdec_ buf_attr.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; (td_void)memset_s(&vb_cfg, sizeof(ot_vb_cfg), 0, sizeof(ot_vb_cfg)); - vb_cfg.max_pool_cnt = 1; + vb_cfg.max_pool_cnt = 2; vb_cfg.common_pool[0].blk_cnt = 10 * vdec_chn_num; /* 10:common vb cnt */ vb_cfg.common_pool[0].blk_size = ot_common_get_pic_buf_size(&buf_attr); + /* 1 号公共池:专给 nosignal 占位图用。块大小="未压缩原始图" */ + vb_cfg.common_pool[NOSIGNAL_POOL_IDX].blk_cnt = 2; + vb_cfg.common_pool[NOSIGNAL_POOL_IDX].blk_size = NOSIGNAL_BLK_SIZE; ret = sample_comm_sys_init(&vb_cfg); if (ret != TD_SUCCESS) { sample_print("init sys fail for %#x!\n", ret); @@ -333,8 +342,6 @@ static td_s32 sample_start_vpss(ot_vpss_grp *vpss_grp, td_u32 vpss_grp_num, td_b vpss_chn_attr[1].depth = 0; vpss_chn_attr[1].mirror_en = TD_FALSE; //TD_TRUE; //180 vpss_chn_attr[1].flip_en = TD_FALSE; //TD_TRUE; //180 - // vpss_chn_attr[1].mirror_en = TD_TRUE; //TD_TRUE; //180 - // vpss_chn_attr[1].flip_en = TD_TRUE; //TD_TRUE; //180 vpss_chn_attr[1].border_en = TD_FALSE; vpss_chn_attr[1].aspect_ratio.mode = OT_ASPECT_RATIO_NONE; } @@ -567,119 +574,129 @@ static td_s32 sample_start_vdec(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_n return ret; } -#if 0 +#if 1 /* ==================== no-signal 占位图 ==================== */ -/* 启动时调用:读源图 nosignal.yuv(1920x1200) 到 VB,填成 user pic frame_info */ - td_s32 load_nosignal_src(void) { - td_u32 width = STREAN_WIDTH; /* 1920 */ - td_u32 height = STREAM_HEIGHT; /* 1200 */ - td_u32 stride = OT_ALIGN_UP(width, 16); - td_u32 y_size = stride * height; - td_u32 frame_size = y_size * 3 / 2; - td_u32 file_size = width * height * 3 / 2; + td_u32 width = STREAN_WIDTH; + td_u32 height = STREAM_HEIGHT; + td_u32 stride = NOSIGNAL_STRIDE; + td_u32 y_size = stride * height ; + td_u32 pic_size = NOSIGNAL_STRIDED_SIZE; /* 3456000 图像实际占用 */ + td_phys_addr_t phys; td_u8 *virt = TD_NULL; td_u8 *file_buf = TD_NULL; td_u32 i; FILE *fp; - ot_vb_pool_cfg pool_cfg = {0}; - /* 建池 */ - pool_cfg.blk_size = frame_size; - pool_cfg.blk_cnt = 1; - pool_cfg.remap_mode = OT_VB_REMAP_MODE_NONE; - g_nosignal_src_pool = ss_mpi_vb_create_pool(&pool_cfg); - if (g_nosignal_src_pool == OT_VB_INVALID_POOL_ID) { - printf("[nosignal] create src pool fail\n"); - return TD_FAILURE; - } - g_nosignal_src_blk = ss_mpi_vb_get_blk(g_nosignal_src_pool, frame_size, TD_NULL); + /* 从专建的非压缩公共池取块 */ + g_nosignal_src_blk = ss_mpi_vb_get_blk(NOSIGNAL_POOL_IDX, pic_size, TD_NULL); if (g_nosignal_src_blk == OT_VB_INVALID_HANDLE) { - printf("[nosignal] get src blk fail\n"); + printf("[nosignal] get vb blk fail(need %u bytes), nosignal disabled\n", pic_size); return TD_FAILURE; } + phys = ss_mpi_vb_handle_to_phys_addr(g_nosignal_src_blk); - virt = (td_u8 *)ss_mpi_sys_mmap(phys, frame_size); + virt = (td_u8 *)ss_mpi_sys_mmap(phys, pic_size); if (virt == TD_NULL) { printf("[nosignal] mmap src fail\n"); return TD_FAILURE; } + memset(virt, 0, pic_size); - /* 读源图 */ fp = fopen(NOSIGNAL_YUV_PATH, "rb"); if (fp == TD_NULL) { - printf("[nosignal] open %s fail\n", NOSIGNAL_YUV_PATH); + printf("[nosignal] open %s fail (当前工作目录里没有该文件!)\n", NOSIGNAL_YUV_PATH); return TD_FAILURE; } - file_buf = (td_u8 *)malloc(file_size); - if (file_buf == TD_NULL || fread(file_buf, 1, file_size, fp) != file_size) { + file_buf = (td_u8 *)malloc(pic_size); + if (file_buf == TD_NULL || fread(file_buf, 1, pic_size, fp) != pic_size) { fclose(fp); - printf("[nosignal] read %s fail\n", NOSIGNAL_YUV_PATH); + printf("[nosignal] read %s fail (need %u bytes, %ux%u YUV420SP)\n", + NOSIGNAL_YUV_PATH, pic_size, width, height); return TD_FAILURE; } + fclose(fp); - /* 按行拷贝处理 stride 对齐:Y 平面 + VU 交错平面 */ - for (i = 0; i < height; i++) { + for (i = 0; i < height; i++) { /* Y 平面 */ memcpy(virt + i * stride, file_buf + i * width, width); } - { - td_u8 *vu_dst = virt + y_size; - td_u8 *vu_src = file_buf + width * height; - for (i = 0; i < height / 2; i++) { - memcpy(vu_dst + i * stride, vu_src + i * width, width); - } + for (i = 0; i < height / 2; i++) { /* VU 交错平面 */ + memcpy(virt + y_size + i * stride, file_buf + width * height + i * width, width); } free(file_buf); - /* 填源图 frame_info(VGS 输入) */ memset(&g_nosignal_src, 0, sizeof(g_nosignal_src)); g_nosignal_src.video_frame.field = OT_VIDEO_FIELD_FRAME; g_nosignal_src.video_frame.width = width; g_nosignal_src.video_frame.height = height; - g_nosignal_src.video_frame.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; - g_nosignal_src.video_frame.video_format = OT_VIDEO_FORMAT_LINEAR; - g_nosignal_src.video_frame.compress_mode = OT_COMPRESS_MODE_NONE; - g_nosignal_src.video_frame.stride[0] = stride; - g_nosignal_src.video_frame.stride[1] = stride; - g_nosignal_src.video_frame.phys_addr[0] = phys; - g_nosignal_src.video_frame.phys_addr[1] = phys + y_size; - g_nosignal_src.video_frame.virt_addr[0] = virt; - g_nosignal_src.video_frame.virt_addr[1] = virt + y_size; - g_nosignal_src.pool_id = ss_mpi_vb_handle_to_pool_id(g_nosignal_src_blk); - g_nosignal_src.mod_id = OT_ID_VDEC; - g_nosignal_src_valid = TD_TRUE; + g_nosignal_src.video_frame.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; /* 8bit 420 */ + g_nosignal_src.video_frame.video_format = OT_VIDEO_FORMAT_LINEAR; /* 只支持 Linear */ + g_nosignal_src.video_frame.compress_mode = OT_COMPRESS_MODE_NONE; /* 不压缩 */ + g_nosignal_src.video_frame.dynamic_range = OT_DYNAMIC_RANGE_SDR8; /* 8bit */ + g_nosignal_src.video_frame.color_gamut = OT_COLOR_GAMUT_BT601; + g_nosignal_src.video_frame.pts = 0; /* PTS 统一 0 */ - printf("[nosignal] load src %ux%u ok, stride=%u, pool_id=%u, mod_id=%d\n", - width, height, stride, g_nosignal_src.pool_id, g_nosignal_src.mod_id); + g_nosignal_src.video_frame.stride[0] = stride; + g_nosignal_src.video_frame.stride[1] = stride; + + g_nosignal_src.video_frame.phys_addr[0] = phys; + g_nosignal_src.video_frame.virt_addr[0] = virt; + g_nosignal_src.video_frame.phys_addr[1] = phys + y_size; + g_nosignal_src.video_frame.virt_addr[1] = virt + y_size; + + g_nosignal_src.pool_id = ss_mpi_vb_handle_to_pool_id(g_nosignal_src_blk); + g_nosignal_src.mod_id = OT_ID_USER; /* 必须是 USER,vdec_set_nosignal_userpic() */ + g_nosignal_src_valid = TD_TRUE; + + printf(" load [nosignal] ok\n"); return TD_SUCCESS; } -/* 停流后 set user pic(共享源图,无需缩放) */ +/* 设置用户图片 */ td_s32 vdec_set_nosignal_userpic(ot_vdec_chn chn) { - printf("[nosignal] pic: w=%u h=%u field=%d pix=%d vidfmt=%d comp=%d dr=%d cg=%d " - "stride0=%u stride1=%u pool=%u mod=%d phys0=%#llx phys1=%#llx\n", - g_nosignal_src.video_frame.width, - g_nosignal_src.video_frame.height, - g_nosignal_src.video_frame.field, - g_nosignal_src.video_frame.pixel_format, - g_nosignal_src.video_frame.video_format, - g_nosignal_src.video_frame.compress_mode, - g_nosignal_src.video_frame.dynamic_range, - g_nosignal_src.video_frame.color_gamut, - g_nosignal_src.video_frame.stride[0], - g_nosignal_src.video_frame.stride[1], - g_nosignal_src.pool_id, - g_nosignal_src.mod_id, - (unsigned long long)g_nosignal_src.video_frame.phys_addr[0], - (unsigned long long)g_nosignal_src.video_frame.phys_addr[1]); + td_s32 ret; - td_s32 ret = ss_mpi_vdec_set_user_pic(chn, &g_nosignal_src); - printf("[nosignal] chn%d set_user_pic ret=%#x\n", chn, ret); + ss_mpi_vdec_disable_user_pic(chn); + ret = ss_mpi_vdec_set_user_pic(chn, &g_nosignal_src); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn%d set_user_pic fail ret=%#x\n", chn, ret); + + } + return ret; +} + +/* 断流时调用:停流 -> (启动时没 set 成功补 set) -> enable 显示占位图。 + * 返回 enable_user_pic 的结果,决定超时是否重试。 */ +td_s32 vdec_enable_nosignal_pic(ot_vdec_chn chn) +{ + td_s32 ret; + + if (g_nosignal_chn_enable[chn] != TD_TRUE) { + return TD_FAILURE; /* 该通道不使用占位图,直接返回,不碰通道状态 */ + } + + ss_mpi_vdec_stop_recv_stream(chn); /*pic 只在停止接收码流时显示 */ + ss_mpi_vdec_disable_user_pic(chn); + + if (g_nosignal_pic_set[chn] != TD_TRUE) { + + ret = vdec_set_nosignal_userpic(chn); + if (ret != TD_SUCCESS) { + ss_mpi_vdec_start_recv_stream(chn); /*if set 不成功重新收流 */ + return ret; + } + g_nosignal_pic_set[chn] = TD_TRUE; + } + + ret = ss_mpi_vdec_enable_user_pic(chn, 1); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn%d enable_user_pic fail ret=%#x\n", chn, ret); + } return ret; } @@ -717,10 +734,24 @@ void* h265_vdec_vpss_vo() goto stop_sys; } - /* 新增:启动读源图并 set user pic(set 前必须先 disable) */ - // if (load_nosignal_src() != TD_SUCCESS) { - // printf("[nosignal] load src fail, nosignal disabled\n"); - // } + /* 启动时把用户图片 set 好,运行只做 enable/disable 切换 */ + if (load_nosignal_src() != TD_SUCCESS) { + printf("[nosignal] load src fail, nosignal disabled\n"); + } else { + for (i = 0; i < vdec_chn_num; i++) { + if (g_nosignal_chn_enable[i] != TD_TRUE) { + continue; + } + + ss_mpi_vdec_disable_user_pic(i); + if (vdec_set_nosignal_userpic(i) == TD_SUCCESS) { + g_nosignal_pic_set[i] = TD_TRUE; + } + + } + printf("[nosignal] setup done\n"); + } + /************************************************ diff --git a/mpp/sample/vdec_udp_h265/udp_get_nal_frame.c b/mpp/sample/vdec_udp_h265/udp_get_nal_frame.c index 39d9a4d..f6472c2 100644 --- a/mpp/sample/vdec_udp_h265/udp_get_nal_frame.c +++ b/mpp/sample/vdec_udp_h265/udp_get_nal_frame.c @@ -26,8 +26,7 @@ #include "sample_comm.h" -// extern td_s32 vdec_set_nosignal_userpic(ot_vdec_chn chn); - +extern td_bool g_nosignal_src_valid; int port = 20000; @@ -116,9 +115,6 @@ void assemble_nal1(unsigned char* buf, unsigned int len) need_sumbit = 0; terminate = 0; - - - if((!memcmp(buf, nal_header , 4)) && (len >= 4)) { //is seperator if(wr_idx == 0) { // is new nal item memcpy(nal_buf_entry1[nalb_idx].buf + wr_idx, buf, len); @@ -160,10 +156,6 @@ void assemble_nal1(unsigned char* buf, unsigned int len) } - - - -#if 0 void *net_recv1(void *arg) { int i; @@ -171,103 +163,43 @@ void *net_recv1(void *arg) int len = sizeof(clientAddr); unsigned char buf[2048]; static int count_time_out=0; - static int nosignal_on = 0; //nosignal satuts + static int nosignal_on = 0; //nosignal satuts ot_vdec_stream stream; int ret; - while(1){ - i = recvfrom(socket_descriptor[0],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); - if(i>0){ - switch_video[2] = 0xAA; - if (nosignal_on == 1) { - ss_mpi_vdec_disable_user_pic(0); - ss_mpi_vdec_start_recv_stream(0); - nosignal_on = 0; + while(1){ + i = recvfrom(socket_descriptor[0],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); + if(i>0){ + switch_video[2] = 0xAA; + if (nosignal_on == 1) { + /* 恢复拉流:先撤占位图,再重新开始收流 */ + ret = ss_mpi_vdec_disable_user_pic(0); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn0 disable_user_pic fail ret=%#x\n", ret); } - - #if 0 - stream.pts = 0; - stream.addr = buf; - stream.len = i; - stream.end_of_frame = TD_FALSE; - stream.end_of_stream = TD_FALSE; - stream.need_display = 1; - - - do { - ret = ss_mpi_vdec_send_stream(0, &stream, 0); - // usleep(1000); - } while (ret != TD_SUCCESS); - - #endif - assemble_nal1(buf,i); - - } - if(i<=0){ - if (nosignal_on == 0) { - ss_mpi_vdec_stop_recv_stream(0); - ss_mpi_vdec_enable_user_pic(0, 1); /* 延迟插入 */ - nosignal_on = 1; - } - switch_video[2] = 0x55; - printf("net1 recv timeout %d\n",i); - } + ret = ss_mpi_vdec_start_recv_stream(0); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn0 start_recv fail ret=%#x\n", ret); + } + nosignal_on = 0; + } + assemble_nal1(buf,i); } -} -#endif + if(i<=0){ + if (nosignal_on == 0 && g_nosignal_src_valid) { + /* 断流:显示占位图(停流/set/enable 都在里面做),失败下轮超时重试 */ + if (vdec_enable_nosignal_pic(0) == TD_SUCCESS) { + printf(" set [nosignal] on chn0 ...ok\n"); + nosignal_on = 1; + } + } + switch_video[2] = 0x55; + printf("net1 recv timeout %d\n",i); + } + } -void *net_recv1(void *arg) -{ - int i; - struct sockaddr_in clientAddr; - int len = sizeof(clientAddr); - unsigned char buf[2048]; - static int count_time_out=0; - // static int nosignal_on = 0; //nosignal satuts - ot_vdec_stream stream; - int ret; - while(1){ - i = recvfrom(socket_descriptor[0],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); - if(i>0){ - switch_video[2] = 0xAA; - // if (nosignal_on == 1) { - // ret = ss_mpi_vdec_disable_user_pic(0); - // printf("[nosignal] disable_user_pic ret=%#x\n", ret); - // ret = ss_mpi_vdec_start_recv_stream(0); - // printf("[nosignal] start_recv_stream ret=%#x\n", ret); - // nosignal_on = 0; - // printf("[nosignal] -> back to normal decode\n"); - // } -#if 0 - stream.pts = 0; - stream.addr = buf; - stream.len = i; - stream.end_of_frame = TD_FALSE; - stream.end_of_stream = TD_FALSE; - stream.need_display = 1; - - do { - ret = ss_mpi_vdec_send_stream(0, &stream, 0); - // usleep(1000); - } while (ret != TD_SUCCESS); -#endif - assemble_nal1(buf,i); - } - if(i<=0){ - // if (nosignal_on == 0) { - // ss_mpi_vdec_stop_recv_stream(0); - // ss_mpi_vdec_disable_user_pic(0); /* 文档:set 前先 disable */ - // vdec_set_nosignal_userpic(0); /* 通道已停,此时 set 才合法 */ - // ss_mpi_vdec_enable_user_pic(0, 1); /* 立即显示占位图 */ - // nosignal_on = 1; - // } - switch_video[2] = 0x55; - printf("net1 recv timeout %d\n",i); - } - - } } @@ -348,12 +280,28 @@ void *net_recv2(void *arg) int len = sizeof(clientAddr); unsigned char buf[2048]; static int count_time_out=0; + static int nosignal_on = 0; ot_vdec_stream stream; int ret; while(1){ i = recvfrom(socket_descriptor[1],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); if(i>0){ switch_video[3] = 0xAA; + + if (nosignal_on == 1) { + /* 恢复拉流:先撤占位图,再重新开始收流 */ + ret = ss_mpi_vdec_disable_user_pic(1); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn1 disable_user_pic fail ret=%#x\n", ret); + } + ret = ss_mpi_vdec_start_recv_stream(1); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn1 start_recv fail ret=%#x\n", ret); + } + nosignal_on = 0; + } + + #if 0 stream.pts = 0; stream.addr = buf; @@ -378,6 +326,15 @@ void *net_recv2(void *arg) //count_time_out++; //if(count_time_out >=1){ switch_video[3] = 0x55; + + if (nosignal_on == 0 && g_nosignal_src_valid) { + /* 断流:显示占位图(停流/set/enable 都在里面做),失败下轮超时重试 */ + if (vdec_enable_nosignal_pic(1) == TD_SUCCESS) { + printf(" set [nosignal] on chn1 ...ok\n"); + nosignal_on = 1; + } + } + printf("net2 recv timeout %d\n",i); // count_time_out =0; //} @@ -460,6 +417,7 @@ void *net_recv3(void *arg) int len = sizeof(clientAddr); unsigned char buf[2048]; static int count_time_out=0; + static int nosignal_on = 0; //nosignal satuts ot_vdec_stream stream; int ret; @@ -468,6 +426,19 @@ void *net_recv3(void *arg) i = recvfrom(socket_descriptor[2],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); if(i>0){ switch_video[4] = 0xAA; + if (nosignal_on == 1) { + /* 恢复拉流:先撤占位图,再重新开始收流 */ + ret = ss_mpi_vdec_disable_user_pic(2); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn2 disable_user_pic fail ret=%#x\n", ret); + } + ret = ss_mpi_vdec_start_recv_stream(2); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn2 start_recv fail ret=%#x\n", ret); + } + nosignal_on = 0; + } + #if 0 stream.pts = 0; @@ -491,6 +462,15 @@ void *net_recv3(void *arg) //count_time_out++; //if(count_time_out >=1){ switch_video[4] = 0x55; + if (nosignal_on == 0 && g_nosignal_src_valid) { + /* 断流:显示占位图(停流/set/enable 都在里面做),失败下轮超时重试 */ + if (vdec_enable_nosignal_pic(2) == TD_SUCCESS) { + printf(" set [nosignal] on chn2 ...ok\n"); + nosignal_on = 1; + } + } + + printf("net3 recv timeout %d\n",i); // count_time_out =0; //} @@ -573,6 +553,7 @@ void *net_recv4(void *arg) int len = sizeof(clientAddr); unsigned char buf[2048]; static int count_time_out=0; + static int nosignal_on = 0; //nosignal satuts ot_vdec_stream stream; int ret; @@ -581,6 +562,20 @@ void *net_recv4(void *arg) i = recvfrom(socket_descriptor[3],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); if(i>0){ switch_video[5] = 0xAA; + + if (nosignal_on == 1) { + /* 恢复拉流:先撤占位图,再重新开始收流 */ + ret = ss_mpi_vdec_disable_user_pic(3); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn3 disable_user_pic fail ret=%#x\n", ret); + } + ret = ss_mpi_vdec_start_recv_stream(3); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn3 start_recv fail ret=%#x\n", ret); + } + nosignal_on = 0; + } + #if 0 stream.pts = 0; stream.addr = buf; @@ -601,6 +596,14 @@ void *net_recv4(void *arg) // printf(" recv4 timeout %d\n",i); //count_time_out++; //if(count_time_out >=2){ + if (nosignal_on == 0 && g_nosignal_src_valid) { + /* 断流:显示占位图(停流/set/enable 都在里面做),失败下轮超时重试 */ + if (vdec_enable_nosignal_pic(3) == TD_SUCCESS) { + printf(" set [nosignal] on chn3 ...ok\n"); + nosignal_on = 1; + } + } + switch_video[5] = 0x55; printf("net4 recv timeout %d\n",i); // count_time_out =0; @@ -662,8 +665,6 @@ void assemble_nal5(unsigned char* buf, unsigned int len) } while (ret != TD_SUCCESS); - - wr_idx = 0; nalb_idx = (nalb_idx+1)%NUM_NAL_BUF; } @@ -689,6 +690,7 @@ void *net_recv5(void *arg) int len = sizeof(clientAddr); unsigned char buf[2048]; static int count_time_out=0; + static int nosignal_on = 0; //nosignal satuts ot_vdec_stream stream; int ret; @@ -698,6 +700,20 @@ void *net_recv5(void *arg) i = recvfrom(socket_descriptor[4],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); if(i>0){ switch_video[6] = 0xAA; + + if (nosignal_on == 1) { + /* 恢复拉流:先撤占位图,再重新开始收流 */ + ret = ss_mpi_vdec_disable_user_pic(4); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn4 disable_user_pic fail ret=%#x\n", ret); + } + ret = ss_mpi_vdec_start_recv_stream(4); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn4 start_recv fail ret=%#x\n", ret); + } + nosignal_on = 0; + } + #if 0 stream.pts = 0; stream.addr = buf; @@ -720,6 +736,15 @@ void *net_recv5(void *arg) // printf(" recv4 timeout %d\n",i); //count_time_out++; //if(count_time_out >=2){ + + if (nosignal_on == 0 && g_nosignal_src_valid) { + /* 断流:显示占位图(停流/set/enable 都在里面做),失败下轮超时重试 */ + if (vdec_enable_nosignal_pic(4) == TD_SUCCESS) { + printf(" set [nosignal] on chn4 ...ok\n"); + nosignal_on = 1; + } + } + switch_video[6] = 0x55; printf("net5 recv timeout %d\n",i); count_time_out =0; @@ -805,6 +830,7 @@ void *net_recv6(void *arg) int len = sizeof(clientAddr); unsigned char buf[2048]; static int count_time_out=0; + static int nosignal_on = 0; //nosignal satuts ot_vdec_stream stream; int ret; @@ -812,6 +838,20 @@ void *net_recv6(void *arg) i = recvfrom(socket_descriptor[5],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); if(i>0){ switch_video[7] = 0xAA; + if (nosignal_on == 1) { + /* 恢复拉流:先撤占位图,再重新开始收流 */ + ret = ss_mpi_vdec_disable_user_pic(5); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn5 disable_user_pic fail ret=%#x\n", ret); + } + ret = ss_mpi_vdec_start_recv_stream(5); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn5 start_recv fail ret=%#x\n", ret); + } + nosignal_on = 0; + } + + #if 0 stream.pts = 0; stream.addr = buf; @@ -834,6 +874,14 @@ void *net_recv6(void *arg) // printf(" recv4 timeout %d\n",i); //count_time_out++; //if(count_time_out >=2){ + if (nosignal_on == 0 && g_nosignal_src_valid) { + /* 断流:显示占位图(停流/set/enable 都在里面做),失败下轮超时重试 */ + if (vdec_enable_nosignal_pic(5) == TD_SUCCESS) { + printf(" set [nosignal] on chn5 ...ok\n"); + nosignal_on = 1; + } + } + switch_video[7] = 0x55; printf("net6 recv timeout %d\n",i); // count_time_out =0; @@ -918,6 +966,7 @@ void *net_recv7(void *arg) int len = sizeof(clientAddr); unsigned char buf[2048]; static int count_time_out=0; + static int nosignal_on = 0; //nosignal satuts ot_vdec_stream stream; int ret; @@ -925,6 +974,19 @@ void *net_recv7(void *arg) i = recvfrom(socket_descriptor[6],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); if(i>0){ switch_video[8] = 0xAA; + if (nosignal_on == 1) { + /* 恢复拉流:先撤占位图,再重新开始收流 */ + ret = ss_mpi_vdec_disable_user_pic(6); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn6 disable_user_pic fail ret=%#x\n", ret); + } + ret = ss_mpi_vdec_start_recv_stream(6); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn6 start_recv fail ret=%#x\n", ret); + } + nosignal_on = 0; + } + #if 0 stream.pts = 0; stream.addr = buf; @@ -945,7 +1007,15 @@ void *net_recv7(void *arg) // printf(" recv4 timeout %d\n",i); //count_time_out++; //if(count_time_out >=2){ + if (nosignal_on == 0 && g_nosignal_src_valid) { + /* 断流:显示占位图(停流/set/enable 都在里面做),失败下轮超时重试 */ + if (vdec_enable_nosignal_pic(6) == TD_SUCCESS) { + printf(" set [nosignal] on chn6 ...ok\n"); + nosignal_on = 1; + } + } switch_video[8] = 0x55; + printf("net7 recv timeout %d\n",i); // count_time_out =0; //} @@ -1031,6 +1101,7 @@ void *net_recv8(void *arg) int len = sizeof(clientAddr); unsigned char buf[2048]; static int count_time_out=0; + static int nosignal_on = 0; //nosignal satuts ot_vdec_stream stream; int ret; @@ -1038,6 +1109,20 @@ void *net_recv8(void *arg) i = recvfrom(socket_descriptor[7],buf, 1472, 0, (struct sockaddr*)&clientAddr, &len); if(i>0){ switch_video[9] = 0xAA; + if (nosignal_on == 1) { + /* 恢复拉流:先撤占位图,再重新开始收流 */ + ret = ss_mpi_vdec_disable_user_pic(7); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn7 disable_user_pic fail ret=%#x\n", ret); + } + ret = ss_mpi_vdec_start_recv_stream(7); + if (ret != TD_SUCCESS) { + printf("[nosignal] chn7 start_recv fail ret=%#x\n", ret); + } + nosignal_on = 0; + } + + #if 0 stream.pts = 0; stream.addr = buf; @@ -1057,6 +1142,14 @@ void *net_recv8(void *arg) if(i<=0){ // count_time_out++; // if(count_time_out >=2){ + if (nosignal_on == 0 && g_nosignal_src_valid) { + /* 断流:显示占位图(停流/set/enable 都在里面做),失败下轮超时重试 */ + if (vdec_enable_nosignal_pic(7) == TD_SUCCESS) { + printf(" set [nosignal] on chn6 ...ok\n"); + nosignal_on = 1; + } + } + switch_video[9] = 0x55; // printf("net8 recv timeout %d\n",i); // count_time_out =0; diff --git a/mpp/sample/vdec_udp_h265/vdec_udp_h265 b/mpp/sample/vdec_udp_h265/vdec_udp_h265 index 5bc2e40..565d375 100644 Binary files a/mpp/sample/vdec_udp_h265/vdec_udp_h265 and b/mpp/sample/vdec_udp_h265/vdec_udp_h265 differ