diff options
author | Abdulla Anam <abdullahanam@codeaurora.org> | 2015-10-29 16:34:58 +0530 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2015-10-31 09:00:23 -0700 |
commit | e7743ae1dabe2cd417a9aa5af3d6ed9aac464784 (patch) | |
tree | 78a28630a5175314671b6a78735d3d870e45ee5e | |
parent | 183f4b16fcd13d3f2eb09cb0d991c64a82ba46d8 (diff) | |
download | android_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.h | 10 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h | 16 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp | 18 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp | 183 |
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(<rinfo, 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; } |