1552 lines
48 KiB
C
Executable File
1552 lines
48 KiB
C
Executable File
/*
|
|
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 "dqueue.h"
|
|
#include <sys/mman.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 3840
|
|
#define STREAM_HEIGHT 2160
|
|
#define REF_NUM 2
|
|
#define DISPLAY_NUM 2
|
|
|
|
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;
|
|
|
|
#define NUM_NAL_BUF (20)
|
|
#define NAL_BUF_SIZE (1024*1024)
|
|
#define VID_BUF_SIZE (1024*1024)
|
|
typedef struct tnal_buf {
|
|
int len;
|
|
uint8_t *buf;
|
|
} nal_buf;
|
|
int fd_fs;
|
|
nal_buf nal_buf_entry[NUM_NAL_BUF];
|
|
|
|
unsigned char nal_header[4]={0x00,0x00,0x00,0x01};
|
|
unsigned char buffer_nal[2048];
|
|
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
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;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int socket_descriptor;
|
|
static int socket_descriptor1;
|
|
static struct sockaddr_in address;
|
|
static struct sockaddr_in address1;
|
|
static struct sockaddr_in clientAddr;
|
|
static struct timeval tv;
|
|
int sock_len;
|
|
|
|
int fd_param_uart;
|
|
int fd_param;
|
|
int *buffer_param;
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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.intf_sync = OT_VO_OUT_1080P60;
|
|
g_vdec_display_cfg.intf_sync = OT_VO_OUT_1920x1200_60;
|
|
//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 = 1;
|
|
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);
|
|
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_1MUX;
|
|
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;
|
|
}
|
|
void* h265_vdec_vpss_vo(void *ctx)
|
|
{
|
|
td_s32 ret;
|
|
#if 0
|
|
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;
|
|
#endif
|
|
struct timespec ts;
|
|
struct timeval tp;
|
|
nal_buf *p_nal;
|
|
int len;
|
|
ot_vdec_stream stream;
|
|
int i;
|
|
|
|
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();
|
|
|
|
|
|
//sample_send_stream_to_vdec(&sample_vdec[0], OT_VDEC_MAX_CHN_NUM, vdec_chn_num, "3840x2160_8bit.h265", TD_FALSE);
|
|
while(!do_exit_inner) {
|
|
pthread_mutex_lock(&vid_au_mutex);
|
|
gettimeofday(&tp, NULL);
|
|
ts.tv_sec = tp.tv_sec+1;
|
|
ts.tv_nsec = tp.tv_usec * 1000;
|
|
|
|
if(!dq_empty(vid_au_q))
|
|
{
|
|
p_nal = (nal_buf *)dq_deq_back(vid_au_q);
|
|
vid_q_len--;
|
|
len = vid_q_len;
|
|
if(len > 3) {
|
|
printf("++f %d\n",len);
|
|
for(i=0; i<len; i++) {
|
|
p_nal = (nal_buf *)dq_deq_back(vid_au_q);
|
|
vid_q_len--;
|
|
}
|
|
pthread_mutex_unlock(&vid_au_mutex);
|
|
printf("--f\n");
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
len = pthread_cond_timedwait(&vid_au_cond, &vid_au_mutex, &ts);
|
|
if(len == ETIMEDOUT)
|
|
{
|
|
pthread_mutex_unlock(&vid_au_mutex);
|
|
continue;
|
|
}
|
|
else {
|
|
p_nal = (nal_buf *)dq_deq_back(vid_au_q);
|
|
vid_q_len--;
|
|
}
|
|
|
|
}
|
|
pthread_mutex_unlock(&vid_au_mutex);
|
|
|
|
|
|
stream.pts = 0;
|
|
stream.addr = p_nal->buf;
|
|
stream.len = p_nal->len;
|
|
stream.end_of_frame = TD_TRUE;
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
|
bzero(&address1,sizeof(address1));
|
|
address1.sin_family=AF_INET;
|
|
address1.sin_addr.s_addr=inet_addr("127.0.0.1");
|
|
address1.sin_port=htons(12565);
|
|
|
|
socket_descriptor1=socket(AF_INET,SOCK_DGRAM,0);//IPV4
|
|
|
|
|
|
tv.tv_sec = 3;
|
|
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 1
|
|
if (setsockopt(socket_descriptor1, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
|
|
printf("socket1 option SO_RCVTIMEO not support\n");
|
|
return -1;
|
|
}
|
|
#endif
|
|
#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
|
|
i
|
|
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
|
|
td_s32 insert_usr_pic(sample_vi_config* pstViConfig)
|
|
{
|
|
td_s32 s32Ret = TD_SUCCESS;
|
|
td_s32 i, j;
|
|
td_s32 s32ViNum;
|
|
sample_sns_type enSnsType;
|
|
sample_vi_info *pstViInfo = TD_NULL;
|
|
ot_vi_user_pic_attr *pstVFrameInfo;
|
|
td_u32 u32LStride = 0;
|
|
td_u32 u32CStride = 0;
|
|
td_u32 u32LumaSize = 0;
|
|
td_u32 u32ChrmSize = 0;
|
|
td_u32 u32Size = 0;
|
|
ot_vb_blk VbBlk;
|
|
td_u64 u64PhyAddr;
|
|
td_void *ppVirAddr;
|
|
td_u8 *p, *puv, *pu, *pv;
|
|
FILE *fpic = NULL;
|
|
td_u32 u32Width = 1920;
|
|
td_u32 u32Height = 1080;
|
|
// VI_PIPE_FRAME_SOURCE_E penSource;
|
|
|
|
//s32ViNum = pstViConfig->pipe_info.as32WorkingViId[0];
|
|
pstViInfo = &pstViConfig->vi_mode;
|
|
enSnsType = pstViInfo->sns_info;
|
|
|
|
pstVFrameInfo = (ot_vi_user_pic_attr*)calloc(1, sizeof(ot_vi_user_pic_attr));
|
|
|
|
if (sample_sns_type == enSnsType)
|
|
{
|
|
u32LStride = (u32Width + 15) & ( ~(15) );
|
|
u32LumaSize = (u32LStride * u32Height);
|
|
u32ChrmSize = (u32CStride * u32Height) >> 2;/* 420*/
|
|
u32Size = u32LumaSize + (u32ChrmSize << 1);
|
|
|
|
/* get video buffer block form common pool */
|
|
VbBlk = HI_MPI_VB_GetBlock(OT_VB_INVALID_POOL_ID, u32Size, NULL);
|
|
if (OT_VB_INVALID_HANDLE == VbBlk)
|
|
{
|
|
sample_print("get YUV vb block failed\n");
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
/* get physical address*/
|
|
u64PhyAddr = HI_MPI_VB_Handle2PhysAddr(VbBlk);
|
|
if (0 == u64PhyAddr)
|
|
{
|
|
sample_print("get YUV vb block phy addr failed\n");
|
|
return TD_FAILURE;
|
|
}
|
|
sample_print("u64PhyAddr: %#x\n", u64PhyAddr);
|
|
|
|
/* get pool id */
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId = HI_MPI_VB_Handle2PoolId(VbBlk);
|
|
if (VB_INVALID_POOLID == pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId)
|
|
{
|
|
sample_print("get YUV vb pool id failed\n");
|
|
return TD_FAILURE;
|
|
}
|
|
sample_print("u32PoolId: %d\n", pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId);
|
|
|
|
/* mmap physical address to virtual address*/
|
|
s32Ret = HI_MPI_VB_MmapPool(pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId);
|
|
if(s32Ret != TD_SUCCESS)
|
|
{
|
|
sample_print("get YUV vb pool id failed with: 0x%x\n", s32Ret);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
s32Ret = HI_MPI_VB_GetBlockVirAddr(pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId, u64PhyAddr, (void **)&ppVirAddr);
|
|
if(s32Ret != TD_SUCCESS)
|
|
{
|
|
HI_MPI_VB_ReleaseBlock(VbBlk);
|
|
HI_MPI_VB_MunmapPool(pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId);
|
|
|
|
sample_print("HI_MPI_VB_GetBlkVirAddr failed with: %#x", s32Ret);
|
|
return TD_FAILURE;
|
|
}
|
|
//sample_print("ppVirAddr: %#x", ppVirAddr);
|
|
|
|
/* now you need get YUV Semi Palnar Data ,fill them to the virtual address */
|
|
puv = malloc(u32Size);
|
|
if(puv == NULL)
|
|
{
|
|
sample_print("pyuv malloc failed");
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
p = ppVirAddr;
|
|
fpic = fopen(pUserpicName,"rb");
|
|
if (fpic == NULL)
|
|
{
|
|
sample_print("can't open file %s", pUserpicName);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
/* read the data of Y component*/
|
|
fread(p, 1, u32Height * u32LStride, fpic);
|
|
|
|
/* read the data of UV component*/
|
|
fread(puv, 1, (u32Height * u32LStride) >> 1, fpic);
|
|
pu = puv;
|
|
pv = puv + ((u32Height * u32LStride) >> 2);
|
|
|
|
p = ppVirAddr + (u32Height * u32LStride);
|
|
|
|
for (i = 0; i < (u32Height >> 1); i++)
|
|
{
|
|
for (j=0; j<(u32Width >> 1); j++)
|
|
{
|
|
p[j*2+1] = pu[j];
|
|
p[j*2+0] = pv[j];
|
|
}
|
|
|
|
pu += u32LStride >> 1; //u32YStride
|
|
pv += u32LStride >> 1;
|
|
p += u32LStride;
|
|
}
|
|
|
|
free(puv);
|
|
puv = TD_NULL;
|
|
fclose(fpic);
|
|
|
|
pstVFrameInfo->enUsrPicMode = VI_USERPIC_MODE_PIC;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[0] = u64PhyAddr;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[1] = pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[0] + u32LumaSize;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[2] = pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[1] + u32ChrmSize;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[0] = ppVirAddr;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[1] = pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[0] + u32LumaSize;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[2] = pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[1] + u32ChrmSize;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Width = u32Width;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Height = u32Height;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Stride[0] = u32LStride;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Stride[1] = u32LStride;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Stride[2] = u32LStride;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.enCompressMode = COMPRESS_MODE_NONE;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.enVideoFormat = VIDEO_FORMAT_LINEAR;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.enField = VIDEO_FIELD_FRAME;
|
|
pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.enPixelFormat = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
|
|
|
|
//HI_MPI_VI_GetPipeFrameSource(0, &penSource);
|
|
//sample_print("PIPE_FRAME_SOURCE: %d\n", penSource);
|
|
|
|
s32Ret = HI_MPI_VI_SetPipeFrameSource(0, VI_PIPE_FRAME_SOURCE_DEV);
|
|
if (TD_SUCCESS != s32Ret)
|
|
{
|
|
sample_print("HI_MPI_VI_SetPipeFrameSource failed with: 0x%x\n", s32Ret);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
/* first set user pic info*/
|
|
s32Ret = HI_MPI_VI_SetUserPic(0, pstVFrameInfo);
|
|
if (TD_SUCCESS != s32Ret)
|
|
{
|
|
sample_print("HI_MPI_VI_SetUserPic failed with: 0x%x\n", s32Ret);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
/* enable insert user pic if you need */
|
|
s32Ret = HI_MPI_VI_EnableUserPic(0);
|
|
if (TD_SUCCESS != s32Ret)
|
|
{
|
|
sample_print("HI_MPI_VI_EnableUserPic failed with: 0x%x\n", s32Ret);
|
|
return TD_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* disable insert user pic if you don't need */
|
|
s32Ret = HI_MPI_VI_DisableUserPic(0);
|
|
if (TD_SUCCESS != s32Ret)
|
|
{
|
|
sample_print("HI_MPI_VI_DisableUserPic failed with: 0x%x\n", s32Ret);
|
|
return TD_FAILURE;
|
|
}
|
|
}
|
|
|
|
return s32Ret;
|
|
}
|
|
|
|
#endif
|
|
void assemble_nal(unsigned char* buf, unsigned int len)
|
|
{
|
|
static int wr_idx = 0;
|
|
static int nalb_idx = 0;
|
|
uint64_t timestamp;
|
|
int need_sumbit, terminate;
|
|
if((wr_idx + len) >= VID_BUF_SIZE) {
|
|
printf("assemble_nal panic: too many error in pakts\r\n");
|
|
wr_idx = 0;
|
|
}
|
|
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_entry[nalb_idx].buf + wr_idx, buf, len);
|
|
wr_idx += len;
|
|
}
|
|
else { //terminate current nal item and submit
|
|
need_sumbit = 1;
|
|
terminate = 1;
|
|
}
|
|
if(need_sumbit) {
|
|
nal_buf_entry[nalb_idx].len = wr_idx;
|
|
pthread_mutex_lock(&vid_au_mutex);
|
|
vid_q_len++;
|
|
dq_enq_front(vid_au_q, (void *)&nal_buf_entry[nalb_idx]);
|
|
pthread_cond_signal(&vid_au_cond);
|
|
pthread_mutex_unlock(&vid_au_mutex);
|
|
|
|
|
|
wr_idx = 0;
|
|
nalb_idx = (nalb_idx+1)%NUM_NAL_BUF;
|
|
}
|
|
if(terminate) {
|
|
memcpy(nal_buf_entry[nalb_idx].buf + wr_idx, buf, len);
|
|
wr_idx += len;
|
|
}
|
|
}else {
|
|
memcpy(nal_buf_entry[nalb_idx].buf + wr_idx, buf, len);
|
|
wr_idx += len;
|
|
if(memcmp(nal_buf_entry[nalb_idx].buf, nal_header, 4)) { //wait nal head
|
|
wr_idx = 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void pthread_init(){
|
|
int len;
|
|
pthread_mutex_init(&vid_au_mutex, NULL);
|
|
pthread_cond_init(&vid_au_cond, NULL);
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
|
len = pthread_create(&vid_au_thread, &attr, h265_vdec_vpss_vo, NULL);
|
|
pthread_attr_destroy(&attr);
|
|
vid_au_q = dq_create();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* function : main()
|
|
* description : video vdec sample
|
|
******************************************************************************/
|
|
#ifdef __LITEOS__
|
|
int app_main(int argc, char *argv[])
|
|
#else
|
|
int main(int argc, char *argv[])
|
|
#endif
|
|
{
|
|
sample_vdec_attr sample_vdec[OT_VDEC_MAX_CHN_NUM];
|
|
|
|
td_s32 ret;
|
|
td_s32 i;
|
|
int fd_fs;
|
|
int clear_buf=0;
|
|
int first=0;
|
|
int first_pre=0;
|
|
ret = sample_check_parameter(argc, argv[0], argv[1], argv[2]); /* 2:array index */
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
sample_vo_cfg *vo_config;
|
|
#ifndef __LITEOS__
|
|
sample_sys_signal(sample_vdec_handle_sig);
|
|
#endif
|
|
for(i=0; i<NUM_NAL_BUF; i++) {
|
|
nal_buf_entry[i].buf = (uint8_t *) malloc(NAL_BUF_SIZE);
|
|
if(!nal_buf_entry[i].buf) {
|
|
printf("allocate nal buf failed\r\n");
|
|
return -1;
|
|
}
|
|
memset(nal_buf_entry[i].buf, 0x0, NAL_BUF_SIZE);
|
|
}
|
|
|
|
|
|
|
|
udp_init(atoi(argv[3]));
|
|
pthread_init();
|
|
|
|
if(argc==5){
|
|
|
|
fd_fs = open(argv[4], O_RDWR | O_CREAT);
|
|
if(fd_fs < 0) {
|
|
printf("open %s failed\n", argv[1]);
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
|
|
fd_param = shm_open("/param.txt",O_RDWR|O_CREAT|O_EXCL,0777);
|
|
if(fd_param < 0){
|
|
fd_param = shm_open("/param.txt",O_RDWR,0777);
|
|
}else
|
|
ftruncate(fd_param,4096);
|
|
buffer_param= mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd_param,0);
|
|
|
|
|
|
while(1){
|
|
i = recvfrom(socket_descriptor, buffer_nal, 1472, 0, (struct sockaddr*)&clientAddr, &sock_len);
|
|
|
|
if(i>0){
|
|
|
|
buffer_param[0]= 0xaa;
|
|
write(fd_fs,buffer_nal,i);
|
|
first=1;
|
|
assemble_nal(buffer_nal,i);
|
|
}
|
|
|
|
if(i<=0){
|
|
buffer_param[0]= 0x55;
|
|
ss_mpi_vdec_stop_recv_stream(0);
|
|
ss_mpi_vdec_stop_recv_stream(1);
|
|
ss_mpi_vdec_stop_recv_stream(2);
|
|
ss_mpi_vdec_stop_recv_stream(3);
|
|
ret=ss_mpi_vdec_reset_chn(0);
|
|
ret=ss_mpi_vdec_reset_chn(1);
|
|
ret=ss_mpi_vdec_reset_chn(2);
|
|
ret=ss_mpi_vdec_reset_chn(3);
|
|
//printf("+++++++reset_chn%d\n",ret);
|
|
// ss_mpi_vdec_start_recv_stream(1);
|
|
ss_mpi_vo_clear_chn_buf(0,0,TD_TRUE);
|
|
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);
|
|
|
|
//sample_comm_vo_start_vo(&vo_config);
|
|
//ss_mpi_vo_clear_chn_buf(0,1,TD_TRUE);
|
|
ss_mpi_vdec_start_recv_stream(0);
|
|
ss_mpi_vdec_start_recv_stream(1);
|
|
ss_mpi_vdec_start_recv_stream(2);
|
|
ss_mpi_vdec_start_recv_stream(3);
|
|
|
|
ss_mpi_vo_clear_chn_buf(0,0,TD_TRUE);
|
|
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);
|
|
|
|
|
|
|
|
//sample_send_stream_to_vdec(&sample_vdec[0], OT_VDEC_MAX_CHN_NUM, vdec_chn_num, "3840x2160.jpg", TD_FALSE);
|
|
|
|
// ret = ss_mpi_vdec_send_stream(0, &stream, 0);
|
|
//sample_send_stream_to_vdec(&sample_vdec[0], OT_VDEC_MAX_CHN_NUM, vdec_chn_num, "3840x2160.jpg", TD_FALSE);
|
|
// sample_send_stream_to_vdec(&sample_vdec[0], OT_VDEC_MAX_CHN_NUM, vdec_chn_num, "3840x2160_8bit.h265", TD_FALSE);
|
|
|
|
}else
|
|
{
|
|
|
|
sendto(socket_descriptor1,buffer_nal,i,0,(struct sockaddr *)&address1,sizeof(address1));
|
|
}
|
|
//if(clear_buf==1){
|
|
// ss_mpi_vo_clear_chn_buf(0,1,TD_TRUE);
|
|
// ss_mpi_vdec_start_recv_stream(1);
|
|
//}
|
|
|
|
if((first == 1) && (first_pre==0)){
|
|
first_pre = 1;
|
|
system("/root/test_ssd2828");
|
|
}
|
|
|
|
}
|
|
#if 0
|
|
/******************************************
|
|
choose the case
|
|
******************************************/
|
|
ret = sample_choose_case(*argv[1], argv[0]);
|
|
if (ret == TD_SUCCESS && g_sample_exit == 0) {
|
|
sample_print("program exit normally!\n");
|
|
} else {
|
|
sample_print("program exit abnormally!\n");
|
|
}
|
|
#endif
|
|
return ret;
|
|
}
|