From 67ab3256df96eb570f2dbf888e209e8cf156eb3e Mon Sep 17 00:00:00 2001 From: Deepak Kushwah Date: Wed, 16 Nov 2016 16:17:32 +0530 Subject: [PATCH] mm-video-v4l2: vdec: Downscale to the highest connected resolution *Downscale video to the highest resolution of the connected displays. *Don't downscale if video resolution is lower than any of connected display resolutions. *Add provision to override the downscalar width and height using the properties vidc.dec.downscalar_width and vidc.dec.downscalar_height *Enable Downsaclar only if the property vidc.dec.enable.downscalar is set to 1. Change-Id: Iac1eeaf89bd06cf86ec3b0b955f25b1c114067be --- mm-video-v4l2/vidc/vdec/Android.mk | 4 +- mm-video-v4l2/vidc/vdec/inc/omx_vdec.h | 3 +- mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp | 114 +++++++++++++++--- 3 files changed, 101 insertions(+), 20 deletions(-) diff --git a/mm-video-v4l2/vidc/vdec/Android.mk b/mm-video-v4l2/vidc/vdec/Android.mk index ecc78c58..beb9edf6 100644 --- a/mm-video-v4l2/vidc/vdec/Android.mk +++ b/mm-video-v4l2/vidc/vdec/Android.mk @@ -60,6 +60,8 @@ ifeq ($(call is-board-platform-in-list, $(MASTER_SIDE_CP_TARGET_LIST)),true) libmm-vdec-def += -DMASTER_SIDE_CP endif +libmm-vdec-def += -D_QUERY_DISP_RES_ + include $(CLEAR_VARS) # Common Includes @@ -111,7 +113,7 @@ LOCAL_C_INCLUDES += $(libmm-vdec-inc) LOCAL_ADDITIONAL_DEPENDENCIES := $(libmm-vdec-add-dep) LOCAL_PRELINK_MODULE := false -LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils libdl +LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils libdl libqdutils LOCAL_SHARED_LIBRARIES += libqdMetaData diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index a5cbacf4..784bdf7b 100644 --- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010 - 2016, The Linux Foundation. All rights reserved. +Copyright (c) 2010 - 2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -1065,6 +1065,7 @@ class omx_vdec: public qc_omx_component bool is_thulium_v1; bool m_disable_ubwc_mode; bool m_disable_split_mode; + bool m_enable_downscalar; OMX_U32 m_downscalar_width; OMX_U32 m_downscalar_height; int decide_downscalar(); diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp index 44a349ad..842a4f39 100644 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010 - 2016, The Linux Foundation. All rights reserved. +Copyright (c) 2010 - 2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -63,6 +63,10 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef _ANDROID_ #include #undef USE_EGL_IMAGE_GPU + +#ifdef _QUERY_DISP_RES_ +#include "display_config.h" +#endif #endif #ifdef _USE_GLIB_ @@ -155,6 +159,9 @@ extern "C" { #define LUMINANCE_DIV_FACTOR 10000.0 +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) + static OMX_U32 maxSmoothStreamingWidth = 1920; static OMX_U32 maxSmoothStreamingHeight = 1088; @@ -824,6 +831,7 @@ omx_vdec::omx_vdec(): m_error_propogated(false), dynamic_buf_mode = false; out_dynamic_list = NULL; is_down_scalar_enabled = false; + m_enable_downscalar = 0; m_downscalar_width = 0; m_downscalar_height = 0; m_force_down_scalar = 0; @@ -1228,6 +1236,7 @@ int omx_vdec::decide_downscalar() struct v4l2_format fmt; enum color_fmts color_format; OMX_U32 width, height; + OMX_BOOL isPortraitVideo = OMX_FALSE; if (capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC) { rc = disable_downscalar(); @@ -1238,11 +1247,77 @@ int omx_vdec::decide_downscalar() return 0; } - if (!m_downscalar_width || !m_downscalar_height) { + if (!m_enable_downscalar) { DEBUG_PRINT_LOW("%s: downscalar not supported", __func__); return 0; } +#ifdef _QUERY_DISP_RES_ + memset(&fmt, 0x0, sizeof(struct v4l2_format)); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.pixelformat = capture_capability; + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); + if (rc < 0) { + DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__); + return rc; + } + isPortraitVideo = fmt.fmt.pix_mp.width < fmt.fmt.pix_mp.height ? OMX_TRUE : OMX_FALSE; + if (!m_downscalar_width || !m_downscalar_height) { + qdutils::DisplayAttributes dpa = {}, dsa = {}, dva = {}; + int prim_config, ext_config, virt_config; + + prim_config = qdutils::getActiveConfig(qdutils::DISPLAY_PRIMARY); + dpa = qdutils::getDisplayAttributes(prim_config, qdutils::DISPLAY_PRIMARY); + DEBUG_PRINT_HIGH("%s: Primary dpa.xres = %d dpa.yres=%d dpa.xdpi = %f dpa.ydpi = %f ", + __func__, dpa.xres, dpa.yres, dpa.xdpi, dpa.ydpi); + + ext_config = qdutils::getActiveConfig(qdutils::DISPLAY_EXTERNAL); + dsa = qdutils::getDisplayAttributes(ext_config, qdutils::DISPLAY_EXTERNAL); + DEBUG_PRINT_HIGH("%s: HDMI dsa.xres = %d dsa.yres = %d dsa.xdpi = %f dsa.ydpi = %f ", + __func__, dsa.xres, dsa.yres, dsa.xdpi, dsa.ydpi); + + virt_config = qdutils::getActiveConfig(qdutils::DISPLAY_VIRTUAL); + dva = qdutils::getDisplayAttributes(virt_config, qdutils::DISPLAY_VIRTUAL); + DEBUG_PRINT_HIGH("%s: Virtual dva.xres = %d dva.yres = %d dva.xdpi = %f dva.ydpi = %f ", + __func__, dva.xres, dva.yres, dva.xdpi, dva.ydpi); + + /* Below logic takes care of following conditions: + * 1. Choose display resolution as maximum resolution of all the connected + * displays (secondary, primary, virtual), so that we do not downscale + * unnecessarily which might be supported on one of the display losing quality. + * 2. Displays connected might be in landscape or portrait mode, so the xres might + * be smaller or greater than the yres. So we first take the max of the two + * in width and min of two in height and then rotate it if below point is true. + * 3. Video might also be in portrait mode, so invert the downscalar width and + * height for such cases. + */ + if (dsa.xres * dsa.yres > dpa.xres * dpa.yres) { + m_downscalar_width = MAX(dsa.xres, dsa.yres); + m_downscalar_height = MIN(dsa.xres, dsa.yres); + } else if (dva.xres * dva.yres > dpa.xres * dpa.yres) { + m_downscalar_width = MAX(dva.xres, dva.yres); + m_downscalar_height = MIN(dva.xres, dva.yres); + + } else { + m_downscalar_width = MAX(dpa.xres, dpa.yres); + m_downscalar_height = MIN(dpa.xres, dpa.yres); + } + if (isPortraitVideo) { + // Swap width and height + m_downscalar_width = m_downscalar_width ^ m_downscalar_height; + m_downscalar_height = m_downscalar_width ^ m_downscalar_height; + m_downscalar_width = m_downscalar_width ^ m_downscalar_height; + } + } + m_downscalar_width = ALIGN(m_downscalar_width, 128); + m_downscalar_height = ALIGN(m_downscalar_height, 32); +#endif + + if (!m_downscalar_width || !m_downscalar_height) { + DEBUG_PRINT_LOW("%s: Invalid downscalar configuration", __func__); + return 0; + } + if (m_force_down_scalar) { DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar); return 0; @@ -1263,7 +1338,7 @@ int omx_vdec::decide_downscalar() DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d m_is_display_session = %d", __func__, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height, m_is_display_session); - if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height >= m_downscalar_width * m_downscalar_height) && + if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) && m_is_display_session) { rc = enable_downscalar(); if (rc < 0) { @@ -2617,24 +2692,27 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) drv_ctx.idr_only_decoding = 0; #ifdef _ANDROID_ - property_get("vidc.dec.downscalar_width",property_value,"0"); + property_get("vidc.dec.enable.downscalar",property_value,"0"); if (atoi(property_value)) { - m_downscalar_width = atoi(property_value); - } - property_get("vidc.dec.downscalar_height",property_value,"0"); - if (atoi(property_value)) { - m_downscalar_height = atoi(property_value); - } + m_enable_downscalar = atoi(property_value); + property_get("vidc.dec.downscalar_width",property_value,"0"); + if (atoi(property_value)) { + m_downscalar_width = atoi(property_value); + } + property_get("vidc.dec.downscalar_height",property_value,"0"); + if (atoi(property_value)) { + m_downscalar_height = atoi(property_value); + } - if (m_downscalar_width < m_decoder_capability.min_width || - m_downscalar_height < m_decoder_capability.min_height) { - m_downscalar_width = 0; - m_downscalar_height = 0; + if (m_downscalar_width < m_decoder_capability.min_width || + m_downscalar_height < m_decoder_capability.min_height) { + m_downscalar_width = 0; + m_downscalar_height = 0; + } + + DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n", + m_downscalar_width, m_downscalar_height); } - - DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n", - m_downscalar_width, m_downscalar_height); - property_get("vidc.disable.split.mode",property_value,"0"); m_disable_split_mode = atoi(property_value); DEBUG_PRINT_HIGH("split mode is %s", m_disable_split_mode ? "disabled" : "enabled");