media: Update to AU 205 drop
Update to AU_LINUX_ANDROID_LA.HB.1.3.9.06.00.01.213.205
media_hal:
1df75f0 Merge "mm-video-v4l2: venc: Avoid processing ETBs/FTBs in invalid states"
dc623d6 mm-video-v4l2: vdec: Avoid processing ETBs/FTBs in invalid states,
d57cbc1 mm-video-v4l2: venc: Avoid processing ETBs/FTBs in invalid states
2b33b5a Merge "mm-video-v4l2: venc: add support for encoding temporal layers"
815b4be mm-video-v4l2: venc: add support for encoding temporal layers
d450628 mm-video-v4l2: vidc: venc: Fix issues with Hier P
a7ead0c mm-video-v4l2: vidc: Enumerate supported HEVC decoder profiles
9e096e8 mm-video-v4l2: vidc: HEVC Main10 profile support
a42a61d mm-video-v4l2: vdec: Add support for prefetching secure memory
Change-Id: I16f46e6d896e296cb2cf3eab6e6683c93f9daa8c
diff --git a/msm8996/mm-core/inc/OMX_IndexExt.h b/msm8996/mm-core/inc/OMX_IndexExt.h
index 09e3b5b..3e1dcfd 100644
--- a/msm8996/mm-core/inc/OMX_IndexExt.h
+++ b/msm8996/mm-core/inc/OMX_IndexExt.h
@@ -73,6 +73,8 @@
OMX_IndexParamVideoHevc, /**< reference: OMX_VIDEO_PARAM_HEVCTYPE */
OMX_IndexParamSliceSegments, /**< reference: OMX_VIDEO_SLICESEGMENTSTYPE */
OMX_IndexConfigAndroidIntraRefresh, /**< reference: OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE */
+ OMX_IndexParamAndroidVideoTemporalLayers, /**< reference: OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE */
+ OMX_IndexConfigAndroidVideoTemporalLayers, /**< reference: OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERTYPE */
/* 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 00a532e..ad88a8f 100644
--- a/msm8996/mm-core/inc/OMX_QCOMExtns.h
+++ b/msm8996/mm-core/inc/OMX_QCOMExtns.h
@@ -512,7 +512,7 @@
/* "OMX.QCOM.index.param.video.InputBatch" */
OMX_QcomIndexParamBatchSize = 0x7F00004A,
- OMX_QcomIndexConfigMaxHierPLayers = 0x7F00004B,
+ OMX_QcomIndexConfigNumHierPLayers = 0x7F00004B,
OMX_QcomIndexConfigRectType = 0x7F00004C,
@@ -582,16 +582,16 @@
*
* 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;
/**
@@ -1601,7 +1601,6 @@
#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"
@@ -1614,7 +1613,7 @@
#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..31ab510 100644
--- a/msm8996/mm-core/inc/OMX_VideoExt.h
+++ b/msm8996/mm-core/inc/OMX_VideoExt.h
@@ -173,6 +173,68 @@
OMX_U32 nRefreshPeriod;
} OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE;
+/** Maximum number of temporal layers supported by AVC/HEVC */
+#define OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS 8
+
+/**
+ * Android specific param for configuration of temporal layering
+ *
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nTemporalLayerCountMax : Max number of temporal coding layers supported
+ * by the encoder
+ * nTemporalBLayerCountMax : Max number of layers that can contain B frames
+ * (0 to nTemporalLayerCountMax)
+ * nTemporalPLayerCountActual : Number of temporal layers to be coded with non-B frames,
+ * starting from and including the base-layer.
+ * (1 to nTemporalLayerCountMax - nTemporalBLayerCountActual)
+ * nTemporalBLayerCountActual : Number of temporal layers to be coded with B frames,
+ * starting after non-B layers.
+ * (0 to nTemporalBLayerCountMax)
+ * bTemporalLayerBitrateRatioSpecified : Flag to indicate if layer-wise bitrate
+ * distribution is specified.
+ * nTemporalLayerBitrateRatio : Bitrate ratio (100 based) per layer. Honored if
+ * bTemporalLayerBitrateRatioSpecified is set.
+ * i.e for 4 layers with desired distribution (25% 25% 25% 25%),
+ * BitrateRatio = {25, 50, 75, 100, 100, 100, 100, 100}
+*/
+typedef struct OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nTemporalLayerCountMax;
+ OMX_U32 nTemporalBLayerCountMax;
+ OMX_U32 nTemporalPLayerCountActual;
+ OMX_U32 nTemporalBLayerCountActual;
+ OMX_BOOL bTemporalLayerBitrateRatioSpecified;
+ OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS];
+} OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE;
+
+/**
+ * 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
+ * nTemporalPLayerCountActual : Number of temporal layers to be coded with non-B frames,
+ * nTemporalBLayerCountActual : Number of temporal layers to be coded with B frames,
+ * bTemporalLayerBitrateRatioSpecified : Flag to indicate if layer-wise bitrate
+ * distribution is specified.
+ * nTemporalLayerBitrateRatio : Bitrate ratio (100 based) per layer. Honored if
+ * bTemporalLayerBitrateRatioSpecified is set.
+ */
+typedef struct OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nTemporalPLayerCountActual;
+ OMX_U32 nTemporalBLayerCountActual;
+ OMX_BOOL bTemporalLayerBitrateRatioSpecified;
+ OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS];
+} OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERTYPE;
+
#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 037bba3..a5e9647 100644
--- a/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -1155,6 +1155,7 @@
}
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 05eb885..24b4ae9 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
@@ -1664,6 +1664,10 @@
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) ?
@@ -3351,6 +3355,9 @@
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);
@@ -7174,6 +7181,7 @@
//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();
@@ -11779,3 +11787,105 @@
#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/inc/omx_video_base.h b/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
index fd88eca..43fc43e 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 @@
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
@@ -627,7 +629,7 @@
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 +638,8 @@
OMX_U32 m_sExtraData;
OMX_U32 m_input_msg_id;
OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE m_sConfigIntraRefresh;
+ OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE m_sParamTemporalLayers;
+ OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERTYPE m_sConfigTemporalLayers;
// 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 @@
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..d4cd92c 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 @@
#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,19 @@
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];
+};
+
enum v4l2_ports {
CAPTURE_PORT,
OUTPUT_PORT,
@@ -347,6 +361,8 @@
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);
@@ -455,6 +471,7 @@
OMX_U32 operating_rate;
int rc_off_level;
struct msm_venc_hybrid_hp hybrid_hp;
+ msm_venc_temporal_layers temporal_layers_config;
bool venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel);
bool venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames);
@@ -499,16 +516,17 @@
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_TEMPORALLAYERTYPE *pTemporalParams);
+ OMX_ERRORTYPE venc_set_temporal_layers_internal();
#ifdef MAX_RES_1080P
OMX_U32 pmem_free();
OMX_U32 pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count);
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 fcaaa99..b95fabd 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 @@
memcpy(pParam, &m_sSar, sizeof(m_sSar));
break;
}
+ case OMX_IndexParamAndroidVideoTemporalLayers:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE);
+ OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE *pLayerInfo =
+ reinterpret_cast<OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE*>(paramData);
+ if (!dev_get_temporal_layer_caps(&m_sParamTemporalLayers.nTemporalLayerCountMax,
+ &m_sParamTemporalLayers.nTemporalBLayerCountMax)) {
+ 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 @@
}
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,16 @@
memcpy(pParam, &m_sConfigIntraRefresh, sizeof(m_sConfigIntraRefresh));
break;
}
+ case OMX_IndexConfigAndroidVideoTemporalLayers:
+ {
+ VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERTYPE);
+ OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERTYPE *layerConfig =
+ (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERTYPE *)configData;
+ DEBUG_PRINT_LOW("get_config: OMX_IndexConfigAndroidVideoTemporalLayers");
+ memcpy(configData, &m_sConfigTemporalLayers, sizeof(m_sConfigTemporalLayers));
+ break;
+ }
+
default:
DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
return OMX_ErrorUnsupportedIndex;
@@ -2303,7 +2326,7 @@
}
if (extn_equals(paramName, "OMX.QCOM.index.config.video.hierplayers")) {
- *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigMaxHierPLayers;
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigNumHierPLayers;
return OMX_ErrorNone;
}
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 fb9ec59..b023bbd 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:
@@ -544,6 +544,9 @@
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_TEMPORALLAYERTYPE);
+ OMX_INIT_STRUCT(&m_sConfigTemporalLayers, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERTYPE);
+
m_state = OMX_StateLoaded;
m_sExtraData = 0;
@@ -1613,6 +1616,25 @@
}
break;
}
+ case OMX_IndexParamAndroidVideoTemporalLayers:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE);
+ if (!handle->venc_set_param(paramData,
+ (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayers)) {
+ 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.nTemporalBLayerCountActual = m_sParamTemporalLayers.nTemporalBLayerCountActual;
+ m_sConfigTemporalLayers.nTemporalPLayerCountActual = m_sParamTemporalLayers.nTemporalPLayerCountActual;
+ m_sConfigTemporalLayers.bTemporalLayerBitrateRatioSpecified = m_sParamTemporalLayers.bTemporalLayerBitrateRatioSpecified;
+ memcpy(&m_sConfigTemporalLayers.nTemporalLayerBitrateRatio[0],
+ &m_sParamTemporalLayers.nTemporalLayerBitrateRatio[0],
+ OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS * sizeof(OMX_U32));
+ break;
+ }
case OMX_IndexParamVideoSliceFMO:
default:
{
@@ -1971,16 +1993,16 @@
}
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:
@@ -2054,6 +2076,12 @@
}
break;
}
+ case OMX_IndexConfigAndroidVideoTemporalLayers:
+ {
+ VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERTYPE);
+ DEBUG_PRINT_ERROR("Setting/modifying Temporal layers at run-time is not supported !");
+ return OMX_ErrorUnsupportedSetting;
+ }
default:
DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
break;
@@ -2270,6 +2298,11 @@
#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 c5ca471..ff47ab7 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
@@ -266,6 +266,7 @@
memset(&hybrid_hp, 0, sizeof(hybrid_hp));
sess_priority.priority = 1;
operating_rate = 0;
+ memset(&temporal_layers_config, 0x0, sizeof(temporal_layers_config));
char property_value[PROPERTY_VALUE_MAX] = {0};
property_get("vidc.enc.log.in", property_value, "0");
@@ -2284,6 +2285,15 @@
}
break;
}
+ case OMX_IndexParamAndroidVideoTemporalLayers:
+ {
+ if (venc_set_temporal_layers(
+ (OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE*)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 +2524,13 @@
}
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 +2545,11 @@
}
break;
}
+ case OMX_IndexParamAndroidVideoTemporalLayers:
+ {
+ DEBUG_PRINT_ERROR("TemporalLayer: Changing layer-configuration dynamically is not supported!");
+ return false;
+ }
case OMX_QcomIndexConfigQp:
{
OMX_SKYPE_VIDEO_CONFIG_QP* pParam =
@@ -2785,6 +2800,26 @@
if (vqzip_sei_info.enabled && !venc_set_vqzip_defaults())
return 1;
+ // 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 +2889,28 @@
}
}
+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,
@@ -2897,16 +2949,29 @@
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: 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: 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: Performace level: %d", performance_level.perflevel);
@@ -3735,6 +3800,13 @@
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);
@@ -4855,6 +4927,25 @@
}
}
+ // 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;
}
@@ -4987,6 +5078,9 @@
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 +5165,10 @@
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 +5178,16 @@
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 +5197,7 @@
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 +5297,21 @@
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];
@@ -5625,21 +5720,21 @@
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;
}
@@ -5815,6 +5910,216 @@
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_TEMPORALLAYERTYPE *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->nTemporalBLayerCountActual > temporal_layers_config.nMaxBLayers) {
+ DEBUG_PRINT_ERROR("TemporalLayer: Requested B-layers(%u) exceeds supported max(%u)",
+ pTemporalParams->nTemporalBLayerCountActual, temporal_layers_config.nMaxBLayers);
+ return OMX_ErrorBadParameter;
+ } else if (pTemporalParams->nTemporalPLayerCountActual + pTemporalParams->nTemporalBLayerCountActual >
+ temporal_layers_config.nMaxLayers) {
+ DEBUG_PRINT_ERROR("TemporalLayer: Requested layers(%u) exceeds supported max(%u)",
+ pTemporalParams->nTemporalPLayerCountActual + pTemporalParams->nTemporalBLayerCountActual,
+ 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->nTemporalBLayerCountActual == 0 && isVBR;
+
+ // If there are more than 3 layers configured for AVC, normal HP will not work. force hybrid
+ bUseHybridMode |= (isAvc && pTemporalParams->nTemporalPLayerCountActual > 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->nTemporalPLayerCountActual,
+ pTemporalParams->nTemporalBLayerCountActual,
+ 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->nTemporalPLayerCountActual - 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->nTemporalPLayerCountActual > 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->nTemporalPLayerCountActual - 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->nTemporalPLayerCountActual;
+ temporal_layers_config.nBLayers = 0;
+
+ temporal_layers_config.bIsBitrateRatioValid = OMX_FALSE;
+ if (pTemporalParams->bTemporalLayerBitrateRatioSpecified == 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->nTemporalPLayerCountActual + pTemporalParams->nTemporalBLayerCountActual;
+
+ OMX_U32 i = 0;
+ for (; i < numLayers; ++i) {
+ OMX_U32 previousLayersAccumulatedBitrateRatio = i == 0 ? 0 : pTemporalParams->nTemporalLayerBitrateRatio[i-1];
+ OMX_U32 currentLayerBitrateRatio = pTemporalParams->nTemporalLayerBitrateRatio[i] - previousLayersAccumulatedBitrateRatio;
+ if (previousLayersAccumulatedBitrateRatio > pTemporalParams->nTemporalLayerBitrateRatio[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->nTemporalLayerBitrateRatio[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_TEMPORALLAYERTYPE pTemporalParams;
+ memset(&pTemporalParams, 0x0, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERTYPE));
+
+ if (!temporal_layers_config.nPLayers) {
+ return OMX_ErrorNone;
+ }
+ pTemporalParams.nTemporalLayerCountMax = temporal_layers_config.nMaxLayers;
+ pTemporalParams.nTemporalBLayerCountActual = temporal_layers_config.nMaxBLayers;
+ pTemporalParams.nTemporalPLayerCountActual = temporal_layers_config.nPLayers;
+ pTemporalParams.nTemporalBLayerCountActual = temporal_layers_config.nBLayers;
+ pTemporalParams.bTemporalLayerBitrateRatioSpecified = 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.nTemporalLayerBitrateRatio[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;