Files
hisi_SS524V100_SDK/mpp/sample/vdec_udp_h265/sample_vdec.c
T

1399 lines
44 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <math.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <sched.h>
#include <sys/syscall.h>
#include <errno.h>
#include <sys/mman.h>
#include "dqueue.h"
#include "ss_mpi_vb.h"
#include "ss_mpi_sys.h"
#include "ss_mpi_vgs.h"
#include "sample_comm.h"
#ifdef OT_FPGA
#define PIC_SIZE PIC_1080P
#else
#define PIC_SIZE PIC_3840X2160
#endif
#define SAMPLE_STREAM_PATH "./source_file"
#define STREAN_WIDTH 1920
#define STREAM_HEIGHT 1200
#define REF_NUM 2
#define DISPLAY_NUM 2
/*占位图要求: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"
/* 用户图片必须是"非压缩"帧,而公共池 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 成功*/
static ot_vo_intf_sync g_intf_sync = OT_VO_OUT_3840x2160_30;
static vdec_display_cfg g_vdec_display_cfg = {
.pic_size = PIC_3840X2160,
.intf_sync = OT_VO_OUT_3840x2160_30,
.intf_type = OT_VO_INTF_HDMI,
};
static ot_size g_disp_size;
static td_s32 g_sample_exit = 0;
int fd_fs;
unsigned char buffer_nal[2048];
static int socket_descriptor;
static struct sockaddr_in address;
static struct sockaddr_in clientAddr;
static struct timeval tv;
int sock_len;
extern int socket_descriptor_audio;
extern struct sockaddr_in address_audio;
pthread_attr_t attr;
static pthread_t vid_au_thread;
pthread_cond_t vid_au_cond;
pthread_mutex_t vid_au_mutex;
dqueue vid_au_q;
int do_exit_inner = 0;
int vid_q_len = 0;
int *switch_video;
int *video_switch;
//unsigned int switch_video[10];
#ifndef __LITEOS__
static td_void sample_vdec_handle_sig(td_s32 signo)
{
if ((signo == SIGINT) || (signo == SIGTERM)) {
g_sample_exit = 1;
}
}
#endif
static td_s32 sample_getchar()
{
int c;
if (g_sample_exit == 1) {
return 'e';
}
c = getchar();
if (g_sample_exit == 1) {
return 'e';
}
return c;
}
static td_void sample_vdec_usage(const char *s_prg_nm)
{
printf("\n/************************************/\n");
printf("usage : %s <index> <intf_sync >\n", s_prg_nm);
printf("index:\n");
printf("\t0: VDEC(H265 PLAYBACK)-VPSS-VO\n");
printf("\t1: VDEC(H264 PLAYBACK)-VPSS-VO\n");
printf("\t2: VDEC(H264 PREVIEW)-VPSS-VOPIP\n");
printf("\t3: VDEC(JPEG PLAYBACK)-VPSS-VO\n");
printf("\nintf_sync :\n");
#ifdef OT_FPGA
printf("\t0: VO BT1120 \n");
#else
printf("\t0: VO HDMI \n");
printf("\t1: VO BT1120 \n");
#endif
printf("/************************************/\n\n");
}
static td_void sample_vdec_get_diplay_cfg()
{
#ifdef OT_FPGA
g_vdec_display_cfg.pic_size = PIC_720P;
g_vdec_display_cfg.intf_sync = OT_VO_OUT_720P60;
g_vdec_display_cfg.intf_type = OT_VO_INTF_BT1120;
#else
if (g_intf_sync == OT_VO_OUT_3840x2160_30) {
g_vdec_display_cfg.pic_size = PIC_3840X2160;
g_vdec_display_cfg.intf_sync = OT_VO_OUT_3840x2160_30;
g_vdec_display_cfg.intf_type = OT_VO_INTF_HDMI;
} else {
g_vdec_display_cfg.pic_size = PIC_1920X1200;
//g_vdec_display_cfg.pic_size = PIC_1080P;
g_vdec_display_cfg.intf_sync = OT_VO_OUT_1920x1200_60;
//g_vdec_display_cfg.intf_sync = OT_VO_OUT_1080P60;
//g_vdec_display_cfg.intf_type = OT_VO_INTF_BT1120;
g_vdec_display_cfg.intf_type = OT_VO_INTF_HDMI;
}
#endif
}
static td_s32 sample_init_module_vb(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_num, ot_payload_type type,
td_u32 len)
{
td_u32 i;
td_s32 ret;
for (i = 0; (i < vdec_chn_num) && (i < len); i++) {
sample_vdec[i].type = type;
sample_vdec[i].width = STREAN_WIDTH;
sample_vdec[i].height = STREAM_HEIGHT;
//sample_vdec[i].mode = OT_VDEC_SEND_MODE_STREAM;
sample_vdec[i].mode = OT_VDEC_SEND_MODE_FRAME;
sample_vdec[i].sample_vdec_video.dec_mode = OT_VIDEO_DEC_MODE_IP;
sample_vdec[i].sample_vdec_video.bit_width = OT_DATA_BIT_WIDTH_8;
if (type == OT_PT_JPEG) {
sample_vdec[i].sample_vdec_video.ref_frame_num = 0;
} else {
sample_vdec[i].sample_vdec_video.ref_frame_num = REF_NUM;
}
sample_vdec[i].display_frame_num = DISPLAY_NUM;
sample_vdec[i].frame_buf_cnt = (type == OT_PT_JPEG) ? (sample_vdec[i].display_frame_num + 1) :
(sample_vdec[i].sample_vdec_video.ref_frame_num + sample_vdec[i].display_frame_num + 1);
if (type == OT_PT_JPEG) {
sample_vdec[i].sample_vdec_picture.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
sample_vdec[i].sample_vdec_picture.alpha = 255; /* 255:pic alpha value */
}
}
ret = sample_comm_vdec_init_vb_pool(vdec_chn_num, &sample_vdec[0], len);
if (ret != TD_SUCCESS) {
sample_print("init mod common vb fail for %#x!\n", ret);
return ret;
}
return ret;
}
static td_s32 sample_init_sys_and_vb(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_num, ot_payload_type type,
td_u32 len)
{
ot_vb_cfg vb_cfg;
ot_pic_buf_attr buf_attr = {0};
td_s32 ret;
sample_vdec_get_diplay_cfg();
ret = sample_comm_sys_get_pic_size(g_vdec_display_cfg.pic_size, &g_disp_size);
if (ret != TD_SUCCESS) {
sample_print("sys get pic size fail for %#x!\n", ret);
return ret;
}
buf_attr.align = 0;
buf_attr.bit_width = OT_DATA_BIT_WIDTH_8;
buf_attr.compress_mode = OT_COMPRESS_MODE_SEG;
buf_attr.height = g_disp_size.height;
buf_attr.width = g_disp_size.width;
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 = 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);
sample_comm_sys_exit();
return ret;
}
ret = sample_init_module_vb(&sample_vdec[0], vdec_chn_num, type, len);
if (ret != TD_SUCCESS) {
sample_print("init mod vb fail for %#x!\n", ret);
sample_comm_vdec_exit_vb_pool();
sample_comm_sys_exit();
return ret;
}
return ret;
}
static td_s32 sample_start_vpss_crop(ot_vpss_grp *vpss_grp)
{
ot_vpss_crop_info crop_info;
td_s32 ret;
*vpss_grp = 1;
crop_info.enable = TD_TRUE;
crop_info.crop_mode = OT_COORD_ABS;
crop_info.crop_rect.x = OT_ALIGN_UP(STREAN_WIDTH / 4, 2); /* 4,2:align */
crop_info.crop_rect.y = OT_ALIGN_UP(STREAM_HEIGHT / 4, 2); /* 4,2:align */
crop_info.crop_rect.width = OT_ALIGN_UP(STREAN_WIDTH / 2, 2); /* 2,2:align */
crop_info.crop_rect.height = OT_ALIGN_UP(STREAM_HEIGHT / 2, 2); /* 2,2:align */
ret = ss_mpi_vpss_set_grp_crop(*vpss_grp, &crop_info);
if (ret != TD_SUCCESS) {
sample_print("start VPSS fail for %#x!\n", ret);
return ret;
}
return ret;
}
static td_s32 sample_vdec_bind_vpss(td_u32 vpss_grp_num, td_bool is_pip)
{
td_u32 i;
td_s32 ret = TD_SUCCESS;
for (i = 0; i < vpss_grp_num; i++) {
ret = sample_comm_vdec_bind_vpss(is_pip ? 0 : i, i);
if (ret != TD_SUCCESS) {
sample_print("vdec bind vpss fail for %#x!\n", ret);
return ret;
}
}
return ret;
}
static td_void sample_stop_vpss(ot_vpss_grp vpss_grp, td_bool *vpss_chn_enable, td_u32 chn_array_size)
{
td_s32 i;
for (i = vpss_grp; i >= 0; i--) {
vpss_grp = i;
sample_common_vpss_stop(vpss_grp, &vpss_chn_enable[0], chn_array_size);
}
}
static td_s32 sample_vdec_unbind_vpss(td_u32 vpss_grp_num, td_bool is_pip)
{
td_u32 i;
td_s32 ret = TD_SUCCESS;
for (i = 0; i < vpss_grp_num; i++) {
ret = sample_comm_vdec_un_bind_vpss(is_pip ? 0 : i, i);
if (ret != TD_SUCCESS) {
sample_print("vdec unbind vpss fail for %#x!\n", ret);
}
}
return ret;
}
static td_void sample_config_vpss_grp_attr(ot_vpss_grp_attr *vpss_grp_attr)
{
vpss_grp_attr->max_width = STREAN_WIDTH;
vpss_grp_attr->max_height = STREAM_HEIGHT;
vpss_grp_attr->frame_rate.src_frame_rate = -1;
vpss_grp_attr->frame_rate.dst_frame_rate = -1;
vpss_grp_attr->pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
vpss_grp_attr->nr_en = TD_FALSE;
vpss_grp_attr->ie_en = TD_FALSE;
vpss_grp_attr->dci_en = TD_FALSE;
vpss_grp_attr->dei_mode = OT_VPSS_DEI_MODE_OFF;
vpss_grp_attr->buf_share_en = TD_FALSE;
}
static td_s32 sample_start_vpss(ot_vpss_grp *vpss_grp, td_u32 vpss_grp_num, td_bool *vpss_chn_enable,
td_bool is_pip, td_u32 arr_len)
{
td_u32 i;
td_s32 ret;
ot_vpss_chn_attr vpss_chn_attr[OT_VPSS_MAX_CHN_NUM];
ot_vpss_grp_attr vpss_grp_attr = {0};
sample_config_vpss_grp_attr(&vpss_grp_attr);
(td_void)memset_s(vpss_chn_enable, arr_len * sizeof(td_bool), 0, arr_len * sizeof(td_bool));
if (arr_len > 1) {
vpss_chn_enable[1] = TD_TRUE;
vpss_chn_attr[1].width = is_pip ? (g_disp_size.width / 4) : g_disp_size.width; /* 4:crop */
vpss_chn_attr[1].height = is_pip ? (g_disp_size.height / 4) : g_disp_size.height; /* 4:crop */
vpss_chn_attr[1].chn_mode = OT_VPSS_CHN_MODE_AUTO;
vpss_chn_attr[1].compress_mode = is_pip ? OT_COMPRESS_MODE_NONE : OT_COMPRESS_MODE_SEG;
vpss_chn_attr[1].pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
vpss_chn_attr[1].frame_rate.src_frame_rate = -1;
vpss_chn_attr[1].frame_rate.dst_frame_rate = -1;
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].border_en = TD_FALSE;
vpss_chn_attr[1].aspect_ratio.mode = OT_ASPECT_RATIO_NONE;
}
for (i = 0; i < vpss_grp_num; i++) {
*vpss_grp = i;
ret = sample_common_vpss_start(*vpss_grp, &vpss_chn_enable[0],
&vpss_grp_attr, vpss_chn_attr, OT_VPSS_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
sample_print("start VPSS fail for %#x!\n", ret);
sample_stop_vpss(*vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
return ret;
}
}
if (is_pip) {
ret = sample_start_vpss_crop(vpss_grp);
if (ret != TD_SUCCESS) {
sample_stop_vpss(*vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
return ret;
}
}
ret = sample_vdec_bind_vpss(vpss_grp_num, is_pip);
if (ret != TD_SUCCESS) {
sample_vdec_unbind_vpss(vpss_grp_num, is_pip);
sample_stop_vpss(*vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
}
return ret;
}
static td_s32 sample_vpss_unbind_vo(td_u32 vpss_grp_num, sample_vo_cfg vo_config)
{
td_u32 i;
ot_vo_layer vo_layer = vo_config.vo_dev;
td_s32 ret = TD_SUCCESS;
for (i = 0; i < vpss_grp_num; i++) {
ret = sample_comm_vpss_un_bind_vo(i, 1, vo_layer, i);
if (ret != TD_SUCCESS) {
sample_print("vpss unbind vo fail for %#x!\n", ret);
}
}
return ret;
}
static td_s32 sample_vpss_bind_vo(sample_vo_cfg vo_config, td_u32 vpss_grp_num, td_bool is_pip)
{
td_u32 i;
ot_vo_layer vo_layer;
td_s32 ret = TD_SUCCESS;
vo_layer = vo_config.vo_dev;
for (i = 0; i < vpss_grp_num; i++) {
if (is_pip) {
vo_layer = (i == 0) ? 0 : 2; /* 2:layer id */
}
ret = sample_comm_vpss_bind_vo(i, 1, vo_layer, is_pip ? 0 : i);
if (ret != TD_SUCCESS) {
sample_print("vpss bind vo fail for %#x!\n", ret);
return ret;
}
}
return ret;
}
static td_s32 sample_start_vo(sample_vo_cfg *vo_config, td_u32 vpss_grp_num, td_bool is_pip)
{
td_s32 ret;
vo_config->vo_dev = SAMPLE_VO_DEV_UHD;
vo_config->vo_intf_type = g_vdec_display_cfg.intf_type;
vo_config->intf_sync = g_vdec_display_cfg.intf_sync;
vo_config->pic_size = g_vdec_display_cfg.pic_size;
vo_config->bg_color = COLOR_RGB_BLACK;//COLOR_RGB_BLUE;
vo_config->dis_buf_len = 3; /* 3:buf length */
vo_config->dst_dynamic_range = OT_DYNAMIC_RANGE_SDR8;
vo_config->vo_mode = VO_MODE_8MUX;//VO_MODE_4MUX;
vo_config->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
vo_config->disp_rect.x = 0;
vo_config->disp_rect.y = 0;
vo_config->disp_rect.width = g_disp_size.width;
vo_config->disp_rect.height = g_disp_size.height;
vo_config->image_size.width = g_disp_size.width;
vo_config->image_size.height = g_disp_size.height;
vo_config->vo_part_mode = OT_VO_PARTITION_MODE_SINGLE;
vo_config->compress_mode = OT_COMPRESS_MODE_NONE;
ret = sample_comm_vo_start_vo(vo_config);
if (ret != TD_SUCCESS) {
sample_print("start VO fail for %#x!\n", ret);
sample_comm_vo_stop_vo(vo_config);
return ret;
}
if (is_pip == TD_TRUE) {
ret = sample_comm_vo_start_pip(vo_config);
if (ret != TD_SUCCESS) {
sample_print("start VO PIP fail for %#x!\n", ret);
sample_comm_vo_stop_pip(vo_config);
sample_comm_vo_stop_vo(vo_config);
return ret;
}
}
ret = sample_vpss_bind_vo(*vo_config, vpss_grp_num, is_pip);
if (ret != TD_SUCCESS) {
sample_vpss_unbind_vo(vpss_grp_num, *vo_config);
if (is_pip == TD_TRUE) {
sample_comm_vo_stop_pip(vo_config);
}
sample_comm_vo_stop_vo(vo_config);
}
return ret;
}
static td_void sample_vdec_cmd_ctrl(td_u32 chn_num, vdec_thread_param *vdec_send, pthread_t *vdec_thread,
td_u32 send_arr_len, td_u32 thread_arr_len)
{
td_u32 i;
ot_vdec_chn_status status;
td_bool vo_pause = TD_FALSE;
td_s32 c;
for (i = 0; (i < chn_num) && (i < send_arr_len) && (i < thread_arr_len); i++) {
if (vdec_send[i].circle_send == TD_TRUE) {
goto circle_send;
}
}
sample_comm_vdec_cmd_not_circle_send(chn_num, vdec_send, vdec_thread, send_arr_len, thread_arr_len);
return;
circle_send:
while (1) {
printf("\n_sample_test:press 'e' to exit; 'p' to pause; 'r' to resume; 'q' to query; 's' to step;"
" 'a' to add; 'd' to sub!;\n");
c = sample_getchar();
if (c == 'e') {
break;
} else if (c == 'r') {
sample_comm_vdec_cmd_ctrl_resume(chn_num, &vdec_send[0], send_arr_len, thread_arr_len, &vo_pause);
} else if (c == 'p') {
sample_comm_vdec_cmd_ctrl_pause(chn_num, &vdec_send[0], send_arr_len, thread_arr_len, &vo_pause);
} else if (c == 'a') {
sample_comm_vdec_cmd_ctrl_add();
} else if (c == 'd') {
sample_comm_vdec_cmd_ctrl_sub();
} else if (c == 's') {
sample_comm_vdec_cmd_ctrl_step(chn_num, vo_pause);
} else if (c == 'q') {
for (i = 0; (i < chn_num) && (i < send_arr_len) && (i < thread_arr_len); i++) {
ss_mpi_vdec_query_status(vdec_send[i].chn_id, &status);
sample_comm_vdec_print_chn_status(vdec_send[i].chn_id, status);
}
}
}
return;
}
static td_void sample_send_stream_to_vdec(sample_vdec_attr *sample_vdec, td_u32 arr_len, td_u32 vdec_chn_num,
const char *stream_name, td_bool is_pip)
{
td_u32 i;
vdec_thread_param vdec_send[OT_VDEC_MAX_CHN_NUM];
pthread_t vdec_thread[OT_VDEC_MAX_CHN_NUM] = {0}; /* 2:thread */
if (arr_len > OT_VDEC_MAX_CHN_NUM) {
sample_print("array size(%u) of vdec_send need < %u!\n", arr_len, OT_VDEC_MAX_CHN_NUM);
return;
}
for (i = 0; (i < vdec_chn_num) && (i < arr_len); i++) {
if (snprintf_s(vdec_send[i].c_file_name, sizeof(vdec_send[i].c_file_name), sizeof(vdec_send[i].c_file_name) - 1,
stream_name) < 0) {
return;
}
if (snprintf_s(vdec_send[i].c_file_path, sizeof(vdec_send[i].c_file_path), sizeof(vdec_send[i].c_file_path) - 1,
"%s", SAMPLE_STREAM_PATH) < 0) {
return;
}
vdec_send[i].type = sample_vdec[i].type;
vdec_send[i].stream_mode = sample_vdec[i].mode;
vdec_send[i].chn_id = i;
vdec_send[i].interval_time = 1000; /* 1000: interval time */
vdec_send[i].pts_init = 0;
vdec_send[i].pts_increase = 0;
vdec_send[i].e_thread_ctrl = THREAD_CTRL_START;
vdec_send[i].circle_send = TD_TRUE;
vdec_send[i].milli_sec = 0;
vdec_send[i].min_buf_size = (sample_vdec[i].width * sample_vdec[i].height * 3) >> 1; /* 3:yuv */
}
sample_comm_vdec_start_send_stream(vdec_chn_num, &vdec_send[0], &vdec_thread[0],
OT_VDEC_MAX_CHN_NUM, OT_VDEC_MAX_CHN_NUM);
while(1){
sleep(5);
}
if (is_pip) {
printf("\n_sample_test:press any key to exit!\n");
sample_getchar();
} else {
sample_vdec_cmd_ctrl(vdec_chn_num, &vdec_send[0], &vdec_thread[0],
OT_VDEC_MAX_CHN_NUM, OT_VDEC_MAX_CHN_NUM);
}
sample_comm_vdec_stop_send_stream(vdec_chn_num, &vdec_send[0], &vdec_thread[0],
OT_VDEC_MAX_CHN_NUM, OT_VDEC_MAX_CHN_NUM);
}
static td_s32 sample_start_vdec(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_num, td_u32 len, td_bool is_pip)
{
td_s32 ret;
td_u32 i;
ret = sample_comm_vdec_start(vdec_chn_num, &sample_vdec[0], len);
if (ret != TD_SUCCESS) {
sample_print("start VDEC fail for %#x!\n", ret);
sample_comm_vdec_stop(vdec_chn_num);
return ret;
}
if (is_pip == TD_TRUE) {
for (i = 0; i < vdec_chn_num; i++) {
ret = ss_mpi_vdec_set_display_mode(i, OT_VIDEO_DISPLAY_MODE_PREVIEW);
if (ret != TD_SUCCESS) {
sample_print("set VDEC display_mode fail for %#x!\n", ret);
sample_comm_vdec_stop(vdec_chn_num);
}
}
}
return ret;
}
#if 1
/* ==================== no-signal 占位图 ==================== */
td_s32 load_nosignal_src(void)
{
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;
/* 从专建的非压缩公共池取块 */
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 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, 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);
return TD_FAILURE;
}
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 (need %u bytes, %ux%u YUV420SP)\n",
NOSIGNAL_YUV_PATH, pic_size, width, height);
return TD_FAILURE;
}
fclose(fp);
for (i = 0; i < height; i++) { /* Y 平面 */
memcpy(virt + i * stride, file_buf + 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);
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; /* 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 */
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;
}
/* 设置用户图片 */
td_s32 vdec_set_nosignal_userpic(ot_vdec_chn chn)
{
td_s32 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;
}
#endif
void* h265_vdec_vpss_vo()
{
td_s32 ret;
td_u32 vdec_chn_num, vpss_grp_num;
sample_vdec_attr sample_vdec[OT_VDEC_MAX_CHN_NUM];
td_bool vpss_chn_enable[OT_VPSS_MAX_CHN_NUM];
sample_vo_cfg vo_config;
ot_vpss_grp vpss_grp;
struct timespec ts;
struct timeval tp;
int len;
ot_vdec_stream stream;
int i;
vdec_chn_num = 8;
vpss_grp_num = vdec_chn_num;
/************************************************
step1: init SYS, init common VB(for VPSS and VO), init module VB(for VDEC)
*************************************************/
ret = sample_init_sys_and_vb(&sample_vdec[0], vdec_chn_num, OT_PT_H265, OT_VDEC_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
return ret;
}
/************************************************
step2: init VDEC
*************************************************/
ret = sample_start_vdec(&sample_vdec[0], vdec_chn_num, OT_VDEC_MAX_CHN_NUM, TD_FALSE);
if (ret != TD_SUCCESS) {
goto stop_sys;
}
/* 启动时把用户图片 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");
}
/************************************************
step3: start VPSS
*************************************************/
ret = sample_start_vpss(&vpss_grp, vpss_grp_num, &vpss_chn_enable[0], TD_FALSE, OT_VPSS_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
goto stop_vdec;
}
/************************************************
step4: start VO
*************************************************/
ret = sample_start_vo(&vo_config, vpss_grp_num, TD_FALSE);
if (ret != TD_SUCCESS) {
goto stop_vpss;
}
return ret;
stop_vpss:
ret = sample_vdec_unbind_vpss(vpss_grp_num, TD_FALSE);
sample_stop_vpss(vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
stop_vdec:
sample_comm_vdec_stop(vdec_chn_num);
sample_comm_vdec_exit_vb_pool();
stop_sys:
sample_comm_sys_exit();
return ret;
}
static td_s32 sample_h265_vdec_vpss_vo(td_void)
{
td_s32 ret;
td_u32 vdec_chn_num, vpss_grp_num;
sample_vdec_attr sample_vdec[OT_VDEC_MAX_CHN_NUM];
td_bool vpss_chn_enable[OT_VPSS_MAX_CHN_NUM];
sample_vo_cfg vo_config;
ot_vpss_grp vpss_grp;
vdec_chn_num = 1;
vpss_grp_num = vdec_chn_num;
/************************************************
step1: init SYS, init common VB(for VPSS and VO), init module VB(for VDEC)
*************************************************/
ret = sample_init_sys_and_vb(&sample_vdec[0], vdec_chn_num, OT_PT_H265, OT_VDEC_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
return ret;
}
/************************************************
step2: init VDEC
*************************************************/
ret = sample_start_vdec(&sample_vdec[0], vdec_chn_num, OT_VDEC_MAX_CHN_NUM, TD_FALSE);
if (ret != TD_SUCCESS) {
goto stop_sys;
}
/************************************************
step3: start VPSS
*************************************************/
ret = sample_start_vpss(&vpss_grp, vpss_grp_num, &vpss_chn_enable[0], TD_FALSE, OT_VPSS_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
goto stop_vdec;
}
/************************************************
step4: start VO
*************************************************/
ret = sample_start_vo(&vo_config, vpss_grp_num, TD_FALSE);
if (ret != TD_SUCCESS) {
goto stop_vpss;
}
audio_init();
int i;
unsigned char buffer[2048];
ot_vdec_stream stream;
while(1){
i = recvfrom(socket_descriptor, buffer, 1472, 0, (struct sockaddr*)&clientAddr, &sock_len);
if (i > 0){
stream.pts = 0;
stream.addr = &buffer[0];
stream.len = i;
stream.end_of_frame = TD_FALSE;
stream.end_of_stream = TD_FALSE;
stream.need_display = 1;
td_s32 ret;
//do {
ret = ss_mpi_vdec_send_stream(0, &stream, 0);
// usleep(thread_param->interval_time);
//} while ((ret != TD_SUCCESS) && (thread_param->e_thread_ctrl == THREAD_CTRL_START));
}
}
/************************************************
step5: send stream to VDEC
*************************************************/
sample_send_stream_to_vdec(&sample_vdec[0], OT_VDEC_MAX_CHN_NUM, vdec_chn_num, "3840x2160_8bit.h265", TD_FALSE);
ret = sample_vpss_unbind_vo(vpss_grp_num, vo_config);
sample_comm_vo_stop_vo(&vo_config);
stop_vpss:
ret = sample_vdec_unbind_vpss(vpss_grp_num, TD_FALSE);
sample_stop_vpss(vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
stop_vdec:
sample_comm_vdec_stop(vdec_chn_num);
sample_comm_vdec_exit_vb_pool();
stop_sys:
sample_comm_sys_exit();
return ret;
}
static td_s32 sample_h264_vdec_vpss_vo(td_void)
{
td_s32 ret;
td_u32 vdec_chn_num, vpss_grp_num;
ot_vpss_grp vpss_grp;
sample_vdec_attr sample_vdec[OT_VDEC_MAX_CHN_NUM];
sample_vo_cfg vo_config;
td_bool vpss_chn_enable[OT_VPSS_MAX_CHN_NUM];
vdec_chn_num = 1;
vpss_grp_num = vdec_chn_num;
/************************************************
step1: init SYS, init common VB(for VPSS and VO), init module VB(for VDEC)
*************************************************/
ret = sample_init_sys_and_vb(&sample_vdec[0], vdec_chn_num, OT_PT_H264, OT_VDEC_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
return ret;
}
/************************************************
step2: init VDEC
*************************************************/
ret = sample_start_vdec(&sample_vdec[0], vdec_chn_num, OT_VDEC_MAX_CHN_NUM, TD_FALSE);
if (ret != TD_SUCCESS) {
goto stop_sys;
}
/************************************************
step3: start VPSS
*************************************************/
ret = sample_start_vpss(&vpss_grp, vpss_grp_num, &vpss_chn_enable[0], TD_FALSE, OT_VPSS_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
goto stop_vdec;
}
/************************************************
step4: start VO
*************************************************/
ret = sample_start_vo(&vo_config, vpss_grp_num, TD_FALSE);
if (ret != TD_SUCCESS) {
goto stop_vpss;
}
int i;
unsigned char buffer[2048];
ot_vdec_stream stream;
while(1){
i = recvfrom(socket_descriptor, buffer, 1472, 0, (struct sockaddr*)&clientAddr, &sock_len);
if (i > 0){
stream.pts = 0;
stream.addr = &buffer[0];
stream.len = i;
stream.end_of_frame = TD_FALSE;
stream.end_of_stream = TD_FALSE;
stream.need_display = 1;
td_s32 ret;
//do {
ret = ss_mpi_vdec_send_stream(0, &stream, 0);
// usleep(thread_param->interval_time);
//} while ((ret != TD_SUCCESS) && (thread_param->e_thread_ctrl == THREAD_CTRL_START));
}
}
/************************************************
step5: send stream to VDEC
*************************************************/
sample_send_stream_to_vdec(&sample_vdec[0], OT_VDEC_MAX_CHN_NUM, vdec_chn_num, "3840x2160_8bit.h264", TD_FALSE);
ret = sample_vpss_unbind_vo(vpss_grp_num, vo_config);
sample_comm_vo_stop_vo(&vo_config);
stop_vpss:
ret = sample_vdec_unbind_vpss(vpss_grp_num, TD_FALSE);
sample_stop_vpss(vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
stop_vdec:
sample_comm_vdec_stop(vdec_chn_num);
sample_comm_vdec_exit_vb_pool();
stop_sys:
sample_comm_sys_exit();
return ret;
}
static td_s32 sample_h264_vdec_vpss_vo_pip(td_void)
{
td_s32 ret;
td_u32 vdec_chn_num, vpss_grp_num;
ot_vpss_grp vpss_grp;
sample_vdec_attr sample_vdec[OT_VDEC_MAX_CHN_NUM];
sample_vo_cfg vo_config;
td_bool vpss_chn_enable[OT_VPSS_MAX_CHN_NUM];
vdec_chn_num = 1;
vpss_grp_num = 2; /* 2:vpss group cnt */
/************************************************
step1: init SYS, init common VB(for VPSS and VO), init module VB(for VDEC)
*************************************************/
ret = sample_init_sys_and_vb(&sample_vdec[0], vdec_chn_num, OT_PT_H264, OT_VDEC_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
return ret;
}
/************************************************
step2: init VDEC
*************************************************/
ret = sample_start_vdec(&sample_vdec[0], vdec_chn_num, OT_VDEC_MAX_CHN_NUM, TD_TRUE);
if (ret != TD_SUCCESS) {
goto stop_sys;
}
/************************************************
step3: start VPSS
*************************************************/
ret = sample_start_vpss(&vpss_grp, vpss_grp_num, &vpss_chn_enable[0], TD_TRUE, OT_VPSS_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
goto stop_vdec;
}
/************************************************
step4: start VO
*************************************************/
ret = sample_start_vo(&vo_config, vpss_grp_num, TD_TRUE);
if (ret != TD_SUCCESS) {
goto stop_vpss;
}
/************************************************
step5: send stream to VDEC
*************************************************/
sample_send_stream_to_vdec(&sample_vdec[0], OT_VDEC_MAX_CHN_NUM, vdec_chn_num, "3840x2160_8bit.h264", TD_TRUE);
ret = sample_vpss_unbind_vo(vpss_grp_num, vo_config);
sample_comm_vo_stop_pip(&vo_config);
sample_comm_vo_stop_vo(&vo_config);
stop_vpss:
usleep(150000); /* 150000:make sure all frames are decoded before unbind */
ret = sample_vdec_unbind_vpss(vpss_grp_num, TD_TRUE);
sample_stop_vpss(vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
stop_vdec:
sample_comm_vdec_stop(vdec_chn_num);
sample_comm_vdec_exit_vb_pool();
stop_sys:
sample_comm_sys_exit();
return ret;
}
static td_s32 sample_jpeg_vdec_vpss_vo(td_void)
{
td_s32 ret;
td_u32 vdec_chn_num, vpss_grp_num;
ot_vpss_grp vpss_grp;
sample_vdec_attr sample_vdec[OT_VDEC_MAX_CHN_NUM];
sample_vo_cfg vo_config;
td_bool vpss_chn_enable[OT_VPSS_MAX_CHN_NUM];
vdec_chn_num = 1;
vpss_grp_num = vdec_chn_num;
/************************************************
step1: init SYS, init common VB(for VPSS and VO), init module VB(for VDEC)
*************************************************/
ret = sample_init_sys_and_vb(&sample_vdec[0], vdec_chn_num, OT_PT_JPEG, OT_VDEC_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
return ret;
}
/************************************************
step2: init VDEC
*************************************************/
ret = sample_start_vdec(&sample_vdec[0], vdec_chn_num, OT_VDEC_MAX_CHN_NUM, TD_FALSE);
if (ret != TD_SUCCESS) {
goto stop_sys;
}
/************************************************
step3: start VPSS
*************************************************/
ret = sample_start_vpss(&vpss_grp, vpss_grp_num, &vpss_chn_enable[0], TD_FALSE, OT_VPSS_MAX_CHN_NUM);
if (ret != TD_SUCCESS) {
goto stop_vdec;
}
/************************************************
step4: start VO
*************************************************/
ret = sample_start_vo(&vo_config, vpss_grp_num, TD_FALSE);
if (ret != TD_SUCCESS) {
goto stop_vpss;
}
/************************************************
step5: send stream to VDEC
*************************************************/
sample_send_stream_to_vdec(&sample_vdec[0], OT_VDEC_MAX_CHN_NUM, vdec_chn_num, "3840x2160.jpg", TD_FALSE);
ret = sample_vpss_unbind_vo(vpss_grp_num, vo_config);
sample_comm_vo_stop_vo(&vo_config);
stop_vpss:
ret = sample_vdec_unbind_vpss(vpss_grp_num, TD_FALSE);
sample_stop_vpss(vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
stop_vdec:
sample_comm_vdec_stop(vdec_chn_num);
sample_comm_vdec_exit_vb_pool();
stop_sys:
sample_comm_sys_exit();
return ret;
}
static td_s32 sample_check_parameter(int argc, const char *argv0, const char *argv1, const char *argv2)
{
if ((argc != 5) || (strlen(argv1) != 1) || (strlen(argv2) != 1)) { /* 3:arg num */
printf("\n_invaild input! for examples:\n");
sample_vdec_usage(argv0);
return TD_FAILURE;
}
if (!strncmp(argv2, "1", 1)) {
g_intf_sync = OT_VO_OUT_1080P60;
} else if (!strncmp(argv2, "0", 1)) {
g_intf_sync = OT_VO_OUT_3840x2160_30;
} else {
printf("\n_invaild input! for examples:\n");
printf("\n argv2 is %s\n", argv2);
sample_vdec_usage(argv0);
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_s32 udp_init(int port){
sock_len = sizeof(clientAddr);
bzero(&address,sizeof(address));
address.sin_family=AF_INET;
address.sin_addr.s_addr=htonl(INADDR_ANY);
address.sin_port=htons(port);
socket_descriptor=socket(AF_INET,SOCK_DGRAM,0);//IPV4
bzero(&address_audio,sizeof(address_audio));
address_audio.sin_family=AF_INET;
address_audio.sin_addr.s_addr=htonl(INADDR_ANY);
address_audio.sin_port=htons(port+1);
socket_descriptor_audio=socket(AF_INET,SOCK_DGRAM,0);//IPV4
tv.tv_sec = 1;
tv.tv_usec = 0;
if (setsockopt(socket_descriptor, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
printf("socket option SO_RCVTIMEO not support\n");
return -1;
}
if (setsockopt(socket_descriptor_audio, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
printf("socket option SO_RCVTIMEO not support\n");
return -1;
}
#if 0
int recvbuf = 5*1024*1024;
int lenbuf = sizeof( recvbuf );
setsockopt( socket_descriptor, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf ) );
getsockopt( socket_descriptor, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&lenbuf );
printf( "the receive buffer size after settting is %d\n", recvbuf );
#endif
if (bind(socket_descriptor, (struct sockaddr *)&address, sizeof(address)) < 0)
{
printf("bind");
//exit(1);
return -1;
}
if (bind(socket_descriptor_audio, (struct sockaddr *)&address_audio, sizeof(address_audio)) < 0)
{
printf("bind");
//exit(1);
return -1;
}
#if 0
setsockopt( socket_descriptor, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf ) );
getsockopt( socket_descriptor, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&lenbuf );
printf( "the receive buffer size after settting is %d\n", recvbuf );
#endif
}
static td_s32 sample_choose_case(const char argv1, const char *argv0)
{
td_s32 ret;
switch (argv1) {
case '0': {
ret = sample_h265_vdec_vpss_vo();
break;
}
case '1': {
ret = sample_h264_vdec_vpss_vo();
break;
}
case '2': {
ret = sample_h264_vdec_vpss_vo_pip();
break;
}
case '3': {
ret = sample_jpeg_vdec_vpss_vo();
break;
}
default: {
sample_print("the index is invalid!\n");
sample_vdec_usage(argv0);
ret = TD_FAILURE;
break;
}
}
return ret;
}
#if 0
int *switch_memory_open(void) {
char buf[128];
int fd;
sprintf(buf, "/video_switch");
fd = shm_open(buf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if(fd < 0) { perror("shm_open"); exit(1); }
if (ftruncate(fd, 4096) == -1) { perror("ftruncate"); exit(1); }
int *retval = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
return retval;
}
#endif
int SAMPLE_VDEC_VPSS_VO_SET_MODE(int mode){
if(mode==1){
sample_comm_vo_stop_chn(SAMPLE_VO_DEV_UHD,VO_MODE_4MUX);
sample_comm_vo_start_chn(SAMPLE_VO_DEV_UHD,VO_MODE_1MUX);
ss_mpi_vdec_stop_recv_stream(1);
ss_mpi_vdec_stop_recv_stream(2);
ss_mpi_vdec_stop_recv_stream(3);
ss_mpi_vdec_reset_chn(1);
ss_mpi_vdec_reset_chn(2);
ss_mpi_vdec_reset_chn(3);
}else if(mode==5){
ss_mpi_vo_clear_chn_buf(0,1,TD_TRUE);
ss_mpi_vo_clear_chn_buf(0,2,TD_TRUE);
ss_mpi_vo_clear_chn_buf(0,3,TD_TRUE);
ss_mpi_vdec_start_recv_stream(1);
ss_mpi_vdec_start_recv_stream(2);
ss_mpi_vdec_start_recv_stream(3);
sleep(2);
sample_comm_vo_stop_chn(SAMPLE_VO_DEV_UHD,VO_MODE_1MUX);
sample_comm_vo_start_chn(SAMPLE_VO_DEV_UHD,VO_MODE_4MUX);
}
}
/******************************************************************************
* function : main()
* description : video vdec sample
******************************************************************************/
#ifdef __LITEOS__
int app_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
td_s32 ret;
td_s32 i;
int fd_fs;
// int *video_switch;
volatile int switch_mode=0; //默认双屏
volatile int switch_mode_pre=0;
g_intf_sync = OT_VO_OUT_1920x1200_60;
//g_intf_sync = OT_VO_OUT_1080P60;
#ifndef __LITEOS__
sample_sys_signal(sample_vdec_handle_sig);
#endif
h265_vdec_vpss_vo();
init_udp_pthread();
// printf("udp\n");
// switch_video = switch_memory_open();
// video_switch = switch_memory_open();
// switch_mode = video_switch[0];
// switch_video[0]=2;
// switch_mode = switch_video[0];
switch_mode = switch_video[0];
switch_mode_pre = switch_mode;
if(argc==2){
fd_fs = open(argv[1], O_RDWR | O_CREAT);
if(fd_fs < 0) {
printf("open %s failed\n", argv[1]);
return -1;
}
}
//switch_mode=2;
printf("hello\n");
printf("++++++%x \n",switch_mode);
sample_vo_chn_switch(switch_mode);
while(1){
#if 1
switch_mode = switch_video[0];
//switch_mode = video_switch[0];
//printf("--w+++++%x \n",switch_mode);
//sample_comm_vo_stop_chn(SAMPLE_VO_DEV_UHD,VO_MODE_4MUX);
//sample_comm_vo_start_chn(SAMPLE_VO_DEV_UHD,VO_MODE_1MUX);
if(switch_mode != switch_mode_pre){
printf("hello\n");
printf("++++++%x \n",switch_mode);
sample_vo_chn_switch(switch_mode);
// SAMPLE_VDEC_VPSS_VO_SET_MODE(switch_mode);
switch_mode_pre = switch_mode;
}
//sleep(1);
usleep(100 * 1000); /*100ms 轮询一次*/
}
#endif
#if 0
video_switch[0]= 0xAA;
sample_comm_vo_stop_chn(SAMPLE_VO_DEV_UHD,VO_MODE_4MUX);
sample_comm_vo_start_chn(SAMPLE_VO_DEV_UHD,VO_MODE_1MUX);
sleep(10);
video_switch[0]= 0x55;
ss_mpi_vdec_stop_recv_stream(1);
ret=ss_mpi_vdec_reset_chn(1);
//printf("+++++++reset_chn%d\n",ret);
//ret=ss_mpi_vpss_reset_grp(1);
//printf("+++++++reset_vpss%d\n",ret);
ss_mpi_vdec_start_recv_stream(1);
ss_mpi_vo_clear_chn_buf(0,1,TD_TRUE);
sleep(2);
ss_mpi_vo_clear_chn_buf(0,1,TD_TRUE);
sample_comm_vo_stop_chn(SAMPLE_VO_DEV_UHD,VO_MODE_1MUX);
sample_comm_vo_start_chn(SAMPLE_VO_DEV_UHD,VO_MODE_4MUX);
// ss_mpi_vdec_stop_recv_stream(1);
// ss_mpi_vdec_reset_chn(1);
// ss_mpi_vdec_start_recv_stream(1);
#endif
sleep(1);
//}
// return ret;
}