diff options
-rw-r--r-- | mm-core/inc/OMX_QCOMExtns.h | 18 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/vdec/inc/omx_vdec.h | 13 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp | 254 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/Android.mk | 1 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/omx_video_base.h | 22 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/omx_video_common.h | 3 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h | 6 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h | 77 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/omx_video_base.cpp | 56 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp | 103 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp | 821 |
11 files changed, 653 insertions, 721 deletions
diff --git a/mm-core/inc/OMX_QCOMExtns.h b/mm-core/inc/OMX_QCOMExtns.h index 07bf3c69..20917932 100644 --- a/mm-core/inc/OMX_QCOMExtns.h +++ b/mm-core/inc/OMX_QCOMExtns.h @@ -512,7 +512,7 @@ enum OMX_QCOM_EXTN_INDEXTYPE /* "OMX.QCOM.index.param.video.InputBatch" */ OMX_QcomIndexParamBatchSize = 0x7F00004A, - OMX_QcomIndexConfigMaxHierPLayers = 0x7F00004B, + OMX_QcomIndexConfigNumHierPLayers = 0x7F00004B, OMX_QcomIndexConfigRectType = 0x7F00004C, @@ -552,7 +552,7 @@ enum OMX_QCOM_EXTN_INDEXTYPE OMX_QTIIndexParamLowLatencyMode = 0x7F00005A, /* Force OPB to UnCompressed mode */ - OMX_QTIIndexParamForceUnCompressedForOPB = 0x7F00005A, + OMX_QTIIndexParamForceUnCompressedForOPB = 0x7F00005B, }; @@ -600,16 +600,16 @@ typedef struct QOMX_EXTNINDEX_VIDEO_VENC_SAR * * nSize : Size of Structure in bytes * nVersion : OpenMAX IL specification version information -* nMaxHierLayers: Set the max number of Hier-p layers for the session -* - This should be less than the Hier-P layers set -* for the session. +* nNumHierLayers: Set the number of Hier-p layers for the session +* - This should be less than the MAX Hier-P +* layers set for the session. */ -typedef struct QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS { +typedef struct QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS { OMX_U32 nSize; OMX_VERSIONTYPE nVersion; - OMX_U32 nMaxHierLayers; -} QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS; + OMX_U32 nNumHierLayers; +} QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS; /** @@ -1616,7 +1616,7 @@ typedef struct QOMX_VIDEO_CUSTOM_BUFFERSIZE { #define OMX_QCOM_INDEX_PARAM_VIDEO_LTRPERIOD "OMX.QCOM.index.param.video.LTRPeriod" #define OMX_QCOM_INDEX_CONFIG_VIDEO_LTRUSE "OMX.QCOM.index.config.video.LTRUse" #define OMX_QCOM_INDEX_CONFIG_VIDEO_LTRMARK "OMX.QCOM.index.config.video.LTRMark" -#define OMX_QCOM_INDEX_CONFIG_VIDEO_MAX_HIER_P_LAYERS "OMX.QCOM.index.config.video.hierplayers" +#define OMX_QCOM_INDEX_CONFIG_VIDEO_HIER_P_LAYERS "OMX.QCOM.index.config.video.hierplayers" #define OMX_QCOM_INDEX_CONFIG_RECTANGLE_TYPE "OMX.QCOM.index.config.video.rectangle" #define OMX_QCOM_INDEX_PARAM_VIDEO_BASE_LAYER_ID "OMX.QCOM.index.param.video.baselayerid" #define OMX_QCOM_INDEX_CONFIG_VIDEO_QP "OMX.QCOM.index.config.video.qp" diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index 3da34d52..23b8d329 100644 --- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -985,12 +985,12 @@ class omx_vdec: public qc_omx_component OMX_ERRORTYPE enable_smoothstreaming(); OMX_ERRORTYPE enable_adaptive_playback(unsigned long width, unsigned long height); bool is_thulium_v1; - bool m_disable_ubwc_mode; OMX_U32 m_downscalar_width; OMX_U32 m_downscalar_height; int decide_downscalar(); int enable_downscalar(); int disable_downscalar(); + static bool m_disable_ubwc_mode; unsigned int m_fill_output_msg; bool client_set_fps; @@ -1133,12 +1133,12 @@ class omx_vdec: public qc_omx_component //for surface mode (normal playback), advertise native/accelerated formats first OMX_COLOR_FORMATTYPE format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; - if (!m_disable_ubwc_mode) { + if (!omx_vdec::m_disable_ubwc_mode) { OMX_COLOR_FORMATTYPE formatsDefault[] = { [0] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed, [1] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m, - [2] = OMX_COLOR_FormatYUV420SemiPlanar, - [3] = OMX_COLOR_FormatYUV420Planar, + [2] = OMX_COLOR_FormatYUV420Planar, + [3] = OMX_COLOR_FormatYUV420SemiPlanar, [4] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView, }; format = (index < sizeof(formatsDefault) / sizeof(OMX_COLOR_FORMATTYPE)) ? @@ -1146,8 +1146,8 @@ class omx_vdec: public qc_omx_component } else { OMX_COLOR_FORMATTYPE formatsDefault[] = { [0] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m, - [1] = OMX_COLOR_FormatYUV420SemiPlanar, - [2] = OMX_COLOR_FormatYUV420Planar, + [1] = OMX_COLOR_FormatYUV420Planar, + [2] = OMX_COLOR_FormatYUV420SemiPlanar, [3] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView, }; format = (index < sizeof(formatsDefault) / sizeof(OMX_COLOR_FORMATTYPE)) ? @@ -1157,6 +1157,7 @@ class omx_vdec: public qc_omx_component } static OMX_ERRORTYPE describeColorFormat(OMX_PTR params); + void prefetchNewBuffers(); }; diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp index 32dac93e..ff0c869c 100644 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp @@ -149,6 +149,8 @@ extern "C" { static OMX_U32 maxSmoothStreamingWidth = 1920; static OMX_U32 maxSmoothStreamingHeight = 1088; +bool omx_vdec::m_disable_ubwc_mode; + void* async_message_thread (void *input) { OMX_BUFFERHEADERTYPE *buffer; @@ -1662,6 +1664,10 @@ void omx_vdec::process_event_cb(void *ctxt, unsigned char id) pThis->m_debug.out_uvmeta_file = NULL; } + if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) { + pThis->prefetchNewBuffers(); + } + if (pThis->m_cb.EventHandler) { uint32_t frame_data[2]; frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ? @@ -4395,6 +4401,24 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, paramIndex); break; } + case OMX_QTIIndexParamLowLatencyMode: { + struct v4l2_control control; + int rc = 0; + QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE* pParam = + (QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE*)paramData; + if (pParam->bLowLatencyMode) { + DEBUG_PRINT_HIGH("Enabling DECODE order"); + time_stamp_dts.set_timestamp_reorder_mode(false); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; + control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Set picture order failed"); + eRet = OMX_ErrorUnsupportedSetting; + } + } + break; + } case OMX_QcomIndexParamVideoDecoderPictureOrder: { QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder = (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData; @@ -4964,110 +4988,7 @@ OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_LOW("Set Config Called"); - if (configIndex == (OMX_INDEXTYPE)OMX_IndexVendorVideoExtraData) { - OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData; - DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData called"); - if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc") || - !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc")) { - DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData AVC"); - OMX_U32 extra_size; - // Parsing done here for the AVC atom is definitely not generic - // Currently this piece of code is working, but certainly - // not tested with all .mp4 files. - // Incase of failure, we might need to revisit this - // for a generic piece of code. - - // Retrieve size of NAL length field - // byte #4 contains the size of NAL lenght field - nal_length = (config->pData[4] & 0x03) + 1; - - extra_size = 0; - if (nal_length > 2) { - /* Presently we assume that only one SPS and one PPS in AvC1 Atom */ - extra_size = (nal_length - 2) * 2; - } - - // SPS starts from byte #6 - OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]); - OMX_U8 *pDestBuf; - m_vendor_config.nPortIndex = config->nPortIndex; - - // minus 6 --> SPS starts from byte #6 - // minus 1 --> picture param set byte to be ignored from avcatom - m_vendor_config.nDataSize = config->nDataSize - 6 - 1 + extra_size; - m_vendor_config.pData = (OMX_U8 *) malloc(m_vendor_config.nDataSize); - OMX_U32 len; - OMX_U8 index = 0; - // case where SPS+PPS is sent as part of set_config - pDestBuf = m_vendor_config.pData; - - DEBUG_PRINT_LOW("Rxd SPS+PPS nPortIndex[%u] len[%u] data[%p]", - (unsigned int)m_vendor_config.nPortIndex, - (unsigned int)m_vendor_config.nDataSize, - m_vendor_config.pData); - while (index < 2) { - uint8 *psize; - len = *pSrcBuf; - len = len << 8; - len |= *(pSrcBuf + 1); - psize = (uint8 *) & len; - memcpy(pDestBuf + nal_length, pSrcBuf + 2,len); - for (unsigned int i = 0; i < nal_length; i++) { - pDestBuf[i] = psize[nal_length - 1 - i]; - } - //memcpy(pDestBuf,pSrcBuf,(len+2)); - pDestBuf += len + nal_length; - pSrcBuf += len + 2; - index++; - pSrcBuf++; // skip picture param set - len = 0; - } - } else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4") || - !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2")) { - m_vendor_config.nPortIndex = config->nPortIndex; - m_vendor_config.nDataSize = config->nDataSize; - m_vendor_config.pData = (OMX_U8 *) malloc((config->nDataSize)); - memcpy(m_vendor_config.pData, config->pData,config->nDataSize); - } else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1")) { - if (m_vendor_config.pData) { - free(m_vendor_config.pData); - m_vendor_config.pData = NULL; - m_vendor_config.nDataSize = 0; - } - - if (((*((OMX_U32 *) config->pData)) & - VC1_SP_MP_START_CODE_MASK) == - VC1_SP_MP_START_CODE) { - DEBUG_PRINT_LOW("set_config - VC1 simple/main profile"); - m_vendor_config.nPortIndex = config->nPortIndex; - m_vendor_config.nDataSize = config->nDataSize; - m_vendor_config.pData = - (OMX_U8 *) malloc(config->nDataSize); - memcpy(m_vendor_config.pData, config->pData, - config->nDataSize); - m_vc1_profile = VC1_SP_MP_RCV; - } else if (*((OMX_U32 *) config->pData) == VC1_AP_SEQ_START_CODE) { - DEBUG_PRINT_LOW("set_config - VC1 Advance profile"); - m_vendor_config.nPortIndex = config->nPortIndex; - m_vendor_config.nDataSize = config->nDataSize; - m_vendor_config.pData = - (OMX_U8 *) malloc((config->nDataSize)); - memcpy(m_vendor_config.pData, config->pData, - config->nDataSize); - m_vc1_profile = VC1_AP; - } else if ((config->nDataSize == VC1_STRUCT_C_LEN)) { - DEBUG_PRINT_LOW("set_config - VC1 Simple/Main profile struct C only"); - m_vendor_config.nPortIndex = config->nPortIndex; - m_vendor_config.nDataSize = config->nDataSize; - m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize); - memcpy(m_vendor_config.pData,config->pData,config->nDataSize); - m_vc1_profile = VC1_SP_MP_RCV; - } else { - DEBUG_PRINT_LOW("set_config - Error: Unknown VC1 profile"); - } - } - return ret; - } else if (configIndex == OMX_IndexConfigVideoNalSize) { + if (configIndex == OMX_IndexConfigVideoNalSize) { struct v4l2_control temp; temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT; @@ -5318,6 +5239,8 @@ OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB; } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) { *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB; + } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) { + *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode; } else { DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName); return OMX_ErrorNotImplemented; @@ -7098,7 +7021,8 @@ if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) { rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); if (rc) { - DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver"); + DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client"); + m_cb.EmptyBufferDone(hComp, m_app_data, buffer); return OMX_ErrorHardware; } @@ -7193,6 +7117,7 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, //We'll restore this size later on, so that it's transparent to client buffer->nFilledLen = 0; buffer->nAllocLen = handle->size; + drv_ctx.op_buf.buffer_size = handle->size; } @@ -7333,7 +7258,8 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); if (rc) { /*TODO: How to handle this case */ - DEBUG_PRINT_ERROR("Failed to qbuf to driver"); + DEBUG_PRINT_ERROR("Failed to qbuf to driver, send FTB back to client"); + m_cb.FillBufferDone(hComp, m_app_data, buffer); } return OMX_ErrorNone; } @@ -9683,10 +9609,24 @@ OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) fmt.fmt.pix_mp.pixelformat = output_capability; } else if (1 == portDefn->nPortIndex) { unsigned int buf_size = 0; + int ret = 0; if (!client_buffers.update_buffer_req()) { DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed"); return OMX_ErrorHardware; } + + memset(&fmt, 0x0, sizeof(struct v4l2_format)); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.pixelformat = capture_capability; + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); + if (ret) { + DEBUG_PRINT_ERROR("Get Resolution failed"); + return OMX_ErrorHardware; + } + drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; + drv_ctx.op_buf.buffer_size += drv_ctx.extradata_info.buffer_size; + drv_ctx.op_buf.buffer_size = (drv_ctx.op_buf.buffer_size + drv_ctx.op_buf.alignment - 1)&(~(drv_ctx.op_buf.alignment - 1)); + if (!client_buffers.get_buffer_req(buf_size)) { DEBUG_PRINT_ERROR("update buffer requirements"); return OMX_ErrorHardware; @@ -11869,3 +11809,105 @@ OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) { #endif //FLEXYUV_SUPPORTED } +void omx_vdec::prefetchNewBuffers() { + + struct v4l2_decoder_cmd dec; + uint32_t prefetch_count; + uint32_t prefetch_size; + uint32_t want_size; + uint32_t have_size; + int color_fmt, rc; + uint32_t new_calculated_size; + uint32_t new_buffer_size; + uint32_t new_buffer_count; + uint32_t old_buffer_size; + uint32_t old_buffer_count; + + memset((void *)&dec, 0 , sizeof(dec)); + DEBUG_PRINT_LOW("Old size : %d, count : %d, width : %u, height : %u\n", + drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount, + drv_ctx.video_resolution.frame_width, + drv_ctx.video_resolution.frame_height); + dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT; + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) { + DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno); + } else { + DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n", + dec.raw.data[0], dec.raw.data[1]); + } + + switch ((int)drv_ctx.output_format) { + case VDEC_YUV_FORMAT_NV12: + color_fmt = COLOR_FMT_NV12; + break; + case VDEC_YUV_FORMAT_NV12_UBWC: + color_fmt = COLOR_FMT_NV12_UBWC; + break; + default: + color_fmt = -1; + } + + new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height); + DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n", + m_reconfig_width, m_reconfig_height, new_calculated_size); + new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size; + new_buffer_count = dec.raw.data[1]; + old_buffer_size = drv_ctx.op_buf.buffer_size; + old_buffer_count = drv_ctx.op_buf.actualcount; + + new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count; + + prefetch_count = new_buffer_count; + prefetch_size = new_buffer_size - old_buffer_size; + want_size = new_buffer_size * new_buffer_count; + have_size = old_buffer_size * old_buffer_count; + + if (want_size > have_size) { + DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size); + DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size); + + int ion_fd = open(MEM_DEVICE, O_RDONLY); + if (ion_fd < 0) { + DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd); + return; + } + + struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data)); + struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data)); + struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions)); + size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count); + + if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) { + DEBUG_PRINT_ERROR("prefetch data allocation failed"); + goto prefetch_exit; + } + + for (uint32_t i = 0; i < prefetch_count; i++) { + sizes[i] = prefetch_size; + } + + regions[0].nr_sizes = prefetch_count; + regions[0].sizes = sizes; + regions[0].vmid = ION_FLAG_CP_PIXEL; + + prefetch_data->nr_regions = 1; + prefetch_data->regions = regions; + prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID); + + custom_data->cmd = ION_IOC_PREFETCH; + custom_data->arg = (unsigned long )prefetch_data; + + rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data); + if (rc) { + DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno); + } + +prefetch_exit: + close(ion_fd); + free(sizes); + free(regions); + free(prefetch_data); + free(custom_data); + } +} + diff --git a/mm-video-v4l2/vidc/venc/Android.mk b/mm-video-v4l2/vidc/venc/Android.mk index 9c98966b..6d4855d5 100644 --- a/mm-video-v4l2/vidc/venc/Android.mk +++ b/mm-video-v4l2/vidc/venc/Android.mk @@ -39,6 +39,7 @@ endif ifeq ($(TARGET_BOARD_PLATFORM),msm8996) libmm-venc-def += -D_UBWC_ +libmm-venc-def += -D_VQZIP_ endif ifeq ($(call is-board-platform-in-list, $(TARGETS_THAT_USE_FLAG_MSM8226)),true) diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h index d9e5a4a4..afbe48f9 100644 --- a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h +++ b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -136,9 +136,10 @@ static const char* MEM_DEVICE = "/dev/pmem_smipool"; & BITMASK_FLAG(mIndex)) #define BITMASK_ABSENT(mArray,mIndex) (((mArray)[BITMASK_OFFSET(mIndex)] \ & BITMASK_FLAG(mIndex)) == 0x0) -#ifdef _ANDROID_ICS_ + #define MAX_NUM_INPUT_BUFFERS 64 -#endif +#define MAX_NUM_OUTPUT_BUFFERS 64 + void* message_thread(void *); enum omx_venc_extradata_types { @@ -147,6 +148,7 @@ enum omx_venc_extradata_types { VENC_EXTRADATA_FRAMEDIMENSION = 0x1000000, VENC_EXTRADATA_YUV_STATS = 0x800, VENC_EXTRADATA_VQZIP = 0x02000000, + VENC_EXTRADATA_ROI = 0x04000000, }; // OMX video class @@ -233,9 +235,8 @@ class omx_video: public qc_omx_component virtual bool dev_loaded_start_done(void) = 0; virtual bool dev_loaded_stop_done(void) = 0; virtual bool is_secure_session(void) = 0; - virtual int dev_handle_output_extradata(void*) = 0; - virtual int dev_handle_input_extradata(void*, int) = 0; - virtual void dev_set_extradata_cookie(void*) = 0; + virtual int dev_handle_output_extradata(void*, int) = 0; + virtual int dev_handle_input_extradata(void*, int, int) = 0; virtual int dev_set_format(int) = 0; virtual bool dev_is_video_session_supported(OMX_U32 width, OMX_U32 height) = 0; virtual bool dev_get_capability_ltrcount(OMX_U32 *, OMX_U32 *, OMX_U32 *) = 0; @@ -244,6 +245,7 @@ class omx_video: public qc_omx_component virtual bool dev_get_vqzip_sei_info(OMX_U32 *) = 0; virtual bool dev_get_peak_bitrate(OMX_U32 *) = 0; virtual bool dev_get_batch_size(OMX_U32 *) = 0; + virtual bool dev_buffer_ready_to_queue(OMX_BUFFERHEADERTYPE *buffer) = 0; #ifdef _ANDROID_ICS_ void omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer); #endif @@ -626,13 +628,19 @@ class omx_video: public qc_omx_component QOMX_VIDEO_HIERARCHICALLAYERS m_sHierLayers; OMX_QOMX_VIDEO_MBI_STATISTICS m_sMBIStatistics; QOMX_EXTNINDEX_VIDEO_INITIALQP m_sParamInitqp; - QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS m_sMaxHPlayers; + QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS m_sHPlayers; OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID m_sBaseLayerID; OMX_SKYPE_VIDEO_PARAM_DRIVERVER m_sDriverVer; OMX_SKYPE_VIDEO_CONFIG_QP m_sConfigQP; QOMX_EXTNINDEX_VIDEO_VENC_SAR m_sSar; QOMX_VIDEO_H264ENTROPYCODINGTYPE m_sParamEntropy; PrependSPSPPSToIDRFramesParams m_sPrependSPSPPS; + struct timestamp_info { + OMX_U64 m_TimeStamp; + bool is_buffer_pending; + OMX_BUFFERHEADERTYPE *pending_buffer; + pthread_mutex_t m_lock; + } timestamp; OMX_U32 m_sExtraData; OMX_U32 m_input_msg_id; QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE m_slowLatencyMode; diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_common.h b/mm-video-v4l2/vidc/venc/inc/omx_video_common.h index 58f14fa0..bb0c29a7 100644 --- a/mm-video-v4l2/vidc/venc/inc/omx_video_common.h +++ b/mm-video-v4l2/vidc/venc/inc/omx_video_common.h @@ -87,16 +87,13 @@ struct venc_debug_cap { bool in_buffer_log; bool out_buffer_log; bool extradata_log; - bool roiqp_log; char infile_name[PROPERTY_VALUE_MAX]; char outfile_name[PROPERTY_VALUE_MAX]; char extradatafile_name[PROPERTY_VALUE_MAX]; - char roiqpfile_name[PROPERTY_VALUE_MAX]; char log_loc[PROPERTY_VALUE_MAX]; FILE *infile; FILE *outfile; FILE *extradatafile; - FILE *roiqpfile; }; #ifdef USE_ION struct venc_ion { diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h b/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h index 8ccd6785..fbb3ecf1 100644 --- a/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h +++ b/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h @@ -59,9 +59,8 @@ class omx_venc: public omx_video //OMX strucutres OMX_U32 m_nVenc_format; class venc_dev *handle; - int dev_handle_output_extradata(void *); - int dev_handle_input_extradata(void *, int); - void dev_set_extradata_cookie(void *); + int dev_handle_output_extradata(void *, int); + int dev_handle_input_extradata(void *, int, int); int dev_set_format(int); private: OMX_U32 dev_stop(void); @@ -75,6 +74,7 @@ class omx_venc: public omx_video bool dev_free_buf( void *,unsigned); bool dev_empty_buf(void *, void *,unsigned,unsigned); bool dev_fill_buf(void *, void *,unsigned,unsigned); + bool dev_buffer_ready_to_queue(OMX_BUFFERHEADERTYPE *buffer); bool dev_get_buf_req(OMX_U32 *,OMX_U32 *,OMX_U32 *,OMX_U32); bool dev_set_buf_req(OMX_U32 *,OMX_U32 *,OMX_U32 *,OMX_U32); bool update_profile_level(); 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 4499a1b2..e03990a5 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 @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -34,7 +34,9 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "OMX_VideoExt.h" #include "OMX_QCOMExtns.h" #include "qc_omx_component.h" +#ifdef _VQZIP_ #include "VQZip.h" +#endif #include "omx_video_common.h" #include "omx_video_base.h" #include "omx_video_encoder.h" @@ -241,47 +243,16 @@ enum v4l2_ports { MAX_PORT }; -class encExtradata { -private: - enum { - FREE, - BUSY, - FOR_CONFIG, - }; - struct info { - int status; - void *cookie; - }; - pthread_mutex_t lock; - unsigned int mCount; - ssize_t mSize; - char *mUaddr; - struct venc_ion mIon; - struct info mIndex[MAX_V4L2_BUFS]; - class omx_venc *mVencHandle; - int __get(char **userptr, int *fd, unsigned *offset, ssize_t *size, int type); - OMX_ERRORTYPE __allocate(); - void __free(); - void __debug(); -public: - unsigned int mDbgEtbCount; - encExtradata(class omx_venc *venc_handle); - ~encExtradata(); - void update(unsigned int count, ssize_t size); - /* Get extradata whose status is FREE. */ - OMX_ERRORTYPE get(char **userptr, int *fd, unsigned *offset, ssize_t *size); - /* Get extradata which is tagged with cookie via setCookieForConfigExtradata. If no extradata is tagged with this cookie then get extradata whose status is FREE. */ - OMX_ERRORTYPE get(void *cookie, char **userptr, int *fd, unsigned *offset, ssize_t *size); - /* return the extradata back to the pool of FREE extradata. */ - OMX_ERRORTYPE put(char *userptr); - /* If there is already an extradata with status FOR_CONFIG, return that else return FREE extradata. */ - OMX_ERRORTYPE getForConfig(char **userptr, int *fd, unsigned *offset, ssize_t *size); - /* Return the extradata pointer corresponding to the index. Does not change status of extradata. */ - OMX_ERRORTYPE peek(unsigned index, char **userptr, int *fd, unsigned* offset, ssize_t *size); - /* Attach a cookie to extradata. Extradata with this cookie can be retrieved via getExtradata call.*/ - void setCookieForConfig(void *cookie); - ssize_t getBufferSize(); - unsigned int getBufferCount(); +struct extradata_buffer_info { + unsigned long buffer_size; + char* uaddr; + int count; + int size; + OMX_BOOL allocated; + enum v4l2_ports port_index; +#ifdef USE_ION + struct venc_ion ion; +#endif bool vqzip_sei_found; }; @@ -352,8 +323,8 @@ class venc_dev unsigned long inputformat); int venc_extradata_log_buffers(char *buffer_addr); bool venc_set_bitrate_type(OMX_U32 type); - int venc_roiqp_log_buffers(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo); +#ifdef _VQZIP_ class venc_dev_vqzip { public: @@ -376,6 +347,7 @@ class venc_dev vqzip_compute_stats_t mVQZIPComputeStats; }; venc_dev_vqzip vqzip; +#endif struct venc_debug_cap m_debug; OMX_U32 m_nDriver_fd; int m_poll_efd; @@ -403,17 +375,17 @@ class venc_dev bool async_thread_created; bool async_thread_force_stop; class omx_venc *venc_handle; + OMX_ERRORTYPE allocate_extradata(struct extradata_buffer_info *extradata_info); + void free_extradata(); int append_mbi_extradata(void *, struct msm_vidc_extradata_header*); - bool handle_output_extradata(void *); - bool handle_input_extradata(void *, int); + bool handle_output_extradata(void *, int); + bool handle_input_extradata(void *, int, int); int venc_set_format(int); bool deinterlace_enabled; bool hw_overload; bool is_gralloc_source_ubwc; bool is_camera_source_ubwc; OMX_U32 fd_list[64]; - encExtradata mInputExtradata; - encExtradata mOutputExtradata; private: OMX_U32 m_codec; @@ -494,8 +466,9 @@ class venc_dev bool venc_set_batch_size(OMX_U32 size); bool venc_calibrate_gop(); bool venc_set_vqzip_defaults(); + int venc_get_index_from_fd(OMX_U32 fd); bool venc_validate_hybridhp_params(OMX_U32 layers, OMX_U32 bFrames, OMX_U32 count, int mode); - bool venc_set_max_hierp(OMX_U32 hierp_layers); + bool venc_set_hierp_layers(OMX_U32 hierp_layers); bool venc_set_baselayerid(OMX_U32 baseid); bool venc_set_qp(OMX_U32 nQp); bool venc_set_aspectratio(void *nSar); @@ -503,8 +476,8 @@ class venc_dev bool venc_set_session_priority(OMX_U32 priority); bool venc_set_operatingrate(OMX_U32 rate); bool venc_set_layer_bitrates(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hpmode); - bool venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo); bool venc_set_low_latency(OMX_BOOL enable); + bool venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo); #ifdef MAX_RES_1080P OMX_U32 pmem_free(); @@ -523,6 +496,8 @@ class venc_dev int metadatamode; bool streaming[MAX_PORT]; bool extradata; + struct extradata_buffer_info input_extradata_info; + struct extradata_buffer_info output_extradata_info; pthread_mutex_t pause_resume_mlock; pthread_cond_t pause_resume_cond; @@ -534,6 +509,10 @@ class venc_dev bool is_thulium_v1; bool camera_mode_enabled; OMX_BOOL low_latency_mode; + struct { + bool dirty; + OMX_QTI_VIDEO_CONFIG_ROIINFO info; + } roi; bool venc_empty_batch (OMX_BUFFERHEADERTYPE *buf, unsigned index); static const int kMaxBuffersInBatch = 16; diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp index 63a37f0b..7f669842 100644 --- a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp +++ b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2015, Linux Foundation. All rights reserved. +Copyright (c) 2010-2016, 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: @@ -311,6 +311,8 @@ omx_video::omx_video(): mUsesColorConversion = false; pthread_mutex_init(&m_lock, NULL); + pthread_mutex_init(×tamp.m_lock, NULL); + timestamp.is_buffer_pending = false; sem_init(&m_cmd_lock,0,0); DEBUG_PRINT_LOW("meta_buffer_hdr = %p", meta_buffer_hdr); } @@ -350,6 +352,7 @@ omx_video::~omx_video() pthread_join(async_thread_id,NULL); #endif pthread_mutex_destroy(&m_lock); + pthread_mutex_destroy(×tamp.m_lock); sem_destroy(&m_cmd_lock); DEBUG_PRINT_HIGH("m_etb_count = %" PRIu64 ", m_fbd_count = %" PRIu64, m_etb_count, m_fbd_count); @@ -2167,12 +2170,12 @@ OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, } break; } - case OMX_QcomIndexConfigMaxHierPLayers: + case OMX_QcomIndexConfigNumHierPLayers: { - QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS* pParam = - reinterpret_cast<QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS*>(configData); - DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigMaxHierPLayers"); - memcpy(pParam, &m_sMaxHPlayers, sizeof(m_sMaxHPlayers)); + QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS* pParam = + reinterpret_cast<QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS*>(configData); + DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigNumHierPLayers"); + memcpy(pParam, &m_sHPlayers, sizeof(m_sHPlayers)); break; } case OMX_QcomIndexConfigQp: @@ -2274,7 +2277,7 @@ OMX_ERRORTYPE omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, if (!strncmp(paramName, "OMX.QCOM.index.config.video.hierplayers", sizeof("OMX.QCOM.index.config.video.hierplayers") - 1)) { - *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigMaxHierPLayers; + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigNumHierPLayers; return OMX_ErrorNone; } @@ -2302,23 +2305,30 @@ OMX_ERRORTYPE omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, return OMX_ErrorNone; } + if (!strncmp(paramName, "OMX.QTI.index.param.video.LowLatency", + sizeof("OMX.QTI.index.param.video.LowLatency") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode; + return OMX_ErrorNone; + } + + if (!strncmp(paramName, OMX_QTI_INDEX_CONFIG_VIDEO_SETTIMEDATA, + sizeof(OMX_QTI_INDEX_CONFIG_VIDEO_SETTIMEDATA) - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_IndexConfigTimePosition; + return OMX_ErrorNone; + } + if (!strncmp(paramName, OMX_QTI_INDEX_PARAM_VIDEO_ENABLE_ROIINFO, sizeof(OMX_QTI_INDEX_PARAM_VIDEO_ENABLE_ROIINFO) - 1)) { *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoEnableRoiInfo; return OMX_ErrorNone; } + if (!strncmp(paramName, OMX_QTI_INDEX_CONFIG_VIDEO_ROIINFO, sizeof(OMX_QTI_INDEX_CONFIG_VIDEO_ROIINFO) - 1)) { *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigVideoRoiInfo; return OMX_ErrorNone; } - if (!strncmp(paramName, "OMX.QTI.index.param.video.LowLatency", - sizeof("OMX.QTI.index.param.video.LowLatency") - 1)) { - *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode; - return OMX_ErrorNone; - } - return OMX_ErrorNotImplemented; } @@ -2645,7 +2655,6 @@ OMX_ERRORTYPE omx_video::use_output_buffer( *bufferHdr = (m_out_mem_ptr + i ); (*bufferHdr)->pBuffer = (OMX_U8 *)buffer; (*bufferHdr)->pAppPrivate = appData; - BITMASK_SET(&m_out_bm_count,i); if (!m_use_output_pmem) { #ifdef USE_ION @@ -2724,6 +2733,8 @@ OMX_ERRORTYPE omx_video::use_output_buffer( DEBUG_PRINT_ERROR("ERROR: dev_use_buf Failed for o/p buf"); return OMX_ErrorInsufficientResources; } + + BITMASK_SET(&m_out_bm_count,i); } else { DEBUG_PRINT_ERROR("ERROR: All o/p Buffers have been Used, invalid use_buf call for " "index = %u", i); @@ -3427,7 +3438,8 @@ OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %u, actual cnt %u", nPortIndex, (unsigned int)m_sInPortDef.nBufferCountActual); - if (nPortIndex < m_sInPortDef.nBufferCountActual) { + if (nPortIndex < m_sInPortDef.nBufferCountActual && + BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) { // Clear the bit associated with it. BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); free_input_buffer (buffer); @@ -3477,7 +3489,8 @@ OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %u, actual cnt %u", nPortIndex, (unsigned int)m_sOutPortDef.nBufferCountActual); - if (nPortIndex < m_sOutPortDef.nBufferCountActual) { + if (nPortIndex < m_sOutPortDef.nBufferCountActual && + BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) { // Clear the bit associated with it. BITMASK_CLEAR(&m_out_bm_count,nPortIndex); m_sOutPortDef.bPopulated = OMX_FALSE; @@ -3563,7 +3576,6 @@ OMX_ERRORTYPE omx_video::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_ERRORTYPE ret1 = OMX_ErrorNone; unsigned int nBufferIndex ; - dev_set_extradata_cookie((void *)buffer); DEBUG_PRINT_LOW("ETB: buffer = %p, buffer->pBuffer[%p]", buffer, buffer->pBuffer); if (m_state == OMX_StateInvalid) { DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State"); @@ -3756,7 +3768,7 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, return OMX_ErrorUndefined; } } - if (m_sExtraData && !dev_handle_input_extradata((void *)buffer, fd)) { + if (m_sExtraData && !dev_handle_input_extradata((void *)buffer, nBufIndex,fd)) { DEBUG_PRINT_ERROR("Failed to parse input extradata\n"); #ifdef _ANDROID_ICS_ omx_release_meta_buffer(buffer); @@ -4284,7 +4296,7 @@ OMX_ERRORTYPE omx_video::fill_buffer_done(OMX_HANDLETYPE hComp, } } if (buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) { - if (!dev_handle_output_extradata((void *)buffer)) + if (!dev_handle_output_extradata((void *)buffer, index)) DEBUG_PRINT_ERROR("Failed to parse output extradata"); dev_extradata_log_buffers((char *)(((unsigned long)buffer->pBuffer + buffer->nOffset + @@ -4851,6 +4863,12 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_opaque(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Invalid buffer[%p]",buffer); return OMX_ErrorBadParameter; } + + if (!dev_buffer_ready_to_queue(buffer)) { + DEBUG_PRINT_HIGH("Info: ETBProxyA: buffer[%p] is deffered", buffer); + return OMX_ErrorNone; + } + nBufIndex = buffer - meta_buffer_hdr; if (nBufIndex >= m_sInPortDef.nBufferCountActual) { DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Invalid bufindex = %u", 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 75ae1d62..365bff89 100644 --- a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp +++ b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp @@ -660,6 +660,11 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_LOW("i/p actual cnt requested = %u", (unsigned int)portDefn->nBufferCountActual); DEBUG_PRINT_LOW("i/p min cnt requested = %u", (unsigned int)portDefn->nBufferCountMin); DEBUG_PRINT_LOW("i/p buffersize requested = %u", (unsigned int)portDefn->nBufferSize); + if (portDefn->nBufferCountActual > MAX_NUM_INPUT_BUFFERS) { + DEBUG_PRINT_ERROR("ERROR: (In_PORT) actual count (%u) exceeds max(%u)", + (unsigned int)portDefn->nBufferCountActual, (unsigned int)MAX_NUM_INPUT_BUFFERS); + return OMX_ErrorUnsupportedSetting; + } if (portDefn->nBufferCountMin > portDefn->nBufferCountActual) { DEBUG_PRINT_ERROR("ERROR: (In_PORT) Min buffers (%u) > actual count (%u)", (unsigned int)portDefn->nBufferCountMin, (unsigned int)portDefn->nBufferCountActual); @@ -708,6 +713,12 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_LOW("o/p actual cnt requested = %u", (unsigned int)portDefn->nBufferCountActual); DEBUG_PRINT_LOW("o/p min cnt requested = %u", (unsigned int)portDefn->nBufferCountMin); DEBUG_PRINT_LOW("o/p buffersize requested = %u", (unsigned int)portDefn->nBufferSize); + + if (portDefn->nBufferCountActual > MAX_NUM_OUTPUT_BUFFERS) { + DEBUG_PRINT_ERROR("ERROR: (Out_PORT) actual count (%u) exceeds max(%u)", + (unsigned int)portDefn->nBufferCountActual, (unsigned int)MAX_NUM_OUTPUT_BUFFERS); + return OMX_ErrorUnsupportedSetting; + } if (portDefn->nBufferCountMin > portDefn->nBufferCountActual) { DEBUG_PRINT_ERROR("ERROR: (Out_PORT) Min buffers (%u) > actual count (%u)", (unsigned int)portDefn->nBufferCountMin, (unsigned int)portDefn->nBufferCountActual); @@ -1558,23 +1569,24 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, memcpy(&m_sSar, paramData, sizeof(m_sSar)); break; } - case OMX_QTIIndexParamVideoEnableRoiInfo: + case OMX_QTIIndexParamLowLatencyMode: { if (!handle->venc_set_param(paramData, - (OMX_INDEXTYPE)OMX_QTIIndexParamVideoEnableRoiInfo)) { - DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamVideoEnableRoiInfo failed"); + (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode)) { + DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamLowLatencyMode failed"); return OMX_ErrorUnsupportedSetting; } + memcpy(&m_slowLatencyMode, paramData, sizeof(m_slowLatencyMode)); break; } - case OMX_QTIIndexParamLowLatencyMode: + case OMX_QTIIndexParamVideoEnableRoiInfo: { if (!handle->venc_set_param(paramData, - (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode)) { - DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamLowLatencyMode failed"); + (OMX_INDEXTYPE)OMX_QTIIndexParamVideoEnableRoiInfo)) { + DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamVideoEnableRoiInfo failed"); return OMX_ErrorUnsupportedSetting; } - memcpy(&m_slowLatencyMode, paramData, sizeof(m_slowLatencyMode)); + m_sExtraData |= VENC_EXTRADATA_ROI; break; } case OMX_IndexParamVideoSliceFMO: @@ -1921,15 +1933,15 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } break; } - case OMX_QcomIndexConfigMaxHierPLayers: + case OMX_QcomIndexConfigNumHierPLayers: { - QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS* pParam = - (QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS*)configData; - if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)OMX_QcomIndexConfigMaxHierPLayers)) { - DEBUG_PRINT_ERROR("ERROR: Setting OMX_QcomIndexConfigMaxHierPLayers failed"); + QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS* pParam = + (QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS*)configData; + if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)OMX_QcomIndexConfigNumHierPLayers)) { + DEBUG_PRINT_ERROR("ERROR: Setting OMX_QcomIndexConfigNumHierPLayers failed"); return OMX_ErrorUnsupportedSetting; } - memcpy(&m_sMaxHPlayers, pParam, sizeof(m_sMaxHPlayers)); + memcpy(&m_sHPlayers, pParam, sizeof(m_sHPlayers)); break; } case OMX_QcomIndexConfigBaseLayerId: @@ -1979,6 +1991,22 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } break; } + case OMX_IndexConfigTimePosition: + { + OMX_TIME_CONFIG_TIMESTAMPTYPE* pParam = + (OMX_TIME_CONFIG_TIMESTAMPTYPE*) configData; + pthread_mutex_lock(×tamp.m_lock); + timestamp.m_TimeStamp = (OMX_U64)pParam->nTimestamp; + DEBUG_PRINT_LOW("Buffer = %p, Timestamp = %llu", timestamp.pending_buffer, (OMX_U64)pParam->nTimestamp); + if (timestamp.is_buffer_pending && (OMX_U64)timestamp.pending_buffer->nTimeStamp == timestamp.m_TimeStamp) { + DEBUG_PRINT_INFO("Queueing back pending buffer %p", timestamp.pending_buffer); + this->post_event((unsigned long)hComp,(unsigned long)timestamp.pending_buffer,m_input_msg_id); + timestamp.pending_buffer = NULL; + timestamp.is_buffer_pending = false; + } + pthread_mutex_unlock(×tamp.m_lock); + break; + } default: DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); break; @@ -2013,7 +2041,14 @@ OMX_ERRORTYPE omx_venc::component_deinit(OMX_IN OMX_HANDLETYPE hComp) if (m_out_mem_ptr) { DEBUG_PRINT_LOW("Freeing the Output Memory"); for (i=0; i< m_sOutPortDef.nBufferCountActual; i++ ) { - free_output_buffer (&m_out_mem_ptr[i]); + if (BITMASK_PRESENT(&m_out_bm_count, i)) { + BITMASK_CLEAR(&m_out_bm_count, i); + free_output_buffer (&m_out_mem_ptr[i]); + } + + if (release_output_done()) { + break; + } } free(m_out_mem_ptr); m_out_mem_ptr = NULL; @@ -2027,7 +2062,14 @@ OMX_ERRORTYPE omx_venc::component_deinit(OMX_IN OMX_HANDLETYPE hComp) ) { DEBUG_PRINT_LOW("Freeing the Input Memory"); for (i=0; i<m_sInPortDef.nBufferCountActual; i++ ) { - free_input_buffer (&m_inp_mem_ptr[i]); + if (BITMASK_PRESENT(&m_inp_bm_count, i)) { + BITMASK_CLEAR(&m_inp_bm_count, i); + free_input_buffer (&m_inp_mem_ptr[i]); + } + + if (release_input_done()) { + break; + } } @@ -2100,6 +2142,24 @@ bool omx_venc::dev_use_buf(void *buf_addr,unsigned port,unsigned index) return handle->venc_use_buf(buf_addr,port,index); } +bool omx_venc::dev_buffer_ready_to_queue(OMX_BUFFERHEADERTYPE *buffer) +{ + bool bRet = true; + + pthread_mutex_lock(×tamp.m_lock); + + if ((!m_slowLatencyMode.bLowLatencyMode) || ((OMX_U64)buffer->nTimeStamp == (OMX_U64)timestamp.m_TimeStamp)) { + DEBUG_PRINT_LOW("ETB is ready to be queued"); + } else { + DEBUG_PRINT_INFO("ETB is defeffed due to timeStamp mismatch"); + timestamp.is_buffer_pending = true; + timestamp.pending_buffer = buffer; + bRet = false; + } + pthread_mutex_unlock(×tamp.m_lock); + return bRet; +} + bool omx_venc::dev_free_buf(void *buf_addr,unsigned port) { return handle->venc_free_buf(buf_addr,port); @@ -2235,19 +2295,14 @@ bool omx_venc::dev_is_video_session_supported(OMX_U32 width, OMX_U32 height) #endif } -int omx_venc::dev_handle_output_extradata(void *buffer) -{ - return handle->handle_output_extradata(buffer); -} - -int omx_venc::dev_handle_input_extradata(void *buffer, int fd) +int omx_venc::dev_handle_output_extradata(void *buffer, int index) { - return handle->handle_input_extradata(buffer, fd); + return handle->handle_output_extradata(buffer, index); } -void omx_venc::dev_set_extradata_cookie(void *cookie) +int omx_venc::dev_handle_input_extradata(void *buffer, int index, int fd) { - handle->mInputExtradata.setCookieForConfig(cookie); + return handle->handle_input_extradata(buffer, index, fd); } int omx_venc::dev_set_format(int color) 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 ceafc1dc..d4c461a6 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 @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -117,23 +117,63 @@ static const unsigned int h264_profile_level_table[][MAX_PROFILE_PARAMS]= { /* Please update H264_HP_START accordingly, while adding new element */ {0,0,0,0,0,0}, - {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh,396}, - {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh,396}, - {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh,900}, - {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh,2376}, - {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh,2376}, - {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh,2376}, - {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh,4752}, - {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh,8100}, - {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh,8100}, - {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh,18000}, - {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh,20480}, - {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh,32768}, - {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileHigh,32768}, - {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileHigh,34816}, - {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileHigh,110400}, - {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileHigh,184320}, - {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileHigh,184320}, + {99,1485,64000,OMX_VIDEO_AVCLevel1, QOMX_VIDEO_AVCProfileConstrainedBaseline,396}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b, QOMX_VIDEO_AVCProfileConstrainedBaseline,396}, + {396,3000,192000,OMX_VIDEO_AVCLevel11, QOMX_VIDEO_AVCProfileConstrainedBaseline,900}, + {396,6000,384000,OMX_VIDEO_AVCLevel12, QOMX_VIDEO_AVCProfileConstrainedBaseline,2376}, + {396,11880,768000,OMX_VIDEO_AVCLevel13, QOMX_VIDEO_AVCProfileConstrainedBaseline,2376}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2, QOMX_VIDEO_AVCProfileConstrainedBaseline,2376}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21, QOMX_VIDEO_AVCProfileConstrainedBaseline,4752}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22, QOMX_VIDEO_AVCProfileConstrainedBaseline,8100}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3, QOMX_VIDEO_AVCProfileConstrainedBaseline,8100}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31, QOMX_VIDEO_AVCProfileConstrainedBaseline,18000}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32, QOMX_VIDEO_AVCProfileConstrainedBaseline,20480}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4, QOMX_VIDEO_AVCProfileConstrainedBaseline,32768}, + {8192,245760,50000000,OMX_VIDEO_AVCLevel41, QOMX_VIDEO_AVCProfileConstrainedBaseline,32768}, + {8704,522240,50000000,OMX_VIDEO_AVCLevel42, QOMX_VIDEO_AVCProfileConstrainedBaseline,34816}, + {22080,589824,135000000,OMX_VIDEO_AVCLevel5, QOMX_VIDEO_AVCProfileConstrainedBaseline,110400}, + {36864,983040,240000000,OMX_VIDEO_AVCLevel51, QOMX_VIDEO_AVCProfileConstrainedBaseline,184320}, + {36864,2073600,240000000,OMX_VIDEO_AVCLevel52, QOMX_VIDEO_AVCProfileConstrainedBaseline,184320}, + /* Please update H264_HP_START accordingly, while adding new element */ + {0,0,0,0,0,0}, + + {99,1485,80000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh,396}, + {99,1485,200000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh,396}, + {396,3000,300000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh,900}, + {396,6000,600000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh,2376}, + {396,11880,1200000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh,2376}, + {396,11880,3125000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh,2376}, + {792,19800,6250000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh,4752}, + {1620,20250,6250000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh,8100}, + {1620,40500,15625000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh,8100}, + {3600,108000,21875000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh,18000}, + {5120,216000,31250000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh,20480}, + {8192,245760,31250000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh,32768}, + {8192,245760,62500000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileHigh,32768}, + {8704,522240,62500000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileHigh,34816}, + {22080,589824,168750000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileHigh,110400}, + {36864,983040,300000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileHigh,184320}, + {36864,2073600,300000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileHigh,184320}, + /* Please update H264_MP_START accordingly, while adding new element */ + {0,0,0,0,0,0}, + + {99,1485,80000,OMX_VIDEO_AVCLevel1,QOMX_VIDEO_AVCProfileConstrainedHigh,396}, + {99,1485,200000,OMX_VIDEO_AVCLevel1b, QOMX_VIDEO_AVCProfileConstrainedHigh,396}, + {396,3000,300000,OMX_VIDEO_AVCLevel11, QOMX_VIDEO_AVCProfileConstrainedHigh,900}, + {396,6000,600000,OMX_VIDEO_AVCLevel12, QOMX_VIDEO_AVCProfileConstrainedHigh,2376}, + {396,11880,1200000,OMX_VIDEO_AVCLevel13, QOMX_VIDEO_AVCProfileConstrainedHigh,2376}, + {396,11880,3125000,OMX_VIDEO_AVCLevel2, QOMX_VIDEO_AVCProfileConstrainedHigh,2376}, + {792,19800,6250000,OMX_VIDEO_AVCLevel21, QOMX_VIDEO_AVCProfileConstrainedHigh,4752}, + {1620,20250,6250000,OMX_VIDEO_AVCLevel22, QOMX_VIDEO_AVCProfileConstrainedHigh,8100}, + {1620,40500,15625000,OMX_VIDEO_AVCLevel3, QOMX_VIDEO_AVCProfileConstrainedHigh,8100}, + {3600,108000,21875000,OMX_VIDEO_AVCLevel31, QOMX_VIDEO_AVCProfileConstrainedHigh,18000}, + {5120,216000,31250000,OMX_VIDEO_AVCLevel32, QOMX_VIDEO_AVCProfileConstrainedHigh,20480}, + {8192,245760,31250000,OMX_VIDEO_AVCLevel4, QOMX_VIDEO_AVCProfileConstrainedHigh,32768}, + {8192,245760,62500000,OMX_VIDEO_AVCLevel41, QOMX_VIDEO_AVCProfileConstrainedHigh,32768}, + {8704,522240,62500000,OMX_VIDEO_AVCLevel42, QOMX_VIDEO_AVCProfileConstrainedHigh,34816}, + {22080,589824,168750000,OMX_VIDEO_AVCLevel5, QOMX_VIDEO_AVCProfileConstrainedHigh,110400}, + {36864,983040,300000000,OMX_VIDEO_AVCLevel51, QOMX_VIDEO_AVCProfileConstrainedHigh,184320}, + {36864,2073600,300000000,OMX_VIDEO_AVCLevel52, QOMX_VIDEO_AVCProfileConstrainedHigh,184320}, /* Please update H264_MP_START accordingly, while adding new element */ {0,0,0,0,0,0}, @@ -215,7 +255,7 @@ static const unsigned int hevc_profile_level_table[][MAX_PROFILE_PARAMS]= { #define BUFFER_LOG_LOC "/data/misc/media" //constructor -venc_dev::venc_dev(class omx_venc *venc_class):mInputExtradata(venc_class), mOutputExtradata(venc_class) +venc_dev::venc_dev(class omx_venc *venc_class) { //nothing to do int i = 0; @@ -234,8 +274,11 @@ venc_dev::venc_dev(class omx_venc *venc_class):mInputExtradata(venc_class), mOut color_format = 0; hw_overload = false; mBatchSize = 0; + deinterlace_enabled = false; pthread_mutex_init(&pause_resume_mlock, NULL); pthread_cond_init(&pause_resume_cond, NULL); + memset(&input_extradata_info, 0, sizeof(input_extradata_info)); + memset(&output_extradata_info, 0, sizeof(output_extradata_info)); memset(&idrperiod, 0, sizeof(idrperiod)); memset(&multislice, 0, sizeof(multislice)); memset (&slice_mode, 0 , sizeof(slice_mode)); @@ -264,6 +307,7 @@ venc_dev::venc_dev(class omx_venc *venc_class):mInputExtradata(venc_class), mOut memset(<rinfo, 0, sizeof(ltrinfo)); memset(&fd_list, 0, sizeof(fd_list)); memset(&hybrid_hp, 0, sizeof(hybrid_hp)); + memset(&roi, 0, sizeof(roi)); sess_priority.priority = 1; operating_rate = 0; low_latency_mode = OMX_FALSE; @@ -278,8 +322,6 @@ venc_dev::venc_dev(class omx_venc *venc_class):mInputExtradata(venc_class), mOut property_get("vidc.enc.log.extradata", property_value, "0"); m_debug.extradata_log = atoi(property_value); - property_get("vidc.enc.log.roiqp", property_value, "0"); - m_debug.roiqp_log = atoi(property_value); #ifdef _UBWC_ property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0"); if(!(strncmp(property_value, "1", PROPERTY_VALUE_MAX)) || @@ -298,6 +340,7 @@ venc_dev::venc_dev(class omx_venc *venc_class):mInputExtradata(venc_class), mOut venc_dev::~venc_dev() { + //nothing to do } void* venc_dev::async_venc_message_thread (void *input) @@ -379,12 +422,6 @@ void* venc_dev::async_venc_message_thread (void *input) venc_msg.msgcode=VEN_MSG_OUTPUT_BUFFER_DONE; venc_msg.statuscode=VEN_S_SUCCESS; omxhdr=omx_venc_base->m_out_mem_ptr+v4l2_buf.index; - int extra_idx = EXTRADATA_IDX(v4l2_buf.length); - if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { - omxhdr->pPlatformPrivate = (void *)v4l2_buf.m.planes[extra_idx].m.userptr; - } else { - omxhdr->pPlatformPrivate = 0; - } venc_msg.buf.len= v4l2_buf.m.planes->bytesused; venc_msg.buf.offset = v4l2_buf.m.planes->data_offset; venc_msg.buf.flags = 0; @@ -454,14 +491,6 @@ void* venc_dev::async_venc_message_thread (void *input) else omxhdr = &omx_venc_base->m_inp_mem_ptr[v4l2_buf.index]; - int extra_idx = EXTRADATA_IDX(v4l2_buf.length); - if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { - omxhdr->pPlatformPrivate = (void *)v4l2_buf.m.planes[extra_idx].m.userptr; - omx->handle->mInputExtradata.put((char *)omxhdr->pPlatformPrivate); - } else { - omxhdr->pPlatformPrivate = 0; - } - venc_msg.buf.clientdata=(void*)omxhdr; DEBUG_PRINT_LOW("sending EBD %p [id=%d]", omxhdr, v4l2_buf.index); @@ -597,17 +626,13 @@ int venc_dev::append_mbi_extradata(void *dst, struct msm_vidc_extradata_header* return mbi->nDataSize + sizeof(*mbi); } -bool venc_dev::handle_input_extradata(void *buffer, int fd) +bool venc_dev::handle_input_extradata(void *buffer, int index, int fd) { OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *) buffer; OMX_OTHER_EXTRADATATYPE *p_extra = NULL; - ssize_t consumed_len = 0; + unsigned int consumed_len = 0; int enable = 0, i = 0; int height = 0, width = 0; - char *userptr; - int extra_fd; - unsigned offset; - ssize_t extra_size; struct v4l2_control control; memset(&control, 0, sizeof(control)); @@ -618,12 +643,18 @@ bool venc_dev::handle_input_extradata(void *buffer, int fd) if (!(control.value == V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS || control.value == V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI || + control.value == V4L2_MPEG_VIDC_EXTRADATA_ROI_QP || control.value == V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP || control.value == V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP)) { DEBUG_PRINT_LOW("Input extradata not enabled"); return true; } + if (!input_extradata_info.uaddr) { + DEBUG_PRINT_ERROR("Extradata buffers not allocated\n"); + return false; + } + /* * At this point encoder component doesn't know where the extradata is * located in YUV buffer. For all practical usecases, decoder appends @@ -634,20 +665,19 @@ bool venc_dev::handle_input_extradata(void *buffer, int fd) height = ALIGN(m_sVenc_cfg.input_height, 32); width = ALIGN(m_sVenc_cfg.input_width, 32); - int rc = mInputExtradata.get(buffer, &userptr, &extra_fd, &offset, &extra_size); - if (rc != OMX_ErrorNone) { - DEBUG_PRINT_ERROR("Unable to get extradata memory 4"); - return false; - } + index = venc_get_index_from_fd(fd); + unsigned char *pVirt; int size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height); pVirt= (unsigned char *)mmap(NULL, size, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0); p_extra = (OMX_OTHER_EXTRADATATYPE *) ((unsigned long)(pVirt + ((width * height * 3) / 2) + 3)&(~3)); - char *p_extradata = userptr; + char *p_extradata = input_extradata_info.uaddr + index * input_extradata_info.buffer_size; OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata; if (p_extra) { - while ((consumed_len < extra_size) + bool vqzip_sei_found = false; + + while ((consumed_len < input_extradata_info.buffer_size) && (p_extra->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) { DEBUG_PRINT_LOW("Extradata Type = 0x%x", (OMX_QCOM_EXTRADATATYPE)p_extra->eType); switch ((OMX_QCOM_EXTRADATATYPE)p_extra->eType) { @@ -685,13 +715,13 @@ bool venc_dev::handle_input_extradata(void *buffer, int fd) qp_payload = (OMX_QCOM_EXTRADATA_QP *)p_extra->data; payload = (struct msm_vidc_frame_qp_payload *)(data->data); payload->frame_qp = qp_payload->nQP; - DEBUG_PRINT_LOW("Frame QP = %d", payload->frame_qp); + DEBUG_PRINT_LOW("FRame QP = %d", payload->frame_qp); data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize); break; } case OMX_ExtraDataVQZipSEI: DEBUG_PRINT_LOW("VQZIP SEI Found "); - mInputExtradata.vqzip_sei_found = true; + input_extradata_info.vqzip_sei_found = true; break; default: break; @@ -702,12 +732,12 @@ bool venc_dev::handle_input_extradata(void *buffer, int fd) if (control.value == V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS || control.value == V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI) { - if (!mInputExtradata.vqzip_sei_found) { + if (!input_extradata_info.vqzip_sei_found) { DEBUG_PRINT_ERROR("VQZIP is enabled, But no VQZIP SEI found. Rejecting the session"); munmap(pVirt, size); - mInputExtradata.put(userptr); return false; } +#ifdef _VQZIP_ data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct VQZipStats) + 3)&(~3); data->nVersion.nVersion = OMX_SPEC_VERSION; data->nPortIndex = 0; @@ -715,6 +745,7 @@ bool venc_dev::handle_input_extradata(void *buffer, int fd) data->nDataSize = sizeof(struct VQZipStats); vqzip.fill_stats_data((void*)pVirt, (void*) data->data); data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize); +#endif } data->nSize = sizeof(OMX_OTHER_EXTRADATATYPE); @@ -725,21 +756,24 @@ bool venc_dev::handle_input_extradata(void *buffer, int fd) } munmap(pVirt, size); - mInputExtradata.put(userptr); return true; } -bool venc_dev::handle_output_extradata(void *buffer) +bool venc_dev::handle_output_extradata(void *buffer, int index) { OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *) buffer; OMX_OTHER_EXTRADATATYPE *p_extra = NULL; - char *extradata_uaddr = (char *)p_bufhdr->pPlatformPrivate; + + if (!output_extradata_info.uaddr) { + DEBUG_PRINT_ERROR("Extradata buffers not allocated\n"); + return false; + } p_extra = (OMX_OTHER_EXTRADATATYPE *)ALIGN(p_bufhdr->pBuffer + p_bufhdr->nOffset + p_bufhdr->nFilledLen, 4); - if (mOutputExtradata.getBufferSize() > - (ssize_t)(p_bufhdr->nAllocLen - ALIGN(p_bufhdr->nOffset + p_bufhdr->nFilledLen, 4))) { + if (output_extradata_info.buffer_size > + p_bufhdr->nAllocLen - ALIGN(p_bufhdr->nOffset + p_bufhdr->nFilledLen, 4)) { DEBUG_PRINT_ERROR("Insufficient buffer size for extradata"); p_extra = NULL; return false; @@ -752,7 +786,8 @@ bool venc_dev::handle_output_extradata(void *buffer) struct msm_vidc_extradata_header *p_extradata = NULL; do { p_extradata = (struct msm_vidc_extradata_header *) (p_extradata ? - ((char *)p_extradata) + p_extradata->size : extradata_uaddr); + ((char *)p_extradata) + p_extradata->size : + output_extradata_info.uaddr + index * output_extradata_info.buffer_size); switch (p_extradata->type) { case MSM_VIDC_EXTRADATA_METADATA_MBI: @@ -804,7 +839,7 @@ bool venc_dev::handle_output_extradata(void *buffer) p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); } - mOutputExtradata.put(extradata_uaddr); + return true; } @@ -830,6 +865,77 @@ int venc_dev::venc_set_format(int format) return rc; } +OMX_ERRORTYPE venc_dev::allocate_extradata(struct extradata_buffer_info *extradata_info) +{ + if (extradata_info->allocated) { + DEBUG_PRINT_HIGH("2nd allocation return for port = %d",extradata_info->port_index); + return OMX_ErrorNone; + } + +#ifdef USE_ION + + if (extradata_info->buffer_size) { + if (extradata_info->ion.ion_alloc_data.handle) { + munmap((void *)extradata_info->uaddr, extradata_info->size); + close(extradata_info->ion.fd_ion_data.fd); + venc_handle->free_ion_memory(&extradata_info->ion); + } + + extradata_info->size = (extradata_info->size + 4095) & (~4095); + + extradata_info->ion.ion_device_fd = venc_handle->alloc_map_ion_memory( + extradata_info->size, + &extradata_info->ion.ion_alloc_data, + &extradata_info->ion.fd_ion_data, 0); + + if (extradata_info->ion.ion_device_fd < 0) { + DEBUG_PRINT_ERROR("Failed to alloc extradata memory\n"); + return OMX_ErrorInsufficientResources; + } + + extradata_info->uaddr = (char *)mmap(NULL, + extradata_info->size, + PROT_READ|PROT_WRITE, MAP_SHARED, + extradata_info->ion.fd_ion_data.fd , 0); + + if (extradata_info->uaddr == MAP_FAILED) { + DEBUG_PRINT_ERROR("Failed to map extradata memory\n"); + close(extradata_info->ion.fd_ion_data.fd); + venc_handle->free_ion_memory(&extradata_info->ion); + return OMX_ErrorInsufficientResources; + } + } + +#endif + extradata_info->allocated = OMX_TRUE; + return OMX_ErrorNone; +} + +void venc_dev::free_extradata() +{ +#ifdef USE_ION + + if (output_extradata_info.uaddr) { + munmap((void *)output_extradata_info.uaddr, output_extradata_info.size); + close(output_extradata_info.ion.fd_ion_data.fd); + venc_handle->free_ion_memory(&output_extradata_info.ion); + } + + memset(&output_extradata_info, 0, sizeof(output_extradata_info)); + output_extradata_info.ion.fd_ion_data.fd = -1; + + if (input_extradata_info.uaddr) { + munmap((void *)input_extradata_info.uaddr, input_extradata_info.size); + close(input_extradata_info.ion.fd_ion_data.fd); + venc_handle->free_ion_memory(&input_extradata_info.ion); + } + + memset(&input_extradata_info, 0, sizeof(input_extradata_info)); + input_extradata_info.ion.fd_ion_data.fd = -1; + +#endif +} + bool venc_dev::venc_get_output_log_flag() { return (m_debug.out_buffer_log == 1); @@ -919,50 +1025,6 @@ int venc_dev::venc_extradata_log_buffers(char *buffer_addr) return 0; } -int venc_dev::venc_roiqp_log_buffers(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo) { - int size = 0; - if (!roiInfo || !m_debug.roiqp_log) { - DEBUG_PRINT_LOW("Nothing to log"); - return 0; - } - if (!m_debug.roiqpfile) { - size = snprintf(m_debug.roiqpfile_name, PROPERTY_VALUE_MAX, "%s/enc_%lu_%lu_%p.roiqp", - m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); - if ((size > PROPERTY_VALUE_MAX) && (size < 0)) { - DEBUG_PRINT_ERROR("Failed to open ROIQP file: %s for logging size:%d", - m_debug.roiqpfile_name, size); - m_debug.roiqpfile_name[0] = '\0'; - return -1; - } - m_debug.roiqpfile = fopen(m_debug.roiqpfile_name, "ab"); - if (!m_debug.roiqpfile) { - DEBUG_PRINT_ERROR("Failed to open ROI QP file: %s for logging errno:%d", - m_debug.roiqpfile_name, errno); - m_debug.roiqpfile_name[0] = '\0'; - return -1; - } - } - if (m_debug.roiqpfile) { - if (fwrite(&mInputExtradata.mDbgEtbCount, sizeof(mInputExtradata.mDbgEtbCount), 1, m_debug.roiqpfile) != 1) { - DEBUG_PRINT_ERROR("Unable to write to QP file"); - return -1; - } - if (fwrite(&roiInfo->nLowerQpOffset, sizeof(roiInfo->nLowerQpOffset), 1, m_debug.roiqpfile) != 1) { - DEBUG_PRINT_ERROR("Unable to write to QP file"); - return -1; - } - if (fwrite(&roiInfo->nUpperQpOffset, sizeof(roiInfo->nUpperQpOffset), 1, m_debug.roiqpfile) != 1) { - DEBUG_PRINT_ERROR("Unable to write to QP file"); - return -1; - } - if (fwrite((char *)roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoSize, 1, m_debug.roiqpfile) != 1) { - DEBUG_PRINT_ERROR("Unable to write to QP file"); - return -1; - } - } - return 0; -} - int venc_dev::venc_input_log_buffers(OMX_BUFFERHEADERTYPE *pbuffer, int fd, int plane_offset, unsigned long inputformat) { if (!m_debug.infile) { @@ -1302,6 +1364,9 @@ bool venc_dev::venc_open(OMX_U32 codec) DEBUG_PRINT_ERROR("Failed to set turbo mode"); } } + + input_extradata_info.port_index = OUTPUT_PORT; + output_extradata_info.port_index = CAPTURE_PORT; return true; } @@ -1368,11 +1433,6 @@ void venc_dev::venc_close() fclose(m_debug.extradatafile); m_debug.extradatafile = NULL; } - - if (m_debug.roiqpfile) { - fclose(m_debug.roiqpfile); - m_debug.roiqpfile = NULL; - } } bool venc_dev::venc_set_buf_req(OMX_U32 *min_buff_count, @@ -1505,7 +1565,10 @@ bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count, DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d\n", extra_idx); return OMX_ErrorBadParameter; } - mInputExtradata.update(m_sInput_buff_property.actualcount + 1, extra_data_size); + input_extradata_info.buffer_size = extra_data_size; + input_extradata_info.count = m_sInput_buff_property.actualcount + 1; + input_extradata_info.size = input_extradata_info.buffer_size * input_extradata_info.count; + } else { unsigned int extra_idx = 0; memset(&fmt, 0, sizeof(fmt)); @@ -1557,7 +1620,10 @@ bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count, DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); return OMX_ErrorBadParameter; } - mOutputExtradata.update(m_sOutput_buff_property.actualcount, extra_data_size); + + output_extradata_info.buffer_size = extra_data_size; + output_extradata_info.count = m_sOutput_buff_property.actualcount; + output_extradata_info.size = output_extradata_info.buffer_size * output_extradata_info.count; } return true; @@ -1625,6 +1691,9 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) if (portDefn->nBufferCountActual >= m_sInput_buff_property.mincount) m_sInput_buff_property.actualcount = portDefn->nBufferCountActual; + if (num_input_planes > 1) + input_extradata_info.count = m_sInput_buff_property.actualcount + 1; + } DEBUG_PRINT_LOW("input: actual: %u, min: %u, count_req: %u", @@ -1668,6 +1737,9 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) if (portDefn->nBufferCountActual >= m_sOutput_buff_property.mincount) m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual; + if (num_output_planes > 1) + output_extradata_info.count = m_sOutput_buff_property.actualcount; + DEBUG_PRINT_LOW("Output: actual: %u, min: %u, count_req: %u", (unsigned int)portDefn->nBufferCountActual, (unsigned int)m_sOutput_buff_property.mincount, bufreq.count); } else { @@ -2256,6 +2328,16 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) } break; } + case OMX_QTIIndexParamLowLatencyMode: + { + QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE* pParam = + (QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE*)paramData; + if (!venc_set_low_latency(pParam->bLowLatencyMode)) { + DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamLowLatencyMode failed"); + return OMX_ErrorUnsupportedSetting; + } + break; + } case OMX_QTIIndexParamVideoEnableRoiInfo: { struct v4l2_control control; @@ -2273,16 +2355,6 @@ bool venc_dev::venc_set_param(void *paramData, OMX_INDEXTYPE index) } break; } - case OMX_QTIIndexParamLowLatencyMode: - { - QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE* pParam = - (QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE*)paramData; - if (!venc_set_low_latency(pParam->bLowLatencyMode)) { - DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamLowLatencyMode failed"); - return OMX_ErrorUnsupportedSetting; - } - break; - } case OMX_IndexParamVideoSliceFMO: default: DEBUG_PRINT_ERROR("ERROR: Unsupported parameter in venc_set_param: %u", @@ -2396,11 +2468,12 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) DEBUG_PRINT_ERROR("ERROR: Rotation is not supported with deinterlacing"); return false; } - DEBUG_PRINT_HIGH("venc_set_config: updating the new Dims"); - nFrameWidth = m_sVenc_cfg.dvs_width; - m_sVenc_cfg.dvs_width = m_sVenc_cfg.dvs_height; - m_sVenc_cfg.dvs_height = nFrameWidth; - + if (config_rotation->nRotation == 90 || config_rotation->nRotation == 270) { + DEBUG_PRINT_HIGH("venc_set_config: updating the new Dims"); + nFrameWidth = m_sVenc_cfg.dvs_width; + m_sVenc_cfg.dvs_width = m_sVenc_cfg.dvs_height; + m_sVenc_cfg.dvs_height = nFrameWidth; + } if(venc_set_vpe_rotation(config_rotation->nRotation) == false) { DEBUG_PRINT_ERROR("ERROR: Dimension Change for Rotation failed"); return false; @@ -2513,13 +2586,13 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) } break; } - case OMX_QcomIndexConfigMaxHierPLayers: + case OMX_QcomIndexConfigNumHierPLayers: { - QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS *pParam = - (QOMX_EXTNINDEX_VIDEO_MAX_HIER_P_LAYERS *) configData; - DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigMaxHierPLayers"); - if (venc_set_max_hierp(pParam->nMaxHierLayers) == false) { - DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigMaxHierPLayers"); + QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS *pParam = + (QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS *) configData; + DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigNumHierPLayers"); + if (venc_set_hierp_layers(pParam->nNumHierLayers) == false) { + DEBUG_PRINT_ERROR("Failed to set OMX_QcomIndexConfigNumHierPLayers"); return false; } break; @@ -2564,14 +2637,6 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) } 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; - } default: DEBUG_PRINT_ERROR("Unsupported config index = %u", index); break; @@ -2674,6 +2739,7 @@ unsigned venc_dev::venc_start_done(void) unsigned venc_dev::venc_stop_done(void) { struct venc_msg venc_msg; + free_extradata(); venc_msg.msgcode=VEN_MSG_STOP; venc_msg.statuscode=VEN_S_SUCCESS; venc_handle->async_message_process(venc_handle,&venc_msg); @@ -2766,6 +2832,9 @@ unsigned venc_dev::venc_start(void) if (vqzip_sei_info.enabled && !venc_set_vqzip_defaults()) return 1; + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) + venc_set_low_latency((OMX_BOOL)!intra_period.num_bframes); + venc_config_print(); if(resume_in_stopped){ @@ -2794,10 +2863,10 @@ unsigned venc_dev::venc_start(void) /* * Workaround for Skype usecase. Skpye doesn't like SPS\PPS come as - seperate buffer. It wants SPS\PPS with IDR frame FTB. + seperate buffer. It wants SPS\PPS with IDR frame FTB. */ - if (!low_latency_mode) { + if (!venc_handle->m_slowLatencyMode.bLowLatencyMode) { control.id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_SEQ_HEADER; control.value = 1; ret = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); @@ -2806,7 +2875,6 @@ unsigned venc_dev::venc_start(void) return 1; } } - stopped = 0; return 0; } @@ -2957,12 +3025,66 @@ bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned index) struct v4l2_plane plane[VIDEO_MAX_PLANES]; int rc = 0; unsigned int extra_idx; + int extradata_index = 0; pmem_tmp = (struct pmem *)buf_addr; DEBUG_PRINT_LOW("venc_use_buf:: pmem_tmp = %p", pmem_tmp); - if (port == PORT_INDEX_OUT) { + if (port == PORT_INDEX_IN) { + extra_idx = EXTRADATA_IDX(num_input_planes); + + if ((num_input_planes > 1) && (extra_idx)) { + rc = allocate_extradata(&input_extradata_info); + + if (rc) + DEBUG_PRINT_ERROR("Failed to allocate extradata: %d\n", rc); + } + buf.index = index; + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + plane[0].length = pmem_tmp->size; + plane[0].m.userptr = (unsigned long)pmem_tmp->buffer; + plane[0].reserved[0] = pmem_tmp->fd; + plane[0].reserved[1] = 0; + plane[0].data_offset = pmem_tmp->offset; + buf.m.planes = plane; + buf.length = num_input_planes; + +if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { + extradata_index = venc_get_index_from_fd(pmem_tmp->fd); + if (extradata_index < 0 ) { + DEBUG_PRINT_ERROR("Extradata index calculation went wrong for fd = %d", pmem_tmp->fd); + return OMX_ErrorBadParameter; + } + plane[extra_idx].length = input_extradata_info.buffer_size; + plane[extra_idx].m.userptr = (unsigned long) (input_extradata_info.uaddr + extradata_index * input_extradata_info.buffer_size); +#ifdef USE_ION + plane[extra_idx].reserved[0] = input_extradata_info.ion.fd_ion_data.fd; +#endif + plane[extra_idx].reserved[1] = input_extradata_info.buffer_size * extradata_index; + plane[extra_idx].data_offset = 0; + } else if (extra_idx >= VIDEO_MAX_PLANES) { + DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d\n", extra_idx); + return OMX_ErrorBadParameter; + } + + + DEBUG_PRINT_LOW("Registering [%d] fd=%d size=%d userptr=%p", index, + pmem_tmp->fd, plane[0].length, plane[0].m.userptr); + rc = ioctl(m_nDriver_fd, VIDIOC_PREPARE_BUF, &buf); + + if (rc) + DEBUG_PRINT_LOW("VIDIOC_PREPARE_BUF Failed"); + } else if (port == PORT_INDEX_OUT) { extra_idx = EXTRADATA_IDX(num_output_planes); + + if ((num_output_planes > 1) && (extra_idx)) { + rc = allocate_extradata(&output_extradata_info); + + if (rc) + DEBUG_PRINT_ERROR("Failed to allocate extradata: %d", rc); + } + buf.index = index; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; buf.memory = V4L2_MEMORY_USERPTR; @@ -2975,21 +3097,12 @@ bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned index) buf.length = num_output_planes; if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { - char *userptr; - int fd; - unsigned offset; - ssize_t size; - int rc = mOutputExtradata.peek(index, &userptr, &fd, &offset, &size); - if (rc != OMX_ErrorNone) { - DEBUG_PRINT_ERROR("Unable to get extradata memory 2"); - return rc; - } - plane[extra_idx].length = size; - plane[extra_idx].m.userptr = (unsigned long)userptr; + plane[extra_idx].length = output_extradata_info.buffer_size; + plane[extra_idx].m.userptr = (unsigned long) (output_extradata_info.uaddr + index * output_extradata_info.buffer_size); #ifdef USE_ION - plane[extra_idx].reserved[0] = fd; + plane[extra_idx].reserved[0] = output_extradata_info.ion.fd_ion_data.fd; #endif - plane[extra_idx].reserved[1] = offset; + plane[extra_idx].reserved[1] = output_extradata_info.buffer_size * index; plane[extra_idx].data_offset = 0; } else if (extra_idx >= VIDEO_MAX_PLANES) { DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); @@ -3000,8 +3113,6 @@ bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned index) if (rc) DEBUG_PRINT_LOW("VIDIOC_PREPARE_BUF Failed"); - } else if (port == PORT_INDEX_IN) { - DEBUG_PRINT_LOW("No need to call VIDIOC_PREPARE_BUF on input port"); } else { DEBUG_PRINT_ERROR("ERROR: venc_use_buf:Invalid Port Index "); return false; @@ -3185,7 +3296,7 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, // CPU (Eg: MediaCodec) 0 -- 0 bufhdr // --------------------------------------------------------------------------------------- if (metadatamode) { - plane[0].m.userptr = (unsigned long)bufhdr->pBuffer; + plane[0].m.userptr = index; meta_buf = (encoder_media_buffer_type *)bufhdr->pBuffer; if (!meta_buf) { @@ -3324,22 +3435,19 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, extra_idx = EXTRADATA_IDX(num_input_planes); if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { - char *userptr; - int fd; - unsigned offset; - ssize_t size; - int rc = mInputExtradata.get(bufhdr, &userptr, &fd, &offset, &size); - if (rc != OMX_ErrorNone) { - DEBUG_PRINT_ERROR("Unable to get extradata memory 1"); - return rc; - } + int extradata_index = venc_get_index_from_fd(fd); + if (extradata_index < 0 ) { + DEBUG_PRINT_ERROR("Extradata index calculation went wrong for fd = %d", fd); + return OMX_ErrorBadParameter; + } + plane[extra_idx].bytesused = 0; - plane[extra_idx].length = size; - plane[extra_idx].m.userptr = (unsigned long) userptr; + plane[extra_idx].length = input_extradata_info.buffer_size; + plane[extra_idx].m.userptr = (unsigned long) (input_extradata_info.uaddr + extradata_index * input_extradata_info.buffer_size); #ifdef USE_ION - plane[extra_idx].reserved[0] = fd; + plane[extra_idx].reserved[0] = input_extradata_info.ion.fd_ion_data.fd; #endif - plane[extra_idx].reserved[1] = offset; + plane[extra_idx].reserved[1] = input_extradata_info.buffer_size * extradata_index; plane[extra_idx].data_offset = 0; } else if (extra_idx >= VIDEO_MAX_PLANES) { DEBUG_PRINT_ERROR("Extradata index higher than expected: %d\n", extra_idx); @@ -3407,7 +3515,7 @@ bool venc_dev::venc_empty_batch(OMX_BUFFERHEADERTYPE *bufhdr, unsigned index) bool status = true; if (metadatamode) { - plane.m.userptr = (unsigned long)bufhdr->pBuffer; + plane.m.userptr = index; meta_buf = (encoder_media_buffer_type *)bufhdr->pBuffer; if (!color_format) { @@ -3466,6 +3574,10 @@ bool venc_dev::venc_empty_batch(OMX_BUFFERHEADERTYPE *bufhdr, unsigned index) buf.m.planes = &plane; buf.length = 1; + rc = ioctl(m_nDriver_fd, VIDIOC_PREPARE_BUF, &buf); + if (rc) + DEBUG_PRINT_LOW("VIDIOC_PREPARE_BUF Failed"); + if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS) buf.flags |= V4L2_QCOM_BUF_FLAG_EOS; if (i != numBufs - 1) { @@ -3564,22 +3676,13 @@ bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,un extra_idx = EXTRADATA_IDX(num_output_planes); if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { - char *userptr; - int fd; - unsigned offset; - ssize_t size; - int rc = mOutputExtradata.get(&userptr, &fd, &offset, &size); - if (rc != OMX_ErrorNone) { - DEBUG_PRINT_ERROR("Unable to get extradata memory 0"); - return false; - } plane[extra_idx].bytesused = 0; - plane[extra_idx].length = size; - plane[extra_idx].m.userptr = (unsigned long)userptr; + plane[extra_idx].length = output_extradata_info.buffer_size; + plane[extra_idx].m.userptr = (unsigned long) (output_extradata_info.uaddr + index * output_extradata_info.buffer_size); #ifdef USE_ION - plane[extra_idx].reserved[0] = fd; + plane[extra_idx].reserved[0] = output_extradata_info.ion.fd_ion_data.fd; #endif - plane[extra_idx].reserved[1] = offset; + plane[extra_idx].reserved[1] = output_extradata_info.buffer_size * index; plane[extra_idx].data_offset = 0; } else if (extra_idx >= VIDEO_MAX_PLANES) { DEBUG_PRINT_ERROR("Extradata index higher than expected: %d", extra_idx); @@ -3650,6 +3753,24 @@ bool venc_dev::venc_set_mbi_statistics_mode(OMX_U32 mode) return true; } +int venc_dev::venc_get_index_from_fd(OMX_U32 fd) +{ + unsigned int i = 0; + for (;i < 64; i++) { + if (fd_list[i] == fd) { + DEBUG_PRINT_HIGH("FD is present at index = %d", i); + return i; + } + } + for (i = 0;i < 64; i++) + if (fd_list[i] == 0) { + DEBUG_PRINT_HIGH("FD added at index = %d", i); + fd_list[i] = fd; + return i; + } + return -EINVAL; +} + bool venc_dev::venc_set_vqzip_sei_type(OMX_BOOL enable) { struct v4l2_control sei_control, yuvstats_control; @@ -3677,10 +3798,12 @@ bool venc_dev::venc_set_vqzip_sei_type(OMX_BOOL enable) if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &yuvstats_control) < 0) { DEBUG_PRINT_HIGH("Non-Fatal: Request to set YUVSTATS failed"); } +#ifdef _VQZIP_ vqzip.pConfig.nWidth = ALIGN(m_sVenc_cfg.input_width, 16); vqzip.pConfig.nHeight = ALIGN(m_sVenc_cfg.input_height, 16); vqzip.init(); vqzip_sei_info.enabled = true; +#endif return true; } @@ -3720,6 +3843,13 @@ bool venc_dev::venc_set_hier_layers(QOMX_VIDEO_HIERARCHICALCODINGTYPE type, if (type == QOMX_HIERARCHICALCODING_P) { // Reduce layer count by 1 before sending to driver. This avoids // driver doing the same in multiple places. + control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS; + control.value = num_layers - 1; + DEBUG_PRINT_HIGH("Set MAX Hier P num layers: %u", (unsigned int)num_layers); + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Request to set MAX Hier P num layers failed"); + return false; + } control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS; control.value = num_layers - 1; DEBUG_PRINT_HIGH("Set Hier P num layers: %u", (unsigned int)num_layers); @@ -5496,6 +5626,7 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) rate_ctrl.rcmode = control.value; } +#ifdef _VQZIP_ if (eControlRate == OMX_Video_ControlRateVariable && (supported_rc_modes & RC_VBR_CFR) && m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { /* Enable VQZIP SEI by default for camcorder RC modes */ @@ -5507,6 +5638,7 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) DEBUG_PRINT_HIGH("Non-Fatal: Request to set VQZIP failed"); } } +#endif return status; } @@ -5615,21 +5747,21 @@ bool venc_dev::venc_set_aspectratio(void *nSar) return true; } -bool venc_dev::venc_set_max_hierp(OMX_U32 hierp_layers) +bool venc_dev::venc_set_hierp_layers(OMX_U32 hierp_layers) { struct v4l2_control control; if (hierp_layers && (hier_layers.hier_mode == HIER_P) && (hierp_layers <= hier_layers.numlayers)) { - control.id = V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS; - control.value = hierp_layers; - DEBUG_PRINT_LOW("Going to set V4L2_CID_MPEG_VIDC_VIDEO_MAX_HIERP_LAYERS"); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS; + control.value = hierp_layers - 1; + DEBUG_PRINT_LOW("Going to set V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS"); if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { - DEBUG_PRINT_ERROR("Failed to set MAX_HIERP_LAYERS"); + DEBUG_PRINT_ERROR("Failed to set HIERP_LAYERS"); return false; } return true; } else { - DEBUG_PRINT_ERROR("Invalid layers set for MAX_HIERP_LAYERS: %d", + DEBUG_PRINT_ERROR("Invalid layers set for HIERP_LAYERS: %d", hierp_layers); return false; } @@ -5781,52 +5913,6 @@ bool venc_dev::venc_set_operatingrate(OMX_U32 rate) { return true; } -bool venc_dev::venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo) { - char *userptr; - int fd; - unsigned offset; - ssize_t size; - struct msm_vidc_roi_qp_payload *roiData; - if (!roiInfo) { - DEBUG_PRINT_ERROR("No ROI info present"); - return false; - } - if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 && - m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) { - DEBUG_PRINT_ERROR("OMX_QTIIndexConfigVideoRoiInfo is not supported for %d codec", m_sVenc_cfg.codectype); - return false; - } - - venc_roiqp_log_buffers(roiInfo); - mInputExtradata.getForConfig(&userptr, &fd, &offset, &size); - if (!userptr || size < roiInfo->nRoiMBInfoSize) { - DEBUG_PRINT_ERROR("ROI extradata insufficient. Check if OMX_QTIIndexParamVideoEnableRoiInfo was set. (%p, %u, %u)", userptr, size, roiInfo->nRoiMBInfoSize); - return false; - } - - OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)userptr; - data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct msm_vidc_roi_qp_payload) + roiInfo->nRoiMBInfoSize - 2 * sizeof(unsigned int), 4); - data->nVersion.nVersion = OMX_SPEC_VERSION; - data->nPortIndex = 0; - data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP; - data->nDataSize = sizeof(struct msm_vidc_roi_qp_payload); - - roiData = (struct msm_vidc_roi_qp_payload *)(data->data); - roiData->upper_qp_offset = roiInfo->nUpperQpOffset; - roiData->lower_qp_offset = roiInfo->nLowerQpOffset; - roiData->b_roi_info = roiInfo->bUseRoiInfo; - roiData->mbi_info_size = roiInfo->nRoiMBInfoSize; - memcpy(roiData->data, roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoSize); - - data = (struct OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize); - data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE), 4); - data->nVersion.nVersion = OMX_SPEC_VERSION; - data->nPortIndex = 0; - data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE; - data->nDataSize = 0; - return true; -} - bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel) { bool status = true; @@ -6544,6 +6630,7 @@ int venc_dev::BatchInfo::getTimeStampAt(native_handle_t *hnd, int index) { return size; } +#ifdef _VQZIP_ venc_dev::venc_dev_vqzip::venc_dev_vqzip() { mLibHandle = NULL; @@ -6625,260 +6712,4 @@ venc_dev::venc_dev_vqzip::~venc_dev_vqzip() mLibHandle = NULL; pthread_mutex_destroy(&lock); } - -encExtradata::encExtradata(class omx_venc *venc_handle) -{ - mCount = 0; - mSize = 0; - mUaddr = NULL; - memset(&mIon, -1, sizeof(struct venc_ion)); - memset(mIndex, 0, sizeof(mIndex)); - mVencHandle = venc_handle; - mDbgEtbCount = 0; - pthread_mutex_init(&lock, NULL); - vqzip_sei_found = false; -} - -encExtradata::~encExtradata() -{ - __free(); - mCount = 0; - mSize = 0; - mVencHandle = NULL; - pthread_mutex_destroy(&lock); -} - -OMX_ERRORTYPE encExtradata::__allocate() -{ - ssize_t totalSize = (mSize * mCount + 4095) & (~4095); - if (!mVencHandle) { - return OMX_ErrorInsufficientResources; - } - if (mUaddr || !totalSize) { - return OMX_ErrorNone; - } - mIon.ion_device_fd = mVencHandle->alloc_map_ion_memory( - totalSize, - &mIon.ion_alloc_data, - &mIon.fd_ion_data, 0); - if (mIon.ion_device_fd < 0) { - DEBUG_PRINT_ERROR("Failed to alloc extradata memory: %d", totalSize); - DEBUG_PRINT_ERROR("Check if OMX_QTIIndexParamVideoEnableRoiInfo is set."); - return OMX_ErrorInsufficientResources; - } - mUaddr = (char *)mmap(NULL, totalSize, - PROT_READ|PROT_WRITE, MAP_SHARED, - mIon.fd_ion_data.fd , 0); - if (mUaddr == MAP_FAILED) { - DEBUG_PRINT_ERROR("Failed to map extradata memory\n"); - close(mIon.fd_ion_data.fd); - mVencHandle->free_ion_memory(&mIon); - return OMX_ErrorInsufficientResources; - } - for (unsigned i = 0; i < mCount; i++) { - mIndex[i].status = FREE; - mIndex[i].cookie = NULL; - } - return OMX_ErrorNone; -} - -int encExtradata::__get(char **userptr, int *fd, unsigned *offset, ssize_t *size, int type) -{ - unsigned i = 0; - if (__allocate() != OMX_ErrorNone) { - return -1; - } - for (i = 0; i < mCount; i++) { - if (mIndex[i].status == type) { - mIndex[i].status = BUSY; - break; - } - } - if (i >= mCount) { - DEBUG_PRINT_HIGH("No Free extradata available"); - return -1; - } - *userptr = mUaddr + i * mSize; - *fd = mIon.fd_ion_data.fd; - *offset = i * mSize; - *size = mSize; - return i; -} - -OMX_ERRORTYPE encExtradata::get(char **userptr, int *fd, unsigned *offset, ssize_t *size) { - int index; - *userptr = NULL; - *fd = -1; - *offset = 0; - *size = 0; - pthread_mutex_lock(&lock); - index = __get(userptr, fd, offset, size, FREE); - DEBUG_PRINT_LOW("%s: (%d, %p, %d, %u, %d)", __func__, index, *userptr, *fd, *offset, *size); - pthread_mutex_unlock(&lock); - return index < 0 ? OMX_ErrorInsufficientResources : OMX_ErrorNone; -} - -OMX_ERRORTYPE encExtradata::get(void *cookie, char **userptr, int *fd, unsigned *offset, ssize_t *size) -{ - OMX_ERRORTYPE rc = OMX_ErrorNone; - unsigned int i; - *userptr = NULL; - *fd = -1; - *offset = 0; - *size = 0; - pthread_mutex_lock(&lock); - for (i = 0; i < mCount; i++) { - if (mIndex[i].cookie == cookie) { - break; - } - } - if (i < mCount) { - *userptr = mUaddr + i * mSize; - *fd = mIon.fd_ion_data.fd; - *offset = i * mSize; - *size = mSize; - } else { - int index = __get(userptr, fd, offset, size, FREE); - if (index < 0 ) { - DEBUG_PRINT_HIGH("%s: failed(%d, %p)", i, cookie); - __debug(); - rc = OMX_ErrorInsufficientResources; - } - } - DEBUG_PRINT_LOW("%s: (%p, %p, %d, %u, %d)", __func__, cookie, *userptr, *fd, *offset, *size); - pthread_mutex_unlock(&lock); - return rc; -} - -OMX_ERRORTYPE encExtradata::getForConfig(char **userptr, int *fd, unsigned *offset, ssize_t *size) -{ - OMX_ERRORTYPE rc = OMX_ErrorNone; - unsigned int i; - int found = -1; - pthread_mutex_lock(&lock); - found = __get(userptr, fd, offset, size, FOR_CONFIG); - if (found < 0) { - found = __get(userptr, fd, offset, size, FREE); - } - - if (found < 0) { - DEBUG_PRINT_HIGH("%s: failed (%d)", __func__, found); - __debug(); - rc = OMX_ErrorInsufficientResources; - } else { - mIndex[found].status = FOR_CONFIG; - DEBUG_PRINT_LOW("%s: (%d, %p, %d, %u, %d)", __func__, *userptr, *fd, *offset, *size); - } - pthread_mutex_unlock(&lock); - return rc; -} - -OMX_ERRORTYPE encExtradata::put(char *userptr) -{ - OMX_ERRORTYPE rc = OMX_ErrorNone; - int index = (userptr - mUaddr)/mSize; - pthread_mutex_lock(&lock); - if (!userptr) { - DEBUG_PRINT_HIGH("Userptr is NULL"); - rc = OMX_ErrorBadParameter; - } else if (index < 0) { - DEBUG_PRINT_HIGH("Userptr is not in valid range: %p"); - __debug(); - rc = OMX_ErrorBadParameter; - } else { - mIndex[index].status = FREE; - mIndex[index].cookie = NULL; - DEBUG_PRINT_LOW("%s: (%d, %p)", __func__, index, userptr); - } - pthread_mutex_unlock(&lock); - return rc; -} - -OMX_ERRORTYPE encExtradata::peek(unsigned index, char **userptr, int *fd, unsigned* offset, ssize_t *size) -{ - OMX_ERRORTYPE rc = OMX_ErrorNone; - *userptr = 0; - *fd = -1; - *offset = 0; - *size = 0; - pthread_mutex_lock(&lock); - if (index < mCount) { - rc = __allocate(); - if (rc == OMX_ErrorNone) { - *userptr = mUaddr + index * mSize; - *fd = mIon.fd_ion_data.fd; - *offset = index * mSize; - *size = mSize; - } - } - DEBUG_PRINT_LOW("%s: (%d, %p, %d, %u, %d)", __func__, index, *userptr, *fd, *offset, *size); - pthread_mutex_unlock(&lock); - return rc; -} - -void encExtradata::setCookieForConfig(void *cookie) -{ - char *userptr; - int fd; - unsigned offset; - ssize_t size; - pthread_mutex_lock(&lock); - int found = __get(&userptr, &fd, &offset, &size, FOR_CONFIG); - if (found >= 0) { - mIndex[found].cookie = cookie; - } else { - DEBUG_PRINT_HIGH("Failed to set cookie for extradata: %d, cookie: %d\n", - found, cookie); - __debug(); - } - mDbgEtbCount++; - pthread_mutex_unlock(&lock); -} - -void encExtradata::__free() -{ - ssize_t totalSize = (mCount * mSize + 4095) & (~4095); - if (mUaddr) { - munmap((void *)mUaddr, totalSize); - mUaddr = NULL; - } - if (mIon.fd_ion_data.fd >= 0) { - if (mVencHandle) - mVencHandle->free_ion_memory(&mIon); - close(mIon.fd_ion_data.fd); - mIon.fd_ion_data.fd = -1; - } - for (unsigned i = 0; i < mCount; i++) { - mIndex[i].status = FREE; - mIndex[i].cookie = NULL; - } -} - -void encExtradata::update(unsigned int count, ssize_t size) -{ - pthread_mutex_lock(&lock); - __free(); - mCount = count <= MAX_V4L2_BUFS ? count : MAX_V4L2_BUFS; - mSize = size; - DEBUG_PRINT_LOW("%s: (%d, %d)", __func__, mCount, mSize); - pthread_mutex_unlock(&lock); -} - -void encExtradata::__debug() -{ - DEBUG_PRINT_HIGH("encExtradata: this: %p, mCount: %d, mSize: %d, mUaddr: %p, mVencHandle: %p", - this, mCount, mSize, mUaddr, mVencHandle); - for (unsigned i = 0; i < mCount; i++) { - DEBUG_PRINT_HIGH("index: %d, status: %d, cookie: %#x\n", i, mIndex[i].status, mIndex[i].cookie); - } -} - -ssize_t encExtradata::getBufferSize() -{ - return mSize; -} - -unsigned int encExtradata::getBufferCount() -{ - return mCount; -} +#endif |