summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbdulla Anam <abdullahanam@codeaurora.org>2015-10-29 16:34:58 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2015-10-31 09:00:23 -0700
commite7743ae1dabe2cd417a9aa5af3d6ed9aac464784 (patch)
tree78a28630a5175314671b6a78735d3d870e45ee5e
parent183f4b16fcd13d3f2eb09cb0d991c64a82ba46d8 (diff)
downloadandroid_hardware_qcom_media-e7743ae1dabe2cd417a9aa5af3d6ed9aac464784.tar.gz
android_hardware_qcom_media-e7743ae1dabe2cd417a9aa5af3d6ed9aac464784.tar.bz2
android_hardware_qcom_media-e7743ae1dabe2cd417a9aa5af3d6ed9aac464784.zip
mm-video-v4l2: venc: Add support to enhance hybrid Hier-p mode
This mode updates configuring the hybrid Hier-p mode in encoder by configuring hier-p layers, min/maxQP, layer wise bitrate. Change-Id: Ife02f0e9bef742c4a8a0e14280445f88382b0c20
-rw-r--r--mm-core/inc/OMX_QCOMExtns.h10
-rw-r--r--mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h16
-rw-r--r--mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp18
-rw-r--r--mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp183
4 files changed, 187 insertions, 40 deletions
diff --git a/mm-core/inc/OMX_QCOMExtns.h b/mm-core/inc/OMX_QCOMExtns.h
index 749594e3..8a46ce21 100644
--- a/mm-core/inc/OMX_QCOMExtns.h
+++ b/mm-core/inc/OMX_QCOMExtns.h
@@ -46,6 +46,7 @@ extern "C" {
#include "OMX_Core.h"
#include "OMX_Video.h"
+#define OMX_VIDEO_MAX_HP_LAYERS 6
/**
* This extension is used to register mapping of a virtual
* address to a physical address. This extension is a parameter
@@ -582,14 +583,23 @@ typedef struct QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS {
*
* nSize : Size of Structure in bytes
* nVersion : OpenMAX IL specification version information
+* nKeyFrameInterval : Indicates the I frame interval
* nHpLayers : Set the number of Hier-p layers for the session
* - This should be <= 6. (1 Base layer +
* 5 Enhancement layers)
+* nTemporalLayerBitrateRatio[OMX_VIDEO_MAX_HP_LAYERS] : Bitrate to
+* be set for each enhancement layer
+* nMinQuantizer : minimum session QP
+* nMaxQuantizer : Maximun session QP
*/
typedef struct QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE {
OMX_U32 nSize;
OMX_VERSIONTYPE nVersion;
+ OMX_U32 nKeyFrameInterval;
+ OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_MAX_HP_LAYERS];
+ OMX_U32 nMinQuantizer;
+ OMX_U32 nMaxQuantizer;
OMX_U32 nHpLayers;
} QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE;
diff --git a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
index 71554b0f..b669bfc1 100644
--- a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
+++ b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
@@ -228,6 +228,15 @@ struct msm_venc_low_latency {
unsigned int enable;
};
+struct msm_venc_hybrid_hp {
+ unsigned int nSize;
+ unsigned int nKeyFrameInterval;
+ unsigned int nTemporalLayerBitrateRatio[OMX_VIDEO_MAX_HP_LAYERS];
+ unsigned int nMinQuantizer;
+ unsigned int nMaxQuantizer;
+ unsigned int nHpLayers;
+};
+
enum v4l2_ports {
CAPTURE_PORT,
OUTPUT_PORT,
@@ -304,11 +313,12 @@ class venc_dev
bool venc_get_vui_timing_info(OMX_U32 *enabled);
bool venc_get_peak_bitrate(OMX_U32 *peakbitrate);
bool venc_get_output_log_flag();
+ bool venc_check_valid_config();
int venc_output_log_buffers(const char *buffer_addr, int buffer_len);
int venc_input_log_buffers(OMX_BUFFERHEADERTYPE *buffer, int fd, int plane_offset);
int venc_extradata_log_buffers(char *buffer_addr);
bool venc_enable_low_latency();
-
+ bool venc_set_bitrate_type(OMX_U32 type);
struct venc_debug_cap m_debug;
OMX_U32 m_nDriver_fd;
bool m_profile_set;
@@ -375,6 +385,7 @@ class venc_dev
struct msm_venc_priority sess_priority;
OMX_U32 operating_rate;
struct msm_venc_low_latency low_latency;
+ struct msm_venc_hybrid_hp hybrid_hp;
bool venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel);
bool venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames);
@@ -413,7 +424,7 @@ class venc_dev
bool venc_set_vpx_error_resilience(OMX_BOOL enable);
bool venc_set_perf_mode(OMX_U32 mode);
bool venc_set_mbi_statistics_mode(OMX_U32 mode);
- bool venc_set_hybrid_hierp(OMX_U32 layers);
+ bool venc_set_hybrid_hierp(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hhp);
bool venc_calibrate_gop();
bool venc_validate_hybridhp_params(OMX_U32 layers, OMX_U32 bFrames, OMX_U32 count, int mode);
bool venc_set_session_priority(OMX_U32 priority);
@@ -421,6 +432,7 @@ class venc_dev
bool venc_set_max_hierp(OMX_U32 hierp_layers);
bool venc_set_lowlatency_mode(OMX_BOOL enable);
void venc_clip_luma_chroma(int fd, OMX_U32 offset, OMX_U32 size);
+ bool venc_set_layer_bitrates(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hpmode);
#ifdef MAX_RES_1080P
OMX_U32 pmem_free();
diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
index c1fe8560..af20444f 100644
--- a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
+++ b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
@@ -54,7 +54,6 @@ extern int m_pipe;
static int bframes;
static int entropy;
static int perfmode;
-static int hybrid_hp;
static int lowlatency;
// factory function executed by the core to create instances
@@ -163,13 +162,9 @@ omx_venc::omx_venc()
property_get("vidc.debug.perf.mode", property_value, "0");
perfmode = atoi(property_value);
property_value[0] = '\0';
- property_get("vidc.debug.hybrid.hierp", property_value, "0");
- hybrid_hp = atoi(property_value);
- property_value[0] = '\0';
property_get("vidc.debug.lowlatency", property_value, "0");
lowlatency = atoi(property_value);
property_value[0] = '\0';
-
m_perf_control.send_hint_to_mpctl(true);
DEBUG_PRINT_HIGH("omx_venc: constructor completed");
}
@@ -600,19 +595,6 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role)
DEBUG_PRINT_ERROR("Failed setting PerfMode to %d", pParam.nPerfMode);
}
- if (hybrid_hp)
- {
- if (hybrid_hp <= MAX_HYB_HIERP_LAYERS) {
- QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE hyb_hp;
- hyb_hp.nHpLayers = hybrid_hp;
- DEBUG_PRINT_LOW("hybrid_hp = 0x%x", hyb_hp.nHpLayers);
- if (!handle->venc_set_param(&hyb_hp, (OMX_INDEXTYPE)OMX_QcomIndexParamVideoHybridHierpMode)) {
- DEBUG_PRINT_ERROR("Failed setting hybrid_hp to %d", hyb_hp.nHpLayers);
- }
- } else {
- DEBUG_PRINT_ERROR("Max hybrid_hp layers supported is %d", hybrid_hp);
- }
- }
if (lowlatency)
{
diff --git a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
index 5a3e0246..3060a26e 100644
--- a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
+++ b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
@@ -221,6 +221,7 @@ venc_dev::venc_dev(class omx_venc *venc_class)
venc_handle = venc_class;
etb = ebd = ftb = fbd = 0;
+ struct v4l2_control control;
for (i = 0; i < MAX_PORT; i++)
streaming[i] = false;
@@ -263,6 +264,7 @@ venc_dev::venc_dev(class omx_venc *venc_class)
enable_mv_narrow_searchrange = false;
supported_rc_modes = RC_ALL;
memset(&ltrinfo, 0, sizeof(ltrinfo));
+ memset(&hybrid_hp, 0, sizeof(hybrid_hp));
sess_priority.priority = 1;
operating_rate = 0;
format_set = false;
@@ -2025,12 +2027,9 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index)
}
case OMX_QcomIndexParamVideoHybridHierpMode:
{
- QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* pParam =
- (QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE*)paramData;
-
- if (!venc_set_hybrid_hierp(pParam->nHpLayers)) {
+ if (!venc_set_hybrid_hierp((QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE*)paramData)) {
DEBUG_PRINT_ERROR("Setting hybrid Hier-P mode failed");
- return OMX_ErrorUnsupportedSetting;
+ return false;
}
break;
}
@@ -2055,11 +2054,29 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index)
return true;
}
+bool venc_dev::venc_check_valid_config()
+{
+ if (streaming[OUTPUT_PORT] && streaming[CAPTURE_PORT] &&
+ ((m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 && hier_layers.hier_mode == HIER_P_HYBRID) ||
+ (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC && hier_layers.hier_mode == HIER_P))) {
+ DEBUG_PRINT_ERROR("venc_set_config not allowed run time for following usecases");
+ DEBUG_PRINT_ERROR("For H264 : When Hybrid Hier P enabled");
+ DEBUG_PRINT_ERROR("For H265 : When Hier P enabled");
+ return false;
+ }
+ return true;
+}
+
bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index)
{
DEBUG_PRINT_LOW("Inside venc_set_config");
+ if(!venc_check_valid_config()) {
+ DEBUG_PRINT_ERROR("venc_set_config not allowed for this configuration");
+ return false;
+ }
+
switch ((int)index) {
case OMX_IndexConfigVideoBitrate:
{
@@ -2480,6 +2497,19 @@ inline const char* hiermode_string(int val)
}
}
+inline const char* bitrate_type_string(int val)
+{
+ switch(val)
+ {
+ case V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_DISABLE:
+ return "CUMULATIVE";
+ case V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_ENABLE:
+ return "LAYER WISE";
+ default:
+ return "Unknown Bitrate Type";
+ }
+}
+
void venc_dev::venc_config_print()
{
@@ -2526,6 +2556,14 @@ void venc_dev::venc_config_print()
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);
DEBUG_PRINT_HIGH("ENC_CONFIG: VUI timing info enabled: %d", vui_timing_info.enabled);
@@ -4360,24 +4398,89 @@ bool venc_dev::venc_calibrate_gop()
return true;
}
-bool venc_dev::venc_set_hybrid_hierp(OMX_U32 layers)
+bool venc_dev::venc_set_bitrate_type(OMX_U32 type)
{
- DEBUG_PRINT_LOW("venc_set_hybrid_hierp layers: %u", layers);
+ struct v4l2_control control;
+ int rc = 0;
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_TYPE;
+ control.value = type;
+ DEBUG_PRINT_LOW("Set Bitrate type to %s for %d \n", bitrate_type_string(type), type);
+ rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Request to set Bitrate type to %s failed",
+ bitrate_type_string(type));
+ return false;
+ }
+ return true;
+}
+
+bool venc_dev::venc_set_layer_bitrates(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hpmode)
+{
+ DEBUG_PRINT_LOW("venc_set_layer_bitrates");
+ struct v4l2_ext_control ctrl[MAX_HYB_HIERP_LAYERS];
+ struct v4l2_ext_controls controls;
+ int rc = 0;
+ OMX_U32 i;
+
+ if (!venc_set_bitrate_type(V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_ENABLE)) {
+ DEBUG_PRINT_ERROR("Failed to set layerwise bitrate type %d", rc);
+ return false;
+ }
+
+ for (i = 0; i < hpmode->nHpLayers; i++) {
+ if (!hpmode->nTemporalLayerBitrateRatio[i]) {
+ DEBUG_PRINT_ERROR("invalid bitrate settings for layer %d\n", 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];
+ }
+ }
+ controls.count = MAX_HYB_HIERP_LAYERS;
+ controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
+ controls.controls = ctrl;
+
+ rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Failed to set layerwise bitrate %d", rc);
+ return false;
+ }
+
+ 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]);
+
+ return true;
+}
+
+bool venc_dev::venc_set_hybrid_hierp(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hhp)
+{
+ DEBUG_PRINT_LOW("venc_set_hybrid_hierp layers");
struct v4l2_control control;
int rc;
- if (!venc_validate_hybridhp_params(layers, 0, 0, (int) HIER_P_HYBRID)) {
+ if (!venc_validate_hybridhp_params(hhp->nHpLayers, 0, 0, (int) HIER_P_HYBRID)) {
DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes");
return false;
}
- if (!layers || layers > MAX_HYB_HIERP_LAYERS) {
- DEBUG_PRINT_ERROR("Invalid numbers of layers set: %d (max supported is 6)", layers);
+ if (!hhp->nHpLayers || hhp->nHpLayers > MAX_HYB_HIERP_LAYERS) {
+ DEBUG_PRINT_ERROR("Invalid numbers of layers set: %d (max supported is 6)", hhp->nHpLayers);
return false;
}
+ if (!venc_set_intra_period(hhp->nKeyFrameInterval, 0)) {
+ DEBUG_PRINT_ERROR("Failed to set Intraperiod: %d", hhp->nKeyFrameInterval);
+ return false;
+ }
- hier_layers.numlayers = layers;
- hier_layers.hier_mode = HIER_P_HYBRID;
+ hier_layers.numlayers = hhp->nHpLayers;
+ if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
+ hier_layers.hier_mode = HIER_P_HYBRID;
+ } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ hier_layers.hier_mode = HIER_P;
+ }
if (venc_calibrate_gop()) {
// Update the driver with the new nPframes and nBframes
control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
@@ -4401,27 +4504,67 @@ bool venc_dev::venc_set_hybrid_hierp(OMX_U32 layers)
DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes");
return false;
}
-
- control.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE;
- control.value = layers - 1;
+ if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE;
+ } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS;
+ }
+ control.value = hhp->nHpLayers - 1;
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d",
control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
- DEBUG_PRINT_ERROR("Failed to set hybrid hierp %d", rc);
+ DEBUG_PRINT_ERROR("Failed to set hybrid hierp/hierp %d", rc);
return false;
}
DEBUG_PRINT_LOW("SUCCESS IOCTL set control for id=%x, val=%d",
control.id, control.value);
- 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");
+ if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
+ 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 false;
+ }
+ } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS;
+ control.value = hhp->nHpLayers - 1;
+ if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_ERROR("Failed to enable SVC_NAL");
+ return false;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("Failed : Unsupported codec for Hybrid Hier P : %d", m_sVenc_cfg.codectype);
return false;
}
+
+ if(venc_set_session_qp_range (hhp->nMinQuantizer,
+ hhp->nMaxQuantizer) == false) {
+ DEBUG_PRINT_ERROR("ERROR: Setting QP Range for hybridHP [%u %u] failed",
+ (unsigned int)hhp->nMinQuantizer, (unsigned int)hhp->nMaxQuantizer);
+ return false;
+ } else {
+ session_qp_values.minqp = hhp->nMinQuantizer;
+ session_qp_values.maxqp = hhp->nMaxQuantizer;
+ }
+
+ if (!venc_set_layer_bitrates(hhp)) {
+ 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;
+ }
+ // 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];
+ hybrid_hp.nHpLayers = hhp->nHpLayers;
+ hybrid_hp.nKeyFrameInterval = hhp->nKeyFrameInterval;
+ hybrid_hp.nMaxQuantizer = hhp->nMaxQuantizer;
+ hybrid_hp.nMinQuantizer = hhp->nMinQuantizer;
return true;
}