Files
hisi_SS524V100_SDK/mpp/sample/common/sample_comm_vo.c
T

1241 lines
39 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
*/
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include "sample_comm.h"
#if VO_LT8618SX
#include "lt8618sx.h"
#endif
#ifdef __cplusplus
#if __cplusplus
#endif
#endif /* end of #ifdef __cplusplus */
static td_bool g_vo_hdmi_rgb_mode = TD_FALSE;
static sample_vo_sync_info g_vo_sample_sync_info[OT_VO_OUT_BUTT] = {
{ OT_VO_OUT_PAL, 720, 576, 25 },
{ OT_VO_OUT_NTSC, 720, 480, 30 },
{ OT_VO_OUT_960H_PAL, 960, 576, 25 },
{ OT_VO_OUT_960H_NTSC, 960, 480, 30 },
{ OT_VO_OUT_640x480_60, 640, 480, 60 },
{ OT_VO_OUT_480P60, 720, 480, 60 },
{ OT_VO_OUT_576P50, 720, 576, 50 },
{ OT_VO_OUT_800x600_60, 800, 600, 60 },
{ OT_VO_OUT_1024x768_60, 1024, 768, 60 },
{ OT_VO_OUT_720P50, 1280, 720, 50 },
{ OT_VO_OUT_720P60, 1280, 720, 60 },
{ OT_VO_OUT_1280x800_60, 1280, 800, 60 },
{ OT_VO_OUT_1280x1024_60, 1280, 1024, 60 },
{ OT_VO_OUT_1366x768_60, 1366, 768, 60 },
{ OT_VO_OUT_1400x1050_60, 1400, 1050, 60 },
{ OT_VO_OUT_1440x900_60, 1440, 900, 60 },
{ OT_VO_OUT_1680x1050_60, 1680, 1050, 60 },
{ OT_VO_OUT_1080P24, 1920, 1080, 24 },
{ OT_VO_OUT_1080P25, 1920, 1080, 25 },
{ OT_VO_OUT_1080P30, 1920, 1080, 30 },
{ OT_VO_OUT_1080I50, 1920, 1080, 25 },
{ OT_VO_OUT_1080I60, 1920, 1080, 30 },
{ OT_VO_OUT_1080P50, 1920, 1080, 50 },
{ OT_VO_OUT_1080P60, 1920, 1080, 60 },
{ OT_VO_OUT_1600x1200_60, 1600, 1200, 60 },
{ OT_VO_OUT_1920x1200_60, 1920, 1200, 60 },
{ OT_VO_OUT_1920x2160_30, 1920, 2160, 30 },
{ OT_VO_OUT_2560x1440_30, 2560, 1440, 30 },
{ OT_VO_OUT_2560x1440_60, 2560, 1440, 60 },
{ OT_VO_OUT_2560x1600_60, 2560, 1600, 60 },
{ OT_VO_OUT_3840x2160_24, 3840, 2160, 24 },
{ OT_VO_OUT_3840x2160_25, 3840, 2160, 25 },
{ OT_VO_OUT_3840x2160_30, 3840, 2160, 30 },
{ OT_VO_OUT_3840x2160_50, 3840, 2160, 50 },
{ OT_VO_OUT_3840x2160_60, 3840, 2160, 60 },
{ OT_VO_OUT_4096x2160_24, 4096, 2160, 24 },
{ OT_VO_OUT_4096x2160_25, 4096, 2160, 25 },
{ OT_VO_OUT_4096x2160_30, 4096, 2160, 30 },
{ OT_VO_OUT_4096x2160_50, 4096, 2160, 50 },
{ OT_VO_OUT_4096x2160_60, 4096, 2160, 60 },
{ OT_VO_OUT_7680x4320_30, 7680, 4320, 30 },
{ OT_VO_OUT_240x320_50, 240, 320, 50 },
{ OT_VO_OUT_320x240_50, 320, 240, 50 },
{ OT_VO_OUT_240x320_60, 240, 320, 60 },
{ OT_VO_OUT_320x240_60, 320, 240, 60 },
{ OT_VO_OUT_800x600_50, 800, 600, 50 },
{ OT_VO_OUT_720x1280_60, 720, 1280, 60 },
{ OT_VO_OUT_1080x1920_60, 1080, 1920, 60 },
{ OT_VO_OUT_USER, 0, 0, 0 }
};
td_s32 sample_comm_vo_get_width_height(ot_vo_intf_sync intf_sync, td_u32 *width, td_u32 *height, td_u32 *frame_rate)
{
check_null_ptr_return(width);
check_null_ptr_return(height);
check_null_ptr_return(frame_rate);
if (intf_sync > OT_VO_OUT_USER) {
sample_print("vo intf_sync %d not support!\n", intf_sync);
return TD_FAILURE;
}
*width = g_vo_sample_sync_info[intf_sync].width;
*height = g_vo_sample_sync_info[intf_sync].height;
*frame_rate = g_vo_sample_sync_info[intf_sync].frame_rate;
return TD_SUCCESS;
}
td_s32 sample_comm_vo_start_dev(ot_vo_dev vo_dev, ot_vo_pub_attr *pub_attr)
{
td_s32 ret;
check_null_ptr_return(pub_attr);
ret = ss_mpi_vo_set_pub_attr(vo_dev, pub_attr);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
ret = ss_mpi_vo_enable(vo_dev);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 sample_comm_vo_stop_dev(ot_vo_dev vo_dev)
{
td_s32 ret;
ret = ss_mpi_vo_disable(vo_dev);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 sample_comm_vo_start_layer(ot_vo_layer vo_layer, const ot_vo_video_layer_attr *layer_attr)
{
td_s32 ret;
check_null_ptr_return(layer_attr);
ret = ss_mpi_vo_set_video_layer_attr(vo_layer, layer_attr);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
ret = ss_mpi_vo_enable_video_layer(vo_layer);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 sample_comm_vo_stop_layer(ot_vo_layer vo_layer)
{
td_s32 ret;
ret = ss_mpi_vo_disable_video_layer(vo_layer);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
static sample_vo_wnd_info g_vo_sample_wnd_info[VO_MODE_BUTT] = {
{ VO_MODE_1MUX, 1, 1, 0, 0 },
{ VO_MODE_2MUX, 2, 2, 0, 0 },
{ VO_MODE_4MUX, 4, 2, 0, 0 },
{ VO_MODE_8MUX, 8, 3, 0, 0 },
{ VO_MODE_9MUX, 9, 3, 0, 0 },
{ VO_MODE_16MUX, 16, 4, 0, 0 },
{ VO_MODE_25MUX, 25, 5, 0, 0 },
{ VO_MODE_36MUX, 36, 6, 0, 0 },
{ VO_MODE_49MUX, 49, 7, 0, 0 },
{ VO_MODE_64MUX, 64, 8, 0, 0 },
{ VO_MODE_2X4, 8, 4, 4, 2 }
};
td_s32 sample_comm_vo_get_wnd_info(sample_vo_mode mode, sample_vo_wnd_info *wnd_info)
{
check_null_ptr_return(wnd_info);
if (mode >= VO_MODE_BUTT) {
sample_print("vo mode %d not support!\n", mode);
return TD_FAILURE;
}
wnd_info->mode = mode;
wnd_info->wnd_num = g_vo_sample_wnd_info[mode].wnd_num;
wnd_info->square = g_vo_sample_wnd_info[mode].square;
wnd_info->row = g_vo_sample_wnd_info[mode].row;
wnd_info->col = g_vo_sample_wnd_info[mode].col;
return TD_SUCCESS;
}
////////////////////////
void sample_vo_chn_switch(int value){
#if 0 //3 lu
vo_chn_switch(1,0,1);
vo_chn_switch(0,0,1);
vo_chn_switch(2,0,1);
if(value== 0){
vo_chn_switch(0,1,0);
}else if(value ==1 ){
vo_chn_switch(0,0,1);
vo_chn_switch(1,1,0);
}else if(value == 2){
vo_chn_switch(1,0,1);
vo_chn_switch(2,1,0);
}else if(value == 3){
vo_chn_switch(2,0,1);
}
#endif
#if 0
vo_chn_switch(0,0,1);
vo_chn_switch(1,0,1);
vo_chn_switch(2,0,1);
vo_chn_switch(3,0,1);
vo_chn_switch(4,0,1);
#endif
#if 0
if(value== 1){
vo_chn_switch(0,1,0);
}else if(value ==2 ){
vo_chn_switch(1,2,0);
vo_chn_switch(0,0,1);
//vo_chn_switch(0,0,1);
//vo_chn_switch(1,1,0);
}else if(value == 3){
vo_chn_switch(2,3,0);
vo_chn_switch(1,0,1);
//vo_chn_switch(2,1,0);
}else if(value == 4){
vo_chn_switch(3,4,0);
vo_chn_switch(2,0,1);
}else if(value == 5){
vo_chn_switch(3,0,1);
//vo_chn_switch(4,0,1); //5lu
//vo_chn_switch(5,0,1); //6lu
//vo_chn_switch(0,0,1);
//vo_chn_switch(1,0,1);
//vo_chn_switch(2,0,1);
}
#endif
#if 0 //5lu
if(value== 1){
//vo_chn_switch(1,0,1);
//vo_chn_switch(2,0,1);
//vo_chn_switch(3,0,1);
//vo_chn_switch(4,0,1);
vo_chn_switch(0,2,0);
}else if(value ==2 ){
vo_chn_switch(1,2,0);
vo_chn_switch(0,0,1);
//vo_chn_switch(0,0,1);
//vo_chn_switch(1,1,0);
}else if(value == 3){
vo_chn_switch(3,4,0);
vo_chn_switch(1,0,1);
//vo_chn_switch(2,1,0);
}else if(value == 4){
vo_chn_switch(3,0,0);
vo_chn_switch(2,3,0);
//vo_chn_switch(2,0,1);
}else if(value == 5){
vo_chn_switch(4,5,0);
vo_chn_switch(3,0,1);
//vo_chn_switch(2,3,0);
//vo_chn_switch(3,0,1);
}else if(value == 6){
//vo_chn_switch(5,0,1);
vo_chn_switch(4,0,1);
vo_chn_switch(3,1,1); //6lu
vo_chn_switch(0,1,1);
vo_chn_switch(1,1,1);
vo_chn_switch(2,1,1);
}
else if(value == 7){
// vo_chn_switch(5,0,1);
vo_chn_switch(0,1,1);
vo_chn_switch(1,1,1);
vo_chn_switch(2,0,1);
vo_chn_switch(4,1,1); //5lu
vo_chn_switch(3,1,1); //6lu
}
#endif
#if 1
switch (value) {
case 0: /* 布局一 双屏:视频1(左) + 视频2(右),各 960x720 */
vo_chn_switch(0, 1, 1);
vo_chn_switch(1, 1, 1);
break;
case 1: /* 布局一 视频1 全屏 1920x1200,视频2 隐藏 */
vo_chn_switch(0, 2, 0);
vo_chn_switch(1, 0, 1);
break;
case 2: /* 布局一 视频2 全屏 1920x1200,视频1 隐藏 */
vo_chn_switch(1, 2, 0);
vo_chn_switch(0, 0, 1);
break;
case 3: /* 布局二 视频1 右上角 1280x720 */
vo_chn_switch(0, 2, 2); // 视频1(chn0) 右上角
vo_chn_switch(1, 0, 1); // 视频2(chn1) 隐藏
break;
case 4: /* 布局二 视频2 右上角 1280x720 */
vo_chn_switch(1, 2, 2); // 视频2(chn1) 右上角
vo_chn_switch(0, 0, 1); // 视频1(chn0) 隐藏
break;
default:
break;
}
#endif
}
void vo_chn_switch(int vo_channel , int priority, int mux ){
int ret;
int vo_layer = 0;
ot_vo_chn_attr chn_attr;
#if 0
int width = 1920;
int height = 1200;
//ret = ss_mpi_vo_disable_chn(vo_layer, vo_channel);
//if (ret != TD_SUCCESS) {
// sample_print("failed with %#x!\n", ret);
// return TD_FAILURE;
//}
ret = ss_mpi_vo_get_chn_attr(vo_layer, vo_channel ,&chn_attr);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
if(mux){
#if 1 // 3lu
if (vo_channel==0){
chn_attr.rect.x = 0;
chn_attr.rect.y = 0;
chn_attr.rect.width = 960;
chn_attr.rect.height = 600;
}
else if (vo_channel==1){
chn_attr.rect.x = 960;
chn_attr.rect.y = 0;
chn_attr.rect.width = 960;
chn_attr.rect.height = 600;
}
else if (vo_channel==2){
chn_attr.rect.x = 0;
chn_attr.rect.y = 600;
chn_attr.rect.width = 960;
chn_attr.rect.height = 600;
}
else if (vo_channel==3){
chn_attr.rect.x = 960;
chn_attr.rect.y = 600;
chn_attr.rect.width = 960;
chn_attr.rect.height = 600;
}else if(vo_channel==4){
chn_attr.rect.x = 0;
chn_attr.rect.y = 600;
chn_attr.rect.width = 960;
chn_attr.rect.height = 600;
}
#endif
#if 0 // 6lu
if (vo_channel==0){
chn_attr.rect.x = 0;
chn_attr.rect.y = 0;
chn_attr.rect.width = 640;
chn_attr.rect.height = 600;
}
else if (vo_channel==1){
chn_attr.rect.x = 0;
chn_attr.rect.y = 600;
chn_attr.rect.width = 640;
chn_attr.rect.height = 600;
}
else if (vo_channel==2){
chn_attr.rect.x = 640;
chn_attr.rect.y = 0;
chn_attr.rect.width = 640;
chn_attr.rect.height = 600;
}else if (vo_channel==3){
chn_attr.rect.x = 640;
chn_attr.rect.y = 600;
chn_attr.rect.width = 640;
chn_attr.rect.height = 600;
}else if (vo_channel==4){
chn_attr.rect.x = 1280;
chn_attr.rect.y = 0;
chn_attr.rect.width = 640;
chn_attr.rect.height = 600;
}else if (vo_channel==5){
chn_attr.rect.x = 1280;
chn_attr.rect.y = 600;
chn_attr.rect.width = 640;
chn_attr.rect.height = 600;
}
#endif
#if 0 //4lu
chn_attr.rect.x = OT_ALIGN_DOWN((width / 2) * (vo_channel % 2), 2); /* 2: 2 aligin */
chn_attr.rect.y = OT_ALIGN_DOWN((height / 2) * (vo_channel / 2), 2); /* 2: 2 aligin */
chn_attr.rect.width = OT_ALIGN_DOWN(width / 2, 2); /* 2: 2 aligin */
chn_attr.rect.height = OT_ALIGN_DOWN(height / 2, 2);
#endif
if(mux==2){
if (vo_channel==2){
chn_attr.rect.x = 0;
chn_attr.rect.y = 0;
chn_attr.rect.width = 200;
chn_attr.rect.height = 300;
}
if (vo_channel==4){
chn_attr.rect.x = 0;
chn_attr.rect.y = 0;
chn_attr.rect.width = 200;
chn_attr.rect.height = 300;
}
}
chn_attr.priority = priority;
}else{
chn_attr.rect.x = 0;
chn_attr.rect.y = 0;
chn_attr.rect.width=1920;
chn_attr.rect.height=1080;//1200;
chn_attr.priority = priority;
}
ret = ss_mpi_vo_set_chn_attr(vo_layer, vo_channel, &chn_attr);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
// ret = ss_mpi_vo_enable_chn(vo_layer, vo_channel);
// if (ret != TD_SUCCESS) {
// sample_print("failed with %#x!\n", ret);
// return TD_FAILURE;
// }
}
#endif
ret = ss_mpi_vo_get_chn_attr(vo_layer, vo_channel, &chn_attr);
if (ret != TD_SUCCESS) {
sample_print("get vo chn attr failed %#x!\n", ret);
return;
}
if (mux == 1) {
/* 双屏窗口 960x720:chn0 在左,chn1 在右 */
chn_attr.rect.x = (vo_channel == 0) ? 0 : 960;
chn_attr.rect.y = 0;
chn_attr.rect.width = 960;
chn_attr.rect.height = 720;
} else if (mux == 0) {
/* 全屏 1920x1200 */
chn_attr.rect.x = 0;
chn_attr.rect.y = 0;
chn_attr.rect.width = 1920;
chn_attr.rect.height = 1200;
} else if (mux == 2) {
/* 右上角 1280x720 */
chn_attr.rect.x = 640; /* 1920 - 1280 */
chn_attr.rect.y = 0;
chn_attr.rect.width = 1280;
chn_attr.rect.height = 720;
}
chn_attr.priority = priority;
ret = ss_mpi_vo_set_chn_attr(vo_layer, vo_channel, &chn_attr);
if (ret != TD_SUCCESS) {
sample_print("set vo chn attr failed %#x!\n", ret);
return;
}
/* priority>0 才显示;priority==0 保持 disable,即隐藏 */
if (priority > 0) {
ret = ss_mpi_vo_enable_chn(vo_layer, vo_channel);
if (ret != TD_SUCCESS) {
sample_print("enable vo chn failed %#x!\n", ret);
}
}
}
/////////////////////////
td_s32 sample_comm_vo_get_chn_attr(sample_vo_wnd_info *wnd_info, ot_vo_video_layer_attr *layer_attr, td_s32 chn,
ot_vo_chn_attr *chn_attr)
{
td_u32 width;
td_u32 height;
check_null_ptr_return(wnd_info);
check_null_ptr_return(layer_attr);
check_null_ptr_return(chn_attr);
width = layer_attr->img_size.width;
height = layer_attr->img_size.height;
if (wnd_info->mode != VO_MODE_2X4) {
chn_attr->rect.x = OT_ALIGN_DOWN((width / wnd_info->square) * (chn % wnd_info->square), 2); /* 2: 2 aligin */
chn_attr->rect.y = OT_ALIGN_DOWN((height / wnd_info->square) * (chn / wnd_info->square), 2); /* 2: 2 aligin */
chn_attr->rect.width = OT_ALIGN_DOWN(width / wnd_info->square, 2); /* 2: 2 aligin */
chn_attr->rect.height = OT_ALIGN_DOWN(height / wnd_info->square, 2); /* 2: 2 aligin */
} else {
chn_attr->rect.x = OT_ALIGN_DOWN((width / wnd_info->col) * (chn % wnd_info->col), 2); /* 2: 2 aligin */
chn_attr->rect.y = OT_ALIGN_DOWN((height / wnd_info->row) * (chn / wnd_info->col), 2); /* 2: 2 aligin */
chn_attr->rect.width = OT_ALIGN_DOWN(width / wnd_info->col, 2); /* 2: 2 aligin */
chn_attr->rect.height = OT_ALIGN_DOWN(height / wnd_info->row, 2); /* 2: 2 aligin */
}
chn_attr->priority = 0;
chn_attr->deflicker_en = TD_FALSE;
return TD_SUCCESS;
}
td_s32 sample_comm_vo_start_chn(ot_vo_layer vo_layer, sample_vo_mode mode)
{
td_s32 ret;
td_s32 i;
sample_vo_wnd_info wnd_info = { 0 };
ot_vo_chn_attr chn_attr;
ot_vo_video_layer_attr layer_attr;
ret = sample_comm_vo_get_wnd_info(mode, &wnd_info);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return ret;
}
ret = ss_mpi_vo_get_video_layer_attr(vo_layer, &layer_attr);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
for (i = 0; i < (td_s32)wnd_info.wnd_num; i++) {
ret = sample_comm_vo_get_chn_attr(&wnd_info, &layer_attr, i, &chn_attr);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
ret = ss_mpi_vo_set_chn_attr(vo_layer, i, &chn_attr);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
ret = ss_mpi_vo_enable_chn(vo_layer, i);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
}
return TD_SUCCESS;
}
td_s32 sample_comm_vo_stop_chn(ot_vo_layer vo_layer, sample_vo_mode mode)
{
td_s32 ret;
td_s32 i;
sample_vo_wnd_info wnd_info = { 0 };
ret = sample_comm_vo_get_wnd_info(mode, &wnd_info);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return ret;
}
for (i = 0; i < (td_s32)wnd_info.wnd_num; i++) {
ret = ss_mpi_vo_disable_chn(vo_layer, i);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
}
return ret;
}
static td_void sample_private_vo_get_def_wbc_attr(ot_vo_wbc_attr *wbc_attr, ot_vo_wbc_src *source)
{
wbc_attr->target_size.width = FHD_WIDTH;
wbc_attr->target_size.height = FHD_HEIGHT;
wbc_attr->pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
wbc_attr->frame_rate = 30; /* 30: 30fps */
wbc_attr->compress_mode = OT_COMPRESS_MODE_NONE;
wbc_attr->dynamic_range = OT_DYNAMIC_RANGE_SDR8;
source->src_type = OT_VO_WBC_SRC_DEV;
source->src_id = SAMPLE_VO_DEV_DHD0;
}
static td_s32 sample_private_vo_start_wbc(ot_vo_wbc vo_wbc, ot_vo_wbc_attr *wbc_attr, ot_vo_wbc_src *source)
{
td_s32 ret;
ret = ss_mpi_vo_set_wbc_src(vo_wbc, source);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
ret = ss_mpi_vo_set_wbc_attr(vo_wbc, wbc_attr);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
ret = ss_mpi_vo_enable_wbc(vo_wbc);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_s32 sample_private_vo_stop_wbc(ot_vo_wbc vo_wbc)
{
td_s32 ret;
ret = ss_mpi_vo_disable_wbc(vo_wbc);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 sample_comm_vo_start_wbc(sample_vo_wbc_cfg *wbc_config)
{
td_s32 ret;
check_null_ptr_return(wbc_config);
/* set dynaminc range if changed */
if ((td_s32)wbc_config->dynamic_range != -1) {
wbc_config->wbc_attr.dynamic_range = wbc_config->dynamic_range;
}
/* set compress mode if changed */
if ((td_s32)wbc_config->compress_mode != -1) {
wbc_config->wbc_attr.compress_mode = wbc_config->compress_mode;
}
if (wbc_config->depth > -1) {
ret = ss_mpi_vo_set_wbc_depth(wbc_config->vo_wbc, 5); /* 5: wbc depth */
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return ret;
}
}
wbc_config->wbc_source.src_type = wbc_config->source_type;
ret = sample_private_vo_start_wbc(wbc_config->vo_wbc, &wbc_config->wbc_attr, &wbc_config->wbc_source);
return ret;
}
td_s32 sample_comm_vo_stop_wbc(sample_vo_wbc_cfg *wbc_config)
{
check_null_ptr_return(wbc_config);
return sample_private_vo_stop_wbc(wbc_config->vo_wbc);
}
td_s32 sample_comm_vo_get_def_wbc_config(sample_vo_wbc_cfg *wbc_config)
{
check_null_ptr_return(wbc_config);
wbc_config->vo_wbc = 0;
wbc_config->source_type = OT_VO_WBC_SRC_DEV;
wbc_config->wbc_source.src_type = OT_VO_WBC_SRC_DEV;
wbc_config->wbc_source.src_id = 0;
wbc_config->dynamic_range = OT_DYNAMIC_RANGE_BUTT;
wbc_config->compress_mode = OT_COMPRESS_MODE_BUTT;
wbc_config->depth = OT_INVALID_VALUE;
sample_private_vo_get_def_wbc_attr(&wbc_config->wbc_attr, &wbc_config->wbc_source);
return TD_SUCCESS;
}
#if VO_LT8618SX
static td_s32 g_vo_lt8618sx_fd = OT_INVALID_VALUE;
td_s32 sample_comm_vo_bt1120_start(ot_vo_dev vo_dev, ot_vo_pub_attr *pub_attr)
{
td_s32 ret;
td_u32 lt_mode, clk_edge;
ot_vo_bt_param bt_param = {0};
check_null_ptr_return(pub_attr);
lt_mode = pub_attr->intf_sync;
if (!(pub_attr->intf_type & OT_VO_INTF_BT1120)) {
return TD_FAILURE;
}
ret = ss_mpi_vo_get_bt_param(vo_dev, &bt_param);
if (ret != TD_SUCCESS) {
sample_print("failed with %#x!\n", ret);
return TD_FAILURE;
}
g_vo_lt8618sx_fd = open(LT8618SX_DEV_NAME, O_RDONLY);
if (g_vo_lt8618sx_fd < 0) {
sample_print("open file (%s) fail!\n", LT8618SX_DEV_NAME);
return TD_FAILURE;
}
/* 0:single, 1:dual, set the clk edge firstly */
clk_edge = (td_u32)bt_param.clk_edge;
if (ioctl(g_vo_lt8618sx_fd, LT_CMD_SETCLK, &clk_edge) < 0) {
sample_print("ioctl (%s) set clk fail!\n", LT8618SX_DEV_NAME);
}
if (ioctl(g_vo_lt8618sx_fd, LT_CMD_SETMODE, &lt_mode) < 0) {
sample_print("ioctl (%s) set mode fail!\n", LT8618SX_DEV_NAME);
}
close(g_vo_lt8618sx_fd);
g_vo_lt8618sx_fd = OT_INVALID_VALUE;
return TD_SUCCESS;
}
#else
td_s32 sample_comm_vo_bt1120_start(ot_vo_dev vo_dev, ot_vo_pub_attr *pub_attr)
{
ot_unused(vo_dev);
ot_unused(pub_attr);
return TD_SUCCESS;
}
#endif
static const ot_hdmi_video_format g_vo_hdmi_sync[OT_VO_OUT_BUTT] = {
OT_HDMI_VIDEO_FORMAT_PAL,
OT_HDMI_VIDEO_FORMAT_NTSC,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
OT_HDMI_VIDEO_FORMAT_861D_640X480_60,
OT_HDMI_VIDEO_FORMAT_480P_60,
OT_HDMI_VIDEO_FORMAT_576P_50,
OT_HDMI_VIDEO_FORMAT_VESA_800X600_60,
OT_HDMI_VIDEO_FORMAT_VESA_1024X768_60,
OT_HDMI_VIDEO_FORMAT_720P_50,
OT_HDMI_VIDEO_FORMAT_720P_60,
OT_HDMI_VIDEO_FORMAT_VESA_1280X800_60,
OT_HDMI_VIDEO_FORMAT_VESA_1280X1024_60,
OT_HDMI_VIDEO_FORMAT_VESA_1366X768_60,
OT_HDMI_VIDEO_FORMAT_VESA_1400X1050_60,
OT_HDMI_VIDEO_FORMAT_VESA_1440X900_60,
OT_HDMI_VIDEO_FORMAT_VESA_1680X1050_60,
OT_HDMI_VIDEO_FORMAT_1080P_24,
OT_HDMI_VIDEO_FORMAT_1080P_25,
OT_HDMI_VIDEO_FORMAT_1080P_30,
OT_HDMI_VIDEO_FORMAT_1080i_50,
OT_HDMI_VIDEO_FORMAT_1080i_60,
OT_HDMI_VIDEO_FORMAT_1080P_50,
OT_HDMI_VIDEO_FORMAT_1080P_60,
OT_HDMI_VIDEO_FORMAT_VESA_1600X1200_60,
OT_HDMI_VIDEO_FORMAT_VESA_1920X1200_60,
OT_HDMI_VIDEO_FORMAT_1920x2160_30,
OT_HDMI_VIDEO_FORMAT_2560x1440_30,
OT_HDMI_VIDEO_FORMAT_2560x1440_60,
OT_HDMI_VIDEO_FORMAT_2560x1600_60,
OT_HDMI_VIDEO_FORMAT_3840X2160P_24,
OT_HDMI_VIDEO_FORMAT_3840X2160P_25,
OT_HDMI_VIDEO_FORMAT_3840X2160P_30,
OT_HDMI_VIDEO_FORMAT_3840X2160P_50,
OT_HDMI_VIDEO_FORMAT_3840X2160P_60,
OT_HDMI_VIDEO_FORMAT_4096X2160P_24,
OT_HDMI_VIDEO_FORMAT_4096X2160P_25,
OT_HDMI_VIDEO_FORMAT_4096X2160P_30,
OT_HDMI_VIDEO_FORMAT_4096X2160P_50,
OT_HDMI_VIDEO_FORMAT_4096X2160P_60,
OT_HDMI_VIDEO_FORMAT_7680X4320P_30,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE,
};
static td_void sample_comm_vo_hdmi_convert_sync(ot_vo_intf_sync intf_sync, ot_hdmi_video_format *video_fmt)
{
*video_fmt = OT_HDMI_VIDEO_FORMAT_1080P_60;
if ((intf_sync >= OT_VO_OUT_PAL) && (intf_sync < OT_VO_OUT_BUTT)) {
*video_fmt = g_vo_hdmi_sync[intf_sync];
}
}
td_s32 sample_comm_vo_hdmi_start(ot_vo_intf_sync intf_sync)
{
ot_hdmi_attr attr;
ot_hdmi_video_format video_fmt;
ot_hdmi_id hdmi_id = OT_HDMI_ID_0;
sample_comm_vo_hdmi_convert_sync(intf_sync, &video_fmt);
check_return(ss_mpi_hdmi_init(), "ss_mpi_hdmi_init");
check_return(ss_mpi_hdmi_open(hdmi_id), "ss_mpi_hdmi_open");
check_return(ss_mpi_hdmi_get_attr(hdmi_id, &attr), "ss_mpi_hdmi_get_attr");
attr.video_format = video_fmt;
check_return(ss_mpi_hdmi_set_attr(hdmi_id, &attr), "ss_mpi_hdmi_set_attr");
check_return(ss_mpi_hdmi_start(hdmi_id), "ss_mpi_hdmi_start");
return TD_SUCCESS;
}
td_s32 sample_comm_vo_hdmi_stop(td_void)
{
ot_hdmi_id hdmi_id = OT_HDMI_ID_0;
check_return(ss_mpi_hdmi_stop(hdmi_id), "ss_mpi_hdmi_stop");
check_return(ss_mpi_hdmi_close(hdmi_id), "ss_mpi_hdmi_close");
check_return(ss_mpi_hdmi_deinit(), "ss_mpi_hdmi_deinit");
return TD_SUCCESS;
}
td_s32 sample_comm_vo_get_def_config(sample_vo_cfg *vo_config)
{
ot_rect def_disp_rect = { 0, 0, 1920, 1080 };
ot_size def_img_size = { 1920, 1080 };
check_null_ptr_return(vo_config);
vo_config->vo_dev = SAMPLE_VO_DEV_UHD;
vo_config->vo_intf_type = OT_VO_INTF_HDMI;
vo_config->intf_sync = OT_VO_OUT_1080P60;
vo_config->bg_color = COLOR_RGB_BLACK;
vo_config->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
vo_config->disp_rect = def_disp_rect;
vo_config->image_size = def_img_size;
vo_config->vo_part_mode = OT_VO_PARTITION_MODE_SINGLE;
vo_config->dis_buf_len = 3; /* 3: def buf len for single */
vo_config->dst_dynamic_range = OT_DYNAMIC_RANGE_SDR8;
vo_config->vo_mode = VO_MODE_1MUX;
vo_config->compress_mode = OT_COMPRESS_MODE_NONE;
return TD_SUCCESS;
}
static td_s32 sample_comm_vo_get_vo_layer_attr(sample_vo_cfg *vo_config, ot_vo_video_layer_attr *layer_attr)
{
td_s32 ret;
ot_rect def_disp_rect = { 0, 0, 1920, 1080 };
ot_size def_img_size = { 1920, 1080 };
check_null_ptr_return(vo_config);
check_null_ptr_return(layer_attr);
ret = sample_comm_vo_get_width_height(vo_config->intf_sync, &layer_attr->display_rect.width,
&layer_attr->display_rect.height, &layer_attr->display_frame_rate);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_get_width_height failed!\n");
return ret;
}
layer_attr->cluster_mode_en = TD_FALSE;
layer_attr->double_frame_en = TD_FALSE;
layer_attr->pixel_format = vo_config->pix_format;
layer_attr->display_rect.x = 0;
layer_attr->display_rect.y = 0;
/* set display rectangle if changed. */
if (memcmp(&vo_config->disp_rect, &def_disp_rect, sizeof(ot_rect)) != 0) {
layer_attr->display_rect.width = vo_config->disp_rect.width;
layer_attr->display_rect.height = vo_config->disp_rect.height;
}
layer_attr->img_size.width = layer_attr->display_rect.width;
layer_attr->img_size.height = layer_attr->display_rect.height;
/* set image size if changed. */
if (memcmp(&vo_config->image_size, &def_img_size, sizeof(ot_size)) != 0) {
layer_attr->img_size.width = vo_config->image_size.width;
layer_attr->img_size.height = vo_config->image_size.height;
}
layer_attr->dst_dynamic_range = vo_config->dst_dynamic_range;
layer_attr->display_buf_len = vo_config->dis_buf_len;
layer_attr->partition_mode = vo_config->vo_part_mode;
layer_attr->compress_mode = vo_config->compress_mode;
return TD_SUCCESS;
}
static td_void sample_comm_vo_set_intf_param(sample_vo_cfg *vo_config)
{
ot_vo_hdmi_param hdmi_param = { 0 };
/* set interface param */
if (g_vo_hdmi_rgb_mode == TD_TRUE) {
ss_mpi_vo_get_hdmi_param(vo_config->vo_dev, &hdmi_param);
hdmi_param.csc.csc_matrix = OT_VO_CSC_MATRIX_BT709FULL_TO_RGBFULL;
ss_mpi_vo_set_hdmi_param(vo_config->vo_dev, &hdmi_param);
}
}
td_void sample_comm_vo_set_hdmi_rgb_mode(td_bool enable)
{
g_vo_hdmi_rgb_mode = !!enable;
}
td_s32 sample_comm_vo_start_vo(sample_vo_cfg *vo_config)
{
/* VO device vo_dev# information declaration. */
td_s32 ret;
ot_vo_dev vo_dev;
ot_vo_layer vo_layer;
ot_vo_pub_attr vo_pub_attr = { 0 };
ot_vo_video_layer_attr layer_attr = { 0 };
check_null_ptr_return(vo_config);
vo_dev = vo_config->vo_dev;
vo_layer = vo_config->vo_dev;
/* set and start VO device vo_dev#. */
vo_pub_attr.intf_type = vo_config->vo_intf_type;
vo_pub_attr.intf_sync = vo_config->intf_sync;
vo_pub_attr.bg_color = vo_config->bg_color;
ret = sample_comm_vo_start_dev(vo_dev, &vo_pub_attr);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_start_dev failed!\n");
return ret;
}
ret = sample_comm_vo_get_vo_layer_attr(vo_config, &layer_attr);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_start get video layer failed!\n");
(td_void)sample_comm_vo_stop_dev(vo_dev);
return ret;
}
ret = sample_comm_vo_start_layer(vo_layer, &layer_attr);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_start set video layer failed!\n");
(td_void)sample_comm_vo_stop_dev(vo_dev);
return ret;
}
/* set interface param */
sample_comm_vo_set_intf_param(vo_config);
/* start vo channels. */
ret = sample_comm_vo_start_chn(vo_layer, vo_config->vo_mode);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_start_chn failed!\n");
(td_void)sample_comm_vo_stop_layer(vo_layer);
(td_void)sample_comm_vo_stop_dev(vo_dev);
return ret;
}
/* start hdmi device. note : do this after vo device started. */
if (vo_config->vo_intf_type & OT_VO_INTF_HDMI) {
(td_void)sample_comm_vo_hdmi_start(vo_config->intf_sync);
}
/* start bt1120 device. note : do this after vo device started. */
if (vo_config->vo_intf_type & OT_VO_INTF_BT1120) {
(td_void)sample_comm_vo_bt1120_start(vo_dev, &vo_pub_attr);
}
return TD_SUCCESS;
}
td_s32 sample_comm_vo_start_pip(sample_vo_cfg *vo_config)
{
/* VO device vo_dev# information declaration. */
ot_vo_dev vo_dev;
ot_vo_layer vo_layer;
ot_vo_pub_attr vo_pub_attr = { 0 };
ot_vo_video_layer_attr layer_attr = { 0 };
td_s32 ret;
check_null_ptr_return(vo_config);
vo_dev = vo_config->vo_dev;
vo_layer = SAMPLE_VO_LAYER_PIP;
vo_pub_attr.intf_sync = vo_config->intf_sync;
/* set and start layer vo_dev#. */
ret = sample_comm_vo_get_width_height(vo_pub_attr.intf_sync, &layer_attr.display_rect.width,
&layer_attr.display_rect.height, &layer_attr.display_frame_rate);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_get_width_height failed!\n");
(td_void)sample_comm_vo_stop_dev(vo_dev);
return ret;
}
layer_attr.cluster_mode_en = TD_FALSE;
layer_attr.double_frame_en = TD_FALSE;
layer_attr.pixel_format = vo_config->pix_format;
layer_attr.display_rect.x = 0;
layer_attr.display_rect.y = 0;
/* set display rectangle if changed. */
layer_attr.display_rect.width /= 2; /* 2: 2x */
layer_attr.display_rect.height /= 2; /* 2: 2x */
layer_attr.img_size.width = layer_attr.display_rect.width;
layer_attr.img_size.height = layer_attr.display_rect.height;
/* set image size if changed. */
layer_attr.dst_dynamic_range = vo_config->dst_dynamic_range;
layer_attr.display_buf_len = vo_config->dis_buf_len;
layer_attr.partition_mode = vo_config->vo_part_mode;
ret = sample_comm_vo_start_layer(vo_layer, &layer_attr);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_start video layer failed!\n");
(td_void)sample_comm_vo_stop_dev(vo_dev);
return ret;
}
/* start vo channels. */
ret = sample_comm_vo_start_chn(vo_layer, vo_config->vo_mode);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_start_chn failed!\n");
(td_void)sample_comm_vo_stop_layer(vo_layer);
(td_void)sample_comm_vo_stop_dev(vo_dev);
return ret;
}
return TD_SUCCESS;
}
td_s32 sample_comm_vo_stop_vo(const sample_vo_cfg *vo_config)
{
td_s32 ret;
ot_vo_dev vo_dev;
ot_vo_layer vo_layer;
sample_vo_mode vo_mode;
check_null_ptr_return(vo_config);
vo_dev = vo_config->vo_dev;
vo_layer = vo_config->vo_dev;
vo_mode = vo_config->vo_mode;
if (OT_VO_INTF_HDMI & vo_config->vo_intf_type) {
sample_comm_vo_hdmi_stop();
}
ret = sample_comm_vo_stop_chn(vo_layer, vo_mode);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_stop_vo stop chn failed!\n");
return ret;
}
ret = sample_comm_vo_stop_layer(vo_layer);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_stop_vo stop layer failed!\n");
return ret;
}
ret = sample_comm_vo_stop_dev(vo_dev);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_stop_vo stop dev failed!\n");
return ret;
}
return TD_SUCCESS;
}
td_s32 sample_comm_vo_stop_pip(const sample_vo_cfg *vo_config)
{
td_s32 ret;
ot_vo_layer vo_layer;
check_null_ptr_return(vo_config);
vo_layer = SAMPLE_VO_LAYER_PIP;
ret = sample_comm_vo_stop_chn(vo_layer, vo_config->vo_mode);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_stop_pip stop chn failed!\n");
return ret;
}
ret = sample_comm_vo_stop_layer(vo_layer);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_stop_pip stop layer failed!\n");
return ret;
}
return TD_SUCCESS;
}
td_s32 sample_comm_vo_get_def_layer_config(sample_comm_vo_layer_cfg *vo_layer_config)
{
ot_rect def_disp_rect = { 0, 0, 1920, 1080 };
ot_size def_img_size = { 1920, 1080 };
check_null_ptr_return(vo_layer_config);
vo_layer_config->vo_layer = SAMPLE_VO_LAYER_VHD2;
vo_layer_config->intf_sync = OT_VO_OUT_1080P60;
vo_layer_config->display_rect = def_disp_rect;
vo_layer_config->image_size = def_img_size;
vo_layer_config->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
vo_layer_config->dis_buf_len = 3; /* 3: display buf len */
vo_layer_config->vo_mode = VO_MODE_1MUX;
return TD_SUCCESS;
}
static td_s32 sample_comm_vo_get_layer_layer_attr(sample_comm_vo_layer_cfg *vo_layer_config,
ot_vo_video_layer_attr *layer_attr)
{
td_s32 ret;
td_u32 frmt = 0;
td_u32 width = 0;
td_u32 height = 0;
ot_rect def_disp_rect = { 0, 0, 1920, 1080 };
ot_size def_img_size = { 1920, 1080 };
check_null_ptr_return(vo_layer_config);
check_null_ptr_return(layer_attr);
/* start vo layer. */
ret = sample_comm_vo_get_width_height(vo_layer_config->intf_sync, &width, &height, &frmt);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_get_width_height failed!\n");
return TD_FAILURE;
}
layer_attr->display_rect.x = 0;
layer_attr->display_rect.y = 0;
layer_attr->display_rect.width = width;
layer_attr->display_rect.height = height;
layer_attr->display_frame_rate = frmt;
layer_attr->double_frame_en = TD_FALSE;
layer_attr->cluster_mode_en = TD_FALSE;
layer_attr->pixel_format = vo_layer_config->pix_format;
/* set display rectangle if changed. */
if (memcmp(&vo_layer_config->display_rect, &def_disp_rect, sizeof(ot_rect)) != 0) {
layer_attr->display_rect.width = vo_layer_config->display_rect.width;
layer_attr->display_rect.height = vo_layer_config->display_rect.height;
}
layer_attr->img_size.width = layer_attr->display_rect.width;
layer_attr->img_size.height = layer_attr->display_rect.height;
/* set image size if changed. */
if (memcmp(&vo_layer_config->image_size, &def_img_size, sizeof(ot_size)) != 0) {
layer_attr->img_size.width = vo_layer_config->image_size.width;
layer_attr->img_size.height = vo_layer_config->image_size.height;
}
layer_attr->dst_dynamic_range = vo_layer_config->dst_dynamic_range;
layer_attr->display_buf_len = vo_layer_config->dis_buf_len;
return TD_SUCCESS;
}
td_s32 sample_comm_vo_start_layer_chn(sample_comm_vo_layer_cfg *vo_layer_config)
{
td_s32 ret;
ot_vo_layer vo_layer;
ot_vo_video_layer_attr layer_attr = { 0 };
check_null_ptr_return(vo_layer_config);
vo_layer = vo_layer_config->vo_layer;
ret = sample_comm_vo_get_layer_layer_attr(vo_layer_config, &layer_attr);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_start video layer failed!\n");
return ret;
}
ret = sample_comm_vo_start_layer(vo_layer, &layer_attr);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_start video layer failed!\n");
return ret;
}
/* start vo channels. */
ret = sample_comm_vo_start_chn(vo_layer, vo_layer_config->vo_mode);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_start_chn failed!\n");
(td_void)sample_comm_vo_stop_layer(vo_layer);
return ret;
}
return ret;
}
td_s32 sample_comm_vo_stop_layer_chn(sample_comm_vo_layer_cfg *vo_layer_config)
{
td_s32 ret;
ot_vo_layer vo_layer;
check_null_ptr_return(vo_layer_config);
vo_layer = vo_layer_config->vo_layer;
ret = sample_comm_vo_stop_chn(vo_layer, vo_layer_config->vo_mode);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_stop_layer_chn stop chn failed!\n");
return ret;
}
ret = sample_comm_vo_stop_layer(vo_layer);
if (ret != TD_SUCCESS) {
sample_print("sample_comm_vo_stop_layer_chn stop layer failed!\n");
return ret;
}
return TD_SUCCESS;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */