blob: ef55daadce622077599d2a1b8acc81ab6f75586a [file] [log] [blame]
/*--------------------------------------------------------------------------
Copyright (c) 2010-2019, 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:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------*/
#include "video_encoder_device_v4l2.h"
#include "omx_video_encoder.h"
#undef LOG_TAG
#define LOG_TAG "OMX-VENC: venc_dev"
void venc_dev::venc_get_consumer_usage(OMX_U32* usage)
{
OMX_U32 eProfile = 0;
bool hevc = venc_get_hevc_profile(&eProfile);
/* Initialize to zero & update as per required color format */
*usage = 0;
/* Configure UBWC as default if target supports */
#ifdef _UBWC_
*usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
#endif
if (hevc &&
(eProfile == (OMX_U32)OMX_VIDEO_HEVCProfileMain10HDR10 ||
eProfile == (OMX_U32)OMX_VIDEO_HEVCProfileMain10 ||
eProfile == (OMX_U32)OMX_VIDEO_HEVCProfileMain10HDR10Plus)) {
DEBUG_PRINT_INFO("Setting 10-bit consumer usage bits");
*usage |= GRALLOC_USAGE_PRIVATE_10BIT_VIDEO;
if (mUseLinearColorFormat & REQUEST_LINEAR_COLOR_10_BIT) {
*usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
DEBUG_PRINT_INFO("Clear UBWC consumer usage bits as 10-bit linear color requested");
}
} else if (mUseLinearColorFormat & REQUEST_LINEAR_COLOR_8_BIT ||
m_codec == OMX_VIDEO_CodingImageHEIC) {
*usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
DEBUG_PRINT_INFO("Clear UBWC consumer usage bits as 8-bit linear color requested");
}
DEBUG_PRINT_INFO("venc_get_consumer_usage 0x%x", *usage);
}
bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index)
{
if (is_streamon_done(PORT_INDEX_IN)) {
if (venc_store_dynamic_config(index, configData)) {
DEBUG_PRINT_HIGH("dynamic config %#X successfully stored.", index);
return true;
}
/* If failed, try to handle the dynamic config immediately */
DEBUG_PRINT_ERROR("Store dynamic config %#X failed", index);
}
DEBUG_PRINT_LOW("Inside venc_set_config");
switch ((int)index) {
case OMX_IndexConfigVideoBitrate:
{
OMX_VIDEO_CONFIG_BITRATETYPE *bit_rate = (OMX_VIDEO_CONFIG_BITRATETYPE *)
configData;
DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoBitrate");
if (!venc_config_bitrate(bit_rate))
return false;
break;
}
case OMX_IndexConfigVideoFramerate:
{
OMX_CONFIG_FRAMERATETYPE *frame_rate = (OMX_CONFIG_FRAMERATETYPE *)
configData;
DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoFramerate");
if (!venc_config_framerate(frame_rate))
return false;
break;
}
case QOMX_IndexConfigVideoIntraperiod:
{
DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexConfigVideoIntraperiod");
QOMX_VIDEO_INTRAPERIODTYPE *intraperiod =
(QOMX_VIDEO_INTRAPERIODTYPE *)configData;
if (set_nP_frames(intraperiod->nPFrames) == false ||
set_nB_frames(intraperiod->nBFrames) == false)
return false;
break;
}
case OMX_IndexConfigVideoIntraVOPRefresh:
{
OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh = (OMX_CONFIG_INTRAREFRESHVOPTYPE *)
configData;
DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoIntraVOPRefresh");
if (!venc_config_intravoprefresh(intra_vop_refresh))
return false;
break;
}
case OMX_IndexConfigCommonMirror:
{
OMX_CONFIG_MIRRORTYPE *mirror = (OMX_CONFIG_MIRRORTYPE*) configData;
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexConfigCommonMirror");
if (venc_set_mirror(mirror->eMirror) == false) {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigCommonMirror failed");
return false;
}
break;
}
case OMX_IndexConfigCommonRotate:
{
OMX_CONFIG_ROTATIONTYPE *config_rotation =
reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
OMX_U32 nFrameWidth;
if (!config_rotation) {
return false;
}
if (venc_handle->m_c2d_rotation) {
if (venc_prepare_c2d_rotation(config_rotation->nRotation) == false) {
DEBUG_PRINT_ERROR("ERROR: venc_prepare_c2d_rotation failed");
return false;
}
} else {
if (venc_set_vpe_rotation(config_rotation->nRotation) == false) {
DEBUG_PRINT_ERROR("ERROR: Dimension Change for Rotation failed");
return false;
}
}
break;
}
case OMX_IndexConfigVideoAVCIntraPeriod:
{
OMX_VIDEO_CONFIG_AVCINTRAPERIOD *avc_iperiod = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD*) configData;
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexConfigVideoAVCIntraPeriod");
if (set_nP_frames(avc_iperiod->nPFrames) == false) {
DEBUG_PRINT_ERROR("ERROR: Setting intra period failed");
return false;
}
break;
}
case OMX_IndexConfigVideoVp8ReferenceFrame:
{
OMX_VIDEO_VP8REFERENCEFRAMETYPE* vp8refframe = (OMX_VIDEO_VP8REFERENCEFRAMETYPE*) configData;
DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoVp8ReferenceFrame");
if (!venc_config_vp8refframe(vp8refframe))
return false;
break;
}
case OMX_QcomIndexConfigVideoLTRUse:
{
OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE* pParam = (OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE*)configData;
DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoLTRUse");
if (!venc_config_useLTR(pParam))
return false;
break;
}
case OMX_IndexParamVideoAndroidVp8Encoder:
{
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoAndroidVp8Encoder");
OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8EncodeParams =
(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)configData;
if (vp8EncodeParams->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
int pFrames = vp8EncodeParams->nKeyFrameInterval - 1;
if (set_nP_frames(pFrames) == false) {
DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoAndroidVp8Encoder");
}
break;
}
case OMX_QcomIndexConfigVideoLTRMark:
{
OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE* pParam = (OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE*)configData;
DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoLTRMark");
if (!venc_config_markLTR(pParam))
return false;
break;
}
case OMX_IndexConfigAndroidVideoTemporalLayering:
{
OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *pParam =
(OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *) configData;
// Update temporal_layers_config with input config
if (pParam->nPLayerCountActual < OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS) {
temporal_layers_config.nPLayers = pParam->nPLayerCountActual;
} else {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigAndroidVideoTemporalLayering failed");
return false;
}
temporal_layers_config.ePattern = pParam->ePattern;
temporal_layers_config.hier_mode = HIER_P;
temporal_layers_config.nBLayers = 0;
// Resetting to zero as we are sending all bitrate ratios to kernel
memset(&temporal_layers_config.nTemporalLayerBitrateRatio, 0x0, sizeof(OMX_U32)*OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS);
for (OMX_U32 i = 0; i < temporal_layers_config.nPLayers; ++i) {
temporal_layers_config.nTemporalLayerBitrateRatio[i] = pParam->nBitrateRatios[i];
}
if (OMX_ErrorNone != venc_set_hierp_layer()) {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigAndroidVideoTemporalLayering failed in setting hierp layers");
return false;
}
if (OMX_ErrorNone != venc_set_bitrate_ratios()) {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigAndroidVideoTemporalLayering failed in setting bitrate ratios");
return false;
}
break;
}
case OMX_QcomIndexConfigBaseLayerId:
{
OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID* pParam =
(OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID*) configData;
if (venc_set_baselayerid(pParam->nPID) == false) {
DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigBaseLayerId failed");
return false;
}
break;
}
case OMX_QcomIndexConfigQp:
{
OMX_QCOM_VIDEO_CONFIG_QP* pParam =
(OMX_QCOM_VIDEO_CONFIG_QP*) configData;
DEBUG_PRINT_LOW("Set_config: nQP %d", pParam->nQP);
if (!venc_config_qp(pParam))
return false;
break;
}
case OMX_IndexConfigPriority:
{
OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
if (!venc_set_priority(priority->nU32)) {
DEBUG_PRINT_ERROR("Failed to set priority");
return false;
}
sess_priority.priority = priority->nU32;
break;
}
case OMX_IndexConfigOperatingRate:
{
OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
DEBUG_PRINT_LOW("Set_config: operating rate %u", rate->nU32);
if (!venc_set_operatingrate(rate->nU32)) {
DEBUG_PRINT_ERROR("Failed to set operating rate");
return false;
}
break;
}
case OMX_IndexConfigAndroidIntraRefresh:
{
OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *intra_refresh_period = (OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *)configData;
DEBUG_PRINT_LOW("OMX_IndexConfigAndroidIntraRefresh : num frames = %d", intra_refresh_period->nRefreshPeriod);
if (intra_refresh_period->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
intra_refresh.framecount = intra_refresh_period->nRefreshPeriod;
intra_refresh.irmode = OMX_VIDEO_IntraRefreshRandom;
intra_refresh.mbcount = 0;
venc_set_intra_refresh();
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoIntraRefreshType");
}
break;
}
case OMX_QTIIndexConfigVideoBlurResolution:
{
OMX_QTI_VIDEO_CONFIG_BLURINFO *blur = (OMX_QTI_VIDEO_CONFIG_BLURINFO *)configData;
if (blur->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
DEBUG_PRINT_LOW("Set_config: blur resolution: %u", blur->nBlurInfo);
if(!venc_set_blur_resolution(blur)) {
DEBUG_PRINT_ERROR("Failed to set Blur Resolution");
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QTIIndexConfigVideoBlurResolution");
return false;
}
break;
}
case OMX_QTIIndexConfigDescribeColorAspects:
{
DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
OMX_U32 color_space = MSM_VIDC_BT601_6_625;
OMX_U32 full_range = 0;
OMX_U32 matrix_coeffs = MSM_VIDC_MATRIX_601_6_625;
OMX_U32 transfer_chars = MSM_VIDC_TRANSFER_601_6_625;
switch((ColorAspects::Primaries)(params->sAspects.mPrimaries)) {
case ColorAspects::PrimariesBT709_5:
color_space = MSM_VIDC_BT709_5;
break;
case ColorAspects::PrimariesBT470_6M:
color_space = MSM_VIDC_BT470_6_M;
break;
case ColorAspects::PrimariesBT601_6_625:
color_space = MSM_VIDC_BT601_6_625;
break;
case ColorAspects::PrimariesBT601_6_525:
color_space = MSM_VIDC_BT601_6_525;
break;
case ColorAspects::PrimariesGenericFilm:
color_space = MSM_VIDC_GENERIC_FILM;
break;
case ColorAspects::PrimariesBT2020:
color_space = MSM_VIDC_BT2020;
break;
default:
color_space = MSM_VIDC_BT601_6_625;
//params->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625;
break;
}
switch((ColorAspects::Range)params->sAspects.mRange) {
case ColorAspects::RangeFull:
full_range = 1;
break;
case ColorAspects::RangeLimited:
full_range = 0;
break;
default:
break;
}
switch((ColorAspects::Transfer)params->sAspects.mTransfer) {
case ColorAspects::TransferSMPTE170M:
transfer_chars = MSM_VIDC_TRANSFER_601_6_525;
break;
case ColorAspects::TransferUnspecified:
transfer_chars = MSM_VIDC_TRANSFER_UNSPECIFIED;
break;
case ColorAspects::TransferGamma22:
transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_M;
break;
case ColorAspects::TransferGamma28:
transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_BG;
break;
case ColorAspects::TransferSMPTE240M:
transfer_chars = MSM_VIDC_TRANSFER_SMPTE_240M;
break;
case ColorAspects::TransferLinear:
transfer_chars = MSM_VIDC_TRANSFER_LINEAR;
break;
case ColorAspects::TransferXvYCC:
transfer_chars = MSM_VIDC_TRANSFER_IEC_61966;
break;
case ColorAspects::TransferBT1361:
transfer_chars = MSM_VIDC_TRANSFER_BT_1361;
break;
case ColorAspects::TransferSRGB:
transfer_chars = MSM_VIDC_TRANSFER_SRGB;
break;
default:
//params->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
transfer_chars = MSM_VIDC_TRANSFER_601_6_625;
break;
}
switch((ColorAspects::MatrixCoeffs)params->sAspects.mMatrixCoeffs) {
case ColorAspects::MatrixUnspecified:
matrix_coeffs = MSM_VIDC_MATRIX_UNSPECIFIED;
break;
case ColorAspects::MatrixBT709_5:
matrix_coeffs = MSM_VIDC_MATRIX_BT_709_5;
break;
case ColorAspects::MatrixBT470_6M:
matrix_coeffs = MSM_VIDC_MATRIX_FCC_47;
break;
case ColorAspects::MatrixBT601_6:
matrix_coeffs = MSM_VIDC_MATRIX_601_6_525;
break;
case ColorAspects::MatrixSMPTE240M:
matrix_coeffs = MSM_VIDC_MATRIX_SMPTE_240M;
break;
case ColorAspects::MatrixBT2020:
matrix_coeffs = MSM_VIDC_MATRIX_BT_2020;
break;
case ColorAspects::MatrixBT2020Constant:
matrix_coeffs = MSM_VIDC_MATRIX_BT_2020_CONST;
break;
default:
//params->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
matrix_coeffs = MSM_VIDC_MATRIX_601_6_625;
break;
}
if (!venc_set_colorspace(color_space, full_range,
transfer_chars, matrix_coeffs)) {
DEBUG_PRINT_ERROR("Failed to set operating rate");
return false;
}
break;
}
case OMX_QTIIndexConfigVideoRoiInfo:
{
if(!venc_set_roi_qp_info((OMX_QTI_VIDEO_CONFIG_ROIINFO *)configData)) {
DEBUG_PRINT_ERROR("Failed to set ROI QP info");
return false;
}
break;
}
case OMX_IndexConfigVideoNalSize:
{
if(!venc_set_nal_size((OMX_VIDEO_CONFIG_NALSIZE *)configData)) {
DEBUG_PRINT_LOW("Failed to set Nal size info");
return false;
}
break;
}
case OMX_QTIIndexConfigVideoRoiRectRegionInfo:
{
if(!venc_set_roi_region_qp_info((OMX_QTI_VIDEO_CONFIG_ROI_RECT_REGION_INFO *)configData)) {
DEBUG_PRINT_LOW("Failed to set ROI Region QP info");
return false;
}
break;
}
default:
DEBUG_PRINT_ERROR("Unsupported config index = %u", index);
break;
}
return true;
}
bool venc_dev::venc_store_dynamic_config(OMX_INDEXTYPE config_type, OMX_PTR config)
{
struct dynamicConfig newConfig;
memset(&newConfig, 0, sizeof(dynamicConfig));
newConfig.type = config_type;
switch ((int)config_type) {
case OMX_IndexConfigVideoFramerate:
memcpy(&newConfig.config_data.framerate, config, sizeof(OMX_CONFIG_FRAMERATETYPE));
break;
case OMX_IndexConfigVideoIntraVOPRefresh:
memcpy(&newConfig.config_data.intravoprefresh, config, sizeof(OMX_CONFIG_INTRAREFRESHVOPTYPE));
break;
case OMX_IndexConfigVideoBitrate:
memcpy(&newConfig.config_data.bitrate, config, sizeof(OMX_VIDEO_CONFIG_BITRATETYPE));
break;
case OMX_QcomIndexConfigVideoLTRUse:
memcpy(&newConfig.config_data.useltr, config, sizeof(OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE));
break;
case OMX_QcomIndexConfigVideoLTRMark:
memcpy(&newConfig.config_data.markltr, config, sizeof(OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE));
break;
case OMX_QcomIndexConfigQp:
memcpy(&newConfig.config_data.configqp, config, sizeof(OMX_QCOM_VIDEO_CONFIG_QP));
break;
case QOMX_IndexConfigVideoIntraperiod:
memcpy(&newConfig.config_data.intraperiod, config, sizeof(QOMX_VIDEO_INTRAPERIODTYPE));
break;
case OMX_IndexConfigVideoVp8ReferenceFrame:
memcpy(&newConfig.config_data.vp8refframe, config, sizeof(OMX_VIDEO_VP8REFERENCEFRAMETYPE));
break;
case OMX_IndexConfigCommonMirror:
memcpy(&newConfig.config_data.mirror, config, sizeof(OMX_CONFIG_MIRRORTYPE));
break;
default:
DEBUG_PRINT_INFO("Unsupported dynamic config.");
return false;
}
if(venc_handle->m_etb_count)
newConfig.timestamp = venc_handle->m_etb_timestamp + 1;
else
newConfig.timestamp = 0;
pthread_mutex_lock(&m_configlock);
DEBUG_PRINT_LOW("list add dynamic config with type %d timestamp %lld us", config_type, newConfig.timestamp);
m_configlist.push_back(newConfig);
pthread_mutex_unlock(&m_configlock);
return true;
}
bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index)
{
DEBUG_PRINT_LOW("venc_set_param index 0x%x", index);
struct v4l2_format fmt;
struct v4l2_requestbuffers bufreq;
int ret;
bool isCBR;
switch ((int)index) {
case OMX_IndexParamPortDefinition:
{
OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
if (portDefn->nPortIndex == PORT_INDEX_IN) {
if (!venc_set_encode_framerate(portDefn->format.video.xFramerate)) {
return false;
}
unsigned long inputformat = venc_get_color_format(portDefn->format.video.eColorFormat);
unsigned long width = m_bDimensionsNeedFlip ? portDefn->format.video.nFrameHeight :
portDefn->format.video.nFrameWidth;
unsigned long height = m_bDimensionsNeedFlip ? portDefn->format.video.nFrameWidth :
portDefn->format.video.nFrameHeight;
if (m_sVenc_cfg.input_height != height || m_sVenc_cfg.input_width != width ||
m_sInput_buff_property.actualcount != portDefn->nBufferCountActual ||
m_sVenc_cfg.inputformat != inputformat) {
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: port: %u, WxH %lux%lu --> %ux%u, count %lu --> %u, format %#lx --> %#lx",
portDefn->nPortIndex, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,
portDefn->format.video.nFrameWidth, portDefn->format.video.nFrameHeight,
m_sInput_buff_property.actualcount, portDefn->nBufferCountActual,
m_sVenc_cfg.inputformat, inputformat);
if (portDefn->nBufferCountActual < m_sInput_buff_property.mincount) {
DEBUG_PRINT_LOW("Actual count %u is less than driver mincount %lu on port %u",
portDefn->nBufferCountActual, m_sInput_buff_property.mincount, portDefn->nPortIndex);
return false;
}
m_sVenc_cfg.input_height = height;
m_sVenc_cfg.input_width = width;
m_sVenc_cfg.inputformat = inputformat;
m_sInput_buff_property.actualcount = portDefn->nBufferCountActual;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, pixelformat %#x, colorspace %#x",
fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.colorspace);
hw_overload = errno == EBUSY;
return false;
}
m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
bufreq.memory = V4L2_MEMORY_USERPTR;
bufreq.count = portDefn->nBufferCountActual;
bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
if (ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
DEBUG_PRINT_ERROR("reqbufs failed, type %d, count %d", bufreq.type, bufreq.count);
return false;
}
if (num_input_planes > 1) {
input_extradata_info.count = m_sInput_buff_property.actualcount;
venc_handle->m_client_in_extradata_info.set_extradata_info(input_extradata_info.buffer_size, input_extradata_info.count);
}
if (!downscalar_enabled) {
m_sVenc_cfg.dvs_height = height;
m_sVenc_cfg.dvs_width = width;
}
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
DEBUG_PRINT_ERROR("VIDIOC_S_FMT CAPTURE_MPLANE Failed");
hw_overload = errno == EBUSY;
return false;
}
m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
} else {
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: parameters not changed on port %d",
portDefn->nPortIndex);
}
} else if (portDefn->nPortIndex == PORT_INDEX_OUT) {
unsigned long codectype = venc_get_codectype(portDefn->format.video.eCompressionFormat);
unsigned long width = m_bDimensionsNeedFlip ? portDefn->format.video.nFrameHeight :
portDefn->format.video.nFrameWidth;
unsigned long height = m_bDimensionsNeedFlip ? portDefn->format.video.nFrameWidth :
portDefn->format.video.nFrameHeight;
//Don't worry about width/height if downscalar is enabled.
if (m_sVenc_cfg.dvs_height != height || m_sVenc_cfg.dvs_width != width ||
m_sOutput_buff_property.actualcount != portDefn->nBufferCountActual ||
m_sVenc_cfg.codectype != codectype) {
if (portDefn->nBufferCountActual < m_sOutput_buff_property.mincount) {
DEBUG_PRINT_LOW("Actual count %u is less than driver mincount %lu on port %u",
portDefn->nBufferCountActual, m_sOutput_buff_property.mincount, portDefn->nPortIndex);
return false;
}
//If downscalar is enabled. Correct width/height is populated no need to replace with port def width/height
if (!downscalar_enabled) {
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: port: %u, WxH %lux%lu --> %ux%u, count %lu --> %u, format %#lx --> %#lx",
portDefn->nPortIndex, m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height,
portDefn->format.video.nFrameWidth, portDefn->format.video.nFrameHeight,
m_sOutput_buff_property.actualcount, portDefn->nBufferCountActual,
m_sVenc_cfg.codectype, codectype);
m_sVenc_cfg.dvs_height = height;
m_sVenc_cfg.dvs_width = width;
}
m_sVenc_cfg.codectype = codectype;
m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
DEBUG_PRINT_ERROR("set format failed, type %d, wxh %dx%d, pixelformat %#x",
fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
fmt.fmt.pix_mp.pixelformat);
hw_overload = errno == EBUSY;
return false;
}
m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
if (!venc_set_target_bitrate(portDefn->format.video.nBitrate)) {
return false;
}
bufreq.memory = V4L2_MEMORY_USERPTR;
bufreq.count = portDefn->nBufferCountActual;
bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
if (ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) {
DEBUG_PRINT_ERROR("reqbufs failed, type %d, count %d", bufreq.type, bufreq.count);
return false;
}
if (num_output_planes > 1) {
output_extradata_info.count = m_sOutput_buff_property.actualcount;
venc_handle->m_client_out_extradata_info.set_extradata_info(output_extradata_info.buffer_size, output_extradata_info.count);
}
} else {
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition: parameters not changed on port %d",
portDefn->nPortIndex);
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index (%d) for OMX_IndexParamPortDefinition", portDefn->nPortIndex);
}
}
break;
case OMX_IndexParamVideoPortFormat:
{
OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt;
portFmt =(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoPortFormat");
if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
if (!venc_set_color_format(portFmt->eColorFormat)) {
return false;
}
} else if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
if (!venc_set_encode_framerate(portFmt->xFramerate)) {
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoPortFormat");
}
break;
}
case OMX_IndexParamVideoBitrate:
{
OMX_VIDEO_PARAM_BITRATETYPE* pParam;
pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoBitrate");
if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
if (!venc_set_ratectrl_cfg(pParam->eControlRate)) {
DEBUG_PRINT_ERROR("ERROR: Rate Control setting failed");
return false;
}
if (!venc_set_target_bitrate(pParam->nTargetBitrate)) {
DEBUG_PRINT_ERROR("ERROR: Target Bit Rate setting failed");
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoBitrate");
}
break;
}
case OMX_IndexParamVideoAvc:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoAvc");
OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
OMX_U32 bFrames = 0;
if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
DEBUG_PRINT_LOW("pParam->eProfile :%d ,pParam->eLevel %d",
pParam->eProfile,pParam->eLevel);
if (!venc_set_profile (pParam->eProfile)) {
DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
pParam->eProfile);
return false;
}
if (set_nP_frames(pParam->nPFrames) == false ||
(pParam->nBFrames && set_nB_frames(pParam->nBFrames) == false)) {
DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
return false;
}
if (!venc_set_entropy_config (pParam->bEntropyCodingCABAC, pParam->nCabacInitIdc)) {
DEBUG_PRINT_ERROR("ERROR: Request for setting Entropy failed");
return false;
}
if (!venc_set_inloop_filter (pParam->eLoopFilterMode)) {
DEBUG_PRINT_ERROR("ERROR: Request for setting Inloop filter failed");
return false;
}
if (!venc_set_multislice_cfg(V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB, pParam->nSliceHeaderSpacing)) {
DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating slice_config");
return false;
}
if (!venc_h264_transform_8x8(pParam->bDirect8x8Inference)) {
DEBUG_PRINT_ERROR("WARNING: Request for setting Transform8x8 failed");
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoAvc");
}
//TBD, lot of other variables to be updated, yet to decide
break;
}
case (OMX_INDEXTYPE)OMX_IndexParamVideoVp8:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoVp8");
OMX_VIDEO_PARAM_VP8TYPE* pParam = (OMX_VIDEO_PARAM_VP8TYPE*)paramData;
//TODO: Set VP8 level/profile currently based on driver change
if (!venc_set_profile (pParam->eProfile)) {
DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
pParam->eProfile);
return false;
}
if(venc_set_vpx_error_resilience(pParam->bErrorResilientMode) == false) {
DEBUG_PRINT_ERROR("ERROR: Failed to set vpx error resilience");
return false;
}
break;
}
case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoHevc");
OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData;
if (!venc_set_profile (pParam->eProfile)) {
DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile %d",
pParam->eProfile);
return false;
}
if (!venc_set_inloop_filter(OMX_VIDEO_AVCLoopFilterEnable))
DEBUG_PRINT_HIGH("WARN: Request for setting Inloop filter failed for HEVC encoder");
OMX_U32 fps = m_sVenc_cfg.fps_den ? m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den : 30;
OMX_U32 nPFrames = pParam->nKeyFrameInterval > 0 ? pParam->nKeyFrameInterval - 1 : fps - 1;
if (set_nP_frames(nPFrames) == false) {
DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
return false;
}
break;
}
case (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid:
{
DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoAndroidImageGrid. Ignore!");
break;
}
case OMX_IndexParamVideoIntraRefresh:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh");
OMX_VIDEO_PARAM_INTRAREFRESHTYPE *intra_refresh_param =
(OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)paramData;
if (intra_refresh_param->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
intra_refresh.irmode = OMX_VIDEO_IntraRefreshCyclic;
intra_refresh.mbcount = intra_refresh_param->nCirMBs;
intra_refresh.framecount = 0;
venc_set_intra_refresh();
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoIntraRefresh");
}
break;
}
case OMX_IndexParamVideoErrorCorrection:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoErrorCorrection");
OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *error_resilience =
(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)paramData;
if (error_resilience->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
if (venc_set_error_resilience(error_resilience) == false) {
DEBUG_PRINT_ERROR("ERROR: Setting Error Correction failed");
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoErrorCorrection");
}
break;
}
case OMX_QcomIndexParamVideoSliceSpacing:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_QcomIndexParamVideoSliceSpacing");
QOMX_VIDEO_PARAM_SLICE_SPACING_TYPE *slice_spacing =
(QOMX_VIDEO_PARAM_SLICE_SPACING_TYPE*)paramData;
if (slice_spacing->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
if (!venc_set_multislice_cfg(slice_spacing->eSliceMode, slice_spacing->nSliceSize)) {
DEBUG_PRINT_ERROR("ERROR: Setting Slice Spacing failed");
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexParamVideoSliceSpacing");
}
break;
}
case OMX_IndexParamVideoProfileLevelCurrent:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoProfileLevelCurrent");
OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level =
(OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
if (profile_level->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
if (!venc_set_profile(profile_level->eProfile)) {
DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating Profile");
return false;
}
if (!venc_set_level(profile_level->eLevel)) {
DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating level");
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoProfileLevelCurrent");
}
break;
}
case OMX_IndexParamVideoQuantization:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoQuantization");
OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp =
(OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)paramData;
if (session_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
if (venc_set_qp(session_qp->nQpI,
session_qp->nQpP,
session_qp->nQpB,
ENABLE_I_QP | ENABLE_P_QP | ENABLE_B_QP) == false) {
DEBUG_PRINT_ERROR("ERROR: Setting Session QP failed");
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoQuantization");
}
break;
}
case QOMX_IndexParamVideoInitialQp:
{
DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexParamVideoInitialQp");
QOMX_EXTNINDEX_VIDEO_INITIALQP *initial_qp =
(QOMX_EXTNINDEX_VIDEO_INITIALQP *)paramData;
if (initial_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
if (venc_set_qp(initial_qp->nQpI,
initial_qp->nQpP,
initial_qp->nQpB,
initial_qp->bEnableInitQp) == false) {
DEBUG_PRINT_ERROR("ERROR: Setting Initial QP failed");
return false;
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for QOMX_IndexParamVideoInitialQp");
}
break;
}
case OMX_QcomIndexParamVideoIPBQPRange:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_QcomIndexParamVideoIPBQPRange");
OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE *session_qp_range =
(OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE *)paramData;
if(session_qp_range->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
if ( venc_set_session_qp_range (session_qp_range) == false) {
DEBUG_PRINT_ERROR("ERROR: Setting QP range failed");
return false;
}
}
break;
}
case OMX_QcomIndexParamIndexExtraDataType:
{
DEBUG_PRINT_LOW("venc_set_param: OMX_QcomIndexParamIndexExtraDataType");
QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData;
if (pParam->nIndex == (OMX_INDEXTYPE)OMX_QTI_ExtraDataCategory_Enc_ROI &&
m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
DEBUG_PRINT_ERROR("OMX_QTI_ExtraDataCategory_Enc_ROI is not supported for %lu codec", m_sVenc_cfg.codectype);
return false;
}
if (venc_set_extradata(pParam->nIndex, pParam->bEnabled) == false) {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_QcomIndexParamIndexExtraDataType failed");
return false;
}
if (pParam->nIndex == (OMX_INDEXTYPE)OMX_QTI_ExtraDataCategory_Enc_ROI && pParam->bEnabled) {
m_roi_enabled = true;
struct v4l2_control control;
control.id = V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE;
control.value = ROI_NONE;
if (ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &control)) {
DEBUG_PRINT_ERROR("ERROR: failed to query supported ROI type");
m_roi_type = ROI_NONE;
} else {
auto type = static_cast<roi_type>(control.value);
if (type != ROI_2BIT && type != ROI_2BYTE) {
DEBUG_PRINT_LOW("invalid ROI type : %u", m_roi_type);
m_roi_type = ROI_NONE;
} else {
m_roi_type = type;
DEBUG_PRINT_LOW("queried ROI type : %u", m_roi_type);
}
}
}
break;
}
case OMX_QcomIndexParamSequenceHeaderWithIDR:
{
PrependSPSPPSToIDRFramesParams * pParam =
(PrependSPSPPSToIDRFramesParams *)paramData;
DEBUG_PRINT_LOW("set inband sps/pps: %d", pParam->bEnable);
if(venc_set_inband_video_header(pParam->bEnable) == false) {
DEBUG_PRINT_ERROR("ERROR: set inband sps/pps failed");
return false;
}
break;
}
case OMX_QcomIndexParamH264VUITimingInfo:
{
OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *pParam =
(OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *)paramData;
DEBUG_PRINT_LOW("Set VUI timing info: %d", pParam->bEnable);
if(venc_set_vui_timing_info(pParam->bEnable) == false) {
DEBUG_PRINT_ERROR("ERROR: Failed to set vui timing info to %d", pParam->bEnable);
return false;
} else {
vui_timing_info.enabled = (unsigned int) pParam->bEnable;
}
break;
}
case OMX_QcomIndexParamVideoLTRCount:
{
DEBUG_PRINT_LOW("venc_set_param: OMX_QcomIndexParamVideoLTRCount");
OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE* pParam =
(OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE*)paramData;
if (venc_set_ltrcount(pParam->nCount) == false) {
DEBUG_PRINT_ERROR("ERROR: Enable LTR mode failed");
return false;
}
break;
}
case OMX_QcomIndexParamBatchSize:
{
OMX_PARAM_U32TYPE* pParam =
(OMX_PARAM_U32TYPE*)paramData;
if (pParam->nPortIndex == PORT_INDEX_OUT) {
DEBUG_PRINT_ERROR("For the moment, client-driven batching not supported"
" on output port");
return false;
}
break;
}
case OMX_QcomIndexParamVencAspectRatio:
{
if (!venc_set_aspectratio(paramData)) {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_QcomIndexParamVencAspectRatio failed");
return false;
}
break;
}
case OMX_QTIIndexParamLowLatencyMode:
{
QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE *pParam =
(QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE*)paramData;
if (!venc_set_lowlatency_mode(pParam->bEnableLowLatencyMode)) {
DEBUG_PRINT_ERROR("Setting low latency mode failed");
return false;
}
break;
}
case OMX_IndexParamAndroidVideoTemporalLayering:
{
OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE hierData;
memcpy(&hierData, paramData, sizeof(hierData));
// Update temporal_layers_config with input param
if (hierData.nPLayerCountActual < OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS) {
temporal_layers_config.nPLayers = hierData.nPLayerCountActual;
} else {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexParamAndroidVideoTemporalLayering failed");
return false;
}
temporal_layers_config.ePattern = hierData.ePattern;
temporal_layers_config.hier_mode = HIER_P;
temporal_layers_config.nMaxLayers = hierData.nLayerCountMax;
temporal_layers_config.nMaxBLayers = hierData.nBLayerCountMax;
temporal_layers_config.nBLayers = hierData.nBLayerCountActual;
// Resetting to zero as we are sending all bitrate ratios to kernel
memset(&temporal_layers_config.nTemporalLayerBitrateRatio, 0x0, sizeof(OMX_U32)*OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS);
for (OMX_U32 i = 0; i < temporal_layers_config.nPLayers; ++i) {
temporal_layers_config.nTemporalLayerBitrateRatio[i] = hierData.nBitrateRatios[i];
}
if (OMX_ErrorNone != venc_set_max_hierp_layer()) {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexParamAndroidVideoTemporalLayering failed in setting max hierp layers");
return false;
}
if (OMX_ErrorNone != venc_set_hierp_layer()) {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexParamAndroidVideoTemporalLayering failed in setting hierp layers");
return false;
}
if (OMX_ErrorNone != venc_set_bitrate_ratios()) {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexParamAndroidVideoTemporalLayering failed in setting bitrate ratios");
return false;
}
break;
}
case OMX_QTIIndexParamEnableAVTimerTimestamps:
{
QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
mUseAVTimerTimestamps = pParam->bEnable == OMX_TRUE;
DEBUG_PRINT_INFO("AVTimer timestamps enabled");
break;
}
case OMX_QcomIndexParamVideoDownScalar:
{
QOMX_INDEXDOWNSCALAR *pParam = (QOMX_INDEXDOWNSCALAR *)paramData;
downscalar_enabled = pParam->bEnable;
DEBUG_PRINT_INFO("Downscalar settings: Enabled : %d Width : %u Height %u",
pParam->bEnable, pParam->nOutputWidth, pParam->nOutputHeight);
if (downscalar_enabled) {
m_sVenc_cfg.dvs_width = pParam->nOutputWidth;
m_sVenc_cfg.dvs_height = pParam->nOutputHeight;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
fmt.fmt.pix_mp.width = pParam->nOutputWidth;
fmt.fmt.pix_mp.height = pParam->nOutputHeight;
fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
DEBUG_PRINT_ERROR("Failed to set format on capture port");
return false;
}
m_sOutput_buff_property.datasize = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
}
break;
}
case OMX_QTIIndexParamColorSpaceConversion:
{
QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
csc_enable = pParam->bEnable;
DEBUG_PRINT_INFO("CSC settings: Enabled : %d ", pParam->bEnable);
break;
}
case OMX_QTIIndexParamEnableLinearColorFormat:
{
QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
mUseLinearColorFormat = pParam->bEnable ? REQUEST_LINEAR_COLOR_ALL : 0;
DEBUG_PRINT_INFO("Linear Color Format Enabled : %d ", pParam->bEnable);
break;
}
case OMX_QTIIndexParamNativeRecorder:
{
QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
if (!set_native_recoder(pParam->bEnable)) {
DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamNativeRecorder failed");
return false;
}
DEBUG_PRINT_INFO("Native recorder encode session %d", pParam->bEnable);
break;
}
case OMX_QTIIndexParamVbvDelay:
{
OMX_EXTNINDEX_VIDEO_VBV_DELAY *pParam =
(OMX_EXTNINDEX_VIDEO_VBV_DELAY*)paramData;
if (!venc_set_vbv_delay(pParam->nVbvDelay)) {
DEBUG_PRINT_ERROR("Setting OMX_QTIIndexParamVbvDelay failed");
return false;
}
break;
}
default:
DEBUG_PRINT_ERROR("ERROR: Unsupported parameter in venc_set_param: %u",
index);
break;
}
return true;
}
bool venc_dev::venc_set_inband_video_header(OMX_BOOL enable)
{
struct v4l2_control control;
control.id = V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR;
control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
if(enable) {
control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
}
DEBUG_PRINT_HIGH("Set inband sps/pps: %d", enable);
if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control) < 0) {
DEBUG_PRINT_ERROR("Request for inband sps/pps failed");
return false;
}
return true;
}
bool venc_dev::venc_set_extradata(OMX_U32 extra_data, OMX_BOOL enable)
{
struct v4l2_control control;
DEBUG_PRINT_HIGH("venc_set_extradata:: %x", (int) extra_data);
if (enable == OMX_FALSE) {
/* No easy way to turn off extradata to the driver
* at the moment */
return false;
}
control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
switch (extra_data) {
case OMX_QTI_ExtraDataCategory_Advanced:
control.value = EXTRADATA_ADVANCED;
break;
case OMX_QTI_ExtraDataCategory_Enc_ROI:
control.value = EXTRADATA_ENC_INPUT_ROI;
break;
default:
DEBUG_PRINT_ERROR("Unrecognized extradata index 0x%x", (unsigned int)extra_data);
return false;
}
if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
DEBUG_PRINT_ERROR("ERROR: Request for setting extradata (%x) failed %d",
(unsigned int)extra_data, errno);
return false;
}
return true;
}
bool venc_dev::venc_set_session_qp_range(OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE* qp_range)
{
int rc;
struct v4l2_control control[2];
control[0].id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP;
control[0].value = qp_range->minIQP | (qp_range->minPQP << 8) | (qp_range->minBQP << 16);
control[1].id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP;
control[1].value = qp_range->maxIQP | (qp_range->maxPQP << 8) | (qp_range->maxBQP << 16);
for(int i=0; i<2; i++) {
if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control[i])) {
DEBUG_PRINT_ERROR("Failed to set QP %s range", i==0?"MIN":"MAX");
return false;
}
}
session_ipb_qp_values.min_qp_packed = control[0].value;
session_ipb_qp_values.max_qp_packed = control[1].value;
return true;
}
bool venc_dev::venc_set_profile(OMX_U32 eProfile)
{
int rc;
struct v4l2_control control;
DEBUG_PRINT_LOW("venc_set_profile:: eProfile = %u",
(unsigned int)eProfile);
if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
} else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
control.id = V4L2_CID_MPEG_VIDEO_VP8_PROFILE;
} else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
control.id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE;
} else {
DEBUG_PRINT_ERROR("Wrong CODEC");
return false;
}
if (!profile_level_converter::convert_omx_profile_to_v4l2(m_sVenc_cfg.codectype, eProfile, &control.value)) {
DEBUG_PRINT_ERROR("Cannot find v4l2 profile for OMX profile : %d Codec : %lu ",
eProfile, m_sVenc_cfg.codectype);
return false;
}
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
codec_profile.profile = control.value;
if (venc_set_extradata_hdr10metadata(eProfile) == false) {
DEBUG_PRINT_ERROR("Failed to set extradata HDR10PLUS_METADATA");
return false;
}
return true;
}
bool venc_dev::venc_set_level(OMX_U32 eLevel)
{
int rc;
struct v4l2_control control;
unsigned int tier = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH;
OMX_U32 omx_profile_level = eLevel;
DEBUG_PRINT_LOW("venc_set_level:: eLevel = %u",
(unsigned int)eLevel);
if (!eLevel) {
DEBUG_PRINT_ERROR(" Unknown OMX level : %u" ,
(unsigned int)eLevel );
return true;
}
if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
if(!profile_level_converter::find_tier(m_sVenc_cfg.codectype, eLevel, &tier)) {
DEBUG_PRINT_ERROR("Failed to find HEVC v4l2 level tier for OMX level : %d", eLevel);
return true;
}
/* HEVC high tier profile levels are mapped to same V4L2 profile levels as main tier profile levels */
if (tier == V4L2_MPEG_VIDEO_HEVC_TIER_HIGH)
omx_profile_level = eLevel >> 1;
}
if (!profile_level_converter::convert_omx_level_to_v4l2(m_sVenc_cfg.codectype, omx_profile_level, &control.value)) {
DEBUG_PRINT_ERROR("Failed to find v4l2 level for OMX level : %d" \
" Codec : %lu", eLevel, m_sVenc_cfg.codectype);
return true;
}
if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
} else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
control.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
} else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
control.id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL;
profile_level.tier = tier;
}
else {
DEBUG_PRINT_ERROR("Wrong CODEC");
return false;
}
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d",
control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d",
control.id, control.value);
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d",
control.id, control.value);
if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
struct v4l2_control control_tier = {
.id = V4L2_CID_MPEG_VIDEO_HEVC_TIER,
.value = (signed int)tier
};
DEBUG_PRINT_LOW("Calling IOCTL set tier control for HEVC, id %#x, value %d",
control_tier.id, control_tier.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control_tier);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set tier control for HEVC, id %#x, value %d",
control_tier.id, control_tier.value);
} else {
profile_level.tier = control_tier.value;
}
}
profile_level.level = control.value;
return true;
}
bool venc_dev::venc_set_grid_enable()
{
int rc;
struct v4l2_control control;
DEBUG_PRINT_LOW("venc_set_grid_enable");
control.id = V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE;
control.value = 1; // TODO: DO we need to get this value from input argument?
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
mIsGridset = true;
return true;
}
bool venc_dev::venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level)
{
int rc = 0;
struct v4l2_control control;
DEBUG_PRINT_LOW("venc_set_entropy_config: CABAC = %u level: %u", enable, (unsigned int)i_cabac_level);
if (enable && (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) &&
(codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE)) {
control.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
} else if (!enable) {
control.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
} else {
DEBUG_PRINT_ERROR("Invalid Entropy mode for Baseline Profile");
return false;
}
control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
entropy.longentropysel = control.value;
return true;
}
bool venc_dev::venc_set_multislice_cfg(OMX_U32 nSlicemode, OMX_U32 nSlicesize)
{
int rc;
int slice_id = 0;
struct v4l2_control control;
bool status = true;
if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263 || nSlicesize == 0) {
nSlicemode = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE;
nSlicesize = 0;
}
if (nSlicemode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
if (!venc_validate_range(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, nSlicesize)) {
DEBUG_PRINT_ERROR("Invalid settings, hardware doesn't support %u as slicesize", nSlicesize);
return false;
}
slice_id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
} else if (nSlicemode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
if (!venc_validate_range(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, nSlicesize)) {
DEBUG_PRINT_ERROR("Invalid settings, hardware doesn't support %u as slicesize", nSlicesize);
return false;
}
slice_id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
} else if (nSlicesize) {
DEBUG_PRINT_ERROR("Invalid settings, unexpected slicemode = %u and slice size = %u", nSlicemode, nSlicesize);
return false;
}
control.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE;
control.value = nSlicemode;
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
if (nSlicemode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) {
return status;
}
control.id = slice_id;
control.value = nSlicesize;
DEBUG_PRINT_LOW("Calling SLICE_MB IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control");
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
multislice.mslice_mode = nSlicemode;
multislice.mslice_size = nSlicesize;
return status;
}
bool venc_dev::venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* error_resilience)
{
bool status = true;
struct venc_headerextension hec_cfg;
struct venc_multiclicecfg multislice_cfg;
int rc;
OMX_U32 resynchMarkerSpacingBytes = 0;
struct v4l2_control control;
memset(&control, 0, sizeof(control));
if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) {
if (error_resilience->bEnableHEC) {
hec_cfg.header_extension = 1;
} else {
hec_cfg.header_extension = 0;
}
hec.header_extension = error_resilience->bEnableHEC;
}
if (error_resilience->bEnableRVLC) {
DEBUG_PRINT_ERROR("RVLC is not Supported");
return false;
}
if (( m_sVenc_cfg.codectype != V4L2_PIX_FMT_H263) &&
(error_resilience->bEnableDataPartitioning)) {
DEBUG_PRINT_ERROR("DataPartioning are not Supported for MPEG4/H264");
return false;
}
if (error_resilience->nResynchMarkerSpacing) {
resynchMarkerSpacingBytes = error_resilience->nResynchMarkerSpacing;
resynchMarkerSpacingBytes = ALIGN(resynchMarkerSpacingBytes, 8) >> 3;
}
status = venc_set_multislice_cfg(V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES, resynchMarkerSpacingBytes);
return status;
}
bool venc_dev::venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter)
{
int rc;
struct v4l2_control control;
control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE;
control.value=0;
if (loopfilter == OMX_VIDEO_AVCLoopFilterEnable) {
control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED;
} else if (loopfilter == OMX_VIDEO_AVCLoopFilterDisable) {
control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED;
} else if (loopfilter == OMX_VIDEO_AVCLoopFilterDisableSliceBoundary) {
control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY;
}
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
dbkfilter.db_mode=control.value;
control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA;
control.value=0;
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA;
control.value=0;
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value);
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
dbkfilter.slicealpha_offset = dbkfilter.slicebeta_offset = 0;
return true;
}
unsigned long venc_dev::venc_get_codectype(OMX_VIDEO_CODINGTYPE eCompressionFormat)
{
unsigned long codectype = V4L2_PIX_FMT_H264;
switch ((int)eCompressionFormat) {
case OMX_VIDEO_CodingAVC:
codectype = V4L2_PIX_FMT_H264;
break;
case OMX_VIDEO_CodingVP8:
codectype = V4L2_PIX_FMT_VP8;
break;
case OMX_VIDEO_CodingVP9:
codectype = V4L2_PIX_FMT_VP9;
break;
case OMX_VIDEO_CodingHEVC:
case OMX_VIDEO_CodingImageHEIC:
codectype = V4L2_PIX_FMT_HEVC;
break;
default:
DEBUG_PRINT_ERROR("Unsupported eCompressionFormat %#x", eCompressionFormat);
codectype = V4L2_PIX_FMT_H264;
break;
}
return codectype;
}
bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)
{
bool status = true;
struct v4l2_control control;
int rc = 0;
control.id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE;
control.value = !!((OMX_U32)eControlRate ^ (OMX_U32)OMX_Video_ControlRateDisable);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set RC_ENABLE");
return false;
}
control.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
int temp = eControlRate;
switch ((OMX_U32)eControlRate) {
case OMX_Video_ControlRateDisable:
control.value = -1;
break;
case OMX_Video_ControlRateVariableSkipFrames:
control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
break;
case OMX_Video_ControlRateVariable:
control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
break;
case OMX_Video_ControlRateConstantSkipFrames:
control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR;
break;
case OMX_Video_ControlRateConstant:
control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
break;
case QOMX_Video_ControlRateMaxBitrate:
control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_MBR;
break;
case QOMX_Video_ControlRateMaxBitrateSkipFrames:
control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_MBR_VFR;
break;
case OMX_Video_ControlRateConstantQuality:
control.value = V4L2_MPEG_VIDEO_BITRATE_MODE_CQ;
break;
default:
status = false;
break;
}
if (status && control.value != -1) {
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set control");
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
rate_ctrl.rcmode = control.value;
}
DEBUG_PRINT_LOW("Set bitrate savings %d", mBitrateSavingsEnable);
control.id = V4L2_CID_MPEG_VIDC_VENC_BITRATE_SAVINGS;
control.value = mBitrateSavingsEnable;
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_HIGH("Non-Fatal: Request to set bitrate savings failed");
}
return status;
}
bool venc_dev::venc_set_aspectratio(void *nSar)
{
int rc;
struct v4l2_control control;
struct v4l2_ext_control ctrl[2];
struct v4l2_ext_controls controls;
QOMX_EXTNINDEX_VIDEO_VENC_SAR *sar;
sar = (QOMX_EXTNINDEX_VIDEO_VENC_SAR *) nSar;
ctrl[0].id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH;
ctrl[0].value = sar->nSARWidth;
ctrl[1].id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT;
ctrl[1].value = sar->nSARHeight;
controls.count = 2;
controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
controls.controls = ctrl;
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x val=%d, id=%x val=%d",
controls.controls[0].id, controls.controls[0].value,
controls.controls[1].id, controls.controls[1].value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_EXT_CTRLS, &controls);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set SAR %d", rc);
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%x val=%d, id=%x val=%d",
controls.controls[0].id, controls.controls[0].value,
controls.controls[1].id, controls.controls[1].value);
return true;
}
bool venc_dev::venc_set_lowlatency_mode(OMX_BOOL enable)
{
int rc = 0;
struct v4l2_control control;
control.id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE;
if (enable)
control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
else
control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
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 lowlatency control");
return false;
}
low_latency_mode = enable;
DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
return true;
}
bool venc_dev::venc_set_vui_timing_info(OMX_BOOL enable)
{
struct v4l2_control control;
int rc = 0;
control.id = V4L2_CID_MPEG_VIDC_VIDEO_VUI_TIMING_INFO;
if (enable)
control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
else
control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
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 VUI timing info control");
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
return true;
}
bool venc_dev::venc_set_peak_bitrate(OMX_U32 nPeakBitrate)
{
struct v4l2_control control;
int rc = 0;
control.id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
control.value = nPeakBitrate;
DEBUG_PRINT_LOW("venc_set_peak_bitrate: bitrate = %u", (unsigned int)nPeakBitrate);
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set peak bitrate control");
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
return true;
}
bool venc_dev::venc_set_vpx_error_resilience(OMX_BOOL enable)
{
struct v4l2_control control;
int rc = 0;
control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE;
if (enable)
control.value = 1;
else
control.value = 0;
DEBUG_PRINT_LOW("venc_set_vpx_error_resilience: %d", control.value);
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set VPX Error Resilience");
return false;
}
vpx_err_resilience.enable = 1;
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
return true;
}
bool venc_dev::venc_set_vbv_delay(OMX_U32 nVbvDelay)
{
int rc = 0;
struct v4l2_control control;
control.id = V4L2_CID_MPEG_VIDEO_VBV_DELAY;
control.value = nVbvDelay;
DEBUG_PRINT_LOW("venc_set_vbv_delay: vbvdelay = %u", (unsigned int)control.value);
DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
DEBUG_PRINT_ERROR("Failed to set vbv delay");
return false;
}
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
return true;
}