diff options
-rw-r--r-- | msm8974/mm-core/inc/OMX_VideoExt.h | 1 | ||||
-rw-r--r-- | msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp | 6 | ||||
-rw-r--r-- | msm8996/libc2dcolorconvert/Android.mk | 2 | ||||
-rw-r--r-- | msm8996/mm-core/inc/OMX_IndexExt.h | 2 | ||||
-rw-r--r-- | msm8996/mm-core/inc/OMX_QCOMExtns.h | 32 | ||||
-rw-r--r-- | msm8996/mm-core/inc/OMX_VideoExt.h | 90 | ||||
-rw-r--r-- | msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h | 20 | ||||
-rw-r--r-- | msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp | 542 | ||||
-rw-r--r-- | msm8996/mm-video-v4l2/vidc/venc/Android.mk | 1 | ||||
-rw-r--r-- | msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h | 8 | ||||
-rw-r--r-- | msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h | 2 | ||||
-rw-r--r-- | msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h | 34 | ||||
-rw-r--r-- | msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp | 79 | ||||
-rw-r--r-- | msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp | 71 | ||||
-rw-r--r-- | msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp | 747 |
15 files changed, 1537 insertions, 100 deletions
diff --git a/msm8974/mm-core/inc/OMX_VideoExt.h b/msm8974/mm-core/inc/OMX_VideoExt.h index 92d360a..30fe514 100644 --- a/msm8974/mm-core/inc/OMX_VideoExt.h +++ b/msm8974/mm-core/inc/OMX_VideoExt.h @@ -155,6 +155,7 @@ typedef struct OMX_VIDEO_PARAM_HEVCTYPE { OMX_U32 nPortIndex; OMX_VIDEO_HEVCPROFILETYPE eProfile; OMX_VIDEO_HEVCLEVELTYPE eLevel; + OMX_U32 nKeyFrameInterval; /* 0 => undefined. Codec-default */ } OMX_VIDEO_PARAM_HEVCTYPE; /** diff --git a/msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp index b3b37d1..cd3ba9f 100644 --- a/msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp +++ b/msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp @@ -1623,6 +1623,12 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) if (!venc_set_inloop_filter(OMX_VIDEO_AVCLoopFilterEnable)) DEBUG_PRINT_HIGH("WARN: Request for setting Inloop filter failed for HEVC encoder"); + OMX_U32 fps = m_sVenc_cfg.fps_num ? m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den : 30; + OMX_U32 nPFrames = pParam->nKeyFrameInterval > 0 ? pParam->nKeyFrameInterval - 1 : fps - 1; + if (!venc_set_intra_period (nPFrames, 0 /* nBFrames */)) { + DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed"); + return false; + } break; } case OMX_IndexParamVideoIntraRefresh: diff --git a/msm8996/libc2dcolorconvert/Android.mk b/msm8996/libc2dcolorconvert/Android.mk index 33a89ae..9b8d9a5 100644 --- a/msm8996/libc2dcolorconvert/Android.mk +++ b/msm8996/libc2dcolorconvert/Android.mk @@ -6,7 +6,7 @@ LOCAL_SRC_FILES := \ C2DColorConverter.cpp LOCAL_C_INCLUDES := \ - $(TARGET_OUT_HEADERS)/adreno + $(TARGET_OUT_HEADERS)/qcom/display ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true) LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include diff --git a/msm8996/mm-core/inc/OMX_IndexExt.h b/msm8996/mm-core/inc/OMX_IndexExt.h index 09e3b5b..468a3a3 100644 --- a/msm8996/mm-core/inc/OMX_IndexExt.h +++ b/msm8996/mm-core/inc/OMX_IndexExt.h @@ -73,6 +73,8 @@ typedef enum OMX_INDEXEXTTYPE { OMX_IndexParamVideoHevc, /**< reference: OMX_VIDEO_PARAM_HEVCTYPE */ OMX_IndexParamSliceSegments, /**< reference: OMX_VIDEO_SLICESEGMENTSTYPE */ OMX_IndexConfigAndroidIntraRefresh, /**< reference: OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE */ + OMX_IndexParamAndroidVideoTemporalLayering, /**< reference: OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE */ + OMX_IndexConfigAndroidVideoTemporalLayering, /**< reference: OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE */ /* Image & Video common configurations */ OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000, diff --git a/msm8996/mm-core/inc/OMX_QCOMExtns.h b/msm8996/mm-core/inc/OMX_QCOMExtns.h index 4ce44f6..8e92946 100644 --- a/msm8996/mm-core/inc/OMX_QCOMExtns.h +++ b/msm8996/mm-core/inc/OMX_QCOMExtns.h @@ -512,7 +512,7 @@ enum OMX_QCOM_EXTN_INDEXTYPE /* "OMX.QCOM.index.param.video.InputBatch" */ OMX_QcomIndexParamBatchSize = 0x7F00004A, - OMX_QcomIndexConfigMaxHierPLayers = 0x7F00004B, + OMX_QcomIndexConfigNumHierPLayers = 0x7F00004B, OMX_QcomIndexConfigRectType = 0x7F00004C, @@ -550,6 +550,21 @@ enum OMX_QCOM_EXTN_INDEXTYPE /* Force OPB to UnCompressed mode */ OMX_QTIIndexParamForceUnCompressedForOPB = 0x7F00005A, + + /*"OMX.google.android.index.allocateNativeHandle"*/ + OMX_GoogleAndroidIndexAllocateNativeHandle = 0x7F00005B, + + /*"OMX.google.android.index.describeColorAspects"*/ + OMX_QTIIndexConfigDescribeColorAspects = 0x7F00005E, + + OMX_QTIIndexParamVUIExtraDataExtraData = 0x7F00005F, + + OMX_QTIIndexParamMPEG2SeqDispExtraData = 0x7F000060, + + OMX_QTIIndexParamVC1SeqDispExtraData = 0x7F000061, + + OMX_QTIIndexParamVPXColorSpaceExtraData = 0x7F000062, + }; /** @@ -579,16 +594,16 @@ typedef struct QOMX_EXTNINDEX_VIDEO_VENC_SAR * * nSize : Size of Structure in bytes * nVersion : OpenMAX IL specification version information -* nMaxHierLayers: Set the max number of Hier-p layers for the session -* - This should be less than the Hier-P layers set -* for the session. +* nNumHierLayers: Set the number of Hier-p layers for the session +* - This should be less than the MAX Hier-P +* layers set for the session. */ -typedef struct QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS { +typedef struct QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS { OMX_U32 nSize; OMX_VERSIONTYPE nVersion; - OMX_U32 nMaxHierLayers; -} QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS; + OMX_U32 nNumHierLayers; +} QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS; /** @@ -1598,7 +1613,6 @@ typedef struct QOMX_VIDEO_CUSTOM_BUFFERSIZE { #define OMX_QCOM_INDEX_PARAM_VIDEO_LTRPERIOD "OMX.QCOM.index.param.video.LTRPeriod" #define OMX_QCOM_INDEX_CONFIG_VIDEO_LTRUSE "OMX.QCOM.index.config.video.LTRUse" #define OMX_QCOM_INDEX_CONFIG_VIDEO_LTRMARK "OMX.QCOM.index.config.video.LTRMark" -#define OMX_QCOM_INDEX_CONFIG_VIDEO_MAX_HIER_P_LAYERS "OMX.QCOM.index.config.video.hierplayers" #define OMX_QCOM_INDEX_CONFIG_RECTANGLE_TYPE "OMX.QCOM.index.config.video.rectangle" #define OMX_QCOM_INDEX_PARAM_VIDEO_BASE_LAYER_ID "OMX.QCOM.index.param.video.baselayerid" #define OMX_QCOM_INDEX_PARAM_VIDEO_DRIVERVERSION "OMX.QCOM.index.param.video.FramePackingInfo" @@ -1611,7 +1625,7 @@ typedef struct QOMX_VIDEO_CUSTOM_BUFFERSIZE { #define OMX_QCOM_INDEX_PARAM_VIDEO_LTRPERIOD "OMX.QCOM.index.param.video.LTRPeriod" #define OMX_QCOM_INDEX_CONFIG_VIDEO_LTRUSE "OMX.QCOM.index.config.video.LTRUse" #define OMX_QCOM_INDEX_CONFIG_VIDEO_LTRMARK "OMX.QCOM.index.config.video.LTRMark" -#define OMX_QCOM_INDEX_CONFIG_VIDEO_MAX_HIER_P_LAYERS "OMX.QCOM.index.config.video.hierplayers" +#define OMX_QCOM_INDEX_CONFIG_VIDEO_HIER_P_LAYERS "OMX.QCOM.index.config.video.hierplayers" #define OMX_QCOM_INDEX_CONFIG_RECTANGLE_TYPE "OMX.QCOM.index.config.video.rectangle" #define OMX_QCOM_INDEX_PARAM_VIDEO_BASE_LAYER_ID "OMX.QCOM.index.param.video.baselayerid" #define OMX_QCOM_INDEX_CONFIG_VIDEO_QP "OMX.QCOM.index.config.video.qp" diff --git a/msm8996/mm-core/inc/OMX_VideoExt.h b/msm8996/mm-core/inc/OMX_VideoExt.h index 92d360a..59258d7 100644 --- a/msm8996/mm-core/inc/OMX_VideoExt.h +++ b/msm8996/mm-core/inc/OMX_VideoExt.h @@ -155,6 +155,7 @@ typedef struct OMX_VIDEO_PARAM_HEVCTYPE { OMX_U32 nPortIndex; OMX_VIDEO_HEVCPROFILETYPE eProfile; OMX_VIDEO_HEVCLEVELTYPE eLevel; + OMX_U32 nKeyFrameInterval; /* 0 => undefined. Codec-default */ } OMX_VIDEO_PARAM_HEVCTYPE; /** @@ -173,6 +174,95 @@ typedef struct OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE { OMX_U32 nRefreshPeriod; } OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE; +/** Maximum number of temporal layers supported by AVC/HEVC */ +#define OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS 8 + +/** temporal layer patterns */ +typedef enum OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE { + OMX_VIDEO_AndroidTemporalLayeringPatternNone = 0, + // pattern as defined by WebRTC + OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC = 1 << 0, + // pattern where frames in any layer other than the base layer only depend on at most the very + // last frame from each preceding layer (other than the base layer.) + OMX_VIDEO_AndroidTemporalLayeringPatternAndroid = 1 << 1, +} OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE; + +/** + * Android specific param for configuration of temporal layering. + * Android only supports temporal layering where successive layers each double the + * previous layer's framerate. + * NOTE: Reading this parameter at run-time SHALL return actual run-time values. + * + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to (output port for encoders) + * eSupportedPatterns : A bitmask of supported layering patterns + * nLayerCountMax : Max number of temporal coding layers supported + * by the encoder (must be at least 1, 1 meaning temporal layering + * is NOT supported) + * nBLayerCountMax : Max number of layers that can contain B frames + * (0) to (nLayerCountMax - 1) + * ePattern : Layering pattern. + * nPLayerCountActual : Number of temporal layers to be coded with non-B frames, + * starting from and including the base-layer. + * (1 to nLayerCountMax - nBLayerCountActual) + * If nPLayerCountActual is 1 and nBLayerCountActual is 0, temporal + * layering is disabled. Otherwise, it is enabled. + * nBLayerCountActual : Number of temporal layers to be coded with B frames, + * starting after non-B layers. + * (0 to nBLayerCountMax) + * bBitrateRatiosSpecified : Flag to indicate if layer-wise bitrate + * distribution is specified. + * nBitrateRatios : Bitrate ratio (100 based) per layer (index 0 is base layer). + * Honored if bBitrateRatiosSpecified is set. + * i.e for 4 layers with desired distribution (25% 25% 25% 25%), + * nBitrateRatio = {25, 50, 75, 100, ... } + * Values in indices not less than 'the actual number of layers + * minus 1' MAY be ignored and assumed to be 100. + */ +typedef struct OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE eSupportedPatterns; + OMX_U32 nLayerCountMax; + OMX_U32 nBLayerCountMax; + OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern; + OMX_U32 nPLayerCountActual; + OMX_U32 nBLayerCountActual; + OMX_BOOL bBitrateRatiosSpecified; + OMX_U32 nBitrateRatios[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; +} OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE; + +/** + * Android specific config for changing the temporal-layer count or + * bitrate-distribution at run-time. + * + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to (output port for encoders) + * ePattern : Layering pattern. + * nPLayerCountActual : Number of temporal layers to be coded with non-B frames. + * (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.) + * nBLayerCountActual : Number of temporal layers to be coded with B frames. + * (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.) + * bBitrateRatiosSpecified : Flag to indicate if layer-wise bitrate + * distribution is specified. + * nBitrateRatios : Bitrate ratio (100 based, Q16 values) per layer (0 is base layer). + * Honored if bBitrateRatiosSpecified is set. + * (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.) + */ +typedef struct OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern; + OMX_U32 nPLayerCountActual; + OMX_U32 nBLayerCountActual; + OMX_BOOL bBitrateRatiosSpecified; + OMX_U32 nBitrateRatios[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; +} OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE; + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index 62d4ddb..d400fc3 100644 --- a/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010 - 2015, The Linux Foundation. All rights reserved. +Copyright (c) 2010 - 2016, 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 @@ -48,6 +48,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <inttypes.h> #include <cstddef> #include <cutils/atomic.h> +#include <qdMetaData.h> static ptrdiff_t x; @@ -195,6 +196,13 @@ class VideoHeap : public MemoryHeapBase #define OMX_BITSINFO_EXTRADATA 0x01000000 #define OMX_VQZIPSEI_EXTRADATA 0x02000000 +#define OMX_VUI_DISPLAY_INFO_EXTRADATA 0x08000000 +#define OMX_MPEG2_SEQDISP_INFO_EXTRADATA 0x10000000 +#define OMX_VPX_COLORSPACE_INFO_EXTRADATA 0x20000000 +#define OMX_VC1_SEQDISP_INFO_EXTRADATA 0x40000000 +#define OMX_DISPLAY_INFO_EXTRADATA 0x80000000 +#define DRIVER_EXTRADATA_MASK 0x0000FFFF + #define OMX_INTERLACE_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\ sizeof(OMX_STREAMINTERLACEFORMAT) + 3)&(~3)) #define OMX_FRAMEINFO_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\ @@ -658,6 +666,12 @@ class omx_vdec: public qc_omx_component void set_frame_rate(OMX_S64 act_timestamp); void handle_extradata_secure(OMX_BUFFERHEADERTYPE *p_buf_hdr); void handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr); + void convert_color_space_info(OMX_U32 primaries, OMX_U32 range, + OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, + ColorAspects *aspects); + void handle_color_space_info(void *data, unsigned int buf_index); + void set_colorspace_in_handle(ColorSpace_t color, unsigned int buf_index); + void print_debug_color_aspects(ColorAspects *aspects, const char *prefix); void print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra); #ifdef _MSM8974_ void append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra, @@ -941,6 +955,7 @@ class omx_vdec: public qc_omx_component omx_time_stamp_reorder time_stamp_dts; desc_buffer_hdr *m_desc_buffer_ptr; bool secure_mode; + bool allocate_native_handle; bool external_meta_buffer; bool external_meta_buffer_iommu; OMX_QCOM_EXTRADATA_FRAMEINFO *m_extradata; @@ -977,6 +992,8 @@ class omx_vdec: public qc_omx_component bool m_smoothstreaming_mode; bool m_input_pass_buffer_fd; + DescribeColorAspectsParams m_client_color_space; + DescribeColorAspectsParams m_internal_color_space; OMX_U32 m_smoothstreaming_width; OMX_U32 m_smoothstreaming_height; @@ -1154,6 +1171,7 @@ class omx_vdec: public qc_omx_component } static OMX_ERRORTYPE describeColorFormat(OMX_PTR params); + void prefetchNewBuffers(); }; diff --git a/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp index c02e1e7..7661b6c 100644 --- a/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp +++ b/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp @@ -123,7 +123,7 @@ extern "C" { #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0) #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1)) -#define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA) +#define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_DISPLAY_INFO_EXTRADATA) #define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default #ifndef ION_FLAG_CP_BITSTREAM @@ -639,6 +639,7 @@ omx_vdec::omx_vdec(): m_error_propogated(false), #endif m_desc_buffer_ptr(NULL), secure_mode(false), + allocate_native_handle(false), m_other_extradata(NULL), m_profile(0), client_set_fps(false), @@ -740,6 +741,8 @@ omx_vdec::omx_vdec(): m_error_propogated(false), memset (m_hwdevice_name,0,sizeof(m_hwdevice_name)); memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize)); + memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams)); + memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams)); m_demux_entries = 0; msg_thread_id = 0; async_thread_id = 0; @@ -787,6 +790,18 @@ omx_vdec::omx_vdec(): m_error_propogated(false), is_q6_platform = false; m_perf_control.send_hint_to_mpctl(true); m_input_pass_buffer_fd = false; + m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX; + m_client_color_space.sAspects.mRange = ColorAspects::RangeUnspecified; + m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified; + m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified; + m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified; + + m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX; + m_internal_color_space.sAspects.mRange = ColorAspects::RangeUnspecified; + m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified; + m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified; + m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified; + m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams); } static const int event_type[] = { @@ -1646,6 +1661,8 @@ void omx_vdec::process_event_cb(void *ctxt, unsigned char id) DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u", pThis->rectangle.nLeft, pThis->rectangle.nTop, pThis->rectangle.nWidth, pThis->rectangle.nHeight); + } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) { + DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects"); } else { DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2); break; @@ -1663,6 +1680,10 @@ void omx_vdec::process_event_cb(void *ctxt, unsigned char id) pThis->m_debug.out_uvmeta_file = NULL; } + if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) { + pThis->prefetchNewBuffers(); + } + if (pThis->m_cb.EventHandler) { uint32_t frame_data[2]; frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ? @@ -3350,6 +3371,9 @@ OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVEL if (profileLevelType->nProfileIndex == 0) { profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain; profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; + } else if (profileLevelType->nProfileIndex == 1) { + profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10; + profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; } else { DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", (unsigned int)profileLevelType->nProfileIndex); @@ -4610,6 +4634,13 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, eRet = use_android_native_buffer(hComp, paramData); } break; + case OMX_GoogleAndroidIndexAllocateNativeHandle: { + AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData; + if (allocateNativeHandleParams != NULL) { + allocate_native_handle = allocateNativeHandleParams->enable; + } + } + break; #endif case OMX_QcomIndexParamEnableTimeStampReorder: { VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER); @@ -5002,6 +5033,28 @@ OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, break; } + case OMX_QTIIndexConfigDescribeColorAspects: + { + VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams); + DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData; + + print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client"); + print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal"); + + if (params->bRequestingDataSpace) { + DEBUG_PRINT_ERROR("Does not handle dataspace request"); + return OMX_ErrorUnsupportedSetting; + } + if (m_internal_color_space.bDataSpaceChanged == OMX_TRUE) { + DEBUG_PRINT_LOW("Updating Client's color aspects with internal"); + memcpy(&(m_client_color_space.sAspects), + &(m_internal_color_space.sAspects), sizeof(ColorAspects)); + m_internal_color_space.bDataSpaceChanged = OMX_FALSE; + } + memcpy(&(params->sAspects), &(m_client_color_space.sAspects), sizeof(ColorAspects)); + + break; + } default: { DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex); eRet = OMX_ErrorBadParameter; @@ -5213,6 +5266,17 @@ OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp, rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno)); } return ret; + + } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) { + VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams); + DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData; + if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) { + enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true); + } + + print_debug_color_aspects(&(params->sAspects), "Set Config"); + memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams)); + return ret; } return OMX_ErrorNotImplemented; @@ -5267,6 +5331,8 @@ OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer; } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) { *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage; + } else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) { + *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle; } #endif else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) { @@ -5290,6 +5356,8 @@ OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB; } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) { *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB; + } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) { + *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects; } else { DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName); return OMX_ErrorNotImplemented; @@ -5884,8 +5952,12 @@ OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) drv_ctx.ptr_inputbuffer[index].bufferaddr); munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr, drv_ctx.ptr_inputbuffer[index].mmaped_size); + close (drv_ctx.ptr_inputbuffer[index].pmem_fd); + } else if (allocate_native_handle){ + native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer; + native_handle_close(nh); + native_handle_delete(nh); } - close (drv_ctx.ptr_inputbuffer[index].pmem_fd); drv_ctx.ptr_inputbuffer[index].pmem_fd = -1; if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) { free(m_desc_buffer_ptr[index].buf_addr); @@ -6214,11 +6286,16 @@ OMX_ERRORTYPE omx_vdec::allocate_input_buffer( input = *bufferHdr; BITMASK_SET(&m_inp_bm_count,i); DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr); - if (secure_mode || m_input_pass_buffer_fd) + if (allocate_native_handle) { + native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/); + nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd; + input->pBuffer = (OMX_U8 *)nh; + } else if (secure_mode || m_input_pass_buffer_fd) { + /*Legacy method, pass ion fd stashed directly in pBuffer*/ input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd; - else - input->pBuffer = (OMX_U8 *)buf_addr; - + } else { + input->pBuffer = (OMX_U8 *)buf_addr; + } input->nSize = sizeof(OMX_BUFFERHEADERTYPE); input->nVersion.nVersion = OMX_SPEC_VERSION; input->nAllocLen = drv_ctx.ip_buf.buffer_size; @@ -7039,7 +7116,7 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, } #endif -log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len); + log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len); if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) { frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; @@ -7207,6 +7284,7 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, //We'll restore this size later on, so that it's transparent to client buffer->nFilledLen = 0; buffer->nAllocLen = handle->size; + drv_ctx.op_buf.buffer_size = handle->size; } nPortIndex = buffer - client_buffers.get_il_buf_hdr(); @@ -7952,6 +8030,42 @@ OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp, } if (!output_flush_progress && (buffer->nFilledLen > 0)) { + // set the default colorspace advised by client, since the bitstream may be + // devoid of colorspace-info. + if (m_enable_android_native_buffers) { + ColorSpace_t color_space = ITU_R_601; + + // Disabled ? + // WA for VP8. Vp8 encoder does not embed color-info (yet!). + // Encoding RGBA results in 601-LR for all resolutions. + // This conflicts with the client't defaults which are based on resolution. + // Eg: 720p will be encoded as 601-LR. Client will say 709. + // Re-enable this code once vp8 encoder generates color-info and hence the + // decoder will be able to override with the correct source color. +#if 0 + switch (m_client_color_space.sAspects.mPrimaries) { + case ColorAspects::PrimariesBT601_6_625: + case ColorAspects::PrimariesBT601_6_525: + { + color_space = m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ? + ITU_R_601_FR : ITU_R_601; + break; + } + case ColorAspects::PrimariesBT709_5: + { + color_space = ITU_R_709; + break; + } + default: + { + break; + } + } +#endif + DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)", + color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709); + set_colorspace_in_handle(color_space, buffer - m_out_mem_ptr); + } DEBUG_PRINT_LOW("Processing extradata"); handle_extradata(buffer); } @@ -9989,6 +10103,279 @@ void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp) } } +void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range, + OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects) +{ + switch (primaries) { + case MSM_VIDC_BT709_5: + *color_space = ITU_R_709; + aspects->mPrimaries = ColorAspects::PrimariesBT709_5; + break; + case MSM_VIDC_BT470_6_M: + aspects->mPrimaries = ColorAspects::PrimariesBT470_6M; + break; + case MSM_VIDC_BT601_6_625: + aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625; + break; + case MSM_VIDC_BT601_6_525: + *color_space = range ? ITU_R_601_FR : ITU_R_601; + aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525; + break; + case MSM_VIDC_GENERIC_FILM: + aspects->mPrimaries = ColorAspects::PrimariesGenericFilm; + break; + case MSM_VIDC_BT2020: + aspects->mPrimaries = ColorAspects::PrimariesBT2020; + break; + case MSM_VIDC_UNSPECIFIED: + //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default + default: + //aspects->mPrimaries = ColorAspects::PrimariesOther; + aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries; + break; + } + + aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited; + + switch (transfer) { + case MSM_VIDC_TRANSFER_BT709_5: + case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625: + aspects->mTransfer = ColorAspects::TransferSMPTE170M; + break; + case MSM_VIDC_TRANSFER_BT_470_6_M: + aspects->mTransfer = ColorAspects::TransferGamma22; + break; + case MSM_VIDC_TRANSFER_BT_470_6_BG: + aspects->mTransfer = ColorAspects::TransferGamma28; + break; + case MSM_VIDC_TRANSFER_SMPTE_240M: + aspects->mTransfer = ColorAspects::TransferSMPTE240M; + break; + case MSM_VIDC_TRANSFER_LINEAR: + aspects->mTransfer = ColorAspects::TransferLinear; + break; + case MSM_VIDC_TRANSFER_IEC_61966: + aspects->mTransfer = ColorAspects::TransferXvYCC; + break; + case MSM_VIDC_TRANSFER_BT_1361: + aspects->mTransfer = ColorAspects::TransferBT1361; + break; + case MSM_VIDC_TRANSFER_SRGB: + aspects->mTransfer = ColorAspects::TransferSRGB; + break; + default: + //aspects->mTransfer = ColorAspects::TransferOther; + aspects->mTransfer = m_client_color_space.sAspects.mTransfer; + break; + } + + switch (matrix) { + case MSM_VIDC_MATRIX_BT_709_5: + aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; + break; + case MSM_VIDC_MATRIX_FCC_47: + aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M; + break; + case MSM_VIDC_MATRIX_601_6_625: + case MSM_VIDC_MATRIX_601_6_525: + aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6; + break; + case MSM_VIDC_MATRIX_SMPTE_240M: + aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M; + break; + case MSM_VIDC_MATRIX_BT_2020: + aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020; + break; + case MSM_VIDC_MATRIX_BT_2020_CONST: + aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant; + break; + default: + //aspects->mMatrixCoeffs = ColorAspects::MatrixOther; + aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs; + break; + } +} + +void omx_vdec::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) { + DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d", + prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs); +} + +void omx_vdec::handle_color_space_info(void *data, unsigned int buf_index) +{ + ColorSpace_t color_space = ITU_R_601; + ColorAspects tempAspects; + memset(&tempAspects, 0x0, sizeof(ColorAspects)); + ColorAspects *aspects = &tempAspects; + + switch(output_capability) { + case V4L2_PIX_FMT_MPEG2: + { + struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload; + seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data; + + /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to + * understand this code */ + + if (seqdisp_payload && seqdisp_payload->color_descp) { + + convert_color_space_info(seqdisp_payload->color_primaries, 1, + seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs, + &color_space,aspects); + m_disp_hor_size = seqdisp_payload->disp_width; + m_disp_vert_size = seqdisp_payload->disp_height; + } + } + break; + case V4L2_PIX_FMT_H264: + case V4L2_PIX_FMT_HEVC: + { + struct msm_vidc_vui_display_info_payload *display_info_payload; + display_info_payload = (struct msm_vidc_vui_display_info_payload*)data; + + /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */ + + if (display_info_payload->video_signal_present_flag && + display_info_payload->color_description_present_flag) { + convert_color_space_info(display_info_payload->color_primaries, + display_info_payload->video_full_range_flag, + display_info_payload->transfer_characteristics, + display_info_payload->matrix_coefficients, + &color_space,aspects); + } + } + break; + case V4L2_PIX_FMT_VC1_ANNEX_G: + case V4L2_PIX_FMT_VC1_ANNEX_L: + { + struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload; + vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data; + + /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23 + * SMPTE 421M to understand this code */ + + if (m_enable_android_native_buffers && + vc1_seq_disp_payload->color_primaries) { + + convert_color_space_info(vc1_seq_disp_payload->color_primaries, + 1, + vc1_seq_disp_payload->transfer_char, + vc1_seq_disp_payload->matrix_coeffs, + &color_space,aspects); + } + } + break; + case V4L2_PIX_FMT_VP8: + { + struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload; + vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data; + + /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011 + * to understand this code */ + + if (vpx_color_space_payload->color_space == 0) { + color_space = ITU_R_601; + } else { + DEBUG_PRINT_ERROR("Unsupported Color space for VP8"); + break; + } + } + break; + case V4L2_PIX_FMT_VP9: + { + struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload; + vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data; + + /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016 + * to understand this code */ + + switch(vpx_color_space_payload->color_space) { + case MSM_VIDC_CS_BT_601: + aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6; + aspects->mTransfer = ColorAspects::TransferSMPTE170M; + aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625; + aspects->mRange = m_client_color_space.sAspects.mRange; + break; + case MSM_VIDC_CS_BT_709: + color_space = ITU_R_709; + aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; + aspects->mTransfer = ColorAspects::TransferSMPTE170M; + aspects->mPrimaries = ColorAspects::PrimariesBT709_5; + aspects->mRange = m_client_color_space.sAspects.mRange; + break; + case MSM_VIDC_CS_SMPTE_170: + aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; + aspects->mTransfer = ColorAspects::TransferSMPTE170M; + aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries; + aspects->mRange = m_client_color_space.sAspects.mRange; + break; + case MSM_VIDC_CS_SMPTE_240: + aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs; + aspects->mTransfer = ColorAspects::TransferSMPTE240M; + aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries; + aspects->mRange = m_client_color_space.sAspects.mRange; + break; + case MSM_VIDC_CS_BT_2020: + aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020; + aspects->mTransfer = ColorAspects:: TransferSMPTE170M; + aspects->mPrimaries = ColorAspects::PrimariesBT2020; + aspects->mRange = m_client_color_space.sAspects.mRange; + break; + case MSM_VIDC_CS_RESERVED: + aspects->mMatrixCoeffs = ColorAspects::MatrixOther; + aspects->mTransfer = ColorAspects::TransferOther; + aspects->mPrimaries = ColorAspects::PrimariesOther; + aspects->mRange = m_client_color_space.sAspects.mRange; + break; + case MSM_VIDC_CS_RGB: + aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5; + aspects->mTransfer = ColorAspects::TransferSMPTE170M; + aspects->mPrimaries = ColorAspects::PrimariesOther; + aspects->mRange = m_client_color_space.sAspects.mRange; + break; + default: + break; + } + } + break; + default: + break; + } + if (m_enable_android_native_buffers) { + DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709); + set_colorspace_in_handle(color_space, buf_index); + } + print_debug_color_aspects(aspects, "Bitstream"); + + if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries || + m_internal_color_space.sAspects.mTransfer != aspects->mTransfer || + m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs || + m_internal_color_space.sAspects.mRange != aspects->mRange) { + memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects)); + m_internal_color_space.bDataSpaceChanged = OMX_TRUE; + + DEBUG_PRINT_HIGH("Initiating PORT Reconfig"); + print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal"); + print_debug_color_aspects(&(m_client_color_space.sAspects), "Client"); + + post_event(OMX_CORE_OUTPUT_PORT_INDEX, + OMX_QTIIndexConfigDescribeColorAspects, + OMX_COMPONENT_GENERATE_PORT_RECONFIG); + } +} + +void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) { + private_handle_t *private_handle = NULL; + if (buf_index < drv_ctx.op_buf.actualcount && + buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS && + native_buffer[buf_index].privatehandle) { + private_handle = native_buffer[buf_index].privatehandle; + } + if (private_handle) { + setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space); + } +} + void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) { OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL; @@ -10052,7 +10439,7 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) return; } - DEBUG_PRINT_LOW("handle_extradata: eType = %d", data->eType); + DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType); switch ((unsigned long)data->eType) { case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO: struct msm_vidc_interlace_payload *payload; @@ -10163,12 +10550,10 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) } break; case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP: - struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload; - seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)(void *)data->data; - if (seqdisp_payload) { - m_disp_hor_size = seqdisp_payload->disp_width; - m_disp_vert_size = seqdisp_payload->disp_height; - } + case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO: + case MSM_VIDC_EXTRADATA_VC1_SEQDISP: + case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO: + handle_color_space_info((void *)data->data, buf_index); break; case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING: struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload; @@ -10365,6 +10750,33 @@ OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, } client_extradata |= OMX_QP_EXTRADATA; } + if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) { + control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; + switch(output_capability) { + case V4L2_PIX_FMT_H264: + case V4L2_PIX_FMT_HEVC: + control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY; + break; + case CODEC_TYPE_MPEG2: + control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP; + break; + case V4L2_PIX_FMT_VP8: + case V4L2_PIX_FMT_VP9: + control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE; + break; + case V4L2_PIX_FMT_VC1_ANNEX_G: + case V4L2_PIX_FMT_VC1_ANNEX_L: + control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP; + break; + default: + DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind); + return ret; + } + + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_HIGH("Failed to set Display info extradata"); + } + } } ret = get_buffer_req(&drv_ctx.op_buf); return ret; @@ -11812,3 +12224,105 @@ OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) { #endif //FLEXYUV_SUPPORTED } +void omx_vdec::prefetchNewBuffers() { + + struct v4l2_decoder_cmd dec; + uint32_t prefetch_count; + uint32_t prefetch_size; + uint32_t want_size; + uint32_t have_size; + int color_fmt, rc; + uint32_t new_calculated_size; + uint32_t new_buffer_size; + uint32_t new_buffer_count; + uint32_t old_buffer_size; + uint32_t old_buffer_count; + + memset((void *)&dec, 0 , sizeof(dec)); + DEBUG_PRINT_LOW("Old size : %d, count : %d, width : %u, height : %u\n", + (int)drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount, + drv_ctx.video_resolution.frame_width, + drv_ctx.video_resolution.frame_height); + dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT; + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) { + DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno); + } else { + DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n", + dec.raw.data[0], dec.raw.data[1]); + } + + switch ((int)drv_ctx.output_format) { + case VDEC_YUV_FORMAT_NV12: + color_fmt = COLOR_FMT_NV12; + break; + case VDEC_YUV_FORMAT_NV12_UBWC: + color_fmt = COLOR_FMT_NV12_UBWC; + break; + default: + color_fmt = -1; + } + + new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height); + DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n", + m_reconfig_width, m_reconfig_height, new_calculated_size); + new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size; + new_buffer_count = dec.raw.data[1]; + old_buffer_size = drv_ctx.op_buf.buffer_size; + old_buffer_count = drv_ctx.op_buf.actualcount; + + new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count; + + prefetch_count = new_buffer_count; + prefetch_size = new_buffer_size - old_buffer_size; + want_size = new_buffer_size * new_buffer_count; + have_size = old_buffer_size * old_buffer_count; + + if (want_size > have_size) { + DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size); + DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size); + + int ion_fd = open(MEM_DEVICE, O_RDONLY); + if (ion_fd < 0) { + DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd); + return; + } + + struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data)); + struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data)); + struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions)); + size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count); + + if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) { + DEBUG_PRINT_ERROR("prefetch data allocation failed"); + goto prefetch_exit; + } + + for (uint32_t i = 0; i < prefetch_count; i++) { + sizes[i] = prefetch_size; + } + + regions[0].nr_sizes = prefetch_count; + regions[0].sizes = sizes; + regions[0].vmid = ION_FLAG_CP_PIXEL; + + prefetch_data->nr_regions = 1; + prefetch_data->regions = regions; + prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID); + + custom_data->cmd = ION_IOC_PREFETCH; + custom_data->arg = (unsigned long )prefetch_data; + + rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data); + if (rc) { + DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno); + } + +prefetch_exit: + close(ion_fd); + free(sizes); + free(regions); + free(prefetch_data); + free(custom_data); + } +} + diff --git a/msm8996/mm-video-v4l2/vidc/venc/Android.mk b/msm8996/mm-video-v4l2/vidc/venc/Android.mk index d71e1eb..25e9601 100644 --- a/msm8996/mm-video-v4l2/vidc/venc/Android.mk +++ b/msm8996/mm-video-v4l2/vidc/venc/Android.mk @@ -89,6 +89,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(libmm-venc-add-dep) LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils \ libc2dcolorconvert libdl libgui +LOCAL_SHARED_LIBRARIES += libqdMetaData LOCAL_STATIC_LIBRARIES := libOmxVidcCommon LOCAL_SRC_FILES := src/omx_video_base.cpp diff --git a/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h b/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h index fd88eca..351c011 100644 --- a/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h +++ b/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h @@ -245,6 +245,8 @@ class omx_video: public qc_omx_component virtual bool dev_get_vqzip_sei_info(OMX_U32 *) = 0; virtual bool dev_get_peak_bitrate(OMX_U32 *) = 0; virtual bool dev_get_batch_size(OMX_U32 *) = 0; + virtual bool dev_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/, + OMX_U32 * /*nMaxBLayers*/) = 0; #ifdef _ANDROID_ICS_ void omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer); #endif @@ -561,6 +563,7 @@ class omx_video: public qc_omx_component void complete_pending_buffer_done_cbs(); bool is_conv_needed(int, int); + void print_debug_color_aspects(ColorAspects *aspects, const char *prefix); #ifdef USE_ION int alloc_map_ion_memory(int size, @@ -627,7 +630,7 @@ class omx_video: public qc_omx_component QOMX_VIDEO_HIERARCHICALLAYERS m_sHierLayers; OMX_QOMX_VIDEO_MBI_STATISTICS m_sMBIStatistics; QOMX_EXTNINDEX_VIDEO_INITIALQP m_sParamInitqp; - QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS m_sMaxHPlayers; + QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS m_sHPlayers; OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID m_sBaseLayerID; OMX_SKYPE_VIDEO_PARAM_DRIVERVER m_sDriverVer; OMX_SKYPE_VIDEO_CONFIG_QP m_sConfigQP; @@ -636,6 +639,9 @@ class omx_video: public qc_omx_component OMX_U32 m_sExtraData; OMX_U32 m_input_msg_id; OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE m_sConfigIntraRefresh; + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE m_sParamTemporalLayers; + OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE m_sConfigTemporalLayers; + DescribeColorAspectsParams m_sConfigColorAspects; // fill this buffer queue omx_cmd_queue m_ftb_q; diff --git a/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h b/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h index 8ccd678..7c51294 100644 --- a/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h +++ b/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h @@ -89,6 +89,8 @@ class omx_venc: public omx_video bool dev_get_vqzip_sei_info(OMX_U32 *); bool dev_get_peak_bitrate(OMX_U32 *); bool dev_get_batch_size(OMX_U32 *); + bool dev_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/, + OMX_U32 * /*nMaxBLayers*/); bool dev_is_video_session_supported(OMX_U32 width, OMX_U32 height); bool dev_color_align(OMX_BUFFERHEADERTYPE *buffer, OMX_U32 width, OMX_U32 height); diff --git a/msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h index ca97fc1..8ad2235 100644 --- a/msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h +++ b/msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h @@ -47,6 +47,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define TIMEOUT 5*60*1000 #define BIT(num) (1 << (num)) #define MAX_HYB_HIERP_LAYERS 6 +#define MAX_AVC_HP_LAYERS (4) #define MAX_V4L2_BUFS 64 //VB2_MAX_FRAME enum hier_type { @@ -237,6 +238,26 @@ struct msm_venc_hybrid_hp { unsigned int nHpLayers; }; +struct msm_venc_temporal_layers { + enum hier_type hier_mode; + OMX_U32 nMaxLayers; + OMX_U32 nMaxBLayers; + OMX_U32 nPLayers; + OMX_U32 nBLayers; + OMX_BOOL bIsBitrateRatioValid; + // cumulative ratio: eg [25, 50, 75, 100] means [L0=25%, L1=25%, L2=25%, L3=25%] + OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; + // Layerwise ratio: eg [L0=25%, L1=25%, L2=25%, L3=25%] + OMX_U32 nTemporalLayerBitrateFraction[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; +}; + +struct msm_venc_color_space { + OMX_U32 primaries; + OMX_U32 range; + OMX_U32 matrix_coeffs; + OMX_U32 transfer_chars; +}; + enum v4l2_ports { CAPTURE_PORT, OUTPUT_PORT, @@ -347,6 +368,8 @@ class venc_dev bool venc_get_vqzip_sei_info(OMX_U32 *enabled); bool venc_get_peak_bitrate(OMX_U32 *peakbitrate); bool venc_get_batch_size(OMX_U32 *size); + bool venc_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/, + OMX_U32 * /*nMaxBLayers*/); bool venc_get_output_log_flag(); bool venc_check_valid_config(); int venc_output_log_buffers(const char *buffer_addr, int buffer_len); @@ -415,6 +438,7 @@ class venc_dev bool hw_overload; bool is_gralloc_source_ubwc; bool is_camera_source_ubwc; + bool is_csc_enabled; OMX_U32 fd_list[64]; encExtradata mInputExtradata; encExtradata mOutputExtradata; @@ -455,8 +479,11 @@ class venc_dev OMX_U32 operating_rate; int rc_off_level; struct msm_venc_hybrid_hp hybrid_hp; + msm_venc_temporal_layers temporal_layers_config; + struct msm_venc_color_space color_space; bool venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel); + bool venc_set_intra_period_config(OMX_U32 nPFrames, OMX_U32 nBFrames); bool venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames); bool venc_set_target_bitrate(OMX_U32 nTargetBitrate, OMX_U32 config); bool venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate); @@ -499,15 +526,18 @@ class venc_dev bool venc_calibrate_gop(); bool venc_set_vqzip_defaults(); bool venc_validate_hybridhp_params(OMX_U32 layers, OMX_U32 bFrames, OMX_U32 count, int mode); - bool venc_set_max_hierp(OMX_U32 hierp_layers); + bool venc_set_hierp_layers(OMX_U32 hierp_layers); bool venc_set_baselayerid(OMX_U32 baseid); bool venc_set_qp(OMX_U32 nQp); bool venc_set_aspectratio(void *nSar); bool venc_set_priority(OMX_U32 priority); bool venc_set_session_priority(OMX_U32 priority); bool venc_set_operatingrate(OMX_U32 rate); - bool venc_set_layer_bitrates(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hpmode); + bool venc_set_layer_bitrates(OMX_U32 *pLayerBitrates, OMX_U32 numLayers); bool venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo); + OMX_ERRORTYPE venc_set_temporal_layers(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalParams); + OMX_ERRORTYPE venc_set_temporal_layers_internal(); + bool venc_set_colorspace(OMX_U32 primaries, OMX_U32 range, OMX_U32 transfer_chars, OMX_U32 matrix_coeffs); #ifdef MAX_RES_1080P OMX_U32 pmem_free(); diff --git a/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp index eeaf630..691ede8 100644 --- a/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp +++ b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp @@ -2068,6 +2068,19 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, memcpy(pParam, &m_sSar, sizeof(m_sSar)); break; } + case OMX_IndexParamAndroidVideoTemporalLayering: + { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE); + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pLayerInfo = + reinterpret_cast<OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE*>(paramData); + if (!dev_get_temporal_layer_caps(&m_sParamTemporalLayers.nLayerCountMax, + &m_sParamTemporalLayers.nBLayerCountMax)) { + DEBUG_PRINT_ERROR("Failed to get temporal layer capabilities"); + eRet = OMX_ErrorHardware; + } + memcpy(pLayerInfo, &m_sParamTemporalLayers, sizeof(m_sParamTemporalLayers)); + break; + } case OMX_IndexParamVideoSliceFMO: default: { @@ -2191,13 +2204,13 @@ OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, } break; } - case OMX_QcomIndexConfigMaxHierPLayers: + case OMX_QcomIndexConfigNumHierPLayers: { - VALIDATE_OMX_PARAM_DATA(configData, QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS); - QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS* pParam = - reinterpret_cast<QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS*>(configData); - DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigMaxHierPLayers"); - memcpy(pParam, &m_sMaxHPlayers, sizeof(m_sMaxHPlayers)); + VALIDATE_OMX_PARAM_DATA(configData, QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS); + QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS* pParam = + reinterpret_cast<QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS*>(configData); + DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigNumHierPLayers"); + memcpy(pParam, &m_sHPlayers, sizeof(m_sHPlayers)); break; } case OMX_QcomIndexConfigQp: @@ -2227,6 +2240,48 @@ OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, memcpy(pParam, &m_sConfigIntraRefresh, sizeof(m_sConfigIntraRefresh)); break; } + case OMX_IndexParamAndroidVideoTemporalLayering: + { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE); + OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *layerConfig = + (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *)configData; + DEBUG_PRINT_LOW("get_config: OMX_IndexConfigAndroidVideoTemporalLayering"); + memcpy(configData, &m_sConfigTemporalLayers, sizeof(m_sConfigTemporalLayers)); + break; + } + case OMX_QTIIndexConfigDescribeColorAspects: + { + VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams); + DescribeColorAspectsParams* pParam = + reinterpret_cast<DescribeColorAspectsParams*>(configData); + DEBUG_PRINT_LOW("get_config: OMX_QTIIndexConfigDescribeColorAspects"); + if (pParam->bRequestingDataSpace) { + DEBUG_PRINT_ERROR("Does not handle dataspace request"); + return OMX_ErrorUnsupportedSetting; + } + if (pParam->bDataSpaceChanged == OMX_TRUE) { + + print_debug_color_aspects(&(pParam->sAspects), "get_config (dataspace changed) Client says"); + // If the dataspace says RGB, recommend 601-limited; + // since that is the destination colorspace that C2D or Venus will convert to. + if (pParam->nPixelFormat == HAL_PIXEL_FORMAT_RGBA_8888) { + DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: Recommend 601-limited for RGBA8888"); + pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; + pParam->sAspects.mRange = ColorAspects::RangeLimited; + pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; + } else { + // For IMPLEMENTATION_DEFINED (or anything else), stick to client's defaults. + DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: use client-default for format=%x", + pParam->nPixelFormat); + } + print_debug_color_aspects(&(pParam->sAspects), "get_config (dataspace changed) recommended"); + } else { + memcpy(pParam, &m_sConfigColorAspects, sizeof(m_sConfigColorAspects)); + print_debug_color_aspects(&(pParam->sAspects), "get_config"); + } + break; + } default: DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); return OMX_ErrorUnsupportedIndex; @@ -2303,7 +2358,7 @@ OMX_ERRORTYPE omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, } if (extn_equals(paramName, "OMX.QCOM.index.config.video.hierplayers")) { - *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigMaxHierPLayers; + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigNumHierPLayers; return OMX_ErrorNone; } @@ -2331,11 +2386,16 @@ OMX_ERRORTYPE omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoEnableRoiInfo; return OMX_ErrorNone; } + if (extn_equals(paramName, OMX_QTI_INDEX_CONFIG_VIDEO_ROIINFO)) { *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigVideoRoiInfo; return OMX_ErrorNone; } + if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) { + *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects; + return OMX_ErrorNone; + } return OMX_ErrorNotImplemented; } @@ -4880,6 +4940,11 @@ bool omx_video::is_conv_needed(int hal_fmt, int hal_flags) return bRet; } +void omx_video::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) { + DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d", + prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs); +} + OMX_ERRORTYPE omx_video::empty_this_buffer_opaque(OMX_IN OMX_HANDLETYPE hComp, OMX_IN OMX_BUFFERHEADERTYPE* buffer) { diff --git a/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp index 2591dc6..c216eee 100644 --- a/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp +++ b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2016, 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: @@ -342,6 +342,13 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sConfigIntraRefresh.nPortIndex = (OMX_U32) PORT_INDEX_OUT; m_sConfigIntraRefresh.nRefreshPeriod = 0; + OMX_INIT_STRUCT(&m_sConfigColorAspects, DescribeColorAspectsParams); + m_sConfigColorAspects.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sConfigColorAspects.sAspects.mRange = ColorAspects::RangeUnspecified; + m_sConfigColorAspects.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified; + m_sConfigColorAspects.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified; + m_sConfigColorAspects.sAspects.mTransfer = ColorAspects::TransferUnspecified; + if (codec_type == OMX_VIDEO_CodingMPEG4) { m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple; m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_MPEG4Level0; @@ -544,6 +551,11 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sMBIStatistics.nPortIndex = (OMX_U32) PORT_INDEX_OUT; m_sMBIStatistics.eMBIStatisticsType = QOMX_MBI_STATISTICS_MODE_DEFAULT; + OMX_INIT_STRUCT(&m_sParamTemporalLayers, OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE); + m_sParamTemporalLayers.eSupportedPatterns = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + + OMX_INIT_STRUCT(&m_sConfigTemporalLayers, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE); + m_state = OMX_StateLoaded; m_sExtraData = 0; @@ -1626,6 +1638,26 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } break; } + case OMX_IndexParamAndroidVideoTemporalLayering: + { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE); + if (!handle->venc_set_param(paramData, + (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering)) { + DEBUG_PRINT_ERROR("Failed to configure temporal layers"); + return OMX_ErrorUnsupportedSetting; + } + // save the actual configuration applied + memcpy(&m_sParamTemporalLayers, paramData, sizeof(m_sParamTemporalLayers)); + // keep the config data in sync + m_sConfigTemporalLayers.ePattern = m_sParamTemporalLayers.ePattern; + m_sConfigTemporalLayers.nBLayerCountActual = m_sParamTemporalLayers.nBLayerCountActual; + m_sConfigTemporalLayers.nPLayerCountActual = m_sParamTemporalLayers.nPLayerCountActual; + m_sConfigTemporalLayers.bBitrateRatiosSpecified = m_sParamTemporalLayers.bBitrateRatiosSpecified; + memcpy(&m_sConfigTemporalLayers.nBitrateRatios[0], + &m_sParamTemporalLayers.nBitrateRatios[0], + OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS * sizeof(OMX_U32)); + break; + } case OMX_IndexParamVideoSliceFMO: default: { @@ -1984,16 +2016,16 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } break; } - case OMX_QcomIndexConfigMaxHierPLayers: + case OMX_QcomIndexConfigNumHierPLayers: { - VALIDATE_OMX_PARAM_DATA(configData, QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS); - QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS* pParam = - (QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS*)configData; - if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)OMX_QcomIndexConfigMaxHierPLayers)) { - DEBUG_PRINT_ERROR("ERROR: Setting OMX_QcomIndexConfigMaxHierPLayers failed"); + VALIDATE_OMX_PARAM_DATA(configData, QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS); + QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS* pParam = + (QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS*)configData; + if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)OMX_QcomIndexConfigNumHierPLayers)) { + DEBUG_PRINT_ERROR("ERROR: Setting OMX_QcomIndexConfigNumHierPLayers failed"); return OMX_ErrorUnsupportedSetting; } - memcpy(&m_sMaxHPlayers, pParam, sizeof(m_sMaxHPlayers)); + memcpy(&m_sHPlayers, pParam, sizeof(m_sHPlayers)); break; } case OMX_QcomIndexConfigBaseLayerId: @@ -2067,6 +2099,24 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } break; } + case OMX_IndexConfigAndroidVideoTemporalLayering: + { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE); + DEBUG_PRINT_ERROR("Setting/modifying Temporal layers at run-time is not supported !"); + return OMX_ErrorUnsupportedSetting; + } + case OMX_QTIIndexConfigDescribeColorAspects: + { + VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams); + DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData; + print_debug_color_aspects(&(params->sAspects), "set_config"); + if (!handle->venc_set_config(configData, (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects)) { + DEBUG_PRINT_ERROR("Failed to set OMX_QTIIndexConfigDescribeColorAspects"); + return OMX_ErrorUnsupportedSetting; + } + memcpy(&m_sConfigColorAspects, configData, sizeof(m_sConfigColorAspects)); + break; + } default: DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); break; @@ -2283,6 +2333,11 @@ bool omx_venc::dev_get_batch_size(OMX_U32 *size) #endif } +bool omx_venc::dev_get_temporal_layer_caps(OMX_U32 *nMaxLayers, + OMX_U32 *nMaxBLayers) { + return handle->venc_get_temporal_layer_caps(nMaxLayers, nMaxBLayers); +} + bool omx_venc::dev_loaded_start() { return handle->venc_loaded_start(); diff --git a/msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp index 3886230..76bd24a 100644 --- a/msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp +++ b/msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp @@ -47,6 +47,8 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <gralloc_priv.h> #endif +#include <qdMetaData.h> + #define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1)) #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0) #define MAXDPB 16 @@ -264,8 +266,10 @@ venc_dev::venc_dev(class omx_venc *venc_class):mInputExtradata(venc_class), mOut memset(<rinfo, 0, sizeof(ltrinfo)); memset(&fd_list, 0, sizeof(fd_list)); memset(&hybrid_hp, 0, sizeof(hybrid_hp)); - sess_priority.priority = 1; + sess_priority.priority = 1; //default to non-realtime operating_rate = 0; + memset(&temporal_layers_config, 0x0, sizeof(temporal_layers_config)); + memset(&color_space, 0x0, sizeof(color_space)); char property_value[PROPERTY_VALUE_MAX] = {0}; property_get("vidc.enc.log.in", property_value, "0"); @@ -291,6 +295,13 @@ venc_dev::venc_dev(class omx_venc *venc_class):mInputExtradata(venc_class), mOut is_gralloc_source_ubwc = 0; #endif + property_get("persist.vidc.enc.csc.enable", property_value, "0"); + if(!(strncmp(property_value, "1", PROPERTY_VALUE_MAX)) || + !(strncmp(property_value, "true", PROPERTY_VALUE_MAX))) { + is_csc_enabled = 1; + } else { + is_csc_enabled = 0; + } snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC); } @@ -1238,6 +1249,7 @@ bool venc_dev::venc_open(OMX_U32 codec) fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; fmt.fmt.pix_mp.pixelformat = V4L2_DEFAULT_OUTPUT_COLOR_FMT; + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt); m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage; @@ -1455,6 +1467,7 @@ bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count, fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat; + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt); m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage; bufreq.memory = V4L2_MEMORY_USERPTR; @@ -1614,6 +1627,7 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat; + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) { DEBUG_PRINT_ERROR("VIDIOC_S_FMT OUTPUT_MPLANE Failed"); @@ -1762,7 +1776,7 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) } } - if (!venc_set_intra_period (pParam->nPFrames,bFrames)) { + if (!venc_set_intra_period_config (pParam->nPFrames,bFrames)) { DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed"); return false; } @@ -1795,7 +1809,7 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) if (pParam->nBFrames) DEBUG_PRINT_ERROR("WARNING: B frame not supported for H.263"); - if (venc_set_intra_period (pParam->nPFrames, bFrames) == false) { + if (venc_set_intra_period_config (pParam->nPFrames, bFrames) == false) { DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed"); return false; } @@ -1836,7 +1850,7 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) } } - if (!venc_set_intra_period (pParam->nPFrames, bFrames)) { + if (!venc_set_intra_period_config (pParam->nPFrames, bFrames)) { DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed"); return false; } @@ -1905,7 +1919,9 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) if (!venc_set_inloop_filter(OMX_VIDEO_AVCLoopFilterEnable)) DEBUG_PRINT_HIGH("WARN: Request for setting Inloop filter failed for HEVC encoder"); - if (is_thulium_v1 && !venc_set_intra_period (0, 0)) { + OMX_U32 fps = m_sVenc_cfg.fps_num ? m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den : 30; + OMX_U32 nPFrames = pParam->nKeyFrameInterval > 0 ? pParam->nKeyFrameInterval - 1 : fps - 1; + if (!venc_set_intra_period (nPFrames, 0 /* nBFrames */)) { DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed"); return false; } @@ -2284,6 +2300,15 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) } break; } + case OMX_IndexParamAndroidVideoTemporalLayering: + { + if (venc_set_temporal_layers( + (OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE*)paramData) != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("set_param: Failed to configure temporal layers"); + return false; + } + break; + } case OMX_IndexParamVideoSliceFMO: default: DEBUG_PRINT_ERROR("ERROR: Unsupported parameter in venc_set_param: %u", @@ -2514,13 +2539,13 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) } break; } - case OMX_QcomIndexConfigMaxHierPLayers: + case OMX_QcomIndexConfigNumHierPLayers: { - QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS *pParam = - (QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS *) configData; - DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigMaxHierPLayers"); - if (venc_set_max_hierp(pParam->nMaxHierLayers) == false) { - DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigMaxHierPLayers"); + QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS *pParam = + (QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS *) configData; + DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigNumHierPLayers"); + if (venc_set_hierp_layers(pParam->nNumHierLayers) == false) { + DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigNumHierPLayers"); return false; } break; @@ -2535,6 +2560,11 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) } break; } + case OMX_IndexParamAndroidVideoTemporalLayering: + { + DEBUG_PRINT_ERROR("TemporalLayer: Changing layer-configuration dynamically is not supported!"); + return false; + } case OMX_QcomIndexConfigQp: { OMX_SKYPE_VIDEO_CONFIG_QP* pParam = @@ -2553,6 +2583,7 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) DEBUG_PRINT_ERROR("Failed to set priority"); return false; } + sess_priority.priority = priority->nU32; break; } case OMX_IndexConfigOperatingRate: @@ -2591,6 +2622,117 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) } break; } + case OMX_QTIIndexConfigDescribeColorAspects: + { + DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData; + + OMX_U32 color_space = MSM_VIDC_BT601_6_625; + OMX_U32 full_range = 0; + OMX_U32 matrix_coeffs = MSM_VIDC_MATRIX_601_6_625; + OMX_U32 transfer_chars = MSM_VIDC_TRANSFER_601_6_625; + + switch((ColorAspects::Primaries)(params->sAspects.mPrimaries)) { + case ColorAspects::PrimariesBT709_5: + color_space = MSM_VIDC_BT709_5; + break; + case ColorAspects::PrimariesBT470_6M: + color_space = MSM_VIDC_BT470_6_M; + break; + case ColorAspects::PrimariesBT601_6_625: + color_space = MSM_VIDC_BT601_6_625; + break; + case ColorAspects::PrimariesBT601_6_525: + color_space = MSM_VIDC_BT601_6_525; + break; + case ColorAspects::PrimariesGenericFilm: + color_space = MSM_VIDC_GENERIC_FILM; + break; + case ColorAspects::PrimariesBT2020: + color_space = MSM_VIDC_BT2020; + break; + default: + color_space = MSM_VIDC_BT601_6_625; + //params->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; + break; + } + switch((ColorAspects::Range)params->sAspects.mRange) { + case ColorAspects::RangeFull: + full_range = 1; + break; + case ColorAspects::RangeLimited: + full_range = 0; + break; + default: + break; + } + switch((ColorAspects::Transfer)params->sAspects.mTransfer) { + case ColorAspects::TransferSMPTE170M: + transfer_chars = MSM_VIDC_TRANSFER_601_6_525; + break; + case ColorAspects::TransferUnspecified: + transfer_chars = MSM_VIDC_TRANSFER_UNSPECIFIED; + break; + case ColorAspects::TransferGamma22: + transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_M; + break; + case ColorAspects::TransferGamma28: + transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_BG; + break; + case ColorAspects::TransferSMPTE240M: + transfer_chars = MSM_VIDC_TRANSFER_SMPTE_240M; + break; + case ColorAspects::TransferLinear: + transfer_chars = MSM_VIDC_TRANSFER_LINEAR; + break; + case ColorAspects::TransferXvYCC: + transfer_chars = MSM_VIDC_TRANSFER_IEC_61966; + break; + case ColorAspects::TransferBT1361: + transfer_chars = MSM_VIDC_TRANSFER_BT_1361; + break; + case ColorAspects::TransferSRGB: + transfer_chars = MSM_VIDC_TRANSFER_SRGB; + break; + default: + //params->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + transfer_chars = MSM_VIDC_TRANSFER_601_6_625; + break; + } + switch((ColorAspects::MatrixCoeffs)params->sAspects.mMatrixCoeffs) { + case ColorAspects::MatrixUnspecified: + matrix_coeffs = MSM_VIDC_MATRIX_UNSPECIFIED; + break; + case ColorAspects::MatrixBT709_5: + matrix_coeffs = MSM_VIDC_MATRIX_BT_709_5; + break; + case ColorAspects::MatrixBT470_6M: + matrix_coeffs = MSM_VIDC_MATRIX_FCC_47; + break; + case ColorAspects::MatrixBT601_6: + matrix_coeffs = MSM_VIDC_MATRIX_601_6_525; + break; + case ColorAspects::MatrixSMPTE240M: + transfer_chars = MSM_VIDC_MATRIX_SMPTE_240M; + break; + case ColorAspects::MatrixBT2020: + matrix_coeffs = MSM_VIDC_MATRIX_BT_2020; + break; + case ColorAspects::MatrixBT2020Constant: + matrix_coeffs = MSM_VIDC_MATRIX_BT_2020_CONST; + break; + default: + //params->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; + matrix_coeffs = MSM_VIDC_MATRIX_601_6_625; + break; + } + if (!venc_set_colorspace(color_space, full_range, + transfer_chars, matrix_coeffs)) { + + DEBUG_PRINT_ERROR("Failed to set operating rate"); + return false; + } + break; + } default: DEBUG_PRINT_ERROR("Unsupported config index = %u", index); break; @@ -2785,6 +2927,41 @@ unsigned venc_dev::venc_start(void) if (vqzip_sei_info.enabled && !venc_set_vqzip_defaults()) return 1; + // disable B-frames for realtime high-resolution/fps usecases for power considerations + if (intra_period.num_bframes && + sess_priority.priority == 0 /*realtime*/ && + (((m_sVenc_cfg.input_width * m_sVenc_cfg.input_height) > (1920 * 1088)) || + (operating_rate >= 60 << 16))) { + intra_period.num_pframes += (intra_period.num_bframes + 1); + intra_period.num_bframes = 0; + if (venc_set_intra_period(intra_period.num_pframes, intra_period.num_bframes)) { + DEBUG_PRINT_INFO("Disabling B frames: res = %lux%lu : operating-rate = %u frames/sec", + m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, operating_rate >> 16); + } else { + DEBUG_PRINT_ERROR("Failed to disable B frames!"); + } + } + + // re-configure the temporal layers as RC-mode and key-frame interval + // might have changed since the client last configured the layers. + if (temporal_layers_config.nPLayers) { + if (venc_set_temporal_layers_internal() != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("Re-configuring temporal layers failed !"); + } else { + // request buffers on capture port again since internal (scratch)- + // buffer requirements may change (i.e if we switch from non-hybrid + // to hybrid mode and vice-versa) + struct v4l2_requestbuffers bufreq; + + bufreq.memory = V4L2_MEMORY_USERPTR; + bufreq.count = m_sOutput_buff_property.actualcount; + bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + if (ioctl(m_nDriver_fd, VIDIOC_REQBUFS, &bufreq)) { + DEBUG_PRINT_ERROR("Request bufs failed while reconfiguring layers"); + } + } + } + venc_config_print(); if(resume_in_stopped){ @@ -2854,11 +3031,28 @@ inline const char* bitrate_type_string(int val) } } +static const char *codec_as_string(unsigned long codec) { + switch (codec) { + case V4L2_PIX_FMT_H264: + return "H264"; + case V4L2_PIX_FMT_MPEG4: + return "MPEG4"; + case V4L2_PIX_FMT_H263: + return "H263"; + case V4L2_PIX_FMT_HEVC: + return "HEVC"; + case V4L2_PIX_FMT_VP8: + return "VP8"; + default: + return "UNKOWN"; + } +} + void venc_dev::venc_config_print() { - DEBUG_PRINT_HIGH("ENC_CONFIG: Codec: %ld, Profile %ld, level : %ld", - m_sVenc_cfg.codectype, codec_profile.profile, profile_level.level); + DEBUG_PRINT_HIGH("ENC_CONFIG: Codec: %s, Profile %ld, level : %ld", + codec_as_string(m_sVenc_cfg.codectype), codec_profile.profile, profile_level.level); DEBUG_PRINT_HIGH("ENC_CONFIG: Input Width: %ld, Height:%ld, Fps: %ld", m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, @@ -2868,6 +3062,9 @@ void venc_dev::venc_config_print() m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height, m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den); + DEBUG_PRINT_HIGH("ENC_CONFIG: Color Space: Primaries = %u, Range = %u, Transfer Chars = %u, Matrix Coeffs = %u", + color_space.primaries, color_space.range, color_space.transfer_chars, color_space.matrix_coeffs); + DEBUG_PRINT_HIGH("ENC_CONFIG: Bitrate: %ld, RC: %ld, P - Frames : %ld, B - Frames = %ld", bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes, intra_period.num_bframes); @@ -2897,16 +3094,29 @@ void venc_dev::venc_config_print() DEBUG_PRINT_HIGH("ENC_CONFIG: LTR Enabled: %d, Count: %d", ltrinfo.enabled, ltrinfo.count); - DEBUG_PRINT_HIGH("ENC_CONFIG: Hier layers: %d, Hier Mode: %s VPX_ErrorResilience: %d", - hier_layers.numlayers, hiermode_string(hier_layers.hier_mode), vpx_err_resilience.enable); + if (temporal_layers_config.nPLayers) { + DEBUG_PRINT_HIGH("ENC_CONFIG: Temporal layers: P-layers: %u, B-layers: %u, Adjusted I-frame-interval: %lu", + temporal_layers_config.nPLayers, temporal_layers_config.nBLayers, + intra_period.num_pframes + intra_period.num_bframes + 1); - DEBUG_PRINT_HIGH("ENC_CONFIG: Hybrid_HP PARAMS: Layers: %d, Frame Interval : %d, MinQP: %d, Max_QP: %d", - hybrid_hp.nHpLayers, hybrid_hp.nKeyFrameInterval, hybrid_hp.nMinQuantizer, hybrid_hp.nMaxQuantizer); + for (OMX_U32 l = 0; temporal_layers_config.bIsBitrateRatioValid + && (l < temporal_layers_config.nPLayers + temporal_layers_config.nBLayers); ++l) { + DEBUG_PRINT_HIGH("ENC_CONFIG: Temporal layers: layer[%d] bitrate %% = %u%%", + l, temporal_layers_config.nTemporalLayerBitrateFraction[l]); + } + } else { + + DEBUG_PRINT_HIGH("ENC_CONFIG: Hier layers: %d, Hier Mode: %s VPX_ErrorResilience: %d", + hier_layers.numlayers, hiermode_string(hier_layers.hier_mode), vpx_err_resilience.enable); + + DEBUG_PRINT_HIGH("ENC_CONFIG: Hybrid_HP PARAMS: Layers: %d, Frame Interval : %d, MinQP: %d, Max_QP: %d", + hybrid_hp.nHpLayers, hybrid_hp.nKeyFrameInterval, hybrid_hp.nMinQuantizer, hybrid_hp.nMaxQuantizer); - DEBUG_PRINT_HIGH("ENC_CONFIG: Hybrid_HP PARAMS: Layer0: %d, Layer1: %d, Later2: %d, Layer3: %d, Layer4: %d, Layer5: %d", - hybrid_hp.nTemporalLayerBitrateRatio[0], hybrid_hp.nTemporalLayerBitrateRatio[1], - hybrid_hp.nTemporalLayerBitrateRatio[2], hybrid_hp.nTemporalLayerBitrateRatio[3], - hybrid_hp.nTemporalLayerBitrateRatio[4], hybrid_hp.nTemporalLayerBitrateRatio[5]); + DEBUG_PRINT_HIGH("ENC_CONFIG: Hybrid_HP PARAMS: Layer0: %d, Layer1: %d, Later2: %d, Layer3: %d, Layer4: %d, Layer5: %d", + hybrid_hp.nTemporalLayerBitrateRatio[0], hybrid_hp.nTemporalLayerBitrateRatio[1], + hybrid_hp.nTemporalLayerBitrateRatio[2], hybrid_hp.nTemporalLayerBitrateRatio[3], + hybrid_hp.nTemporalLayerBitrateRatio[4], hybrid_hp.nTemporalLayerBitrateRatio[5]); + } DEBUG_PRINT_HIGH("ENC_CONFIG: Performace level: %d", performance_level.perflevel); @@ -3235,6 +3445,23 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, struct v4l2_format fmt; memset(&fmt, 0, sizeof(fmt)); + if (usage & private_handle_t::PRIV_FLAGS_ITU_R_709 || + usage & private_handle_t::PRIV_FLAGS_ITU_R_601) { + DEBUG_PRINT_ERROR("Camera buffer color format is not 601_FR."); + DEBUG_PRINT_ERROR(" This leads to unknown color space"); + } + if (usage & private_handle_t::PRIV_FLAGS_ITU_R_601_FR) { + if (is_csc_enabled) { + buf.flags = V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP; + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709; + venc_set_colorspace(MSM_VIDC_BT709_5, 1, + MSM_VIDC_TRANSFER_BT709_5, MSM_VIDC_MATRIX_BT_709_5); + } else { + venc_set_colorspace(MSM_VIDC_BT601_6_525, 1, + MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525); + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; + } + } fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12; fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; @@ -3274,28 +3501,92 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, fd, plane[0].bytesused, plane[0].length, buf.flags, m_sVenc_cfg.inputformat); } else if (meta_buf->buffer_type == kMetadataBufferTypeGrallocSource) { private_handle_t *handle = (private_handle_t *)meta_buf->meta_handle; - if (!streaming[OUTPUT_PORT]) { + if (!streaming[OUTPUT_PORT] && handle) { + + // Moment of truth... actual colorspace is known here.. + ColorSpace_t colorSpace = ITU_R_601; + if (getMetaData(handle, GET_COLOR_SPACE, &colorSpace) == 0) { + DEBUG_PRINT_INFO("ENC_CONFIG: gralloc ColorSpace = %d (601=%d 601_FR=%d 709=%d)", + colorSpace, ITU_R_601, ITU_R_601_FR, ITU_R_709); + } + struct v4l2_format fmt; memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + bool isUBWC = (handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) && is_gralloc_source_ubwc; if (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE) { - if ((handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) && - is_gralloc_source_ubwc) { - m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC; - } else { - m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12; - } + m_sVenc_cfg.inputformat = isUBWC ? V4L2_PIX_FMT_NV12_UBWC : V4L2_PIX_FMT_NV12; + DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 %s", isUBWC ? "UBWC" : "Linear"); } else if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888) { - if ((handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) && - is_gralloc_source_ubwc) { - m_sVenc_cfg.inputformat = V4L2_PIX_FMT_RGBA8888_UBWC; + // In case of RGB, conversion to YUV is handled within encoder. + // Disregard the Colorspace in gralloc-handle in case of RGB and use + // [a] 601 for non-UBWC case : C2D output is (apparently) 601-LR + // [b] 601 for UBWC case : Venus can convert to 601-LR or FR. use LR for now. + colorSpace = ITU_R_601; + m_sVenc_cfg.inputformat = isUBWC ? V4L2_PIX_FMT_RGBA8888_UBWC : V4L2_PIX_FMT_RGB32; + DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = RGBA8888 %s", isUBWC ? "UBWC" : "Linear"); + } else if (handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) { + m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12; + DEBUG_PRINT_INFO("ENC_CONFIG: Input Color = NV12 Linear"); + } + + // If device recommendation (persist.vidc.enc.csc.enable) is to use 709, force CSC + if (colorSpace == ITU_R_601_FR && is_csc_enabled) { + struct v4l2_control control; + control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC; + control.value = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_ENABLE; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("venc_empty_buf: Failed to set VPE CSC for 601_to_709"); } else { - m_sVenc_cfg.inputformat = V4L2_PIX_FMT_RGB32; + DEBUG_PRINT_INFO("venc_empty_buf: Will convert 601-FR to 709"); + buf.flags = V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP; + colorSpace = ITU_R_709; + } + } + + msm_vidc_h264_color_primaries_values primary; + msm_vidc_h264_transfer_chars_values transfer; + msm_vidc_h264_matrix_coeff_values matrix; + OMX_U32 range; + + switch (colorSpace) { + case ITU_R_601_FR: + { + primary = MSM_VIDC_BT601_6_525; + range = 1; // full + transfer = MSM_VIDC_TRANSFER_601_6_525; + matrix = MSM_VIDC_MATRIX_601_6_525; + + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; + break; + } + case ITU_R_709: + { + primary = MSM_VIDC_BT709_5; + range = 0; // limited + transfer = MSM_VIDC_TRANSFER_BT709_5; + matrix = MSM_VIDC_MATRIX_BT_709_5; + + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709; + break; + } + default: + { + // 601 or something else ? assume 601 + primary = MSM_VIDC_BT601_6_625; + range = 0; //limited + transfer = MSM_VIDC_TRANSFER_601_6_625; + matrix = MSM_VIDC_MATRIX_601_6_625; + + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; + break; } - } else if ( handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) { - m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12; } + DEBUG_PRINT_INFO("ENC_CONFIG: selected ColorSpace = %d (601=%d 601_FR=%d 709=%d)", + colorSpace, ITU_R_601, ITU_R_601_FR, ITU_R_709); + venc_set_colorspace(primary, range, transfer, matrix); + fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat; fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; @@ -3735,6 +4026,13 @@ bool venc_dev::venc_set_hier_layers(QOMX_VIDEO_HIERARCHICALCODINGTYPE type, if (type == QOMX_HIERARCHICALCODING_P) { // Reduce layer count by 1 before sending to driver. This avoids // driver doing the same in multiple places. + control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS; + control.value = num_layers - 1; + DEBUG_PRINT_HIGH("Set MAX Hier P num layers: %u", (unsigned int)num_layers); + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Request to set MAX Hier P num layers failed"); + return false; + } control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS; control.value = num_layers - 1; DEBUG_PRINT_HIGH("Set Hier P num layers: %u", (unsigned int)num_layers); @@ -3884,6 +4182,78 @@ bool venc_dev::venc_enable_initial_qp(QOMX_EXTNINDEX_VIDEO_INITIALQP* initqp) return true; } +bool venc_dev::venc_set_colorspace(OMX_U32 primaries, OMX_U32 range, + OMX_U32 transfer_chars, OMX_U32 matrix_coeffs) +{ + int rc; + struct v4l2_control control; + + DEBUG_PRINT_LOW("Setting color space : Primaries = %d, Range = %d, Trans = %d, Matrix = %d", + primaries, range, transfer_chars, matrix_coeffs); + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE; + control.value = primaries; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE"); + return false; + } + + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value); + + color_space.primaries = control.value; + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE; + control.value = range; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE"); + return false; + } + + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value); + + color_space.range = control.value; + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS; + control.value = transfer_chars; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS"); + return false; + } + + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value); + + color_space.transfer_chars = control.value; + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS; + control.value = matrix_coeffs; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control : V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS"); + return false; + } + + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value); + + color_space.matrix_coeffs = control.value; + + return true; +} + bool venc_dev::venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp,OMX_U32 b_frame_qp) { int rc; @@ -4415,6 +4785,17 @@ bool venc_dev::venc_set_voptiming_cfg( OMX_U32 TimeIncRes) return true; } +bool venc_dev::venc_set_intra_period_config(OMX_U32 nPFrames, OMX_U32 nBFrames) { +#if _ANDROID_ + // Android defines nBFrames as number of Bs between I OR P + // Per the spec, nBFrames is number of Bs between I + OMX_U32 nBs = nBFrames * (nPFrames + 1); + DEBUG_PRINT_INFO("Updating Bframes from %u to %u", nBFrames, nBs); + nBFrames = nBs; +#endif //_ANDROID_ + return venc_set_intra_period(nPFrames, nBFrames); +} + bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) { @@ -4855,6 +5236,25 @@ bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate, OMX_U32 config) } } + // Configure layer-wise bitrate if temporal layers are enabled and layer-wise distribution + // has been specified + if (temporal_layers_config.bIsBitrateRatioValid && temporal_layers_config.nPLayers) { + OMX_U32 layerBitrates[OMX_VIDEO_MAX_HP_LAYERS] = {0}, + numLayers = temporal_layers_config.nPLayers + temporal_layers_config.nBLayers; + + DEBUG_PRINT_LOW("TemporalLayer: configuring layerwise bitrate"); + for (OMX_U32 i = 0; i < numLayers; ++i) { + layerBitrates[i] = + (temporal_layers_config.nTemporalLayerBitrateFraction[i] * bitrate.target_bitrate) / 100; + DEBUG_PRINT_LOW("TemporalLayer: layer[%u] ratio=%u%% bitrate=%u(of %ld)", + i, temporal_layers_config.nTemporalLayerBitrateFraction[i], + layerBitrates[i], bitrate.target_bitrate); + } + if (!venc_set_layer_bitrates((OMX_U32 *)layerBitrates, numLayers)) { + return false; + } + } + return true; } @@ -4893,18 +5293,22 @@ bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate, OMX_U32 confi bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format) { struct v4l2_format fmt; + int color_space = 0; DEBUG_PRINT_LOW("venc_set_color_format: color_format = %u ", color_format); switch ((int)color_format) { case OMX_COLOR_FormatYUV420SemiPlanar: case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m: m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12; + color_space = V4L2_COLORSPACE_470_SYSTEM_BG; break; case QOMX_COLOR_FormatYVU420SemiPlanar: m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV21; + color_space = V4L2_COLORSPACE_470_SYSTEM_BG; break; case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed: m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC; + color_space = V4L2_COLORSPACE_470_SYSTEM_BG; break; case QOMX_COLOR_Format32bitRGBA8888: m_sVenc_cfg.inputformat = V4L2_PIX_FMT_RGB32; @@ -4915,6 +5319,7 @@ bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format) default: DEBUG_PRINT_HIGH("WARNING: Unsupported Color format [%d]", color_format); m_sVenc_cfg.inputformat = V4L2_DEFAULT_OUTPUT_COLOR_FMT; + color_space = V4L2_COLORSPACE_470_SYSTEM_BG; DEBUG_PRINT_HIGH("Default color format NV12 UBWC is set"); break; } @@ -4922,6 +5327,7 @@ bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format) memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat; + fmt.fmt.pix_mp.colorspace = color_space; fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; @@ -4987,6 +5393,9 @@ bool venc_dev::venc_calibrate_gop() nPframes = intra_period.num_pframes; nBframes = intra_period.num_bframes; nLayers = hier_layers.numlayers; + if (temporal_layers_config.nPLayers) { + nLayers = temporal_layers_config.nPLayers + temporal_layers_config.nBLayers; + } if (!nPframes && nLayers) { DEBUG_PRINT_ERROR("nPframes should be non-zero when nLayers are present\n"); @@ -5071,10 +5480,10 @@ bool venc_dev::venc_set_bitrate_type(OMX_U32 type) return true; } -bool venc_dev::venc_set_layer_bitrates(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hpmode) +bool venc_dev::venc_set_layer_bitrates(OMX_U32 *layerBitrate, OMX_U32 numLayers) { DEBUG_PRINT_LOW("venc_set_layer_bitrates"); - struct v4l2_ext_control ctrl[MAX_HYB_HIERP_LAYERS]; + struct v4l2_ext_control ctrl[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; struct v4l2_ext_controls controls; int rc = 0; OMX_U32 i; @@ -5084,17 +5493,16 @@ bool venc_dev::venc_set_layer_bitrates(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hpmo return false; } - for (i = 0; i < hpmode->nHpLayers; i++) { - if (!hpmode->nTemporalLayerBitrateRatio[i]) { - DEBUG_PRINT_ERROR("invalid bitrate settings for layer %d\n", i); + for (OMX_U32 i = 0; i < numLayers && i < OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS; ++i) { + if (!layerBitrate[i]) { + DEBUG_PRINT_ERROR("Invalid bitrate settings for layer %d", i); return false; } else { ctrl[i].id = V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE; - ctrl[i].value = hpmode->nTemporalLayerBitrateRatio[i]; - hybrid_hp.nTemporalLayerBitrateRatio[i] = hpmode->nTemporalLayerBitrateRatio[i]; + ctrl[i].value = layerBitrate[i]; } } - controls.count = hpmode->nHpLayers; + controls.count = numLayers; controls.ctrl_class = V4L2_CTRL_CLASS_MPEG; controls.controls = ctrl; @@ -5104,13 +5512,7 @@ bool venc_dev::venc_set_layer_bitrates(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hpmo return false; } - hybrid_hp.nHpLayers = hpmode->nHpLayers; - - DEBUG_PRINT_LOW("Success in setting Layer wise bitrate: %d, %d, %d, %d, %d, %d", - hpmode->nTemporalLayerBitrateRatio[0],hpmode->nTemporalLayerBitrateRatio[1], - hpmode->nTemporalLayerBitrateRatio[2],hpmode->nTemporalLayerBitrateRatio[3], - hpmode->nTemporalLayerBitrateRatio[4],hpmode->nTemporalLayerBitrateRatio[5]); - + DEBUG_PRINT_LOW("Layerwise bitrate configured successfully"); return true; } @@ -5210,13 +5612,21 @@ bool venc_dev::venc_set_hybrid_hierp(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hhp) session_qp_values.maxqp = hhp->nMaxQuantizer; } - if (!venc_set_layer_bitrates(hhp)) { + OMX_U32 layerBitrates[OMX_VIDEO_MAX_HP_LAYERS] = {0}; + for (OMX_U32 i = 0; i < hhp->nHpLayers; i++) { + layerBitrates[i] = hhp->nTemporalLayerBitrateRatio[i]; + hybrid_hp.nTemporalLayerBitrateRatio[i] = hhp->nTemporalLayerBitrateRatio[i]; + DEBUG_PRINT_LOW("Setting Layer[%u] bitrate = %u", i, layerBitrates[i]); + } + if (!venc_set_layer_bitrates((OMX_U32 *)layerBitrates, hhp->nHpLayers)) { DEBUG_PRINT_ERROR("Failed to set Layer wise bitrate: %d, %d, %d, %d, %d, %d", hhp->nTemporalLayerBitrateRatio[0],hhp->nTemporalLayerBitrateRatio[1], hhp->nTemporalLayerBitrateRatio[2],hhp->nTemporalLayerBitrateRatio[3], hhp->nTemporalLayerBitrateRatio[4],hhp->nTemporalLayerBitrateRatio[5]); return false; } + hybrid_hp.nHpLayers = hhp->nHpLayers; + // Set this or else the layer0 bitrate will be overwritten by // default value in component m_sVenc_cfg.targetbitrate = bitrate.target_bitrate = hhp->nTemporalLayerBitrateRatio[0]; @@ -5504,6 +5914,7 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) rate_ctrl.rcmode = control.value; } +#ifdef _VQZIP_ if (eControlRate == OMX_Video_ControlRateVariable && (supported_rc_modes & RC_VBR_CFR) && m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { /* Enable VQZIP SEI by default for camcorder RC modes */ @@ -5515,6 +5926,7 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) DEBUG_PRINT_HIGH("Non-Fatal: Request to set VQZIP failed"); } } +#endif //_VQZIP_ return status; } @@ -5623,21 +6035,21 @@ bool venc_dev::venc_set_aspectratio(void *nSar) return true; } -bool venc_dev::venc_set_max_hierp(OMX_U32 hierp_layers) +bool venc_dev::venc_set_hierp_layers(OMX_U32 hierp_layers) { struct v4l2_control control; if (hierp_layers && (hier_layers.hier_mode == HIER_P) && (hierp_layers <= hier_layers.numlayers)) { - control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS; - control.value = hierp_layers; - DEBUG_PRINT_LOW("Going to set V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS"); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS; + control.value = hierp_layers - 1; + DEBUG_PRINT_LOW("Going to set V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS"); if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { - DEBUG_PRINT_ERROR("Failed to set MAX_HIERP_LAYERS"); + DEBUG_PRINT_ERROR("Failed to set HIERP_LAYERS"); return false; } return true; } else { - DEBUG_PRINT_ERROR("Invalid layers set for MAX_HIERP_LAYERS: %d", + DEBUG_PRINT_ERROR("Invalid layers set for HIERP_LAYERS: %d", hierp_layers); return false; } @@ -5813,6 +6225,227 @@ bool venc_dev::venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo) { return true; } +bool venc_dev::venc_get_temporal_layer_caps(OMX_U32 *nMaxLayers, + OMX_U32 *nMaxBLayers) { + + // no B-layers for all cases + temporal_layers_config.nMaxBLayers = 0; + temporal_layers_config.nMaxLayers = 1; + + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 + || m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { + temporal_layers_config.nMaxLayers = MAX_HYB_HIERP_LAYERS; // TODO: get this count from codec + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) { + temporal_layers_config.nMaxLayers = 4; // TODO: get this count from codec + } + + *nMaxLayers = temporal_layers_config.nMaxLayers; + *nMaxBLayers = temporal_layers_config.nMaxBLayers; + return true; +} + +OMX_ERRORTYPE venc_dev::venc_set_temporal_layers( + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalParams) { + + if (!(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 + || m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC + || m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8)) { + DEBUG_PRINT_ERROR("Temporal layers not supported for %s", codec_as_string(m_sVenc_cfg.codectype)); + return OMX_ErrorUnsupportedSetting; + } + + if (pTemporalParams->ePattern == OMX_VIDEO_AndroidTemporalLayeringPatternNone && + (pTemporalParams->nBLayerCountActual != 0 || + pTemporalParams->nPLayerCountActual != 1)) { + return OMX_ErrorBadParameter; + } else if (pTemporalParams->ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternAndroid || + pTemporalParams->nPLayerCountActual < 1) { + return OMX_ErrorBadParameter; + } + + if (pTemporalParams->nBLayerCountActual > temporal_layers_config.nMaxBLayers) { + DEBUG_PRINT_ERROR("TemporalLayer: Requested B-layers(%u) exceeds supported max(%u)", + pTemporalParams->nBLayerCountActual, temporal_layers_config.nMaxBLayers); + return OMX_ErrorBadParameter; + } else if (pTemporalParams->nPLayerCountActual > + temporal_layers_config.nMaxLayers - pTemporalParams->nBLayerCountActual) { + DEBUG_PRINT_ERROR("TemporalLayer: Requested layers(%u) exceeds supported max(%u)", + pTemporalParams->nPLayerCountActual + pTemporalParams->nBLayerCountActual, + temporal_layers_config.nMaxLayers); + return OMX_ErrorBadParameter; + } + + // For AVC, if B-layer has not been configured and RC mode is VBR (camcorder), + // use hybrid-HP for best results + bool isAvc = m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264; + bool isVBR = rate_ctrl.rcmode == RC_VBR_CFR || rate_ctrl.rcmode == RC_VBR_VFR; + bool bUseHybridMode = isAvc && pTemporalParams->nBLayerCountActual == 0 && isVBR; + + // If there are more than 3 layers configured for AVC, normal HP will not work. force hybrid + bUseHybridMode |= (isAvc && pTemporalParams->nPLayerCountActual > MAX_AVC_HP_LAYERS); + + DEBUG_PRINT_LOW("TemporalLayer: RC-mode = %ld : %s hybrid-HP", + rate_ctrl.rcmode, bUseHybridMode ? "enable" : "disable"); + + if (bUseHybridMode && + !venc_validate_hybridhp_params(pTemporalParams->nPLayerCountActual, + pTemporalParams->nBLayerCountActual, + 0 /* LTR count */, (int) HIER_P_HYBRID)) { + bUseHybridMode = false; + DEBUG_PRINT_ERROR("Failed to validate Hybrid HP. Will try fallback to normal HP"); + } + + if (intra_period.num_bframes) { + DEBUG_PRINT_ERROR("TemporalLayer: B frames are not supported with layers"); + return OMX_ErrorUnsupportedSetting; + } + + if (!venc_set_intra_period(intra_period.num_pframes, intra_period.num_bframes)) { + DEBUG_PRINT_ERROR("TemporalLayer : Failed to set Intra-period nP(%lu)/pB(%lu)", + intra_period.num_pframes, intra_period.num_bframes); + return OMX_ErrorUnsupportedSetting; + } + + struct v4l2_control control; + // Num enhancements layers does not include the base-layer + control.value = pTemporalParams->nPLayerCountActual - 1; + + if (bUseHybridMode) { + DEBUG_PRINT_LOW("TemporalLayer: Try enabling hybrid HP with %u layers", control.value); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + bUseHybridMode = false; + DEBUG_PRINT_ERROR("Failed to set hybrid HP"); + } else { + // Disable normal HP if Hybrid mode is being enabled + control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS; + control.value = 0; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set max HP layers to %u", control.value); + return OMX_ErrorUnsupportedSetting; + } + control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS; + control.value = 0; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set HP layers to %u", control.value); + return OMX_ErrorUnsupportedSetting; + } + } + } + + if (!bUseHybridMode) { + + // in case of normal HP, avc encoder cannot support more than MAX_AVC_HP_LAYERS + if (isAvc && pTemporalParams->nPLayerCountActual > MAX_AVC_HP_LAYERS) { + DEBUG_PRINT_ERROR("AVC supports only up to %d layers", MAX_AVC_HP_LAYERS); + return OMX_ErrorUnsupportedSetting; + } + + DEBUG_PRINT_LOW("TemporalLayer: Try enabling HP with %u layers", control.value); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set hybrid hierp/hierp"); + return OMX_ErrorUnsupportedSetting; + } + + // configure max layers for a session.. Okay to use current num-layers as max + // since we do not plan to support dynamic changes to number of layers + control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS; + control.value = pTemporalParams->nPLayerCountActual - 1; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set max HP layers to %u", control.value); + return OMX_ErrorUnsupportedSetting; + + } else if (temporal_layers_config.hier_mode == HIER_P_HYBRID) { + // Disable hybrid mode if it was enabled already + DEBUG_PRINT_LOW("TemporalLayer: disable hybrid HP (normal-HP preferred)"); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE; + control.value = 0; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to disable hybrid HP !"); + return OMX_ErrorUnsupportedSetting; + } + } + } + + // SVC-NALs to indicate layer-id in case of H264 needs explicit enablement.. + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { + DEBUG_PRINT_LOW("TemporalLayer: Enable H264_SVC_NAL"); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC; + control.value = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_ENABLED; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to enable SVC_NAL"); + return OMX_ErrorUnsupportedSetting; + } + } + + temporal_layers_config.hier_mode = bUseHybridMode ? HIER_P_HYBRID : HIER_P; + temporal_layers_config.nPLayers = pTemporalParams->nPLayerCountActual; + temporal_layers_config.nBLayers = 0; + + temporal_layers_config.bIsBitrateRatioValid = OMX_FALSE; + if (pTemporalParams->bBitrateRatiosSpecified == OMX_FALSE) { + DEBUG_PRINT_LOW("TemporalLayer: layerwise bitrate ratio not specified. Will use cumulative.."); + return OMX_ErrorNone; + } + DEBUG_PRINT_LOW("TemporalLayer: layerwise bitrate ratio specified"); + + OMX_U32 layerBitrates[OMX_VIDEO_MAX_HP_LAYERS] = {0}, + numLayers = pTemporalParams->nPLayerCountActual + pTemporalParams->nBLayerCountActual; + + OMX_U32 i = 0; + for (; i < numLayers; ++i) { + OMX_U32 previousLayersAccumulatedBitrateRatio = i == 0 ? 0 : pTemporalParams->nBitrateRatios[i-1]; + OMX_U32 currentLayerBitrateRatio = pTemporalParams->nBitrateRatios[i] - previousLayersAccumulatedBitrateRatio; + if (previousLayersAccumulatedBitrateRatio > pTemporalParams->nBitrateRatios[i]) { + DEBUG_PRINT_ERROR("invalid bitrate ratio for layer %d.. Will fallback to cumulative", i); + return OMX_ErrorBadParameter; + } else { + layerBitrates[i] = (currentLayerBitrateRatio * bitrate.target_bitrate) / 100; + temporal_layers_config.nTemporalLayerBitrateRatio[i] = pTemporalParams->nBitrateRatios[i]; + temporal_layers_config.nTemporalLayerBitrateFraction[i] = currentLayerBitrateRatio; + DEBUG_PRINT_LOW("TemporalLayer: layer[%u] ratio=%u%% bitrate=%u(of %ld)", + i, currentLayerBitrateRatio, layerBitrates[i], bitrate.target_bitrate); + } + } + + temporal_layers_config.bIsBitrateRatioValid = OMX_TRUE; + + // Setting layerwise bitrate makes sense only if target bitrate is configured, else defer until later.. + if (bitrate.target_bitrate > 0) { + if (!venc_set_layer_bitrates((OMX_U32 *)layerBitrates, numLayers)) { + return OMX_ErrorUnsupportedSetting; + } + } else { + DEBUG_PRINT_HIGH("Defer setting layerwise bitrate since target bitrate is not yet set"); + } + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE venc_dev::venc_set_temporal_layers_internal() { + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE pTemporalParams; + memset(&pTemporalParams, 0x0, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE)); + + if (!temporal_layers_config.nPLayers) { + return OMX_ErrorNone; + } + pTemporalParams.eSupportedPatterns = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + pTemporalParams.nLayerCountMax = temporal_layers_config.nMaxLayers; + pTemporalParams.nBLayerCountMax = temporal_layers_config.nMaxBLayers; + pTemporalParams.ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + pTemporalParams.nPLayerCountActual = temporal_layers_config.nPLayers; + pTemporalParams.nBLayerCountActual = temporal_layers_config.nBLayers; + pTemporalParams.bBitrateRatiosSpecified = temporal_layers_config.bIsBitrateRatioValid; + if (temporal_layers_config.bIsBitrateRatioValid == OMX_TRUE) { + for (OMX_U32 i = 0; i < temporal_layers_config.nPLayers + temporal_layers_config.nBLayers; ++i) { + pTemporalParams.nBitrateRatios[i] = + temporal_layers_config.nTemporalLayerBitrateRatio[i]; + } + } + return venc_set_temporal_layers(&pTemporalParams); +} + bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel) { bool status = true; |