diff options
-rw-r--r-- | mm-core/inc/OMX_IndexExt.h | 1 | ||||
-rw-r--r-- | mm-core/inc/OMX_Video.h | 1 | ||||
-rw-r--r-- | mm-core/inc/OMX_VideoExt.h | 52 | ||||
-rw-r--r-- | mm-core/src/sdm845/registry_table.c | 18 | ||||
-rw-r--r-- | mm-core/src/sdm845/registry_table_android.c | 18 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/common/src/vidc_common.cpp | 4 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/omx_video_base.h | 3 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h | 5 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h | 5 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/omx_video_base.cpp | 24 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp | 47 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp | 111 |
12 files changed, 242 insertions, 47 deletions
diff --git a/mm-core/inc/OMX_IndexExt.h b/mm-core/inc/OMX_IndexExt.h index 8948393b..c3d8cb4d 100644 --- a/mm-core/inc/OMX_IndexExt.h +++ b/mm-core/inc/OMX_IndexExt.h @@ -82,6 +82,7 @@ typedef enum OMX_INDEXEXTTYPE { OMX_IndexConfigAndroidIntraRefresh, /**< reference: OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE */ OMX_IndexParamAndroidVideoTemporalLayering, /**< reference: OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE */ OMX_IndexConfigAndroidVideoTemporalLayering, /**< reference: OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE */ + OMX_IndexParamVideoAndroidImageGrid = OMX_IndexExtVideoStartUnused + 16, /**< reference: OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE */ /* Image & Video common configurations */ OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000, diff --git a/mm-core/inc/OMX_Video.h b/mm-core/inc/OMX_Video.h index ebef026a..a5568fe3 100644 --- a/mm-core/inc/OMX_Video.h +++ b/mm-core/inc/OMX_Video.h @@ -71,6 +71,7 @@ typedef enum OMX_VIDEO_CODINGTYPE { OMX_VIDEO_CodingVP8, /**< Google VP8, formerly known as On2 VP8 */ OMX_VIDEO_CodingVP9, /**< Google VP9 */ OMX_VIDEO_CodingHEVC, /**< HEVC */ + OMX_VIDEO_CodingHEIC = 13, /**< HEIC */ OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_VIDEO_CodingMax = 0x7FFFFFFF diff --git a/mm-core/inc/OMX_VideoExt.h b/mm-core/inc/OMX_VideoExt.h index af0ec808..758b8be7 100644 --- a/mm-core/inc/OMX_VideoExt.h +++ b/mm-core/inc/OMX_VideoExt.h @@ -143,12 +143,13 @@ typedef enum OMX_VIDEO_VP9LEVELTYPE { /** HEVC Profiles */ typedef enum OMX_VIDEO_HEVCPROFILETYPE { - OMX_VIDEO_HEVCProfileMain = 0x01, - OMX_VIDEO_HEVCProfileMain10 = 0x02, + OMX_VIDEO_HEVCProfileMain = 0x01, + OMX_VIDEO_HEVCProfileMain10 = 0x02, + OMX_VIDEO_HEVCProfileMainStill = 0x04, // Main10 profile with HDR SEI support. OMX_VIDEO_HEVCProfileMain10HDR10 = 0x1000, - OMX_VIDEO_HEVCProfileUnknown = 0x6EFFFFFF, - OMX_VIDEO_HEVCProfileMax = 0x7FFFFFFF + OMX_VIDEO_HEVCProfileUnknown = 0x6EFFFFFF, + OMX_VIDEO_HEVCProfileMax = 0x7FFFFFFF } OMX_VIDEO_HEVCPROFILETYPE; /** HEVC levels */ @@ -195,6 +196,49 @@ typedef struct OMX_VIDEO_PARAM_HEVCTYPE { } OMX_VIDEO_PARAM_HEVCTYPE; /** + * Android specific param for specifying image grid layout information for image encoding + * use cases, corresponding to index OMX_IndexParamVideoAndroidImageGrid. + * + * OMX_VIDEO_CodingImageHEIC encoders must handle this param type. When this param is set + * on the component with bEnabled set to true, nTileWidth, nTileHeight, nGridRows, + * nGridCols indicates the desired grid config by the client. The component can use this + * as a heuristic, and is free to choose any suitable grid configs. The client shall + * always get the actual from the component after the param is set. Encoder will receive + * each input image in full, and shall encode it into tiles in row-major, top-row first, + * left-to-right order, and send each encoded tile in a separate output buffer. All output + * buffers for the same input buffer shall carry the same timestamp as the input buffer. + * If the input buffer is marked EOS, the EOS should only appear on the last output buffer + * for that input buffer. + * + * OMX_VIDEO_CodingHEVC encoders might also receive this param when it's used for image + * encoding, although in this case the param only serves as a hint. The encoder will + * receive the input image tiles in row-major, top-row first, left-to-right order. + * The grid config can be used for quality control, or optimizations. + * + * If this param is not set, the component shall assume that grid option is disabled. + * + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to (output port for encoders) + * bEnabled : Whether grid is enabled. If true, the other parameters + * specifies the grid config; otherwise they shall be ignored. + * nTileWidth : Width of each tile. + * nTileHeight : Height of each tile. + * nGridRows : Number of rows in the grid. + * nGridCols : Number of cols in the grid. + */ +typedef struct OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnabled; + OMX_U32 nTileWidth; + OMX_U32 nTileHeight; + OMX_U32 nGridRows; + OMX_U32 nGridCols; +} OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE; + +/** * Structure for configuring video compression intra refresh period * * STRUCT MEMBERS: diff --git a/mm-core/src/sdm845/registry_table.c b/mm-core/src/sdm845/registry_table.c index 1170fa1b..e766d9b1 100644 --- a/mm-core/src/sdm845/registry_table.c +++ b/mm-core/src/sdm845/registry_table.c @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved. +Copyright (c) 2016 - 2018, 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 @@ -301,6 +301,22 @@ omx_core_cb_type core[] = } }, { + "OMX.qcom.video.encoder.heic", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "image_encoder.heic" + } + }, + { "OMX.qcom.audio.decoder.Qcelp13", NULL, // Create instance function // Unique instance handle diff --git a/mm-core/src/sdm845/registry_table_android.c b/mm-core/src/sdm845/registry_table_android.c index 0433f916..82ea3e4f 100644 --- a/mm-core/src/sdm845/registry_table_android.c +++ b/mm-core/src/sdm845/registry_table_android.c @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +Copyright (c) 2016-2018, 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 @@ -348,6 +348,22 @@ omx_core_cb_type core[] = } }, { + "OMX.qcom.video.encoder.heic", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "image_encoder.heic" + } + }, + { "OMX.qcom.video.encoder.tme", NULL, // Create instance function // Unique instance handle diff --git a/mm-video-v4l2/vidc/common/src/vidc_common.cpp b/mm-video-v4l2/vidc/common/src/vidc_common.cpp index f960e963..db96ecef 100644 --- a/mm-video-v4l2/vidc/common/src/vidc_common.cpp +++ b/mm-video-v4l2/vidc/common/src/vidc_common.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2017, The Linux Foundation. All rights reserved. +Copyright (c) 2017 - 2018 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 @@ -60,6 +60,8 @@ pl_map profile_level_converter::profile_hevc_omx_to_v4l2 ({ V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN}, {OMX_VIDEO_HEVCProfileMain10HDR10, V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10}, + {OMX_VIDEO_HEVCProfileMainStill, + V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC}, }); pl_map profile_level_converter::profile_hevc_v4l2_to_omx ({}); diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h index 0027694d..5908843a 100644 --- a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h +++ b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2018, 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 @@ -730,6 +730,7 @@ class omx_video: public qc_omx_component QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE m_sParamLowLatency; OMX_U32 m_nOperatingRate; QOMX_ENABLETYPE m_sParamColorSpaceConversion; + OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE m_sParamAndroidImageGrid; // fill this buffer queue omx_cmd_queue m_ftb_q; diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h b/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h index cba870d9..3ac07f3d 100644 --- a/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h +++ b/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2018, 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 @@ -37,6 +37,9 @@ extern "C" { OMX_API void * get_omx_component_factory_fn(void); } +#define DEFAULT_TILE_DIMENSION 512 +#define DEFAULT_TILE_COUNT 40 + class omx_venc: public omx_video { public: diff --git a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h index 6db4993e..acb09d4d 100644 --- a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h +++ b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h @@ -285,8 +285,9 @@ enum rc_modes { RC_CBR_CFR = BIT(3), RC_MBR_CFR = BIT(4), RC_MBR_VFR = BIT(5), + RC_CQ = BIT(6), RC_ALL = (RC_VBR_VFR | RC_VBR_CFR - | RC_CBR_VFR | RC_CBR_CFR | RC_MBR_CFR | RC_MBR_VFR) + | RC_CBR_VFR | RC_CBR_CFR | RC_MBR_CFR | RC_MBR_VFR | RC_CQ) }; class venc_dev @@ -468,7 +469,6 @@ class venc_dev bool bframe_implicitly_enabled; bool client_req_disable_temporal_layers; bool client_req_turbo_mode; - static const unsigned int QFQPMapping[21]; bool venc_query_cap(struct v4l2_queryctrl &cap); bool venc_validate_range(OMX_S32 id, OMX_S32 val); @@ -530,6 +530,7 @@ class venc_dev bool venc_set_iframesize_type(QOMX_VIDEO_IFRAMESIZE_TYPE type); unsigned long venc_get_color_format(OMX_COLOR_FORMATTYPE eColorFormat); unsigned long venc_get_codectype(OMX_VIDEO_CODINGTYPE eCompressionFormat); + bool venc_set_tile_dimension(OMX_U32 nTileDimension); OMX_U32 pmem_free(); OMX_U32 pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count); diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp index 00072fc2..016f5cb9 100644 --- a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp +++ b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2017, Linux Foundation. All rights reserved. +Copyright (c) 2010-2018, 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: @@ -1582,6 +1582,16 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef)); + // Tiling in HW expects output port def to be aligned to tile size + // At the same time, FWK needs original WxH for various purposes + // Sending input WxH as output port def WxH to FWK + if (m_sOutPortDef.format.video.eCompressionFormat == + OMX_VIDEO_CodingHEIC) { + portDefn->format.video.nFrameWidth = + m_sInPortDef.format.video.nFrameWidth; + portDefn->format.video.nFrameHeight = + m_sInPortDef.format.video.nFrameHeight; + } if (secure_session || allocate_native_handle) { portDefn->nBufferSize = @@ -1706,6 +1716,15 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, memcpy(pParam, &m_sParamTME, sizeof(m_sParamTME)); break; } + case OMX_IndexParamVideoAndroidImageGrid: + { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE); + OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE* pParam = + (OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAndroidImageGrid"); + memcpy(pParam, &m_sParamAndroidImageGrid, sizeof(m_sParamAndroidImageGrid)); + break; + } case OMX_IndexParamVideoProfileLevelQuerySupported: { VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); @@ -4331,7 +4350,8 @@ OMX_ERRORTYPE omx_video::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_ERROR("ERROR: No more roles"); eRet = OMX_ErrorNoMore; } - } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { + } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE) || + !strncmp((char*)m_nkind, "OMX.qcom.video.encoder.heic", OMX_MAX_STRINGNAME_SIZE)) { if ((0 == index) && role) { strlcpy((char *)role, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE); DEBUG_PRINT_LOW("component_role_enum: role %s", role); diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp index 540f8b5a..8181347c 100644 --- a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp +++ b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2018, 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: @@ -124,6 +124,10 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) OMX_MAX_STRINGNAME_SIZE)) { strlcpy((char *)m_cRole, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE); codec_type = OMX_VIDEO_CodingHEVC; + } else if (!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.heic", \ + OMX_MAX_STRINGNAME_SIZE)) { + strlcpy((char *)m_cRole, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE); + codec_type = OMX_VIDEO_CodingHEIC; } else if (!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.hevc.secure", \ OMX_MAX_STRINGNAME_SIZE)) { strlcpy((char *)m_cRole, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE); @@ -264,6 +268,9 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) } else if (codec_type == OMX_VIDEO_CodingHEVC) { m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_HEVCProfileMain; m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_HEVCMainTierLevel1; + } else if (codec_type == OMX_VIDEO_CodingHEIC) { + m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_HEVCProfileMainStill; + m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_HEVCMainTierLevel1; } OMX_INIT_STRUCT(&m_sParamEntropy, QOMX_VIDEO_H264ENTROPYCODINGTYPE); @@ -313,6 +320,8 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8; } else if (codec_type == OMX_VIDEO_CodingHEVC) { m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC; + } else if (codec_type == OMX_VIDEO_CodingHEIC) { + m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingHEIC; } else if (codec_type == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingTME) { m_sOutPortDef.format.video.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingTME; } @@ -344,6 +353,8 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingVP8; } else if (codec_type == OMX_VIDEO_CodingHEVC) { m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingHEVC; + } else if (codec_type == OMX_VIDEO_CodingHEIC) { + m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingHEIC; } else if (codec_type == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingTME) { m_sOutPortFormat.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingTME; } @@ -405,6 +416,15 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sParamTME.eLevel = QOMX_VIDEO_TMELevelInteger; m_sParamTME.ePayloadVersion = tme_payload_version; + // HEIC specific init + OMX_INIT_STRUCT(&m_sParamAndroidImageGrid, OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE); + m_sParamAndroidImageGrid.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sParamAndroidImageGrid.bEnabled = OMX_FALSE; + m_sParamAndroidImageGrid.nTileWidth = DEFAULT_TILE_DIMENSION; + m_sParamAndroidImageGrid.nTileHeight = DEFAULT_TILE_DIMENSION; + m_sParamAndroidImageGrid.nGridRows = DEFAULT_TILE_COUNT; + m_sParamAndroidImageGrid.nGridCols = DEFAULT_TILE_COUNT; + OMX_INIT_STRUCT(&m_sParamLTRCount, QOMX_VIDEO_PARAM_LTRCOUNT_TYPE); m_sParamLTRCount.nPortIndex = (OMX_U32) PORT_INDEX_OUT; m_sParamLTRCount.nCount = 0; @@ -812,6 +832,19 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, m_sParamTME.ePayloadVersion = tme_payload_version; break; } + case OMX_IndexParamVideoAndroidImageGrid: + { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE); + DEBUG_PRINT_LOW("set_param:OMX_IndexParamVideoAndroidImageGrid"); + OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE* pParam = + (OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE*)paramData; + if (!handle->venc_set_param(paramData, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid)) { + DEBUG_PRINT_ERROR("ERROR: Request for setting image grid failed"); + return OMX_ErrorUnsupportedSetting; + } + memcpy(&m_sParamAndroidImageGrid, pParam, sizeof(m_sParamAndroidImageGrid)); + break; + } case OMX_IndexParamVideoProfileLevelCurrent: { VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); @@ -846,6 +879,8 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, m_sParamVP8.eLevel); } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc",\ + OMX_MAX_STRINGNAME_SIZE) || + !strncmp((char*)m_nkind, "OMX.qcom.video.encoder.heic",\ OMX_MAX_STRINGNAME_SIZE)) { m_sParamHEVC.eProfile = (OMX_VIDEO_HEVCPROFILETYPE)m_sParamProfileLevel.eProfile; m_sParamHEVC.eLevel = (OMX_VIDEO_HEVCLEVELTYPE)m_sParamProfileLevel.eLevel; @@ -901,6 +936,14 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, eRet = OMX_ErrorUnsupportedSetting; } } + else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.heic",OMX_MAX_STRINGNAME_SIZE)) { + if (!strncmp((const char*)comp_role->cRole,"image_encoder.heic",OMX_MAX_STRINGNAME_SIZE)) { + strlcpy((char*)m_cRole,"video_encoder.hevc",OMX_MAX_STRINGNAME_SIZE); + } else { + DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown Index %s", comp_role->cRole); + eRet = OMX_ErrorUnsupportedSetting; + } + } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.tme", OMX_MAX_STRINGNAME_SIZE)) { if (!strncmp((const char*)comp_role->cRole,"video_encoder.tme",OMX_MAX_STRINGNAME_SIZE)) { strlcpy((char*)m_cRole,"video_encoder.tme",OMX_MAX_STRINGNAME_SIZE); @@ -1596,6 +1639,8 @@ bool omx_venc::update_profile_level() m_sParamVP8.eLevel); } else if (!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.hevc",\ + OMX_MAX_STRINGNAME_SIZE) || + !strncmp((char *)m_nkind, "OMX.qcom.video.encoder.heic",\ OMX_MAX_STRINGNAME_SIZE)) { m_sParamHEVC.eProfile = (OMX_VIDEO_HEVCPROFILETYPE)eProfile; m_sParamHEVC.eLevel = (OMX_VIDEO_HEVCLEVELTYPE)eLevel; diff --git a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp index bedeaba8..4db6d0ea 100644 --- a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp +++ b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp @@ -86,10 +86,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define VENC_BFRAME_MAX_WIDTH 1920 #define VENC_BFRAME_MAX_HEIGHT 1088 -// Scaled quality factor - QP mapping -#define SCALED_QUALITY_FACTOR_MAX 20 -const unsigned int venc_dev::QFQPMapping[21] = {51, 47, 43, 39, 35, 31, 28, 25, 22, 19, 16, 13, 11, 9, 7, 5, 6, 4, 3, 2}; - #undef LOG_TAG #define LOG_TAG "OMX-VENC: venc_dev" @@ -948,8 +944,9 @@ OMX_ERRORTYPE venc_dev::venc_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILE QOMX_VIDEO_AVCProfileMain, QOMX_VIDEO_AVCProfileConstrainedHigh, QOMX_VIDEO_AVCProfileHigh }; - int hevc_profiles[2] = { OMX_VIDEO_HEVCProfileMain, - OMX_VIDEO_HEVCProfileMain10HDR10 }; + int hevc_profiles[3] = { OMX_VIDEO_HEVCProfileMain, + OMX_VIDEO_HEVCProfileMain10HDR10, + OMX_VIDEO_HEVCProfileMainStill }; if (!profileLevelType) return OMX_ErrorBadParameter; @@ -1412,12 +1409,15 @@ bool venc_dev::venc_open(OMX_U32 codec) profile_level.level = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0; minqp = 0; maxqp = 127; - } else if (codec == OMX_VIDEO_CodingHEVC) { + } else if (codec == OMX_VIDEO_CodingHEVC || codec == OMX_VIDEO_CodingHEIC) { m_sVenc_cfg.codectype = V4L2_PIX_FMT_HEVC; idrperiod.idrperiod = 1; minqp = 0; maxqp = 51; - codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN; + if (codec == OMX_VIDEO_CodingHEIC) + codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC; + else + codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN; profile_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1; } else if (codec == QOMX_VIDEO_CodingTME) { m_sVenc_cfg.codectype = V4L2_PIX_FMT_TME; @@ -2011,9 +2011,15 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) portDefn->nPortIndex); } } else if (portDefn->nPortIndex == PORT_INDEX_OUT) { - unsigned long codectype = venc_get_codectype(portDefn->format.video.eCompressionFormat); + if (portDefn->format.video.eCompressionFormat == OMX_VIDEO_CodingHEIC) { + portDefn->format.video.nFrameWidth = DEFAULT_TILE_DIMENSION; + portDefn->format.video.nFrameHeight = DEFAULT_TILE_DIMENSION; + DEBUG_PRINT_HIGH("set_parameter: OMX_IndexParamPortDefinition: port %d, wxh (for HEIC coding type) %dx%d", + portDefn->nPortIndex, portDefn->format.video.nFrameWidth, + portDefn->format.video.nFrameHeight); + } //Don't worry about width/height if downscalar is enabled. if (((m_sVenc_cfg.dvs_height != portDefn->format.video.nFrameHeight || m_sVenc_cfg.dvs_width != portDefn->format.video.nFrameWidth) && !downscalar_enabled) || @@ -2109,14 +2115,6 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoBitrate"); if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { - // Quality factor setting - unsigned int scaledQF; - if (pParam->eControlRate == OMX_Video_ControlRateConstantQuality) { - pParam->eControlRate = OMX_Video_ControlRateDisable; - scaledQF = pParam->nQualityFactor / 5; - scaledQF = (scaledQF > SCALED_QUALITY_FACTOR_MAX) ? SCALED_QUALITY_FACTOR_MAX : scaledQF; - } - if (!venc_set_target_bitrate(pParam->nTargetBitrate)) { DEBUG_PRINT_ERROR("ERROR: Setting Target Bit Rate / Quality Factor failed"); return false; @@ -2126,18 +2124,6 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) DEBUG_PRINT_ERROR("ERROR: Rate Control setting failed"); return false; } - // Setting QP values - if (((OMX_VIDEO_PARAM_BITRATETYPE*)paramData)->eControlRate == OMX_Video_ControlRateDisable) { - if (venc_set_qp(QFQPMapping[scaledQF], - QFQPMapping[scaledQF], - QFQPMapping[scaledQF], - ENABLE_I_QP | ENABLE_P_QP | ENABLE_B_QP) == false) { - DEBUG_PRINT_ERROR("ERROR: Setting QP values failed"); - return false; - } - DEBUG_PRINT_LOW("Rate control: %u Quality factor(client): %u scaledQF: %u", - pParam->eControlRate, pParam->nQualityFactor, scaledQF); - } } else { DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoBitrate"); } @@ -2266,6 +2252,24 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) } break; } + case (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid: + { + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoAndroidImageGrid"); + OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE* pParam = + (OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE*)paramData; + + if (m_codec != OMX_VIDEO_CodingHEIC) { + DEBUG_PRINT_ERROR("OMX_IndexParamVideoAndroidImageGrid is only supported for HEIC"); + return false; + } + + if (!venc_set_tile_dimension(pParam->nTileWidth)) { + DEBUG_PRINT_ERROR("ERROR: Failed to set tile dimension %d", + pParam->nTileWidth); + return false; + } + break; + } case OMX_IndexParamVideoIntraRefresh: { DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh"); @@ -4249,7 +4253,9 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, return false; } - if (inp_width * inp_height != out_width * out_height) { + // Tiling in HEIC requires output WxH to be Tile size; difference is permitted + if (!(m_codec == OMX_VIDEO_CodingHEIC) && + inp_width * inp_height != out_width * out_height) { DEBUG_PRINT_ERROR("Downscalar is disabled and input/output dimenstions don't match"); DEBUG_PRINT_ERROR("Input WxH : %dx%d Output WxH : %dx%d",inp_width, inp_height, out_width, out_height); return false; @@ -5027,7 +5033,9 @@ bool venc_dev::venc_reconfigure_intra_period() if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC && ((codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN) || - (codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10))) { + (codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) || + (codec_profile.profile == V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC)) && + (m_codec != OMX_VIDEO_CodingHEIC)) { isValidCodec = true; } @@ -5127,6 +5135,27 @@ bool venc_dev::venc_reconfigure_intra_period() return true; } +bool venc_dev::venc_set_tile_dimension(OMX_U32 nTileDimension) +{ + int rc; + struct v4l2_control control; + + DEBUG_PRINT_LOW("venc_set_tile_dimension: nTileDimension = %u", (unsigned int)nTileDimension); + + control.id = V4L2_CID_MPEG_VIDC_IMG_GRID_DIMENSION; + control.value = nTileDimension; + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value); + return false; + } + + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value); + + return true; +} + bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) { DEBUG_PRINT_LOW("venc_set_intra_period: nPFrames = %u, nBFrames: %u", (unsigned int)nPFrames, (unsigned int)nBFrames); @@ -5145,7 +5174,8 @@ bool venc_dev::_venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) char property_value[PROPERTY_VALUE_MAX] = {0}; if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 && - m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) { + m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC && + m_codec == OMX_VIDEO_CodingHEIC) { nBFrames = 0; } @@ -5153,6 +5183,7 @@ bool venc_dev::_venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) && (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN) && (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) && + (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC) && (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)) { nBFrames = 0; } @@ -5520,7 +5551,10 @@ bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate) return true; } - control.id = V4L2_CID_MPEG_VIDEO_BITRATE; + if (rate_ctrl.rcmode == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CQ) + control.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_QUALITY; + else + control.id = V4L2_CID_MPEG_VIDEO_BITRATE; control.value = nTargetBitrate; DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value); @@ -5532,6 +5566,8 @@ bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate) DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value); + if (control.id == V4L2_CID_MPEG_VIDC_VIDEO_FRAME_QUALITY) + return true; m_sVenc_cfg.targetbitrate = control.value; bitrate.target_bitrate = control.value; @@ -5602,6 +5638,7 @@ unsigned long venc_dev::venc_get_codectype(OMX_VIDEO_CODINGTYPE eCompressionForm case OMX_VIDEO_CodingVP9: codectype = V4L2_PIX_FMT_VP9; break; + case OMX_VIDEO_CodingHEIC: case OMX_VIDEO_CodingHEVC: codectype = V4L2_PIX_FMT_HEVC; break; @@ -6129,6 +6166,11 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_MBR_VFR: status = false; break; + case OMX_Video_ControlRateConstantQuality: + (supported_rc_modes & RC_CQ) ? + control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CQ: + status = false; + break; default: status = false; break; @@ -7144,6 +7186,9 @@ bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel) case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10: *eProfile = OMX_VIDEO_HEVCProfileMain10HDR10; break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC: + *eProfile = OMX_VIDEO_HEVCProfileMainStill; + break; default: *eProfile = OMX_VIDEO_HEVCProfileMax; status = false; |