From 641f666a195e6d6f8b35a5fee83d07d30206bbb7 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Thu, 11 Apr 2019 16:16:35 +0800 Subject: [PATCH] vpp: use new interface to increase accuracy of ar calculation [1/2] PD#OTT-2068 Problem: When playing 1280x128 video under normal screen mode, the aspect ratio from decodec is not accurate enough by multipling 0x100. (128x256/1280=25.6). Dropping 0.6 will cause height losing 9 lines. Solution: Using new interface to pass real ar width and height following steps: 1.Set old ar variable to 0x3ff as a trigger flag. 2.set the original ar value into sar_width and sar_height of vframe Verify: verified on franklin Change-Id: I8a794edd968a76f198ee9cb168a7cfb858c858f8 Signed-off-by: Brian Zhu Signed-off-by: Luan Yuan --- drivers/amlogic/media/video_sink/vpp.c | 89 ++++++++++++++++++++++++++------ include/linux/amlogic/media/vfm/vframe.h | 3 ++ 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index de47f7d1..38f8b32 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -596,6 +596,10 @@ static unsigned int custom_ar; MODULE_PARM_DESC(custom_ar, "custom_ar"); module_param(custom_ar, uint, 0664); +static unsigned int force_use_ext_ar; +MODULE_PARM_DESC(force_use_ext_ar, "force_use_ext_ar"); +module_param(force_use_ext_ar, uint, 0664); + /* *test on txlx: *Time_out = (V_out/V_screen_total)/FPS_out; @@ -848,7 +852,7 @@ static int vpp_set_filters_internal( u32 width_out = wid_out; /* vinfo->width; */ u32 height_out = hei_out; /* vinfo->height; */ u32 aspect_ratio_out = - (vinfo->aspect_ratio_den << 8) / vinfo->aspect_ratio_num; + (vinfo->aspect_ratio_den << 10) / vinfo->aspect_ratio_num; bool fill_match = true; u32 orig_aspect = 0; u32 screen_aspect = 0; @@ -869,6 +873,8 @@ static int vpp_set_filters_internal( u32 vert_chroma_filter; struct filter_info_s *cur_filter; s32 vpp_zoom_center_x, vpp_zoom_center_y; + u32 sar_width = 0, sar_height = 0; + bool ext_sar = false; if (!input) return VppFilter_Fail; @@ -939,11 +945,36 @@ static int vpp_set_filters_internal( else vskip_step = 1; + if (super_debug) + pr_info("sar_width=%d, sar_height = %d, %d\n", + vf->sar_width, vf->sar_height, + force_use_ext_ar); + RESTART: aspect_factor = (vpp_flags & VPP_FLAG_AR_MASK) >> VPP_FLAG_AR_BITS; /* don't use input->wide_mode */ wide_mode = vpp_flags & VPP_FLAG_WIDEMODE_MASK; + if ((vpp_flags & VPP_FLAG_AR_MASK) == VPP_FLAG_AR_MASK) { + ext_sar = true; + sar_width = vf->sar_width; + sar_height = vf->sar_height; + } else if (force_use_ext_ar) { + ext_sar = true; + sar_width = 1; + sar_height = 1; + } + + if (ext_sar && sar_width && sar_height) { + aspect_factor = + div_u64((u64)256ULL * + (u64)sar_height * + (u64)height_in, + (u32)(sar_width * width_in)); + } else { + ext_sar = false; + } + /* keep 8 bits resolution for aspect conversion */ if (wide_mode == VIDEO_WIDEOPTION_4_3) { if (vpp_flags & VPP_FLAG_PORTRAIT_MODE) @@ -951,12 +982,14 @@ RESTART: else aspect_factor = 0xc0; wide_mode = VIDEO_WIDEOPTION_NORMAL; + ext_sar = false; } else if (wide_mode == VIDEO_WIDEOPTION_16_9) { if (vpp_flags & VPP_FLAG_PORTRAIT_MODE) aspect_factor = 0x1c7; else aspect_factor = 0x90; wide_mode = VIDEO_WIDEOPTION_NORMAL; + ext_sar = false; } else if ((wide_mode >= VIDEO_WIDEOPTION_4_3_IGNORE) && (wide_mode <= VIDEO_WIDEOPTION_4_3_COMBINED)) { if (aspect_factor != 0xc0) @@ -964,6 +997,7 @@ RESTART: orig_aspect = aspect_factor; screen_aspect = 0xc0; + ext_sar = false; } else if ((wide_mode >= VIDEO_WIDEOPTION_16_9_IGNORE) && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED)) { if (aspect_factor != 0x90) @@ -971,35 +1005,60 @@ RESTART: orig_aspect = aspect_factor; screen_aspect = 0x90; + ext_sar = false; } else if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) { - if (cur_custom_ar != 0) + if (cur_custom_ar != 0) { aspect_factor = cur_custom_ar & 0x3ff; + ext_sar = false; + } wide_mode = VIDEO_WIDEOPTION_NORMAL; } else if (wide_mode == VIDEO_WIDEOPTION_AFD) { - if (aspect_factor == 0x90) + if (aspect_factor == 0x90) { wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; - else + ext_sar = false; + } else wide_mode = VIDEO_WIDEOPTION_NORMAL; } + /* if use the mode ar, will disable ext ar */ if (super_debug) pr_info("aspect_factor=%d,%d,%d,%d,%d,%d\n", aspect_factor, w_in, height_out, - width_out, h_in, aspect_ratio_out); + width_out, h_in, aspect_ratio_out >> 2); if ((aspect_factor == 0) + || (aspect_factor == + (VPP_FLAG_AR_MASK >> VPP_FLAG_AR_BITS)) || (wide_mode == VIDEO_WIDEOPTION_FULL_STRETCH) - || (wide_mode == VIDEO_WIDEOPTION_NONLINEAR)) + || (wide_mode == VIDEO_WIDEOPTION_NONLINEAR)) { aspect_factor = 0x100; - else { + height_after_ratio = h_in; + } else if (ext_sar) { + /* avoid the bit length overflow */ + u64 tmp = (u64)((u64)(width_out * width_in) * aspect_ratio_out); + + tmp = tmp >> 2; + height_after_ratio = + div_u64((u64)256ULL * + (u64)w_in * + (u64)height_out * + (u64)sar_height * + (u64)height_in, + (u32)tmp); + height_after_ratio /= sar_height; + aspect_factor = (height_after_ratio << 8) / h_in; + } else { + /* avoid the bit length overflow */ + u64 tmp = (u64)((u64)(width_out * h_in) * aspect_ratio_out); + + tmp = tmp >> 2; aspect_factor = div_u64((unsigned long long)w_in * height_out * - (aspect_factor << 8), - width_out * h_in * aspect_ratio_out); + (aspect_factor << 8), + (u32)tmp); + height_after_ratio = (h_in * aspect_factor) >> 8; } - height_after_ratio = (h_in * aspect_factor) >> 8; - /* *if we have ever set a cropped display area for video layer * (by checking video_layer_width/video_height), then @@ -1035,17 +1094,17 @@ RESTART: && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED) && orig_aspect) { if (vinfo->width && vinfo->height) - aspect_ratio_out = (vinfo->height << 8) / vinfo->width; + aspect_ratio_out = (vinfo->height << 10) / vinfo->width; - if ((video_height << 8) > (video_width * aspect_ratio_out)) { + if ((video_height << 10) > (video_width * aspect_ratio_out)) { u32 real_video_height = - (video_width * aspect_ratio_out) >> 8; + (video_width * aspect_ratio_out) >> 10; video_top += (video_height - real_video_height) >> 1; video_height = real_video_height; } else { u32 real_video_width = - (video_height << 8) / aspect_ratio_out; + (video_height << 10) / aspect_ratio_out; video_left += (video_width - real_video_width) >> 1; video_width = real_video_width; diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 7cc65e1..678a148 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -409,6 +409,9 @@ struct vframe_s { struct vframe_pic_mode_s pic_mode; unsigned long v4l_mem_handle; + + u32 sar_width; + u32 sar_height; } /*vframe_t */; #if 0 -- 2.7.4