diff options
41 files changed, 5471 insertions, 899 deletions
@@ -1,5 +1,5 @@ QCOM_MEDIA_ROOT := $(call my-dir) -ifneq ($(filter msm8610 msm8226 msm8974 msm8960 msm8660 msm7627a msm7630_surf msm8084 mpq8092,$(TARGET_BOARD_PLATFORM)),) +ifneq ($(filter msm8610 msm8226 msm8974 msm8960 msm8660 msm7627a msm7630_surf msm8084 msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),) include $(QCOM_MEDIA_ROOT)/mm-core/Android.mk include $(QCOM_MEDIA_ROOT)/libstagefrighthw/Android.mk endif @@ -8,10 +8,10 @@ ifneq ($(filter msm8960 msm8660,$(TARGET_BOARD_PLATFORM)),) include $(QCOM_MEDIA_ROOT)/mm-video-legacy/Android.mk endif -ifneq ($(filter msm8610 msm8226 msm8974 msm8084 mpq8092,$(TARGET_BOARD_PLATFORM)),) +ifneq ($(filter msm8610 msm8226 msm8974 msm8084 msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),) include $(QCOM_MEDIA_ROOT)/mm-video-v4l2/Android.mk endif -ifneq ($(filter msm8610 msm8226 msm8974 msm8960 msm8084 mpq8092,$(TARGET_BOARD_PLATFORM)),) +ifneq ($(filter msm8610 msm8226 msm8974 msm8960 msm8084 msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),) include $(QCOM_MEDIA_ROOT)/libc2dcolorconvert/Android.mk endif diff --git a/libc2dcolorconvert/Android.mk b/libc2dcolorconvert/Android.mk index 7aa530d..4edb0a5 100644 --- a/libc2dcolorconvert/Android.mk +++ b/libc2dcolorconvert/Android.mk @@ -6,8 +6,6 @@ LOCAL_SRC_FILES := \ C2DColorConverter.cpp LOCAL_C_INCLUDES := \ - $(TOP)/frameworks/av/include/media/stagefright \ - $(TOP)/frameworks/native/include/media/openmax \ $(TARGET_OUT_HEADERS)/qcom/display LOCAL_SHARED_LIBRARIES := liblog libdl diff --git a/libc2dcolorconvert/C2DColorConverter.cpp b/libc2dcolorconvert/C2DColorConverter.cpp index 7f42892..bf61269 100644 --- a/libc2dcolorconvert/C2DColorConverter.cpp +++ b/libc2dcolorconvert/C2DColorConverter.cpp @@ -29,11 +29,14 @@ #include <C2DColorConverter.h> #include <stdlib.h> +#include <string.h> #include <fcntl.h> #include <linux/msm_kgsl.h> #include <sys/ioctl.h> #include <utils/Log.h> #include <dlfcn.h> +#include <string.h> +#include <errno.h> #undef LOG_TAG #define LOG_TAG "C2DColorConvert" diff --git a/libc2dcolorconvert/C2DColorConverter.h b/libc2dcolorconvert/C2DColorConverter.h index 0c84fad..f13f919 100644 --- a/libc2dcolorconvert/C2DColorConverter.h +++ b/libc2dcolorconvert/C2DColorConverter.h @@ -31,7 +31,6 @@ #define C2D_ColorConverter_H_ #include <c2d2.h> -#include <ColorConverter.h> #include <sys/types.h> typedef C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id, diff --git a/libstagefrighthw/QComOMXPlugin.cpp b/libstagefrighthw/QComOMXPlugin.cpp index 9446dcf..5d23243 100644 --- a/libstagefrighthw/QComOMXPlugin.cpp +++ b/libstagefrighthw/QComOMXPlugin.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 The Android Open Source Project + * Copyright (c) 2014, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,6 +49,11 @@ QComOMXPlugin::QComOMXPlugin() (GetRolesOfComponentFunc)dlsym( mLibHandle, "OMX_GetRolesOfComponent"); + if (!mInit || !mDeinit || !mComponentNameEnum || !mGetHandle || + !mFreeHandle || !mGetRolesOfComponentHandle) { + dlclose(mLibHandle); + mLibHandle = NULL; + } else (*mInit)(); } } diff --git a/mm-core/Android.mk b/mm-core/Android.mk index 25fd900..bdee813 100755..100644 --- a/mm-core/Android.mk +++ b/mm-core/Android.mk @@ -34,8 +34,12 @@ else ifeq ($(TARGET_BOARD_PLATFORM),msm8084) MM_CORE_TARGET = 8084 else ifeq ($(TARGET_BOARD_PLATFORM),mpq8092) MM_CORE_TARGET = 8092 -else ifeq ($(TARGET_BOARD_PLATFORM),plutonium) -MM_CORE_TARGET = plutonium +else ifeq ($(TARGET_BOARD_PLATFORM),msm8992) +MM_CORE_TARGET = msm8992 +else ifeq ($(TARGET_BOARD_PLATFORM),msm8994) +MM_CORE_TARGET = msm8994 +else ifeq ($(TARGET_BOARD_PLATFORM),thulium) +MM_CORE_TARGET = thulium else MM_CORE_TARGET = default endif @@ -79,7 +83,6 @@ LOCAL_COPY_HEADERS += inc/QCMetaData.h LOCAL_C_INCLUDES := $(LOCAL_PATH)/src/common LOCAL_C_INCLUDES += $(LOCAL_PATH)/inc -LOCAL_PRELINK_MODULE := false LOCAL_MODULE := libOmxCore LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := liblog libdl @@ -87,7 +90,7 @@ LOCAL_CFLAGS := $(OMXCORE_CFLAGS) LOCAL_SRC_FILES := src/common/omx_core_cmp.cpp LOCAL_SRC_FILES += src/common/qc_omx_core.c -ifneq (,$(filter msm8916 plutonium,$(TARGET_BOARD_PLATFORM))) +ifneq (,$(filter msm8916 msm8994 msm8909 thulium msm8992,$(TARGET_BOARD_PLATFORM))) LOCAL_SRC_FILES += src/$(MM_CORE_TARGET)/registry_table_android.c else LOCAL_SRC_FILES += src/$(MM_CORE_TARGET)/qc_registry_table_android.c @@ -103,7 +106,6 @@ include $(CLEAR_VARS) LOCAL_C_INCLUDES := $(LOCAL_PATH)/src/common LOCAL_C_INCLUDES += $(LOCAL_PATH)/inc -LOCAL_PRELINK_MODULE := false LOCAL_MODULE := libmm-omxcore LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := liblog libdl @@ -111,7 +113,7 @@ LOCAL_CFLAGS := $(OMXCORE_CFLAGS) LOCAL_SRC_FILES := src/common/omx_core_cmp.cpp LOCAL_SRC_FILES += src/common/qc_omx_core.c -ifneq (,$(filter msm8916 plutonium,$(TARGET_BOARD_PLATFORM))) +ifneq (,$(filter msm8916 msm8994 msm8909 thulium msm8992,$(TARGET_BOARD_PLATFORM))) LOCAL_SRC_FILES += src/$(MM_CORE_TARGET)/registry_table.c else LOCAL_SRC_FILES += src/$(MM_CORE_TARGET)/qc_registry_table.c diff --git a/mm-core/inc/OMX_IndexExt.h b/mm-core/inc/OMX_IndexExt.h index 007165b..feddcb1 100644 --- a/mm-core/inc/OMX_IndexExt.h +++ b/mm-core/inc/OMX_IndexExt.h @@ -78,6 +78,9 @@ typedef enum OMX_INDEXEXTTYPE { /* Other configurations */ OMX_IndexExtOtherStartUnused = OMX_IndexKhronosExtensions + 0x00800000, + OMX_IndexConfigAutoFramerateConversion, /**< reference: OMX_CONFIG_BOOLEANTYPE */ + OMX_IndexConfigPriority, /**< reference: OMX_PARAM_U32TYPE */ + OMX_IndexConfigOperatingRate, /**< reference: OMX_PARAM_U32TYPE in Q16 format for video and in Hz for audio */ /* Time configurations */ OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000, diff --git a/mm-core/inc/OMX_QCOMExtns.h b/mm-core/inc/OMX_QCOMExtns.h index 1c85a80..eb1b990 100755..100644 --- a/mm-core/inc/OMX_QCOMExtns.h +++ b/mm-core/inc/OMX_QCOMExtns.h @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. +Copyright (c) 2009-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: @@ -229,7 +229,7 @@ typedef struct OMX_QCOM_PLATFORM_PRIVATE_ENTRY OMX_QCOM_PLATFORM_PRIVATE_ENTRY_TYPE type; /** Pointer to platform specific entry */ - void* entry; + OMX_PTR entry; }OMX_QCOM_PLATFORM_PRIVATE_ENTRY; typedef struct OMX_QCOM_PLATFORM_PRIVATE_LIST @@ -461,18 +461,79 @@ enum OMX_QCOM_EXTN_INDEXTYPE OMX_QcomIndexParamPeakBitrate = 0x7F00003A, - /*"OMX.QCOM.index.config.video.LTRMark"*/ - OMX_QcomIndexConfigVideoLTRMark = QOMX_IndexConfigVideoLTRMark, - /* Enable InitialQP index */ QOMX_IndexParamVideoInitialQp = 0x7F00003B, OMX_QcomIndexParamSetMVSearchrange = 0x7F00003C, - OMX_QcomIndexFlexibleYUVDescription = 0x7F00003D, + OMX_QcomIndexConfigPerfLevel = 0x7F00003D, + + /*"OMX.QCOM.index.param.video.LTRCount"*/ + OMX_QcomIndexParamVideoLTRCount = QOMX_IndexParamVideoLTRCount, + + /*"OMX.QCOM.index.config.video.LTRUse"*/ + OMX_QcomIndexConfigVideoLTRUse = QOMX_IndexConfigVideoLTRUse, + + /*"OMX.QCOM.index.config.video.LTRMark"*/ + OMX_QcomIndexConfigVideoLTRMark = QOMX_IndexConfigVideoLTRMark, + + /*"OMX.QCOM.index.param.video.CustomBufferSize"*/ + OMX_QcomIndexParamVideoCustomBufferSize = 0x7F00003E, + + /*"OMX.QCOM.index.param.video.Mpeg2SeqDispExtraData"*/ + OMX_QcomIndexParamMpeg2SeqDispExtraData = 0x7F000040, + + /* Max Hierarchical P layers */ + OMX_QcomIndexMaxHierarchicallayers = 0x7F000041, + + /* Set Encoder Performance Index */ + OMX_QcomIndexConfigVideoVencPerfMode = 0x7F000042, + + /* Set Hybrid Hier-p layers */ + OMX_QcomIndexParamVideoHybridHierpMode = 0x7F000043, + + OMX_QcomIndexFlexibleYUVDescription = 0x7F000044, }; /** +* This is custom extension to configure Hybrid Hier-p settings. +* This mode is different from enabling Hier-p mode. This +* property enables Hier-p encoding with LTR referencing in each +* sub-GOP. +* +* STRUCT MEMBERS +* +* nSize : Size of Structure in bytes +* nVersion : OpenMAX IL specification version information +* nHpLayers : Set the number of Hier-p layers for the session +* - This should be <= 6. (1 Base layer + +* 5 Enhancement layers) +*/ + +typedef struct QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nHpLayers; +} QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE; + +/** + * Encoder Performance Mode. This structure is used to set + * performance mode or power save mode when encoding. The search + * range is modified to save power or improve quality. + * + * STRUCT MEMBERS: + * OMX_U32 nPerfMode : Performance mode: + * 1: MAX_QUALITY + * 2: POWER_SAVE + */ + +typedef struct QOMX_EXTNINDEX_VIDEO_PERFMODE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPerfMode; +} QOMX_EXTNINDEX_VIDEO_PERFMODE; + +/** * Initial QP parameter. This structure is used to enable * vendor specific extension to let client enable setting * initial QP values to I P B Frames @@ -610,6 +671,12 @@ typedef struct QOMX_VIDEO_PARAM_LTRCOUNT_TYPE { OMX_U32 nCount; } QOMX_VIDEO_PARAM_LTRCOUNT_TYPE; + +/** + * This should be used with OMX_QcomIndexParamVideoLTRCount extension. + */ +typedef QOMX_VIDEO_PARAM_LTRCOUNT_TYPE OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE; + /** * LTR period index parameter. This structure is used * to enable vendor specific extension on output port @@ -635,14 +702,22 @@ typedef struct QOMX_VIDEO_CONFIG_LTRPERIOD_TYPE { * nSize : Size of Structure in bytes * nVersion : OpenMAX IL specification version information * nPortIndex : Index of the port to which this structure applies + * nID : Specifies the identifier of the LTR frame to be marked + * as reference frame for encoding subsequent frames. */ typedef struct QOMX_VIDEO_CONFIG_LTRMARK_TYPE { OMX_U32 nSize; OMX_VERSIONTYPE nVersion; OMX_U32 nPortIndex; + OMX_U32 nID; } QOMX_VIDEO_CONFIG_LTRMARK_TYPE; /** + * This should be used with OMX_QcomIndexConfigVideoLTRMark extension. + */ +typedef QOMX_VIDEO_CONFIG_LTRMARK_TYPE OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE; + +/** * Specifies an LTR frame to encode subsequent frames. * STRUCT MEMBERS: * nSize : Size of Structure in bytes @@ -666,6 +741,11 @@ typedef struct QOMX_VIDEO_CONFIG_LTRUSE_TYPE { } QOMX_VIDEO_CONFIG_LTRUSE_TYPE; /** + * This should be used with OMX_QcomIndexConfigVideoLTRUse extension. + */ +typedef QOMX_VIDEO_CONFIG_LTRUSE_TYPE OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE; + +/** * Enumeration used to define the video encoder modes * * ENUMS: @@ -832,6 +912,17 @@ typedef struct OMX_QCOM_VIDEO_PARAM_PERF_LEVEL { /** * This structure describes the parameters corresponding + * to OMX_QcomIndexConfigPerfLevel extension. It will set + * the performance mode specified as QOMX_VIDEO_PERF_LEVEL. + */ +typedef struct OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL { + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /** OMX specification version information */ + QOMX_VIDEO_PERF_LEVEL ePerfLevel; /** Performance level */ +} OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL; + +/** + * This structure describes the parameters corresponding * to OMX_QcomIndexParamH264VUITimingInfo extension. It * will enable/disable the VUI timing info. */ @@ -1026,6 +1117,11 @@ typedef struct OMX_QCOM_EXTRADATA_MBINFO OMX_U8 data[0]; } OMX_QCOM_EXTRADATA_MBINFO; +typedef struct OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY { + OMX_U32 disp_width; + OMX_U32 disp_height; +} OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY; + typedef enum OMX_QCOM_EXTRADATATYPE { OMX_ExtraDataFrameInfo = 0x7F000001, @@ -1043,6 +1139,7 @@ typedef enum OMX_QCOM_EXTRADATATYPE OMX_ExtraDataQP = 0x7F00000d, OMX_ExtraDataInputBitsInfo = 0x7F00000e, OMX_ExtraDataVideoEncoderMBInfo = 0x7F00000f, + OMX_ExtraDataMpeg2SeqDisplay = 0x7F000010, } OMX_QCOM_EXTRADATATYPE; typedef struct OMX_STREAMINTERLACEFORMATTYPE { @@ -1251,6 +1348,8 @@ typedef struct QOMX_VIDEO_QUERY_DECODER_INSTANCES { } QOMX_VIDEO_QUERY_DECODER_INSTANCES; typedef struct QOMX_ENABLETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; OMX_BOOL bEnable; } QOMX_ENABLETYPE; @@ -1292,6 +1391,12 @@ typedef struct QOMX_INDEXDOWNSCALAR { OMX_BOOL bEnable; } QOMX_INDEXDOWNSCALAR; +typedef struct QOMX_VIDEO_CUSTOM_BUFFERSIZE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nBufferSize; +} QOMX_VIDEO_CUSTOM_BUFFERSIZE; #define OMX_QCOM_INDEX_PARAM_VIDEO_SYNCFRAMEDECODINGMODE "OMX.QCOM.index.param.video.SyncFrameDecodingMode" #define OMX_QCOM_INDEX_PARAM_INDEXEXTRADATA "OMX.QCOM.index.param.IndexExtraData" @@ -1301,6 +1406,7 @@ typedef struct QOMX_INDEXDOWNSCALAR { #define OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA "OMX.QCOM.index.param.video.InputBitsInfoExtradata" #define OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA "OMX.QCOM.index.param.video.ExtnUserExtraData" #define OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO "OMX.QCOM.index.config.video.FramePackingInfo" +#define OMX_QCOM_INDEX_PARAM_VIDEO_MPEG2SEQDISP_EXTRADATA "OMX.QCOM.index.param.video.Mpeg2SeqDispExtraData" typedef enum { QOMX_VIDEO_FRAME_PACKING_CHECKERBOARD = 0, @@ -1347,6 +1453,8 @@ typedef enum QOMX_VIDEO_PICTURETYPE { typedef struct QOMX_RECTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; OMX_S32 nLeft; OMX_S32 nTop; OMX_U32 nWidth; @@ -1447,7 +1555,6 @@ typedef struct QOMX_VIDEO_HIERARCHICALLAYERS { QOMX_VIDEO_HIERARCHICALCODINGTYPE eHierarchicalCodingType; } QOMX_VIDEO_HIERARCHICALLAYERS; - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/mm-core/inc/OMX_Types.h b/mm-core/inc/OMX_Types.h index 264532d..9871def 100644 --- a/mm-core/inc/OMX_Types.h +++ b/mm-core/inc/OMX_Types.h @@ -31,6 +31,8 @@ #ifndef OMX_Types_h #define OMX_Types_h +#include <stdint.h> + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -142,10 +144,10 @@ typedef unsigned short OMX_U16; typedef signed short OMX_S16; /** OMX_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */ -typedef unsigned long OMX_U32; +typedef uint32_t OMX_U32; /** OMX_S32 is a 32 bit signed quantity that is 32 bit word aligned */ -typedef signed long OMX_S32; +typedef int32_t OMX_S32; /* Users with compilers that cannot accept the "long long" designation should @@ -192,6 +194,14 @@ typedef enum OMX_BOOL { OMX_BOOL_MAX = 0x7FFFFFFF } OMX_BOOL; +#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS + +typedef OMX_U32 OMX_PTR; +typedef OMX_PTR OMX_STRING; +typedef OMX_PTR OMX_BYTE; + +#else + /** The OMX_PTR type is intended to be used to pass pointers between the OMX applications and the OMX Core and components. This is a 32 bit pointer and is aligned on a 32 bit boundary. @@ -216,6 +226,10 @@ typedef unsigned char* OMX_BYTE; at runtime. This identifier should be generated by a component in a way that guarantees that every instance of the identifier running on the system is unique. */ + + +#endif + typedef unsigned char OMX_UUIDTYPE[128]; /** The OMX_DIRTYPE enumeration is used to indicate if a port is an input or diff --git a/mm-core/inc/QCMediaDefs.h b/mm-core/inc/QCMediaDefs.h index cc2ea95..050f2ec 100755..100644 --- a/mm-core/inc/QCMediaDefs.h +++ b/mm-core/inc/QCMediaDefs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 - 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2012 - 2014, 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 @@ -51,7 +51,6 @@ extern const char *MEDIA_MIMETYPE_AUDIO_DTS_LBR; extern const char *MEDIA_MIMETYPE_AUDIO_EAC3; extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS; extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2TS; -extern const char *MEDIA_MIMETYPE_VIDEO_HEVC; extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG; extern const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_NB; extern const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_WB; @@ -63,6 +62,7 @@ extern const char *MEDIA_MIMETYPE_CONTAINER_QCMATROSKA; extern const char *MEDIA_MIMETYPE_CONTAINER_QCOGG; extern const char *MEDIA_MIMETYPE_CONTAINER_QTIFLAC; extern const char *MEDIA_MIMETYPE_VIDEO_VPX; //backward compatibility +extern const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC; } // namespace android #endif //QC_MEDIA_DEFS_H_ diff --git a/mm-core/inc/QCMetaData.h b/mm-core/inc/QCMetaData.h index 473cca6..c4805e0 100755..100644 --- a/mm-core/inc/QCMetaData.h +++ b/mm-core/inc/QCMetaData.h @@ -64,6 +64,14 @@ enum { kKeySmoothStreaming = 'ESmS', //bool (int32_t) kKeyHFR = 'hfr ', // int32_t kKeyHSR = 'hsr ', // int32_t + + kKeySampleBits = 'sbit', // int32_t (audio sample bit-width) + kKeyPcmFormat = 'pfmt', //int32_t (pcm format) + kKeyMinBlkSize = 'mibs', //int32_t + kKeyMaxBlkSize = 'mabs', //int32_t + kKeyMinFrmSize = 'mifs', //int32_t + kKeyMaxFrmSize = 'mafs', //int32_t + kKeyMd5Sum = 'md5s', //cstring }; enum { diff --git a/mm-core/src/msm8992/registry_table.c b/mm-core/src/msm8992/registry_table.c new file mode 100644 index 0000000..b4d4866 --- /dev/null +++ b/mm-core/src/msm8992/registry_table.c @@ -0,0 +1,511 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2014, 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. + +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + + "libOmxMux.so", + { + "container_muxer.mp2" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.decoder.hevc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.hevc" + } + }, + { + "OMX.qcom.video.decoder.hevc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.hevc" + } + }, + { + "OMX.qcom.video.decoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vp8" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263", + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.video.encoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.vp8", + } + }, + { + "OMX.qti.video.encoder.hevc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxSwVencHevc.so", + { + "video_encoder.hevc" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.video.postprocessing", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdpp.so", + { + "videopostprocessing" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/msm8992/registry_table_android.c b/mm-core/src/msm8992/registry_table_android.c new file mode 100644 index 0000000..200374e --- /dev/null +++ b/mm-core/src/msm8992/registry_table_android.c @@ -0,0 +1,654 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2014, 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. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.avc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.mpeg2", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg2" + } + }, + { + "OMX.qcom.video.decoder.mpeg2.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg2" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.vc1.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, +{ + "OMX.qcom.video.decoder.hevc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.hevc" + } + }, + { + "OMX.qcom.video.decoder.hevc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.hevc" + } + }, + { + "OMX.qcom.video.decoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vp8" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263" + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.video.encoder.avc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.video.encoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.vp8" + } + }, + { + "OMX.qti.video.encoder.hevc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxSwVencHevc.so", + { + "video_encoder.hevc" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wmaLossLess", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.amrwbplus", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrwbplusDec.so", + { + "audio_decoder.awbplus" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "AIV.play.generic", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libAivPlay.so", + { + "AIV.play.role.generic" + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMux.so", + { + "container_muxer.mp2" + } + }, + { + "OMX.qcom.video.postprocessing", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdpp.so", + { + "videopostprocessing" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/msm8994/registry_table.c b/mm-core/src/msm8994/registry_table.c new file mode 100644 index 0000000..d6820a8 --- /dev/null +++ b/mm-core/src/msm8994/registry_table.c @@ -0,0 +1,495 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2014, 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. + +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + + "libOmxMux.so", + { + "container_muxer.mp2" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.decoder.hevc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.hevc" + } + }, + { + "OMX.qcom.video.decoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vp8" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263", + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.video.encoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.vp8", + } + }, + { + "OMX.qcom.video.encoder.hevc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.hevc" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.video.postprocessing", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdpp.so", + { + "videopostprocessing" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/msm8994/registry_table_android.c b/mm-core/src/msm8994/registry_table_android.c new file mode 100644 index 0000000..449e4c9 --- /dev/null +++ b/mm-core/src/msm8994/registry_table_android.c @@ -0,0 +1,670 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2014, 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. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.avc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.mpeg2", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg2" + } + }, + { + "OMX.qcom.video.decoder.mpeg2.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg2" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.vc1.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.decoder.hevc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.hevc" + } + }, + { + "OMX.qcom.video.decoder.hevc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.hevc" + } + }, + { + "OMX.qcom.video.decoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vp8" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263" + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.video.encoder.avc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.video.encoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.vp8" + } + }, + { + "OMX.qcom.video.encoder.hevc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.hevc" + } + }, + { + "OMX.qcom.video.encoder.hevc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.hevc" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wmaLossLess", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.amrwbplus", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrwbplusDec.so", + { + "audio_decoder.awbplus" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "AIV.play.generic", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libAivPlay.so", + { + "AIV.play.role.generic" + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMux.so", + { + "container_muxer.mp2" + } + }, + { + "OMX.qcom.video.postprocessing", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdpp.so", + { + "videopostprocessing" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-video-legacy/DivxDrmDecrypt/Android.mk b/mm-video-legacy/DivxDrmDecrypt/Android.mk index 26a2f7a..ea43944 100755 --- a/mm-video-legacy/DivxDrmDecrypt/Android.mk +++ b/mm-video-legacy/DivxDrmDecrypt/Android.mk @@ -11,7 +11,6 @@ LOCAL_C_INCLUDES:= \ $(LOCAL_PATH)/inc \ $(TARGET_OUT_HEADERS)/mm-core/omxcore -LOCAL_PRELINK_MODULE:= false LOCAL_MODULE:= libdivxdrmdecrypt LOCAL_MODULE_TAGS := optional diff --git a/mm-video-legacy/vidc/vdec.mk b/mm-video-legacy/vidc/vdec.mk index 8a03382..478d2bc 100644 --- a/mm-video-legacy/vidc/vdec.mk +++ b/mm-video-legacy/vidc/vdec.mk @@ -51,9 +51,7 @@ libOmxVdec-def += -DUSE_ION include $(CLEAR_VARS) LOCAL_PATH:= $(ROOT_DIR) -libmm-vdec-inc := bionic/libc/include -libmm-vdec-inc += bionic/libstdc++/include -libmm-vdec-inc += $(LOCAL_PATH)/vdec/inc +libmm-vdec-inc := $(LOCAL_PATH)/vdec/inc libmm-vdec-inc += $(OMX_VIDEO_PATH)/vidc/common/inc libmm-vdec-inc += hardware/qcom/media/mm-core/inc #DRM include - Interface which loads the DRM library @@ -71,7 +69,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libOmxVdec-def) LOCAL_C_INCLUDES += $(libmm-vdec-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils libdl LOCAL_SHARED_LIBRARIES += libdivxdrmdecrypt @@ -101,7 +98,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libOmxVdec-def) LOCAL_C_INCLUDES := $(mm-vdec-test-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES := libutils liblog libOmxCore libOmxVdec libbinder LOCAL_SRC_FILES := vdec/src/queue.c @@ -121,7 +117,6 @@ LOCAL_MODULE := mm-video-driver-test LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libOmxVdec-def) LOCAL_C_INCLUDES := $(mm-vdec-drv-test-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SRC_FILES := vdec/src/message_queue.c LOCAL_SRC_FILES += vdec/test/decoder_driver_test.c diff --git a/mm-video-legacy/vidc/vdec/src/omx_vdec.cpp b/mm-video-legacy/vidc/vdec/src/omx_vdec.cpp index f47702d..4238a0c 100644 --- a/mm-video-legacy/vidc/vdec/src/omx_vdec.cpp +++ b/mm-video-legacy/vidc/vdec/src/omx_vdec.cpp @@ -437,7 +437,9 @@ PARAMETERS RETURN VALUE None. ========================================================================== */ -omx_vdec::omx_vdec(): m_state(OMX_StateInvalid), +omx_vdec::omx_vdec(): msg_thread_id(0), + async_thread_id(0), + m_state(OMX_StateInvalid), m_app_data(NULL), m_inp_mem_ptr(NULL), m_out_mem_ptr(NULL), @@ -582,9 +584,13 @@ omx_vdec::~omx_vdec() m_pipe_in = -1; m_pipe_out = -1; DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit"); - pthread_join(msg_thread_id,NULL); + if (msg_thread_id != 0) { + pthread_join(msg_thread_id,NULL); + } DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit"); - pthread_join(async_thread_id,NULL); + if (async_thread_id != 0) { + pthread_join(async_thread_id,NULL); + } pthread_mutex_destroy(&m_lock); pthread_mutex_destroy(&c_lock); sem_destroy(&m_cmd_lock); diff --git a/mm-video-legacy/vidc/venc.mk b/mm-video-legacy/vidc/venc.mk index 6ae2f16..052d4a6 100644 --- a/mm-video-legacy/vidc/venc.mk +++ b/mm-video-legacy/vidc/venc.mk @@ -42,8 +42,6 @@ libmm-venc-def += -D_ANDROID_ICS_ include $(CLEAR_VARS) -libmm-venc-inc := bionic/libc/include -libmm-venc-inc += bionic/libstdc++/include libmm-venc-inc := $(LOCAL_PATH)/venc/inc libmm-venc-inc += $(OMX_VIDEO_PATH)/vidc/common/inc libmm-venc-inc += hardware/qcom/media/mm-core/inc @@ -61,7 +59,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libmm-venc-def) LOCAL_C_INCLUDES := $(libmm-venc-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils \ libc2dcolorconvert libdl @@ -94,7 +91,6 @@ LOCAL_MODULE := mm-venc-omx-test720p LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libmm-venc-def) LOCAL_C_INCLUDES := $(mm-venc-test720p-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES := libmm-omxcore libOmxVenc libbinder LOCAL_SRC_FILES := venc/test/venc_test.cpp @@ -117,7 +113,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(venc-test-inc) LOCAL_C_INCLUDES += hardware/qcom/media/mm-core/inc -LOCAL_PRELINK_MODULE := false LOCAL_SRC_FILES := venc/test/video_encoder_test.c LOCAL_SRC_FILES += venc/test/queue.c diff --git a/mm-video-legacy/vidc/venc/inc/video_encoder_device.h b/mm-video-legacy/vidc/venc/inc/video_encoder_device.h index fcca3ea..bacb3fc 100644 --- a/mm-video-legacy/vidc/venc/inc/video_encoder_device.h +++ b/mm-video-legacy/vidc/venc/inc/video_encoder_device.h @@ -65,10 +65,10 @@ public: bool venc_empty_buf(void *, void *,unsigned,unsigned); bool venc_fill_buf(void *, void *,unsigned,unsigned); - bool venc_get_buf_req(unsigned long *,unsigned long *, - unsigned long *,unsigned long); - bool venc_set_buf_req(unsigned long *,unsigned long *, - unsigned long *,unsigned long); + bool venc_get_buf_req(OMX_U32 *,OMX_U32 *, + OMX_U32 *,OMX_U32); + bool venc_set_buf_req(OMX_U32 *,OMX_U32 *, + OMX_U32 *,OMX_U32); bool venc_set_param(void *,OMX_INDEXTYPE); bool venc_set_config(void *configData, OMX_INDEXTYPE index); bool venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel); diff --git a/mm-video-legacy/vidc/venc/src/omx_video_base.cpp b/mm-video-legacy/vidc/venc/src/omx_video_base.cpp index adf782f..dd4d98d 100644 --- a/mm-video-legacy/vidc/venc/src/omx_video_base.cpp +++ b/mm-video-legacy/vidc/venc/src/omx_video_base.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. +Copyright (c) 2010-2012, 2015 Code Aurora Forum. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -223,7 +223,9 @@ PARAMETERS RETURN VALUE None. ========================================================================== */ -omx_video::omx_video(): m_state(OMX_StateInvalid), +omx_video::omx_video(): msg_thread_id(0), + async_thread_id(0), + m_state(OMX_StateInvalid), m_app_data(NULL), m_inp_mem_ptr(NULL), m_out_mem_ptr(NULL), @@ -247,6 +249,8 @@ omx_video::omx_video(): m_state(OMX_StateInvalid), m_use_output_pmem(OMX_FALSE), m_etb_count(0), m_fbd_count(0), + m_pipe_in(-1), + m_pipe_out(-1), m_error_propogated(false), m_input_msg_id(OMX_COMPONENT_GENERATE_ETB), psource_frame(NULL), @@ -279,12 +283,16 @@ RETURN VALUE omx_video::~omx_video() { DEBUG_PRINT_HIGH("\n ~omx_video(): Inside Destructor()"); - if(m_pipe_in) close(m_pipe_in); - if(m_pipe_out) close(m_pipe_out); + if(m_pipe_in >= 0) close(m_pipe_in); + if(m_pipe_out >= 0) close(m_pipe_out); DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit\n"); - pthread_join(msg_thread_id,NULL); + if (msg_thread_id != 0) { + pthread_join(msg_thread_id,NULL); + } DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit\n"); - pthread_join(async_thread_id,NULL); + if (async_thread_id != 0) { + pthread_join(async_thread_id,NULL); + } pthread_mutex_destroy(&m_lock); sem_destroy(&m_cmd_lock); DEBUG_PRINT_HIGH("\n m_etb_count = %u, m_fbd_count = %u\n", m_etb_count, @@ -1691,15 +1699,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, comp_role->nSize = sizeof(*comp_role); DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n",paramIndex); - if(NULL != comp_role->cRole) - { - strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE); - } - else - { - DEBUG_PRINT_ERROR("ERROR: Getparameter: OMX_IndexParamStandardComponentRole %d is passed with NULL parameter for role\n",paramIndex); - eRet =OMX_ErrorBadParameter; - } + strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE); break; } /* Added for parameter test */ diff --git a/mm-video-legacy/vidc/venc/src/video_encoder_device.cpp b/mm-video-legacy/vidc/venc/src/video_encoder_device.cpp index aed5b18..4992780 100644 --- a/mm-video-legacy/vidc/venc/src/video_encoder_device.cpp +++ b/mm-video-legacy/vidc/venc/src/video_encoder_device.cpp @@ -335,10 +335,10 @@ void venc_dev::venc_close() #endif } -bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count, - unsigned long *actual_buff_count, - unsigned long *buff_size, - unsigned long port) +bool venc_dev::venc_set_buf_req(OMX_U32 *min_buff_count, + OMX_U32 *actual_buff_count, + OMX_U32 *buff_size, + OMX_U32 port) { struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; unsigned long temp_count = 0; @@ -501,10 +501,10 @@ bool venc_dev::venc_get_seq_hdr(void *buffer, return true; } -bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count, - unsigned long *actual_buff_count, - unsigned long *buff_size, - unsigned long port) +bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count, + OMX_U32 *actual_buff_count, + OMX_U32 *buff_size, + OMX_U32 port) { struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; diff --git a/mm-video-legacy/vidc/venc/test/venc_test.cpp b/mm-video-legacy/vidc/venc/test/venc_test.cpp index 5e8d040..154fee4 100644 --- a/mm-video-legacy/vidc/venc/test/venc_test.cpp +++ b/mm-video-legacy/vidc/venc/test/venc_test.cpp @@ -80,23 +80,23 @@ REFERENCES #ifdef VENC_SYSLOG #include "cutils/log.h" /// Debug message macro -#define D(fmt, ...) LOGE("venc_test Debug %s::%d "fmt"\n", \ +#define D(fmt, ...) LOGE("venc_test Debug %s::%d " fmt "\n", \ __FUNCTION__, __LINE__, \ ## __VA_ARGS__) /// Error message macro -#define E(fmt, ...) LOGE("venc_test Error %s::%d "fmt"\n", \ +#define E(fmt, ...) LOGE("venc_test Error %s::%d " fmt "\n", \ __FUNCTION__, __LINE__, \ ## __VA_ARGS__) #else #ifdef TEST_LOG - #define D(fmt, ...) fprintf(stderr, "venc_test Debug %s::%d "fmt"\n", \ + #define D(fmt, ...) fprintf(stderr, "venc_test Debug %s::%d " fmt "\n", \ __FUNCTION__, __LINE__, \ ## __VA_ARGS__) /// Error message macro - #define E(fmt, ...) fprintf(stderr, "venc_test Error %s::%d "fmt"\n", \ + #define E(fmt, ...) fprintf(stderr, "venc_test Error %s::%d " fmt "\n", \ __FUNCTION__, __LINE__, \ ## __VA_ARGS__) #else diff --git a/mm-video-v4l2/DivxDrmDecrypt/Android.mk b/mm-video-v4l2/DivxDrmDecrypt/Android.mk index 3886226..28f5072 100755 --- a/mm-video-v4l2/DivxDrmDecrypt/Android.mk +++ b/mm-video-v4l2/DivxDrmDecrypt/Android.mk @@ -18,7 +18,6 @@ LOCAL_C_INCLUDES:= \ $(LOCAL_PATH)/inc \ $(TARGET_OUT_HEADERS)/mm-core/omxcore -LOCAL_PRELINK_MODULE:= false LOCAL_MODULE:= libdivxdrmdecrypt LOCAL_MODULE_TAGS := optional diff --git a/mm-video-v4l2/vidc/common/inc/vidc_debug.h b/mm-video-v4l2/vidc/common/inc/vidc_debug.h index d7a158c..d9007f2 100755 --- a/mm-video-v4l2/vidc/common/inc/vidc_debug.h +++ b/mm-video-v4l2/vidc/common/inc/vidc_debug.h @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013 - 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: @@ -31,6 +31,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef _ANDROID_ #include <cstdio> +#include <pthread.h> enum { PRIO_ERROR=0x1, @@ -64,4 +65,28 @@ extern int debug_level; #define DEBUG_PRINT_HIGH printf #endif +#define VALIDATE_OMX_PARAM_DATA(ptr, paramType) \ + { \ + if (ptr == NULL) { return OMX_ErrorBadParameter; } \ + paramType *p = reinterpret_cast<paramType *>(ptr); \ + if (p->nSize < sizeof(paramType)) { \ + ALOGE("Insufficient object size(%u) v/s expected(%zu) for type %s",\ + (unsigned int)p->nSize, sizeof(paramType), #paramType); \ + return OMX_ErrorBadParameter; \ + } \ + } \ + +class auto_lock { + public: + auto_lock(pthread_mutex_t &lock) + : mLock(lock) { + pthread_mutex_lock(&mLock); + } + ~auto_lock() { + pthread_mutex_unlock(&mLock); + } + private: + pthread_mutex_t &mLock; +}; + #endif diff --git a/mm-video-v4l2/vidc/common/src/extra_data_handler.cpp b/mm-video-v4l2/vidc/common/src/extra_data_handler.cpp index d14a252..bb4cafa 100755..100644 --- a/mm-video-v4l2/vidc/common/src/extra_data_handler.cpp +++ b/mm-video-v4l2/vidc/common/src/extra_data_handler.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2015, 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: @@ -28,6 +28,8 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "extra_data_handler.h" +int debug_level = PRIO_ERROR; + extra_data_handler::extra_data_handler() { rbsp_buf = (OMX_U8 *) calloc(1,100); diff --git a/mm-video-v4l2/vidc/vdec.mk b/mm-video-v4l2/vidc/vdec.mk index 998cf5b..ffee562 100644 --- a/mm-video-v4l2/vidc/vdec.mk +++ b/mm-video-v4l2/vidc/vdec.mk @@ -42,6 +42,7 @@ libOmxVdec-def += -DMAX_RES_1080P_EBI libOmxVdec-def += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT libOmxVdec-def += -D_MSM8974_ libOmxVdec-def += -D_HEVC_USE_ADSP_HEAP_ +libOmxVdec-def += -DDISABLE_INPUT_BUFFER_CACHE endif ifeq ($(TARGET_BOARD_PLATFORM),msm7627a) libOmxVdec-def += -DMAX_RES_720P @@ -70,7 +71,7 @@ libOmxVdec-def += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT libOmxVdec-def += -D_MSM8974_ libOmxVdec-def += -D_ION_HEAP_MASK_COMPATIBILITY_WA endif -ifeq ($(TARGET_BOARD_PLATFORM),mpq8092) +ifneq ($(filter msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),) libOmxVdec-def += -DMAX_RES_1080P libOmxVdec-def += -DMAX_RES_1080P_EBI libOmxVdec-def += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT @@ -82,6 +83,9 @@ ifeq ($(TARGET_USES_ION),true) libOmxVdec-def += -DUSE_ION endif +libOmxVdec-def += -DFLEXYUV_SUPPORTED +libOmxVdec-def += -DADAPTIVE_PLAYBACK_SUPPORTED + # --------------------------------------------------------------------------------- # Make the Shared library (libOmxVdec) # --------------------------------------------------------------------------------- @@ -89,9 +93,7 @@ endif include $(CLEAR_VARS) LOCAL_PATH:= $(ROOT_DIR) -libmm-vdec-inc := bionic/libc/include -libmm-vdec-inc += bionic/libstdc++/include -libmm-vdec-inc += $(LOCAL_PATH)/vdec/inc +libmm-vdec-inc := $(LOCAL_PATH)/vdec/inc libmm-vdec-inc += $(OMX_VIDEO_PATH)/vidc/common/inc libmm-vdec-inc += hardware/qcom/media/mm-core/inc #DRM include - Interface which loads the DRM library @@ -110,7 +112,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libOmxVdec-def) LOCAL_C_INCLUDES += $(libmm-vdec-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils libdl LOCAL_SHARED_LIBRARIES += libdivxdrmdecrypt @@ -121,7 +122,7 @@ LOCAL_SRC_FILES += vdec/src/h264_utils.cpp LOCAL_SRC_FILES += vdec/src/ts_parser.cpp LOCAL_SRC_FILES += vdec/src/mp4_utils.cpp LOCAL_SRC_FILES += vdec/src/hevc_utils.cpp -ifneq ($(filter msm8974 msm8610 msm8226 msm8084 mpq8092,$(TARGET_BOARD_PLATFORM)),) +ifneq ($(filter msm8974 msm8610 msm8226 msm8084 msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),) LOCAL_SRC_FILES += vdec/src/omx_vdec_msm8974.cpp else LOCAL_SHARED_LIBRARIES += libhardware @@ -133,6 +134,9 @@ endif LOCAL_SRC_FILES += common/src/extra_data_handler.cpp LOCAL_SRC_FILES += common/src/vidc_color_converter.cpp +# omx_vdec_msm8974.cpp:9375:16: address of array 'extra->data' will always evaluate to 'true' +LOCAL_CLANG_CFLAGS += -Wno-pointer-bool-conversion + include $(BUILD_SHARED_LIBRARY) @@ -143,14 +147,13 @@ include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_PATH:= $(ROOT_DIR) -ifneq ($(filter msm8974 msm8610 msm8084 mpq8092,$(TARGET_BOARD_PLATFORM)),) +ifneq ($(filter msm8974 msm8610 msm8084 msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),) LOCAL_MODULE := libOmxVdecHevc LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libOmxVdec-def) LOCAL_C_INCLUDES += $(libmm-vdec-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils libdl LOCAL_SHARED_LIBRARIES += libdivxdrmdecrypt @@ -185,7 +188,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libOmxVdec-def) LOCAL_C_INCLUDES := $(mm-vdec-test-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES := libutils libOmxCore libOmxVdec libbinder libcutils LOCAL_SRC_FILES := vdec/src/queue.c @@ -206,7 +208,6 @@ LOCAL_MODULE := mm-video-driver-test LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libOmxVdec-def) LOCAL_C_INCLUDES := $(mm-vdec-drv-test-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SRC_FILES := vdec/src/message_queue.c LOCAL_SRC_FILES += vdec/test/decoder_driver_test.c diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index 59fd836..bc3d41a 100755..100644 --- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -92,6 +92,8 @@ extern "C" { #endif #include "OMX_Core.h" #include "OMX_QCOMExtns.h" +#include "OMX_VideoExt.h" +#include "OMX_IndexExt.h" #include "qc_omx_component.h" #include <linux/msm_vidc_dec.h> #include <media/msm_vidc.h> @@ -118,11 +120,11 @@ using namespace android; class VideoHeap : public MemoryHeapBase { public: - VideoHeap(int devicefd, size_t size, void* base,struct ion_handle *handle,int mapfd); + VideoHeap(int devicefd, size_t size, void* base,ion_user_handle_t handle,int mapfd); virtual ~VideoHeap() {} private: int m_ion_device_fd; - struct ion_handle *m_ion_handle; + ion_user_handle_t m_ion_handle; }; #else // local pmem heap object @@ -153,10 +155,10 @@ class VideoHeap : public MemoryHeapBase (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp) // BitMask Management logic -#define BITS_PER_BYTE 32 -#define BITMASK_SIZE(mIndex) (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE) -#define BITMASK_OFFSET(mIndex) ((mIndex)/BITS_PER_BYTE) -#define BITMASK_FLAG(mIndex) (1 << ((mIndex) % BITS_PER_BYTE)) +#define BITS_PER_INDEX 64 +#define BITMASK_SIZE(mIndex) (((mIndex) + BITS_PER_INDEX - 1)/BITS_PER_INDEX) +#define BITMASK_OFFSET(mIndex) ((mIndex)/BITS_PER_INDEX) +#define BITMASK_FLAG(mIndex) ((uint64_t)1 << ((mIndex) % BITS_PER_INDEX)) #define BITMASK_CLEAR(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \ &= ~(BITMASK_FLAG(mIndex)) #define BITMASK_SET(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \ @@ -181,7 +183,7 @@ class VideoHeap : public MemoryHeapBase #define DESC_BUFFER_SIZE (8192 * 16) #ifdef _ANDROID_ -#define MAX_NUM_INPUT_OUTPUT_BUFFERS 32 +#define MAX_NUM_INPUT_OUTPUT_BUFFERS 64 #endif #ifdef _ION_HEAP_MASK_COMPATIBILITY_WA @@ -199,6 +201,7 @@ class VideoHeap : public MemoryHeapBase #define OMX_FRAMEPACK_EXTRADATA 0x00400000 #define OMX_QP_EXTRADATA 0x00800000 #define OMX_BITSINFO_EXTRADATA 0x01000000 +#define OMX_MPEG2SEQDISP_EXTRADATA 0x02000000 #define DRIVER_EXTRADATA_MASK 0x0000FFFF #define OMX_INTERLACE_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\ @@ -215,8 +218,10 @@ class VideoHeap : public MemoryHeapBase sizeof(OMX_QCOM_EXTRADATA_QP) + 3)&(~3)) #define OMX_BITSINFO_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\ sizeof(OMX_QCOM_EXTRADATA_BITS_INFO) + 3)&(~3)) +#define OMX_MPEG2SEQDISP_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\ + sizeof(OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY) + 3)&(~3)) #define OMX_USERDATA_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\ - ((8*1024) + 3))&(~3)) /* 8 KB is the size that driver/FW considers as worst case size for userdata */ + + 3)&(~3)) // Define next macro with required values to enable default extradata, // VDEC_EXTRADATA_MB_ERROR_MAP @@ -256,6 +261,7 @@ struct video_driver_context { enum vdec_output_fromat output_format; enum vdec_interlaced_format interlace; enum vdec_output_order picture_order; + struct vdec_framesize frame_size; struct vdec_picsize video_resolution; struct vdec_allocatorproperty ip_buf; struct vdec_allocatorproperty op_buf; @@ -474,7 +480,8 @@ class omx_vdec: public qc_omx_component OMX_COMPONENT_PAUSE_PENDING =0xB, OMX_COMPONENT_EXECUTE_PENDING =0xC, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING =0xD, - OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED=0xE + OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED=0xE, + OMX_COMPONENT_FLUSH_DEFERRED = 0xF }; // Deferred callback identifiers @@ -511,6 +518,7 @@ class omx_vdec: public qc_omx_component OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG = 0x15, OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED = 0x16, OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING = 0x17, + OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD = 0x18, }; enum vc1_profile_type { @@ -688,6 +696,8 @@ class omx_vdec: public qc_omx_component struct msm_vidc_frame_qp_payload *qp_payload); void append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra, struct msm_vidc_frame_bits_info_payload *bits_payload); + void append_mpeg2_seqdisplay_extradata(OMX_OTHER_EXTRADATATYPE *extra, + struct msm_vidc_mpeg2_seqdisp_payload* seq_display_payload); void insert_demux_addr_offset(OMX_U32 address_offset); void extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr); OMX_ERRORTYPE handle_demux_data(OMX_BUFFERHEADERTYPE *buf_hdr); @@ -730,7 +740,7 @@ class omx_vdec: public qc_omx_component inline void omx_report_error () { if (m_cb.EventHandler && !m_error_propogated) { - ALOGE("\nERROR: Sending OMX_EventError to Client"); + DEBUG_PRINT_ERROR("ERROR: Sending OMX_ErrorHardware to Client"); m_error_propogated = true; m_cb.EventHandler(&m_cmp,m_app_data, OMX_EventError,OMX_ErrorHardware,0,NULL); @@ -740,12 +750,22 @@ class omx_vdec: public qc_omx_component inline void omx_report_unsupported_setting () { if (m_cb.EventHandler && !m_error_propogated) { DEBUG_PRINT_ERROR( - "\nERROR: Sending OMX_ErrorUnsupportedSetting to Client"); + "ERROR: Sending OMX_ErrorUnsupportedSetting to Client"); m_error_propogated = true; m_cb.EventHandler(&m_cmp,m_app_data, OMX_EventError,OMX_ErrorUnsupportedSetting,0,NULL); } } + inline void omx_report_hw_overload () { + if (m_cb.EventHandler && !m_error_propogated) { + DEBUG_PRINT_ERROR( + "ERROR: Sending OMX_ErrorInsufficientResources to Client"); + m_error_propogated = true; + m_cb.EventHandler(&m_cmp, m_app_data, + OMX_EventError, OMX_ErrorInsufficientResources, 0, NULL); + } + } + #ifdef _ANDROID_ OMX_ERRORTYPE createDivxDrmContext(); #endif //_ANDROID_ @@ -767,6 +787,7 @@ class omx_vdec: public qc_omx_component //************************************************************* pthread_mutex_t m_lock; pthread_mutex_t c_lock; + pthread_mutex_t buf_lock; //sem to handle the minimum procesing of commands sem_t m_cmd_lock; sem_t m_safe_flush; @@ -809,9 +830,9 @@ class omx_vdec: public qc_omx_component int pending_input_buffers; int pending_output_buffers; // bitmask array size for output side - unsigned int m_out_bm_count; + uint64_t m_out_bm_count; // bitmask array size for input side - unsigned int m_inp_bm_count; + uint64_t m_inp_bm_count; //Input port Populated OMX_BOOL m_inp_bPopulated; //Output port Populated @@ -933,10 +954,14 @@ class omx_vdec: public qc_omx_component int capture_capability; int output_capability; bool streaming[MAX_PORT]; + OMX_FRAMESIZETYPE framesize; OMX_CONFIG_RECTTYPE rectangle; - int prev_n_filled_len; + OMX_U32 prev_n_filled_len; bool is_down_scalar_enabled; #endif + struct custom_buffersize { + OMX_U32 input_buffersize; + } m_custom_buffersize; bool m_power_hinted; bool is_q6_platform; OMX_ERRORTYPE power_module_register(); @@ -954,6 +979,7 @@ class omx_vdec: public qc_omx_component OMX_U32 m_smoothstreaming_width; OMX_U32 m_smoothstreaming_height; OMX_ERRORTYPE enable_smoothstreaming(); + OMX_ERRORTYPE enable_adaptive_playback(unsigned long width, unsigned long height); unsigned int m_fill_output_msg; bool client_set_fps; @@ -977,6 +1003,7 @@ class omx_vdec: public qc_omx_component OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData, OMX_U32 bytes); OMX_ERRORTYPE free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr); + bool is_color_conversion_enabled() {return enabled;} private: #define MAX_COUNT 32 omx_vdec *omx; @@ -1002,6 +1029,14 @@ class omx_vdec: public qc_omx_component sp<MemoryHeapBase> video_heap_ptr; }; struct vidc_heap m_heap_ptr[MAX_COUNT]; + + OMX_ERRORTYPE cache_ops(unsigned int index, unsigned int cmd); + inline OMX_ERRORTYPE cache_clean_buffer(unsigned int index) { + return cache_ops(index, ION_IOC_CLEAN_CACHES); + } + OMX_ERRORTYPE cache_clean_invalidate_buffer(unsigned int index) { + return cache_ops(index, ION_IOC_CLEAN_INV_CACHES); + } }; #if defined (_MSM8960_) || defined (_MSM8974_) allocate_color_convert_buf client_buffers; @@ -1014,6 +1049,8 @@ class omx_vdec: public qc_omx_component void send_codec_config(); #endif OMX_TICKS m_last_rendered_TS; + volatile int32_t m_queued_codec_config_count; + bool secure_scaling_to_non_secure_opb; class perf_control { // 2 cores will be requested if framerate is beyond 45 fps @@ -1035,19 +1072,33 @@ class omx_vdec: public qc_omx_component }; perf_control m_perf_control; - volatile int32_t m_queued_codec_config_count; - static OMX_COLOR_FORMATTYPE getColorFormatAt(OMX_U32 index) { - OMX_COLOR_FORMATTYPE formats[] = { + static OMX_COLOR_FORMATTYPE getPreferredColorFormatNonSurfaceMode(OMX_U32 index) { + //On Android, we default to standard YUV formats for non-surface use-cases + //where apps prefer known color formats. + OMX_COLOR_FORMATTYPE formatsNonSurfaceMode[] = { + [0] = OMX_COLOR_FormatYUV420SemiPlanar, + [1] = OMX_COLOR_FormatYUV420Planar, + [2] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m, + [3] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView, + }; + return (index < sizeof(formatsNonSurfaceMode) / sizeof(OMX_COLOR_FORMATTYPE)) ? + formatsNonSurfaceMode[index] : OMX_COLOR_FormatMax; + } + + static OMX_COLOR_FORMATTYPE getPreferredColorFormatDefaultMode(OMX_U32 index) { + //for surface mode (normal playback), advertise native/accelerated formats first + OMX_COLOR_FORMATTYPE formatsDefault[] = { [0] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m, [1] = OMX_COLOR_FormatYUV420SemiPlanar, [2] = OMX_COLOR_FormatYUV420Planar, [3] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView, }; - return (index < sizeof(formats) / sizeof(OMX_COLOR_FORMATTYPE)) ? - formats[index] : OMX_COLOR_FormatMax; + return (index < sizeof(formatsDefault) / sizeof(OMX_COLOR_FORMATTYPE)) ? + formatsDefault[index] : OMX_COLOR_FormatMax; } - static OMX_ERRORTYPE describeColorFormat(DescribeColorFormatParams *params); + static OMX_ERRORTYPE describeColorFormat(OMX_PTR params); + }; #ifdef _MSM8974_ diff --git a/mm-video-v4l2/vidc/vdec/inc/ts_parser.h b/mm-video-v4l2/vidc/vdec/inc/ts_parser.h index 161b64d..2d5d1a4 100755..100644 --- a/mm-video-v4l2/vidc/vdec/inc/ts_parser.h +++ b/mm-video-v4l2/vidc/vdec/inc/ts_parser.h @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2015, 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: @@ -47,6 +47,21 @@ extern "C" { class omx_time_stamp_reorder { + class auto_lock { + public: + auto_lock(pthread_mutex_t *lock) + : mLock(lock) { + if (mLock) + pthread_mutex_lock(mLock); + } + ~auto_lock() { + if (mLock) + pthread_mutex_unlock(mLock); + } + private: + pthread_mutex_t *mLock; + }; + public: omx_time_stamp_reorder(); ~omx_time_stamp_reorder(); @@ -86,5 +101,6 @@ class omx_time_stamp_reorder } bool reorder_ts; bool print_debug; + pthread_mutex_t m_lock; }; #endif diff --git a/mm-video-v4l2/vidc/vdec/src/h264_utils.cpp b/mm-video-v4l2/vidc/vdec/src/h264_utils.cpp index e21d716..8eb5168 100755..100644 --- a/mm-video-v4l2/vidc/vdec/src/h264_utils.cpp +++ b/mm-video-v4l2/vidc/vdec/src/h264_utils.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010 - 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2010 - 2015, 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: @@ -1292,7 +1292,7 @@ void h264_stream_parser::get_frame_rate(OMX_U32 *frame_rate) void h264_stream_parser::parse_nal(OMX_U8* data_ptr, OMX_U32 data_len, OMX_U32 nal_type, bool enable_emu_sc) { OMX_U32 nal_unit_type = NALU_TYPE_UNSPECIFIED, cons_bytes = 0; - ALOGV("parse_nal(): IN nal_type(%lu)", nal_type); + ALOGV("parse_nal(): IN nal_type(%u)", nal_type); if (!data_len) return; init_bitstream(data_ptr, data_len); @@ -1320,7 +1320,7 @@ void h264_stream_parser::parse_nal(OMX_U8* data_ptr, OMX_U32 data_len, OMX_U32 n parse_vui(true); break; default: - ALOGV("nal_unit_type received : %lu", nal_type); + ALOGV("nal_unit_type received : %u", nal_type); } ALOGV("parse_nal(): OUT"); } diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_hevc.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_hevc.cpp index 2811e3b..b82d066 100755..100644 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_hevc.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_hevc.cpp @@ -136,8 +136,6 @@ extern "C" { #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA) -int debug_level = PRIO_ERROR; - void* async_message_thread (void *input) { OMX_BUFFERHEADERTYPE *buffer; @@ -462,7 +460,7 @@ void *get_omx_component_factory_fn(void) #ifdef _ANDROID_ #ifdef USE_ION VideoHeap::VideoHeap(int devicefd, size_t size, void* base, - struct ion_handle *handle, int ionMapfd) + ion_user_handle_t handle, int ionMapfd) { // ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd); } @@ -5252,6 +5250,7 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE h OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_IN OMX_BUFFERHEADERTYPE* buffer) { + unsigned nPortIndex = buffer - client_buffers.get_il_buf_hdr(); if (m_state == OMX_StateInvalid) { DEBUG_PRINT_ERROR("FTB in Invalid State"); @@ -5264,7 +5263,9 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, } if (buffer == NULL || - ((buffer - client_buffers.get_il_buf_hdr()) >= drv_ctx.op_buf.actualcount)) { + (nPortIndex >= drv_ctx.op_buf.actualcount)) { + DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u", + nPortIndex, drv_ctx.op_buf.actualcount); return OMX_ErrorBadParameter; } @@ -5305,8 +5306,11 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); - if (bufferAdd == NULL || nPortIndex > drv_ctx.op_buf.actualcount) + if (bufferAdd == NULL || nPortIndex > drv_ctx.op_buf.actualcount) { + DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u", + nPortIndex, drv_ctx.op_buf.actualcount); return OMX_ErrorBadParameter; + } DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p", bufferAdd, bufferAdd->pBuffer); @@ -6941,12 +6945,12 @@ int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, alloc_data->flags |= ION_SECURE; #ifdef _HEVC_USE_ADSP_HEAP_ - alloc_data->ION_HEAP_MASK = ION_HEAP(ION_ADSP_HEAP_ID); + alloc_data->heap_id_mask = ION_HEAP(ION_ADSP_HEAP_ID); #else - alloc_data->ION_HEAP_MASK = ION_HEAP(ION_IOMMU_HEAP_ID); + alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID); #endif if (secure_mode) { - alloc_data->ION_HEAP_MASK = ION_HEAP(MEM_HEAP_ID); + alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID); } rc = ioctl(fd,ION_IOC_ALLOC,alloc_data); if (rc || !alloc_data->handle) { diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp index b425157..c0d19e0 100755..100644 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp @@ -39,6 +39,9 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Include Files ////////////////////////////////////////////////////////////////////////////// +#define __STDC_FORMAT_MACROS +#include <inttypes.h> + #include <string.h> #include <pthread.h> #include <sys/prctl.h> @@ -83,11 +86,10 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef OUTPUT_EXTRADATA_LOG FILE *outputExtradataFile; -char output_extradata_filename [] = "/data/misc/extradata"; +char output_extradata_filename [] = "/data/misc/media/extradata"; #endif #define DEFAULT_FPS 30 -#define MAX_INPUT_ERROR DEFAULT_FPS #define MAX_SUPPORTED_FPS 120 #define DEFAULT_WIDTH_ALIGNMENT 128 #define DEFAULT_HEIGHT_ALIGNMENT 32 @@ -124,11 +126,11 @@ extern "C" { #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } #define EXTRADATA_IDX(__num_planes) (__num_planes - 1) +#define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1)) #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA) -#define DEFAULT_CONCEAL_COLOR "32896" //0x8080, black by default +#define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default -int debug_level = PRIO_ERROR; static OMX_U32 maxSmoothStreamingWidth = 1920; static OMX_U32 maxSmoothStreamingHeight = 1088; @@ -176,6 +178,8 @@ void* async_message_thread (void *input) vdec_msg.msgdata.output_frame.framesize.top = plane[0].reserved[3]; vdec_msg.msgdata.output_frame.framesize.right = plane[0].reserved[4]; vdec_msg.msgdata.output_frame.framesize.bottom = plane[0].reserved[5]; + vdec_msg.msgdata.output_frame.picsize.frame_width = plane[0].reserved[6]; + vdec_msg.msgdata.output_frame.picsize.frame_height = plane[0].reserved[7]; } if (omx->async_message_process(input,&vdec_msg) < 0) { DEBUG_PRINT_HIGH("async_message_thread Exited"); @@ -229,6 +233,24 @@ void* async_message_thread (void *input) } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_CLOSE_DONE) { DEBUG_PRINT_HIGH("VIDC Close Done Recieved and async_message_thread Exited"); break; + } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) { + struct vdec_msginfo vdec_msg; + vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD; + vdec_msg.status_code=VDEC_S_SUCCESS; + DEBUG_PRINT_ERROR("HW Overload received"); + if (omx->async_message_process(input,&vdec_msg) < 0) { + DEBUG_PRINT_HIGH("async_message_thread Exited"); + break; + } + } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) { + struct vdec_msginfo vdec_msg; + vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED; + vdec_msg.status_code=VDEC_S_SUCCESS; + DEBUG_PRINT_ERROR("HW Unsupported received"); + if (omx->async_message_process(input,&vdec_msg) < 0) { + DEBUG_PRINT_HIGH("async_message_thread Exited"); + break; + } } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) { struct vdec_msginfo vdec_msg; vdec_msg.msgcode=VDEC_MSG_EVT_HW_ERROR; @@ -470,7 +492,7 @@ void *get_omx_component_factory_fn(void) #ifdef _ANDROID_ #ifdef USE_ION VideoHeap::VideoHeap(int devicefd, size_t size, void* base, - struct ion_handle *handle, int ionMapfd) + ion_user_handle_t handle, int ionMapfd) { (void) devicefd; (void) size; @@ -505,7 +527,6 @@ omx_vdec::omx_vdec(): m_error_propogated(false), m_app_data(NULL), m_inp_mem_ptr(NULL), m_out_mem_ptr(NULL), - m_inp_err_count(0), input_flush_progress (false), output_flush_progress (false), input_use_buffer (false), @@ -570,10 +591,11 @@ omx_vdec::omx_vdec(): m_error_propogated(false), m_profile(0), client_set_fps(false), m_last_rendered_TS(-1), - m_queued_codec_config_count(0) + m_queued_codec_config_count(0), + secure_scaling_to_non_secure_opb(false) { /* Assumption is that , to begin with , we have all the frames with decoder */ - DEBUG_PRINT_HIGH("In %d bit OMX vdec Constructor", sizeof(long) * 8); + DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8); memset(&m_debug,0,sizeof(m_debug)); #ifdef _ANDROID_ char property_value[PROPERTY_VALUE_MAX] = {0}; @@ -645,6 +667,7 @@ omx_vdec::omx_vdec(): m_error_propogated(false), memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE)); memset (m_hwdevice_name,0,sizeof(m_hwdevice_name)); memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); + memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize)); m_demux_entries = 0; msg_thread_id = 0; async_thread_id = 0; @@ -664,6 +687,7 @@ omx_vdec::omx_vdec(): m_error_propogated(false), m_vendor_config.pData = NULL; pthread_mutex_init(&m_lock, NULL); pthread_mutex_init(&c_lock, NULL); + pthread_mutex_init(&buf_lock, NULL); sem_init(&m_cmd_lock,0,0); sem_init(&m_safe_flush, 0, 0); streaming[CAPTURE_PORT] = @@ -692,7 +716,9 @@ static const int event_type[] = { V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE, V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER, V4L2_EVENT_MSM_VIDC_CLOSE_DONE, - V4L2_EVENT_MSM_VIDC_SYS_ERROR + V4L2_EVENT_MSM_VIDC_SYS_ERROR, + V4L2_EVENT_MSM_VIDC_HW_OVERLOAD, + V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED }; static OMX_ERRORTYPE subscribe_to_events(int fd) @@ -789,6 +815,7 @@ omx_vdec::~omx_vdec() close(drv_ctx.video_driver_fd); pthread_mutex_destroy(&m_lock); pthread_mutex_destroy(&c_lock); + pthread_mutex_destroy(&buf_lock); sem_destroy(&m_cmd_lock); if (perf_flag) { DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME"); @@ -947,12 +974,17 @@ void omx_vdec::process_event_cb(void *ctxt, unsigned char id) pThis->omx_report_error (); } break; - case OMX_COMPONENT_GENERATE_ETB: - if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\ - (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) { + case OMX_COMPONENT_GENERATE_ETB: { + OMX_ERRORTYPE iret; + iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2); + if (iret == OMX_ErrorInsufficientResources) { + DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload"); + pThis->omx_report_hw_overload (); + } else if (iret != OMX_ErrorNone) { DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure"); pThis->omx_report_error (); } + } break; case OMX_COMPONENT_GENERATE_FTB: @@ -975,23 +1007,16 @@ void omx_vdec::process_event_cb(void *ctxt, unsigned char id) pThis->omx_report_error (); } else { if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) { - pThis->m_inp_err_count++; pThis->time_stamp_dts.remove_time_stamp( ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp, (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) ?true:false); - } else { - pThis->m_inp_err_count = 0; } if ( pThis->empty_buffer_done(&pThis->m_cmp, (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) { DEBUG_PRINT_ERROR("empty_buffer_done failure"); pThis->omx_report_error (); } - if (pThis->m_inp_err_count >= MAX_INPUT_ERROR) { - DEBUG_PRINT_ERROR("Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR); - pThis->omx_report_error (); - } } break; case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: { @@ -1218,10 +1243,87 @@ void omx_vdec::process_event_cb(void *ctxt, unsigned char id) break; case OMX_COMPONENT_GENERATE_PORT_RECONFIG: - DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG"); - if (p2 == OMX_IndexParamPortDefinition) { + DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition"); pThis->in_reconfig = true; + + } else if (p2 == OMX_IndexConfigCommonOutputCrop) { + DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop"); + + /* Check if resolution is changed in smooth streaming mode */ + if (pThis->m_smoothstreaming_mode && + (pThis->framesize.nWidth != + pThis->drv_ctx.video_resolution.frame_width) || + (pThis->framesize.nHeight != + pThis->drv_ctx.video_resolution.frame_height)) { + + DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d", + pThis->framesize.nWidth, + pThis->framesize.nHeight, + pThis->drv_ctx.video_resolution.frame_width, + pThis->drv_ctx.video_resolution.frame_height); + + /* Update new resolution */ + pThis->framesize.nWidth = + pThis->drv_ctx.video_resolution.frame_width; + pThis->framesize.nHeight = + pThis->drv_ctx.video_resolution.frame_height; + + /* Update C2D with new resolution */ + if (!pThis->client_buffers.update_buffer_req()) { + DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed"); + } + } + + /* Update new crop information */ + pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left; + pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top; + pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right; + pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom; + + /* Validate the new crop information */ + if (pThis->rectangle.nLeft + pThis->rectangle.nWidth > + pThis->drv_ctx.video_resolution.frame_width) { + + DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]", + pThis->rectangle.nLeft, pThis->rectangle.nWidth, + pThis->drv_ctx.video_resolution.frame_width); + pThis->rectangle.nLeft = 0; + + if (pThis->rectangle.nWidth > + pThis->drv_ctx.video_resolution.frame_width) { + + DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]", + pThis->rectangle.nWidth, + pThis->drv_ctx.video_resolution.frame_width); + pThis->rectangle.nWidth = + pThis->drv_ctx.video_resolution.frame_width; + } + } + if (pThis->rectangle.nTop + pThis->rectangle.nHeight > + pThis->drv_ctx.video_resolution.frame_height) { + + DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]", + pThis->rectangle.nTop, pThis->rectangle.nHeight, + pThis->drv_ctx.video_resolution.frame_height); + pThis->rectangle.nTop = 0; + + if (pThis->rectangle.nHeight > + pThis->drv_ctx.video_resolution.frame_height) { + + DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]", + pThis->rectangle.nHeight, + pThis->drv_ctx.video_resolution.frame_height); + pThis->rectangle.nHeight = + pThis->drv_ctx.video_resolution.frame_height; + } + } + DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u", + pThis->rectangle.nLeft, pThis->rectangle.nTop, + pThis->rectangle.nWidth, pThis->rectangle.nHeight); + } else { + DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2); + break; } if (pThis->m_cb.EventHandler) { pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, @@ -1254,6 +1356,11 @@ void omx_vdec::process_event_cb(void *ctxt, unsigned char id) pThis->omx_report_unsupported_setting(); break; + case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD: + DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD"); + pThis->omx_report_hw_overload(); + break; + default: break; } @@ -1281,10 +1388,12 @@ int omx_vdec::update_resolution(int width, int height, int stride, int scan_line drv_ctx.video_resolution.frame_width = width; drv_ctx.video_resolution.scan_lines = scan_lines; drv_ctx.video_resolution.stride = stride; + if(!is_down_scalar_enabled) { rectangle.nLeft = 0; rectangle.nTop = 0; rectangle.nWidth = drv_ctx.video_resolution.frame_width; rectangle.nHeight = drv_ctx.video_resolution.frame_height; + } return format_changed; } @@ -1338,6 +1447,10 @@ int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len) sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.264", m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { + sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.265", + m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); + } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) { sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.vc1", m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); @@ -1350,6 +1463,10 @@ int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len) sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.ivf", m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); } + else { + sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.divx", + m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); + } m_debug.infile = fopen (m_debug.infile_name, "ab"); if (!m_debug.infile) { DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name); @@ -1402,7 +1519,7 @@ int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len) } int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) { - if (m_debug.out_buffer_log && !m_debug.outfile) { + if (m_debug.out_buffer_log && !m_debug.outfile && buffer->nFilledLen) { sprintf(m_debug.outfile_name, "%s/output_%d_%d_%p.yuv", m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); m_debug.outfile = fopen (m_debug.outfile_name, "ab"); @@ -1473,7 +1590,7 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) int fds[2]; int r,ret=0; bool codec_ambiguous = false; - OMX_STRING device_name = (OMX_STRING)"/dev/video/venus_dec"; + OMX_STRING device_name = (OMX_STRING)"/dev/video32"; char property_value[PROPERTY_VALUE_MAX] = {0}; #ifdef _ANDROID_ @@ -1493,10 +1610,15 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode */ arbitrary_bytes = false; + property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0"); + if (atoi(property_value)) { + DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command"); + arbitrary_bytes = true; + } #endif - if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",OMX_MAX_STRINGNAME_SIZE)) { - struct v4l2_control control; + if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure", + OMX_MAX_STRINGNAME_SIZE)) { secure_mode = true; arbitrary_bytes = false; role = (OMX_STRING)"OMX.qcom.video.decoder.avc"; @@ -1505,6 +1627,26 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) secure_mode = true; arbitrary_bytes = false; role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2"; + } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure", + OMX_MAX_STRINGNAME_SIZE)) { + secure_mode = true; + arbitrary_bytes = false; + role = (OMX_STRING)"OMX.qcom.video.decoder.hevc"; + } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure", + OMX_MAX_STRINGNAME_SIZE)) { + secure_mode = true; + arbitrary_bytes = false; + role = (OMX_STRING)"OMX.qcom.video.decoder.vc1"; + } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure", + OMX_MAX_STRINGNAME_SIZE)) { + secure_mode = true; + arbitrary_bytes = false; + role = (OMX_STRING)"OMX.qcom.video.decoder.wmv"; + } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure", + OMX_MAX_STRINGNAME_SIZE)) { + secure_mode = true; + arbitrary_bytes = false; + role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4"; } drv_ctx.video_driver_fd = open(device_name, O_RDWR); @@ -1643,7 +1785,7 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE); drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC; output_capability = V4L2_PIX_FMT_HEVC; - eCompressionFormat = OMX_VIDEO_CodingHEVC; + eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc; codec_type_parse = CODEC_TYPE_HEVC; m_frame_parser.init_start_codes(codec_type_parse); m_frame_parser.init_nal_length(nal_length); @@ -1779,6 +1921,7 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) m_decoder_capability.max_height = frmsize.stepwise.max_height; } + memset(&fmt, 0x0, sizeof(struct v4l2_format)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; @@ -1788,6 +1931,14 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) /*TODO: How to handle this case */ DEBUG_PRINT_ERROR("Failed to set format on capture port"); } + memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE)); + framesize.nWidth = drv_ctx.video_resolution.frame_width; + framesize.nHeight = drv_ctx.video_resolution.frame_height; + + memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE)); + rectangle.nWidth = drv_ctx.video_resolution.frame_width; + rectangle.nHeight = drv_ctx.video_resolution.frame_height; + DEBUG_PRINT_HIGH("Set Format was successful"); if (secure_mode) { control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE; @@ -1827,6 +1978,16 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); drv_ctx.idr_only_decoding = 0; + property_get("vidc.debug.turbo", property_value, "0"); + if (atoi(property_value)) { + DEBUG_PRINT_HIGH("Turbo mode debug property enabled"); + control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; + control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set turbo mode"); + } + } + m_state = OMX_StateLoaded; #ifdef DEFAULT_EXTRADATA if (strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", @@ -1835,7 +1996,7 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) enable_extradata(DEFAULT_EXTRADATA, true, true); #endif eRet=get_buffer_req(&drv_ctx.ip_buf); - DEBUG_PRINT_HIGH("Input Buffer Size =%d",drv_ctx.ip_buf.buffer_size); + DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size); get_buffer_req(&drv_ctx.op_buf); if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 || drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC || @@ -1905,6 +2066,13 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) drv_ctx.video_driver_fd); } //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer)); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY; + control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE; + + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set Default Priority"); + eRet = OMX_ErrorUnsupportedSetting; + } return eRet; } @@ -1977,18 +2145,6 @@ OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush " "to invalid port: %u", (unsigned int)param1); return OMX_ErrorBadPortIndex; - } else if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX || - param1 == OMX_ALL)) { - while (android_atomic_add(0, &m_queued_codec_config_count) > 0) { - struct timespec ts; - - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += 2; - if (sem_timedwait(&m_safe_flush, &ts)) { - DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers"); - break; - } - } } post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); @@ -2325,6 +2481,23 @@ OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, #ifdef _MSM8974_ send_codec_config(); #endif + if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX || + param1 == OMX_ALL)) { + if (android_atomic_add(0, &m_queued_codec_config_count) > 0) { + struct timespec ts; + + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 2; + DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ", + m_queued_codec_config_count); + BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED); + if (sem_timedwait(&m_safe_flush, &ts)) { + DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers"); + } + BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED); + } + } + if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) { BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); } @@ -2646,11 +2819,26 @@ bool omx_vdec::post_event(unsigned long p1, { bool bRet = false; + /* Just drop messages typically generated by hardware (w/o client request), + * if we've reported an error to client. */ + if (m_error_propogated) { + switch (id) { + case OMX_COMPONENT_GENERATE_PORT_RECONFIG: + case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: + DEBUG_PRINT_ERROR("Dropping message %lx " + "since client expected to be in error state", id); + return false; + default: + /* whatever */ + break; + } + } pthread_mutex_lock(&m_lock); if (id == m_fill_output_msg || - id == OMX_COMPONENT_GENERATE_FBD) { + id == OMX_COMPONENT_GENERATE_FBD || + id == OMX_COMPONENT_GENERATE_PORT_RECONFIG) { m_ftb_q.insert_entry(p1,p2,id); } else if (id == OMX_COMPONENT_GENERATE_ETB || id == OMX_COMPONENT_GENERATE_EBD || @@ -2702,9 +2890,14 @@ OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PR eRet = OMX_ErrorNoMore; } } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { + if (profileLevelType->nProfileIndex == 0) { + profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; + } else { DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", (unsigned int)profileLevelType->nProfileIndex); eRet = OMX_ErrorNoMore; + } } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) { if (profileLevelType->nProfileIndex == 0) { profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; @@ -2784,6 +2977,7 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } switch ((unsigned long)paramIndex) { case OMX_IndexParamPortDefinition: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE); OMX_PARAM_PORTDEFINITIONTYPE *portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition"); @@ -2793,23 +2987,25 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, break; } case OMX_IndexParamVideoInit: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); OMX_PORT_PARAM_TYPE *portParamType = (OMX_PORT_PARAM_TYPE *) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit"); portParamType->nVersion.nVersion = OMX_SPEC_VERSION; - portParamType->nSize = sizeof(portParamType); + portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); portParamType->nPorts = 2; portParamType->nStartPortNumber = 0; break; } case OMX_IndexParamVideoPortFormat: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE); OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat"); portFmt->nVersion.nVersion = OMX_SPEC_VERSION; - portFmt->nSize = sizeof(portFmt); + portFmt->nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); if (0 == portFmt->nPortIndex) { if (0 == portFmt->nIndex) { @@ -2822,7 +3018,19 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } } else if (1 == portFmt->nPortIndex) { portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused; - portFmt->eColorFormat = getColorFormatAt(portFmt->nIndex); + + // Distinguish non-surface mode from normal playback use-case based on + // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2" + // For non-android, use the default list + // Also use default format-list if FLEXIBLE YUV is supported, + // as the client negotiates the standard color-format if it needs to + bool useNonSurfaceMode = false; +#if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED) + useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE); +#endif + portFmt->eColorFormat = useNonSurfaceMode ? + getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) : + getPreferredColorFormatDefaultMode(portFmt->nIndex); if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) { eRet = OMX_ErrorNoMore; @@ -2839,22 +3047,24 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } /*Component should support this port definition*/ case OMX_IndexParamAudioInit: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit"); audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; - audioPortParamType->nSize = sizeof(audioPortParamType); + audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); audioPortParamType->nPorts = 0; audioPortParamType->nStartPortNumber = 0; break; } /*Component should support this port definition*/ case OMX_IndexParamImageInit: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit"); imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION; - imagePortParamType->nSize = sizeof(imagePortParamType); + imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE); imagePortParamType->nPorts = 0; imagePortParamType->nStartPortNumber = 0; break; @@ -2868,6 +3078,7 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, break; } case OMX_IndexParamStandardComponentRole: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE); OMX_PARAM_COMPONENTROLETYPE *comp_role; comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; comp_role->nVersion.nVersion = OMX_SPEC_VERSION; @@ -2881,22 +3092,23 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } /* Added for parameter test */ case OMX_IndexParamPriorityMgmt: { - + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE); OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt"); priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION; - priorityMgmType->nSize = sizeof(priorityMgmType); + priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE); break; } /* Added for parameter test */ case OMX_IndexParamCompBufferSupplier: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE); OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier"); - bufferSupplierType->nSize = sizeof(bufferSupplierType); + bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE); bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; if (0 == bufferSupplierType->nPortIndex) bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; @@ -2934,6 +3146,7 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, break; } case OMX_IndexParamVideoProfileLevelQuerySupported: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex); OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; @@ -2942,11 +3155,12 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: { + VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams); DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage"); GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData; if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { - if (secure_mode) { + if (secure_mode && !secure_scaling_to_non_secure_opb) { nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_PRIVATE_UNCACHED); } else { @@ -2961,11 +3175,16 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } break; #endif + +#ifdef FLEXYUV_SUPPORTED case OMX_QcomIndexFlexibleYUVDescription: { DEBUG_PRINT_LOW("get_parameter: describeColorFormat"); - eRet = describeColorFormat((DescribeColorFormatParams *)paramData); + VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams); + eRet = describeColorFormat(paramData); break; } +#endif + default: { DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex); eRet =OMX_ErrorUnsupportedIndex; @@ -3050,6 +3269,9 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, OMX_ERRORTYPE eRet = OMX_ErrorNone; int ret=0; struct v4l2_format fmt; +#ifdef _ANDROID_ + char property_value[PROPERTY_VALUE_MAX] = {0}; +#endif if (m_state == OMX_StateInvalid) { DEBUG_PRINT_ERROR("Set Param in Invalid State"); return OMX_ErrorInvalidState; @@ -3068,6 +3290,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } switch ((unsigned long)paramIndex) { case OMX_IndexParamPortDefinition: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE); OMX_PARAM_PORTDEFINITIONTYPE *portDefn; portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has @@ -3075,8 +3298,15 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d", (int)portDefn->format.video.nFrameHeight, (int)portDefn->format.video.nFrameWidth); + if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { + DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d", + portDefn->nBufferCountActual); + eRet = OMX_ErrorBadParameter; + break; + } if (OMX_DirOutput == portDefn->eDir) { DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port"); + bool port_format_changed = false; m_display_id = portDefn->format.video.pNativeWindow; unsigned int buffer_size; /* update output port resolution with client supplied dimensions @@ -3088,13 +3318,34 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, (unsigned int)portDefn->format.video.nFrameHeight); if (portDefn->format.video.nFrameHeight != 0x0 && portDefn->format.video.nFrameWidth != 0x0) { + 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"); + eRet = OMX_ErrorHardware; + break; + } + if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) || + (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) { + port_format_changed = true; + } update_resolution(portDefn->format.video.nFrameWidth, portDefn->format.video.nFrameHeight, portDefn->format.video.nFrameWidth, portDefn->format.video.nFrameHeight); + + /* set crop info */ + rectangle.nLeft = 0; + rectangle.nTop = 0; + rectangle.nWidth = portDefn->format.video.nFrameWidth; + rectangle.nHeight = portDefn->format.video.nFrameHeight; + eRet = is_video_session_supported(); if (eRet) break; + memset(&fmt, 0x0, sizeof(struct v4l2_format)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; @@ -3108,11 +3359,71 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } else eRet = get_buffer_req(&drv_ctx.op_buf); } + + if (eRet) { + break; + } + + if (secure_mode) { + struct v4l2_control control; + control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD; + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) { + DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id); + eRet = OMX_ErrorHardware; + } else { + /* This is a workaround for a bug in fw which uses stride + * and slice instead of width and height to check against + * the threshold. + */ + OMX_U32 stride, slice; + if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { + stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth); + slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight); + } else { + stride = portDefn->format.video.nFrameWidth; + slice = portDefn->format.video.nFrameHeight; + } + + DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice); + DEBUG_PRINT_LOW("Threshold value is %d\n", control.value); + + if (stride * slice <= (OMX_U32)control.value) { + secure_scaling_to_non_secure_opb = true; + DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ"); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2; + control.value = 1; + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) { + DEBUG_PRINT_ERROR("Enabling non-secure output2 failed"); + eRet = OMX_ErrorUnsupportedSetting; + } + } + } + } + } + + if (eRet) { + break; } - if (!client_buffers.get_buffer_req(buffer_size)) { + + if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { + DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)", + portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS); + eRet = OMX_ErrorBadParameter; + } else if (!client_buffers.get_buffer_req(buffer_size)) { DEBUG_PRINT_ERROR("Error in getting buffer requirements"); eRet = OMX_ErrorBadParameter; - } else { + } else if (!port_format_changed) { + + // Buffer count can change only when port is unallocated + if (m_out_mem_ptr && + (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount || + portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) { + + DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !"); + eRet = OMX_ErrorInvalidState; + break; + } + if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount && portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size ) { drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual; @@ -3125,7 +3436,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, m_port_def = *portDefn; } else { DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)", - drv_ctx.op_buf.mincount, drv_ctx.op_buf.buffer_size, + drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize); eRet = OMX_ErrorBadParameter; } @@ -3170,7 +3481,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, eRet = OMX_ErrorHardware; break; } - m_perf_control.request_cores(frm_int); + //m_perf_control.request_cores(frm_int); } if (drv_ctx.video_resolution.frame_height != @@ -3198,6 +3509,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, eRet = is_video_session_supported(); if (eRet) break; + memset(&fmt, 0x0, sizeof(struct v4l2_format)); fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; @@ -3207,10 +3519,34 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, if (ret) { DEBUG_PRINT_ERROR("Set Resolution failed"); eRet = OMX_ErrorUnsupportedSetting; - } else + } else { + if (!is_down_scalar_enabled) eRet = get_buffer_req(&drv_ctx.op_buf); } } + } + if (m_custom_buffersize.input_buffersize + && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) { + DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d", + m_custom_buffersize.input_buffersize, portDefn->nBufferSize); + eRet = OMX_ErrorBadParameter; + break; + } + if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { + DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)", + portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS); + eRet = OMX_ErrorBadParameter; + break; + } + // Buffer count can change only when port is unallocated + if (m_inp_mem_ptr && + (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount || + portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) { + DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !"); + eRet = OMX_ErrorInvalidState; + break; + } + if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) { port_format_changed = true; @@ -3222,7 +3558,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } if (false == port_format_changed) { DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)", - drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size, + drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size, (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize); eRet = OMX_ErrorBadParameter; } @@ -3234,6 +3570,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } break; case OMX_IndexParamVideoPortFormat: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE); OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; int ret=0; @@ -3241,6 +3578,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u", portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex); + memset(&fmt, 0x0, sizeof(struct v4l2_format)); if (1 == portFmt->nPortIndex) { fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; @@ -3279,6 +3617,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, break; case OMX_QcomIndexPortDefn: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE); OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt = (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData; DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u", @@ -3286,6 +3625,14 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, /* Input port */ if (portFmt->nPortIndex == 0) { + // arbitrary_bytes mode cannot be changed arbitrarily since this controls how: + // - headers are allocated and + // - headers-indices are derived + // Avoid changing arbitrary_bytes when the port is already allocated + if (m_inp_mem_ptr) { + DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!"); + return OMX_ErrorUnsupportedSetting; + } if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) { if (secure_mode) { arbitrary_bytes = false; @@ -3297,6 +3644,13 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } else if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_OnlyOneCompleteFrame) { arbitrary_bytes = false; +#ifdef _ANDROID_ + property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0"); + if (atoi(property_value)) { + DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command"); + arbitrary_bytes = true; + } +#endif } else { DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u", (unsigned int)portFmt->nFramePackingFormat); @@ -3318,6 +3672,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, break; case OMX_IndexParamStandardComponentRole: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE); OMX_PARAM_COMPONENTROLETYPE *comp_role; comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s", @@ -3408,6 +3763,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamPriorityMgmt: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE); if (m_state != OMX_StateLoaded) { DEBUG_PRINT_ERROR("Set Parameter called in Invalid State"); return OMX_ErrorIncorrectStateOperation; @@ -3426,6 +3782,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamCompBufferSupplier: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE); OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d", bufferSupplierType->eBufferSupplier); @@ -3465,6 +3822,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, break; } case OMX_QcomIndexParamVideoDecoderPictureOrder: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER); QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder = (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData; struct v4l2_control control; @@ -3490,46 +3848,61 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, break; } case OMX_QcomIndexParamConcealMBMapExtraData: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false, ((QOMX_ENABLETYPE *)paramData)->bEnable); break; case OMX_QcomIndexParamFrameInfoExtraData: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false, ((QOMX_ENABLETYPE *)paramData)->bEnable); break; case OMX_ExtraDataFrameDimension: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false, ((QOMX_ENABLETYPE *)paramData)->bEnable); break; case OMX_QcomIndexParamInterlaceExtraData: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false, ((QOMX_ENABLETYPE *)paramData)->bEnable); break; case OMX_QcomIndexParamH264TimeInfo: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false, ((QOMX_ENABLETYPE *)paramData)->bEnable); break; case OMX_QcomIndexParamVideoFramePackingExtradata: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false, ((QOMX_ENABLETYPE *)paramData)->bEnable); break; case OMX_QcomIndexParamVideoQPExtraData: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); eRet = enable_extradata(OMX_QP_EXTRADATA, false, ((QOMX_ENABLETYPE *)paramData)->bEnable); break; case OMX_QcomIndexParamVideoInputBitsInfoExtraData: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false, ((QOMX_ENABLETYPE *)paramData)->bEnable); break; case OMX_QcomIndexEnableExtnUserData: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false, ((QOMX_ENABLETYPE *)paramData)->bEnable); break; + case OMX_QcomIndexParamMpeg2SeqDispExtraData: + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE); + eRet = enable_extradata(OMX_MPEG2SEQDISP_EXTRADATA, false, + ((QOMX_ENABLETYPE *)paramData)->bEnable); + break; case OMX_QcomIndexParamVideoDivx: { QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData; } break; case OMX_QcomIndexPlatformPvt: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN); DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port"); OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData; if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { @@ -3580,6 +3953,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, break; case OMX_QcomIndexParamIndexExtraDataType: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE); QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData; if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) && (extradataIndexType->bEnabled == OMX_TRUE) && @@ -3603,18 +3977,39 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, * state. This is ANDROID architecture which is not in sync * with openmax standard. */ case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: { + VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams); EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData; + if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) { + DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!"); + eRet = OMX_ErrorUnsupportedSetting; + break; + } else if (m_out_mem_ptr) { + DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !"); + eRet = OMX_ErrorInvalidState; + break; + } if (enableNativeBuffers) { m_enable_android_native_buffers = enableNativeBuffers->enable; } +#if !defined(FLEXYUV_SUPPORTED) + if (m_enable_android_native_buffers) { + // Use the most-preferred-native-color-format as surface-mode is hinted here + if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) { + DEBUG_PRINT_ERROR("Failed to set native color format!"); + eRet = OMX_ErrorUnsupportedSetting; + } + } +#endif } break; case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: { + VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams); eRet = use_android_native_buffer(hComp, paramData); } break; #endif case OMX_QcomIndexParamEnableTimeStampReorder: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER); QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData; if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) { if (reorder->bEnable == OMX_TRUE) { @@ -3631,6 +4026,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } break; case OMX_IndexParamVideoProfileLevelCurrent: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; if (pParam) { @@ -3642,6 +4038,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamVideoMetaBufferMode: { + VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams); StoreMetaDataInBuffersParams *metabuffer = (StoreMetaDataInBuffersParams *)paramData; if (!metabuffer) { @@ -3655,6 +4052,11 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, break; } if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { + if (m_out_mem_ptr) { + DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !"); + eRet = OMX_ErrorInvalidState; + break; + } //set property dynamic buffer mode to driver. struct v4l2_control control; struct v4l2_format fmt; @@ -3684,6 +4086,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamVideoDownScalar: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR); QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData; struct v4l2_control control; int rc; @@ -3712,6 +4115,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, #ifdef ADAPTIVE_PLAYBACK_SUPPORTED case OMX_QcomIndexParamVideoAdaptivePlaybackMode: { + VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams); DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback"); PrepareForAdaptivePlaybackParams* pParams = (PrepareForAdaptivePlaybackParams *) paramData; @@ -3727,36 +4131,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight); eRet = OMX_ErrorBadParameter; } else { - eRet = enable_smoothstreaming(); - if (eRet != OMX_ErrorNone) { - DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver."); - eRet = OMX_ErrorHardware; - } else { - DEBUG_PRINT_HIGH("Enabling Adaptive playback for %u x %u", - (unsigned int)pParams->nMaxFrameWidth, - (unsigned int)pParams->nMaxFrameHeight); - m_smoothstreaming_mode = true; - m_smoothstreaming_width = pParams->nMaxFrameWidth; - m_smoothstreaming_height = pParams->nMaxFrameHeight; - } - struct v4l2_format fmt; - update_resolution(m_smoothstreaming_width, m_smoothstreaming_height, - m_smoothstreaming_width, m_smoothstreaming_height); - eRet = is_video_session_supported(); - if (eRet) - break; - fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; - fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; - fmt.fmt.pix_mp.pixelformat = output_capability; - DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d", - fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width); - ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); - if (ret) { - DEBUG_PRINT_ERROR("Set Resolution failed"); - eRet = OMX_ErrorUnsupportedSetting; - } else - eRet = get_buffer_req(&drv_ctx.op_buf); + eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight); } } else { DEBUG_PRINT_ERROR( @@ -3767,6 +4142,34 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } #endif + case OMX_QcomIndexParamVideoCustomBufferSize: + { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE); + DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize"); + QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData; + if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) { + struct v4l2_control control; + control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT; + control.value = pParam->nBufferSize; + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set input buffer size"); + eRet = OMX_ErrorUnsupportedSetting; + } else { + eRet = get_buffer_req(&drv_ctx.ip_buf); + if (eRet == OMX_ErrorNone) { + m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size; + DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d", + m_custom_buffersize.input_buffersize); + } else { + DEBUG_PRINT_ERROR("Failed to get buffer requirement"); + } + } + } else { + DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port"); + eRet = OMX_ErrorBadParameter; + } + break; + } default: { DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex); eRet = OMX_ErrorUnsupportedIndex; @@ -3805,6 +4208,7 @@ OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, switch ((unsigned long)configIndex) { case OMX_QcomIndexConfigInterlaced: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE); OMX_QCOM_CONFIG_INTERLACETYPE *configFmt = (OMX_QCOM_CONFIG_INTERLACETYPE *) configData; if (configFmt->nPortIndex == 1) { @@ -3830,6 +4234,7 @@ OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, break; } case OMX_QcomIndexQueryNumberOfVideoDecInstance: { + VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES); QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances = (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData; decoderinstances->nNumOfInstances = 16; @@ -3838,6 +4243,7 @@ OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexConfigVideoFramePackingArrangement: { if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) { + VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT); OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData; memcpy(configFmt, &m_frame_pack_arrangement, @@ -3848,10 +4254,42 @@ OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, break; } case OMX_IndexConfigCommonOutputCrop: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE); OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData; memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE)); + DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u", + rectangle.nLeft, rectangle.nTop, + rectangle.nWidth, rectangle.nHeight); break; } + case OMX_QcomIndexConfigPerfLevel: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL); + struct v4l2_control control; + OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf = + (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData; + + control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) { + DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno); + eRet = OMX_ErrorHardware; + } + + if (eRet == OMX_ErrorNone) { + switch (control.value) { + case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO: + perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo; + break; + default: + DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value); + /* Fall through */ + case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL: + perf->ePerfLevel = OMX_QCOM_PerfLevelNominal; + break; + } + } + + break; + } default: { DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex); eRet = OMX_ErrorBadParameter; @@ -3890,113 +4328,11 @@ 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; + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE); pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData); switch (pNal->nNaluBytes) { case 0: @@ -4082,6 +4418,66 @@ OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp, } return ret; + } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) { + OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf = + (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData; + struct v4l2_control control; + + DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel); + + control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; + + switch (perf->ePerfLevel) { + case OMX_QCOM_PerfLevelNominal: + control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL; + break; + case OMX_QCOM_PerfLevelTurbo: + control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; + break; + default: + ret = OMX_ErrorUnsupportedSetting; + break; + } + + if (ret == OMX_ErrorNone) { + ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ? + OMX_ErrorUnsupportedSetting : OMX_ErrorNone; + } + + return ret; + } else if ((int)configIndex == (int)OMX_IndexConfigPriority) { + OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData; + DEBUG_PRINT_LOW("Set_config: priority %d", priority->nU32); + + struct v4l2_control control; + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY; + if (priority->nU32 == 0) + control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE; + else + control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE; + + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set Priority"); + ret = OMX_ErrorUnsupportedSetting; + } + return ret; + } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) { + OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData; + DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16); + + struct v4l2_control control; + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE; + control.value = rate->nU32; + + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { + ret = errno == -EBUSY ? OMX_ErrorInsufficientResources : + OMX_ErrorUnsupportedSetting; + DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)", + rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno)); + } + return ret; } return OMX_ErrorNotImplemented; @@ -4125,6 +4521,8 @@ OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData; } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) { *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData; + } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_MPEG2SEQDISP_EXTRADATA)) { + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamMpeg2SeqDispExtraData; } #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) { @@ -4141,14 +4539,16 @@ OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) { *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode; } -#if ADAPTIVE_PLAYBACK_SUPPORTED +#ifdef ADAPTIVE_PLAYBACK_SUPPORTED else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) { *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode; } #endif +#ifdef FLEXYUV_SUPPORTED else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) { *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription; } +#endif else { DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName); return OMX_ErrorNotImplemented; @@ -4318,6 +4718,9 @@ OMX_ERRORTYPE omx_vdec::use_output_buffer( eRet = OMX_ErrorInsufficientResources; } + if (eRet != OMX_ErrorNone) + return eRet; + if (dynamic_buf_mode) { *bufferHdr = (m_out_mem_ptr + i ); (*bufferHdr)->pBuffer = NULL; @@ -4352,13 +4755,24 @@ OMX_ERRORTYPE omx_vdec::use_output_buffer( handle = (private_handle_t *)buff; privateAppData = appData; } + if (!handle) { + DEBUG_PRINT_ERROR("handle is invalid"); + return OMX_ErrorBadParameter; + } if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) { + if (secure_mode && secure_scaling_to_non_secure_opb) { + DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it", + (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size); + } else { DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback," " expected %u, got %u", - drv_ctx.op_buf.buffer_size, (unsigned int)handle->size); + (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size); return OMX_ErrorBadParameter; } + } + + drv_ctx.op_buf.buffer_size = handle->size; if (!m_use_android_native_buffers) { if (!secure_mode) { @@ -4454,7 +4868,7 @@ OMX_ERRORTYPE omx_vdec::use_output_buffer( OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list; OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info; pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData; - if (!pmem_list->entryList || !pmem_list->entryList->entry || + if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry || !pmem_list->nEntries || pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { DEBUG_PRINT_ERROR("Pmem info not valid in use buffer"); @@ -4633,19 +5047,24 @@ OMX_ERRORTYPE omx_vdec::use_buffer( OMX_ERRORTYPE error = OMX_ErrorNone; struct vdec_setbuffer_cmd setbuffers; - if (bufferHdr == NULL || bytes == 0) { - if (!secure_mode && buffer == NULL) { + if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) { DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer); return OMX_ErrorBadParameter; } - } if (m_state == OMX_StateInvalid) { DEBUG_PRINT_ERROR("Use Buffer in Invalid State"); return OMX_ErrorInvalidState; } - if (port == OMX_CORE_INPUT_PORT_INDEX) + if (port == OMX_CORE_INPUT_PORT_INDEX) { + // If this is not the first allocation (i.e m_inp_mem_ptr is allocated), + // ensure that use-buffer was called for previous allocation. + // Mix-and-match of useBuffer and allocateBuffer is not allowed + if (m_inp_mem_ptr && !input_use_buffer) { + DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !"); + return OMX_ErrorUndefined; + } error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer); - else if (port == OMX_CORE_OUTPUT_PORT_INDEX) + } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested else { DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); @@ -4699,6 +5118,9 @@ OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) index = bufferHdr - m_inp_mem_ptr; DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); + auto_lock l(buf_lock); + bufferHdr->pInputPortPrivate = NULL; + if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) { DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0) { @@ -4709,8 +5131,8 @@ OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) if (!secure_mode) { DEBUG_PRINT_LOW("unmap the input buffer fd=%d", drv_ctx.ptr_inputbuffer[index].pmem_fd); - DEBUG_PRINT_LOW("unmap the input buffer size=%d address = %p", - drv_ctx.ptr_inputbuffer[index].mmaped_size, + DEBUG_PRINT_LOW("unmap the input buffer size=%u address = %p", + (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size, drv_ctx.ptr_inputbuffer[index].bufferaddr); munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr, drv_ctx.ptr_inputbuffer[index].mmaped_size); @@ -4768,8 +5190,8 @@ OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) if (!secure_mode) { DEBUG_PRINT_LOW("unmap the output buffer fd = %d", drv_ctx.ptr_outputbuffer[0].pmem_fd); - DEBUG_PRINT_LOW("unmap the ouput buffer size=%d address = %p", - drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount, + DEBUG_PRINT_LOW("unmap the ouput buffer size=%u address = %p", + (unsigned int)drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount, drv_ctx.ptr_outputbuffer[0].bufferaddr); munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr, drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount); @@ -4817,8 +5239,8 @@ OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp, calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), drv_ctx.ip_buf.actualcount); - if (m_inp_heap_ptr == NULL) { - DEBUG_PRINT_ERROR("m_inp_heap_ptr Allocation failed "); + if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) { + DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed "); return OMX_ErrorInsufficientResources; } } @@ -4899,15 +5321,15 @@ OMX_ERRORTYPE omx_vdec::allocate_input_buffer( if (bytes != drv_ctx.ip_buf.buffer_size) { - DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %d", - (unsigned int)bytes, drv_ctx.ip_buf.buffer_size); + DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u", + (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size); return OMX_ErrorBadParameter; } if (!m_inp_mem_ptr) { - DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%d)", + DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)", drv_ctx.ip_buf.actualcount, - drv_ctx.ip_buf.buffer_size); + (unsigned int)drv_ctx.ip_buf.buffer_size); m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount); @@ -4955,7 +5377,13 @@ OMX_ERRORTYPE omx_vdec::allocate_input_buffer( drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment, &drv_ctx.ip_buf_ion_info[i].ion_alloc_data, - &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE : 0); + &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE +#ifndef DISABLE_INPUT_BUFFER_CACHE + : ION_FLAG_CACHED +#else + : 0 +#endif + ); if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) { return OMX_ErrorInsufficientResources; } @@ -5091,9 +5519,9 @@ OMX_ERRORTYPE omx_vdec::allocate_output_buffer( struct ion_fd_data fd_ion_data; #endif if (!m_out_mem_ptr) { - DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%d)", + DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)", drv_ctx.op_buf.actualcount, - drv_ctx.op_buf.buffer_size); + (unsigned int)drv_ctx.op_buf.buffer_size); int nBufHdrSize = 0; int nPlatformEntrySize = 0; int nPlatformListSize = 0; @@ -5117,17 +5545,23 @@ OMX_ERRORTYPE omx_vdec::allocate_output_buffer( nPlatformEntrySize = drv_ctx.op_buf.actualcount * sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); - DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize, - sizeof(OMX_BUFFERHEADERTYPE), + DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize, + (unsigned int)sizeof(OMX_BUFFERHEADERTYPE), nPMEMInfoSize, nPlatformListSize); DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize, drv_ctx.op_buf.actualcount); #ifdef USE_ION + // Allocate output buffers as cached to improve performance of software-reading + // of the YUVs. Output buffers are cache-invalidated in driver. + // If color-conversion is involved, Only the C2D output buffers are cached, no + // need to cache the decoder's output buffers + int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED; ion_device_fd = alloc_map_ion_memory( drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount, - drv_ctx.op_buf.alignment, - &ion_alloc_data, &fd_ion_data, secure_mode ? ION_SECURE : 0); + secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment, + &ion_alloc_data, &fd_ion_data, + (secure_mode && !secure_scaling_to_non_secure_opb) ? ION_SECURE : cache_flag); if (ion_device_fd < 0) { return OMX_ErrorInsufficientResources; } @@ -5165,8 +5599,8 @@ OMX_ERRORTYPE omx_vdec::allocate_output_buffer( drv_ctx.op_buf.actualcount), PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0); if (pmem_baseaddress == MAP_FAILED) { - DEBUG_PRINT_ERROR("MMAP failed for Size %d", - drv_ctx.op_buf.buffer_size); + DEBUG_PRINT_ERROR("MMAP failed for Size %u", + (unsigned int)drv_ctx.op_buf.buffer_size); close(pmem_fd); #ifdef USE_ION free_ion_memory(&drv_ctx.op_buf_ion_info[i]); @@ -5185,10 +5619,19 @@ OMX_ERRORTYPE omx_vdec::allocate_output_buffer( drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ calloc (sizeof (struct vdec_output_frameinfo), drv_ctx.op_buf.actualcount); + if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) { + DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer "); + return OMX_ErrorInsufficientResources; + } + #ifdef USE_ION drv_ctx.op_buf_ion_info = (struct vdec_ion *)\ calloc (sizeof(struct vdec_ion), drv_ctx.op_buf.actualcount); + if (!drv_ctx.op_buf_ion_info) { + DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info"); + return OMX_ErrorInsufficientResources; + } #endif if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer @@ -5254,8 +5697,8 @@ OMX_ERRORTYPE omx_vdec::allocate_output_buffer( m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size; m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr; - DEBUG_PRINT_LOW("pmem_fd = %d offset = %d address = %p", - pmem_fd, drv_ctx.ptr_outputbuffer[i].offset, + DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p", + pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset, drv_ctx.ptr_outputbuffer[i].bufferaddr); // Move the buffer and buffer header pointers bufHdr++; @@ -5314,7 +5757,12 @@ OMX_ERRORTYPE omx_vdec::allocate_output_buffer( *bufferHdr = (m_out_mem_ptr + i ); if (secure_mode) { +#ifdef USE_ION + drv_ctx.ptr_outputbuffer[i].bufferaddr = + (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; +#else drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; +#endif } drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size; @@ -5407,6 +5855,13 @@ OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hC } if (port == OMX_CORE_INPUT_PORT_INDEX) { + // If this is not the first allocation (i.e m_inp_mem_ptr is allocated), + // ensure that use-buffer was never called. + // Mix-and-match of useBuffer and allocateBuffer is not allowed + if (m_inp_mem_ptr && input_use_buffer) { + DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !"); + return OMX_ErrorUndefined; + } if (arbitrary_bytes) { eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes); } else { @@ -5506,7 +5961,8 @@ OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, nPortIndex = buffer - m_inp_heap_ptr; DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex); - if (nPortIndex < drv_ctx.ip_buf.actualcount) { + if (nPortIndex < drv_ctx.ip_buf.actualcount && + BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) { // Clear the bit associated with it. BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex); @@ -5548,7 +6004,8 @@ OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { // check if the buffer is valid nPortIndex = buffer - client_buffers.get_il_buf_hdr(); - if (nPortIndex < drv_ctx.op_buf.actualcount) { + if (nPortIndex < drv_ctx.op_buf.actualcount && + BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) { DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex); // Clear the bit associated with it. BITMASK_CLEAR(&m_out_bm_count,nPortIndex); @@ -5619,7 +6076,9 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_ERRORTYPE ret1 = OMX_ErrorNone; unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount; - if (m_state == OMX_StateInvalid) { + if (m_state != OMX_StateExecuting && + m_state != OMX_StatePause && + m_state != OMX_StateIdle) { DEBUG_PRINT_ERROR("Empty this buffer in Invalid State"); return OMX_ErrorInvalidState; } @@ -5661,6 +6120,10 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, } else { if (input_use_buffer == true) { nBufferIndex = buffer - m_inp_heap_ptr; + if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) { + DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode"); + return OMX_ErrorBadParameter; + } m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen; m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp; m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags; @@ -5672,7 +6135,7 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, } } - if (nBufferIndex > drv_ctx.ip_buf.actualcount ) { + if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) { DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid"); return OMX_ErrorBadParameter; } @@ -5690,6 +6153,7 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, } else { post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB); } + time_stamp_dts.insert_timestamp(buffer); return OMX_ErrorNone; } @@ -5719,7 +6183,6 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, struct vdec_bufferpayload *temp_buffer; struct vdec_seqheader seq_header; bool port_setting_changed = true; - bool not_coded_vop = false; /*Should we generate a Aync error event*/ if (buffer == NULL || buffer->pInputPortPrivate == NULL) { @@ -5729,7 +6192,7 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); - if (nPortIndex > drv_ctx.ip_buf.actualcount) { + if (nPortIndex >= drv_ctx.ip_buf.actualcount) { DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]", nPortIndex); return OMX_ErrorBadParameter; @@ -5746,39 +6209,17 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, return OMX_ErrorNone; } - - if (codec_type_parse == CODEC_TYPE_MPEG4 || codec_type_parse == CODEC_TYPE_DIVX) { - mp4StreamType psBits; - psBits.data = (unsigned char *)(buffer->pBuffer + buffer->nOffset); - psBits.numBytes = buffer->nFilledLen; - mp4_headerparser.parseHeader(&psBits); - not_coded_vop = mp4_headerparser.is_notcodec_vop( - (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen); - if (not_coded_vop) { - DEBUG_PRINT_HIGH("Found Not coded vop len %u frame number %u", - (unsigned int)buffer->nFilledLen,frame_count); - if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { - DEBUG_PRINT_HIGH("Eos and Not coded Vop set len to zero"); - not_coded_vop = false; - buffer->nFilledLen = 0; - } - } - } - - if (input_flush_progress == true - - || not_coded_vop - - ) { + if (input_flush_progress == true) { DEBUG_PRINT_LOW("Flush in progress return buffer "); post_event ((unsigned long)buffer,VDEC_S_SUCCESS, OMX_COMPONENT_GENERATE_EBD); return OMX_ErrorNone; } + auto_lock l(buf_lock); temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate; - if ((temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) { + if (!temp_buffer || (temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) { return OMX_ErrorBadParameter; } /* If its first frame, H264 codec and reject is true, then parse the nal @@ -5910,16 +6351,17 @@ log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0; buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0; + if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + DEBUG_PRINT_LOW("Increment codec_config buffer counter"); + android_atomic_inc(&m_queued_codec_config_count); + } + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); if (rc) { DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver"); return OMX_ErrorHardware; } - if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { - android_atomic_inc(&m_queued_codec_config_count); - } - if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { codec_config_flag = false; } @@ -5933,6 +6375,11 @@ log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len if (!ret) { DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful"); streaming[OUTPUT_PORT] = true; + } else if (errno == EBUSY) { + DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD"); + post_event ((unsigned long)buffer, VDEC_S_SUCCESS, + OMX_COMPONENT_GENERATE_EBD); + return OMX_ErrorInsufficientResources; } else { DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT"); DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued"); @@ -5941,9 +6388,9 @@ log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len return OMX_ErrorBadParameter; } } - DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%d)", - frameinfo.bufferaddr, frameinfo.timestamp, frameinfo.datalen); - time_stamp_dts.insert_timestamp(buffer); + DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)", + frameinfo.bufferaddr, (long long)frameinfo.timestamp, + (unsigned int)frameinfo.datalen); return ret; } @@ -5966,13 +6413,26 @@ log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_IN OMX_BUFFERHEADERTYPE* buffer) { + if (m_state != OMX_StateExecuting && + m_state != OMX_StatePause && + m_state != OMX_StateIdle) { + DEBUG_PRINT_ERROR("FTB in Invalid State"); + return OMX_ErrorInvalidState; + } + + if (!m_out_bEnabled) { + DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled."); + return OMX_ErrorIncorrectStateOperation; + } + + unsigned nPortIndex = 0; if (dynamic_buf_mode) { private_handle_t *handle = NULL; struct VideoDecoderOutputMetaData *meta; unsigned int nPortIndex = 0; if (!buffer || !buffer->pBuffer) { - DEBUG_PRINT_ERROR("%s: invalid params: %p %p", __FUNCTION__, buffer, buffer->pBuffer); + DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer); return OMX_ErrorBadParameter; } @@ -5994,21 +6454,19 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, //Store private handle from GraphicBuffer native_buffer[nPortIndex].privatehandle = handle; native_buffer[nPortIndex].nativehandle = handle; - } - - - if (m_state == OMX_StateInvalid) { - DEBUG_PRINT_ERROR("FTB in Invalid State"); - return OMX_ErrorInvalidState; - } - if (!m_out_bEnabled) { - DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled."); - return OMX_ErrorIncorrectStateOperation; + //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite + //this with a more sane size so that we don't compensate in rest of code + //We'll restore this size later on, so that it's transparent to client + buffer->nFilledLen = 0; + buffer->nAllocLen = handle->size; } + nPortIndex = buffer - client_buffers.get_il_buf_hdr(); if (buffer == NULL || - ((buffer - client_buffers.get_il_buf_hdr()) >= (int)drv_ctx.op_buf.actualcount)) { + (nPortIndex >= drv_ctx.op_buf.actualcount)) { + DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u", + nPortIndex, drv_ctx.op_buf.actualcount); return OMX_ErrorBadParameter; } @@ -6049,8 +6507,11 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); - if (bufferAdd == NULL || nPortIndex > drv_ctx.op_buf.actualcount) + if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) { + DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u", + nPortIndex, drv_ctx.op_buf.actualcount); return OMX_ErrorBadParameter; + } DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p", bufferAdd, bufferAdd->pBuffer); @@ -6079,6 +6540,10 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( pending_output_buffers++; buffer = client_buffers.get_dr_buf_hdr(bufferAdd); + if (!buffer) { + DEBUG_PRINT_ERROR("err: client_buffer ptr invalid"); + return OMX_ErrorBadParameter; + } ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate; if (ptr_respbuffer) { ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data; @@ -6097,7 +6562,7 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( struct v4l2_plane plane[VIDEO_MAX_PLANES]; memset( (void *)&buf, 0, sizeof(buf)); memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES)); - int extra_idx = 0; + unsigned int extra_idx = 0; buf.index = nPortIndex; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; @@ -6121,7 +6586,7 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size; plane[extra_idx].data_offset = 0; } else if (extra_idx >= VIDEO_MAX_PLANES) { - DEBUG_PRINT_ERROR("Extradata index higher than expected: %d", extra_idx); + DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx); return OMX_ErrorBadParameter; } buf.m.planes = plane; @@ -6200,7 +6665,14 @@ OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) if (m_out_mem_ptr) { DEBUG_PRINT_LOW("Freeing the Output Memory"); for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) { - free_output_buffer (&m_out_mem_ptr[i]); + if (BITMASK_PRESENT(&m_out_bm_count, i)) { + BITMASK_CLEAR(&m_out_bm_count, i); + client_buffers.free_output_buffer (&m_out_mem_ptr[i]); + } + + if (release_output_done()) { + break; + } } #ifdef _ANDROID_ICS_ memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); @@ -6211,11 +6683,19 @@ OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) if (m_inp_mem_ptr || m_inp_heap_ptr) { DEBUG_PRINT_LOW("Freeing the Input Memory"); for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) { - if (m_inp_mem_ptr) - free_input_buffer (i,&m_inp_mem_ptr[i]); - else - free_input_buffer (i,NULL); - } + + if (BITMASK_PRESENT(&m_inp_bm_count, i)) { + BITMASK_CLEAR(&m_inp_bm_count, i); + if (m_inp_mem_ptr) + free_input_buffer (i,&m_inp_mem_ptr[i]); + else + free_input_buffer (i,NULL); + } + + if (release_input_done()) { + break; + } + } } free_input_buffer_header(); free_output_buffer_header(); @@ -6617,7 +7097,7 @@ bool omx_vdec::release_output_done(void) bool bRet = false; unsigned i=0,j=0; - DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p",m_inp_mem_ptr); + DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p",m_out_mem_ptr); if (m_out_mem_ptr) { for (; j < drv_ctx.op_buf.actualcount ; j++) { if (BITMASK_PRESENT(&m_out_bm_count,j)) { @@ -6727,6 +7207,28 @@ OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp, handle_extradata(buffer); } +#ifdef OUTPUT_EXTRADATA_LOG + if (outputExtradataFile) { + int buf_index = buffer - m_out_mem_ptr; + OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr); + + OMX_OTHER_EXTRADATATYPE *p_extra = NULL; + p_extra = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3)); + + while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) { + DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x", + p_extra->nSize, p_extra->eType); + fwrite (p_extra,1,p_extra->nSize,outputExtradataFile); + + if (p_extra->eType == OMX_ExtraDataNone) { + break; + } + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } + } +#endif + /* For use buffer we need to copy the data */ if (!output_flush_progress) { /* This is the error check for non-recoverable errros */ @@ -6765,13 +7267,16 @@ OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp, } } } - } else { - time_stamp_dts.remove_time_stamp( - buffer->nTimeStamp, - is_interlaced && is_duplicate_ts_valid); + } } - + /* Since we're passing around handles, adjust nFilledLen and nAllocLen + * to size of the handle. Do it _after_ handle_extradata() which + * requires the respective sizes to be accurate. */ + if (dynamic_buf_mode) { + buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData); + buffer->nFilledLen = buffer->nFilledLen ? + sizeof(struct VideoDecoderOutputMetaData) : 0; } if (m_cb.FillBufferDone) { if (buffer->nFilledLen > 0) { @@ -6799,25 +7304,6 @@ OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp, proc_frms = 0; } } - -#ifdef OUTPUT_EXTRADATA_LOG - if (outputExtradataFile) { - - OMX_OTHER_EXTRADATATYPE *p_extra = NULL; - p_extra = (OMX_OTHER_EXTRADATATYPE *) - ((unsigned)(buffer->pBuffer + buffer->nOffset + - buffer->nFilledLen + 3)&(~3)); - while (p_extra && - (OMX_U8*)p_extra < (buffer->pBuffer + buffer->nAllocLen) ) { - DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%d",p_extra->nSize, p_extra->eType); - fwrite (p_extra,1,p_extra->nSize,outputExtradataFile); - if (p_extra->eType == OMX_ExtraDataNone) { - break; - } - p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); - } - } -#endif } if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { prev_ts = LLONG_MAX; @@ -6883,12 +7369,14 @@ OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp, } #ifdef ADAPTIVE_PLAYBACK_SUPPORTED - if (m_smoothstreaming_mode) { + if (m_smoothstreaming_mode && m_out_mem_ptr) { OMX_U32 buf_index = buffer - m_out_mem_ptr; BufferDim_t dim; - dim.sliceWidth = drv_ctx.video_resolution.frame_width; - dim.sliceHeight = drv_ctx.video_resolution.frame_height; - private_handle_t *private_handle = native_buffer[buf_index].privatehandle; + private_handle_t *private_handle = NULL; + dim.sliceWidth = framesize.nWidth; + dim.sliceHeight = framesize.nHeight; + if (native_buffer[buf_index].privatehandle) + private_handle = native_buffer[buf_index].privatehandle; if (private_handle) { DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d", dim.sliceWidth, dim.sliceHeight); @@ -6904,26 +7392,14 @@ OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp, OMX_BUFFERHEADERTYPE* buffer) { - if (buffer == NULL || ((buffer - m_inp_mem_ptr) > (int)drv_ctx.ip_buf.actualcount)) { + if (buffer == NULL || ((buffer - m_inp_mem_ptr) >= (int)drv_ctx.ip_buf.actualcount)) { DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer); return OMX_ErrorBadParameter; } - DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p", - buffer, buffer->pBuffer); + DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = %x", + buffer, buffer->pBuffer, buffer->nFlags); pending_input_buffers--; - if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { - int pending_flush_waiters; - - while (pending_flush_waiters = INT_MAX, - sem_getvalue(&m_safe_flush, &pending_flush_waiters), - /* 0 == there /are/ waiters depending on POSIX implementation */ - pending_flush_waiters <= 0 ) { - sem_post(&m_safe_flush); - } - - android_atomic_and(0, &m_queued_codec_config_count); /* no clearer way to set to 0 */ - } if (arbitrary_bytes) { if (pdest_frame == NULL && input_flush_progress == false) { @@ -6973,6 +7449,16 @@ int omx_vdec::async_message_process (void *context, void* message) OMX_COMPONENT_GENERATE_HARDWARE_ERROR); break; + case VDEC_MSG_EVT_HW_OVERLOAD: + omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD); + break; + + case VDEC_MSG_EVT_HW_UNSUPPORTED: + omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING); + break; + case VDEC_MSG_RESP_START_DONE: omx->post_event ((unsigned)NULL, vdec_msg->status_code,\ OMX_COMPONENT_GENERATE_START_DONE); @@ -7013,14 +7499,27 @@ int omx_vdec::async_message_process (void *context, void* message) ((omxhdr - omx->m_inp_mem_ptr) > (int)omx->drv_ctx.ip_buf.actualcount) ) { omxhdr = NULL; vdec_msg->status_code = VDEC_S_EFATAL; + break; } if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) { DEBUG_PRINT_HIGH("Unsupported input"); omx->omx_report_error (); } if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) { + omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR; } + if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + + DEBUG_PRINT_LOW("Decrement codec_config buffer counter"); + android_atomic_dec(&omx->m_queued_codec_config_count); + if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) && + BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) { + DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer"); + sem_post(&omx->m_safe_flush); + } + } + omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code, OMX_COMPONENT_GENERATE_EBD); break; @@ -7032,7 +7531,7 @@ int omx_vdec::async_message_process (void *context, void* message) omx->post_event ((unsigned long)timestamp, vdec_msg->status_code, OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED); DEBUG_PRINT_HIGH("Field dropped time stamp is %lld", - vdec_msg->msgdata.output_frame.time_stamp); + (long long)vdec_msg->msgdata.output_frame.time_stamp); } break; case VDEC_MSG_RESP_OUTPUT_FLUSHED: @@ -7040,17 +7539,21 @@ int omx_vdec::async_message_process (void *context, void* message) v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data; omxhdr=omx->m_out_mem_ptr+v4l2_buf_ptr->index; - DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) Pic_type(%u)", - omxhdr, vdec_msg->msgdata.output_frame.time_stamp, - vdec_msg->msgdata.output_frame.pic_type); + + DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x) FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)", + omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp, + vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags, + (unsigned int)vdec_msg->msgdata.output_frame.len, + vdec_msg->msgdata.output_frame.framesize.left, + vdec_msg->msgdata.output_frame.framesize.top, + vdec_msg->msgdata.output_frame.framesize.right, + vdec_msg->msgdata.output_frame.framesize.bottom); if (omxhdr && omxhdr->pOutputPortPrivate && ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) && (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) { - if (omx->dynamic_buf_mode && vdec_msg->msgdata.output_frame.len) { - vdec_msg->msgdata.output_frame.len = omxhdr->nAllocLen; - } + if ( vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) { omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len; omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset; @@ -7069,6 +7572,9 @@ int omx_vdec::async_message_process (void *context, void* message) } else { omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME; } + if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) { + omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; + } if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) { omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY; } @@ -7103,75 +7609,51 @@ int omx_vdec::async_message_process (void *context, void* message) } vdec_msg->msgdata.output_frame.bufferaddr = omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr; - int format_notably_changed = 0; - if (omxhdr->nFilledLen && - (omxhdr->nFilledLen != (unsigned)omx->prev_n_filled_len)) { - if ((vdec_msg->msgdata.output_frame.framesize.bottom != omx->drv_ctx.video_resolution.frame_height) || - (vdec_msg->msgdata.output_frame.framesize.right != omx->drv_ctx.video_resolution.frame_width)) { - DEBUG_PRINT_HIGH("Height/Width information has changed"); - omx->drv_ctx.video_resolution.frame_height = vdec_msg->msgdata.output_frame.framesize.bottom; - omx->drv_ctx.video_resolution.frame_width = vdec_msg->msgdata.output_frame.framesize.right; - format_notably_changed = 1; - } - } - if (omxhdr->nFilledLen && (((unsigned)omx->rectangle.nLeft != - vdec_msg->msgdata.output_frame.framesize.left) - || ((unsigned)omx->rectangle.nTop != vdec_msg->msgdata.output_frame.framesize.top) - || (omx->rectangle.nWidth != vdec_msg->msgdata.output_frame.framesize.right) - || (omx->rectangle.nHeight != vdec_msg->msgdata.output_frame.framesize.bottom))) { - if ((vdec_msg->msgdata.output_frame.framesize.bottom != omx->drv_ctx.video_resolution.frame_height) || - (vdec_msg->msgdata.output_frame.framesize.right != omx->drv_ctx.video_resolution.frame_width)) { - omx->drv_ctx.video_resolution.frame_height = vdec_msg->msgdata.output_frame.framesize.bottom; - omx->drv_ctx.video_resolution.frame_width = vdec_msg->msgdata.output_frame.framesize.right; - DEBUG_PRINT_HIGH("Height/Width information has changed. W: %d --> %d, H: %d --> %d", - omx->drv_ctx.video_resolution.frame_width, vdec_msg->msgdata.output_frame.framesize.right, - omx->drv_ctx.video_resolution.frame_height, vdec_msg->msgdata.output_frame.framesize.bottom); - } - DEBUG_PRINT_HIGH("Crop information changed. W: %u --> %d, H: %u -> %d", - (unsigned int)omx->rectangle.nWidth, vdec_msg->msgdata.output_frame.framesize.right, - (unsigned int)omx->rectangle.nHeight, vdec_msg->msgdata.output_frame.framesize.bottom); - if (vdec_msg->msgdata.output_frame.framesize.left + vdec_msg->msgdata.output_frame.framesize.right >= - omx->drv_ctx.video_resolution.frame_width) { - vdec_msg->msgdata.output_frame.framesize.left = 0; - if (vdec_msg->msgdata.output_frame.framesize.right > omx->drv_ctx.video_resolution.frame_width) { - vdec_msg->msgdata.output_frame.framesize.right = omx->drv_ctx.video_resolution.frame_width; - } - } - if (vdec_msg->msgdata.output_frame.framesize.top + vdec_msg->msgdata.output_frame.framesize.bottom >= - omx->drv_ctx.video_resolution.frame_height) { - vdec_msg->msgdata.output_frame.framesize.top = 0; - if (vdec_msg->msgdata.output_frame.framesize.bottom > omx->drv_ctx.video_resolution.frame_height) { - vdec_msg->msgdata.output_frame.framesize.bottom = omx->drv_ctx.video_resolution.frame_height; - } - } - DEBUG_PRINT_LOW("omx_vdec: Adjusted Dim L: %d, T: %d, R: %d, B: %d, W: %d, H: %d", + + /* Post event if resolution OR crop changed */ + /* filled length will be changed if resolution changed */ + /* Crop parameters can be changed even without resolution change */ + if (omxhdr->nFilledLen + && ((omx->prev_n_filled_len != omxhdr->nFilledLen) + || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left) + || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top) + || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right) + || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom) + || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width) + || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) { + + DEBUG_PRINT_HIGH("Paramters Changed From: Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u --> Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u", + omx->prev_n_filled_len, + omx->drv_ctx.video_resolution.frame_width, + omx->drv_ctx.video_resolution.frame_height, + omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top, + omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom, + omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width, + vdec_msg->msgdata.output_frame.picsize.frame_height, vdec_msg->msgdata.output_frame.framesize.left, vdec_msg->msgdata.output_frame.framesize.top, vdec_msg->msgdata.output_frame.framesize.right, - vdec_msg->msgdata.output_frame.framesize.bottom, - omx->drv_ctx.video_resolution.frame_width, - omx->drv_ctx.video_resolution.frame_height); - omx->rectangle.nLeft = vdec_msg->msgdata.output_frame.framesize.left; - omx->rectangle.nTop = vdec_msg->msgdata.output_frame.framesize.top; - omx->rectangle.nWidth = vdec_msg->msgdata.output_frame.framesize.right; - omx->rectangle.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom; - format_notably_changed = 1; - } - DEBUG_PRINT_HIGH("Left: %d, Right: %d, top: %d, Bottom: %d", - vdec_msg->msgdata.output_frame.framesize.left,vdec_msg->msgdata.output_frame.framesize.right, - vdec_msg->msgdata.output_frame.framesize.top, vdec_msg->msgdata.output_frame.framesize.bottom); - if (format_notably_changed) { - if (omx->is_video_session_supported()) { - omx->post_event (0, vdec_msg->status_code, - OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING); - } else { - if (!omx->client_buffers.update_buffer_req()) { - DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed"); - } - omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexConfigCommonOutputCrop, + vdec_msg->msgdata.output_frame.framesize.bottom); + + omx->drv_ctx.video_resolution.frame_width = + vdec_msg->msgdata.output_frame.picsize.frame_width; + omx->drv_ctx.video_resolution.frame_height = + vdec_msg->msgdata.output_frame.picsize.frame_height; + if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) { + omx->drv_ctx.video_resolution.stride = + VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width); + omx->drv_ctx.video_resolution.scan_lines = + VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height); + } + memcpy(&omx->drv_ctx.frame_size, + &vdec_msg->msgdata.output_frame.framesize, + sizeof(struct vdec_framesize)); + + omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX, + OMX_IndexConfigCommonOutputCrop, OMX_COMPONENT_GENERATE_PORT_RECONFIG); } - } + if (omxhdr->nFilledLen) omx->prev_n_filled_len = omxhdr->nFilledLen; @@ -7194,16 +7676,23 @@ int omx_vdec::async_message_process (void *context, void* message) ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr + (unsigned long)vdec_msg->msgdata.output_frame.offset), vdec_msg->msgdata.output_frame.len); - } else + } else { + DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u", + (unsigned int)vdec_msg->msgdata.output_frame.len, + omxhdr->nAllocLen, omx->prev_n_filled_len); omxhdr->nFilledLen = 0; + } + omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code, OMX_COMPONENT_GENERATE_FBD); - } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) + + } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) { omx->post_event ((unsigned long)NULL, vdec_msg->status_code, OMX_COMPONENT_GENERATE_EOS_DONE); - else + } else { omx->post_event ((unsigned int)NULL, vdec_msg->status_code, OMX_COMPONENT_GENERATE_HARDWARE_ERROR); + } break; case VDEC_MSG_EVT_CONFIG_CHANGED: DEBUG_PRINT_HIGH("Port settings changed"); @@ -7253,7 +7742,9 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary ( } } - + if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { + codec_config_flag = false; + } return OMX_ErrorNone; } @@ -7615,6 +8106,7 @@ OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp) h264_scratch.pBuffer,h264_scratch.nFilledLen); pdest_frame->nFilledLen += h264_scratch.nFilledLen; h264_scratch.nFilledLen = 0; + if (h264_last_au_ts != LLONG_MAX) pdest_frame->nTimeStamp = h264_last_au_ts; } else { /* Completely new frame, let's just push what @@ -8117,12 +8609,12 @@ OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) { OMX_ERRORTYPE eRet = OMX_ErrorNone; struct v4l2_requestbuffers bufreq; - unsigned int buf_size = 0, extra_data_size = 0, client_extra_data_size = 0; + unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0; unsigned int final_extra_data_size = 0; struct v4l2_format fmt; int ret = 0; - DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d)", - buffer_prop->actualcount, buffer_prop->buffer_size); + DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)", + buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); bufreq.memory = V4L2_MEMORY_USERPTR; bufreq.count = 1; if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) { @@ -8149,8 +8641,8 @@ OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) buffer_prop->mincount = bufreq.count; DEBUG_PRINT_HIGH("Count = %d",bufreq.count); } - DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d)", - buffer_prop->actualcount, buffer_prop->buffer_size); + DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)", + buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; @@ -8185,53 +8677,24 @@ OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx); return OMX_ErrorBadParameter; } - if (client_extradata & OMX_FRAMEINFO_EXTRADATA) { - DEBUG_PRINT_HIGH("Frame info extra data enabled!"); - client_extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE; - } - if (client_extradata & OMX_INTERLACE_EXTRADATA) { - client_extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE; - } - if (client_extradata & OMX_PORTDEF_EXTRADATA) { - client_extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE; - DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d", - client_extra_data_size); - } - if ((client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) { - client_extra_data_size += OMX_FRAMEDIMENSION_EXTRADATA_SIZE; - DEBUG_PRINT_HIGH("Frame dimension enabled extra_data_size = %d\n", - client_extra_data_size); - } - if (client_extradata & OMX_FRAMEPACK_EXTRADATA) { - client_extra_data_size += OMX_FRAMEPACK_EXTRADATA_SIZE; - DEBUG_PRINT_HIGH("framepack extradata enabled"); - } - if (client_extradata & OMX_QP_EXTRADATA) { - client_extra_data_size += OMX_QP_EXTRADATA_SIZE; - DEBUG_PRINT_HIGH("QP extradata enabled"); - } - if (client_extradata & OMX_BITSINFO_EXTRADATA) { - client_extra_data_size += OMX_BITSINFO_EXTRADATA_SIZE; - DEBUG_PRINT_HIGH("Input bits info extradata enabled"); - } - if (client_extradata & OMX_EXTNUSER_EXTRADATA) { - client_extra_data_size += OMX_USERDATA_EXTRADATA_SIZE; - DEBUG_PRINT_HIGH("Userdata extradata enabled"); - } - if (client_extra_data_size) { - client_extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator - buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit - } - final_extra_data_size = (extra_data_size > client_extra_data_size ? - extra_data_size : client_extra_data_size); + default_extra_data_size = VENUS_EXTRADATA_SIZE( + drv_ctx.video_resolution.frame_height, + drv_ctx.video_resolution.frame_width); + final_extra_data_size = extra_data_size > default_extra_data_size ? + extra_data_size : default_extra_data_size; + + final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) & + (~(buffer_prop->alignment - 1)); + drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size; drv_ctx.extradata_info.count = buffer_prop->actualcount; drv_ctx.extradata_info.buffer_size = final_extra_data_size; - buf_size += client_extra_data_size; + if (!secure_mode) + buf_size += final_extra_data_size; buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); - DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d)", - buffer_prop->actualcount, buffer_prop->buffer_size, buf_size); + DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)", + buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size); if (extra_data_size) DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)", drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size); @@ -8243,8 +8706,8 @@ OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) eRet = set_buffer_req(buffer_prop); } } - DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%d)", - buffer_prop->actualcount, buffer_prop->buffer_size); + DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)", + buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); return eRet; } @@ -8255,14 +8718,15 @@ OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop) struct v4l2_format fmt; struct v4l2_requestbuffers bufreq; int ret; - DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%d)", - buffer_prop->actualcount, buffer_prop->buffer_size); + DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)", + buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size); buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); if (buf_size != buffer_prop->buffer_size) { - DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)", - buffer_prop->buffer_size, buf_size); + DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)", + (unsigned int)buffer_prop->buffer_size, buf_size); eRet = OMX_ErrorBadParameter; } else { + memset(&fmt, 0x0, sizeof(struct v4l2_format)); fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; @@ -8326,12 +8790,13 @@ OMX_ERRORTYPE omx_vdec::update_picture_resolution() OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) { OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct v4l2_format fmt; if (!portDefn) { return OMX_ErrorBadParameter; } DEBUG_PRINT_LOW("omx_vdec::update_portdef"); portDefn->nVersion.nVersion = OMX_SPEC_VERSION; - portDefn->nSize = sizeof(portDefn); + portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portDefn->eDomain = OMX_PortDomainVideo; if (drv_ctx.frame_rate.fps_denominator > 0) portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator / @@ -8340,6 +8805,7 @@ OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) DEBUG_PRINT_ERROR("Error: Divide by zero"); return OMX_ErrorBadParameter; } + memset(&fmt, 0x0, sizeof(struct v4l2_format)); if (0 == portDefn->nPortIndex) { portDefn->eDir = OMX_DirInput; portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount; @@ -8349,6 +8815,9 @@ OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) portDefn->format.video.eCompressionFormat = eCompressionFormat; portDefn->bEnabled = m_inp_bEnabled; portDefn->bPopulated = m_inp_bPopulated; + + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.fmt.pix_mp.pixelformat = output_capability; } else if (1 == portDefn->nPortIndex) { unsigned int buf_size = 0; if (!client_buffers.update_buffer_req()) { @@ -8370,19 +8839,36 @@ OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) DEBUG_PRINT_ERROR("Error in getting color format"); return OMX_ErrorHardware; } + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.pixelformat = capture_capability; } else { portDefn->eDir = OMX_DirMax; DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d", (int)portDefn->nPortIndex); eRet = OMX_ErrorBadPortIndex; } + if (is_down_scalar_enabled) { + int ret = 0; + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); + if (ret) { + DEBUG_PRINT_ERROR("update_portdef : Error in getting port resolution"); + return OMX_ErrorHardware; + } else { + portDefn->format.video.nFrameWidth = fmt.fmt.pix_mp.width; + portDefn->format.video.nFrameHeight = fmt.fmt.pix_mp.height; + portDefn->format.video.nStride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline; + portDefn->format.video.nSliceHeight = fmt.fmt.pix_mp.plane_fmt[0].reserved[0]; + } + } else { portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height; portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width; portDefn->format.video.nStride = drv_ctx.video_resolution.stride; portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines; + } + if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) || (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) { - portDefn->format.video.nStride = drv_ctx.video_resolution.frame_width; + portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16); portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height; } DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d " @@ -8427,11 +8913,11 @@ OMX_ERRORTYPE omx_vdec::allocate_output_headers() nPlatformEntrySize = drv_ctx.op_buf.actualcount * sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); - DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize, - sizeof(OMX_BUFFERHEADERTYPE), + DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize, + (unsigned int)sizeof(OMX_BUFFERHEADERTYPE), nPMEMInfoSize, nPlatformListSize); - DEBUG_PRINT_LOW("PE %d bmSize %d",nPlatformEntrySize, + DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize, m_out_bm_count); m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); // Alloc mem for platform specific info @@ -8444,9 +8930,18 @@ OMX_ERRORTYPE omx_vdec::allocate_output_headers() drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ calloc (sizeof (struct vdec_output_frameinfo), drv_ctx.op_buf.actualcount); + if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) { + DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer"); + return OMX_ErrorInsufficientResources; + } + #ifdef USE_ION drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \ calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount); + if (!drv_ctx.op_buf_ion_info) { + DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info"); + return OMX_ErrorInsufficientResources; + } #endif if (dynamic_buf_mode) { out_dynamic_list = (struct dynamic_buf_list *) \ @@ -8599,7 +9094,7 @@ void omx_vdec::set_frame_rate(OMX_S64 act_timestamp) && llabs(act_timestamp - prev_ts) > 2000) { new_frame_interval = client_set_fps ? frm_int : llabs(act_timestamp - prev_ts); - if (new_frame_interval < frm_int || frm_int == 0) { + if (new_frame_interval != frm_int || frm_int == 0) { frm_int = new_frame_interval; if (frm_int) { drv_ctx.frame_rate.fps_numerator = 1e6; @@ -8607,7 +9102,7 @@ void omx_vdec::set_frame_rate(OMX_S64 act_timestamp) DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)", (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator / (float)drv_ctx.frame_rate.fps_denominator); - m_perf_control.request_cores(frm_int); + //m_perf_control.request_cores(frm_int); /* We need to report the difference between this FBD and the previous FBD * back to the driver for clock scaling purposes. */ struct v4l2_outputparm oparm; @@ -8637,16 +9132,20 @@ void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp) rst_prev_ts = false; } else if (VALID_TS(prev_ts)) { bool codec_cond = (drv_ctx.timestamp_adjust)? - (!VALID_TS(act_timestamp) || (((act_timestamp > prev_ts)? - (act_timestamp - prev_ts):(prev_ts - act_timestamp)) <= 2000)): - (!VALID_TS(act_timestamp) || act_timestamp == prev_ts); + (!VALID_TS(act_timestamp) || act_timestamp < prev_ts || llabs(act_timestamp - prev_ts) <= 2000) : + (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts); if (frm_int > 0 && codec_cond) { DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp); act_timestamp = prev_ts + frm_int; DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp); prev_ts = act_timestamp; - } else + } else { + if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) { + // ensure that timestamps can never step backwards when in display order + act_timestamp = prev_ts; + } set_frame_rate(act_timestamp); + } } else if (frm_int > 0) // In this case the frame rate was set along { // with the port definition, start ts with 0 act_timestamp = prev_ts = 0; // and correct if a valid ts is received. @@ -8665,6 +9164,9 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) OMX_U32 recovery_sei_flags = 1; int enable = 0; + //TODO: disable extradata + return; + int buf_index = p_buf_hdr - m_out_mem_ptr; if (buf_index >= drv_ctx.extradata_info.count) { DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)", @@ -8693,6 +9195,7 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) { p_extra = NULL; + DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra"); return; } OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata; @@ -8799,6 +9302,10 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) if (seqdisp_payload) { m_disp_hor_size = seqdisp_payload->disp_width; m_disp_vert_size = seqdisp_payload->disp_height; + if (client_extradata & OMX_MPEG2SEQDISP_EXTRADATA) { + append_mpeg2_seqdisplay_extradata(p_extra, seqdisp_payload); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } } break; case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING: @@ -8856,7 +9363,7 @@ unrecognized_extradata: p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; append_terminator_extradata(p_extra); } - if (secure_mode) { + if (secure_mode && p_extradata && m_other_extradata) { struct vdec_output_frameinfo *ptr_extradatabuff = NULL; memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size); ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate; @@ -8923,13 +9430,6 @@ OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { DEBUG_PRINT_HIGH("Failed to set panscan extradata"); } - if (output_capability == V4L2_PIX_FMT_MPEG2) { - control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; - control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP; - if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { - DEBUG_PRINT_HIGH("Failed to set panscan extradata"); - } - } } if (requested_extradata & OMX_TIMEINFO_EXTRADATA) { control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; @@ -8971,6 +9471,18 @@ OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, DEBUG_PRINT_HIGH("Failed to set stream userdata extradata"); } } + if (requested_extradata & OMX_MPEG2SEQDISP_EXTRADATA) { + if (output_capability == V4L2_PIX_FMT_MPEG2) { + DEBUG_PRINT_HIGH("Enable seq display extradata"); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA; + control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP; + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_HIGH("Failed to set seqdisp extradata"); + } + } else { + DEBUG_PRINT_HIGH("Seq display extradata is supported for MPEG2 only"); + } + } } ret = get_buffer_req(&drv_ctx.op_buf); return ret; @@ -9131,6 +9643,14 @@ void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra) } DEBUG_PRINT_HIGH( "=========== End of Userdata ==========="); + } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMpeg2SeqDisplay) { + OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY *seq_display = (OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY*)(void*)extra->data; + DEBUG_PRINT_HIGH( + "------Mpeg2SeqDisplay ------\n" + " Frame Width: %d\n" + " Frame Height: %d\n" + "=========== End of Mpeg2SeqDisplay ===========", + seq_display->disp_width, seq_display->disp_height); } else if (extra->eType == OMX_ExtraDataNone) { DEBUG_PRINT_HIGH("========== End of Terminator ==========="); } else { @@ -9179,7 +9699,6 @@ void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra, void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra) { OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension; - OMX_U8* tmp = extra->data; if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) { return; } @@ -9213,7 +9732,6 @@ void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra, { OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL; struct msm_vidc_panscan_window *panscan_window; - OMX_U8 *tmp = extra->data; if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) { return; } @@ -9275,7 +9793,6 @@ void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra, void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra) { OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL; - OMX_U8 *tmp = extra->data; extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE; extra->nVersion.nVersion = OMX_SPEC_VERSION; extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; @@ -9294,7 +9811,6 @@ void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra, struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload) { OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack; - OMX_U8* tmp = extra->data; if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) { DEBUG_PRINT_ERROR("frame packing size mismatch"); return; @@ -9319,7 +9835,6 @@ void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra, struct msm_vidc_frame_qp_payload *qp_payload) { OMX_QCOM_EXTRADATA_QP * qp = NULL; - OMX_U8* tmp = extra->data; if (!qp_payload) { DEBUG_PRINT_ERROR("QP payload is NULL"); return; @@ -9338,7 +9853,6 @@ void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra, struct msm_vidc_frame_bits_info_payload *bits_payload) { OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL; - OMX_U8* tmp = extra->data; if (!bits_payload) { DEBUG_PRINT_ERROR("bits info payload is NULL"); return; @@ -9359,11 +9873,10 @@ void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra, { int userdata_size = 0; struct msm_vidc_stream_userdata_payload *userdata_payload = NULL; - OMX_U8* tmp = p_user->data; userdata_payload = (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data; userdata_size = p_user->nDataSize; - extra->nSize = OMX_USERDATA_EXTRADATA_SIZE; + extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size; extra->nVersion.nVersion = OMX_SPEC_VERSION; extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData; @@ -9373,6 +9886,20 @@ void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra, print_debug_extradata(extra); } +void omx_vdec::append_mpeg2_seqdisplay_extradata(OMX_OTHER_EXTRADATATYPE *extra, + struct msm_vidc_mpeg2_seqdisp_payload *seq_display_payload) +{ + OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY *seq_display = NULL; + extra->nSize = OMX_MPEG2SEQDISP_EXTRADATA_SIZE; + extra->nVersion.nVersion = OMX_SPEC_VERSION; + extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMpeg2SeqDisplay; + extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY); + seq_display = (OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY *)(void *)extra->data; + seq_display->disp_width = seq_display_payload->disp_width; + seq_display->disp_height = seq_display_payload->disp_height; + print_debug_extradata(extra); +} void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra) { if (!client_extradata) { @@ -9615,8 +10142,9 @@ bool omx_vdec::allocate_color_convert_buf::update_buffer_req() if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size || !destination_size) { DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d" - "driver size %d destination size %d", - src_size,omx->drv_ctx.op_buf.buffer_size,destination_size); + "driver size %u destination size %d", + src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size, + destination_size); status = false; c2d.close(); buffer_size_req = 0; @@ -9654,7 +10182,7 @@ bool omx_vdec::allocate_color_convert_buf::set_color_format( DEBUG_PRINT_ERROR("Incorrect color format"); status = false; } - if (status && + if (status && !omx->is_component_secure() && drv_color_format != dest_color_format && drv_color_format != (OMX_COLOR_FORMATTYPE) QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) { @@ -9714,6 +10242,7 @@ OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr() bool status; if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) { pthread_mutex_lock(&omx->c_lock); + cache_clean_buffer(index); status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd, omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index], pmem_baseaddress[index], pmem_baseaddress[index]); @@ -9726,6 +10255,7 @@ OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr() unsigned int filledLen = 0; c2d.get_output_filled_length(filledLen); m_out_mem_ptr_client[index].nFilledLen = filledLen; + cache_clean_invalidate_buffer(index); } pthread_mutex_unlock(&omx->c_lock); } else @@ -9847,16 +10377,19 @@ OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_conve } if ((temp_bufferHdr - omx->m_out_mem_ptr) >= (int)omx->drv_ctx.op_buf.actualcount) { - DEBUG_PRINT_ERROR("Invalid header index %d", - (temp_bufferHdr - omx->m_out_mem_ptr)); + DEBUG_PRINT_ERROR("Invalid header index %ld", + (long int)(temp_bufferHdr - omx->m_out_mem_ptr)); return OMX_ErrorUndefined; } unsigned int i = allocated_count; #ifdef USE_ION + // Allocate color-conversion buffers as cached to improve software-reading + // performance of YUV (thumbnails). NOTE: These buffers will need an explicit + // cache invalidation. op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory( buffer_size_req,buffer_alignment_req, &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data, - 0); + ION_FLAG_CACHED); pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd; if (op_buf_ion_info[i].ion_device_fd < 0) { DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert"); @@ -9873,7 +10406,7 @@ OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_conve } m_heap_ptr[i].video_heap_ptr = new VideoHeap ( op_buf_ion_info[i].ion_device_fd,buffer_size_req, - pmem_baseaddress[i],(ion_handle*)op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]); + pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]); #endif m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get(); m_pmem_info_client[i].offset = 0; @@ -9925,10 +10458,59 @@ bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE return status; } +OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops( + unsigned int index, unsigned int cmd) +{ + if (!enabled) { + return OMX_ErrorNone; + } + + if (!omx || index >= omx->drv_ctx.op_buf.actualcount) { + DEBUG_PRINT_ERROR("%s: Invalid param", __func__); + return OMX_ErrorBadParameter; + } + + struct ion_flush_data flush_data; + struct ion_custom_data custom_data; + + memset(&flush_data, 0x0, sizeof(flush_data)); + memset(&custom_data, 0x0, sizeof(custom_data)); + + flush_data.vaddr = pmem_baseaddress[index]; + flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd; + flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle; + flush_data.length = buffer_size_req; + custom_data.cmd = cmd; + custom_data.arg = (unsigned long)&flush_data; + + DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d", + (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate", + flush_data.fd, flush_data.handle, flush_data.vaddr, + flush_data.length); + int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data); + if (ret < 0) { + DEBUG_PRINT_ERROR("Cache %s failed: %s\n", + (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate", + strerror(errno)); + return OMX_ErrorUndefined; + } + return OMX_ErrorNone; +} + void omx_vdec::buf_ref_add(OMX_U32 fd, OMX_U32 offset) { unsigned long i = 0; bool buf_present = false; + + if (!dynamic_buf_mode) { + return; + } + + if (!out_dynamic_list) { + DEBUG_PRINT_ERROR("buf_ref_add: out_dynamic_list is NULL"); + return; + } + pthread_mutex_lock(&m_lock); for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { //check the buffer fd, offset, uv addr with list contents @@ -9962,6 +10544,16 @@ void omx_vdec::buf_ref_add(OMX_U32 fd, OMX_U32 offset) void omx_vdec::buf_ref_remove(OMX_U32 fd, OMX_U32 offset) { unsigned long i = 0; + + if (!dynamic_buf_mode) { + return; + } + + if (!out_dynamic_list) { + DEBUG_PRINT_ERROR("buf_ref_add: out_dynamic_list is NULL"); + return; + } + pthread_mutex_lock(&m_lock); for (i = 0; i < drv_ctx.op_buf.actualcount; i++) { //check the buffer fd, offset, uv addr with list contents @@ -10090,14 +10682,112 @@ void omx_vdec::perf_control::load_lib() } } +OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth, + unsigned long nMaxFrameHeight) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + int ret = 0; + unsigned long min_res_buf_count = 0; + + eRet = enable_smoothstreaming(); + if (eRet != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver"); + return eRet; + } + + DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu", + nMaxFrameWidth, + nMaxFrameHeight); + m_smoothstreaming_mode = true; + m_smoothstreaming_width = nMaxFrameWidth; + m_smoothstreaming_height = nMaxFrameHeight; + + //Get upper limit buffer count for min supported resolution + struct v4l2_format fmt; + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.fmt.pix_mp.height = m_decoder_capability.min_height; + fmt.fmt.pix_mp.width = m_decoder_capability.min_width; + fmt.fmt.pix_mp.pixelformat = output_capability; + + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); + if (ret) { + DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u", + m_decoder_capability.min_height, + m_decoder_capability.min_width); + return OMX_ErrorUnsupportedSetting; + } + + eRet = get_buffer_req(&drv_ctx.op_buf); + if (eRet != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("failed to get_buffer_req"); + return eRet; + } + + min_res_buf_count = drv_ctx.op_buf.mincount; + DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u", + min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width); + + update_resolution(m_smoothstreaming_width, m_smoothstreaming_height, + m_smoothstreaming_width, m_smoothstreaming_height); + eRet = is_video_session_supported(); + if (eRet != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("video session is not supported"); + return eRet; + } + + //Get upper limit buffer size for max smooth streaming resolution set + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; + fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; + fmt.fmt.pix_mp.pixelformat = output_capability; + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); + if (ret) { + DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback"); + return OMX_ErrorUnsupportedSetting; + } + + eRet = get_buffer_req(&drv_ctx.op_buf); + if (eRet != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("failed to get_buffer_req!!"); + return eRet; + } + DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u", + (unsigned int)drv_ctx.op_buf.buffer_size); + + drv_ctx.op_buf.mincount = min_res_buf_count; + drv_ctx.op_buf.actualcount = min_res_buf_count; + eRet = set_buffer_req(&drv_ctx.op_buf); + if (eRet != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("failed to set_buffer_req"); + return eRet; + } + + eRet = get_buffer_req(&drv_ctx.op_buf); + if (eRet != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("failed to get_buffer_req!!!"); + return eRet; + } + DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u", + drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size); + return eRet; +} //static -OMX_ERRORTYPE omx_vdec::describeColorFormat(DescribeColorFormatParams *params) { - if (params == NULL) { +OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) { + +#ifndef FLEXYUV_SUPPORTED + (void) pParam; + return OMX_ErrorUndefined; +#else + + if (pParam == NULL) { DEBUG_PRINT_ERROR("describeColorFormat: invalid params"); return OMX_ErrorBadParameter; } + DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam; + MediaImage *img = &(params->sMediaImage); switch(params->eColorFormat) { case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m: @@ -10155,4 +10845,5 @@ OMX_ERRORTYPE omx_vdec::describeColorFormat(DescribeColorFormatParams *params) { i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc); } return OMX_ErrorNone; +#endif //FLEXYUV_SUPPORTED } diff --git a/mm-video-v4l2/vidc/vdec/src/ts_parser.cpp b/mm-video-v4l2/vidc/vdec/src/ts_parser.cpp index ce6779a..809a1f7 100755..100644 --- a/mm-video-v4l2/vidc/vdec/src/ts_parser.cpp +++ b/mm-video-v4l2/vidc/vdec/src/ts_parser.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2015, 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: @@ -32,17 +32,20 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. void omx_time_stamp_reorder::set_timestamp_reorder_mode(bool mode) { + auto_lock l(&m_lock); reorder_ts = mode; } void omx_time_stamp_reorder::enable_debug_print(bool flag) { + auto_lock l(&m_lock); print_debug = flag; } omx_time_stamp_reorder::~omx_time_stamp_reorder() { delete_list(); + pthread_mutex_destroy(&m_lock); } omx_time_stamp_reorder::omx_time_stamp_reorder() @@ -51,6 +54,7 @@ omx_time_stamp_reorder::omx_time_stamp_reorder() phead = pcurrent = NULL; error = false; print_debug = false; + pthread_mutex_init(&m_lock, NULL); } void omx_time_stamp_reorder::delete_list() @@ -143,6 +147,7 @@ bool omx_time_stamp_reorder::add_new_list() bool omx_time_stamp_reorder::insert_timestamp(OMX_BUFFERHEADERTYPE *header) { + auto_lock l(&m_lock); OMX_TICKS *table_entry = NULL; if (!reorder_ts || error || !header) { @@ -209,6 +214,7 @@ bool omx_time_stamp_reorder::insert_timestamp(OMX_BUFFERHEADERTYPE *header) bool omx_time_stamp_reorder::remove_time_stamp(OMX_TICKS ts, bool is_interlaced = false) { + auto_lock l(&m_lock); unsigned int num_ent_remove = (is_interlaced)?2:1; if (!reorder_ts || error) { @@ -241,11 +247,13 @@ bool omx_time_stamp_reorder::remove_time_stamp(OMX_TICKS ts, bool is_interlaced void omx_time_stamp_reorder::flush_timestamp() { + auto_lock l(&m_lock); delete_list(); } bool omx_time_stamp_reorder::get_next_timestamp(OMX_BUFFERHEADERTYPE *header, bool is_interlaced) { + auto_lock l(&m_lock); timestamp *element = NULL,*duplicate = NULL; bool status = false; diff --git a/mm-video-v4l2/vidc/venc.mk b/mm-video-v4l2/vidc/venc.mk index ae3de49..9f799cc 100644 --- a/mm-video-v4l2/vidc/venc.mk +++ b/mm-video-v4l2/vidc/venc.mk @@ -57,7 +57,7 @@ libOmxVdec-def += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT libmm-venc-def += -D_MSM8974_ libmm-venc-def += -D_ION_HEAP_MASK_COMPATIBILITY_WA endif -ifeq ($(TARGET_BOARD_PLATFORM),mpq8092) +ifneq ($(filter msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),) libmm-venc-def += -DMAX_RES_1080P libmm-venc-def += -DMAX_RES_1080P_EBI libOmxVdec-def += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT @@ -75,9 +75,7 @@ libmm-venc-def += -D_ANDROID_ICS_ include $(CLEAR_VARS) -libmm-venc-inc := bionic/libc/include -libmm-venc-inc += bionic/libstdc++/include -libmm-venc-inc += $(LOCAL_PATH)/venc/inc +libmm-venc-inc := $(LOCAL_PATH)/venc/inc libmm-venc-inc += $(OMX_VIDEO_PATH)/vidc/common/inc libmm-venc-inc += hardware/qcom/media/mm-core/inc libmm-venc-inc += hardware/qcom/media/libstagefrighthw @@ -95,13 +93,12 @@ LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(libmm-venc-def) LOCAL_C_INCLUDES := $(libmm-venc-inc) -LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils \ libc2dcolorconvert libdl libgui LOCAL_SRC_FILES := venc/src/omx_video_base.cpp LOCAL_SRC_FILES += venc/src/omx_video_encoder.cpp -ifneq ($(filter msm8974 msm8610 msm8226 msm8084 mpq8092,$(TARGET_BOARD_PLATFORM)),) +ifneq ($(filter msm8974 msm8610 msm8226 msm8084 msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),) LOCAL_SRC_FILES += venc/src/video_encoder_device_v4l2.cpp else LOCAL_SRC_FILES += venc/src/video_encoder_device.cpp 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 3c482e8..5db0613 100755..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-2014, 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 @@ -125,10 +125,10 @@ static const char* MEM_DEVICE = "/dev/pmem_smipool"; (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp) // BitMask Management logic -#define BITS_PER_BYTE 32 -#define BITMASK_SIZE(mIndex) (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE) -#define BITMASK_OFFSET(mIndex) ((mIndex)/BITS_PER_BYTE) -#define BITMASK_FLAG(mIndex) (1 << ((mIndex) % BITS_PER_BYTE)) +#define BITS_PER_INDEX 64 +#define BITMASK_SIZE(mIndex) (((mIndex) + BITS_PER_INDEX - 1)/BITS_PER_INDEX) +#define BITMASK_OFFSET(mIndex) ((mIndex)/BITS_PER_INDEX) +#define BITMASK_FLAG(mIndex) ((uint64_t)1 << ((mIndex) % BITS_PER_INDEX)) #define BITMASK_CLEAR(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \ &= ~(BITMASK_FLAG(mIndex)) #define BITMASK_SET(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \ @@ -141,9 +141,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 32 -#endif + +#define MAX_NUM_INPUT_BUFFERS 64 +#define MAX_NUM_OUTPUT_BUFFERS 64 + void* message_thread(void *); // OMX video class @@ -155,13 +156,11 @@ class omx_video: public qc_omx_component bool c2d_opened; encoder_media_buffer_type meta_buffers[MAX_NUM_INPUT_BUFFERS]; OMX_BUFFERHEADERTYPE *opaque_buffer_hdr[MAX_NUM_INPUT_BUFFERS]; - bool mUseProxyColorFormat; - //RGB or non-native input, and we have pre-allocated conversion buffers - bool mUsesColorConversion; bool get_syntaxhdr_enable; OMX_BUFFERHEADERTYPE *psource_frame; OMX_BUFFERHEADERTYPE *pdest_frame; bool secure_session; + bool hier_b_enabled; //intermediate conversion buffer queued to encoder in case of invalid EOS input OMX_BUFFERHEADERTYPE *mEmptyEosBuffer; @@ -190,6 +189,11 @@ class omx_video: public qc_omx_component omx_c2d_conv c2d_conv; #endif public: + + bool mUseProxyColorFormat; + //RGB or non-native input, and we have pre-allocated conversion buffers + bool mUsesColorConversion; + omx_video(); // constructor virtual ~omx_video(); // destructor @@ -221,7 +225,7 @@ class omx_video: public qc_omx_component virtual bool dev_empty_buf(void *, void *,unsigned,unsigned) = 0; virtual bool dev_fill_buf(void *buffer, void *,unsigned,unsigned) = 0; virtual bool dev_get_buf_req(OMX_U32 *,OMX_U32 *,OMX_U32 *,OMX_U32) = 0; - virtual bool dev_get_seq_hdr(void *, unsigned, OMX_U32 *) = 0; + virtual bool dev_get_seq_hdr(void *, unsigned, unsigned *) = 0; virtual bool dev_loaded_start(void) = 0; virtual bool dev_loaded_stop(void) = 0; virtual bool dev_loaded_start_done(void) = 0; @@ -522,11 +526,22 @@ class omx_video: public qc_omx_component inline void omx_report_error () { if (m_pCallbacks.EventHandler && !m_error_propogated) { m_error_propogated = true; + DEBUG_PRINT_ERROR("ERROR: send OMX_ErrorHardware to Client"); m_pCallbacks.EventHandler(&m_cmp,m_app_data, OMX_EventError,OMX_ErrorHardware,0,NULL); } } + inline void omx_report_hw_overload () + { + if (m_pCallbacks.EventHandler && !m_error_propogated) { + m_error_propogated = true; + DEBUG_PRINT_ERROR("ERROR: send OMX_ErrorInsufficientResources to Client"); + m_pCallbacks.EventHandler(&m_cmp, m_app_data, + OMX_EventError, OMX_ErrorInsufficientResources, 0, NULL); + } + } + inline void omx_report_unsupported_setting () { if (m_pCallbacks.EventHandler && !m_error_propogated) { m_error_propogated = true; @@ -575,6 +590,7 @@ class omx_video: public qc_omx_component OMX_VIDEO_PARAM_H263TYPE m_sParamH263; OMX_VIDEO_PARAM_AVCTYPE m_sParamAVC; OMX_VIDEO_PARAM_VP8TYPE m_sParamVP8; + OMX_VIDEO_PARAM_HEVCTYPE m_sParamHEVC; OMX_PORT_PARAM_TYPE m_sPortParam_img; OMX_PORT_PARAM_TYPE m_sPortParam_audio; OMX_VIDEO_CONFIG_BITRATETYPE m_sConfigBitrate; @@ -623,11 +639,11 @@ class omx_video: public qc_omx_component int pending_input_buffers; int pending_output_buffers; - unsigned int m_out_bm_count; - unsigned int m_inp_bm_count; - unsigned int m_flags; - unsigned int m_etb_count; - unsigned int m_fbd_count; + uint64_t m_out_bm_count; + uint64_t m_inp_bm_count; + uint64_t m_flags; + uint64_t m_etb_count; + uint64_t m_fbd_count; #ifdef _ANDROID_ // Heap pointer to frame buffers sp<MemoryHeapBase> m_heap_ptr; @@ -636,6 +652,7 @@ class omx_video: public qc_omx_component bool m_event_port_settings_sent; OMX_U8 m_cRole[OMX_MAX_STRINGNAME_SIZE]; extra_data_handler extra_data_handle; + bool hw_overload; }; 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 0d9c2ff..d7b21db 100755..100644 --- a/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h +++ b/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h @@ -78,7 +78,7 @@ class omx_venc: public omx_video 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(); - bool dev_get_seq_hdr(void *, unsigned, OMX_U32 *); + bool dev_get_seq_hdr(void *, unsigned, unsigned *); bool dev_loaded_start(void); bool dev_loaded_stop(void); bool dev_loaded_start_done(void); diff --git a/mm-video-v4l2/vidc/venc/inc/video_encoder_device.h b/mm-video-v4l2/vidc/venc/inc/video_encoder_device.h index 1289237..fde041d 100755..100644 --- a/mm-video-v4l2/vidc/venc/inc/video_encoder_device.h +++ b/mm-video-v4l2/vidc/venc/inc/video_encoder_device.h @@ -73,7 +73,7 @@ class venc_dev bool venc_set_config(void *configData, OMX_INDEXTYPE index); bool venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel); bool venc_max_allowed_bitrate_check(OMX_U32 nTargetBitrate); - bool venc_get_seq_hdr(void *, unsigned, OMX_U32 *); + bool venc_get_seq_hdr(void *, unsigned, unsigned *); bool venc_loaded_start(void); bool venc_loaded_stop(void); bool venc_loaded_start_done(void); 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 64482bf..e2bdaf7 100755..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 @@ -38,14 +38,18 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "omx_video_base.h" #include "omx_video_encoder.h" #include <linux/videodev2.h> -#include <linux/fb.h> #include <poll.h> -#include <gui/ISurfaceComposer.h> -#include <gui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> #define TIMEOUT 5*60*1000 +#define BIT(num) (1 << (num)) +#define MAX_HYB_HIERP_LAYERS 6 +enum hier_type { + HIER_NONE = 0x0, + HIER_P = 0x1, + HIER_B = 0x2, + HIER_P_HYBRID = 0x3, +}; struct msm_venc_switch { unsigned char status; @@ -187,6 +191,7 @@ struct msm_venc_slice_delivery { struct msm_venc_hierlayers { unsigned int numlayers; + enum hier_type hier_mode; }; struct msm_venc_ltrinfo { @@ -206,6 +211,14 @@ struct msm_venc_peak_bitrate { unsigned int peakbitrate; }; +struct msm_venc_vpx_error_resilience { + unsigned int enable; +}; + +struct msm_venc_priority { + OMX_U32 priority; +}; + enum v4l2_ports { CAPTURE_PORT, OUTPUT_PORT, @@ -223,6 +236,15 @@ struct extradata_buffer_info { #endif }; +enum rc_modes { + RC_VBR_VFR = BIT(0), + RC_VBR_CFR = BIT(1), + RC_CBR_VFR = BIT(2), + RC_CBR_CFR = BIT(3), + RC_ALL = (RC_VBR_VFR | RC_VBR_CFR + | RC_CBR_VFR | RC_CBR_CFR) +}; + class venc_dev { public: @@ -255,7 +277,7 @@ class venc_dev bool venc_set_param(void *,OMX_INDEXTYPE); bool venc_set_config(void *configData, OMX_INDEXTYPE index); bool venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel); - bool venc_get_seq_hdr(void *, unsigned, OMX_U32 *); + bool venc_get_seq_hdr(void *, unsigned, unsigned *); bool venc_loaded_start(void); bool venc_loaded_stop(void); bool venc_loaded_start_done(void); @@ -302,6 +324,7 @@ class venc_dev bool handle_extradata(void *, int); int venc_set_format(int); bool deinterlace_enabled; + bool hw_overload; private: OMX_U32 m_codec; struct msm_venc_basecfg m_sVenc_cfg; @@ -327,10 +350,14 @@ class venc_dev struct msm_venc_video_capability capability; struct msm_venc_idrperiod idrperiod; struct msm_venc_slice_delivery slice_mode; - struct msm_venc_hierlayers hier_p_layers; + struct msm_venc_hierlayers hier_layers; struct msm_venc_perf_level performance_level; struct msm_venc_vui_timing_info vui_timing_info; struct msm_venc_peak_bitrate peak_bitrate; + struct msm_venc_ltrinfo ltrinfo; + struct msm_venc_vpx_error_resilience vpx_err_resilience; + struct msm_venc_priority sess_priority; + OMX_U32 operating_rate; bool venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel); bool venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames); @@ -356,9 +383,9 @@ class venc_dev bool venc_set_vpe_rotation(OMX_S32 rotation_angle); bool venc_set_deinterlace(OMX_U32 enable); bool venc_set_ltrmode(OMX_U32 enable, OMX_U32 count); - bool venc_set_useltr(); - bool venc_set_markltr(); bool venc_enable_initial_qp(QOMX_EXTNINDEX_VIDEO_INITIALQP* initqp); + bool venc_set_useltr(OMX_U32 frameIdx); + bool venc_set_markltr(OMX_U32 frameIdx); bool venc_set_inband_video_header(OMX_BOOL enable); bool venc_set_au_delimiter(OMX_BOOL enable); bool venc_set_hier_layers(QOMX_VIDEO_HIERARCHICALCODINGTYPE type, OMX_U32 num_layers); @@ -366,6 +393,13 @@ class venc_dev bool venc_set_vui_timing_info(OMX_BOOL enable); bool venc_set_peak_bitrate(OMX_U32 nPeakBitrate); bool venc_set_searchrange(); + bool venc_set_vpx_error_resilience(OMX_BOOL enable); + bool venc_set_perf_mode(OMX_U32 mode); + bool venc_set_hybrid_hierp(OMX_U32 layers); + bool venc_calibrate_gop(); + bool venc_validate_hybridhp_params(OMX_U32 layers, OMX_U32 bFrames, OMX_U32 count, int mode); + bool venc_set_session_priority(OMX_U32 priority); + bool venc_set_operatingrate(OMX_U32 rate); #ifdef MAX_RES_1080P OMX_U32 pmem_free(); @@ -392,7 +426,8 @@ class venc_dev int color_format; bool is_searchrange_set; bool enable_mv_narrow_searchrange; - DisplayInfo display_info; + int supported_rc_modes; + bool camera_mode_enabled; }; enum instance_state { 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 0cf76d9..52a9313 100755..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-2014, 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: @@ -38,6 +38,8 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Include Files ////////////////////////////////////////////////////////////////////////////// +#define __STDC_FORMAT_MACROS //enables the format specifiers in inttypes.h +#include <inttypes.h> #include <string.h> #include "omx_video_base.h" #include <stdlib.h> @@ -78,10 +80,11 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define SZ_4K 0x1000 #define SZ_1M 0x100000 -#define SECURE_BUFPTR 0xDEADBEEF typedef struct OMXComponentCapabilityFlagsType { ////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; OMX_BOOL iIsOMXComponentMultiThreaded; OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc; OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc; @@ -210,11 +213,12 @@ VideoHeap::VideoHeap(int fd, size_t size, void* base) ========================================================================== */ omx_video::omx_video(): c2d_opened(false), - mUsesColorConversion(false), psource_frame(NULL), pdest_frame(NULL), secure_session(false), mEmptyEosBuffer(NULL), + m_pipe_in(-1), + m_pipe_out(-1), m_pInput_pmem(NULL), m_pOutput_pmem(NULL), #ifdef USE_ION @@ -240,7 +244,8 @@ omx_video::omx_video(): m_flags(0), m_etb_count(0), m_fbd_count(0), - m_event_port_settings_sent(false) + m_event_port_settings_sent(false), + hw_overload(false) { DEBUG_PRINT_HIGH("omx_video(): Inside Constructor()"); memset(&m_cmp,0,sizeof(m_cmp)); @@ -248,8 +253,10 @@ omx_video::omx_video(): async_thread_created = false; msg_thread_created = false; + mUsesColorConversion = false; pthread_mutex_init(&m_lock, NULL); sem_init(&m_cmd_lock,0,0); + DEBUG_PRINT_LOW("meta_buffer_hdr = %p", meta_buffer_hdr); } @@ -269,8 +276,8 @@ omx_video::omx_video(): omx_video::~omx_video() { DEBUG_PRINT_HIGH("~omx_video(): Inside Destructor()"); - if (m_pipe_in) close(m_pipe_in); - if (m_pipe_out) close(m_pipe_out); + if (m_pipe_in >= 0) close(m_pipe_in); + if (m_pipe_out >= 0) close(m_pipe_out); DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit"); if (msg_thread_created) pthread_join(msg_thread_id,NULL); @@ -283,10 +290,10 @@ omx_video::~omx_video() #endif pthread_mutex_destroy(&m_lock); sem_destroy(&m_cmd_lock); - DEBUG_PRINT_HIGH("m_etb_count = %u, m_fbd_count = %u", m_etb_count, + DEBUG_PRINT_HIGH("m_etb_count = %" PRIu64 ", m_fbd_count = %" PRIu64, m_etb_count, m_fbd_count); DEBUG_PRINT_HIGH("omx_video: Destructor exit"); - DEBUG_PRINT_HIGH("Exiting 7x30 OMX Video Encoder ..."); + DEBUG_PRINT_HIGH("Exiting OMX Video Encoder ..."); } /* ====================================================================== @@ -405,13 +412,18 @@ void omx_video::process_event_cb(void *ctxt, unsigned char id) pThis->omx_report_error (); } break; - case OMX_COMPONENT_GENERATE_ETB: + case OMX_COMPONENT_GENERATE_ETB: { + OMX_ERRORTYPE iret; DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB"); - if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ - (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { - DEBUG_PRINT_ERROR("ERROR: ETBProxy() failed!"); + iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2); + if (iret == OMX_ErrorInsufficientResources) { + DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload"); + pThis->omx_report_hw_overload (); + } else if (iret != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure"); pThis->omx_report_error (); } + } break; case OMX_COMPONENT_GENERATE_FTB: @@ -446,7 +458,7 @@ void omx_video::process_event_cb(void *ctxt, unsigned char id) case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: pThis->input_flush_progress = false; - DEBUG_PRINT_HIGH("m_etb_count at i/p flush = %u", m_etb_count); + DEBUG_PRINT_HIGH("m_etb_count at i/p flush = %" PRIu64, m_etb_count); m_etb_count = 0; if (pThis->m_pCallbacks.EventHandler) { /*Check if we need generate event for Flush done*/ @@ -473,7 +485,7 @@ void omx_video::process_event_cb(void *ctxt, unsigned char id) case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: pThis->output_flush_progress = false; - DEBUG_PRINT_HIGH("m_fbd_count at o/p flush = %u", m_fbd_count); + DEBUG_PRINT_HIGH("m_fbd_count at o/p flush = %" PRIu64, m_fbd_count); m_fbd_count = 0; if (pThis->m_pCallbacks.EventHandler) { /*Check if we need generate event for Flush done*/ @@ -526,7 +538,7 @@ void omx_video::process_event_cb(void *ctxt, unsigned char id) } BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_START_PENDING); } else { - DEBUG_PRINT_LOW("ERROR: unknown flags=%x",pThis->m_flags); + DEBUG_PRINT_LOW("ERROR: unknown flags=%" PRIx64, pThis->m_flags); } } else { DEBUG_PRINT_LOW("Event Handler callback is NULL"); @@ -586,7 +598,7 @@ void omx_video::process_event_cb(void *ctxt, unsigned char id) } BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_STOP_PENDING); } else { - DEBUG_PRINT_LOW("ERROR: unknown flags=%x",pThis->m_flags); + DEBUG_PRINT_LOW("ERROR: unknown flags=%" PRIx64, pThis->m_flags); } } @@ -1432,6 +1444,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, switch ((int)paramIndex) { case OMX_IndexParamPortDefinition: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE); OMX_PARAM_PORTDEFINITIONTYPE *portDefn; portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; @@ -1455,10 +1468,12 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } #endif } else if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { + if (m_state != OMX_StateExecuting) { dev_get_buf_req (&m_sOutPortDef.nBufferCountMin, &m_sOutPortDef.nBufferCountActual, &m_sOutPortDef.nBufferSize, m_sOutPortDef.nPortIndex); + } DEBUG_PRINT_LOW("m_sOutPortDef: size = %u, min cnt = %u, actual cnt = %u", (unsigned int)m_sOutPortDef.nBufferSize, (unsigned int)m_sOutPortDef.nBufferCountMin, (unsigned int)m_sOutPortDef.nBufferCountActual); @@ -1471,6 +1486,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoInit: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); OMX_PORT_PARAM_TYPE *portParamType = (OMX_PORT_PARAM_TYPE *) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit"); @@ -1480,6 +1496,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoPortFormat: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE); OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat"); @@ -1497,7 +1514,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, [2] = OMX_COLOR_FormatYUV420SemiPlanar, }; - if (index >= sizeof(supportedFormats)/sizeof(*supportedFormats)) + if (index > (sizeof(supportedFormats)/sizeof(*supportedFormats) - 1)) eRet = OMX_ErrorNoMore; else { memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat)); @@ -1514,6 +1531,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoBitrate: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_BITRATETYPE); OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate"); @@ -1528,6 +1546,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoMpeg4: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_MPEG4TYPE); OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4"); memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4)); @@ -1535,6 +1554,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoH263: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_H263TYPE); OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263"); memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263)); @@ -1542,6 +1562,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoAvc: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_AVCTYPE); OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc"); memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC)); @@ -1549,13 +1570,23 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case (OMX_INDEXTYPE)OMX_IndexParamVideoVp8: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_VP8TYPE); OMX_VIDEO_PARAM_VP8TYPE* pParam = (OMX_VIDEO_PARAM_VP8TYPE*)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoVp8"); memcpy(pParam, &m_sParamVP8, sizeof(m_sParamVP8)); break; } + case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc: + { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_HEVCTYPE); + OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoHevc"); + memcpy(pParam, &m_sParamHEVC, sizeof(m_sParamHEVC)); + break; + } case OMX_IndexParamVideoProfileLevelQuerySupported: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported"); eRet = get_supported_profile_level(pParam); @@ -1566,6 +1597,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoProfileLevelCurrent: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent"); memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel)); @@ -1574,6 +1606,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, /*Component should support this port definition*/ case OMX_IndexParamAudioInit: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit"); memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio)); @@ -1582,6 +1615,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, /*Component should support this port definition*/ case OMX_IndexParamImageInit: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit"); memcpy(imagePortParamType, &m_sPortParam_img, sizeof(m_sPortParam_img)); @@ -1597,24 +1631,20 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamStandardComponentRole: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE); OMX_PARAM_COMPONENTROLETYPE *comp_role; comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; comp_role->nVersion.nVersion = OMX_SPEC_VERSION; comp_role->nSize = sizeof(*comp_role); DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",paramIndex); - if (NULL != comp_role->cRole) { - strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE); - } else { - DEBUG_PRINT_ERROR("ERROR: Getparameter: OMX_IndexParamStandardComponentRole %d is passed with NULL parameter for role",paramIndex); - eRet =OMX_ErrorBadParameter; - } + strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE); break; } /* Added for parameter test */ case OMX_IndexParamPriorityMgmt: { - + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE); OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt"); memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt)); @@ -1623,6 +1653,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, /* Added for parameter test */ case OMX_IndexParamCompBufferSupplier: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE); OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier"); if (bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_IN) { @@ -1638,6 +1669,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_IndexParamVideoQuantization: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_QUANTIZATIONTYPE); OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization"); memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization)); @@ -1646,6 +1678,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_QcomIndexParamVideoQPRange: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_QPRANGETYPE); OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *qp_range = (OMX_QCOM_VIDEO_PARAM_QPRANGETYPE*) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoQPRange"); memcpy(qp_range, &m_sSessionQPRange, sizeof(m_sSessionQPRange)); @@ -1654,6 +1687,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_IndexParamVideoErrorCorrection: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE); OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* errorresilience = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData; DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection"); errorresilience->bEnableHEC = m_sErrorCorrection.bEnableHEC; @@ -1663,6 +1697,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoIntraRefresh: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_INTRAREFRESHTYPE); OMX_VIDEO_PARAM_INTRAREFRESHTYPE* intrarefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData; DEBUG_PRINT_LOW("OMX_IndexParamVideoIntraRefresh"); DEBUG_PRINT_ERROR("OMX_IndexParamVideoIntraRefresh GET"); @@ -1675,6 +1710,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, break; case OMX_COMPONENT_CAPABILITY_TYPE_INDEX: { + VALIDATE_OMX_PARAM_DATA(paramData, OMXComponentCapabilityFlagsType); OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(paramData); DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX"); pParam->iIsOMXComponentMultiThreaded = OMX_TRUE; @@ -1692,6 +1728,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, #if !defined(MAX_RES_720P) || defined(_MSM8974_) case OMX_QcomIndexParamIndexExtraDataType: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE); DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamIndexExtraDataType"); QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData; if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderSliceInfo) { @@ -1737,6 +1774,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case QOMX_IndexParamVideoLTRCountRangeSupported: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_RANGETYPE); DEBUG_PRINT_HIGH("get_parameter: QOMX_IndexParamVideoLTRCountRangeSupported"); QOMX_EXTNINDEX_RANGETYPE *pParam = (QOMX_EXTNINDEX_RANGETYPE *)paramData; if (pParam->nPortIndex == PORT_INDEX_OUT) { @@ -1755,9 +1793,19 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } } break; + case OMX_QcomIndexParamVideoLTRCount: + { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE); + DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoLTRCount"); + OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE *pParam = + reinterpret_cast<OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE*>(paramData); + memcpy(pParam, &m_sParamLTRCount, sizeof(m_sParamLTRCount)); + break; + } #endif case QOMX_IndexParamVideoSyntaxHdr: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_PARAMTYPE); DEBUG_PRINT_HIGH("QOMX_IndexParamVideoSyntaxHdr"); QOMX_EXTNINDEX_PARAMTYPE* pParam = reinterpret_cast<QOMX_EXTNINDEX_PARAMTYPE*>(paramData); @@ -1781,7 +1829,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } if (dev_get_seq_hdr(pParam->pData, (unsigned)(pParam->nSize - sizeof(QOMX_EXTNINDEX_PARAMTYPE)), - (OMX_U32 *)(void *)&pParam->nDataSize)) { + (unsigned *)(void *)&pParam->nDataSize)) { DEBUG_PRINT_HIGH("get syntax header successful (hdrlen = %u)", (unsigned int)pParam->nDataSize); for (unsigned i = 0; i < pParam->nDataSize; i++) { @@ -1803,6 +1851,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexHierarchicalStructure: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_HIERARCHICALLAYERS); QOMX_VIDEO_HIERARCHICALLAYERS* hierp = (QOMX_VIDEO_HIERARCHICALLAYERS*) paramData; DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexHierarchicalStructure"); memcpy(hierp, &m_sHierLayers, sizeof(m_sHierLayers)); @@ -1810,6 +1859,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamPerfLevel: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PERF_LEVEL); OMX_U32 perflevel; OMX_QCOM_VIDEO_PARAM_PERF_LEVEL *pParam = reinterpret_cast<OMX_QCOM_VIDEO_PARAM_PERF_LEVEL*>(paramData); @@ -1824,6 +1874,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamH264VUITimingInfo: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO); OMX_U32 enabled; OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *pParam = reinterpret_cast<OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO*>(paramData); @@ -1838,6 +1889,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamPeakBitrate: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE); OMX_U32 peakbitrate; OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE *pParam = reinterpret_cast<OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE*>(paramData); @@ -1852,6 +1904,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, } case QOMX_IndexParamVideoInitialQp: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_INITIALQP); QOMX_EXTNINDEX_VIDEO_INITIALQP* initqp = reinterpret_cast<QOMX_EXTNINDEX_VIDEO_INITIALQP *>(paramData); memcpy(initqp, &m_sParamInitqp, sizeof(m_sParamInitqp)); @@ -1911,18 +1964,21 @@ OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, switch ((int)configIndex) { case OMX_IndexConfigVideoBitrate: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_BITRATETYPE); OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData); memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate)); break; } case OMX_IndexConfigVideoFramerate: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_FRAMERATETYPE); OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData); memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate)); break; } case OMX_IndexConfigCommonRotate: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ROTATIONTYPE); OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData); memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation)); break; @@ -1930,12 +1986,14 @@ OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, case QOMX_IndexConfigVideoIntraperiod: { DEBUG_PRINT_LOW("get_config:QOMX_IndexConfigVideoIntraperiod"); + VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_INTRAPERIODTYPE); QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(configData); memcpy(pParam, &m_sIntraperiod, sizeof(m_sIntraperiod)); break; } case OMX_IndexConfigVideoAVCIntraPeriod: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_AVCINTRAPERIOD); OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pParam = reinterpret_cast<OMX_VIDEO_CONFIG_AVCINTRAPERIOD*>(configData); DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoAVCIntraPeriod"); @@ -1944,6 +2002,7 @@ OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexConfigCommonDeinterlace: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_DEINTERLACE); OMX_VIDEO_CONFIG_DEINTERLACE *pParam = reinterpret_cast<OMX_VIDEO_CONFIG_DEINTERLACE*>(configData); DEBUG_PRINT_LOW("get_config: OMX_IndexConfigCommonDeinterlace"); @@ -1952,12 +2011,28 @@ OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexConfigVideoVp8ReferenceFrame: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_VP8REFERENCEFRAMETYPE); OMX_VIDEO_VP8REFERENCEFRAMETYPE* pParam = reinterpret_cast<OMX_VIDEO_VP8REFERENCEFRAMETYPE*>(configData); DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoVp8ReferenceFrame"); memcpy(pParam, &m_sConfigVp8ReferenceFrame, sizeof(m_sConfigVp8ReferenceFrame)); break; } + case OMX_QcomIndexConfigPerfLevel: + { + VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL); + OMX_U32 perflevel; + OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *pParam = + reinterpret_cast<OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL*>(configData); + DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigPerfLevel"); + if (!dev_get_performance_level(&perflevel)) { + DEBUG_PRINT_ERROR("Invalid entry returned from get_performance_level %d", + pParam->ePerfLevel); + } else { + pParam->ePerfLevel = (QOMX_VIDEO_PERF_LEVEL)perflevel; + } + break; + } default: DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); return OMX_ErrorUnsupportedIndex; @@ -2101,6 +2176,7 @@ OMX_ERRORTYPE omx_video::use_input_buffer( DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_inp_mem_ptr"); return OMX_ErrorInsufficientResources; } + DEBUG_PRINT_LOW("Successfully allocated m_inp_mem_ptr = %p", m_inp_mem_ptr); m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); @@ -2175,7 +2251,7 @@ OMX_ERRORTYPE omx_video::use_input_buffer( m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; m_pInput_pmem[i].offset = 0; - m_pInput_pmem[i].buffer = (OMX_U8 *)SECURE_BUFPTR; + m_pInput_pmem[i].buffer = NULL; if(!secure_session) { m_pInput_pmem[i].buffer = (unsigned char *)mmap( NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE, @@ -2183,6 +2259,7 @@ OMX_ERRORTYPE omx_video::use_input_buffer( if (m_pInput_pmem[i].buffer == MAP_FAILED) { DEBUG_PRINT_ERROR("ERROR: mmap() Failed"); + m_pInput_pmem[i].buffer = NULL; close(m_pInput_pmem[i].fd); #ifdef USE_ION free_ion_memory(&m_pInput_ion[i]); @@ -2332,7 +2409,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 @@ -2367,7 +2443,7 @@ OMX_ERRORTYPE omx_video::use_output_buffer( m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; m_pOutput_pmem[i].offset = 0; - m_pOutput_pmem[i].buffer = (OMX_U8 *)SECURE_BUFPTR; + m_pOutput_pmem[i].buffer = NULL; if(!secure_session) { #ifdef _MSM8974_ m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL, @@ -2380,6 +2456,7 @@ OMX_ERRORTYPE omx_video::use_output_buffer( #endif if (m_pOutput_pmem[i].buffer == MAP_FAILED) { DEBUG_PRINT_ERROR("ERROR: mmap() Failed"); + m_pOutput_pmem[i].buffer = NULL; close(m_pOutput_pmem[i].fd); #ifdef USE_ION free_ion_memory(&m_pOutput_ion[i]); @@ -2410,6 +2487,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); @@ -2497,7 +2576,7 @@ OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) return OMX_ErrorBadParameter; } - index = bufferHdr - ((!mUseProxyColorFormat)?m_inp_mem_ptr:meta_buffer_hdr); + index = bufferHdr - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr); #ifdef _ANDROID_ICS_ if (meta_mode_enable) { if (index < m_sInPortDef.nBufferCountActual) { @@ -2518,6 +2597,8 @@ OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) } if (index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) { + auto_lock l(m_lock); + if (m_pInput_pmem[index].fd > 0 && input_use_buffer == false) { DEBUG_PRINT_LOW("FreeBuffer:: i/p AllocateBuffer case"); if(!secure_session) { @@ -2525,6 +2606,7 @@ OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) } else { free(m_pInput_pmem[index].buffer); } + m_pInput_pmem[index].buffer = NULL; close (m_pInput_pmem[index].fd); #ifdef USE_ION free_ion_memory(&m_pInput_ion[index]); @@ -2537,7 +2619,8 @@ OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) DEBUG_PRINT_ERROR("ERROR: dev_free_buf() Failed for i/p buf"); } if(!secure_session) { - munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); + munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); + m_pInput_pmem[index].buffer = NULL; } close (m_pInput_pmem[index].fd); #ifdef USE_ION @@ -2576,7 +2659,8 @@ OMX_ERRORTYPE omx_video::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) m_pOutput_pmem[index].size); } else { char *data = (char*) m_pOutput_pmem[index].buffer; - native_handle_t *handle = (native_handle_t*) data + 4; + native_handle_t *handle = NULL; + memcpy(&handle, data + sizeof(OMX_U32), sizeof(native_handle_t*)); native_handle_delete(handle); free(m_pOutput_pmem[index].buffer); } @@ -2620,8 +2704,11 @@ OMX_ERRORTYPE omx_video::allocate_input_meta_buffer( return OMX_ErrorBadParameter; } - if (!m_inp_mem_ptr && !mUseProxyColorFormat) + if (!m_inp_mem_ptr && !mUseProxyColorFormat) { m_inp_mem_ptr = meta_buffer_hdr; + DEBUG_PRINT_LOW("use meta_buffer_hdr (%p) as m_inp_mem_ptr = %p", + meta_buffer_hdr, m_inp_mem_ptr); + } for (index = 0; ((index < m_sInPortDef.nBufferCountActual) && meta_buffer_hdr[index].pBuffer); index++); if (index == m_sInPortDef.nBufferCountActual) { @@ -2697,6 +2784,7 @@ OMX_ERRORTYPE omx_video::allocate_input_buffer( return OMX_ErrorInsufficientResources; } + DEBUG_PRINT_LOW("Successfully allocated m_inp_mem_ptr = %p", m_inp_mem_ptr); m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); if (m_pInput_pmem == NULL) { @@ -2767,13 +2855,14 @@ OMX_ERRORTYPE omx_video::allocate_input_buffer( m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; m_pInput_pmem[i].offset = 0; - m_pInput_pmem[i].buffer = (OMX_U8 *)SECURE_BUFPTR; + m_pInput_pmem[i].buffer = NULL; if(!secure_session) { m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL, m_pInput_pmem[i].size,PROT_READ|PROT_WRITE, MAP_SHARED,m_pInput_pmem[i].fd,0); if (m_pInput_pmem[i].buffer == MAP_FAILED) { DEBUG_PRINT_ERROR("ERROR: mmap FAILED= %d", errno); + m_pInput_pmem[i].buffer = NULL; close(m_pInput_pmem[i].fd); #ifdef USE_ION free_ion_memory(&m_pInput_ion[i]); @@ -2784,6 +2873,11 @@ OMX_ERRORTYPE omx_video::allocate_input_buffer( //This should only be used for passing reference to source type and //secure handle fd struct native_handle_t* m_pInput_pmem[i].buffer = malloc(sizeof(OMX_U32) + sizeof(native_handle_t*)); + if (m_pInput_pmem[i].buffer == NULL) { + DEBUG_PRINT_ERROR("%s: failed to allocate native-handle", __func__); + return OMX_ErrorInsufficientResources; + } + (*bufferHdr)->nAllocLen = sizeof(OMX_U32) + sizeof(native_handle_t*); } (*bufferHdr)->pBuffer = (OMX_U8 *)m_pInput_pmem[i].buffer; @@ -2902,7 +2996,7 @@ OMX_ERRORTYPE omx_video::allocate_output_buffer( align_size = ((m_sOutPortDef.nBufferSize + 4095)/4096) * 4096; m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(align_size, &m_pOutput_ion[i].ion_alloc_data, - &m_pOutput_ion[i].fd_ion_data,0); + &m_pOutput_ion[i].fd_ion_data, ION_FLAG_CACHED); #else m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sOutPortDef.nBufferSize, &m_pOutput_ion[i].ion_alloc_data, @@ -2928,7 +3022,7 @@ OMX_ERRORTYPE omx_video::allocate_output_buffer( m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; m_pOutput_pmem[i].offset = 0; - m_pOutput_pmem[i].buffer = (OMX_U8 *)SECURE_BUFPTR; + m_pOutput_pmem[i].buffer = NULL; if(!secure_session) { #ifdef _MSM8974_ m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL, @@ -2941,6 +3035,7 @@ OMX_ERRORTYPE omx_video::allocate_output_buffer( #endif if (m_pOutput_pmem[i].buffer == MAP_FAILED) { DEBUG_PRINT_ERROR("ERROR: MMAP_FAILED in o/p alloc buffer"); + m_pOutput_pmem[i].buffer = NULL; close (m_pOutput_pmem[i].fd); #ifdef USE_ION free_ion_memory(&m_pOutput_ion[i]); @@ -2952,12 +3047,17 @@ OMX_ERRORTYPE omx_video::allocate_output_buffer( //This should only be used for passing reference to source type and //secure handle fd struct native_handle_t* m_pOutput_pmem[i].buffer = malloc(sizeof(OMX_U32) + sizeof(native_handle_t*)); + if (m_pOutput_pmem[i].buffer == NULL) { + DEBUG_PRINT_ERROR("%s: Failed to allocate native-handle", __func__); + return OMX_ErrorInsufficientResources; + } + (*bufferHdr)->nAllocLen = sizeof(OMX_U32) + sizeof(native_handle_t*); native_handle_t *handle = native_handle_create(1, 0); handle->data[0] = m_pOutput_pmem[i].fd; char *data = (char*) m_pOutput_pmem[i].buffer; OMX_U32 type = 1; - memcpy(data, &type, 4); - memcpy(data + 4, &handle, sizeof(native_handle_t*)); + memcpy(data, &type, sizeof(OMX_U32)); + memcpy(data + sizeof(OMX_U32), &handle, sizeof(native_handle_t*)); } *bufferHdr = (m_out_mem_ptr + i ); @@ -3102,28 +3202,27 @@ OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp, if (port == PORT_INDEX_IN) { // check if the buffer is valid - nPortIndex = buffer - ((!mUseProxyColorFormat)?m_inp_mem_ptr:meta_buffer_hdr); + nPortIndex = buffer - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr); 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); m_sInPortDef.bPopulated = OMX_FALSE; /*Free the Buffer Header*/ - if (release_input_done() -#ifdef _ANDROID_ICS_ - && !meta_mode_enable -#endif - ) { + if (release_input_done()) { input_use_buffer = false; - if (m_inp_mem_ptr) { + // "m_inp_mem_ptr" may point to "meta_buffer_hdr" in some modes, + // in which case, it was not explicitly allocated + if (m_inp_mem_ptr && m_inp_mem_ptr != meta_buffer_hdr) { DEBUG_PRINT_LOW("Freeing m_inp_mem_ptr"); free (m_inp_mem_ptr); - m_inp_mem_ptr = NULL; } + m_inp_mem_ptr = NULL; if (m_pInput_pmem) { DEBUG_PRINT_LOW("Freeing m_pInput_pmem"); free(m_pInput_pmem); @@ -3156,7 +3255,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; @@ -3212,7 +3312,7 @@ OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp, post_event(OMX_CommandStateSet, OMX_StateLoaded, OMX_COMPONENT_GENERATE_EVENT); } else { - DEBUG_PRINT_HIGH("in free buffer, release not done, need to free more buffers input 0x%x output 0x%x", + DEBUG_PRINT_HIGH("in free buffer, release not done, need to free more buffers input %" PRIx64" output %" PRIx64, m_out_bm_count, m_inp_bm_count); } } @@ -3243,7 +3343,9 @@ OMX_ERRORTYPE omx_video::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, unsigned int nBufferIndex ; DEBUG_PRINT_LOW("ETB: buffer = %p, buffer->pBuffer[%p]", buffer, buffer->pBuffer); - if (m_state == OMX_StateInvalid) { + if (m_state != OMX_StateExecuting && + m_state != OMX_StatePause && + m_state != OMX_StateIdle) { DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State"); return OMX_ErrorInvalidState; } @@ -3267,7 +3369,7 @@ OMX_ERRORTYPE omx_video::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, return OMX_ErrorIncorrectStateOperation; } - nBufferIndex = buffer - ((!mUseProxyColorFormat)?m_inp_mem_ptr:meta_buffer_hdr); + nBufferIndex = buffer - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr); if (nBufferIndex > m_sInPortDef.nBufferCountActual ) { DEBUG_PRINT_ERROR("ERROR: ETB: Invalid buffer index[%d]", nBufferIndex); @@ -3367,6 +3469,10 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, if (meta_mode_enable && !mUseProxyColorFormat) { // Camera or Gralloc-source meta-buffers queued with pre-announced color-format struct pmem Input_pmem_info; + if (!media_buffer) { + DEBUG_PRINT_ERROR("%s: invalid media_buffer",__FUNCTION__); + return OMX_ErrorBadParameter; + } if (media_buffer->buffer_type == kMetadataBufferTypeCameraSource) { Input_pmem_info.buffer = media_buffer; Input_pmem_info.fd = media_buffer->meta_handle->data[0]; @@ -3415,9 +3521,13 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, #endif { DEBUG_PRINT_LOW("Heap UseBuffer case, so memcpy the data"); + + auto_lock l(m_lock); pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer; - memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset), - buffer->nFilledLen); + if (pmem_data_buf) { + memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset), + buffer->nFilledLen); + } DEBUG_PRINT_LOW("memcpy() done in ETBProxy for i/p Heap UseBuf"); } else if (mUseProxyColorFormat) { // Gralloc-source buffers with color-conversion @@ -3449,6 +3559,9 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD); /*Generate an async error and move to invalid state*/ pending_input_buffers--; + if (hw_overload) { + return OMX_ErrorInsufficientResources; + } return OMX_ErrorBadParameter; } return ret; @@ -3473,7 +3586,9 @@ OMX_ERRORTYPE omx_video::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_IN OMX_BUFFERHEADERTYPE* buffer) { DEBUG_PRINT_LOW("FTB: buffer->pBuffer[%p]", buffer->pBuffer); - if (m_state == OMX_StateInvalid) { + if (m_state != OMX_StateExecuting && + m_state != OMX_StatePause && + m_state != OMX_StateIdle) { DEBUG_PRINT_ERROR("ERROR: FTB in Invalid State"); return OMX_ErrorInvalidState; } @@ -3694,6 +3809,16 @@ OMX_ERRORTYPE omx_video::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, } } #endif + else if ((!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE)) || + (!strncmp((char*)m_nkind, "OMX.qti.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE))) { + if ((0 == index) && role) { + strlcpy((char *)role, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s", role); + } else { + DEBUG_PRINT_ERROR("ERROR: No more roles"); + eRet = OMX_ErrorNoMore; + } + } else { DEBUG_PRINT_ERROR("ERROR: Querying Role on Unknown Component"); eRet = OMX_ErrorInvalidComponentName; @@ -3961,22 +4086,20 @@ OMX_ERRORTYPE omx_video::empty_buffer_done(OMX_HANDLETYPE hComp, OMX_BUFFERHEADERTYPE* buffer) { int buffer_index = -1; - int buffer_index_meta = -1; - buffer_index = (buffer - m_inp_mem_ptr); - buffer_index_meta = (buffer - meta_buffer_hdr); + buffer_index = buffer - ((mUseProxyColorFormat && !mUsesColorConversion) ? meta_buffer_hdr : m_inp_mem_ptr); DEBUG_PRINT_LOW("empty_buffer_done: buffer[%p]", buffer); if (buffer == NULL || - ((buffer_index > (int)m_sInPortDef.nBufferCountActual) && - (buffer_index_meta > (int)m_sInPortDef.nBufferCountActual))) { + ((buffer_index > (int)m_sInPortDef.nBufferCountActual))) { DEBUG_PRINT_ERROR("ERROR in empty_buffer_done due to index buffer"); return OMX_ErrorBadParameter; } pending_input_buffers--; - if (mUseProxyColorFormat && ((OMX_U32)buffer_index < m_sInPortDef.nBufferCountActual)) { - if (!pdest_frame && !input_flush_progress) { + if (mUseProxyColorFormat && + (buffer_index >= 0 && (buffer_index < (int)m_sInPortDef.nBufferCountActual))) { + if (!pdest_frame && !input_flush_progress && mUsesColorConversion) { pdest_frame = buffer; DEBUG_PRINT_LOW("empty_buffer_done pdest_frame address is %p",pdest_frame); return push_input_buffer(hComp); @@ -3997,10 +4120,9 @@ OMX_ERRORTYPE omx_video::empty_buffer_done(OMX_HANDLETYPE hComp, } else { // We are not dealing with color-conversion, Buffer being returned // here is client's buffer, return it back to client - OMX_BUFFERHEADERTYPE* il_buffer = &meta_buffer_hdr[buffer_index]; - if (m_pCallbacks.EmptyBufferDone && il_buffer) { - m_pCallbacks.EmptyBufferDone(hComp, m_app_data, il_buffer); - DEBUG_PRINT_LOW("empty_buffer_done: Returning client buf %p",il_buffer); + if (m_pCallbacks.EmptyBufferDone && buffer) { + m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer); + DEBUG_PRINT_LOW("empty_buffer_done: Returning client buf %p", buffer); } } } else if (m_pCallbacks.EmptyBufferDone) { @@ -4199,6 +4321,18 @@ OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVE (unsigned int)profileLevelType->nProfileIndex); eRet = OMX_ErrorNoMore; } + } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingHEVC) { + if (profileLevelType->nProfileIndex == 0) { + profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel52; + } else if (profileLevelType->nProfileIndex == 1) { + profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10; + profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel52; + } else { + DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", + (unsigned int)profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } } else { DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore"); eRet = OMX_ErrorNoMore; @@ -4237,20 +4371,22 @@ int omx_video::alloc_map_ion_memory(int size, alloc_data->align = SZ_1M; alloc_data->flags = ION_SECURE; alloc_data->ION_HEAP_MASK = ION_HEAP(ION_CP_MM_HEAP_ID); - DEBUG_PRINT_HIGH("ION ALLOC sec buf: size %d align %d flags %x", - alloc_data->len, alloc_data->align,alloc_data->flags); + DEBUG_PRINT_HIGH("ION ALLOC sec buf: size %u align %u flags %x", + (unsigned int)alloc_data->len, (unsigned int)alloc_data->align, + alloc_data->flags); } else { alloc_data->len = (size + (SZ_4K - 1)) & ~(SZ_4K - 1); alloc_data->align = SZ_4K; alloc_data->flags = (flag & ION_FLAG_CACHED ? ION_FLAG_CACHED : 0); #ifdef MAX_RES_720P - alloc_data->ION_HEAP_MASK = ION_HEAP(MEM_HEAP_ID); + alloc_data->ION_HEAP_MASK = ION_HEAP(MEM_HEAP_ID); #else - alloc_data->ION_HEAP_MASK = (ION_HEAP(MEM_HEAP_ID) | + alloc_data->ION_HEAP_MASK = (ION_HEAP(MEM_HEAP_ID) | ION_HEAP(ION_IOMMU_HEAP_ID)); #endif - DEBUG_PRINT_HIGH("ION ALLOC unsec buf: size %d align %d flags %x", - alloc_data->len, alloc_data->align,alloc_data->flags); + DEBUG_PRINT_HIGH("ION ALLOC unsec buf: size %u align %u flags %x", + (unsigned int)alloc_data->len, (unsigned int)alloc_data->align, + alloc_data->flags); } rc = ioctl(ion_device_fd,ION_IOC_ALLOC,alloc_data); @@ -4476,6 +4612,7 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_opaque(OMX_IN OMX_HANDLETYPE hComp, unsigned nBufIndex = 0; OMX_ERRORTYPE ret = OMX_ErrorNone; encoder_media_buffer_type *media_buffer; + private_handle_t *handle = NULL; DEBUG_PRINT_LOW("ETBProxyOpaque: buffer[%p]", buffer); if (buffer == NULL) { @@ -4489,19 +4626,27 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_opaque(OMX_IN OMX_HANDLETYPE hComp, return OMX_ErrorBadParameter; } media_buffer = (encoder_media_buffer_type *)buffer->pBuffer; - private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle; + if ((!media_buffer || !media_buffer->meta_handle) && + !(buffer->nFlags & OMX_BUFFERFLAG_EOS)) { + DEBUG_PRINT_ERROR("Incorrect Buffer queued media buffer = %p", + media_buffer); + m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer); + return OMX_ErrorBadParameter; + } else if (media_buffer) { + handle = (private_handle_t *)media_buffer->meta_handle; + } /*Enable following code once private handle color format is updated correctly*/ + mUsesColorConversion = true; - if (buffer->nFilledLen > 0) { + if (buffer->nFilledLen > 0 && handle) { if (c2d_opened && handle->format != c2d_conv.get_src_format()) { c2d_conv.close(); c2d_opened = false; } if (!c2d_opened) { if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888) { - mUsesColorConversion = true; DEBUG_PRINT_INFO("open Color conv for RGBA888 W: %u, H: %u", (unsigned int)m_sInPortDef.format.video.nFrameWidth, (unsigned int)m_sInPortDef.format.video.nFrameHeight); @@ -4517,8 +4662,12 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_opaque(OMX_IN OMX_HANDLETYPE hComp, if (!dev_set_format(handle->format)) DEBUG_PRINT_ERROR("cannot set color format for RGBA8888"); #endif - } else if (handle->format != HAL_PIXEL_FORMAT_NV12_ENCODEABLE) { + } else if (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE && + handle->format != QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) { + mUsesColorConversion = false; + } else { DEBUG_PRINT_ERROR("Incorrect color format"); + mUsesColorConversion = false; m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); return OMX_ErrorBadParameter; } @@ -4672,6 +4821,7 @@ OMX_ERRORTYPE omx_video::push_input_buffer(OMX_HANDLETYPE hComp) unsigned long address = 0,p2,id, index = 0; OMX_ERRORTYPE ret = OMX_ErrorNone; + DEBUG_PRINT_LOW("In push input buffer"); if (!psource_frame && m_opq_meta_q.m_size) { m_opq_meta_q.pop_entry(&address,&p2,&id); psource_frame = (OMX_BUFFERHEADERTYPE* ) address; @@ -4717,7 +4867,8 @@ OMX_ERRORTYPE omx_video::push_input_buffer(OMX_HANDLETYPE hComp) Input_pmem_info.size = handle->size; if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888) ret = convert_queue_buffer(hComp,Input_pmem_info,index); - else if (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE) + else if (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE || + handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) ret = queue_meta_buffer(hComp,Input_pmem_info); else ret = OMX_ErrorBadParameter; @@ -4730,7 +4881,11 @@ OMX_ERRORTYPE omx_video::push_empty_eos_buffer(OMX_HANDLETYPE hComp, OMX_BUFFERHEADERTYPE* buffer) { OMX_BUFFERHEADERTYPE* opqBuf = NULL; OMX_ERRORTYPE retVal = OMX_ErrorNone; + unsigned index = 0; + + DEBUG_PRINT_LOW("In push empty eos buffer"); do { + if (mUsesColorConversion) { if (pdest_frame) { //[1] use a checked out conversion buffer, if one is available opqBuf = pdest_frame; @@ -4741,7 +4896,12 @@ OMX_ERRORTYPE omx_video::push_empty_eos_buffer(OMX_HANDLETYPE hComp, m_opq_pmem_q.pop_entry(&address,&p2,&id); opqBuf = (OMX_BUFFERHEADERTYPE* ) address; } - unsigned index = opqBuf - m_inp_mem_ptr; + index = opqBuf - m_inp_mem_ptr; + } else { + opqBuf = (OMX_BUFFERHEADERTYPE* ) buffer; + index = opqBuf - meta_buffer_hdr; + } + if (!opqBuf || index >= m_sInPortDef.nBufferCountActual) { DEBUG_PRINT_ERROR("push_empty_eos_buffer: Could not find a " "color-conversion buffer to queue ! defer until available"); @@ -4770,6 +4930,8 @@ OMX_ERRORTYPE omx_video::push_empty_eos_buffer(OMX_HANDLETYPE hComp, emptyEosBufHdr.nTimeStamp = buffer->nTimeStamp; emptyEosBufHdr.nFlags = buffer->nFlags; emptyEosBufHdr.pBuffer = NULL; + if (!mUsesColorConversion) + emptyEosBufHdr.nAllocLen = m_sInPortDef.nBufferSize; if (dev_empty_buf(&emptyEosBufHdr, 0, index, m_pInput_pmem[index].fd) != true) { DEBUG_PRINT_ERROR("ERROR: in dev_empty_buf for empty eos buffer"); dev_free_buf(&Input_pmem_info, PORT_INDEX_IN); 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 63deeeb..ce9ea69 100755..100644 --- a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp +++ b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp @@ -27,7 +27,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------*/ #include "omx_video_encoder.h" #include <string.h> -#include "video_encoder_device.h" #include <stdio.h> #ifdef _ANDROID_ICS_ #include <media/hardware/HardwareAPI.h> @@ -50,9 +49,10 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (_s_)->nVersion.nVersion = OMX_SPEC_VERSION extern int m_pipe; -int debug_level = PRIO_ERROR; static int bframes; static int entropy; +static int perfmode; +static int hybrid_hp; // factory function executed by the core to create instances void *get_omx_component_factory_fn(void) { @@ -82,6 +82,13 @@ omx_venc::omx_venc() property_get("vidc.debug.entropy", property_value, "1"); entropy = !!atoi(property_value); property_value[0] = '\0'; + property_get("vidc.debug.perf.mode", property_value, "0"); + perfmode = atoi(property_value); + property_value[0] = '\0'; + property_get("vidc.debug.hybrid.hierp", property_value, "0"); + hybrid_hp = atoi(property_value); + property_value[0] = '\0'; + handle = NULL; } omx_venc::~omx_venc() @@ -149,7 +156,16 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) codec_type = OMX_VIDEO_CodingVP8; } #endif - else { + else if (!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.hevc", \ + OMX_MAX_STRINGNAME_SIZE)) { + strlcpy((char *)m_cRole, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE); + codec_type = OMX_VIDEO_CodingHEVC; + } else if (!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.hevc.secure", \ + OMX_MAX_STRINGNAME_SIZE)) { + strlcpy((char *)m_cRole, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE); + codec_type = OMX_VIDEO_CodingHEVC; + secure_session = true; + } else { DEBUG_PRINT_ERROR("ERROR: Unknown Component"); eRet = OMX_ErrorInvalidComponentName; } @@ -172,7 +188,8 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) if (handle->venc_open(codec_type) != true) { DEBUG_PRINT_ERROR("ERROR: venc_open failed"); - return OMX_ErrorInsufficientResources; + eRet = OMX_ErrorInsufficientResources; + goto init_error; } //Intialise the OMX layer variables @@ -208,7 +225,7 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sConfigIntraRefreshVOP.IntraRefreshVOP = OMX_FALSE; OMX_INIT_STRUCT(&m_sConfigFrameRotation, OMX_CONFIG_ROTATIONTYPE); - m_sConfigFrameRotation.nPortIndex = (OMX_U32) PORT_INDEX_IN; + m_sConfigFrameRotation.nPortIndex = (OMX_U32) PORT_INDEX_OUT; m_sConfigFrameRotation.nRotation = 0; OMX_INIT_STRUCT(&m_sSessionQuantization, OMX_VIDEO_PARAM_QUANTIZATIONTYPE); @@ -261,6 +278,9 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) } else if (codec_type == OMX_VIDEO_CodingVP8) { m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_VP8ProfileMain; m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_VP8Level_Version0; + } else if (codec_type == OMX_VIDEO_CodingHEVC) { + m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_HEVCProfileMain; + m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_HEVCMainTierLevel1; } // Initialize the video parameters for input port @@ -286,7 +306,7 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) &m_sInPortDef.nBufferSize, m_sInPortDef.nPortIndex) != true) { eRet = OMX_ErrorUndefined; - + goto init_error; } // Initialize the video parameters for output port @@ -309,6 +329,8 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; } else if (codec_type == OMX_VIDEO_CodingVP8) { m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8; + } else if (codec_type == OMX_VIDEO_CodingHEVC) { + m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC; } if (dev_get_buf_req(&m_sOutPortDef.nBufferCountMin, @@ -340,6 +362,8 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingAVC; } else if (codec_type == OMX_VIDEO_CodingVP8) { m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingVP8; + } else if (codec_type == OMX_VIDEO_CodingHEVC) { + m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingHEVC; } @@ -419,10 +443,20 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) m_sParamVP8.nDCTPartitions = 0; m_sParamVP8.bErrorResilientMode = OMX_FALSE; + // HEVC specific init + OMX_INIT_STRUCT(&m_sParamHEVC, OMX_VIDEO_PARAM_HEVCTYPE); + m_sParamHEVC.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sParamHEVC.eProfile = OMX_VIDEO_HEVCProfileMain; + m_sParamHEVC.eLevel = OMX_VIDEO_HEVCMainTierLevel1; + OMX_INIT_STRUCT(&m_sParamLTRMode, QOMX_VIDEO_PARAM_LTRMODE_TYPE); m_sParamLTRMode.nPortIndex = (OMX_U32) PORT_INDEX_OUT; m_sParamLTRMode.eLTRMode = QOMX_VIDEO_LTRMode_Disable; + OMX_INIT_STRUCT(&m_sParamLTRCount, QOMX_VIDEO_PARAM_LTRCOUNT_TYPE); + m_sParamLTRCount.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sParamLTRCount.nCount = 0; + OMX_INIT_STRUCT(&m_sConfigDeinterlace, OMX_VIDEO_CONFIG_DEINTERLACE); m_sConfigDeinterlace.nPortIndex = (OMX_U32) PORT_INDEX_OUT; m_sConfigDeinterlace.nEnable = OMX_FALSE; @@ -467,8 +501,34 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) } } + if (perfmode) { + QOMX_EXTNINDEX_VIDEO_PERFMODE pParam; + pParam.nPerfMode = perfmode; + DEBUG_PRINT_LOW("Perfmode = 0x%x", pParam.nPerfMode); + if (!handle->venc_set_config(&pParam, (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoVencPerfMode)) + DEBUG_PRINT_ERROR("Failed setting PerfMode to %d", pParam.nPerfMode); + } + + if (hybrid_hp) + { + if (hybrid_hp <= MAX_HYB_HIERP_LAYERS) { + QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE hyb_hp; + hyb_hp.nHpLayers = hybrid_hp; + DEBUG_PRINT_LOW("hybrid_hp = 0x%x", hyb_hp.nHpLayers); + if (!handle->venc_set_param(&hyb_hp, (OMX_INDEXTYPE)OMX_QcomIndexParamVideoHybridHierpMode)) { + DEBUG_PRINT_ERROR("Failed setting hybrid_hp to %d", hyb_hp.nHpLayers); + } + } else { + DEBUG_PRINT_ERROR("Max hybrid_hp layers supported is %d", hybrid_hp); + } + } DEBUG_PRINT_INFO("Component_init : %s : return = 0x%x", m_nkind, eRet); return eRet; +init_error: + handle->venc_close(); + delete handle; + handle = NULL; + return eRet; } @@ -517,6 +577,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, switch ((int)paramIndex) { case OMX_IndexParamPortDefinition: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE); OMX_PARAM_PORTDEFINITIONTYPE *portDefn; portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d", @@ -533,6 +594,17 @@ 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 (m_inp_mem_ptr && + (portDefn->nBufferCountActual != m_sInPortDef.nBufferCountActual || + portDefn->nBufferSize != m_sInPortDef.nBufferSize)) { + DEBUG_PRINT_ERROR("ERROR: (In_PORT) buffer count/size can change only if port is unallocated !"); + return OMX_ErrorInvalidState; + } 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); @@ -540,7 +612,8 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } if (handle->venc_set_param(paramData,OMX_IndexParamPortDefinition) != true) { DEBUG_PRINT_ERROR("ERROR: venc_set_param input failed"); - return OMX_ErrorUnsupportedSetting; + return handle->hw_overload ? OMX_ErrorInsufficientResources : + OMX_ErrorUnsupportedSetting; } DEBUG_PRINT_LOW("i/p previous actual cnt = %u", (unsigned int)m_sInPortDef.nBufferCountActual); @@ -580,6 +653,18 @@ 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 (m_out_mem_ptr && + (portDefn->nBufferCountActual != m_sOutPortDef.nBufferCountActual || + portDefn->nBufferSize != m_sOutPortDef.nBufferSize)) { + DEBUG_PRINT_ERROR("ERROR: (Out_PORT) buffer count/size can change only if port is unallocated !"); + return OMX_ErrorInvalidState; + } + 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); @@ -615,6 +700,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_IndexParamVideoPortFormat: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE); OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d", @@ -658,6 +744,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, break; case OMX_IndexParamVideoInit: { //TODO, do we need this index set param + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); OMX_PORT_PARAM_TYPE* pParam = (OMX_PORT_PARAM_TYPE*)(paramData); DEBUG_PRINT_LOW("Set OMX_IndexParamVideoInit called"); break; @@ -665,6 +752,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_IndexParamVideoBitrate: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_BITRATETYPE); OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoBitrate"); if (handle->venc_set_param(paramData,OMX_IndexParamVideoBitrate) != true) { @@ -681,6 +769,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoMpeg4: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_MPEG4TYPE); OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; OMX_VIDEO_PARAM_MPEG4TYPE mp4_param; memcpy(&mp4_param, pParam, sizeof(struct OMX_VIDEO_PARAM_MPEG4TYPE)); @@ -700,8 +789,6 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, #ifdef _MSM8974_ if (pParam->nBFrames || bframes) mp4_param.nBFrames = (pParam->nBFrames > (unsigned int) bframes)? pParam->nBFrames : bframes; - if (mp4_param.nBFrames > 3) - mp4_param.nBFrames = 3; DEBUG_PRINT_HIGH("MPEG4: %u BFrames are being set", (unsigned int)mp4_param.nBFrames); #endif @@ -736,6 +823,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoAvc: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_AVCTYPE); OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; OMX_VIDEO_PARAM_AVCTYPE avc_param; memcpy(&avc_param, pParam, sizeof( struct OMX_VIDEO_PARAM_AVCTYPE)); @@ -758,18 +846,14 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, avc_param.nBFrames = 0; } if (pParam->nRefFrames != 1) { - DEBUG_PRINT_ERROR("Warning: Only 1 RefFrame is supported, changing RefFrame from %lu to 1)", pParam->nRefFrames); + DEBUG_PRINT_ERROR("Warning: Only 1 RefFrame is supported, changing RefFrame from %u to 1)", (unsigned int)pParam->nRefFrames); avc_param.nRefFrames = 1; } #endif #ifdef _MSM8974_ if (pParam->nBFrames || bframes) { avc_param.nBFrames = (pParam->nBFrames > (unsigned int) bframes)? pParam->nBFrames : bframes; - avc_param.nRefFrames = avc_param.nBFrames + 1; - } - if (avc_param.nBFrames > 3) { - avc_param.nBFrames = 3; - avc_param.nRefFrames = avc_param.nBFrames + 1; + avc_param.nRefFrames = (avc_param.nBFrames < 4)? avc_param.nBFrames + 1 : 4; } DEBUG_PRINT_HIGH("AVC: RefFrames: %u, BFrames: %u", (unsigned int)avc_param.nRefFrames, (unsigned int)avc_param.nBFrames); @@ -799,6 +883,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case (OMX_INDEXTYPE)OMX_IndexParamVideoVp8: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_VP8TYPE); OMX_VIDEO_PARAM_VP8TYPE* pParam = (OMX_VIDEO_PARAM_VP8TYPE*)paramData; OMX_VIDEO_PARAM_VP8TYPE vp8_param; DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoVp8"); @@ -813,8 +898,23 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, memcpy(&m_sParamVP8,pParam, sizeof(struct OMX_VIDEO_PARAM_VP8TYPE)); break; } + case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc: + { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_HEVCTYPE); + OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData; + OMX_VIDEO_PARAM_HEVCTYPE hevc_param; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoHevc"); + memcpy(&hevc_param, pParam, sizeof( struct OMX_VIDEO_PARAM_HEVCTYPE)); + if (handle->venc_set_param(&hevc_param, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc) != true) { + DEBUG_PRINT_ERROR("Failed : set_parameter: OMX_IndexParamVideoHevc"); + return OMX_ErrorUnsupportedSetting; + } + memcpy(&m_sParamHEVC, pParam, sizeof(struct OMX_VIDEO_PARAM_HEVCTYPE)); + break; + } case OMX_IndexParamVideoProfileLevelCurrent: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoProfileLevelCurrent"); if (handle->venc_set_param(pParam,OMX_IndexParamVideoProfileLevelCurrent) != true) { @@ -857,10 +957,19 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_LOW("VP8 profile = %d, level = %d", m_sParamVP8.eProfile, m_sParamVP8.eLevel); } + else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc",\ + OMX_MAX_STRINGNAME_SIZE)) { + m_sParamHEVC.eProfile = (OMX_VIDEO_HEVCPROFILETYPE)m_sParamProfileLevel.eProfile; + m_sParamHEVC.eLevel = (OMX_VIDEO_HEVCLEVELTYPE)m_sParamProfileLevel.eLevel; + DEBUG_PRINT_LOW("HEVC profile = %d, level = %d", m_sParamHEVC.eProfile, + m_sParamHEVC.eLevel); + } + break; } case OMX_IndexParamStandardComponentRole: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE); OMX_PARAM_COMPONENTROLETYPE *comp_role; comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s", @@ -913,6 +1022,15 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } } #endif + else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc",OMX_MAX_STRINGNAME_SIZE)) { + if (!strncmp((const char*)comp_role->cRole,"video_encoder.hevc",OMX_MAX_STRINGNAME_SIZE)) { + strlcpy((char*)m_cRole,"video_encoder.hevc",OMX_MAX_STRINGNAME_SIZE); + } else { + DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown Index %s", comp_role->cRole); + eRet = OMX_ErrorUnsupportedSetting; + } + } + else { DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown param %s", m_nkind); eRet = OMX_ErrorInvalidComponentName; @@ -922,6 +1040,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_IndexParamPriorityMgmt: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE); DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt"); if (m_state != OMX_StateLoaded) { DEBUG_PRINT_ERROR("ERROR: Set Parameter called in Invalid State"); @@ -942,6 +1061,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_IndexParamCompBufferSupplier: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE); DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier"); OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d", @@ -958,6 +1078,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoQuantization: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_QUANTIZATIONTYPE); DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoQuantization"); OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData; if (session_qp->nPortIndex == PORT_INDEX_OUT) { @@ -976,6 +1097,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_QcomIndexParamVideoQPRange: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_QPRANGETYPE); DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoQPRange"); OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *qp_range = (OMX_QCOM_VIDEO_PARAM_QPRANGETYPE*) paramData; if (qp_range->nPortIndex == PORT_INDEX_OUT) { @@ -994,6 +1116,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_QcomIndexPortDefn: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE); OMX_QCOM_PARAM_PORTDEFINITIONTYPE* pParam = (OMX_QCOM_PARAM_PORTDEFINITIONTYPE*)paramData; DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexPortDefn"); @@ -1020,6 +1143,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_IndexParamVideoErrorCorrection: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE); DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection"); OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* pParam = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData; @@ -1032,6 +1156,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexParamVideoIntraRefresh: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_INTRAREFRESHTYPE); DEBUG_PRINT_LOW("set_param:OMX_IndexParamVideoIntraRefresh"); OMX_VIDEO_PARAM_INTRAREFRESHTYPE* pParam = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData; @@ -1045,6 +1170,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, #ifdef _ANDROID_ICS_ case OMX_QcomIndexParamVideoMetaBufferMode: { + VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams); StoreMetaDataInBuffersParams *pParam = (StoreMetaDataInBuffersParams*)paramData; DEBUG_PRINT_HIGH("set_parameter:OMX_QcomIndexParamVideoMetaBufferMode: " @@ -1091,6 +1217,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, #if !defined(MAX_RES_720P) || defined(_MSM8974_) case OMX_QcomIndexParamIndexExtraDataType: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE); DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType"); QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData; bool enable = false; @@ -1171,6 +1298,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case QOMX_IndexParamVideoLTRMode: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_PARAM_LTRMODE_TYPE); QOMX_VIDEO_PARAM_LTRMODE_TYPE* pParam = (QOMX_VIDEO_PARAM_LTRMODE_TYPE*)paramData; if (!handle->venc_set_param(paramData, (OMX_INDEXTYPE)QOMX_IndexParamVideoLTRMode)) { @@ -1182,6 +1310,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case QOMX_IndexParamVideoLTRCount: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_PARAM_LTRCOUNT_TYPE); QOMX_VIDEO_PARAM_LTRCOUNT_TYPE* pParam = (QOMX_VIDEO_PARAM_LTRCOUNT_TYPE*)paramData; if (!handle->venc_set_param(paramData, (OMX_INDEXTYPE)QOMX_IndexParamVideoLTRCount)) { @@ -1194,6 +1323,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, #endif case OMX_QcomIndexParamVideoMaxAllowedBitrateCheck: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_PARAMTYPE); QOMX_EXTNINDEX_PARAMTYPE* pParam = (QOMX_EXTNINDEX_PARAMTYPE*)paramData; if (pParam->nPortIndex == PORT_INDEX_OUT) { @@ -1211,6 +1341,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, #ifdef MAX_RES_1080P case OMX_QcomIndexEnableSliceDeliveryMode: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_PARAMTYPE); QOMX_EXTNINDEX_PARAMTYPE* pParam = (QOMX_EXTNINDEX_PARAMTYPE*)paramData; if (pParam->nPortIndex == PORT_INDEX_OUT) { @@ -1229,6 +1360,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, #endif case OMX_QcomIndexEnableH263PlusPType: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_PARAMTYPE); QOMX_EXTNINDEX_PARAMTYPE* pParam = (QOMX_EXTNINDEX_PARAMTYPE*)paramData; DEBUG_PRINT_LOW("OMX_QcomIndexEnableH263PlusPType"); @@ -1247,6 +1379,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamSequenceHeaderWithIDR: { + VALIDATE_OMX_PARAM_DATA(paramData, PrependSPSPPSToIDRFramesParams); if(!handle->venc_set_param(paramData, (OMX_INDEXTYPE)OMX_QcomIndexParamSequenceHeaderWithIDR)) { DEBUG_PRINT_ERROR("%s: %s", @@ -1258,6 +1391,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamH264AUDelimiter: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_CONFIG_H264_AUD); if(!handle->venc_set_param(paramData, (OMX_INDEXTYPE)OMX_QcomIndexParamH264AUDelimiter)) { DEBUG_PRINT_ERROR("%s: %s", @@ -1269,6 +1403,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexHierarchicalStructure: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_HIERARCHICALLAYERS); QOMX_VIDEO_HIERARCHICALLAYERS* pParam = (QOMX_VIDEO_HIERARCHICALLAYERS*)paramData; DEBUG_PRINT_LOW("OMX_QcomIndexHierarchicalStructure"); @@ -1278,6 +1413,8 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_ERROR("ERROR: Request for setting PlusPType failed"); return OMX_ErrorUnsupportedSetting; } + if((pParam->eHierarchicalCodingType == QOMX_HIERARCHICALCODING_B) && pParam->nNumLayers) + hier_b_enabled = true; m_sHierLayers.nNumLayers = pParam->nNumLayers; m_sHierLayers.eHierarchicalCodingType = pParam->eHierarchicalCodingType; } else { @@ -1290,6 +1427,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamPerfLevel: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PERF_LEVEL); if (!handle->venc_set_param(paramData, (OMX_INDEXTYPE) OMX_QcomIndexParamPerfLevel)) { DEBUG_PRINT_ERROR("ERROR: Setting performance level"); @@ -1299,6 +1437,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamH264VUITimingInfo: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO); if (!handle->venc_set_param(paramData, (OMX_INDEXTYPE) OMX_QcomIndexParamH264VUITimingInfo)) { DEBUG_PRINT_ERROR("ERROR: Setting VUI timing info"); @@ -1308,6 +1447,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case OMX_QcomIndexParamPeakBitrate: { + VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE); if (!handle->venc_set_param(paramData, (OMX_INDEXTYPE) OMX_QcomIndexParamPeakBitrate)) { DEBUG_PRINT_ERROR("ERROR: Setting peak bitrate"); @@ -1317,6 +1457,7 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } case QOMX_IndexParamVideoInitialQp: { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_INITIALQP); if(!handle->venc_set_param(paramData, (OMX_INDEXTYPE)QOMX_IndexParamVideoInitialQp)) { DEBUG_PRINT_ERROR("Request to Enable initial QP failed"); @@ -1334,6 +1475,16 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, } break; } + case OMX_QcomIndexParamVideoHybridHierpMode: + { + VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE); + if(!handle->venc_set_param(paramData, + (OMX_INDEXTYPE)OMX_QcomIndexParamVideoHybridHierpMode)) { + DEBUG_PRINT_ERROR("Request to Enable Hybrid Hier-P failed"); + return OMX_ErrorUnsupportedSetting; + } + break; + } case OMX_IndexParamVideoSliceFMO: default: { @@ -1389,6 +1540,14 @@ bool omx_venc::update_profile_level() DEBUG_PRINT_LOW("VP8 profile = %d, level = %d", m_sParamVP8.eProfile, m_sParamVP8.eLevel); } + else if (!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.hevc",\ + OMX_MAX_STRINGNAME_SIZE)) { + m_sParamHEVC.eProfile = (OMX_VIDEO_HEVCPROFILETYPE)eProfile; + m_sParamHEVC.eLevel = (OMX_VIDEO_HEVCLEVELTYPE)eLevel; + DEBUG_PRINT_LOW("HEVC profile = %d, level = %d", m_sParamHEVC.eProfile, + m_sParamHEVC.eLevel); + } + return true; } /* ====================================================================== @@ -1423,6 +1582,7 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, switch ((int)configIndex) { case OMX_IndexConfigVideoBitrate: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_BITRATETYPE); OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData); DEBUG_PRINT_HIGH("set_config(): OMX_IndexConfigVideoBitrate (%u)", (unsigned int)pParam->nEncodeBitrate); @@ -1444,6 +1604,7 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexConfigVideoFramerate: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_FRAMERATETYPE); OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData); DEBUG_PRINT_HIGH("set_config(): OMX_IndexConfigVideoFramerate (0x%x)", (unsigned int)pParam->xEncodeFramerate); @@ -1466,6 +1627,7 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } case QOMX_IndexConfigVideoIntraperiod: { + VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_INTRAPERIODTYPE); QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(configData); @@ -1481,9 +1643,14 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, (unsigned int)m_sIntraperiod.nPFrames, (unsigned int)m_sIntraperiod.nBFrames, (unsigned int)pParam->nPFrames, (unsigned int)pParam->nBFrames); if (m_sIntraperiod.nBFrames != pParam->nBFrames) { + if(hier_b_enabled && m_state == OMX_StateLoaded) { + DEBUG_PRINT_INFO("B-frames setting is supported if HierB is enabled"); + } + else { DEBUG_PRINT_HIGH("Dynamically changing B-frames not supported"); return OMX_ErrorUnsupportedSetting; } + } if (handle->venc_set_config(configData, (OMX_INDEXTYPE) QOMX_IndexConfigVideoIntraperiod) != true) { DEBUG_PRINT_ERROR("ERROR: Setting QOMX_IndexConfigVideoIntraperiod failed"); return OMX_ErrorUnsupportedSetting; @@ -1518,6 +1685,7 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, case OMX_IndexConfigVideoIntraVOPRefresh: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_INTRAREFRESHVOPTYPE); OMX_CONFIG_INTRAREFRESHVOPTYPE* pParam = reinterpret_cast<OMX_CONFIG_INTRAREFRESHVOPTYPE*>(configData); @@ -1539,11 +1707,12 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexConfigCommonRotate: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ROTATIONTYPE); OMX_CONFIG_ROTATIONTYPE *pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData); OMX_S32 nRotation; - if (pParam->nPortIndex != PORT_INDEX_IN) { + if (pParam->nPortIndex != PORT_INDEX_OUT) { DEBUG_PRINT_ERROR("ERROR: Unsupported port index: %u", (unsigned int)pParam->nPortIndex); return OMX_ErrorBadPortIndex; } @@ -1567,18 +1736,14 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, return OMX_ErrorUnsupportedSetting; } else { OMX_U32 nFrameWidth; + OMX_U32 nFrameHeight; DEBUG_PRINT_HIGH("set_config: updating port Dims"); - nFrameWidth = m_sInPortDef.format.video.nFrameWidth; - m_sInPortDef.format.video.nFrameWidth = - m_sInPortDef.format.video.nFrameHeight; - m_sInPortDef.format.video.nFrameHeight = nFrameWidth; - - m_sOutPortDef.format.video.nFrameWidth = - m_sInPortDef.format.video.nFrameWidth; - m_sOutPortDef.format.video.nFrameHeight = - m_sInPortDef.format.video.nFrameHeight; + nFrameWidth = m_sOutPortDef.format.video.nFrameWidth; + nFrameHeight = m_sOutPortDef.format.video.nFrameHeight; + m_sOutPortDef.format.video.nFrameWidth = nFrameHeight; + m_sOutPortDef.format.video.nFrameHeight = nFrameWidth; m_sConfigFrameRotation.nRotation = pParam->nRotation; } } else { @@ -1590,6 +1755,7 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, { DEBUG_PRINT_HIGH("set_config(): OMX_QcomIndexConfigVideoFramePackingArrangement"); if (m_sOutPortFormat.eCompressionFormat == OMX_VIDEO_CodingAVC) { + VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT); OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData; extra_data_handle.set_frame_pack_data(configFmt); @@ -1600,6 +1766,7 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } case QOMX_IndexConfigVideoLTRPeriod: { + VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_CONFIG_LTRPERIOD_TYPE); QOMX_VIDEO_CONFIG_LTRPERIOD_TYPE* pParam = (QOMX_VIDEO_CONFIG_LTRPERIOD_TYPE*)configData; if (!handle->venc_set_config(configData, (OMX_INDEXTYPE)QOMX_IndexConfigVideoLTRPeriod)) { DEBUG_PRINT_ERROR("ERROR: Setting LTR period failed"); @@ -1611,6 +1778,7 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, case OMX_IndexConfigVideoVp8ReferenceFrame: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_VP8REFERENCEFRAMETYPE); OMX_VIDEO_VP8REFERENCEFRAMETYPE* pParam = (OMX_VIDEO_VP8REFERENCEFRAMETYPE*) configData; if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE) OMX_IndexConfigVideoVp8ReferenceFrame)) { DEBUG_PRINT_ERROR("ERROR: Setting VP8 reference frame"); @@ -1622,8 +1790,9 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, case QOMX_IndexConfigVideoLTRUse: { + VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_CONFIG_LTRUSE_TYPE); QOMX_VIDEO_CONFIG_LTRUSE_TYPE* pParam = (QOMX_VIDEO_CONFIG_LTRUSE_TYPE*)configData; - if (!handle->venc_set_config(configData, (OMX_INDEXTYPE)QOMX_IndexConfigVideoLTRUse)) { + if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)QOMX_IndexConfigVideoLTRUse)) { DEBUG_PRINT_ERROR("ERROR: Setting LTR use failed"); return OMX_ErrorUnsupportedSetting; } @@ -1632,13 +1801,17 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } case QOMX_IndexConfigVideoLTRMark: { + VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_CONFIG_LTRMARK_TYPE); QOMX_VIDEO_CONFIG_LTRMARK_TYPE* pParam = (QOMX_VIDEO_CONFIG_LTRMARK_TYPE*)configData; - DEBUG_PRINT_ERROR("Setting ltr mark is not supported"); + if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)QOMX_IndexConfigVideoLTRMark)) { + DEBUG_PRINT_ERROR("ERROR: Setting LTR mark failed"); return OMX_ErrorUnsupportedSetting; + } break; } case OMX_IndexConfigVideoAVCIntraPeriod: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_AVCINTRAPERIOD); OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pParam = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD*) configData; DEBUG_PRINT_LOW("set_config: OMX_IndexConfigVideoAVCIntraPeriod"); if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)OMX_IndexConfigVideoAVCIntraPeriod)) { @@ -1650,6 +1823,7 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, } case OMX_IndexConfigCommonDeinterlace: { + VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_DEINTERLACE); OMX_VIDEO_CONFIG_DEINTERLACE *pParam = (OMX_VIDEO_CONFIG_DEINTERLACE*) configData; DEBUG_PRINT_LOW("set_config: OMX_IndexConfigCommonDeinterlace"); if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)OMX_IndexConfigCommonDeinterlace)) { @@ -1659,6 +1833,35 @@ OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, memcpy(&m_sConfigDeinterlace, pParam, sizeof(m_sConfigDeinterlace)); break; } + case OMX_QcomIndexConfigVideoVencPerfMode: + { + VALIDATE_OMX_PARAM_DATA(configData, QOMX_EXTNINDEX_VIDEO_PERFMODE); + QOMX_EXTNINDEX_VIDEO_PERFMODE* pParam = (QOMX_EXTNINDEX_VIDEO_PERFMODE*)configData; + if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoVencPerfMode)) { + DEBUG_PRINT_ERROR("ERROR: Setting OMX_QcomIndexConfigVideoVencPerfMode failed"); + return OMX_ErrorUnsupportedSetting; + } + break; + } + case OMX_IndexConfigPriority: + { + VALIDATE_OMX_PARAM_DATA(configData, OMX_PARAM_U32TYPE); + if (!handle->venc_set_config(configData, (OMX_INDEXTYPE)OMX_IndexConfigPriority)) { + DEBUG_PRINT_ERROR("Failed to set OMX_IndexConfigPriority"); + return OMX_ErrorUnsupportedSetting; + } + break; + } + case OMX_IndexConfigOperatingRate: + { + VALIDATE_OMX_PARAM_DATA(configData, OMX_PARAM_U32TYPE); + if (!handle->venc_set_config(configData, (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate)) { + DEBUG_PRINT_ERROR("Failed to set OMX_IndexConfigOperatingRate"); + return handle->hw_overload ? OMX_ErrorInsufficientResources : + OMX_ErrorUnsupportedSetting; + } + break; + } default: DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); break; @@ -1693,7 +1896,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; @@ -1707,7 +1917,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; + } } @@ -1729,9 +1946,12 @@ OMX_ERRORTYPE omx_venc::component_deinit(OMX_IN OMX_HANDLETYPE hComp) m_heap_ptr.clear(); #endif // _ANDROID_ DEBUG_PRINT_HIGH("Calling venc_close()"); - handle->venc_close(); - DEBUG_PRINT_HIGH("Deleting HANDLE[%p]", handle); - delete (handle); + if (handle) { + handle->venc_close(); + DEBUG_PRINT_HIGH("Deleting HANDLE[%p]", handle); + delete (handle); + handle = NULL; + } DEBUG_PRINT_INFO("Component Deinit"); return OMX_ErrorNone; } @@ -1784,7 +2004,10 @@ bool omx_venc::dev_free_buf(void *buf_addr,unsigned port) bool omx_venc::dev_empty_buf(void *buffer, void *pmem_data_buf,unsigned index,unsigned fd) { - return handle->venc_empty_buf(buffer, pmem_data_buf,index,fd); + bool bret = false; + bret = handle->venc_empty_buf(buffer, pmem_data_buf,index,fd); + hw_overload = handle->hw_overload; + return bret; } bool omx_venc::dev_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,unsigned fd) @@ -1792,7 +2015,7 @@ bool omx_venc::dev_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,uns return handle->venc_fill_buf(buffer, pmem_data_buf,index,fd); } -bool omx_venc::dev_get_seq_hdr(void *buffer, unsigned size, OMX_U32 *hdrlen) +bool omx_venc::dev_get_seq_hdr(void *buffer, unsigned size, unsigned *hdrlen) { return handle->venc_get_seq_hdr(buffer, size, hdrlen); } @@ -1924,6 +2147,9 @@ int omx_venc::async_message_process (void *context, void* message) if (m_sVenc_msg->statuscode != VEN_S_SUCCESS) { DEBUG_PRINT_ERROR("ERROR: async_msg_process() - Error statuscode = %lu", m_sVenc_msg->statuscode); + if(m_sVenc_msg->msgcode == VEN_MSG_HW_OVERLOAD) { + omx->omx_report_hw_overload(); + } else omx->omx_report_error(); } @@ -1985,7 +2211,7 @@ int omx_venc::async_message_process (void *context, void* message) omxhdr->nFlags = m_sVenc_msg->buf.flags; /*Use buffer case*/ - if (omx->output_use_buffer && !omx->m_use_output_pmem) { + if (omx->output_use_buffer && !omx->m_use_output_pmem && !omx->is_secure_session()) { DEBUG_PRINT_LOW("memcpy() for o/p Heap UseBuffer"); memcpy(omxhdr->pBuffer, (m_sVenc_msg->buf.ptrbuffer), 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 976498f..89ca5eb 100755..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-2014, The Linux Foundation. All rights reserved. +Copyright (c) 2010-2015, 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: @@ -44,17 +44,24 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef _ANDROID_ #include <media/hardware/HardwareAPI.h> #include <gralloc_priv.h> +#include <qdMetaData.h> #endif #define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1)) #define EXTRADATA_IDX(__num_planes) (__num_planes - 1) - +#define MAXDPB 16 +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#define ROUND(__sz, __align) (((__sz) + ((__align>>1))) & (~(__align-1))) +#define MAX_PROFILE_PARAMS 6 #define MPEG4_SP_START 0 #define MPEG4_ASP_START (MPEG4_SP_START + 10) #define H263_BP_START 0 #define H264_BP_START 0 #define H264_HP_START (H264_BP_START + 17) #define H264_MP_START (H264_BP_START + 34) +#define HEVC_MAIN_START 0 +#define HEVC_MAIN10_START (HEVC_MAIN_START + 12) #define POLL_TIMEOUT 1000 #define MAX_SUPPORTED_SLICES_PER_FRAME 28 /* Max supported slices with 32 output buffers */ @@ -62,106 +69,138 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define SZ_1M 0x100000 /* MPEG4 profile and level table*/ -static const unsigned int mpeg4_profile_level_table[][5]= { - /*max mb per frame, max mb per sec, max bitrate, level, profile*/ - {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple}, - {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple}, - {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple}, - {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple}, - {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple}, - {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, - {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, - {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, - {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, - {0,0,0,0,0}, - - {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {0,0,0,0,0}, +static const unsigned int mpeg4_profile_level_table[][MAX_PROFILE_PARAMS]= { + /*max mb per frame, max mb per sec, max bitrate, level, profile, dpbmbs*/ + {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple,0}, + {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple,0}, + {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple,0}, + {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple,0}, + {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple,0}, + {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple,0}, + {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple,0}, + {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple,0}, + {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple,0}, + {0,0,0,0,0,0}, + + {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0}, + {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0}, + {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0}, + {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0}, + {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0}, + {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0}, + {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0}, + {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0}, + {0,0,0,0,0,0}, }; /* H264 profile and level table*/ -static const unsigned int h264_profile_level_table[][5]= { - /*max mb per frame, max mb per sec, max bitrate, level, profile*/ - {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline}, - {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline}, - {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline}, - {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline}, - {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline}, - {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline}, - {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline}, - {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline}, - {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline}, - {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline}, - {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline}, - {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, - {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileBaseline}, - {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileBaseline}, - {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileBaseline}, - {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileBaseline}, - {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileBaseline}, - {0,0,0,0,0}, - - {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh}, - {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh}, - {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh}, - {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh}, - {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh}, - {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh}, - {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh}, - {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh}, - {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh}, - {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh}, - {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh}, - {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, - {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileHigh}, - {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileHigh}, - {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileHigh}, - {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileHigh}, - {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileHigh}, - {0,0,0,0,0}, - - {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain}, - {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain}, - {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain}, - {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain}, - {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain}, - {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain}, - {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain}, - {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain}, - {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain}, - {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain}, - {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain}, - {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, - {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileMain}, - {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileMain}, - {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileMain}, - {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileMain}, - {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileBaseline}, - {0,0,0,0,0} +static const unsigned int h264_profile_level_table[][MAX_PROFILE_PARAMS]= { + /*max mb per frame, max mb per sec, max bitrate, level, profile, dpbmbs*/ + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline,396}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline,396}, + {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline,900}, + {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline,2376}, + {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline,2376}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline,2376}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline,4752}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline,8100}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline,8100}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline,18000}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline,20480}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline,32768}, + {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileBaseline,32768}, + {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileBaseline,34816}, + {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileBaseline,110400}, + {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileBaseline,184320}, + {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileBaseline,184320}, + {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}, + {0,0,0,0,0,0}, + + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain,396}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain,396}, + {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain,900}, + {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain,2376}, + {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain,2376}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain,2376}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain,4752}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain,8100}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain,8100}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain,18000}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain,20480}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain,32768}, + {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileMain,32768}, + {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileMain,34816}, + {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileMain,110400}, + {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileMain,184320}, + {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileMain,184320}, + {0,0,0,0,0,0} }; /* H263 profile and level table*/ -static const unsigned int h263_profile_level_table[][5]= { +static const unsigned int h263_profile_level_table[][MAX_PROFILE_PARAMS]= { + /*max mb per frame, max mb per sec, max bitrate, level, profile, dpbmbs*/ + {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline,0}, + {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline,0}, + {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline,0}, + {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline,0}, + {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline,0}, + {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline,0}, + {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline,0}, + {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline,0}, + {32400,972000,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline,0}, + {34560,1036800,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline,0}, + {0,0,0,0,0,0} +}; + +/* HEVC profile and level table*/ +static const unsigned int hevc_profile_level_table[][MAX_PROFILE_PARAMS]= { /*max mb per frame, max mb per sec, max bitrate, level, profile*/ - {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline}, - {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline}, - {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline}, - {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline}, - {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline}, - {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline}, - {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline}, - {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, - {32400,972000,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, - {34560,1036800,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, - {0,0,0,0,0} + {99,1485,128000,OMX_VIDEO_HEVCMainTierLevel1,OMX_VIDEO_HEVCProfileMain,0}, + {396,11880,1500000,OMX_VIDEO_HEVCMainTierLevel2,OMX_VIDEO_HEVCProfileMain,0}, + {900,27000,3000000,OMX_VIDEO_HEVCMainTierLevel21,OMX_VIDEO_HEVCProfileMain,0}, + {2025,60750,6000000,OMX_VIDEO_HEVCMainTierLevel3,OMX_VIDEO_HEVCProfileMain,0}, + {8640,259200,10000000,OMX_VIDEO_HEVCMainTierLevel31,OMX_VIDEO_HEVCProfileMain,0}, + {34560,1166400,12000000,OMX_VIDEO_HEVCMainTierLevel4,OMX_VIDEO_HEVCProfileMain,0}, + {138240,4147200,20000000,OMX_VIDEO_HEVCMainTierLevel41,OMX_VIDEO_HEVCProfileMain,0}, + {138240,8294400,25000000,OMX_VIDEO_HEVCMainTierLevel5,OMX_VIDEO_HEVCProfileMain,0}, + {138240,4147200,40000000,OMX_VIDEO_HEVCMainTierLevel51,OMX_VIDEO_HEVCProfileMain,0}, + {138240,4147200,50000000,OMX_VIDEO_HEVCHighTierLevel41,OMX_VIDEO_HEVCProfileMain,0}, + {138240,4147200,100000000,OMX_VIDEO_HEVCHighTierLevel5,OMX_VIDEO_HEVCProfileMain,0}, + {138240,4147200,1600000000,OMX_VIDEO_HEVCHighTierLevel51,OMX_VIDEO_HEVCProfileMain,0}, + {0,0,0,0,0}, + + {99,1485,128000,OMX_VIDEO_HEVCMainTierLevel1,OMX_VIDEO_HEVCProfileMain10,0}, + {396,11880,1500000,OMX_VIDEO_HEVCMainTierLevel2,OMX_VIDEO_HEVCProfileMain10,0}, + {900,27000,3000000,OMX_VIDEO_HEVCMainTierLevel21,OMX_VIDEO_HEVCProfileMain10,0}, + {2025,60750,6000000,OMX_VIDEO_HEVCMainTierLevel3,OMX_VIDEO_HEVCProfileMain10,0}, + {8640,259200,10000000,OMX_VIDEO_HEVCMainTierLevel31,OMX_VIDEO_HEVCProfileMain10,0}, + {34560,1166400,12000000,OMX_VIDEO_HEVCMainTierLevel4,OMX_VIDEO_HEVCProfileMain10,0}, + {138240,4147200,20000000,OMX_VIDEO_HEVCMainTierLevel41,OMX_VIDEO_HEVCProfileMain10,0}, + {138240,8294400,25000000,OMX_VIDEO_HEVCMainTierLevel5,OMX_VIDEO_HEVCProfileMain10,0}, + {138240,4147200,40000000,OMX_VIDEO_HEVCMainTierLevel51,OMX_VIDEO_HEVCProfileMain10,0}, + {138240,4147200,50000000,OMX_VIDEO_HEVCHighTierLevel41,OMX_VIDEO_HEVCProfileMain10,0}, + {138240,4147200,100000000,OMX_VIDEO_HEVCHighTierLevel5,OMX_VIDEO_HEVCProfileMain10,0}, + {138240,4147200,1600000000,OMX_VIDEO_HEVCHighTierLevel51,OMX_VIDEO_HEVCProfileMain10,0}, + {0,0,0,0,0}, }; #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } @@ -184,6 +223,7 @@ venc_dev::venc_dev(class omx_venc *venc_class) paused = false; async_thread_created = false; color_format = 0; + hw_overload = false; pthread_mutex_init(&pause_resume_mlock, NULL); pthread_cond_init(&pause_resume_cond, NULL); memset(&extradata_info, 0, sizeof(extradata_info)); @@ -207,10 +247,14 @@ venc_dev::venc_dev(class omx_venc *venc_class) memset(&voptimecfg, 0, sizeof(voptimecfg)); memset(&capability, 0, sizeof(capability)); memset(&m_debug,0,sizeof(m_debug)); - memset(&hier_p_layers,0,sizeof(hier_p_layers)); - memset(&display_info,0,sizeof(display_info)); + memset(&hier_layers,0,sizeof(hier_layers)); is_searchrange_set = false; enable_mv_narrow_searchrange = false; + supported_rc_modes = RC_ALL; + camera_mode_enabled = false; + memset(<rinfo, 0, sizeof(ltrinfo)); + sess_priority.priority = 1; + operating_rate = 0; char property_value[PROPERTY_VALUE_MAX] = {0}; property_get("vidc.enc.log.in", property_value, "0"); @@ -347,7 +391,11 @@ void* venc_dev::async_venc_message_thread (void *input) while (!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) { venc_msg.msgcode=VEN_MSG_INPUT_BUFFER_DONE; venc_msg.statuscode=VEN_S_SUCCESS; - omxhdr=omx_venc_base->m_inp_mem_ptr+v4l2_buf.index; + if (omx_venc_base->mUseProxyColorFormat && !omx_venc_base->mUsesColorConversion) + omxhdr = &omx_venc_base->meta_buffer_hdr[v4l2_buf.index]; + else + omxhdr = &omx_venc_base->m_inp_mem_ptr[v4l2_buf.index]; + venc_msg.buf.clientdata=(void*)omxhdr; omx->handle->ebd++; @@ -380,6 +428,15 @@ void* venc_dev::async_venc_message_thread (void *input) DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message"); break; } + } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) { + DEBUG_PRINT_ERROR("HW Overload received"); + venc_msg.statuscode = VEN_S_EFAIL; + venc_msg.msgcode = VEN_MSG_HW_OVERLOAD; + + if (omx->async_message_process(input,&venc_msg) < 0) { + DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message"); + break; + } } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) { DEBUG_PRINT_ERROR("ERROR: Encoder is in bad state"); venc_msg.msgcode = VEN_MSG_INDICATION; @@ -500,6 +557,16 @@ bool venc_dev::handle_extradata(void *buffer, int index) p_extra->nDataSize = payloadSize; break; } + case MSM_VIDC_EXTRADATA_METADATA_LTR: + { + *p_extra->data = *p_extradata->data; + p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + p_extradata->data_size, 4); + p_extra->nVersion.nVersion = OMX_SPEC_VERSION; + p_extra->nPortIndex = OMX_DirOutput; + p_extra->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataVideoLTRInfo; + p_extra->nDataSize = p_extradata->data_size; + break; + } case MSM_VIDC_EXTRADATA_NONE: p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE), 4); p_extra->nVersion.nVersion = OMX_SPEC_VERSION; @@ -614,6 +681,11 @@ bool venc_dev::venc_get_output_log_flag() int venc_dev::venc_output_log_buffers(const char *buffer_addr, int buffer_len) { + if (venc_handle->is_secure_session()) { + DEBUG_PRINT_ERROR("logging secure output buffers is not allowed!"); + return -1; + } + if (!m_debug.outfile) { int size = 0; if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) { @@ -622,6 +694,9 @@ int venc_dev::venc_output_log_buffers(const char *buffer_addr, int buffer_len) } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.264", m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); + } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { + size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%ld_%ld_%p.265", + m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) { size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.263", m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); @@ -658,6 +733,9 @@ int venc_dev::venc_extradata_log_buffers(char *buffer_addr) } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.264", m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); + } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { + size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.265", + m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) { size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.263", m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); @@ -691,6 +769,11 @@ int venc_dev::venc_extradata_log_buffers(char *buffer_addr) } int venc_dev::venc_input_log_buffers(OMX_BUFFERHEADERTYPE *pbuffer, int fd, int plane_offset) { + if (venc_handle->is_secure_session()) { + DEBUG_PRINT_ERROR("logging secure input buffers is not allowed!"); + return -1; + } + if (!m_debug.infile) { int size = snprintf(m_debug.infile_name, PROPERTY_VALUE_MAX, "%s/input_enc_%lu_%lu_%p.yuv", m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); @@ -754,21 +837,17 @@ bool venc_dev::venc_open(OMX_U32 codec) int r; unsigned int alignment = 0,buffer_size = 0, temp =0; struct v4l2_control control; - OMX_STRING device_name = (OMX_STRING)"/dev/video/venus_enc"; + OMX_STRING device_name = (OMX_STRING)"/dev/video33"; + char property_value[PROPERTY_VALUE_MAX] = {0}; + char platform_name[PROPERTY_VALUE_MAX] = {0}; - char platform_name[PROPERTY_VALUE_MAX]; property_get("ro.board.platform", platform_name, "0"); + property_get("vidc.enc.narrow.searchrange", property_value, "0"); + enable_mv_narrow_searchrange = atoi(property_value); if (!strncmp(platform_name, "msm8610", 7)) { device_name = (OMX_STRING)"/dev/video/q6_enc"; - } - if (!strncmp(platform_name, "msm8916", 7)) { - enable_mv_narrow_searchrange = true; - sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay( - ISurfaceComposer::eDisplayIdMain)); - SurfaceComposerClient::getDisplayInfo(display, &display_info); - DEBUG_PRINT_LOW("Display panel resolution %dX%d", - display_info.w, display_info.h); + supported_rc_modes = (RC_ALL & ~RC_CBR_CFR); } m_nDriver_fd = open (device_name, O_RDWR); @@ -818,6 +897,12 @@ bool venc_dev::venc_open(OMX_U32 codec) profile_level.level = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0; session_qp_range.minqp = 1; session_qp_range.maxqp = 128; + } else if (codec == OMX_VIDEO_CodingHEVC) { + m_sVenc_cfg.codectype = V4L2_PIX_FMT_HEVC; + session_qp_range.minqp = 1; + session_qp_range.maxqp = 51; + codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN; + profile_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1; } session_qp_values.minqp = session_qp_range.minqp; session_qp_values.maxqp = session_qp_range.maxqp; @@ -923,6 +1008,7 @@ bool venc_dev::venc_open(OMX_U32 codec) resume_in_stopped = 0; metadatamode = 0; + camera_mode_enabled = false; control.id = V4L2_CID_MPEG_VIDEO_HEADER_MODE; control.value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE; @@ -959,6 +1045,21 @@ bool venc_dev::venc_open(OMX_U32 codec) DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAME\n"); } + property_get("vidc.debug.turbo", property_value, "0"); + if (atoi(property_value)) { + DEBUG_PRINT_HIGH("Turbo mode debug property enabled"); + control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; + control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set turbo mode"); + } + } + + sess_priority.priority = 1; /* default to non-real-time */ + if (venc_set_session_priority(sess_priority.priority)) { + DEBUG_PRINT_ERROR("Setting session priority failed"); + return OMX_ErrorUnsupportedSetting; + } return true; } @@ -1071,7 +1172,7 @@ bool venc_dev::venc_loaded_stop_done() } bool venc_dev::venc_get_seq_hdr(void *buffer, - unsigned buffer_size, OMX_U32 *header_len) + unsigned buffer_size, unsigned *header_len) { (void) buffer, (void) buffer_size, (void) header_len; return true; @@ -1101,6 +1202,14 @@ bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count, else bufreq.count = 2; + // Increase buffer-header count for metadata-mode on input port + // to improve buffering and reduce bottlenecks in clients + if (metadatamode && (bufreq.count < 9)) { + DEBUG_PRINT_LOW("FW returned buffer count = %d , overwriting with 16", + bufreq.count); + bufreq.count = 9; + } + bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq); @@ -1120,7 +1229,7 @@ bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count, #endif *buff_size = m_sInput_buff_property.datasize; } else { - int extra_idx = 0; + unsigned int extra_idx = 0; 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; @@ -1194,8 +1303,7 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) if (!venc_set_color_format(portDefn->format.video.eColorFormat)) { return false; } - if ((display_info.w * display_info.h) > (OMX_CORE_720P_WIDTH * OMX_CORE_720P_HEIGHT) - && enable_mv_narrow_searchrange && + if (enable_mv_narrow_searchrange && (m_sVenc_cfg.input_width * m_sVenc_cfg.input_height) >= (OMX_CORE_1080P_WIDTH * OMX_CORE_1080P_HEIGHT)) { if (venc_set_searchrange() == false) { @@ -1214,6 +1322,7 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) { DEBUG_PRINT_ERROR("VIDIOC_S_FMT OUTPUT_MPLANE Failed"); + hw_overload = errno == EBUSY; return false; } @@ -1246,6 +1355,7 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) { DEBUG_PRINT_ERROR("VIDIOC_S_FMT CAPTURE_MPLANE Failed"); + hw_overload = errno == EBUSY; return false; } @@ -1467,7 +1577,10 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) pParam->eProfile, pParam->eLevel); return false; } - + if(venc_set_vpx_error_resilience(pParam->bErrorResilientMode) == false) { + DEBUG_PRINT_ERROR("ERROR: Failed to set vpx error resilience"); + return false; + } if(!venc_set_ltrmode(1, 1)) { DEBUG_PRINT_ERROR("ERROR: Failed to enable ltrmode"); return false; @@ -1484,6 +1597,20 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) 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_level (pParam->eProfile, pParam->eLevel)) { + DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile and level %d, %d", + pParam->eProfile, pParam->eLevel); + return false; + } + if (!venc_set_inloop_filter(OMX_VIDEO_AVCLoopFilterEnable)) + DEBUG_PRINT_HIGH("WARN: Request for setting Inloop filter failed for HEVC encoder"); + + break; + } case OMX_IndexParamVideoIntraRefresh: { DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh"); @@ -1737,6 +1864,35 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) } } 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 (pParam->nCount > 0) { + if (venc_set_ltrmode(1, pParam->nCount) == false) { + DEBUG_PRINT_ERROR("ERROR: Enable LTR mode failed"); + return false; + } + } else { + if (venc_set_ltrmode(0, 0) == false) { + DEBUG_PRINT_ERROR("ERROR: Disable LTR mode failed"); + return false; + } + } + break; + } + case OMX_QcomIndexParamVideoHybridHierpMode: + { + QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* pParam = + (QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE*)paramData; + + if (!venc_set_hybrid_hierp(pParam->nHpLayers)) { + DEBUG_PRINT_ERROR("Setting hybrid Hier-P mode failed"); + return OMX_ErrorUnsupportedSetting; + } + break; + } case OMX_IndexParamVideoSliceFMO: default: DEBUG_PRINT_ERROR("ERROR: Unsupported parameter in venc_set_param: %u", @@ -1825,6 +1981,9 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) OMX_CONFIG_ROTATIONTYPE *config_rotation = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData); OMX_U32 nFrameWidth; + if (!config_rotation) { + return false; + } if (true == deinterlace_enabled) { DEBUG_PRINT_ERROR("ERROR: Rotation is not supported with deinterlacing"); return false; @@ -1880,13 +2039,13 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoVp8ReferenceFrame"); if ((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) && (vp8refframe->bUseGoldenFrame)) { - if(venc_set_useltr() == false) { + if(venc_set_useltr(0x1) == false) { DEBUG_PRINT_ERROR("ERROR: use goldenframe failed"); return false; } } else if((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) && (vp8refframe->bGoldenFrameRefresh)) { - if(venc_set_markltr() == false) { + if(venc_set_markltr(0x1) == false) { DEBUG_PRINT_ERROR("ERROR: Setting goldenframe failed"); return false; } @@ -1895,6 +2054,77 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) } 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 (pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN) { + if (venc_set_useltr(pParam->nID) == false) { + DEBUG_PRINT_ERROR("ERROR: Use LTR failed"); + return false; + } + } else { + DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRUse"); + } + 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 (pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN) { + if (venc_set_markltr(pParam->nID) == false) { + DEBUG_PRINT_ERROR("ERROR: Mark LTR failed"); + return false; + } + } else { + DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRMark"); + } + break; + } + case OMX_QcomIndexConfigPerfLevel: + { + OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf = + (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData; + DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel); + if (!venc_set_perf_level(perf->ePerfLevel)) { + DEBUG_PRINT_ERROR("ERROR: Failed to set perf level to %d", perf->ePerfLevel); + return false; + } else { + performance_level.perflevel = (unsigned int) perf->ePerfLevel; + } + break; + } + case OMX_QcomIndexConfigVideoVencPerfMode: + { + QOMX_EXTNINDEX_VIDEO_PERFMODE *pParam = (QOMX_EXTNINDEX_VIDEO_PERFMODE *) configData; + DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoVencPerfMode"); + if (venc_set_perf_mode(pParam->nPerfMode) == false) { + DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE"); + return false; + } + break; + } + case OMX_IndexConfigPriority: + { + OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData; + DEBUG_PRINT_LOW("Set_config: priority %u",priority->nU32); + if (!venc_set_session_priority(priority->nU32)) { + DEBUG_PRINT_ERROR("Failed to set priority"); + return false; + } + break; + } + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData; + DEBUG_PRINT_LOW("Set_config: operating rate %d", rate->nU32); + if (!venc_set_operatingrate(rate->nU32)) { + DEBUG_PRINT_ERROR("Failed to set operating rate"); + return false; + } + break; + } default: DEBUG_PRINT_ERROR("Unsupported config index = %u", index); break; @@ -2022,6 +2252,7 @@ unsigned venc_dev::venc_start(void) DEBUG_PRINT_HIGH("%s(): Check Profile/Level set in driver before start", __func__); + m_level_set = false; if (!venc_set_profile_level(0, 0)) { DEBUG_PRINT_ERROR("ERROR: %s(): Driver Profile/Level is NOT SET", @@ -2069,6 +2300,23 @@ unsigned venc_dev::venc_start(void) return 0; } +inline const char* hiermode_string(int val) +{ + switch(val) + { + case HIER_NONE: + return "No Hier"; + case HIER_P: + return "Hier-P"; + case HIER_B: + return "Hier-B"; + case HIER_P_HYBRID: + return "Hybrid Hier-P"; + default: + return "No hier"; + } +} + void venc_dev::venc_config_print() { @@ -2083,8 +2331,8 @@ void venc_dev::venc_config_print() m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height, m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den); - DEBUG_PRINT_HIGH("ENC_CONFIG: Bitrate: %ld, RC: %ld, I-Period: %ld", - bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes); + DEBUG_PRINT_HIGH("ENC_CONFIG: Bitrate: %ld, RC: %ld, P - Frames : %ld, B - Frames = %ld", + bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes, intra_period.num_bframes); DEBUG_PRINT_HIGH("ENC_CONFIG: qpI: %ld, qpP: %ld, qpb: %ld", session_qp.iframeqp, session_qp.pframeqp, session_qp.bframeqp); @@ -2092,9 +2340,6 @@ void venc_dev::venc_config_print() DEBUG_PRINT_HIGH("ENC_CONFIG: Init_qpI: %ld, Init_qpP: %ld, Init_qpb: %ld", init_qp.iframeqp, init_qp.pframeqp, init_qp.bframeqp); - DEBUG_PRINT_HIGH("ENC_CONFIG: Init_qpI: %ld, Init_qpP: %ld, Init_qpb: %ld", - init_qp.iframeqp, init_qp.pframeqp, init_qp.bframeqp); - DEBUG_PRINT_HIGH("ENC_CONFIG: minQP: %lu, maxQP: %lu", session_qp_values.minqp, session_qp_values.maxqp); @@ -2112,13 +2357,21 @@ void venc_dev::venc_config_print() DEBUG_PRINT_HIGH("ENC_CONFIG: IntraMB/Frame: %ld, HEC: %ld, IDR Period: %ld", intra_refresh.mbcount, hec.header_extension, idrperiod.idrperiod); - DEBUG_PRINT_HIGH("ENC_CONFIG: Hier-P layers: %d", hier_p_layers.numlayers); + DEBUG_PRINT_HIGH("ENC_CONFIG: LTR Enabled: %d, Count: %d", + ltrinfo.enabled, ltrinfo.count); + + DEBUG_PRINT_HIGH("ENC_CONFIG: Hier layers: %d, Hier Mode: %s VPX_ErrorResilience: %d", + hier_layers.numlayers, hiermode_string(hier_layers.hier_mode), vpx_err_resilience.enable); DEBUG_PRINT_HIGH("ENC_CONFIG: Performace level: %d", performance_level.perflevel); DEBUG_PRINT_HIGH("ENC_CONFIG: VUI timing info enabled: %d", vui_timing_info.enabled); DEBUG_PRINT_HIGH("ENC_CONFIG: Peak bitrate: %d", peak_bitrate.peakbitrate); + + DEBUG_PRINT_HIGH("ENC_CONFIG: Session Priority: %u", sess_priority.priority); + + DEBUG_PRINT_HIGH("ENC_CONFIG: Operating Rate: %u", operating_rate); } bool venc_dev::venc_reconfig_reqbufs() @@ -2170,7 +2423,8 @@ bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned index) struct pmem *pmem_tmp; struct v4l2_buffer buf; struct v4l2_plane plane[VIDEO_MAX_PLANES]; - int rc = 0, extra_idx; + int rc = 0; + unsigned int extra_idx; pmem_tmp = (struct pmem *)buf_addr; DEBUG_PRINT_LOW("venc_use_buf:: pmem_tmp = %p", pmem_tmp); @@ -2355,6 +2609,7 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, struct v4l2_plane plane; int rc=0; struct OMX_BUFFERHEADERTYPE *bufhdr; + struct v4l2_control control; encoder_media_buffer_type * meta_buf = NULL; temp_buffer = (struct pmem *)buffer; @@ -2401,11 +2656,24 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, } } else if (!color_format) { if (meta_buf->buffer_type == kMetadataBufferTypeCameraSource) { - if (meta_buf->meta_handle->data[3] & private_handle_t::PRIV_FLAGS_ITU_R_709) + if (meta_buf->meta_handle->numFds + meta_buf->meta_handle->numInts > 3 && + meta_buf->meta_handle->data[3] & private_handle_t::PRIV_FLAGS_ITU_R_709) buf.flags = V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP; + if (meta_buf->meta_handle->numFds + meta_buf->meta_handle->numInts > 2) { plane.data_offset = meta_buf->meta_handle->data[1]; plane.length = meta_buf->meta_handle->data[2]; plane.bytesused = meta_buf->meta_handle->data[2]; + } + if (!camera_mode_enabled) { + camera_mode_enabled = true; + control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; + control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL; + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) + DEBUG_PRINT_HIGH("Failed to set control for perf level"); + DEBUG_PRINT_LOW("Set control id = 0x%x, value = 0x%x, meta_buf type = %d", + control.id, control.value, meta_buf->buffer_type); + } DEBUG_PRINT_LOW("venc_empty_buf: camera buf: fd = %d filled %d of %d flag 0x%x", fd, plane.bytesused, plane.length, buf.flags); } else if (meta_buf->buffer_type == kMetadataBufferTypeGrallocSource) { @@ -2414,6 +2682,29 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, plane.data_offset = 0; plane.length = handle->size; plane.bytesused = handle->size; + if ((!camera_mode_enabled) && (handle->flags & private_handle_t:: PRIV_FLAGS_CAMERA_WRITE)) { + camera_mode_enabled = true; + control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL; + control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL; + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) + DEBUG_PRINT_HIGH("Failed to set perl level"); + DEBUG_PRINT_LOW("Set control id = 0x%x, value = 0x%x, flags = 0x%x", + control.id, control.value, handle->flags); + } + + if (handle->base_metadata) { + MetaData_t *pMeta = + reinterpret_cast<MetaData_t*>(handle->base_metadata); + ColorSpace_t csc = pMeta->operation & UPDATE_COLOR_SPACE ? + pMeta->colorSpace : (ColorSpace_t)-1; + if (csc == ITU_R_709) { + buf.flags |= V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP; + DEBUG_PRINT_LOW("venc_empty_buf: force 601 -> 709 clamping"); + } + } else { + DEBUG_PRINT_LOW("venc_empty_buf: gralloc metadata is NULL"); + } DEBUG_PRINT_LOW("venc_empty_buf: Opaque camera buf: fd = %d " ": filled %d of %d", fd, plane.bytesused, plane.length); } @@ -2463,6 +2754,9 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index, if (ret) { DEBUG_PRINT_ERROR("Failed to call streamon"); + if (errno == EBUSY) { + hw_overload = true; + } return false; } else { streaming[OUTPUT_PORT] = true; @@ -2480,7 +2774,8 @@ bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,un struct venc_buffer frameinfo; struct v4l2_buffer buf; struct v4l2_plane plane[VIDEO_MAX_PLANES]; - int rc = 0, extra_idx; + int rc = 0; + unsigned int extra_idx; struct OMX_BUFFERHEADERTYPE *bufhdr; if (buffer == NULL) @@ -2572,23 +2867,76 @@ bool venc_dev::venc_set_au_delimiter(OMX_BOOL enable) return true; } +bool venc_dev::venc_validate_hybridhp_params(OMX_U32 layers, OMX_U32 bFrames, OMX_U32 count, int mode) +{ + // Check for layers in Hier-p/hier-B with Hier-P-Hybrid + if (layers && (mode == HIER_P || mode == HIER_B) && hier_layers.hier_mode == HIER_P_HYBRID) + return false; + + // Check for bframes with Hier-P-Hybrid + if (bFrames && hier_layers.hier_mode == HIER_P_HYBRID) + return false; + + // Check for Hier-P-Hybrid with bframes/LTR/hier-p/Hier-B + if (layers && mode == HIER_P_HYBRID && (intra_period.num_bframes || hier_layers.hier_mode == HIER_P || + hier_layers.hier_mode == HIER_B || ltrinfo.count)) + return false; + + // Check for LTR with Hier-P-Hybrid + if (count && hier_layers.hier_mode == HIER_P_HYBRID) + return false; + + return true; +} + bool venc_dev::venc_set_hier_layers(QOMX_VIDEO_HIERARCHICALCODINGTYPE type, OMX_U32 num_layers) { struct v4l2_control control; - control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS; + + if (!venc_validate_hybridhp_params(num_layers, 0, 0, (int)type)){ + DEBUG_PRINT_ERROR("Invalid settings, Hier-pLayers enabled with HybridHP"); + return false; + } + if (type == QOMX_HIERARCHICALCODING_P) { - control.value = num_layers; + // 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_HIER_P_NUM_LAYERS; + control.value = num_layers - 1; DEBUG_PRINT_HIGH("Set Hier P num layers: %u", (unsigned int)num_layers); if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { DEBUG_PRINT_ERROR("Request to set Hier P num layers failed"); return false; } - hier_p_layers.numlayers = num_layers; + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { + DEBUG_PRINT_LOW("Set H264_SVC_NAL"); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC; + control.value = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_ENABLED; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to enable SVC_NAL"); + return false; + } + } + hier_layers.hier_mode = HIER_P; + } else if (type == QOMX_HIERARCHICALCODING_B) { + if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) { + DEBUG_PRINT_ERROR("Failed : Hier B layers supported only for HEVC encode"); + return false; + } + control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS; + control.value = num_layers - 1; + DEBUG_PRINT_INFO("Set Hier B num layers: %u", (unsigned int)num_layers); + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Request to set Hier P num layers failed"); + return false; + } + hier_layers.hier_mode = HIER_B; } else { DEBUG_PRINT_ERROR("Request to set hier num layers failed for type: %d", type); return false; } + hier_layers.numlayers = num_layers; return true; } @@ -2773,7 +3121,7 @@ bool venc_dev::venc_set_session_qp_range(OMX_U32 min_qp, OMX_U32 max_qp) control.id, control.value); rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); if (rc) { - DEBUG_PRINT_ERROR("Failed to set control\n"); + DEBUG_PRINT_ERROR("Failed to set control"); return false; } @@ -2787,12 +3135,12 @@ bool venc_dev::venc_set_session_qp_range(OMX_U32 min_qp, OMX_U32 max_qp) control.id, control.value); rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); if (rc) { - DEBUG_PRINT_ERROR("Failed to set control\n"); + DEBUG_PRINT_ERROR("Failed to set control"); return false; } } else { - DEBUG_PRINT_ERROR("Wrong qp values[%lu %lu], allowed range[%lu %lu]", - min_qp, max_qp, session_qp_range.minqp, session_qp_range.maxqp); + DEBUG_PRINT_ERROR("Wrong qp values[%u %u], allowed range[%u %u]", + (unsigned int)min_qp, (unsigned int)max_qp, (unsigned int)session_qp_range.minqp, (unsigned int)session_qp_range.maxqp); } return true; @@ -3047,6 +3395,96 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) return false; break; } + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { + if (eProfile == OMX_VIDEO_HEVCProfileMain) { + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN; + } else if(eProfile == OMX_VIDEO_HEVCProfileMain10) { + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10; + } else { + DEBUG_PRINT_ERROR("ERROR: Unsupported HEVC profile = %lu", + requested_profile.profile); + return false; + } + + //profile level + switch (eLevel) { + case OMX_VIDEO_HEVCMainTierLevel1: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1; + break; + case OMX_VIDEO_HEVCHighTierLevel1: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1; + break; + case OMX_VIDEO_HEVCMainTierLevel2: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2; + break; + case OMX_VIDEO_HEVCHighTierLevel2: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2; + break; + case OMX_VIDEO_HEVCMainTierLevel21: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1; + break; + case OMX_VIDEO_HEVCHighTierLevel21: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1; + break; + case OMX_VIDEO_HEVCMainTierLevel3: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3; + break; + case OMX_VIDEO_HEVCHighTierLevel3: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3; + break; + case OMX_VIDEO_HEVCMainTierLevel31: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1; + break; + case OMX_VIDEO_HEVCHighTierLevel31: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1; + break; + case OMX_VIDEO_HEVCMainTierLevel4: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4; + break; + case OMX_VIDEO_HEVCHighTierLevel4: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4; + break; + case OMX_VIDEO_HEVCMainTierLevel41: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1; + break; + case OMX_VIDEO_HEVCHighTierLevel41: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1; + break; + case OMX_VIDEO_HEVCMainTierLevel5: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5; + break; + case OMX_VIDEO_HEVCHighTierLevel5: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5; + break; + case OMX_VIDEO_HEVCMainTierLevel51: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1; + break; + case OMX_VIDEO_HEVCHighTierLevel51: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1; + break; + case OMX_VIDEO_HEVCMainTierLevel52: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2; + break; + case OMX_VIDEO_HEVCHighTierLevel52: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2; + break; + case OMX_VIDEO_HEVCMainTierLevel6: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6; + break; + case OMX_VIDEO_HEVCHighTierLevel6: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6; + break; + case OMX_VIDEO_HEVCMainTierLevel61: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1; + break; + case OMX_VIDEO_HEVCHighTierLevel61: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1; + break; + default : + DEBUG_PRINT_ERROR("ERROR: Unsupported HEVC level= %lu", + requested_level.level); + return false; + } } if (!m_profile_set) { @@ -3059,6 +3497,8 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) control.id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE; } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) { control.id = V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { + control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE; } else { DEBUG_PRINT_ERROR("Wrong CODEC"); return false; @@ -3092,6 +3532,8 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) control.id = V4L2_CID_MPEG_VIDC_VIDEO_H263_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_VIDC_VIDEO_HEVC_TIER_LEVEL; } else { DEBUG_PRINT_ERROR("Wrong CODEC"); return false; @@ -3140,17 +3582,28 @@ bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) if ((codec_profile.profile != V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE) && (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) && + (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN) && + (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) && (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)) { nBFrames=0; } - if ((display_info.w * display_info.h > OMX_CORE_720P_WIDTH * OMX_CORE_720P_HEIGHT) - && enable_mv_narrow_searchrange && (m_sVenc_cfg.input_width * m_sVenc_cfg.input_height >= - OMX_CORE_1080P_WIDTH * OMX_CORE_1080P_HEIGHT || is_searchrange_set)) { - nBFrames=0; + + if (!venc_validate_hybridhp_params(0, nBFrames, 0, 0)) { + DEBUG_PRINT_ERROR("Invalid settings, bframes cannot be enabled with HybridHP"); + return false; + } + + intra_period.num_pframes = nPFrames; + intra_period.num_bframes = nBFrames; + + if (!venc_calibrate_gop()) + { + DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes"); + return false; } control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES; - control.value = nPFrames; + control.value = intra_period.num_pframes; rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); if (rc) { @@ -3160,9 +3613,8 @@ bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value); - intra_period.num_pframes = control.value; control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES; - control.value = nBFrames; + control.value = intra_period.num_bframes; 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); @@ -3171,7 +3623,6 @@ bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) return false; } - intra_period.num_bframes = nBFrames; DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%lu", control.id, intra_period.num_bframes); if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { @@ -3357,6 +3808,11 @@ bool venc_dev::venc_set_intra_refresh(OMX_VIDEO_INTRAREFRESHTYPE ir_mode, OMX_U3 } else if ((ir_mode == OMX_VIDEO_IntraRefreshBoth) && (irMBs < ((m_sVenc_cfg.dvs_width * m_sVenc_cfg.dvs_height)>>8))) { control_mode.value = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_CYCLIC_ADAPTIVE; + } else if ((ir_mode == OMX_VIDEO_IntraRefreshRandom) && + (irMBs < ((m_sVenc_cfg.dvs_width * m_sVenc_cfg.dvs_height)>>8))) { + control_mode.value = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM; + control_mbs.id = V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS; + control_mbs.value = irMBs; } else { DEBUG_PRINT_ERROR("ERROR: Invalid IntraRefresh Parameters:" "mb count: %u, mb mode:%d", (unsigned int)irMBs, ir_mode); @@ -3668,6 +4124,146 @@ bool venc_dev::venc_set_deinterlace(OMX_U32 enable) return true; } +bool venc_dev::venc_calibrate_gop() +{ + int ratio, sub_gop_size, gop_size, nPframes, nBframes, nLayers; + int num_sub_gops_in_a_gop; + nPframes = intra_period.num_pframes; + nBframes = intra_period.num_bframes; + nLayers = hier_layers.numlayers; + + if (!nPframes) { + DEBUG_PRINT_ERROR("nPframes should be non-zero\n"); + return false; + } + + if (nLayers > 1) { /*Multi-layer encoding*/ + sub_gop_size = 1 << (nLayers - 1); + /* Actual GOP definition is nPframes + nBframes + 1 but for the sake of + * below calculations we are ignoring +1 . Ignoring +1 in below + * calculations is not a mistake but intentional. + */ + gop_size = MAX(sub_gop_size, ROUND(nPframes + nBframes, sub_gop_size)); + num_sub_gops_in_a_gop = gop_size/sub_gop_size; + if (nBframes) { /*Hier-B case*/ + /* + * Frame Type--> I B B B P B B B P I B B P ... + * Layer --> 0 2 1 2 0 2 1 2 0 0 2 1 2 ... + * nPframes = 2, nBframes = 6, nLayers = 3 + * + * Intention is to keep the intraperiod as close as possible to what is desired + * by the client while adjusting nPframes and nBframes to meet other constraints. + * eg1: Input by client: nPframes = 9, nBframes = 14, nLayers = 2 + * Output of this fn: nPframes = 12, nBframes = 12, nLayers = 2 + * + * eg2: Input by client: nPframes = 9, nBframes = 4, nLayers = 2 + * Output of this fn: nPframes = 7, nBframes = 7, nLayers = 2 + */ + nPframes = num_sub_gops_in_a_gop; + nBframes = gop_size - nPframes; + } else { /*Hier-P case*/ + /* + * Frame Type--> I P P P P P P P I P P P P ... + * Layer--> 0 2 1 2 0 2 1 2 0 2 1 2 0 ... + * nPframes = 7, nBframes = 0, nLayers = 3 + * + * Intention is to keep the intraperiod as close as possible to what is desired + * by the client while adjusting nPframes and nBframes to meet other constraints. + * eg1: Input by client: nPframes = 9, nBframes = 0, nLayers = 3 + * Output of this fn: nPframes = 7, nBframes = 0, nLayers = 3 + * + * eg2: Input by client: nPframes = 10, nBframes = 0, nLayers = 3 + * Output of this fn:nPframes = 12, nBframes = 0, nLayers = 3 + */ + nPframes = gop_size - 1; + } + } else { /*Single-layer encoding*/ + if (nBframes) { + /* I P B B B P B B B P B B B I P B B... + * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17... + * nPframes = 3, nBframes = 9, nLayers = 0 + * + * ratio is rounded, + * eg1: nPframes = 9, nBframes = 11 => ratio = 1 + * eg2: nPframes = 9, nBframes = 16 => ratio = 2 + */ + ratio = MAX(1, MIN((nBframes + (nPframes >> 1))/nPframes, 3)); + nBframes = ratio * nPframes; + } + } + DEBUG_PRINT_LOW("P/B Frames changed from: %ld/%ld to %d/%d", + intra_period.num_pframes, intra_period.num_bframes, nPframes, nBframes); + intra_period.num_pframes = nPframes; + intra_period.num_bframes = nBframes; + hier_layers.numlayers = nLayers; + return true; +} + +bool venc_dev::venc_set_hybrid_hierp(OMX_U32 layers) +{ + DEBUG_PRINT_LOW("venc_set_hybrid_hierp layers: %u", layers); + struct v4l2_control control; + int rc; + + if (!venc_validate_hybridhp_params(layers, 0, 0, (int) HIER_P_HYBRID)) { + DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes"); + return false; + } + + if (!layers || layers > MAX_HYB_HIERP_LAYERS) { + DEBUG_PRINT_ERROR("Invalid numbers of layers set: %d (max supported is 6)", layers); + return false; + } + + hier_layers.numlayers = layers; + hier_layers.hier_mode = HIER_P_HYBRID; + if (venc_calibrate_gop()) { + // Update the driver with the new nPframes and nBframes + control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES; + control.value = intra_period.num_pframes; + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control"); + return false; + } + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES; + control.value = intra_period.num_bframes; + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control"); + return false; + } + DEBUG_PRINT_LOW("Updated nPframes (%ld) and nBframes (%ld)", + intra_period.num_pframes, intra_period.num_bframes); + } else { + DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes"); + return false; + } + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE; + control.value = layers - 1; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d", + control.id, control.value); + + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set hybrid hierp %d", rc); + return false; + } + + DEBUG_PRINT_LOW("SUCCESS IOCTL set control for id=%x, val=%d", + control.id, control.value); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC; + control.value = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_ENABLED; + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to enable SVC_NAL"); + return false; + } + return true; +} + bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count) { DEBUG_PRINT_LOW("venc_set_ltrmode: enable = %u", (unsigned int)enable); @@ -3676,6 +4272,11 @@ bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count) struct v4l2_ext_controls controls; int rc; + if (!venc_validate_hybridhp_params(0, 0, count, 0)) { + DEBUG_PRINT_ERROR("Invalid settings, LTR enabled with HybridHP"); + return false; + } + ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE; if (enable) ctrl[0].value = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_MANUAL; @@ -3683,10 +4284,12 @@ bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count) ctrl[0].value = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE; ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT; - if (count) + if (enable && count > 0) ctrl[1].value = count; - else + else if (enable) ctrl[1].value = 1; + else + ctrl[1].value = 0; controls.count = 2; controls.ctrl_class = V4L2_CTRL_CLASS_MPEG; @@ -3701,6 +4304,8 @@ bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count) DEBUG_PRINT_ERROR("Failed to set ltrmode %d", rc); return false; } + ltrinfo.enabled = enable; + ltrinfo.count = count; DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d id=%x, val=%d", controls.controls[0].id, controls.controls[0].value, @@ -3713,17 +4318,26 @@ bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count) DEBUG_PRINT_ERROR("ERROR: Request for setting extradata failed"); return false; } + + if (!venc_set_profile_level(0, 0)) { + DEBUG_PRINT_ERROR("ERROR: %s(): Driver Profile/Level is NOT SET", + __func__); + } else { + DEBUG_PRINT_HIGH("%s(): Driver Profile[%lu]/Level[%lu] successfully SET", + __func__, codec_profile.profile, profile_level.level); + } + return true; } -bool venc_dev::venc_set_useltr() +bool venc_dev::venc_set_useltr(OMX_U32 frameIdx) { DEBUG_PRINT_LOW("venc_use_goldenframe"); int rc = true; struct v4l2_control control; control.id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME; - control.value = 1; + control.value = frameIdx; rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); if (rc) { @@ -3736,14 +4350,14 @@ bool venc_dev::venc_set_useltr() return true; } -bool venc_dev::venc_set_markltr() +bool venc_dev::venc_set_markltr(OMX_U32 frameIdx) { DEBUG_PRINT_LOW("venc_set_goldenframe"); int rc = true; struct v4l2_control control; control.id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME; - control.value = 1; + control.value = frameIdx; rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); if (rc) { @@ -3896,16 +4510,24 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF; break; case OMX_Video_ControlRateVariableSkipFrames: - control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR; + (supported_rc_modes & RC_VBR_VFR) ? + control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR : + status = false; break; case OMX_Video_ControlRateVariable: - control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR; + (supported_rc_modes & RC_VBR_CFR) ? + control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR : + status = false; break; case OMX_Video_ControlRateConstantSkipFrames: - control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR; + (supported_rc_modes & RC_CBR_VFR) ? + control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR : + status = false; break; case OMX_Video_ControlRateConstant: - control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR; + (supported_rc_modes & RC_CBR_CFR) ? + control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR : + status = false; break; default: status = false; @@ -3963,6 +4585,24 @@ bool venc_dev::venc_set_perf_level(QOMX_VIDEO_PERF_LEVEL ePerfLevel) return status; } +bool venc_dev::venc_set_perf_mode(OMX_U32 mode) +{ + struct v4l2_control control; + if (mode && mode <= V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE) { + control.id = V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE; + control.value = mode; + DEBUG_PRINT_LOW("Going to set V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE"); + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE"); + return false; + } + return true; + } else { + DEBUG_PRINT_ERROR("Invalid mode set for V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE: %d", mode); + return false; + } +} + bool venc_dev::venc_set_vui_timing_info(OMX_BOOL enable) { struct v4l2_control control; @@ -4006,6 +4646,82 @@ bool venc_dev::venc_set_peak_bitrate(OMX_U32 nPeakBitrate) 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_session_priority(OMX_U32 priority) { + struct v4l2_control control; + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY; + switch(priority) { + case 0: + control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE; + break; + case 1: + control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE; + break; + default: + priority = 1; + control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE; + DEBUG_PRINT_ERROR("Unsupported priority level %u", priority); + break; + } + + if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + DEBUG_PRINT_ERROR("Failed to set V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_%s", + priority == 0 ? "ENABLE" : "DISABLE"); + return false; + } + + sess_priority.priority = priority; + + DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d", + control.id, control.value); + return true; +} + +bool venc_dev::venc_set_operatingrate(OMX_U32 rate) { + struct v4l2_control control; + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE; + control.value = rate; + + DEBUG_PRINT_LOW("venc_set_operating_rate: %d fps", rate >> 16); + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value); + + if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) { + hw_overload = errno == EBUSY; + DEBUG_PRINT_ERROR("Failed to set operating rate %d fps (%s)", + rate >> 16, hw_overload ? "HW overload" : strerror(errno)); + return false; + } + operating_rate = rate; + DEBUG_PRINT_LOW("Operating Rate Set = %d fps", rate >> 16); + return true; +} + bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel) { bool status = true; @@ -4218,6 +4934,104 @@ bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel) status = false; break; } + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { + switch (codec_profile.profile) { + case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN: + *eProfile = OMX_VIDEO_HEVCProfileMain; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10: + *eProfile = OMX_VIDEO_HEVCProfileMain10; + break; + default: + *eProfile = OMX_VIDEO_HEVCProfileMax; + status = false; + break; + } + if (!status) { + return status; + } + + switch (profile_level.level) { + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1: + *eLevel = OMX_VIDEO_HEVCMainTierLevel1; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1: + *eLevel = OMX_VIDEO_HEVCHighTierLevel1; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2: + *eLevel = OMX_VIDEO_HEVCMainTierLevel2; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2: + *eLevel = OMX_VIDEO_HEVCHighTierLevel2; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1: + *eLevel = OMX_VIDEO_HEVCMainTierLevel21; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1: + *eLevel = OMX_VIDEO_HEVCHighTierLevel21; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3: + *eLevel = OMX_VIDEO_HEVCMainTierLevel3; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3: + *eLevel = OMX_VIDEO_HEVCHighTierLevel3; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1: + *eLevel = OMX_VIDEO_HEVCMainTierLevel31; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1: + *eLevel = OMX_VIDEO_HEVCHighTierLevel31; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4: + *eLevel = OMX_VIDEO_HEVCMainTierLevel4; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4: + *eLevel = OMX_VIDEO_HEVCHighTierLevel4; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1: + *eLevel = OMX_VIDEO_HEVCMainTierLevel41; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1: + *eLevel = OMX_VIDEO_HEVCHighTierLevel41; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5: + *eLevel = OMX_VIDEO_HEVCMainTierLevel5; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5: + *eLevel = OMX_VIDEO_HEVCHighTierLevel5; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1: + *eLevel = OMX_VIDEO_HEVCMainTierLevel51; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1: + *eLevel = OMX_VIDEO_HEVCHighTierLevel51; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2: + *eLevel = OMX_VIDEO_HEVCMainTierLevel52; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2: + *eLevel = OMX_VIDEO_HEVCHighTierLevel52; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6: + *eLevel = OMX_VIDEO_HEVCMainTierLevel6; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6: + *eLevel = OMX_VIDEO_HEVCHighTierLevel6; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1: + *eLevel = OMX_VIDEO_HEVCMainTierLevel61; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1: + *eLevel = OMX_VIDEO_HEVCHighTierLevel61; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2: + *eLevel = OMX_VIDEO_HEVCMainTierLevel62; + break; + default: + *eLevel = OMX_VIDEO_HEVCLevelMax; + status = false; + break; + } } return status; @@ -4372,8 +5186,40 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) } } return true; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { + if (*eProfile == 0) { + if (!m_profile_set) { + *eProfile = OMX_VIDEO_HEVCProfileMain; } else { - DEBUG_PRINT_LOW("Invalid codec type"); + switch (codec_profile.profile) { + case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN: + *eProfile = OMX_VIDEO_HEVCProfileMain; + break; + case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10: + *eProfile = OMX_VIDEO_HEVCProfileMain10; + break; + default: + DEBUG_PRINT_ERROR("%s(): Unknown Error", __func__); + return false; + } + } + } + + if (*eLevel == 0 && !m_level_set) { + *eLevel = OMX_VIDEO_HEVCLevelMax; + } + + if (*eProfile == OMX_VIDEO_HEVCProfileMain) { + profile_tbl = (unsigned int const *)hevc_profile_level_table; + } else if (*eProfile == OMX_VIDEO_HEVCProfileMain10) { + profile_tbl = (unsigned int const *) + (&hevc_profile_level_table[HEVC_MAIN10_START]); + } else { + DEBUG_PRINT_ERROR("Unsupported HEVC profile type %u", (unsigned int)*eProfile); + return false; + } + } else { + DEBUG_PRINT_ERROR("Invalid codec type"); return false; } @@ -4396,20 +5242,46 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) mb_per_sec = mb_per_frame * m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den; + bool h264, ltr, hlayers; + unsigned int hybridp = 0, maxDpb = profile_tbl[5] / mb_per_frame; + h264 = m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264; + ltr = ltrinfo.enabled && ((ltrinfo.count + 2) <= MIN((unsigned int) (profile_tbl[5] / mb_per_frame), MAXDPB)); + hlayers = hier_layers.numlayers && hier_layers.hier_mode == HIER_P && + ((intra_period.num_bframes + ltrinfo.count + hier_layers.numlayers + 1) <= (unsigned int) (profile_tbl[5] / profile_tbl[0])); + + /* Hybrid HP reference buffers: + layers = 1, 2 need 1 reference buffer + layers = 3, 4 need 2 reference buffers + layers = 5, 6 need 3 reference buffers + */ + + if(hier_layers.hier_mode == HIER_P_HYBRID) + hybridp = MIN(MAX(maxDpb, ((hier_layers.numlayers + 1) / 2)), 16); + do { if (mb_per_frame <= (unsigned int)profile_tbl[0]) { if (mb_per_sec <= (unsigned int)profile_tbl[1]) { if (m_sVenc_cfg.targetbitrate <= (unsigned int)profile_tbl[2]) { + if (h264 && (ltr || hlayers || hybridp)) { + // Update profile and level to adapt to the LTR and Hier-p/Hybrid-HP settings + new_level = (int)profile_tbl[3]; + new_profile = (int)profile_tbl[4]; + profile_level_found = true; + DEBUG_PRINT_LOW("Appropriate profile/level for LTR count: %u OR Hier-p: %u is %u/%u, maxDPB: %u", + ltrinfo.count, hier_layers.numlayers, (int)new_profile, (int)new_level, + MIN((unsigned int) (profile_tbl[5] / mb_per_frame), MAXDPB)); + break; + } else { new_level = (int)profile_tbl[3]; new_profile = (int)profile_tbl[4]; profile_level_found = true; - DEBUG_PRINT_LOW("Appropriate profile/level found %u/%u", (unsigned int)new_profile, (unsigned int)new_level); + DEBUG_PRINT_LOW("Appropriate profile/level found %u/%u", (int) new_profile, (int) new_level); break; } } } - - profile_tbl = profile_tbl + 5; + } + profile_tbl = profile_tbl + MAX_PROFILE_PARAMS; } while (profile_tbl[0] != 0); if (profile_level_found != true) { @@ -4418,7 +5290,8 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) } if ((*eLevel == OMX_VIDEO_MPEG4LevelMax) || (*eLevel == OMX_VIDEO_AVCLevelMax) - || (*eLevel == OMX_VIDEO_H263LevelMax || (*eLevel == OMX_VIDEO_VP8ProfileMax))) { + || (*eLevel == OMX_VIDEO_H263LevelMax) || (*eLevel == OMX_VIDEO_VP8ProfileMax) + || (*eLevel == OMX_VIDEO_HEVCLevelMax)) { *eLevel = new_level; } |