diff options
author | Praveen Chavan <pchavan@codeaurora.org> | 2016-03-30 00:19:58 -0700 |
---|---|---|
committer | Lajos Molnar <lajos@google.com> | 2016-08-25 11:01:00 -0700 |
commit | 03783f82008b7447073e0da4550da02bdc2286cf (patch) | |
tree | 5dd97f92baa30476a11c9dff90e25c861d92d1b4 /msm8974 | |
parent | bfdb1adb7ea840c4c0a9e0c9ad8ebc0ecd43919a (diff) | |
download | media-03783f82008b7447073e0da4550da02bdc2286cf.tar.gz |
mm-video-v4l2: venc: add support for encoding with temporal layers
Implement OMX_IndexParamAndroidVideoTemporalLayers to expose
configuration of temporal-layered encoding to client.
Layer-wise bitrate support and changing layer-count dynamically
is not supported.
Bug: 27596987
Change-Id: Ib32e7aea22e2cbaf78a903561b67de7d14ed57e5
Diffstat (limited to 'msm8974')
8 files changed, 315 insertions, 2 deletions
diff --git a/msm8974/mm-core/inc/OMX_IndexExt.h b/msm8974/mm-core/inc/OMX_IndexExt.h index 3f278ba..c584c08 100644 --- a/msm8974/mm-core/inc/OMX_IndexExt.h +++ b/msm8974/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/msm8974/mm-core/inc/OMX_VideoExt.h b/msm8974/mm-core/inc/OMX_VideoExt.h index 30fe514..9ea4828 100644 --- a/msm8974/mm-core/inc/OMX_VideoExt.h +++ b/msm8974/mm-core/inc/OMX_VideoExt.h @@ -174,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/msm8974/mm-video-v4l2/vidc/venc/inc/omx_video_base.h b/msm8974/mm-video-v4l2/vidc/venc/inc/omx_video_base.h index 5916582..e75bfcb 100644 --- a/msm8974/mm-video-v4l2/vidc/venc/inc/omx_video_base.h +++ b/msm8974/mm-video-v4l2/vidc/venc/inc/omx_video_base.h @@ -240,6 +240,8 @@ class omx_video: public qc_omx_component virtual bool dev_get_performance_level(OMX_U32 *) = 0; virtual bool dev_get_vui_timing_info(OMX_U32 *) = 0; virtual bool dev_get_peak_bitrate(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 @@ -616,6 +618,8 @@ class omx_video: public qc_omx_component OMX_VIDEO_VP8REFERENCEFRAMETYPE m_sConfigVp8ReferenceFrame; QOMX_VIDEO_HIERARCHICALLAYERS m_sHierLayers; QOMX_EXTNINDEX_VIDEO_INITIALQP m_sParamInitqp; + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE m_sParamTemporalLayers; + OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE m_sConfigTemporalLayers; OMX_U32 m_sExtraData; OMX_U32 m_input_msg_id; OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE m_sConfigIntraRefresh; diff --git a/msm8974/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h b/msm8974/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h index d7b21db..73a5d33 100644 --- a/msm8974/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h +++ b/msm8974/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h @@ -87,6 +87,8 @@ class omx_venc: public omx_video bool dev_get_performance_level(OMX_U32 *); bool dev_get_vui_timing_info(OMX_U32 *); bool dev_get_peak_bitrate(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/msm8974/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/msm8974/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h index e2bdaf7..94d68ee 100644 --- a/msm8974/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h +++ b/msm8974/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h @@ -219,6 +219,16 @@ struct msm_venc_priority { OMX_U32 priority; }; +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; + OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; +}; + enum v4l2_ports { CAPTURE_PORT, OUTPUT_PORT, @@ -288,6 +298,8 @@ class venc_dev bool venc_get_performance_level(OMX_U32 *perflevel); bool venc_get_vui_timing_info(OMX_U32 *enabled); bool venc_get_peak_bitrate(OMX_U32 *peakbitrate); + bool venc_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/, + OMX_U32 * /*nMaxBLayers*/); bool venc_get_output_log_flag(); 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); @@ -358,6 +370,7 @@ class venc_dev struct msm_venc_vpx_error_resilience vpx_err_resilience; struct msm_venc_priority sess_priority; OMX_U32 operating_rate; + 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); @@ -400,6 +413,8 @@ class venc_dev bool venc_validate_hybridhp_params(OMX_U32 layers, OMX_U32 bFrames, OMX_U32 count, int mode); bool venc_set_session_priority(OMX_U32 priority); bool venc_set_operatingrate(OMX_U32 rate); + OMX_ERRORTYPE venc_set_temporal_layers(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalParams); + OMX_ERRORTYPE venc_set_temporal_layers_internal(); #ifdef MAX_RES_1080P OMX_U32 pmem_free(); diff --git a/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp index 6e7e05a..9c71157 100644 --- a/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp +++ b/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp @@ -1910,6 +1910,19 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, memcpy(initqp, &m_sParamInitqp, sizeof(m_sParamInitqp)); 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: { @@ -2042,6 +2055,14 @@ 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; + memcpy(configData, &m_sConfigTemporalLayers, sizeof(m_sConfigTemporalLayers)); + break; + } default: DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); return OMX_ErrorUnsupportedIndex; diff --git a/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp index 33a147b..1da8627 100644 --- a/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp +++ b/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp @@ -470,6 +470,13 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sHierLayers.nNumLayers = 0; m_sHierLayers.eHierarchicalCodingType = QOMX_HIERARCHICALCODING_P; + memset(&m_sParamTemporalLayers, 0x0, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE)); + OMX_INIT_STRUCT(&m_sParamTemporalLayers, OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE); + m_sParamTemporalLayers.eSupportedPatterns = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + + memset(&m_sConfigTemporalLayers, 0x0, sizeof(OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE)); + OMX_INIT_STRUCT(&m_sConfigTemporalLayers, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE); + m_state = OMX_StateLoaded; m_sExtraData = 0; @@ -1477,6 +1484,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: { @@ -2074,6 +2101,11 @@ bool omx_venc::dev_get_peak_bitrate(OMX_U32 *peakbitrate) #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/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 cd3ba9f..cc8d6ae 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 @@ -255,6 +255,7 @@ venc_dev::venc_dev(class omx_venc *venc_class) memset(<rinfo, 0, sizeof(ltrinfo)); 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"); @@ -1913,6 +1914,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", @@ -2163,6 +2173,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; + } default: DEBUG_PRINT_ERROR("Unsupported config index = %u", index); break; @@ -2300,6 +2315,26 @@ unsigned venc_dev::venc_start(void) __func__, codec_profile.profile, profile_level.level); } + // 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){ @@ -2398,8 +2433,16 @@ 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 (hier_layers.numlayers) { + 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_INFO("ENC_CONFIG: Temporal layers: P-layers: %u, B-layers: %u, Adjusted I-frame-interval: %u", + temporal_layers_config.nPLayers, temporal_layers_config.nBLayers, + intra_period.num_pframes + intra_period.num_bframes + 1); + } DEBUG_PRINT_HIGH("ENC_CONFIG: Performace level: %d", performance_level.perflevel); @@ -4790,6 +4833,111 @@ bool venc_dev::venc_set_operatingrate(OMX_U32 rate) { return true; } +bool venc_dev::venc_get_temporal_layer_caps(OMX_U32 *nMaxLayers, + OMX_U32 *nMaxBLayers) { + temporal_layers_config.nMaxLayers = MAX_HYB_HIERP_LAYERS; // TODO: get this count from codec + temporal_layers_config.nMaxBLayers = 0; + + *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 %ld", 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 + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264 && + pTemporalParams->nBLayerCountActual == 0 && + (rate_ctrl.rcmode == RC_VBR_CFR || rate_ctrl.rcmode == RC_VBR_VFR)) { + if (!venc_set_hybrid_hierp(pTemporalParams->nPLayerCountActual)) { + DEBUG_PRINT_ERROR("Failed to enable (hybrid) Hier-P with %u layers", + pTemporalParams->nPLayerCountActual); + return OMX_ErrorUnsupportedSetting; + } + temporal_layers_config.hier_mode = HIER_P_HYBRID; + temporal_layers_config.nPLayers = pTemporalParams->nPLayerCountActual; + temporal_layers_config.nBLayers = 0; + + // we ignore layer-size bitrate request for this mode + temporal_layers_config.bIsBitrateRatioValid = OMX_FALSE; + pTemporalParams->bBitrateRatiosSpecified = OMX_FALSE; + + } else { + if (pTemporalParams->nBLayerCountActual == 0) { + if (!venc_set_hier_layers(QOMX_HIERARCHICALCODING_P, pTemporalParams->nPLayerCountActual)) { + DEBUG_PRINT_ERROR("Failed to enable Hier-P with %u layers", + pTemporalParams->nPLayerCountActual); + return OMX_ErrorUnsupportedSetting; + } + temporal_layers_config.hier_mode = HIER_P; + temporal_layers_config.nPLayers = pTemporalParams->nPLayerCountActual; + temporal_layers_config.nBLayers = 0; + + // TODO: handle layer-wise bitrate request. For now, disregard the setting + temporal_layers_config.bIsBitrateRatioValid = OMX_FALSE; + pTemporalParams->bBitrateRatiosSpecified = OMX_FALSE; + + } else { + // we do not support B-frames with enhancement layers for now + } + } + + 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; |