Files

1936 lines
61 KiB
C

/*
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include "sample_comm.h"
#include "securec.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* end of #ifdef __cplusplus */
#define PIC_SIZE PIC_1080P
#define BIG_STREAM_SIZE PIC_1080P
#define SMALL_STREAM_SIZE PIC_D1_NTSC
#define ENTER_ASCII 10
#define VB_MAX_NUM 10
#define CHN_NUM_MAX 2
typedef struct {
ot_size max_size;
ot_pixel_format pixel_format;
ot_size output_size[OT_VPSS_MAX_PHYS_CHN_NUM];
ot_compress_mode compress_mode[OT_VPSS_MAX_PHYS_CHN_NUM];
td_bool enable[OT_VPSS_MAX_PHYS_CHN_NUM];
} sample_venc_vpss_chn_attr;
typedef struct {
td_u32 valid_num;
td_u64 blk_size[OT_VB_MAX_COMMON_POOLS];
td_u32 blk_cnt[OT_VB_MAX_COMMON_POOLS];
td_u32 supplement_config;
} sample_venc_vb_attr;
typedef struct {
ot_vpss_chn vpss_chn[CHN_NUM_MAX];
ot_venc_chn venc_chn[CHN_NUM_MAX];
} sample_venc_vpss_chn;
/******************************************************************************
* function : show usage
******************************************************************************/
static td_void sample_venc_usage(td_char *s_prg_nm)
{
printf("usage : %s [index] \n", s_prg_nm);
printf("index:\n");
printf("\t 0) normal :H.265e@1080P@30fps + h264e@D1@30fps.\n");
printf("\t 1) qpmap :H.265e@1080P@30fps + h264e@1080P@30fps.\n");
printf("\t 2) intra_refresh :H.265e@1080P@30fps(row) + h264e@1080P@30fps(column).\n");
printf("\t 3) roi_bg_frame_rate:H.265e@1080P@30fps + H.264@1080P@30fps.\n");
printf("\t 4) debreath_effect :H.265e@1080P@30fps(enable) + H.265e@1080P@30fps(disable).\n");
printf("\t 5) roi_set :Mjpege@1080P@30fps(user set roi info by API).\n");
printf("\t 6) roimap :Mjpege@1080P@30fps(user customize every region).\n");
}
static td_bool g_sample_venc_exit = TD_FALSE;
/******************************************************************************
* function : to process abnormal case
******************************************************************************/
static td_void sample_venc_handle_sig(td_s32 signo)
{
if (g_sample_venc_exit == TD_TRUE) {
return;
}
if (signo == SIGINT || signo == SIGTERM) {
g_sample_venc_exit = TD_TRUE;
}
}
static td_s32 sample_venc_getchar()
{
td_s32 c;
if (g_sample_venc_exit == TD_TRUE) {
printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
return 'e';
}
c = getchar();
if (g_sample_venc_exit == TD_TRUE) {
printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
return 'e';
}
return c;
}
static td_s32 get_gop_mode(ot_venc_gop_mode *gop_mode)
{
td_s32 c[2] = {'\0'}; /* 2: len */
begin_get:
printf("please input choose gop mode!\n");
printf("\t 0) normal p.\n");
printf("\t 1) smart p.\n");
c[0] = sample_venc_getchar();
if (c[0] == 'e') {
return TD_FAILURE;
} else if ((c[0] == ENTER_ASCII) || ((c[0] != '0') && (c[0] != '1'))) {
sample_print("invalid input! please try again.\n");
while (sample_venc_getchar() != ENTER_ASCII) {
}
goto begin_get;
}
c[1] = sample_venc_getchar();
if (c[1] != ENTER_ASCII) {
sample_print("invalid input! please try again.\n");
while (sample_venc_getchar() != ENTER_ASCII) {
}
goto begin_get;
}
switch (c[0]) {
case '0':
*gop_mode = OT_VENC_GOP_MODE_NORMAL_P;
break;
case '1':
*gop_mode = OT_VENC_GOP_MODE_SMART_P;
break;
default:
sample_print("input invalid!\n");
goto begin_get;
}
return TD_SUCCESS;
}
static td_void print_rc_mode(ot_payload_type type)
{
printf("please input choose rc mode!\n");
printf("\t c) cbr.\n");
printf("\t v) vbr.\n");
if (type != OT_PT_MJPEG) {
printf("\t a) avbr.\n");
printf("\t x) cvbr.\n");
printf("\t q) qvbr.\n");
}
printf("\t f) fix_qp\n");
}
static td_s32 get_rc_mode(ot_payload_type type, sample_rc *rc_mode)
{
td_s32 c[2] = {'\0'}; /* 2: len */
begin_get:
if (type != OT_PT_JPEG) {
print_rc_mode(type);
c[0] = sample_venc_getchar();
if (c[0] == 'e') {
return TD_FAILURE;
} else if ((c[0] == ENTER_ASCII) || ((c[0] != 'c') && (c[0] != 'v') && (c[0] != 'a') && (c[0] != 'x') &&
(c[0] != 'q') && (c[0] != 'f'))) {
sample_print("invalid input! please try again.\n");
while (sample_venc_getchar() != ENTER_ASCII) {
}
goto begin_get;
}
c[1] = sample_venc_getchar();
if (c[1] != ENTER_ASCII) {
sample_print("invalid input! please try again.\n");
while (sample_venc_getchar() != ENTER_ASCII) {
}
goto begin_get;
}
switch (c[0]) {
case 'c':
*rc_mode = SAMPLE_RC_CBR;
break;
case 'v':
*rc_mode = SAMPLE_RC_VBR;
break;
case 'a':
*rc_mode = SAMPLE_RC_AVBR;
break;
case 'x':
*rc_mode = SAMPLE_RC_CVBR;
break;
case 'q':
*rc_mode = SAMPLE_RC_QVBR;
break;
case 'f':
*rc_mode = SAMPLE_RC_FIXQP;
break;
default:
sample_print("input invalid!\n");
goto begin_get;
}
}
return TD_SUCCESS;
}
static td_s32 get_intra_refresh_mode(ot_venc_intra_refresh_mode *intra_refresh_mode)
{
td_s32 c[2] = {'\0'}; /* 2: len */
begin_get:
printf("please input choose intra refresh mode!\n");
printf("\t r) row.\n");
printf("\t c) column.\n");
c[0] = sample_venc_getchar();
if (c[0] == 'e') {
return TD_FAILURE;
} else if ((c[0] == ENTER_ASCII) || ((c[0] != 'c') && (c[0] != 'r'))) {
sample_print("invalid input! please try again.\n");
while (sample_venc_getchar() != ENTER_ASCII) {
}
goto begin_get;
}
c[1] = sample_venc_getchar();
if (c[1] != ENTER_ASCII) {
sample_print("invalid input! please try again.\n");
while (sample_venc_getchar() != ENTER_ASCII) {
}
goto begin_get;
}
switch (c[0]) {
case 'r':
*intra_refresh_mode = OT_VENC_INTRA_REFRESH_ROW;
break;
case 'c':
*intra_refresh_mode = OT_VENC_INTRA_REFRESH_COLUMN;
break;
default:
sample_print("input invalid!\n");
goto begin_get;
}
return TD_SUCCESS;
}
static td_void get_vb_attr(const ot_size *vi_size, const sample_venc_vpss_chn_attr *vpss_chn_attr,
sample_venc_vb_attr *vb_attr)
{
td_s32 i;
ot_pic_buf_attr pic_buf_attr = {0};
vb_attr->valid_num = 0;
// vb for vi-vpss
pic_buf_attr.width = vi_size->width;
pic_buf_attr.height = vi_size->height;
pic_buf_attr.align = OT_DEFAULT_ALIGN;
pic_buf_attr.bit_width = OT_DATA_BIT_WIDTH_8;
pic_buf_attr.pixel_format = SAMPLE_PIXEL_FORMAT;
pic_buf_attr.compress_mode = OT_COMPRESS_MODE_SEG_COMPACT;
vb_attr->blk_size[vb_attr->valid_num] = ot_common_get_pic_buf_size(&pic_buf_attr);
vb_attr->blk_cnt[vb_attr->valid_num] = 4; // 4: vb num
vb_attr->valid_num++;
// vb for vpss-venc(big stream)
if (vb_attr->valid_num >= OT_VB_MAX_COMMON_POOLS) {
return;
}
for (i = 0; i < OT_VPSS_MAX_PHYS_CHN_NUM && vb_attr->valid_num < OT_VB_MAX_COMMON_POOLS; i++) {
if (vpss_chn_attr->enable[i] == TD_TRUE) {
pic_buf_attr.width = vpss_chn_attr->output_size[i].width;
pic_buf_attr.height = vpss_chn_attr->output_size[i].height;
pic_buf_attr.align = OT_DEFAULT_ALIGN;
pic_buf_attr.bit_width = OT_DATA_BIT_WIDTH_8;
pic_buf_attr.pixel_format = vpss_chn_attr->pixel_format;
pic_buf_attr.compress_mode = vpss_chn_attr->compress_mode[i];
vb_attr->blk_size[vb_attr->valid_num] = ot_common_get_pic_buf_size(&pic_buf_attr);
vb_attr->blk_cnt[vb_attr->valid_num] = 3; // 3: vb num
vb_attr->valid_num++;
}
}
}
static td_void get_default_vi_cfg(sample_vi_config *vi_cfg)
{
#if SAMPLE_AD_TYPE == AD_NVP6158
vi_cfg->vi_mode = SAMPLE_VI_MODE_720P_2X2;
#elif SAMPLE_AD_TYPE == AD_TP2854B || SAMPLE_AD_TYPE == AD_TP2856
vi_cfg->vi_mode = SAMPLE_VI_MODE_1080P_1X2;
#endif
vi_cfg->video_encoding = SAMPLE_VIDEO_ENCODING_NTSC;
}
static ot_size get_vi_size_from_mode(sample_vi_mode vi_mode)
{
td_s32 ret;
ot_size vi_size = { 0 };
ot_pic_size vi_pic_size;
ret = sample_common_vi_get_size_by_mode(vi_mode, &vi_pic_size);
if (ret != TD_SUCCESS) {
sample_print("get size by mode failed!\n");
goto exit;
}
ret = sample_comm_sys_get_pic_size(vi_pic_size, &vi_size);
if (ret != TD_SUCCESS) {
sample_print("get pic size failed!\n");
goto exit;
}
exit:
return vi_size;
}
static td_void get_default_vpss_chn_attr(ot_size vi_size, ot_size enc_size[], td_s32 len,
sample_venc_vpss_chn_attr *vpss_chan_attr)
{
td_s32 i;
td_u32 max_width, max_height;
if (memset_s(vpss_chan_attr, sizeof(sample_venc_vpss_chn_attr), 0, sizeof(sample_venc_vpss_chn_attr)) != EOK) {
printf("vpss chn attr call memset_s error\n");
return;
}
max_width = vi_size.width;
max_height = vi_size.height;
for (i = 0; (i < len) && (i < OT_VPSS_MAX_PHYS_CHN_NUM); i++) {
vpss_chan_attr->output_size[i].width = enc_size[i].width;
vpss_chan_attr->output_size[i].height = enc_size[i].height;
vpss_chan_attr->compress_mode[i] = (i == 0) ? OT_COMPRESS_MODE_SEG_COMPACT : OT_COMPRESS_MODE_NONE;
vpss_chan_attr->enable[i] = TD_TRUE;
max_width = MAX2(max_width, enc_size[i].width);
max_height = MAX2(max_height, enc_size[i].height);
}
vpss_chan_attr->max_size.width = max_width;
vpss_chan_attr->max_size.height = max_height;
vpss_chan_attr->pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
return;
}
static td_s32 sample_venc_sys_init(sample_venc_vb_attr *vb_attr)
{
td_s32 ret;
td_u32 i;
ot_vb_cfg vb_cfg = {0};
if (vb_attr->valid_num > OT_VB_MAX_COMMON_POOLS) {
sample_print("sample_venc_sys_init vb valid num(%d) too large than OT_VB_MAX_COMMON_POOLS(%d)!\n",
vb_attr->valid_num, OT_VB_MAX_COMMON_POOLS);
return TD_FAILURE;
}
for (i = 0; i < vb_attr->valid_num; i++) {
vb_cfg.common_pool[i].blk_size = vb_attr->blk_size[i];
vb_cfg.common_pool[i].blk_cnt = vb_attr->blk_cnt[i];
}
vb_cfg.max_pool_cnt = vb_attr->valid_num;
if (vb_attr->supplement_config == 0) {
ret = sample_comm_sys_init(&vb_cfg);
} else {
ret = sample_comm_sys_init_with_vb_supplement(&vb_cfg, vb_attr->supplement_config);
}
if (ret != TD_SUCCESS) {
sample_print("sample_venc_sys_init failed!\n");
}
return ret;
}
static td_s32 sample_venc_vi_init(sample_vi_config *vi_cfg)
{
td_s32 ret;
sample_vi_param vi_param;
/* get parameter from vi mode */
ret = sample_common_vi_mode_to_param(vi_cfg->vi_mode, &vi_param);
if (ret != TD_SUCCESS) {
sample_print("vi get param failed!\n");
return ret;
}
vi_param.vi_dev_cnt = 1;
vi_param.vi_chn_cnt = 1;
vi_param.minor_attr_en = TD_FALSE;
ret = sample_common_vi_start_vi(vi_cfg->vi_mode, vi_cfg->video_encoding, &vi_param);
if (ret != TD_SUCCESS) {
sample_print("start vi failed with 0x%x!\n", ret);
}
ot_vi_chn_attr attr;
ss_mpi_vi_get_chn_attr(0, &attr);
attr.src_frame_rate = -1;
attr.dst_frame_rate = -1;
ss_mpi_vi_set_chn_attr(0, &attr);
return ret;
}
static td_void sample_venc_vi_deinit(sample_vi_config *vi_cfg)
{
td_s32 ret;
sample_vi_param vi_param;
/* get parameter from vi mode */
ret = sample_common_vi_mode_to_param(vi_cfg->vi_mode, &vi_param);
if (ret != TD_SUCCESS) {
sample_print("vi get param failed!\n");
return;
}
vi_param.vi_dev_cnt = 1;
vi_param.vi_chn_cnt = 1;
vi_param.minor_attr_en = TD_FALSE;
ret = sample_common_vi_stop(vi_cfg->vi_mode, &vi_param);
if (ret != TD_SUCCESS) {
sample_print("stop vi failed with 0x%x!\n", ret);
}
}
static td_s32 sample_venc_vpss_init(ot_vpss_grp vpss_grp, sample_venc_vpss_chn_attr *vpss_chan_cfg)
{
td_s32 ret;
ot_vpss_chn vpss_chn;
ot_vpss_grp_attr grp_attr = { 0 };
ot_vpss_chn_attr chn_attr[OT_VPSS_MAX_PHYS_CHN_NUM] = {0};
grp_attr.max_width = vpss_chan_cfg->max_size.width;
grp_attr.max_height = vpss_chan_cfg->max_size.height;
grp_attr.nr_en = TD_FALSE;
grp_attr.dei_mode = OT_VPSS_DEI_MODE_OFF;
grp_attr.pixel_format = vpss_chan_cfg->pixel_format;
grp_attr.frame_rate.src_frame_rate = -1;
grp_attr.frame_rate.dst_frame_rate = -1;
for (vpss_chn = 0; vpss_chn < OT_VPSS_MAX_PHYS_CHN_NUM; vpss_chn++) {
if (vpss_chan_cfg->enable[vpss_chn] == 1) {
chn_attr[vpss_chn].width = vpss_chan_cfg->output_size[vpss_chn].width;
chn_attr[vpss_chn].height = vpss_chan_cfg->output_size[vpss_chn].height;
chn_attr[vpss_chn].chn_mode = OT_VPSS_CHN_MODE_USER;
chn_attr[vpss_chn].compress_mode = vpss_chan_cfg->compress_mode[vpss_chn];
chn_attr[vpss_chn].pixel_format = vpss_chan_cfg->pixel_format;
chn_attr[vpss_chn].frame_rate.src_frame_rate = -1;
chn_attr[vpss_chn].frame_rate.dst_frame_rate = -1;
chn_attr[vpss_chn].depth = 0;
chn_attr[vpss_chn].mirror_en = 0;
chn_attr[vpss_chn].flip_en = 0;
chn_attr[vpss_chn].aspect_ratio.mode = OT_ASPECT_RATIO_NONE;
}
}
ret = sample_common_vpss_start(vpss_grp, vpss_chan_cfg->enable, &grp_attr, chn_attr, OT_VPSS_MAX_PHYS_CHN_NUM);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
}
return ret;
}
static td_void sample_venc_vpss_deinit(ot_vpss_grp vpss_grp, sample_venc_vpss_chn_attr *vpss_chan_cfg)
{
td_s32 ret;
ret = sample_common_vpss_stop(vpss_grp, vpss_chan_cfg->enable, OT_VPSS_MAX_PHYS_CHN_NUM);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
}
}
static td_s32 sample_venc_init_param(ot_size *enc_size, td_s32 chn_num_max, sample_vi_config *vi_cfg, ot_size *vi_size,
sample_venc_vpss_chn_attr *vpss_param)
{
td_s32 i, ret;
ot_pic_size pic_size[CHN_NUM_MAX] = {BIG_STREAM_SIZE, SMALL_STREAM_SIZE};
for (i = 0; i < chn_num_max && i < CHN_NUM_MAX; i++) {
ret = sample_comm_sys_get_pic_size(pic_size[i], &enc_size[i]);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_sys_get_pic_size failed!\n");
return ret;
}
}
// get vi param
get_default_vi_cfg(vi_cfg);
*vi_size = get_vi_size_from_mode(vi_cfg->vi_mode);
if (vi_size->width == 0 || vi_size->height == 0) {
sample_print("call get_vi_size_from_mode failed! vi mode = %d\n", vi_cfg->vi_mode);
return TD_FAILURE;
}
// get vpss param
get_default_vpss_chn_attr(*vi_size, enc_size, CHN_NUM_MAX, vpss_param);
return 0;
}
static td_void sample_venc_set_video_param(sample_comm_venc_chnl_param *venc_create_param,
ot_venc_gop_attr gop_attr, td_s32 chn_num_max, td_bool qp_map)
{
td_u32 profile[CHN_NUM_MAX] = {0, 0};
td_bool share_buf_en = TD_TRUE;
ot_pic_size pic_size[CHN_NUM_MAX] = {BIG_STREAM_SIZE, SMALL_STREAM_SIZE};
ot_payload_type payload[CHN_NUM_MAX] = {OT_PT_H265, OT_PT_H264};
sample_rc rc_mode = 0;
if (qp_map) {
rc_mode = SAMPLE_RC_QPMAP;
} else {
if (get_rc_mode(payload[0], &rc_mode) != TD_SUCCESS) {
return;
}
}
if (chn_num_max < 2) { /* 2: venc_create_param array len */
sample_print("chn_num_max %d not enough! should > 2\n", chn_num_max);
return;
}
/* encode h.265 */
venc_create_param[0].gop_attr = gop_attr;
venc_create_param[0].type = payload[0];
venc_create_param[0].size = pic_size[0];
venc_create_param[0].rc_mode = rc_mode;
venc_create_param[0].profile = profile[0];
venc_create_param[0].is_rcn_ref_share_buf = share_buf_en;
/* encode h.264 */
venc_create_param[1].gop_attr = gop_attr;
venc_create_param[1].type = payload[1];
venc_create_param[1].size = pic_size[1];
venc_create_param[1].rc_mode = rc_mode;
venc_create_param[1].profile = profile[1];
venc_create_param[1].is_rcn_ref_share_buf = share_buf_en;
}
static td_void sample_set_venc_vpss_chn(sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 i;
for (i = 0; i < CHN_NUM_MAX; i++) {
venc_vpss_chn->vpss_chn[i] = i;
venc_vpss_chn->venc_chn[i] = i;
}
}
static td_void sample_venc_unbind_vpss_stop(ot_vpss_grp vpss_grp, const sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 i;
for (i = 0; i < CHN_NUM_MAX; i++) {
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[i], venc_vpss_chn->venc_chn[i]);
sample_comm_venc_stop(venc_vpss_chn->venc_chn[i]);
}
}
static td_void sample_venc_stop(const sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 i;
for (i = 0; i < CHN_NUM_MAX; i++) {
sample_comm_venc_stop(venc_vpss_chn->venc_chn[i]);
}
}
static td_s32 sample_venc_normal_start_encode(ot_vpss_grp vpss_grp, sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 ret;
ot_venc_gop_mode gop_mode;
ot_venc_gop_attr gop_attr;
sample_comm_venc_chnl_param venc_create_param[CHN_NUM_MAX] = {0};
sample_comm_venc_chnl_param h265_venc_param, h264_venc_param;
if (get_gop_mode(&gop_mode) != TD_SUCCESS) {
return TD_FAILURE;
}
if ((ret = sample_comm_venc_get_gop_attr(gop_mode, &gop_attr)) != TD_SUCCESS) {
sample_print("Venc Get GopAttr for %#x!\n", ret);
return ret;
}
sample_venc_set_video_param(venc_create_param, gop_attr, CHN_NUM_MAX, TD_FALSE);
/* encode h.265 */
h265_venc_param = venc_create_param[0];
if ((ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[0], &h265_venc_param)) != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
return ret;
}
ret = sample_comm_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vpss_bind_venc failed for %#x!\n", ret);
goto EXIT_VENC_H265_STOP;
}
/* encode h.264 */
h264_venc_param = venc_create_param[1];
if ((ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[1], &h264_venc_param)) != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
goto EXIT_VENC_H265_UnBind;
}
ret = sample_comm_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vpss_bind_venc failed for %#x!\n", ret);
goto EXIT_VENC_H264_STOP;
}
/******************************************
stream save process
******************************************/
if ((ret = sample_comm_venc_start_get_stream(venc_vpss_chn->venc_chn, CHN_NUM_MAX)) != TD_SUCCESS) {
sample_print("Start Venc failed!\n");
goto EXIT_VENC_H264_UnBind;
}
return TD_SUCCESS;
EXIT_VENC_H264_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
EXIT_VENC_H264_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[1]);
EXIT_VENC_H265_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
EXIT_VENC_H265_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[0]);
return ret;
}
static td_void sample_venc_exit_process()
{
printf("please press twice ENTER to exit this sample\n");
(td_void)getchar();
if (g_sample_venc_exit != TD_TRUE) {
(td_void)getchar();
}
sample_comm_venc_stop_get_stream(CHN_NUM_MAX);
}
/******************************************************************************
* function : H.265e@1080P@30fps + h264e@D1@30fps
******************************************************************************/
static td_s32 sample_venc_normal(td_void)
{
td_s32 ret;
sample_vi_config vi_cfg;
ot_size enc_size[CHN_NUM_MAX];
ot_size vi_size = {0};
const ot_vi_pipe vi_pipe = 0;
const ot_vi_chn vi_chn = 0;
const ot_vpss_grp vpss_grp = 0;
sample_venc_vpss_chn_attr vpss_param;
sample_venc_vb_attr vb_attr = {0};
sample_venc_vpss_chn venc_vpss_chn = {0};
sample_set_venc_vpss_chn(&venc_vpss_chn);
/******************************************
step 0: related parameter ready
******************************************/
ret = sample_venc_init_param(enc_size, CHN_NUM_MAX, &vi_cfg, &vi_size, &vpss_param);
if (ret != TD_SUCCESS) {
return ret;
}
/******************************************
step 1: init sys alloc common vb
******************************************/
get_vb_attr(&vi_size, &vpss_param, &vb_attr);
if ((ret = sample_venc_sys_init(&vb_attr)) != TD_SUCCESS) {
sample_print("Init SYS err for %#x!\n", ret);
return ret;
}
if ((ret = sample_venc_vi_init(&vi_cfg)) != TD_SUCCESS) {
sample_print("Init VI err for %#x!\n", ret);
goto EXIT_SYS_STOP;
}
if ((ret = sample_venc_vpss_init(vpss_grp, &vpss_param)) != TD_SUCCESS) {
sample_print("Init VPSS err for %#x!\n", ret);
goto EXIT_VI_STOP;
}
if ((ret = sample_comm_vi_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0)) != TD_SUCCESS) {
sample_print("VI Bind VPSS err for %#x!\n", ret);
goto EXIT_VPSS_STOP;
}
if ((ret = sample_venc_normal_start_encode(vpss_grp, &venc_vpss_chn)) != TD_SUCCESS) {
goto EXIT_VI_VPSS_UNBIND;
}
/******************************************
exit process
******************************************/
sample_venc_exit_process();
sample_venc_unbind_vpss_stop(vpss_grp, &venc_vpss_chn);
EXIT_VI_VPSS_UNBIND:
sample_comm_vi_un_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0);
EXIT_VPSS_STOP:
sample_venc_vpss_deinit(vpss_grp, &vpss_param);
EXIT_VI_STOP:
sample_venc_vi_deinit(&vi_cfg);
EXIT_SYS_STOP:
sample_comm_sys_exit();
return ret;
}
static td_s32 sample_venc_qpmap_start_encode(ot_size *enc_size, td_s32 chn_num_max,
ot_vpss_grp vpss_grp, sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 ret;
ot_venc_gop_mode gop_mode;
ot_venc_gop_attr gop_attr;
sample_comm_venc_chnl_param venc_create_param[CHN_NUM_MAX] = {0};
sample_comm_venc_chnl_param h265_venc_param, h264_venc_param;
ot_unused(chn_num_max);
if (get_gop_mode(&gop_mode) != TD_SUCCESS) {
return TD_FAILURE;
}
if ((ret = sample_comm_venc_get_gop_attr(gop_mode, &gop_attr)) != TD_SUCCESS) {
sample_print("Venc Get GopAttr for %#x!\n", ret);
return ret;
}
sample_venc_set_video_param(venc_create_param, gop_attr, CHN_NUM_MAX, TD_TRUE);
/* encode h.265 */
h265_venc_param = venc_create_param[0];
ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[0], &h265_venc_param);
if (ret != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
return ret;
}
/* encode h.264 */
h264_venc_param = venc_create_param[1];
ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[1], &h264_venc_param);
if (ret != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
goto EXIT_VENC_H265_STOP;
}
ret = sample_comm_venc_qpmap_send_frame(vpss_grp, venc_vpss_chn->vpss_chn,
venc_vpss_chn->venc_chn, CHN_NUM_MAX, enc_size);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_venc_qpmap_send_frame failed for %#x!\n", ret);
goto EXIT_VENC_H264_STOP;
}
/******************************************
stream save process
******************************************/
if ((ret = sample_comm_venc_start_get_stream(venc_vpss_chn->venc_chn, CHN_NUM_MAX)) != TD_SUCCESS) {
sample_print("Start Venc failed!\n");
goto EXIT_VENC_H264_STOP;
}
return TD_SUCCESS;
EXIT_VENC_H264_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[1]);
EXIT_VENC_H265_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[0]);
return ret;
}
static td_void sample_venc_qpmap_exit_process()
{
printf("please press twice ENTER to exit this sample\n");
(td_void)getchar();
if (g_sample_venc_exit != TD_TRUE) {
(td_void)getchar();
}
sample_comm_venc_stop_send_qpmap_frame();
sample_comm_venc_stop_get_stream(CHN_NUM_MAX);
}
static td_s32 sample_venc_qpmap(td_void)
{
td_s32 ret;
sample_vi_config vi_cfg;
ot_size enc_size[CHN_NUM_MAX];
ot_size vi_size = {0};
const ot_vi_pipe vi_pipe = 0;
const ot_vi_chn vi_chn = 0;
const ot_vpss_grp vpss_grp = 0;
sample_venc_vpss_chn_attr vpss_param;
sample_venc_vb_attr vb_attr = {0};
sample_venc_vpss_chn venc_vpss_chn = {0};
sample_set_venc_vpss_chn(&venc_vpss_chn);
/******************************************
step 0: related parameter ready
******************************************/
ret = sample_venc_init_param(enc_size, CHN_NUM_MAX, &vi_cfg, &vi_size, &vpss_param);
if (ret != TD_SUCCESS) {
return ret;
}
/******************************************
step 1: init sys alloc common vb
******************************************/
get_vb_attr(&vi_size, &vpss_param, &vb_attr);
if ((ret = sample_venc_sys_init(&vb_attr)) != TD_SUCCESS) {
sample_print("Init SYS err for %#x!\n", ret);
return ret;
}
if ((ret = sample_venc_vi_init(&vi_cfg)) != TD_SUCCESS) {
sample_print("Init VI err for %#x!\n", ret);
goto EXIT_SYS_STOP;
}
if ((ret = sample_venc_vpss_init(vpss_grp, &vpss_param)) != TD_SUCCESS) {
sample_print("Init VPSS err for %#x!\n", ret);
goto EXIT_VI_STOP;
}
if ((ret = sample_comm_vi_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0)) != TD_SUCCESS) {
sample_print("VI Bind VPSS err for %#x!\n", ret);
goto EXIT_VPSS_STOP;
}
/******************************************
start stream venc
******************************************/
if ((ret = sample_venc_qpmap_start_encode(enc_size, CHN_NUM_MAX, vpss_grp, &venc_vpss_chn)) != TD_SUCCESS) {
goto EXIT_VI_VPSS_UNBIND;
}
/******************************************
exit process
******************************************/
sample_venc_qpmap_exit_process();
sample_venc_stop(&venc_vpss_chn);
EXIT_VI_VPSS_UNBIND:
sample_comm_vi_un_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0);
EXIT_VPSS_STOP:
sample_venc_vpss_deinit(vpss_grp, &vpss_param);
EXIT_VI_STOP:
sample_venc_vi_deinit(&vi_cfg);
EXIT_SYS_STOP:
sample_comm_sys_exit();
return ret;
}
static td_s32 sample_venc_vpss_bind_venc(ot_vpss_grp vpss_grp, ot_vpss_chn vpss_chn, ot_venc_chn venc_chn)
{
td_s32 ret;
ret = sample_comm_vpss_bind_venc(vpss_grp, vpss_chn, venc_chn);
if (ret != TD_SUCCESS) {
sample_print("call sample_comm_vpss_bind_venc vpss grp %d, vpss chn %d, venc chn %d, ret = %#x!\n",
vpss_grp, vpss_chn, venc_chn, ret);
return ret;
}
return TD_SUCCESS;
}
static td_void sample_venc_intra_refresh_param_init(ot_venc_intra_refresh_mode intra_refresh_mode,
ot_venc_intra_refresh *intra_refresh)
{
intra_refresh->enable = TD_TRUE;
intra_refresh->mode = intra_refresh_mode;
if (intra_refresh_mode == OT_VENC_INTRA_REFRESH_ROW) {
intra_refresh->refresh_num = 5; /* 5: refresh num */
} else {
intra_refresh->refresh_num = 6; /* 6: refresh num */
}
intra_refresh->request_i_qp = 30; /* 30: request num */
}
static td_s32 sample_venc_set_intra_refresh(ot_venc_chn venc_chn, ot_venc_intra_refresh_mode intra_refresh_mode)
{
td_s32 ret;
ot_venc_intra_refresh intra_refresh = {0};
if ((ret = ss_mpi_venc_get_intra_refresh(venc_chn, &intra_refresh)) != TD_SUCCESS) {
sample_print("Get Intra Refresh failed for %#x!\n", ret);
return ret;
}
sample_venc_intra_refresh_param_init(intra_refresh_mode, &intra_refresh);
if ((ret = ss_mpi_venc_set_intra_refresh(venc_chn, &intra_refresh)) != TD_SUCCESS) {
sample_print("Set Intra Refresh failed for %#x!\n", ret);
return ret;
}
return TD_SUCCESS;
}
static td_s32 sample_comm_venc_get_gop_default_attr(ot_venc_gop_attr *gop_attr)
{
td_s32 ret;
ot_venc_gop_mode gop_mode;
if (get_gop_mode(&gop_mode) != TD_SUCCESS) {
return TD_FAILURE;
}
ret = sample_comm_venc_get_gop_attr(gop_mode, gop_attr);
if (ret != TD_SUCCESS) {
sample_print("Venc get gop default attr for mode %d failed return %#x!\n", gop_mode, ret);
return ret;
}
return TD_SUCCESS;
}
static td_s32 sample_venc_intra_refresh_set_video_param(ot_venc_intra_refresh_mode *intra_refresh_mode,
sample_comm_venc_chnl_param *venc_create_param, td_s32 len)
{
td_s32 ret;
ot_venc_gop_attr gop_attr;
if ((ret = sample_comm_venc_get_gop_default_attr(&gop_attr)) != TD_SUCCESS) {
return ret;
}
if (get_intra_refresh_mode(intra_refresh_mode) != TD_SUCCESS) {
return TD_FAILURE;
}
if (len > CHN_NUM_MAX) {
sample_print("the num of venc_create_param is beyond CHN_NUM_MAX !\n");
return TD_FAILURE;
}
sample_venc_set_video_param(venc_create_param, gop_attr, CHN_NUM_MAX, TD_FALSE);
return TD_SUCCESS;
}
static td_s32 sample_venc_intra_refresh_start_encode(ot_vpss_grp vpss_grp, sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 ret;
ot_venc_intra_refresh_mode intra_refresh_mode;
sample_comm_venc_chnl_param venc_create_param[CHN_NUM_MAX] = {0};
sample_comm_venc_chnl_param h265_venc_param, h264_venc_param;
ret = sample_venc_intra_refresh_set_video_param(&intra_refresh_mode, venc_create_param, CHN_NUM_MAX);
if (ret != TD_SUCCESS) {
return ret;
}
/* encode h.265 */
h265_venc_param = venc_create_param[0];
if ((ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[0], &h265_venc_param)) != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
return ret;
}
ret = sample_venc_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
if (ret != TD_SUCCESS) {
goto EXIT_VENC_H265_STOP;
}
/* set intra refresh mode for chn 0 */
if ((ret = sample_venc_set_intra_refresh(venc_vpss_chn->venc_chn[0], intra_refresh_mode)) != TD_SUCCESS) {
goto EXIT_VENC_H265_UnBind;
}
/* encode h.264 */
h264_venc_param = venc_create_param[1];
if ((ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[1], &h264_venc_param)) != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
goto EXIT_VENC_H265_UnBind;
}
ret = sample_venc_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
if (ret != TD_SUCCESS) {
goto EXIT_VENC_H264_STOP;
}
/* set intra refresh mode for chn 1 */
if ((ret = sample_venc_set_intra_refresh(venc_vpss_chn->venc_chn[1], intra_refresh_mode)) != TD_SUCCESS) {
goto EXIT_VENC_H264_UnBind;
}
/******************************************
stream save process
******************************************/
if ((ret = sample_comm_venc_start_get_stream(venc_vpss_chn->venc_chn, CHN_NUM_MAX)) != TD_SUCCESS) {
sample_print("Start Venc failed!\n");
}
return ret;
EXIT_VENC_H264_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
EXIT_VENC_H264_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[1]);
EXIT_VENC_H265_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
EXIT_VENC_H265_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[0]);
return ret;
}
/******************************************************************************
* function : intra_refresh:H.265e@1080P@30fps(row) + h264e@1080P@30fps(column).
******************************************************************************/
static td_s32 sample_venc_intra_refresh(td_void)
{
td_s32 ret;
sample_vi_config vi_cfg;
ot_size vi_size = {0};
ot_size enc_size[CHN_NUM_MAX];
const ot_vi_pipe vi_pipe = 0;
const ot_vi_chn vi_chn = 0;
const ot_vpss_grp vpss_grp = 0;
sample_venc_vpss_chn_attr vpss_param;
sample_venc_vb_attr vb_attr = {0};
sample_venc_vpss_chn venc_vpss_chn = {0};
sample_set_venc_vpss_chn(&venc_vpss_chn);
/******************************************
step 0: related parameter ready
******************************************/
if ((ret = sample_venc_init_param(enc_size, CHN_NUM_MAX, &vi_cfg, &vi_size, &vpss_param)) != TD_SUCCESS) {
return ret;
}
/******************************************
step 1: init sys alloc common vb
******************************************/
get_vb_attr(&vi_size, &vpss_param, &vb_attr);
if ((ret = sample_venc_sys_init(&vb_attr)) != TD_SUCCESS) {
sample_print("Init SYS err for %#x!\n", ret);
return ret;
}
if ((ret = sample_venc_vi_init(&vi_cfg)) != TD_SUCCESS) {
sample_print("Init VI err for %#x!\n", ret);
goto EXIT_SYS_STOP;
}
if ((ret = sample_venc_vpss_init(vpss_grp, &vpss_param)) != TD_SUCCESS) {
sample_print("Init VPSS err for %#x!\n", ret);
goto EXIT_VI_STOP;
}
if ((ret = sample_comm_vi_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0)) != TD_SUCCESS) {
sample_print("VI Bind VPSS err for %#x!\n", ret);
goto EXIT_VPSS_STOP;
}
/******************************************
start stream venc
******************************************/
ret = sample_venc_intra_refresh_start_encode(vpss_grp, &venc_vpss_chn);
if (ret != TD_SUCCESS) {
goto EXIT_VI_VPSS_UNBIND;
}
/******************************************
exit process
******************************************/
sample_venc_exit_process();
sample_venc_unbind_vpss_stop(vpss_grp, &venc_vpss_chn);
EXIT_VI_VPSS_UNBIND:
sample_comm_vi_un_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0);
EXIT_VPSS_STOP:
sample_venc_vpss_deinit(vpss_grp, &vpss_param);
EXIT_VI_STOP:
sample_venc_vi_deinit(&vi_cfg);
EXIT_SYS_STOP:
sample_comm_sys_exit();
return ret;
}
static td_void sample_venc_roi_attr_init(ot_venc_roi_attr *roi_attr)
{
roi_attr->is_abs_qp = TD_TRUE;
roi_attr->enable = TD_TRUE;
roi_attr->qp = 30; /* 30: qp value */
roi_attr->idx = 0;
roi_attr->rect.x = 64; /* 64: rect.x value */
roi_attr->rect.y = 64; /* 64: rect.y value */
roi_attr->rect.height = 256; /* 256: rect.height value */
roi_attr->rect.width = 256; /* 256: rect.width value */
}
static td_void sample_venc_roi_bg_frame_rate_init(ot_venc_roi_bg_frame_rate *roi_bg_frame_rate)
{
roi_bg_frame_rate->src_frame_rate = 30; /* 30: src_frame_rate value */
roi_bg_frame_rate->dst_frame_rate = 15; /* 15: dst_frame_rate value */
}
static td_s32 sample_venc_set_roi_attr(ot_venc_chn venc_chn)
{
td_s32 ret;
ot_venc_roi_attr roi_attr;
ot_venc_roi_bg_frame_rate roi_bg_frame_rate;
if ((ret = ss_mpi_venc_get_roi_attr(venc_chn, 0, &roi_attr)) != TD_SUCCESS) { /* 0: roi index */
sample_print("chn %d Get Roi Attr failed for %#x!\n", venc_chn, ret);
return ret;
}
sample_venc_roi_attr_init(&roi_attr);
if ((ret = ss_mpi_venc_set_roi_attr(venc_chn, &roi_attr)) != TD_SUCCESS) {
sample_print("chn %d Set Roi Attr failed for %#x!\n", venc_chn, ret);
return ret;
}
if ((ret = ss_mpi_venc_get_roi_bg_frame_rate(venc_chn, &roi_bg_frame_rate)) != TD_SUCCESS) {
sample_print("chn %d Get Roi BgFrameRate failed for %#x!\n", venc_chn, ret);
return ret;
}
sample_venc_roi_bg_frame_rate_init(&roi_bg_frame_rate);
if ((ret = ss_mpi_venc_set_roi_bg_frame_rate(venc_chn, &roi_bg_frame_rate)) != TD_SUCCESS) {
sample_print("chn %d Set Roi BgFrameRate failed for %#x!\n", venc_chn, ret);
return ret;
}
return TD_SUCCESS;
}
static td_s32 sample_venc_roi_bg_start_encode(ot_vpss_grp vpss_grp, sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 ret;
ot_venc_gop_attr gop_attr;
sample_comm_venc_chnl_param venc_create_param[CHN_NUM_MAX] = {0};
sample_comm_venc_chnl_param h265_venc_param, h264_venc_param;
if ((ret = sample_comm_venc_get_gop_default_attr(&gop_attr)) != TD_SUCCESS) {
return ret;
}
sample_venc_set_video_param(venc_create_param, gop_attr, CHN_NUM_MAX, TD_FALSE);
/* encode h.265 */
h265_venc_param = venc_create_param[0];
if ((ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[0], &h265_venc_param)) != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
return ret;
}
ret = sample_venc_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
if (ret != TD_SUCCESS) {
goto EXIT_VENC_H265_STOP;
}
/* set roi bg frame rate for chn 0 */
if ((ret = sample_venc_set_roi_attr(venc_vpss_chn->venc_chn[0])) != TD_SUCCESS) {
goto EXIT_VENC_H265_UnBind;
}
/* encode h.264 */
h264_venc_param = venc_create_param[1];
if ((ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[1], &h264_venc_param)) != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
goto EXIT_VENC_H265_UnBind;
}
ret = sample_venc_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
if (ret != TD_SUCCESS) {
goto EXIT_VENC_H264_STOP;
}
/* set roi bg frame rate for chn 1 */
if ((ret = sample_venc_set_roi_attr(venc_vpss_chn->venc_chn[1])) != TD_SUCCESS) {
goto EXIT_VENC_H264_UnBind;
}
/******************************************
stream save process
******************************************/
if ((ret = sample_comm_venc_start_get_stream(venc_vpss_chn->venc_chn, CHN_NUM_MAX)) != TD_SUCCESS) {
sample_print("Start Venc failed!\n");
goto EXIT_VENC_H264_UnBind;
}
return ret;
EXIT_VENC_H264_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
EXIT_VENC_H264_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[1]);
EXIT_VENC_H265_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
EXIT_VENC_H265_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[0]);
return ret;
}
/******************************************************************************
* function : roi_bg_frame_rate:H.265e@1080P@30fps + H.264@1080P@30fps.
******************************************************************************/
static td_s32 sample_venc_roi_bg(td_void)
{
td_s32 ret;
sample_vi_config vi_cfg;
ot_size vi_size = {0};
const ot_vi_pipe vi_pipe = 0;
const ot_vi_chn vi_chn = 0;
const ot_vpss_grp vpss_grp = 0;
sample_venc_vpss_chn_attr vpss_param;
sample_venc_vb_attr vb_attr = {0};
ot_size enc_size[CHN_NUM_MAX];
sample_venc_vpss_chn venc_vpss_chn = {0};
sample_set_venc_vpss_chn(&venc_vpss_chn);
/******************************************
step 0: related parameter ready
******************************************/
if ((ret = sample_venc_init_param(enc_size, CHN_NUM_MAX, &vi_cfg, &vi_size, &vpss_param)) != TD_SUCCESS) {
return ret;
}
/******************************************
step 1: init sys alloc common vb
******************************************/
get_vb_attr(&vi_size, &vpss_param, &vb_attr);
if ((ret = sample_venc_sys_init(&vb_attr)) != TD_SUCCESS) {
sample_print("Init SYS err for %#x!\n", ret);
return ret;
}
if ((ret = sample_venc_vi_init(&vi_cfg)) != TD_SUCCESS) {
sample_print("Init VI err for %#x!\n", ret);
goto EXIT_SYS_STOP;
}
if ((ret = sample_venc_vpss_init(vpss_grp, &vpss_param)) != TD_SUCCESS) {
sample_print("Init VPSS err for %#x!\n", ret);
goto EXIT_VI_STOP;
}
if ((ret = sample_comm_vi_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0)) != TD_SUCCESS) {
sample_print("VI Bind VPSS err for %#x!\n", ret);
goto EXIT_VPSS_STOP;
}
/******************************************
start stream venc
******************************************/
if ((ret = sample_venc_roi_bg_start_encode(vpss_grp, &venc_vpss_chn)) != TD_SUCCESS) {
goto EXIT_VI_VPSS_UNBIND;
}
/******************************************
exit process
******************************************/
sample_venc_exit_process();
sample_venc_unbind_vpss_stop(vpss_grp, &venc_vpss_chn);
EXIT_VI_VPSS_UNBIND:
sample_comm_vi_un_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0);
EXIT_VPSS_STOP:
sample_venc_vpss_deinit(vpss_grp, &vpss_param);
EXIT_VI_STOP:
sample_venc_vi_deinit(&vi_cfg);
EXIT_SYS_STOP:
sample_comm_sys_exit();
return ret;
}
static td_s32 sample_venc_set_debreath_effect(ot_venc_chn venc_chn, td_bool enable)
{
td_s32 ret;
ot_venc_debreath_effect debreath_effect;
if ((ret = ss_mpi_venc_get_debreath_effect(venc_chn, &debreath_effect)) != TD_SUCCESS) {
sample_print("Get debreath_effect failed for %#x!\n", ret);
return ret;
}
if (enable) {
debreath_effect.enable = TD_TRUE;
debreath_effect.strength0 = 3; /* 3 : param */
debreath_effect.strength1 = 20; /* 20 : param */
} else {
debreath_effect.enable = TD_FALSE;
}
if ((ret = ss_mpi_venc_set_debreath_effect(venc_chn, &debreath_effect)) != TD_SUCCESS) {
sample_print("Set debreath_effect failed for %#x!\n", ret);
return ret;
}
return TD_SUCCESS;
}
static td_s32 sample_venc_debreath_effect_start_encode(ot_vpss_grp vpss_grp, sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 ret;
ot_venc_gop_attr gop_attr;
sample_comm_venc_chnl_param venc_create_param[CHN_NUM_MAX] = {0};
sample_comm_venc_chnl_param h265_venc_param, h264_venc_param;
if ((ret = sample_comm_venc_get_gop_default_attr(&gop_attr)) != TD_SUCCESS) {
return ret;
}
sample_venc_set_video_param(venc_create_param, gop_attr, CHN_NUM_MAX, TD_FALSE);
/* encode h.265 */
h265_venc_param = venc_create_param[0];
if ((ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[0], &h265_venc_param)) != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
return ret;
}
ret = sample_venc_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
if (ret != TD_SUCCESS) {
goto EXIT_VENC_H265_STOP;
}
/* set intra refresh mode for chn 0 */
if ((ret = sample_venc_set_debreath_effect(venc_vpss_chn->venc_chn[0], TD_TRUE)) != TD_SUCCESS) {
goto EXIT_VENC_H265_UnBind;
}
/* encode h.264 */
h264_venc_param = venc_create_param[1];
if ((ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[1], &h264_venc_param)) != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
goto EXIT_VENC_H265_UnBind;
}
ret = sample_venc_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
if (ret != TD_SUCCESS) {
goto EXIT_VENC_H264_STOP;
}
/* set intra refresh mode for chn 1 */
if ((ret = sample_venc_set_debreath_effect(venc_vpss_chn->venc_chn[1], TD_FALSE)) != TD_SUCCESS) {
goto EXIT_VENC_H264_UnBind;
}
/******************************************
stream save process
******************************************/
if ((ret = sample_comm_venc_start_get_stream(venc_vpss_chn->venc_chn, CHN_NUM_MAX)) != TD_SUCCESS) {
sample_print("Start Venc failed!\n");
goto EXIT_VENC_H264_UnBind;
}
return TD_SUCCESS;
EXIT_VENC_H264_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
EXIT_VENC_H264_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[1]);
EXIT_VENC_H265_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
EXIT_VENC_H265_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[0]);
return ret;
}
static td_s32 sample_venc_debreath_effect(td_void)
{
td_s32 ret;
sample_vi_config vi_cfg;
ot_size vi_size = {0};
const ot_vi_pipe vi_pipe = 0;
const ot_vi_chn vi_chn = 0;
const ot_vpss_grp vpss_grp = 0;
sample_venc_vpss_chn_attr vpss_param;
sample_venc_vb_attr vb_attr = {0};
ot_size enc_size[CHN_NUM_MAX];
sample_venc_vpss_chn venc_vpss_chn = {0};
sample_set_venc_vpss_chn(&venc_vpss_chn);
/******************************************
step 0: related parameter ready
******************************************/
if ((ret = sample_venc_init_param(enc_size, CHN_NUM_MAX, &vi_cfg, &vi_size, &vpss_param)) != TD_SUCCESS) {
return ret;
}
/******************************************
step 1: init sys alloc common vb
******************************************/
get_vb_attr(&vi_size, &vpss_param, &vb_attr);
if ((ret = sample_venc_sys_init(&vb_attr)) != TD_SUCCESS) {
sample_print("Init SYS err for %#x!\n", ret);
return ret;
}
if ((ret = sample_venc_vi_init(&vi_cfg)) != TD_SUCCESS) {
sample_print("Init VI err for %#x!\n", ret);
goto EXIT_SYS_STOP;
}
if ((ret = sample_venc_vpss_init(vpss_grp, &vpss_param)) != TD_SUCCESS) {
sample_print("Init VPSS err for %#x!\n", ret);
goto EXIT_VI_STOP;
}
if ((ret = sample_comm_vi_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0)) != TD_SUCCESS) {
sample_print("VI Bind VPSS err for %#x!\n", ret);
goto EXIT_VPSS_STOP;
}
/******************************************
start stream venc
******************************************/
ret = sample_venc_debreath_effect_start_encode(vpss_grp, &venc_vpss_chn);
if (ret != TD_SUCCESS) {
goto EXIT_VI_VPSS_UNBIND;
}
/******************************************
exit process
******************************************/
sample_venc_exit_process();
sample_venc_unbind_vpss_stop(vpss_grp, &venc_vpss_chn);
EXIT_VI_VPSS_UNBIND:
sample_comm_vi_un_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0);
EXIT_VPSS_STOP:
sample_venc_vpss_deinit(vpss_grp, &vpss_param);
EXIT_VI_STOP:
sample_venc_vi_deinit(&vi_cfg);
EXIT_SYS_STOP:
sample_comm_sys_exit();
return ret;
}
static td_void sample_venc_mjpeg_roi_attr_init(ot_venc_jpeg_roi_attr *roi_attr, td_s32 chn_num_max)
{
if (chn_num_max < 2) { /* 2: roi_attr array len */
sample_print("roi_attr array len not enough, need 2, current %d!\n", chn_num_max);
return;
}
roi_attr[0].enable = 1;
roi_attr[0].idx = 0;
roi_attr[0].rect.x = 0;
roi_attr[0].rect.y = 0;
roi_attr[0].rect.width = 160; /* 160: rect.width value */
roi_attr[0].rect.height = 160; /* 160: rect.height value */
roi_attr[0].level = 0;
roi_attr[1].enable = 1;
roi_attr[1].idx = 0;
roi_attr[1].rect.x = 0;
roi_attr[1].rect.y = 0;
roi_attr[1].rect.width = 160; /* 160: rect.width value */
roi_attr[1].rect.height = 160; /* 160: rect.height value */
roi_attr[1].level = 0;
}
static td_void sample_venc_set_jpeg_param(sample_comm_venc_chnl_param *venc_create_param,
ot_venc_gop_attr gop_attr, td_s32 chn_num_max)
{
td_u32 profile[CHN_NUM_MAX] = {0, 0};
ot_pic_size pic_size[CHN_NUM_MAX] = {BIG_STREAM_SIZE, SMALL_STREAM_SIZE};
td_bool share_buf_en = TD_FALSE;
ot_payload_type payload[CHN_NUM_MAX] = {OT_PT_MJPEG, OT_PT_MJPEG};
sample_rc rc_mode = 0;
if (get_rc_mode(payload[0], &rc_mode) != TD_SUCCESS) {
return;
}
if (chn_num_max < 2) { /* 2: venc_create_param array len */
sample_print("chn_num_max %d not enough! should > 2\n", chn_num_max);
return;
}
venc_create_param[0].gop_attr = gop_attr;
venc_create_param[0].type = payload[0];
venc_create_param[0].size = pic_size[0];
venc_create_param[0].rc_mode = rc_mode;
venc_create_param[0].profile = profile[0];
venc_create_param[0].is_rcn_ref_share_buf = share_buf_en;
venc_create_param[1].gop_attr = gop_attr;
venc_create_param[1].type = payload[1];
venc_create_param[1].size = pic_size[1];
venc_create_param[1].rc_mode = rc_mode;
venc_create_param[1].profile = profile[1];
venc_create_param[1].is_rcn_ref_share_buf = share_buf_en;
}
static td_s32 sample_venc_mjpeg_roimap_start_encode(ot_vpss_grp vpss_grp, ot_venc_jpeg_roi_attr *roi_attr,
ot_size *enc_size, td_s32 chn_num_max, sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 ret;
ot_venc_gop_attr gop_attr;
sample_comm_venc_chnl_param venc_create_param[CHN_NUM_MAX] = {0};
sample_comm_venc_chnl_param venc_chn0_param, venc_chn1_param;
sample_venc_roimap_chn_info roimap_chn_info = {0};
ot_unused(chn_num_max);
if ((ret = sample_comm_venc_get_gop_attr(OT_VENC_GOP_MODE_NORMAL_P, &gop_attr)) != TD_SUCCESS) {
sample_print("Venc Get GopAttr for %#x!\n", ret);
return ret;
}
sample_venc_set_jpeg_param(venc_create_param, gop_attr, CHN_NUM_MAX);
venc_chn0_param = venc_create_param[0];
ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[0], &venc_chn0_param);
if (ret != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
return ret;
}
venc_chn1_param = venc_create_param[1];
ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[1], &venc_chn1_param);
if (ret != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
goto EXIT_VENC_CHN0_STOP;
}
roimap_chn_info.vpss_chn = venc_vpss_chn->vpss_chn;
roimap_chn_info.venc_chn = venc_vpss_chn->venc_chn;
roimap_chn_info.cnt = CHN_NUM_MAX;
ret = sample_comm_venc_send_roimap_frame(vpss_grp, roimap_chn_info, enc_size, roi_attr);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_venc_qpmap_send_frame failed for %#x!\n", ret);
goto EXIT_VENC_CHN1_STOP;
}
/******************************************
stream save process
******************************************/
if ((ret = sample_comm_venc_start_get_stream(venc_vpss_chn->venc_chn, CHN_NUM_MAX)) != TD_SUCCESS) {
sample_print("Start Venc failed!\n");
goto EXIT_VENC_CHN1_STOP;
}
return TD_SUCCESS;
EXIT_VENC_CHN1_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[1]);
EXIT_VENC_CHN0_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[0]);
return ret;
}
static td_void sample_venc_mjpeg_roimap_exit_process()
{
printf("please press twice ENTER to exit this sample\n");
(td_void)getchar();
if (g_sample_venc_exit != TD_TRUE) {
(td_void)getchar();
}
sample_comm_venc_stop_send_roimap_frame();
sample_comm_venc_stop_get_stream(CHN_NUM_MAX);
}
static td_s32 sample_venc_mjpeg_roimap(td_void)
{
td_s32 ret;
sample_vi_config vi_cfg;
ot_size vi_size = {0};
const ot_vi_pipe vi_pipe = 0;
const ot_vi_chn vi_chn = 0;
const ot_vpss_grp vpss_grp = 0;
sample_venc_vpss_chn_attr vpss_param;
sample_venc_vb_attr vb_attr = {0};
ot_venc_jpeg_roi_attr roi_attr[CHN_NUM_MAX];
ot_size enc_size[CHN_NUM_MAX];
sample_venc_vpss_chn venc_vpss_chn = {0};
sample_set_venc_vpss_chn(&venc_vpss_chn);
sample_venc_mjpeg_roi_attr_init(roi_attr, CHN_NUM_MAX);
if ((ret = sample_venc_init_param(enc_size, CHN_NUM_MAX, &vi_cfg, &vi_size, &vpss_param)) != TD_SUCCESS) {
return ret;
}
/******************************************
step 1: init sys alloc common vb
******************************************/
get_vb_attr(&vi_size, &vpss_param, &vb_attr);
if ((ret = sample_venc_sys_init(&vb_attr)) != TD_SUCCESS) {
sample_print("Init SYS err for %#x!\n", ret);
return ret;
}
if ((ret = sample_venc_vi_init(&vi_cfg)) != TD_SUCCESS) {
sample_print("Init VI err for %#x!\n", ret);
goto EXIT_SYS_STOP;
}
if ((ret = sample_venc_vpss_init(vpss_grp, &vpss_param)) != TD_SUCCESS) {
sample_print("Init VPSS err for %#x!\n", ret);
goto EXIT_VI_STOP;
}
if ((ret = sample_comm_vi_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0)) != TD_SUCCESS) {
sample_print("VI Bind VPSS err for %#x!\n", ret);
goto EXIT_VPSS_STOP;
}
ret = sample_venc_mjpeg_roimap_start_encode(vpss_grp, roi_attr, enc_size, CHN_NUM_MAX, &venc_vpss_chn);
if (ret != TD_SUCCESS) {
goto EXIT_VI_VPSS_UNBIND;
}
/******************************************
exit process
******************************************/
sample_venc_mjpeg_roimap_exit_process();
sample_venc_stop(&venc_vpss_chn);
EXIT_VI_VPSS_UNBIND:
sample_comm_vi_un_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0);
EXIT_VPSS_STOP:
sample_venc_vpss_deinit(vpss_grp, &vpss_param);
EXIT_VI_STOP:
sample_venc_vi_deinit(&vi_cfg);
EXIT_SYS_STOP:
sample_comm_sys_exit();
return ret;
}
static td_void sample_venc_mjpeg_roi_param_init(ot_venc_jpeg_roi_attr *roi_param)
{
roi_param->idx = 0;
roi_param->enable = TD_TRUE;
roi_param->level = 0;
roi_param->rect.x = 0;
roi_param->rect.y = 0;
roi_param->rect.width = 1280; /* 1280: rect.width value */
roi_param->rect.height = 720; /* 720: rect.height value */
}
static td_s32 sample_venc_set_mjpeg_roi(ot_venc_chn venc_chn)
{
td_s32 ret;
const td_u32 idx = 0;
ot_venc_jpeg_roi_attr roi_param;
if ((ret = ss_mpi_venc_get_jpeg_roi_attr(venc_chn, idx, &roi_param)) != TD_SUCCESS) {
sample_print("Get roi_param failed for %#x!\n", ret);
return ret;
}
sample_venc_mjpeg_roi_param_init(&roi_param);
if ((ret = ss_mpi_venc_set_jpeg_roi_attr(venc_chn, &roi_param)) != TD_SUCCESS) {
sample_print("Set roi_param failed for %#x!\n", ret);
}
return ret;
}
static td_s32 sample_venc_mjpeg_roi_set_start_encode(ot_vpss_grp vpss_grp, sample_venc_vpss_chn *venc_vpss_chn)
{
td_s32 ret;
ot_venc_gop_attr gop_attr;
sample_comm_venc_chnl_param venc_create_param[CHN_NUM_MAX] = {0};
sample_comm_venc_chnl_param venc_chn0_param, venc_chn1_param;
if ((ret = sample_comm_venc_get_gop_attr(OT_VENC_GOP_MODE_NORMAL_P, &gop_attr)) != TD_SUCCESS) {
return ret;
}
sample_venc_set_jpeg_param(venc_create_param, gop_attr, CHN_NUM_MAX);
venc_chn0_param = venc_create_param[0];
ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[0], &venc_chn0_param);
if (ret != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
return ret;
}
ret = sample_venc_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
if (ret != TD_SUCCESS) {
goto EXIT_VENC_CHN0_STOP;
}
/* set intra refresh mode for chn 0 */
if ((ret = sample_venc_set_mjpeg_roi(venc_vpss_chn->venc_chn[0])) != TD_SUCCESS) {
goto EXIT_VENC_CHN_0_UnBind;
}
venc_chn1_param = venc_create_param[1];
ret = sample_comm_venc_start(venc_vpss_chn->venc_chn[1], &venc_chn1_param);
if (ret != TD_SUCCESS) {
sample_print("Venc Start failed for %#x!\n", ret);
goto EXIT_VENC_CHN_0_UnBind;
}
ret = sample_venc_vpss_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
if (ret != TD_SUCCESS) {
goto EXIT_VENC_CHN_1_STOP;
}
/******************************************
stream save process
******************************************/
if ((ret = sample_comm_venc_start_get_stream(venc_vpss_chn->venc_chn, CHN_NUM_MAX)) != TD_SUCCESS) {
goto EXIT_VENC_CHN_1_UnBind;
}
return TD_SUCCESS;
EXIT_VENC_CHN_1_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[1], venc_vpss_chn->venc_chn[1]);
EXIT_VENC_CHN_1_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[1]);
EXIT_VENC_CHN_0_UnBind:
sample_comm_vpss_un_bind_venc(vpss_grp, venc_vpss_chn->vpss_chn[0], venc_vpss_chn->venc_chn[0]);
EXIT_VENC_CHN0_STOP:
sample_comm_venc_stop(venc_vpss_chn->venc_chn[0]);
return ret;
}
static td_s32 sample_venc_mjpeg_roi_set(td_void)
{
td_s32 ret;
sample_vi_config vi_cfg;
ot_size vi_size = {0};
const ot_vi_pipe vi_pipe = 0;
const ot_vi_chn vi_chn = 0;
const ot_vpss_grp vpss_grp = 0;
sample_venc_vpss_chn_attr vpss_param;
sample_venc_vb_attr vb_attr = {0};
ot_size enc_size[CHN_NUM_MAX];
sample_venc_vpss_chn venc_vpss_chn = {0};
sample_set_venc_vpss_chn(&venc_vpss_chn);
/******************************************
step 0: related parameter ready
******************************************/
if ((ret = sample_venc_init_param(enc_size, CHN_NUM_MAX, &vi_cfg, &vi_size, &vpss_param)) != TD_SUCCESS) {
return ret;
}
/******************************************
step 1: init sys alloc common vb
******************************************/
get_vb_attr(&vi_size, &vpss_param, &vb_attr);
if ((ret = sample_venc_sys_init(&vb_attr)) != TD_SUCCESS) {
sample_print("Init SYS err for %#x!\n", ret);
return ret;
}
if ((ret = sample_venc_vi_init(&vi_cfg)) != TD_SUCCESS) {
sample_print("Init VI err for %#x!\n", ret);
goto EXIT_SYS_STOP;
}
if ((ret = sample_venc_vpss_init(vpss_grp, &vpss_param)) != TD_SUCCESS) {
sample_print("Init VPSS err for %#x!\n", ret);
goto EXIT_VI_STOP;
}
if ((ret = sample_comm_vi_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0)) != TD_SUCCESS) {
sample_print("VI Bind VPSS err for %#x!\n", ret);
goto EXIT_VPSS_STOP;
}
/******************************************
start stream venc
******************************************/
ret = sample_venc_mjpeg_roi_set_start_encode(vpss_grp, &venc_vpss_chn);
if (ret != TD_SUCCESS) {
goto EXIT_VI_VPSS_UNBIND;
}
/******************************************
exit process
******************************************/
sample_venc_exit_process();
sample_venc_unbind_vpss_stop(vpss_grp, &venc_vpss_chn);
EXIT_VI_VPSS_UNBIND:
sample_comm_vi_un_bind_vpss(vi_pipe, vi_chn, vpss_grp, 0);
EXIT_VPSS_STOP:
sample_venc_vpss_deinit(vpss_grp, &vpss_param);
EXIT_VI_STOP:
sample_venc_vi_deinit(&vi_cfg);
EXIT_SYS_STOP:
sample_comm_sys_exit();
return ret;
}
static td_s32 sample_venc_choose_mode(td_u32 index)
{
td_s32 ret;
switch (index) {
case 0: /* 0: mode 0 */
ret = sample_venc_normal();
break;
case 1: /* 1: mode 1 */
ret = sample_venc_qpmap();
break;
case 2: /* 2: mode 2 */
ret = sample_venc_intra_refresh();
break;
case 3: /* 3: mode 3 */
ret = sample_venc_roi_bg();
break;
case 4: /* 4: mode 4 */
ret = sample_venc_debreath_effect();
break;
case 5: /* 5: mode 5 */
ret = sample_venc_mjpeg_roi_set();
break;
case 6: /* 6: mode 6 */
ret = sample_venc_mjpeg_roimap();
break;
default:
printf("the index is invalid!\n");
return TD_FAILURE;
}
return ret;
}
/******************************************************************************
* function : main()
* description : video venc sample
******************************************************************************/
#ifdef __LITEOS__
td_s32 app_main(td_s32 argc, td_char *argv[])
#else
td_s32 main(td_s32 argc, td_char *argv[])
#endif
{
td_s32 ret;
td_u32 index;
if (argc != 2) { /* 2:arg num */
sample_venc_usage(argv[0]);
return TD_FAILURE;
}
if (!strncmp(argv[1], "-h", 2)) { /* 2:arg num */
sample_venc_usage(argv[0]);
return TD_FAILURE;
}
if (strlen(argv[1]) != 1) {
sample_venc_usage(argv[0]);
return TD_FAILURE;
}
if (argv[1][0] < '0' || argv[1][0] > '9') {
sample_venc_usage(argv[0]);
return TD_FAILURE;
}
index = atoi(argv[1]);
#ifndef __LITEOS__
sample_sys_signal(sample_venc_handle_sig);
#endif
ret = sample_venc_choose_mode(index);
if (ret == TD_SUCCESS) {
printf("program exit normally!\n");
} else {
printf("program exit abnormally!\n");
}
#ifdef __LITEOS__
return ret;
#else
exit(ret);
#endif
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */