summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--msm8974/mm-core/inc/OMX_VideoExt.h1
-rw-r--r--msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp6
-rw-r--r--msm8996/libc2dcolorconvert/Android.mk2
-rw-r--r--msm8996/mm-core/inc/OMX_IndexExt.h2
-rw-r--r--msm8996/mm-core/inc/OMX_QCOMExtns.h32
-rw-r--r--msm8996/mm-core/inc/OMX_VideoExt.h90
-rw-r--r--msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h20
-rw-r--r--msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp542
-rw-r--r--msm8996/mm-video-v4l2/vidc/venc/Android.mk1
-rw-r--r--msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h8
-rw-r--r--msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h2
-rw-r--r--msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h34
-rw-r--r--msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp79
-rw-r--r--msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp71
-rw-r--r--msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp747
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(&ltrinfo, 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;