1106 lines
35 KiB
C
1106 lines
35 KiB
C
/*
|
|
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
|
|
*/
|
|
|
|
#include "sample_hdmi_video_path.h"
|
|
|
|
#define VIDIO_STREAM_PATH "."
|
|
#define AACLC_SAMPLES_PER_FRAME 1024
|
|
#define AUDIO_STREAM_PATH "./source_file/music_8kHz_mono_1min.pcm"
|
|
#define AUDIO_CHANNEL_CNT 2
|
|
#define ERRNO_SYS_INIT_FAILE (-1)
|
|
#define ERRNO_VB_INIT_FAILE (-2)
|
|
#define ERRNO_VDEC_START_FAILE (-3)
|
|
#define ERRNO_VO_START_FAILE (-5)
|
|
#define ERRNO_VPSS_START_FAILE (-4)
|
|
#define ERRNO_VDEC_BIND_FAILE (-6)
|
|
#define ERRNO_STREAM_SEND_FAILE (-7)
|
|
|
|
#define hdmi_if_not_success_return_void(express, name) \
|
|
do { \
|
|
td_s32 re; \
|
|
re = express; \
|
|
if (re != TD_SUCCESS) { \
|
|
printf("\033[0;31mtest case <%s>not pass at line:%d.\033[0;39m\n", __FUNCTION__, __LINE__); \
|
|
return; \
|
|
} \
|
|
} while (0)
|
|
|
|
/* video info */
|
|
static ot_pic_size g_disp_pic_size;
|
|
static ot_vo_intf_type g_vo_intf_type = OT_VO_INTF_HDMI;
|
|
static ot_size g_disp_size;
|
|
static pthread_t g_vdec_thread[NUM_2 * OT_VDEC_MAX_CHN_NUM];
|
|
static sample_media_status g_media_status = SAMPLE_MEDIA_RUN;
|
|
static ot_hdmi_callback_func g_callback_func;
|
|
static hdmi_args g_hdmi_args;
|
|
static td_u32 g_vdec_chn_num = 1;
|
|
static vdec_thread_param g_vdec_send[OT_VDEC_MAX_CHN_NUM];
|
|
static td_u32 g_vpss_grp_num = 1;
|
|
static ot_vo_layer g_vo_layer;
|
|
static sample_vo_cfg g_vo_config;
|
|
static ot_vpss_grp g_vpss_grp;
|
|
static td_bool g_vpss_chn_enable[OT_VPSS_MAX_CHN_NUM];
|
|
/* audio info */
|
|
static ot_payload_type g_payload_type = OT_PT_LPCM;
|
|
static sample_adec g_sample_adec[OT_ADEC_MAX_CHN_NUM];
|
|
static ot_audio_snd_mode g_audio_snd_mode = OT_AUDIO_SOUND_MODE_MONO;
|
|
static ot_audio_sample_rate g_steam_smple_rate = OT_AUDIO_SAMPLE_RATE_BUTT;
|
|
static td_bool g_resample_en = TD_FALSE;
|
|
static aduio_input g_audio_input;
|
|
static td_bool g_audio_input_modified = TD_FALSE;
|
|
static const pic_size_param g_pic[] = {
|
|
{ OT_VO_OUT_480P60, PIC_480P },
|
|
{ OT_VO_OUT_576P50, PIC_576P },
|
|
{ OT_VO_OUT_800x600_60, PIC_800X600 },
|
|
{ OT_VO_OUT_1024x768_60, PIC_1024X768 },
|
|
{ OT_VO_OUT_1366x768_60, PIC_1366X768 },
|
|
{ OT_VO_OUT_1280x1024_60, PIC_1280X1024 },
|
|
{ OT_VO_OUT_2560x1440_60, PIC_2560X1440 },
|
|
{ OT_VO_OUT_1440x900_60, PIC_1440X900 },
|
|
{ OT_VO_OUT_1280x800_60, PIC_1280X800 },
|
|
{ OT_VO_OUT_1600x1200_60, PIC_1600X1200 },
|
|
{ OT_VO_OUT_1680x1050_60, PIC_1680X1050 },
|
|
{ OT_VO_OUT_1920x1200_60, PIC_1920X1200 },
|
|
{ OT_VO_OUT_640x480_60, PIC_640X480 },
|
|
{ OT_VO_OUT_1920x2160_30, PIC_1920X2160 },
|
|
{ OT_VO_OUT_2560x1440_30, PIC_2560X1440 },
|
|
{ OT_VO_OUT_2560x1600_60, PIC_2560X1600 },
|
|
{ OT_VO_OUT_1080P24, PIC_1080P },
|
|
{ OT_VO_OUT_1080P25, PIC_1080P },
|
|
{ OT_VO_OUT_1080P30, PIC_1080P },
|
|
{ OT_VO_OUT_1080P50, PIC_1080P },
|
|
{ OT_VO_OUT_1080P60, PIC_1080P },
|
|
{ OT_VO_OUT_1080I50, PIC_1080P },
|
|
{ OT_VO_OUT_1080I60, PIC_1080P },
|
|
{ OT_VO_OUT_720P50, PIC_720P },
|
|
{ OT_VO_OUT_720P60, PIC_720P },
|
|
{ OT_VO_OUT_3840x2160_24, PIC_3840X2160 },
|
|
{ OT_VO_OUT_3840x2160_25, PIC_3840X2160 },
|
|
{ OT_VO_OUT_3840x2160_30, PIC_3840X2160 },
|
|
{ OT_VO_OUT_3840x2160_50, PIC_3840X2160 },
|
|
{ OT_VO_OUT_3840x2160_60, PIC_3840X2160 },
|
|
{ OT_VO_OUT_4096x2160_24, PIC_4096X2160 },
|
|
{ OT_VO_OUT_4096x2160_25, PIC_4096X2160 },
|
|
{ OT_VO_OUT_4096x2160_30, PIC_4096X2160 },
|
|
{ OT_VO_OUT_4096x2160_50, PIC_4096X2160 },
|
|
{ OT_VO_OUT_4096x2160_60, PIC_4096X2160 },
|
|
{ OT_VO_OUT_7680x4320_30, PIC_7680X4320 },
|
|
};
|
|
|
|
static const vo_hdmi_fmt g_vo_hdmi_fmt[] = {
|
|
{ OT_VO_OUT_PAL, OT_HDMI_VIDEO_FORMAT_PAL },
|
|
{ OT_VO_OUT_NTSC, OT_HDMI_VIDEO_FORMAT_NTSC },
|
|
{ OT_VO_OUT_1080P24, OT_HDMI_VIDEO_FORMAT_1080P_24 },
|
|
{ OT_VO_OUT_1080P25, OT_HDMI_VIDEO_FORMAT_1080P_25 },
|
|
{ OT_VO_OUT_1080P30, OT_HDMI_VIDEO_FORMAT_1080P_30 },
|
|
{ OT_VO_OUT_720P50, OT_HDMI_VIDEO_FORMAT_720P_50 },
|
|
{ OT_VO_OUT_720P60, OT_HDMI_VIDEO_FORMAT_720P_60 },
|
|
{ OT_VO_OUT_1080I50, OT_HDMI_VIDEO_FORMAT_1080i_50 },
|
|
{ OT_VO_OUT_1080I60, OT_HDMI_VIDEO_FORMAT_1080i_60 },
|
|
{ OT_VO_OUT_1080P50, OT_HDMI_VIDEO_FORMAT_1080P_50 },
|
|
{ OT_VO_OUT_1080P60, OT_HDMI_VIDEO_FORMAT_1080P_60 },
|
|
{ OT_VO_OUT_576P50, OT_HDMI_VIDEO_FORMAT_576P_50 },
|
|
{ OT_VO_OUT_480P60, OT_HDMI_VIDEO_FORMAT_480P_60 },
|
|
{ OT_VO_OUT_640x480_60, OT_HDMI_VIDEO_FORMAT_861D_640X480_60 },
|
|
{ OT_VO_OUT_800x600_60, OT_HDMI_VIDEO_FORMAT_VESA_800X600_60 },
|
|
{ OT_VO_OUT_1024x768_60, OT_HDMI_VIDEO_FORMAT_VESA_1024X768_60 },
|
|
{ OT_VO_OUT_1280x1024_60, OT_HDMI_VIDEO_FORMAT_VESA_1280X1024_60 },
|
|
{ OT_VO_OUT_1366x768_60, OT_HDMI_VIDEO_FORMAT_VESA_1366X768_60 },
|
|
{ OT_VO_OUT_1440x900_60, OT_HDMI_VIDEO_FORMAT_VESA_1440X900_60 },
|
|
{ OT_VO_OUT_1280x800_60, OT_HDMI_VIDEO_FORMAT_VESA_1280X800_60 },
|
|
{ OT_VO_OUT_1680x1050_60, OT_HDMI_VIDEO_FORMAT_VESA_1680X1050_60 },
|
|
{ OT_VO_OUT_1920x2160_30, OT_HDMI_VIDEO_FORMAT_1920x2160_30 },
|
|
{ OT_VO_OUT_1600x1200_60, OT_HDMI_VIDEO_FORMAT_VESA_1600X1200_60 },
|
|
{ OT_VO_OUT_1920x1200_60, OT_HDMI_VIDEO_FORMAT_VESA_1920X1200_60 },
|
|
{ OT_VO_OUT_2560x1440_30, OT_HDMI_VIDEO_FORMAT_2560x1440_30 },
|
|
{ OT_VO_OUT_2560x1440_60, OT_HDMI_VIDEO_FORMAT_2560x1440_60 },
|
|
{ OT_VO_OUT_2560x1600_60, OT_HDMI_VIDEO_FORMAT_2560x1600_60 },
|
|
{ OT_VO_OUT_3840x2160_24, OT_HDMI_VIDEO_FORMAT_3840X2160P_24 },
|
|
{ OT_VO_OUT_3840x2160_25, OT_HDMI_VIDEO_FORMAT_3840X2160P_25 },
|
|
{ OT_VO_OUT_3840x2160_30, OT_HDMI_VIDEO_FORMAT_3840X2160P_30 },
|
|
{ OT_VO_OUT_3840x2160_50, OT_HDMI_VIDEO_FORMAT_3840X2160P_50 },
|
|
{ OT_VO_OUT_3840x2160_60, OT_HDMI_VIDEO_FORMAT_3840X2160P_60 }
|
|
};
|
|
|
|
ot_pic_size sample_vdec_get_diplay_cfg(ot_vo_intf_sync intf_sync)
|
|
{
|
|
td_u32 i;
|
|
ot_pic_size pic_size;
|
|
|
|
for (i = 0; i < (sizeof(g_pic) / sizeof(g_pic[0])); i++) {
|
|
if (intf_sync == g_pic[i].vo_sync) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i < (sizeof(g_pic) / sizeof(g_pic[0]))) {
|
|
pic_size = g_pic[i].pic_size;
|
|
} else {
|
|
pic_size = PIC_3840X2160;
|
|
}
|
|
|
|
return pic_size;
|
|
}
|
|
|
|
static td_s32 step2_init_vb(sample_vdec_attr *sample_vdec, td_u32 size)
|
|
{
|
|
td_u32 i;
|
|
td_s32 ret;
|
|
|
|
for (i = 0; i < g_vdec_chn_num && i < size; i++) {
|
|
sample_vdec[i].type = OT_PT_H265;
|
|
sample_vdec[i].width = FMT_3840_2160_WIDTH;
|
|
sample_vdec[i].height = FMT_3840_2160_HEIGHT;
|
|
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;
|
|
sample_vdec[i].sample_vdec_video.ref_frame_num = NUM_2;
|
|
sample_vdec[i].display_frame_num = NUM_2;
|
|
sample_vdec[i].frame_buf_cnt = sample_vdec[i].sample_vdec_video.ref_frame_num +
|
|
sample_vdec[i].display_frame_num + 1;
|
|
}
|
|
|
|
ret = sample_comm_vdec_init_vb_pool(g_vdec_chn_num, &sample_vdec[0], OT_VDEC_MAX_CHN_NUM);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("init mod common vb fail for %#x!\n", ret);
|
|
return ERRNO_VB_INIT_FAILE;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 step4_start_vpss(ot_vpss_chn_attr *vpss_chn_attr, td_u32 size)
|
|
{
|
|
td_u32 i;
|
|
td_s32 ret;
|
|
ot_vpss_grp_attr vpss_grp_attr = {0};
|
|
|
|
if (size < NUM_2) {
|
|
sample_prt("param err %d!\n", size);
|
|
return ERRNO_VPSS_START_FAILE;
|
|
}
|
|
|
|
vpss_grp_attr.max_width = FMT_3840_2160_WIDTH;
|
|
vpss_grp_attr.max_height = FMT_3840_2160_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;
|
|
(td_void)memset_s(g_vpss_chn_enable, sizeof(g_vpss_chn_enable), 0, sizeof(g_vpss_chn_enable));
|
|
g_vpss_chn_enable[1] = TD_TRUE;
|
|
vpss_chn_attr[1].width = g_disp_size.width;
|
|
vpss_chn_attr[1].height = g_disp_size.height;
|
|
vpss_chn_attr[1].chn_mode = OT_VPSS_CHN_MODE_AUTO;
|
|
vpss_chn_attr[1].compress_mode = 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;
|
|
vpss_chn_attr[1].flip_en = TD_FALSE;
|
|
vpss_chn_attr[1].border_en = TD_FALSE;
|
|
vpss_chn_attr[1].aspect_ratio.mode = OT_ASPECT_RATIO_NONE;
|
|
for (i = 0; i < g_vdec_chn_num; i++) {
|
|
g_vpss_grp = i;
|
|
ret = sample_common_vpss_start(g_vpss_grp, &g_vpss_chn_enable[0],
|
|
&vpss_grp_attr, &vpss_chn_attr[0], OT_VPSS_MAX_CHN_NUM);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("start VPSS fail for %#x!\n", ret);
|
|
return ERRNO_VPSS_START_FAILE;
|
|
}
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 step5_start_vo(ot_vo_intf_sync intf_sync)
|
|
{
|
|
td_s32 ret;
|
|
|
|
g_vo_config.vo_dev = SAMPLE_VO_DEV_UHD;
|
|
g_vo_config.vo_intf_type = g_vo_intf_type;
|
|
g_vo_config.intf_sync = intf_sync;
|
|
g_vo_config.pic_size = g_disp_pic_size;
|
|
g_vo_config.bg_color = COLOR_RGB_BLUE;
|
|
g_vo_config.dis_buf_len = NUM_3;
|
|
g_vo_config.dst_dynamic_range = OT_DYNAMIC_RANGE_SDR8;
|
|
g_vo_config.vo_mode = VO_MODE_1MUX;
|
|
g_vo_config.pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
|
|
g_vo_config.disp_rect.x = 0;
|
|
g_vo_config.disp_rect.y = 0;
|
|
g_vo_config.disp_rect.width = g_disp_size.width;
|
|
g_vo_config.disp_rect.height = g_disp_size.height;
|
|
g_vo_config.image_size.width = g_disp_size.width;
|
|
g_vo_config.image_size.height = g_disp_size.height;
|
|
g_vo_config.vo_part_mode = OT_VO_PARTITION_MODE_SINGLE;
|
|
|
|
ret = sample_comm_vo_start_vo(&g_vo_config);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("start VO fail for %#x!\n", ret);
|
|
return ERRNO_VO_START_FAILE;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 step8_send_stream_to_vdec(sample_vdec_attr *sample_vdec, td_u32 size)
|
|
{
|
|
td_u32 i;
|
|
td_s32 ret;
|
|
|
|
for (i = 0; i < g_vdec_chn_num && i < size; i++) {
|
|
ret = snprintf_s(g_vdec_send[i].c_file_name, FILE_NAME_LEN, FILE_NAME_LEN - 1,
|
|
"source_file/3840x2160_8bit.h265");
|
|
if (ret < 0) {
|
|
sample_prt("snprintf_s err\n");
|
|
return ERRNO_STREAM_SEND_FAILE;
|
|
}
|
|
ret = snprintf_s(g_vdec_send[i].c_file_path, FILE_NAME_LEN, FILE_NAME_LEN - 1, "%s", VIDIO_STREAM_PATH);
|
|
if (ret < 0) {
|
|
sample_prt("snprintf_s err\n");
|
|
return ERRNO_STREAM_SEND_FAILE;
|
|
}
|
|
g_vdec_send[i].type = sample_vdec[i].type;
|
|
g_vdec_send[i].stream_mode = sample_vdec[i].mode;
|
|
g_vdec_send[i].chn_id = i;
|
|
g_vdec_send[i].interval_time = NUM_1000;
|
|
g_vdec_send[i].pts_init = 0;
|
|
g_vdec_send[i].pts_increase = 0;
|
|
g_vdec_send[i].e_thread_ctrl = THREAD_CTRL_START;
|
|
g_vdec_send[i].circle_send = TD_TRUE;
|
|
g_vdec_send[i].milli_sec = 0;
|
|
g_vdec_send[i].min_buf_size = (sample_vdec[i].width * sample_vdec[i].height * NUM_3) >> 1;
|
|
}
|
|
|
|
sample_comm_vdec_start_send_stream(g_vdec_chn_num, &g_vdec_send[0], &g_vdec_thread[0],
|
|
OT_VDEC_MAX_CHN_NUM, NUM_2 * OT_VDEC_MAX_CHN_NUM);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_void error_handle(td_s32 err)
|
|
{
|
|
td_u32 i;
|
|
td_s32 j, ret;
|
|
|
|
switch (err) {
|
|
case ERRNO_STREAM_SEND_FAILE: {
|
|
for (i = 0; i < g_vpss_grp_num; i++) {
|
|
ret = sample_comm_vpss_un_bind_vo(i, 1, g_vo_layer, i);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("vpss unbind vo fail for %#x!\n", ret);
|
|
}
|
|
}
|
|
}; /* fall-through */
|
|
case ERRNO_VDEC_BIND_FAILE: {
|
|
for (i = 0; i < g_vdec_chn_num; i++) {
|
|
ret = sample_comm_vdec_un_bind_vpss(i, i);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("vdec unbind vpss fail for %#x!\n", ret);
|
|
}
|
|
}
|
|
}; /* fall-through */
|
|
case ERRNO_VO_START_FAILE: {
|
|
sample_comm_vo_stop_vo(&g_vo_config);
|
|
}; /* fall-through */
|
|
case ERRNO_VPSS_START_FAILE: {
|
|
for (j = g_vpss_grp; j >= 0; j--) {
|
|
sample_common_vpss_stop(j, &g_vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
|
|
}
|
|
}; /* fall-through */
|
|
case ERRNO_VDEC_START_FAILE: {
|
|
sample_comm_vdec_stop(g_vdec_chn_num);
|
|
}; /* fall-through */
|
|
case ERRNO_VB_INIT_FAILE: {
|
|
sample_comm_vdec_exit_vb_pool();
|
|
}; /* fall-through */
|
|
case ERRNO_SYS_INIT_FAILE: {
|
|
sample_comm_sys_exit();
|
|
} break;
|
|
default: {
|
|
sample_prt("err errno :%d\n", err);
|
|
} break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static td_s32 step1_init(ot_vo_intf_sync intf_sync)
|
|
{
|
|
td_s32 ret;
|
|
ot_vb_cfg vb_cfg = {0};
|
|
ot_pic_buf_attr buf_attr = {0};
|
|
|
|
g_disp_pic_size = sample_vdec_get_diplay_cfg(intf_sync);
|
|
ret = sample_comm_sys_get_pic_size(g_disp_pic_size, &g_disp_size);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("sys get pic size fail for %#x!\n", ret);
|
|
return ERRNO_SYS_INIT_FAILE;
|
|
}
|
|
|
|
buf_attr.align = 0;
|
|
buf_attr.bit_width = OT_DATA_BIT_WIDTH_8;
|
|
buf_attr.compress_mode = OT_COMPRESS_MODE_SEG;
|
|
buf_attr.height = FMT_3840_2160_WIDTH;
|
|
buf_attr.width = FMT_3840_2160_HEIGHT;
|
|
buf_attr.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
|
|
|
|
vb_cfg.max_pool_cnt = 1;
|
|
vb_cfg.common_pool[0].blk_cnt = NUM_10 * g_vdec_chn_num;
|
|
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_prt("init sys fail for %#x!\n", ret);
|
|
return ERRNO_SYS_INIT_FAILE;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 sample_hdmi_vdec_vpss_vo_start(ot_vo_intf_sync intf_sync)
|
|
{
|
|
td_u32 i;
|
|
td_s32 ret;
|
|
sample_vdec_attr sample_vdec[OT_VDEC_MAX_CHN_NUM] = {0};
|
|
ot_vpss_chn_attr vpss_chn_attr[OT_VPSS_MAX_CHN_NUM] = {0};
|
|
|
|
/* step1: init */
|
|
ret = step1_init(intf_sync);
|
|
if (ret != TD_SUCCESS) {
|
|
goto end;
|
|
}
|
|
|
|
/* step2: init module VB or user VB(for VDEC) */
|
|
ret = step2_init_vb(sample_vdec, OT_VDEC_MAX_CHN_NUM);
|
|
if (ret != TD_SUCCESS) {
|
|
goto end;
|
|
}
|
|
|
|
/* step3: start VDEC */
|
|
ret = sample_comm_vdec_start(g_vdec_chn_num, &sample_vdec[0], OT_VDEC_MAX_CHN_NUM);
|
|
if (ret != TD_SUCCESS) {
|
|
ret = ERRNO_VDEC_START_FAILE;
|
|
goto end;
|
|
}
|
|
|
|
/* step4: start VPSS */
|
|
ret = step4_start_vpss(vpss_chn_attr, OT_VPSS_MAX_CHN_NUM);
|
|
if (ret != TD_SUCCESS) {
|
|
goto end;
|
|
}
|
|
|
|
/* step5: start VO */
|
|
ret = step5_start_vo(intf_sync);
|
|
if (ret != TD_SUCCESS) {
|
|
goto end;
|
|
}
|
|
|
|
/* step6: VDEC bind VPSS */
|
|
for (i = 0; i < g_vdec_chn_num; i++) {
|
|
ret = sample_comm_vdec_bind_vpss(i, i);
|
|
if (ret != TD_SUCCESS) {
|
|
ret = ERRNO_VDEC_BIND_FAILE;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
/* step7: VPSS bind VO */
|
|
g_vo_layer = g_vo_config.vo_dev;
|
|
for (i = 0; i < g_vpss_grp_num; i++) {
|
|
ret = sample_comm_vpss_bind_vo(i, 1, g_vo_layer, i);
|
|
if (ret != TD_SUCCESS) {
|
|
ret = ERRNO_STREAM_SEND_FAILE;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
/* step8: send stream to VDEC */
|
|
ret = step8_send_stream_to_vdec(sample_vdec, OT_VDEC_MAX_CHN_NUM);
|
|
if (ret != TD_SUCCESS) {
|
|
goto end;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
|
|
end:
|
|
error_handle(ret);
|
|
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
td_s32 sample_hdmi_vdec_vpss_vo_stop(td_void)
|
|
{
|
|
td_u32 i;
|
|
td_s32 j;
|
|
|
|
sample_comm_vdec_stop_send_stream(g_vdec_chn_num, &g_vdec_send[0], &g_vdec_thread[0],
|
|
OT_VDEC_MAX_CHN_NUM, NUM_2 * OT_VDEC_MAX_CHN_NUM);
|
|
|
|
for (i = 0; i < g_vpss_grp_num; i++) {
|
|
sample_comm_vpss_un_bind_vo(i, 1, g_vo_layer, i);
|
|
}
|
|
|
|
for (i = 0; i < g_vdec_chn_num; i++) {
|
|
sample_comm_vdec_un_bind_vpss(i, i);
|
|
}
|
|
|
|
sample_comm_vo_stop_vo(&g_vo_config);
|
|
|
|
for (j = g_vpss_grp; j >= 0; j--) {
|
|
sample_common_vpss_stop(j, &g_vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
|
|
}
|
|
|
|
sample_comm_vdec_stop(g_vdec_chn_num);
|
|
sample_comm_vdec_exit_vb_pool();
|
|
sample_comm_sys_exit();
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_void sample_hdmi_media_set(td_bool run)
|
|
{
|
|
if (run == TD_FALSE) {
|
|
g_media_status = SAMPLE_MEDIA_STOP;
|
|
} else {
|
|
g_media_status = SAMPLE_MEDIA_RUN;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static td_void hdmi_mst_hdmi_convert_sync(ot_vo_intf_sync intf_sync, ot_hdmi_video_format *video_format)
|
|
{
|
|
td_u32 i;
|
|
|
|
for (i = 0; i < (sizeof(g_vo_hdmi_fmt) / sizeof(g_vo_hdmi_fmt[0])); i++) {
|
|
if (intf_sync == g_vo_hdmi_fmt[i].intf_sync) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i < (sizeof(g_vo_hdmi_fmt) / sizeof(g_vo_hdmi_fmt[0]))) {
|
|
*video_format = g_vo_hdmi_fmt[i].hdmi_fmt;
|
|
} else {
|
|
*video_format = OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static td_void hdmi_hot_plug_proc(td_void *private_data)
|
|
{
|
|
td_s32 ret;
|
|
hdmi_args args = {0};
|
|
ot_hdmi_attr attr = {0};
|
|
ot_hdmi_sink_capability caps = {0};
|
|
|
|
printf("\033[32;1mEVENT: HPD\033[0m\n");
|
|
|
|
if (private_data == TD_NULL) {
|
|
printf("\033[31;1m[%s:%d]null pointer!\033[0m\n", __FUNCTION__, __LINE__);
|
|
return;
|
|
}
|
|
|
|
ret = memcpy_s(&args, sizeof(args), private_data, sizeof(hdmi_args));
|
|
if (ret != EOK) {
|
|
sample_prt("return; failed!\n");
|
|
return;
|
|
}
|
|
ret = ss_mpi_hdmi_get_sink_capability(args.hdmi, &caps);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("get sink caps failed!\n");
|
|
} else {
|
|
sample_prt("get sink caps success!\n");
|
|
}
|
|
ret = ss_mpi_hdmi_get_attr(args.hdmi, &attr);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("get attr failed: 0x%x!\n", ret);
|
|
}
|
|
ret = ss_mpi_hdmi_set_attr(args.hdmi, &attr);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("set attr failed: 0x%x!\n", ret);
|
|
}
|
|
ss_mpi_hdmi_start(args.hdmi);
|
|
|
|
return;
|
|
}
|
|
|
|
static td_void hdmi_un_plug_proc(td_void *private_data)
|
|
{
|
|
td_s32 ret;
|
|
hdmi_args args = {0};
|
|
|
|
printf("\033[32;1mEVENT: UN-HPD\033[0m\n");
|
|
|
|
if (private_data == TD_NULL) {
|
|
printf("\033[31;1m[%s:%d]null pointer!\033[0m\n", __FUNCTION__, __LINE__);
|
|
return;
|
|
}
|
|
|
|
ret = memcpy_s(&args, sizeof(args), private_data, sizeof(hdmi_args));
|
|
if (ret != EOK) {
|
|
sample_prt("memcpy_s err. /n");
|
|
return;
|
|
}
|
|
|
|
ret = ss_mpi_hdmi_stop(args.hdmi);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("ret = %d./n", ret);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static td_void hdmi_event_call_back(ot_hdmi_event_type event, td_void *private_data)
|
|
{
|
|
switch (event) {
|
|
case OT_HDMI_EVENT_HOTPLUG:
|
|
hdmi_hot_plug_proc(private_data);
|
|
break;
|
|
case OT_HDMI_EVENT_NO_PLUG:
|
|
hdmi_un_plug_proc(private_data);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
td_void sample_hdmi_start(ot_vo_intf_sync intf_sync)
|
|
{
|
|
td_s32 ret;
|
|
ot_hdmi_attr attr = {0};
|
|
ot_vo_hdmi_param hdmi_param = {0};
|
|
ot_hdmi_video_format video_format;
|
|
ot_hdmi_sink_capability capability = {0};
|
|
|
|
hdmi_mst_hdmi_convert_sync(intf_sync, &video_format);
|
|
|
|
g_hdmi_args.hdmi = OT_HDMI_ID_0;
|
|
g_callback_func.hdmi_event_callback = hdmi_event_call_back;
|
|
g_callback_func.private_data = &g_hdmi_args;
|
|
|
|
ret = ss_mpi_hdmi_init();
|
|
sample_if_failure_return_void(ret);
|
|
|
|
ret = ss_mpi_hdmi_open(OT_HDMI_ID_0);
|
|
sample_if_failure_return_void(ret);
|
|
|
|
ret = ss_mpi_hdmi_register_callback(OT_HDMI_ID_0, &g_callback_func);
|
|
sample_if_failure_return_void(ret);
|
|
|
|
ret = ss_mpi_hdmi_get_attr(OT_HDMI_ID_0, &attr);
|
|
sample_if_failure_return_void(ret);
|
|
|
|
attr.hdmi_en = TD_TRUE;
|
|
attr.video_format = video_format;
|
|
attr.deep_color_mode = OT_HDMI_DEEP_COLOR_24BIT;
|
|
attr.bit_depth = OT_HDMI_BIT_DEPTH_16;
|
|
attr.audio_en = TD_TRUE;
|
|
attr.sample_rate = OT_HDMI_SAMPLE_RATE_48K;
|
|
|
|
ret = ss_mpi_hdmi_set_attr(OT_HDMI_ID_0, &attr);
|
|
sample_if_failure_return_void(ret);
|
|
|
|
ret = ss_mpi_hdmi_get_sink_capability(OT_HDMI_ID_0, &capability);
|
|
sample_if_failure_return_void(ret);
|
|
|
|
if (capability.support_hdmi == TD_FALSE || capability.support_ycbcr == TD_FALSE) {
|
|
ret = ss_mpi_vo_get_hdmi_param(SAMPLE_VO_DEV_DHD0, &hdmi_param);
|
|
sample_if_failure_return_void(ret);
|
|
hdmi_param.csc.csc_matrix = OT_VO_CSC_MATRIX_BT709FULL_TO_RGBFULL;
|
|
ret = ss_mpi_vo_set_hdmi_param(SAMPLE_VO_DEV_DHD0, &hdmi_param);
|
|
sample_if_failure_return_void(ret);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static td_s32 sample_stop_vo(sample_vo_cfg *vo_config)
|
|
{
|
|
td_s32 ret;
|
|
ot_vo_dev vo_dev;
|
|
ot_vo_layer vo_layer;
|
|
sample_vo_mode vo_mode;
|
|
|
|
if (vo_config == TD_NULL) {
|
|
sample_print("error:argument can not be NULL\n");
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
vo_dev = vo_config->vo_dev;
|
|
vo_layer = vo_config->vo_dev;
|
|
vo_mode = vo_config->vo_mode;
|
|
|
|
ret = sample_comm_vo_stop_chn(vo_layer, vo_mode);
|
|
sample_if_failure_return(ret, TD_FAILURE);
|
|
ret = sample_comm_vo_stop_layer(vo_layer);
|
|
sample_if_failure_return(ret, TD_FAILURE);
|
|
ret = sample_comm_vo_stop_dev(vo_dev);
|
|
sample_if_failure_return(ret, TD_FAILURE);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 sample_hdmi_fmt_change(ot_vo_intf_sync intf_sync, td_bool rgb_enable)
|
|
{
|
|
td_s32 ret;
|
|
ot_hdmi_attr attr = {0};
|
|
td_bool rgb_en = TD_FALSE;
|
|
|
|
ss_mpi_hdmi_stop(OT_HDMI_ID_0);
|
|
ret = sample_stop_vo(&g_vo_config);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("sys get pic size fail for %#x!\n", ret);
|
|
goto err1;
|
|
}
|
|
|
|
g_disp_pic_size = sample_vdec_get_diplay_cfg(intf_sync);
|
|
ret = sample_comm_sys_get_pic_size(g_disp_pic_size, &g_disp_size);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("sys get pic size fail for %#x!\n", ret);
|
|
goto err1;
|
|
}
|
|
|
|
ret = ss_mpi_hdmi_get_attr(OT_HDMI_ID_0, &attr);
|
|
sample_if_failure_return(ret, TD_FAILURE);
|
|
if (attr.hdmi_en == TD_FALSE || rgb_enable == TD_TRUE) {
|
|
rgb_en = TD_TRUE;
|
|
}
|
|
sample_comm_vo_set_hdmi_rgb_mode(rgb_en);
|
|
|
|
g_vo_config.intf_sync = intf_sync;
|
|
g_vo_config.pic_size = g_disp_pic_size;
|
|
g_vo_config.disp_rect.width = g_disp_size.width;
|
|
g_vo_config.disp_rect.height = g_disp_size.height;
|
|
g_vo_config.image_size.width = g_disp_size.width;
|
|
g_vo_config.image_size.height = g_disp_size.height;
|
|
ret = sample_comm_vo_start_vo(&g_vo_config);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("start VO fail for %#x!\n", ret);
|
|
goto err2;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
|
|
err2:
|
|
sample_comm_vo_stop_vo(&g_vo_config);
|
|
|
|
err1:
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
td_s32 sample_hdmi_set_audio_sample_rate(td_u32 sample_rate)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (sample_rate != g_audio_input.sample_rate) {
|
|
g_audio_input.sample_rate = sample_rate;
|
|
g_audio_input_modified = TD_TRUE;
|
|
|
|
ret = sample_hdmi_stop_audio();
|
|
sample_if_failure_return(ret, TD_FAILURE);
|
|
ret = sample_hdmi_start_audio();
|
|
sample_if_failure_return(ret, TD_FAILURE);
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_void hdmi_mst_audio_start_hdmi(ot_aio_attr *attr)
|
|
{
|
|
ot_hdmi_attr hdmi_attr = {0};
|
|
ot_hdmi_id hdmi = OT_HDMI_ID_0;
|
|
|
|
hdmi_if_not_success_return_void(ss_mpi_hdmi_set_avmute(hdmi, TD_TRUE), "hdmi_set_av_mute");
|
|
hdmi_if_not_success_return_void(ss_mpi_hdmi_get_attr(hdmi, &hdmi_attr), "hdmi_get_attr");
|
|
|
|
hdmi_attr.audio_en = TD_TRUE;
|
|
|
|
if (attr->sample_rate == OT_AUDIO_SAMPLE_RATE_48000) {
|
|
hdmi_attr.sample_rate = OT_HDMI_SAMPLE_RATE_48K;
|
|
} else if (attr->sample_rate == OT_AUDIO_SAMPLE_RATE_44100) {
|
|
hdmi_attr.sample_rate = OT_HDMI_SAMPLE_RATE_44K;
|
|
} else if (attr->sample_rate == OT_AUDIO_SAMPLE_RATE_32000) {
|
|
hdmi_attr.sample_rate = OT_HDMI_SAMPLE_RATE_32K;
|
|
}
|
|
|
|
if (attr->bit_width == OT_AUDIO_BIT_WIDTH_16) {
|
|
hdmi_attr.bit_depth = OT_HDMI_BIT_DEPTH_16;
|
|
} else if (attr->bit_width == OT_AUDIO_BIT_WIDTH_8) {
|
|
hdmi_attr.bit_depth = OT_HDMI_BIT_DEPTH_8;
|
|
} else if (attr->bit_width == OT_AUDIO_BIT_WIDTH_24) {
|
|
hdmi_attr.bit_depth = OT_HDMI_BIT_DEPTH_24;
|
|
}
|
|
hdmi_if_not_success_return_void(ss_mpi_hdmi_stop(hdmi), "hdmi_stop");
|
|
hdmi_if_not_success_return_void(ss_mpi_hdmi_set_attr(hdmi, &hdmi_attr), "hdmi_set_attr");
|
|
hdmi_if_not_success_return_void(ss_mpi_hdmi_start(hdmi), "hdmi_start");
|
|
hdmi_if_not_success_return_void(ss_mpi_hdmi_set_avmute(hdmi, TD_FALSE), "hdmi_set_av_mute");
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* function : start adec
|
|
*/
|
|
td_s32 hdmi_mst_start_adec(ot_adec_chn ad_chn, ot_payload_type type)
|
|
{
|
|
td_s32 ret;
|
|
ot_adec_chn_attr adec_attr = {0};
|
|
ot_adec_attr_adpcm adec_adpcm = {0};
|
|
ot_adec_attr_lpcm adec_lpcm;
|
|
|
|
adec_attr.type = type;
|
|
adec_attr.buf_size = NUM_20;
|
|
adec_attr.mode = OT_ADEC_MODE_STREAM; /* propose use pack mode in your app */
|
|
|
|
if (adec_attr.type == OT_PT_ADPCMA) {
|
|
adec_attr.value = &adec_adpcm;
|
|
adec_adpcm.adpcm_type = OT_ADPCM_TYPE_DVI4;
|
|
} else {
|
|
adec_attr.value = &adec_lpcm;
|
|
adec_attr.mode = OT_ADEC_MODE_PACK; /* lpcm must use pack mode */
|
|
}
|
|
|
|
/* create adec chn */
|
|
ret = ss_mpi_adec_create_chn(ad_chn, &adec_attr);
|
|
if (ret) {
|
|
sample_prt("adec_create_chn(%d) failed with %#x!\n", ad_chn, ret);
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
td_s32 hdmi_mst_comm_start_ao(ot_audio_dev ao_dev_id, td_s32 ao_chn_cnt,
|
|
ot_aio_attr *attr, ot_audio_sample_rate in_sample_rate, td_bool resample_en)
|
|
{
|
|
td_s32 i;
|
|
td_u32 ret;
|
|
|
|
if (attr->chn_cnt == 0) {
|
|
attr->chn_cnt = 1;
|
|
}
|
|
|
|
ret = ss_mpi_ao_set_pub_attr(ao_dev_id, attr);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("ao_set_pub_attr(%d) failed with %#x!\n", ao_dev_id, ret);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
ret = ss_mpi_ao_enable(ao_dev_id);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("ao_enable(%d) failed with %#x!\n", ao_dev_id, ret);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
for (i = 0; i < ao_chn_cnt; i++) {
|
|
ret = ss_mpi_ao_enable_chn(ao_dev_id, i);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("ao_enable_chn(%d) failed with %#x!\n", i, ret);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
if (resample_en == TD_TRUE && attr->snd_mode == OT_AUDIO_SOUND_MODE_MONO) {
|
|
ret = ss_mpi_ao_disable_resample(ao_dev_id, i);
|
|
ret = ss_mpi_ao_enable_resample(ao_dev_id, i, in_sample_rate);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("ao_enable_re_smp(%d,%d) failed with %#x!\n", ao_dev_id, i, ret);
|
|
return TD_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* function : ao bind adec
|
|
*/
|
|
td_s32 hdmi_mst_comm_ao_bind_adec(ot_audio_dev ao_dev, ot_ao_chn ao_chn, ot_adec_chn ad_chn)
|
|
{
|
|
ot_mpp_chn src_chn, dest_chn;
|
|
|
|
src_chn.mod_id = OT_ID_ADEC;
|
|
src_chn.dev_id = 0;
|
|
src_chn.chn_id = ad_chn;
|
|
dest_chn.mod_id = OT_ID_AO;
|
|
dest_chn.dev_id = ao_dev;
|
|
dest_chn.chn_id = ao_chn;
|
|
|
|
return ss_mpi_sys_bind(&src_chn, &dest_chn);
|
|
}
|
|
|
|
/*
|
|
* function : ao unbind adec
|
|
*/
|
|
td_s32 hdmi_mst_comm_ao_unbind_adec(ot_audio_dev ao_dev, ot_ao_chn ao_chn, ot_adec_chn ad_chn)
|
|
{
|
|
ot_mpp_chn src_chn, dest_chn;
|
|
|
|
src_chn.mod_id = OT_ID_ADEC;
|
|
src_chn.chn_id = ad_chn;
|
|
src_chn.dev_id = 0;
|
|
dest_chn.mod_id = OT_ID_AO;
|
|
dest_chn.dev_id = ao_dev;
|
|
dest_chn.chn_id = ao_chn;
|
|
|
|
return ss_mpi_sys_unbind(&src_chn, &dest_chn);
|
|
}
|
|
|
|
/*
|
|
* function : get stream from file, and send it to adec
|
|
*/
|
|
void *hdmi_mst_comm_adec_proc(void *parg)
|
|
{
|
|
td_s32 ret;
|
|
ot_audio_stream aud_stream;
|
|
td_u32 len = NUM_1024;
|
|
td_u32 read_len;
|
|
td_s32 adec_chn;
|
|
td_u8 *audio_stream = NULL;
|
|
sample_adec *adec_ctl = (sample_adec *)parg;
|
|
FILE *pfd = adec_ctl->pfd;
|
|
adec_chn = adec_ctl->ad_chn;
|
|
|
|
audio_stream = (td_u8 *)malloc(sizeof(td_u8) * OT_MAX_AUDIO_STREAM_LEN);
|
|
if (audio_stream == NULL) {
|
|
sample_prt("malloc failed!\n");
|
|
fclose(pfd);
|
|
return NULL;
|
|
}
|
|
(td_void)memset_s(audio_stream, OT_MAX_AUDIO_STREAM_LEN, 0, OT_MAX_AUDIO_STREAM_LEN);
|
|
|
|
while (adec_ctl->start == TD_TRUE) {
|
|
/* read from file */
|
|
aud_stream.stream = audio_stream;
|
|
read_len = fread(aud_stream.stream, 1, len, pfd);
|
|
if (read_len <= 0) {
|
|
fseek(pfd, 0, SEEK_SET); /* read file again */
|
|
continue;
|
|
}
|
|
|
|
/* here only demo adec streaming sending mode, but pack sending mode is commended */
|
|
aud_stream.len = read_len;
|
|
ret = ss_mpi_adec_send_stream(adec_chn, &aud_stream, TD_TRUE);
|
|
if (ret != TD_SUCCESS) {
|
|
sample_prt("%s: ss_mpi_adec_send_stream(%d) failed with %#x!\n",
|
|
__FUNCTION__, adec_chn, ret);
|
|
break;
|
|
}
|
|
}
|
|
|
|
free(audio_stream);
|
|
audio_stream = NULL;
|
|
fclose(pfd);
|
|
adec_ctl->start = TD_FALSE;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* function : create the thread to get stream from file and send to adec
|
|
*/
|
|
td_s32 hdmi_mst_comm_creat_trd_file_adec(ot_adec_chn ad_chn, td_char *src_path)
|
|
{
|
|
td_char *path = TD_NULL;
|
|
sample_adec *adec = NULL;
|
|
|
|
if (src_path == NULL) {
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
if (ad_chn >= OT_ADEC_MAX_CHN_NUM) {
|
|
sample_prt("param err!\n");
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
adec = &g_sample_adec[ad_chn];
|
|
adec->ad_chn = ad_chn;
|
|
|
|
path = realpath(src_path, TD_NULL);
|
|
if (path == TD_NULL) {
|
|
sample_prt("\033[31;1m realpath err! \033[0m\n");
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
adec->pfd = fopen(path, "rb");
|
|
if (adec->pfd == NULL) {
|
|
sample_prt("open file %s failed\n", path);
|
|
free(path);
|
|
return TD_FAILURE;
|
|
}
|
|
adec->start = TD_TRUE;
|
|
pthread_create(&adec->ad_pid, 0, hdmi_mst_comm_adec_proc, adec);
|
|
free(path);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* function : file -> a_dec -> ao
|
|
*/
|
|
td_void hdmi_mst_adec_ao(ot_aio_attr *attr, td_char *src_path)
|
|
{
|
|
td_s32 i;
|
|
td_s32 ao_chn_cnt;
|
|
|
|
g_audio_input.ao_dev = 1;
|
|
if (attr == NULL) {
|
|
sample_prt("\033[31;1m%s: input point is invalid!\033[0m\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
hdmi_mst_audio_start_hdmi(attr);
|
|
ao_chn_cnt = (td_s32)(attr->chn_cnt >> (td_u32)attr->snd_mode);
|
|
for (i = 0; i < ao_chn_cnt; i++) {
|
|
hdmi_if_not_success_return_void(hdmi_mst_start_adec(i, g_payload_type), "start_adec");
|
|
}
|
|
hdmi_if_not_success_return_void(hdmi_mst_comm_start_ao(g_audio_input.ao_dev, ao_chn_cnt, attr,
|
|
g_steam_smple_rate, g_resample_en), "start_ao");
|
|
for (i = 0; i < ao_chn_cnt; i++) {
|
|
hdmi_if_not_success_return_void(hdmi_mst_comm_ao_bind_adec(g_audio_input.ao_dev, i, i), "ao_bind_adec");
|
|
hdmi_if_not_success_return_void(hdmi_mst_comm_creat_trd_file_adec(i, src_path), "creat_trd_file_adec");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
td_s32 sample_hdmi_start_audio(td_void)
|
|
{
|
|
td_u32 strm_smprate;
|
|
td_u32 strm_point_num;
|
|
ot_aio_attr attr = {0};
|
|
|
|
if (g_audio_input_modified != TD_TRUE) {
|
|
g_audio_input.src_path = AUDIO_STREAM_PATH;
|
|
g_audio_input.chnl_num = AUDIO_CHANNEL_CNT;
|
|
g_audio_input.sample_rate = OT_HDMI_SAMPLE_RATE_48K;
|
|
}
|
|
|
|
g_payload_type = OT_PT_LPCM;
|
|
|
|
/* init aio. all of cases will use it */
|
|
attr.bit_width = OT_AUDIO_BIT_WIDTH_16;
|
|
attr.work_mode = OT_AIO_MODE_I2S_MASTER;
|
|
attr.snd_mode = OT_AUDIO_SOUND_MODE_MONO;
|
|
attr.expand_flag = 0;
|
|
attr.frame_num = NUM_30;
|
|
attr.chn_cnt = AUDIO_CHANNEL_CNT;
|
|
attr.clk_share = 1;
|
|
attr.i2s_type = OT_AIO_I2STYPE_INNERHDMI;
|
|
attr.point_num_per_frame = AACLC_SAMPLES_PER_FRAME;
|
|
|
|
if (g_audio_input.sample_rate == OT_HDMI_SAMPLE_RATE_48K) {
|
|
attr.sample_rate = OT_AUDIO_SAMPLE_RATE_48000;
|
|
} else if (g_audio_input.sample_rate == OT_HDMI_SAMPLE_RATE_44K) {
|
|
attr.sample_rate = OT_AUDIO_SAMPLE_RATE_44100;
|
|
} else if (g_audio_input.sample_rate == OT_HDMI_SAMPLE_RATE_32K) {
|
|
attr.sample_rate = OT_AUDIO_SAMPLE_RATE_32000;
|
|
} else {
|
|
sample_prt("wrong audio sample rate: %d!\n", g_audio_input.sample_rate);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
strm_smprate = OT_AUDIO_SAMPLE_RATE_8000;
|
|
strm_point_num = NUM_320;
|
|
attr.point_num_per_frame = strm_point_num * attr.sample_rate / strm_smprate;
|
|
|
|
if (attr.point_num_per_frame > OT_MAX_AO_POINT_NUM || attr.point_num_per_frame < OT_MIN_AUDIO_POINT_NUM) {
|
|
sample_prt("invalid OT_PT_num_per_frm:%d\n", attr.point_num_per_frame);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
g_resample_en = TD_TRUE;
|
|
g_steam_smple_rate = strm_smprate;
|
|
hdmi_mst_adec_ao(&attr, g_audio_input.src_path);
|
|
g_audio_snd_mode = attr.snd_mode;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* function : destroy the thread to get stream from file and send to adec
|
|
*/
|
|
td_s32 hdmi_mst_comm_destory_trd_file_adec(ot_adec_chn ad_chn)
|
|
{
|
|
sample_adec *adec = NULL;
|
|
|
|
if (ad_chn >= OT_ADEC_MAX_CHN_NUM) {
|
|
printf("err param ad_chn: %d\n", ad_chn);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
adec = &g_sample_adec[ad_chn];
|
|
if (adec->start) {
|
|
adec->start = TD_FALSE;
|
|
pthread_join(adec->ad_pid, 0);
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 hdmi_mst_comm_stop_ao(ot_audio_dev ao_dev_id, td_s32 ao_chn_cnt, td_bool resample_en)
|
|
{
|
|
td_s32 i, ret;
|
|
|
|
for (i = 0; i < ao_chn_cnt; i++) {
|
|
if (resample_en == TD_TRUE) {
|
|
ret = ss_mpi_ao_disable_resample(ao_dev_id, i);
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
}
|
|
ret = ss_mpi_ao_disable_chn(ao_dev_id, i);
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
}
|
|
ret = ss_mpi_ao_disable(ao_dev_id);
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* function : stop adec
|
|
*/
|
|
td_s32 hdmi_mst_comm_stop_adec(ot_adec_chn ad_chn)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = ss_mpi_adec_destroy_chn(ad_chn);
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 sample_hdmi_stop_audio(td_void)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 i;
|
|
td_u32 ao_chn_cnt = g_audio_input.chnl_num >> (td_u32)g_audio_snd_mode;
|
|
|
|
for (i = 0; i < ao_chn_cnt; i++) {
|
|
ret = hdmi_mst_comm_destory_trd_file_adec(i);
|
|
ret = hdmi_mst_comm_ao_unbind_adec(g_audio_input.ao_dev, i, i);
|
|
}
|
|
ret = hdmi_mst_comm_stop_ao(g_audio_input.ao_dev, ao_chn_cnt, g_resample_en);
|
|
|
|
for (i = 0; i < ao_chn_cnt; i++) {
|
|
ret = hdmi_mst_comm_stop_adec(i);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|