SmartAudio/package/allwinner/tina_multimedia/libcedarc/openmax/venc/omx_venc.cpp

5015 lines
193 KiB
C++
Executable File

/*
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
* All rights reserved.
*
* File : omx_venc.cpp
*
* Description : OpenMax Encoder Definition
* History :
*
*/
#define LOG_TAG "omx_venc"
#include "log.h"
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include "omx_venc.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memoryAdapter.h"
#include "CdcUtil.h"
#ifdef __ANDROID__
#include "MetadataBufferType.h"
#include <ion/ion.h>
#include <HardwareAPI.h>
#include <utils/CallStack.h>
#include <binder/IPCThreadState.h>
#include <ui/Rect.h>
#include <ui/GraphicBufferMapper.h>
#include <ui/GraphicBuffer.h>
#include <ui/Fence.h>
#ifdef __ANDROID__
#include <cutils/properties.h>
#endif
#if ((CONF_ANDROID_MAJOR_VER >= 4)||((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER >= 4)))
#include "hardware/hal_public.h"
#endif
//#if (CONF_ANDROID_MAJOR_VER >= 6)
//#include <OMX_IndexExt.h>
//#endif
using namespace android;
#define FENCE_TIMEOUT_MS 1000
#endif
#define SAVE_BITSTREAM 0
#define ION_DEV_NAME "/dev/ion"
#if SAVE_BITSTREAM
static FILE *OutFile = NULL;
#endif
#ifdef CONF_ARMV7_A_NEON
extern "C" void ImgRGBA2YUV420SP_neon(unsigned char *pu8RgbBuffer,
unsigned char** pu8SrcYUV,
int *l32Width_stride,
int l32Height);
#endif
#define DEFAULT_BITRATE 1024*1024*2
#define OPEN_STATISTICS 0
#define PRINT_FRAME_CNT (50)
#define HW_VIDEO_CALL_APK "com.huawei.iptv.stb.videotalk.activity"
#define BUF_ALIGN_SIZE 32
static unsigned int omx_venc_align(unsigned int x, int a)
{
return (x + (a-1)) & (~(a-1));
}
#define ALIGN_16B(x) (((x) + (15)) & ~(15))
#if (OPEN_STATISTICS)
int64_t nTimeUs1;
int64_t nTimeUs2;
static int64_t GetNowUs()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (int64_t)tv.tv_sec * 1000000ll + tv.tv_usec;
}
#endif
/* H.263 Supported Levels & profiles */
VIDEO_PROFILE_LEVEL_TYPE SupportedH263ProfileLevels[] = {
{OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10},
{OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level20},
{OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level30},
{OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level40},
{OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45},
{OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level50},
{OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level60},
{OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level70},
{-1, -1}
};
/* AVC Supported Levels & profiles for cts*/
static VIDEO_PROFILE_LEVEL_TYPE CTSSupportedAVCProfileLevels[] = {
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel1},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel1b},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel11},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel12},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel13},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel2 },
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel21},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel22},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel3 },
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel31},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel32},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1 },
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1b},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel11},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel12},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel13},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel2 },
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel21},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel22},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel3 },
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel31},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel32},
{-1,-1}
};
/* AVC Supported Levels & profiles */
static VIDEO_PROFILE_LEVEL_TYPE SupportedAVCProfileLevels[] = {
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel5},
{OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel51},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel1},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel1b},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel11},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel12},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel13},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel2 },
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel21},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel22},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel3 },
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel31},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel32},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel4},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel41},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel42},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel5},
{OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel51},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1 },
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1b},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel11},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel12},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel13},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel2 },
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel21},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel22},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel3 },
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel31},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel32},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel4},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel41},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel42},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel5},
{OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel51},
{-1,-1}
};
/* HEVC Supported Levels & profiles */
static VIDEO_PROFILE_LEVEL_TYPE SupportedHEVCProfileLevels[] = {
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel1},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel2},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel21},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel3},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel31},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel4},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel41},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel5},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel51},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel52},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel6},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel61},
{OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel62},
{-1,-1}
};
/*
* M A C R O S
*/
/*
* Initializes a data structure using a pointer to the structure.
* The initialization of OMX structures always sets up the nSize and nVersion fields
* of the structure.
*/
#define OMX_CONF_INIT_STRUCT_PTR(_variable_, _struct_name_) \
memset((_variable_), 0x0, sizeof(_struct_name_)); \
(_variable_)->nSize = sizeof(_struct_name_); \
(_variable_)->nVersion.s.nVersionMajor = 0x1; \
(_variable_)->nVersion.s.nVersionMinor = 0x1; \
(_variable_)->nVersion.s.nRevision = 0x0; \
(_variable_)->nVersion.s.nStep = 0x0
typedef enum VIDENC_CUSTOM_INDEX
{
VideoEncodeCustomParamStoreMetaDataInBuffers = OMX_IndexVendorStartUnused,
VideoEncodeCustomParamPrependSPSPPSToIDRFrames,
VideoEncodeCustomParamEnableAndroidNativeBuffers,
VideoEncodeCustomParamextendedVideo,
VideoEncodeCustomParamextendedVideoSuperframe,
VideoEncodeCustomParamextendedVideoSVCSkip,
VideoEncodeCustomParamextendedVideoVBR,
VideoEncodeCustomParamStoreANWBufferInMetadata,
VideoEncodeCustomParamextendedVideoPSkip,
} VIDENC_CUSTOM_INDEX;
static VIDDEC_CUSTOM_PARAM sVideoEncCustomParams[] =
{
{"OMX.google.android.index.storeMetaDataInBuffers",
(OMX_INDEXTYPE)VideoEncodeCustomParamStoreMetaDataInBuffers},
{"OMX.google.android.index.prependSPSPPSToIDRFrames",
(OMX_INDEXTYPE)VideoEncodeCustomParamPrependSPSPPSToIDRFrames},
{"OMX.google.android.index.enableAndroidNativeBuffers",
(OMX_INDEXTYPE)VideoEncodeCustomParamEnableAndroidNativeBuffers},
{"OMX.Topaz.index.param.extended_video",
(OMX_INDEXTYPE)VideoEncodeCustomParamextendedVideo},
{"OMX.aw.index.param.videoSuperFrameConfig",
(OMX_INDEXTYPE)VideoEncodeCustomParamextendedVideoSuperframe},
{"OMX.aw.index.param.videoSVCSkipConfig",
(OMX_INDEXTYPE)VideoEncodeCustomParamextendedVideoSVCSkip},
{"OMX.aw.index.param.videoVBRConfig",
(OMX_INDEXTYPE)VideoEncodeCustomParamextendedVideoVBR},
{"OMX.google.android.index.storeANWBufferInMetadata",
(OMX_INDEXTYPE)VideoEncodeCustomParamStoreANWBufferInMetadata},
{"OMX.aw.index.param.videoPSkipConfig",
(OMX_INDEXTYPE)VideoEncodeCustomParamextendedVideoPSkip}
};
typedef enum OMX_VENC_COMMANDTYPE
{
OMX_Venc_Cmd_Open,
OMX_Venc_Cmd_Close,
OMX_Venc_Cmd_Stop,
OMX_Venc_Cmd_Enc_Idle,
OMX_Venc_Cmd_ChangeBitrate,
OMX_Venc_Cmd_ChangeColorFormat,
OMX_Venc_Cmd_RequestIDRFrame,
OMX_Venc_Cmd_ChangeFramerate,
} OMX_VENC_COMMANDTYPE;
typedef enum OMX_VENC_INPUTBUFFER_STEP
{
OMX_VENC_STEP_GET_INPUTBUFFER,
OMX_VENC_STEP_GET_ALLOCBUFFER,
OMX_VENC_STEP_ADD_BUFFER_TO_ENC,
} OMX_VENC_INPUTBUFFER_STEP;
static void* ComponentThread(void* pThreadData);
static void* ComponentVencThread(void* pThreadData);
#ifdef __ANDROID__
#define GET_CALLING_PID (IPCThreadState::self()->getCallingPid())
static void getCallingProcessName(char *name)
{
char proc_node[128];
if (name == 0)
{
loge("error in params");
return;
}
memset(proc_node, 0, sizeof(proc_node));
sprintf(proc_node, "/proc/%d/cmdline", GET_CALLING_PID);
int fp = ::open(proc_node, O_RDONLY);
if (fp > 0)
{
memset(name, 0, 128);
::read(fp, name, 128);
::close(fp);
fp = 0;
logd("Calling process is: %s", name);
}
else
{
loge("Obtain calling process failed");
}
}
#endif
//* factory function executed by the core to create instances
void *get_omx_component_factory_fn(void)
{
logd("----get_omx_component_factory_fn");
return (new omx_venc);
}
void post_message_to_venc_and_wait(omx_venc *omx, OMX_S32 id)
{
int ret_value;
logv("omx_venc: post_message %d pipe out%d to venc\n", (int)id,omx->m_venc_cmdpipe[1]);
ret_value = write(omx->m_venc_cmdpipe[1], &id, sizeof(OMX_S32));
logv("post_message to pipe done %d\n",ret_value);
omx_sem_down(&omx->m_msg_sem);
}
void post_message_to_venc(omx_venc *omx, OMX_S32 id)
{
int ret_value;
logv("omx_vdec: post_message %d pipe out%d to venc\n", (int)id,omx->m_venc_cmdpipe[1]);
ret_value = write(omx->m_venc_cmdpipe[1], &id, sizeof(OMX_S32));
logv("post_message to pipe done %d\n",ret_value);
}
int parse_omx_enc_input_buffer(omx_venc *pSelf,
long long aw_buf_id,
int share_fd,
unsigned long *phy_addr)
{
int i;
int ret;
aw_ion_user_handle_t ion_handle;
for(i=0; i<NUM_MAX_IN_BUFFERS; i++)
{
//parse a new share fd
if(-1 == pSelf->mInputBufInfo[i].nAwBufId)
{
pSelf->mInputBufInfo[i].nAwBufId = aw_buf_id;
//get ion buffer handle
ret = CdcIonImport(pSelf->mIonFd, share_fd, &ion_handle);
if(ret < 0)
{
loge("use CdcIonImport get ion_handle error\n");
return -1;
}
pSelf->mInputBufInfo[i].handle_ion = ion_handle;
pSelf->mInputBufInfo[i].nShareFd = share_fd;
//get ion buffer fd
ret = CdcIonGetFd(pSelf->mIonFd, (uintptr_t)ion_handle);
if(ret < 0)
{
loge("use CdcIonImport get ion_handle error\n");
return -1;
}
pSelf->mInputBufInfo[i].nBufFd = ret;
//get phy address
if(CdcIonGetMemType() == MEMORY_IOMMU)
{
user_iommu_param sIommuBuf;
sIommuBuf.fd = pSelf->mInputBufInfo[i].nBufFd;
VideoEncoderGetVeIommuAddr(pSelf->m_encoder, &sIommuBuf);
pSelf->mInputBufInfo[i].nBufPhyAddr = (unsigned long)sIommuBuf.iommu_addr;
}
else
{
pSelf->mInputBufInfo[i].nBufPhyAddr = CdcIonGetPhyAdr(pSelf->mIonFd,
(uintptr_t)ion_handle);
}
break;
}
//get already parsed share fd's index
else if(aw_buf_id == pSelf->mInputBufInfo[i].nAwBufId)
break;
}
if(NUM_MAX_IN_BUFFERS == i)
{
loge("the omx_venc inputBuffer num is bigger than NUM_MAX_IN_BUFFERS[%d]\n",
NUM_MAX_IN_BUFFERS);
return -1;
}
*phy_addr = pSelf->mInputBufInfo[i].nBufPhyAddr;
logv("mInputBufInfo[%d], nShareFd:%d, nBufPhyAddr:%lx, handle:%lx, nBufFd:%d\n",
i,
pSelf->mInputBufInfo[i].nShareFd,
pSelf->mInputBufInfo[i].nBufPhyAddr,
(long)pSelf->mInputBufInfo[i].handle_ion,
pSelf->mInputBufInfo[i].nBufFd);
return 0;
}
int deparse_omx_enc_input_buffer(int nIonFd,
VideoEncoder *pEncoder,
OMXInputBufferInfoT *pInputBufInfo)
{
OMX_S32 i;
int ret;
for(i=0; i<NUM_MAX_IN_BUFFERS; i++)
{
OMXInputBufferInfoT *p;
p = pInputBufInfo + i;
if(p->nAwBufId != -1)
{
//deattach buf fd from ve
if(CdcIonGetMemType() == MEMORY_IOMMU)
{
user_iommu_param sIommuBuf;
sIommuBuf.fd = p->nBufFd;
VideoEncoderFreeVeIommuAddr(pEncoder, &sIommuBuf);
}
//close buf fd
if(p->nBufFd != -1)
{
ret = CdcIonClose(p->nBufFd);
if(ret < 0)
{
loge("CdcIonClose close buf fd error\n");
return -1;
}
}
//free ion handle
if(p->handle_ion)
{
ret = CdcIonFree(nIonFd, p->handle_ion);
if(ret < 0)
{
loge("CdcIonFree free ion_handle error\n");
return -1;
}
}
p->nShareFd = -1;
}
}
return 0;
}
omx_venc::omx_venc()
{
m_state = OMX_StateLoaded;
m_cRole[0] = 0;
m_cName[0] = 0;
m_eCompressionFormat = OMX_VIDEO_CodingUnused;
m_pAppData = NULL;
m_thread_id = 0;
m_venc_thread_id = 0;
m_cmdpipe[0] = 0;
m_cmdpipe[1] = 0;
m_cmddatapipe[0] = 0;
m_cmddatapipe[1] = 0;
m_venc_cmdpipe[0] = 0;
m_venc_cmdpipe[1] = 0;
m_firstFrameFlag = OMX_FALSE;
m_framerate = 30;
mIsFromCts = OMX_FALSE;
mIsFromVideoeditor = OMX_FALSE;
m_useAllocInputBuffer = OMX_FALSE;
m_useAndroidBuffer = OMX_FALSE;
mFirstInputFrame = OMX_TRUE;
m_usePSkip = OMX_FALSE;
mEmptyBufCnt = 0;
mFillBufCnt = 0;
mIonFd = -1;
memops = MemAdapterGetOpsS();
CdcMemOpen(memops);
#if PRINTF_FRAME_SIZE
mFrameCnt = 0;
mAllFrameSize = 0;
mTimeStart = 0;
mTimeOut = 999;//ms
#endif
memset(mCallingProcess,0,sizeof(mCallingProcess));
#ifdef __ANDROID__
getCallingProcessName(mCallingProcess);
if ((strcmp(mCallingProcess, "com.android.cts.media") == 0) ||
(strcmp(mCallingProcess, "com.android.cts.videoperf") == 0) ||
(strcmp(mCallingProcess, "com.android.pts.videoperf") == 0))
{
mIsFromCts = OMX_TRUE;
}
else if (strcmp(mCallingProcess, "com.android.videoeditor") == 0)
{
mIsFromVideoeditor = OMX_TRUE;
}
#endif
m_encoder = NULL;
memset(&m_Callbacks, 0, sizeof(m_Callbacks));
memset(&m_sInPortDefType, 0, sizeof(m_sInPortDefType));
memset(&m_sOutPortDefType, 0, sizeof(m_sOutPortDefType));
memset(&m_sInPortFormatType, 0, sizeof(m_sInPortFormatType));
memset(&m_sOutPortFormatType, 0, sizeof(m_sOutPortFormatType));
memset(&m_sPriorityMgmtType, 0, sizeof(m_sPriorityMgmtType));
memset(&m_sInBufSupplierType, 0, sizeof(m_sInBufSupplierType));
memset(&m_sOutBufSupplierType, 0, sizeof(m_sOutBufSupplierType));
memset(&m_sInBufList, 0, sizeof(m_sInBufList));
memset(&m_sOutBufList, 0, sizeof(m_sOutBufList));
memset(mInputBufInfo, 0, sizeof(mInputBufInfo));
pthread_mutex_init(&m_inBufMutex, NULL);
pthread_mutex_init(&m_outBufMutex, NULL);
pthread_mutex_init(&m_pipeMutex, NULL);
omx_sem_init(&m_msg_sem, 0);
omx_sem_init(&m_input_sem, 0);
logd("omx_enc Create!");
}
omx_venc::~omx_venc()
{
OMX_S32 nIndex;
// In case the client crashes, check for nAllocSize parameter.
// If this is greater than zero, there are elements in the list that are not free'd.
// In that case, free the elements.
pthread_mutex_lock(&m_inBufMutex);
for (nIndex=0; nIndex<m_sInBufList.nBufArrSize; nIndex++)
{
if (m_sInBufList.pBufArr[nIndex].pBuffer != NULL)
{
if (m_sInBufList.nAllocBySelfFlags & (1<<nIndex))
{
free(m_sInBufList.pBufArr[nIndex].pBuffer);
m_sInBufList.pBufArr[nIndex].pBuffer = NULL;
}
}
}
if (m_sInBufList.pBufArr != NULL)
{
free(m_sInBufList.pBufArr);
}
if (m_sInBufList.pBufHdrList != NULL)
{
free(m_sInBufList.pBufHdrList);
}
memset(&m_sInBufList, 0, sizeof(struct _BufferList));
m_sInBufList.nBufArrSize = m_sInPortDefType.nBufferCountActual;
pthread_mutex_unlock(&m_inBufMutex);
pthread_mutex_lock(&m_outBufMutex);
for (nIndex=0; nIndex<m_sOutBufList.nBufArrSize; nIndex++)
{
if (m_sOutBufList.pBufArr[nIndex].pBuffer != NULL)
{
if (m_sOutBufList.nAllocBySelfFlags & (1<<nIndex))
{
free(m_sOutBufList.pBufArr[nIndex].pBuffer);
m_sOutBufList.pBufArr[nIndex].pBuffer = NULL;
}
}
}
if (m_sOutBufList.pBufArr != NULL)
{
free(m_sOutBufList.pBufArr);
}
if (m_sOutBufList.pBufHdrList != NULL)
{
free(m_sOutBufList.pBufHdrList);
}
memset(&m_sOutBufList, 0, sizeof(struct _BufferList));
m_sOutBufList.nBufArrSize = m_sOutPortDefType.nBufferCountActual;
if(memops)
CdcMemClose(memops);
if (mIonFd != -1)
{
int ret = 0;
ret = CdcIonClose(mIonFd);
if(ret < 0)
loge("CdcIonClose ion fd error\n");
mIonFd = -1;
}
pthread_mutex_unlock(&m_outBufMutex);
pthread_mutex_destroy(&m_inBufMutex);
pthread_mutex_destroy(&m_outBufMutex);
pthread_mutex_destroy(&m_pipeMutex);
omx_sem_deinit(&m_msg_sem);
omx_sem_deinit(&m_input_sem);
logv("~omx_enc done!");
}
OMX_ERRORTYPE omx_venc::component_init(OMX_STRING pName)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
int err;
OMX_U32 nIndex;
char calling_process[256];
int i;
memset(calling_process, 0, sizeof(calling_process));
logd(" COMPONENT_INIT, name = %s", pName);
strncpy((char*)m_cName, pName, OMX_MAX_STRINGNAME_SIZE);
if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.avc", OMX_MAX_STRINGNAME_SIZE))
{
strncpy((char*)m_cRole, "video_encoder.avc", OMX_MAX_STRINGNAME_SIZE);
m_eCompressionFormat = OMX_VIDEO_CodingAVC;
}
else if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE))
{
strncpy((char*)m_cRole, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE);
m_eCompressionFormat = OMX_VIDEO_CodingHEVC;
}
else if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.h263", OMX_MAX_STRINGNAME_SIZE))
{
strncpy((char*)m_cRole, "video_encoder.avc", OMX_MAX_STRINGNAME_SIZE);
m_eCompressionFormat = OMX_VIDEO_CodingH263;
}
else if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.mpeg4", OMX_MAX_STRINGNAME_SIZE))
{
strncpy((char*)m_cRole, "video_encoder.avc", OMX_MAX_STRINGNAME_SIZE);
m_eCompressionFormat = OMX_VIDEO_CodingMPEG4;
}
else if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.mjpeg", OMX_MAX_STRINGNAME_SIZE))
{
strncpy((char*)m_cRole, "video_encoder.mjpeg", OMX_MAX_STRINGNAME_SIZE);
m_eCompressionFormat = OMX_VIDEO_CodingMJPEG;
}
else
{
logv("\nERROR:Unknown Component\n");
eRet = OMX_ErrorInvalidComponentName;
return eRet;
}
// init codec type
if (OMX_VIDEO_CodingAVC == m_eCompressionFormat)
{
m_vencCodecType = VENC_CODEC_H264;
}
else if (OMX_VIDEO_CodingVP8 == m_eCompressionFormat)
{
m_vencCodecType = VENC_CODEC_VP8;
}
else if (OMX_VIDEO_CodingMJPEG == m_eCompressionFormat)
{
m_vencCodecType = VENC_CODEC_JPEG;
}
else if (OMX_VIDEO_CodingHEVC == m_eCompressionFormat)
{
m_vencCodecType = VENC_CODEC_H265;
}
else
{
logd("need check codec type");
}
// Initialize component data structures to default values
OMX_CONF_INIT_STRUCT_PTR(&m_sPortParam, OMX_PORT_PARAM_TYPE);
m_sPortParam.nPorts = 0x2;
m_sPortParam.nStartPortNumber = 0x0;
// Initialize the video parameters for input port
OMX_CONF_INIT_STRUCT_PTR(&m_sInPortDefType, OMX_PARAM_PORTDEFINITIONTYPE);
m_sInPortDefType.nPortIndex = 0x0;
m_sInPortDefType.bEnabled = OMX_TRUE;
m_sInPortDefType.bPopulated = OMX_FALSE;
m_sInPortDefType.eDomain = OMX_PortDomainVideo;
m_sInPortDefType.format.video.nFrameWidth = 0;
m_sInPortDefType.format.video.nFrameHeight = 0;
m_sInPortDefType.eDir = OMX_DirInput;
//for 4k recorder @30fps
#ifdef CONF_SUPPORT_4K_30FPS_RECORDER
m_sInPortDefType.nBufferCountMin = 4;
m_sInPortDefType.nBufferCountActual = 4;
#else
m_sInPortDefType.nBufferCountMin = NUM_IN_BUFFERS;
m_sInPortDefType.nBufferCountActual = NUM_IN_BUFFERS;
#endif
#ifdef __ANDROID__
getCallingProcessName(calling_process);
if (strcmp(calling_process, HW_VIDEO_CALL_APK) == 0)
{
m_sInPortDefType.nBufferCountMin = 4;
m_sInPortDefType.nBufferCountActual = 4;
logd("HW_VIDOE_CALL:%s,F:%s,L:%d",HW_VIDEO_CALL_APK,__FUNCTION__,__LINE__);
}
#endif
m_sInPortDefType.nBufferSize = (OMX_U32)(m_sOutPortDefType.format.video.nFrameWidth *
m_sOutPortDefType.format.video.nFrameHeight * 3 / 2);
m_sInPortDefType.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; //fix it later
// Initialize the video parameters for output port
OMX_CONF_INIT_STRUCT_PTR(&m_sOutPortDefType, OMX_PARAM_PORTDEFINITIONTYPE);
m_sOutPortDefType.nPortIndex = 0x1;
m_sOutPortDefType.bEnabled = OMX_TRUE;
m_sOutPortDefType.bPopulated = OMX_FALSE;
m_sOutPortDefType.eDomain = OMX_PortDomainVideo;
m_sOutPortDefType.format.video.cMIMEType = (OMX_STRING)"YUV420";
m_sOutPortDefType.format.video.nFrameWidth = 176;
m_sOutPortDefType.format.video.nFrameHeight = 144;
m_sOutPortDefType.eDir = OMX_DirOutput;
//for 4k recorder @30fps
#ifdef CONF_SUPPORT_4K_30FPS_RECORDER
m_sOutPortDefType.nBufferCountMin = 6;
m_sOutPortDefType.nBufferCountActual = 6;
#else
m_sOutPortDefType.nBufferCountMin = NUM_OUT_BUFFERS;
m_sOutPortDefType.nBufferCountActual = NUM_OUT_BUFFERS;
#endif
if (strcmp(calling_process, HW_VIDEO_CALL_APK) == 0)
{
m_sOutPortDefType.nBufferCountMin = 4;
m_sOutPortDefType.nBufferCountActual = 4;
logd("HW_VIDOE_CALL:%s,F:%s,L:%d",HW_VIDEO_CALL_APK,__FUNCTION__,__LINE__);
}
m_sOutPortDefType.nBufferSize = OMX_VIDEO_ENC_INPUT_BUFFER_SIZE;
m_sOutPortDefType.format.video.eCompressionFormat = m_eCompressionFormat;
m_sOutPortDefType.format.video.cMIMEType = (OMX_STRING)"";
// Initialize the video compression format for input port
OMX_CONF_INIT_STRUCT_PTR(&m_sInPortFormatType, OMX_VIDEO_PARAM_PORTFORMATTYPE);
m_sInPortFormatType.nPortIndex = 0x0;
m_sInPortFormatType.nIndex = 0x2;
m_sInPortFormatType.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
m_inputcolorFormats[0] = OMX_COLOR_FormatYUV420SemiPlanar;
m_inputcolorFormats[1] = OMX_COLOR_FormatAndroidOpaque;
m_inputcolorFormats[2] = OMX_COLOR_FormatYVU420SemiPlanar;
// Initialize the compression format for output port
OMX_CONF_INIT_STRUCT_PTR(&m_sOutPortFormatType, OMX_VIDEO_PARAM_PORTFORMATTYPE);
m_sOutPortFormatType.nPortIndex = 0x1;
m_sOutPortFormatType.nIndex = 0x0;
m_sOutPortFormatType.eCompressionFormat = m_eCompressionFormat;
OMX_CONF_INIT_STRUCT_PTR(&m_sPriorityMgmtType, OMX_PRIORITYMGMTTYPE);
OMX_CONF_INIT_STRUCT_PTR(&m_sInBufSupplierType, OMX_PARAM_BUFFERSUPPLIERTYPE );
m_sInBufSupplierType.nPortIndex = 0x0;
OMX_CONF_INIT_STRUCT_PTR(&m_sOutBufSupplierType, OMX_PARAM_BUFFERSUPPLIERTYPE );
m_sOutBufSupplierType.nPortIndex = 0x1;
// Initalize the output bitrate
OMX_CONF_INIT_STRUCT_PTR(&m_sOutPutBitRateType, OMX_VIDEO_PARAM_BITRATETYPE);
m_sOutPutBitRateType.nPortIndex = 0x01;
m_sOutPutBitRateType.eControlRate = OMX_Video_ControlRateDisable;
m_sOutPutBitRateType.nTargetBitrate = DEFAULT_BITRATE; //default bitrate
// Initalize the output h264param
OMX_CONF_INIT_STRUCT_PTR(&m_sH264Type, OMX_VIDEO_PARAM_AVCTYPE);
m_sH264Type.nPortIndex = 0x01;
m_sH264Type.nSliceHeaderSpacing = 0;
m_sH264Type.nPFrames = -1;
m_sH264Type.nBFrames = -1;
m_sH264Type.bUseHadamard = OMX_TRUE; /*OMX_FALSE*/
m_sH264Type.nRefFrames = 1; /*-1; */
m_sH264Type.nRefIdx10ActiveMinus1 = -1;
m_sH264Type.nRefIdx11ActiveMinus1 = -1;
m_sH264Type.bEnableUEP = OMX_FALSE;
m_sH264Type.bEnableFMO = OMX_FALSE;
m_sH264Type.bEnableASO = OMX_FALSE;
m_sH264Type.bEnableRS = OMX_FALSE;
m_sH264Type.eProfile = OMX_VIDEO_AVCProfileBaseline; /*0x01;*/
m_sH264Type.eLevel = OMX_VIDEO_AVCLevel1; /*OMX_VIDEO_AVCLevel11;*/
m_sH264Type.nAllowedPictureTypes = -1;
m_sH264Type.bFrameMBsOnly = OMX_FALSE;
m_sH264Type.bMBAFF = OMX_FALSE;
m_sH264Type.bEntropyCodingCABAC = OMX_FALSE;
m_sH264Type.bWeightedPPrediction = OMX_FALSE;
m_sH264Type.nWeightedBipredicitonMode = -1;
m_sH264Type.bconstIpred = OMX_FALSE;
m_sH264Type.bDirect8x8Inference = OMX_FALSE;
m_sH264Type.bDirectSpatialTemporal = OMX_FALSE;
m_sH264Type.nCabacInitIdc = -1;
m_sH264Type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterDisable;
// Initalize the output h265param
OMX_CONF_INIT_STRUCT_PTR(&m_sH265Type, OMX_VIDEO_PARAM_HEVCTYPE);
m_sH265Type.nPortIndex = 0x01;
m_sH265Type.eProfile = OMX_VIDEO_HEVCProfileMain;
m_sH265Type.eLevel = OMX_VIDEO_HEVCMainTierLevel51;
m_sH265Type.nKeyFrameInterval = 30;
// Initialize the input buffer list
memset(&(m_sInBufList), 0x0, sizeof(BufferList));
m_sInBufList.pBufArr = (OMX_BUFFERHEADERTYPE*)malloc(sizeof(OMX_BUFFERHEADERTYPE) *
m_sInPortDefType.nBufferCountActual);
if (m_sInBufList.pBufArr == NULL)
{
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
memset(m_sInBufList.pBufArr, 0,
sizeof(OMX_BUFFERHEADERTYPE) * m_sInPortDefType.nBufferCountActual);
for (nIndex = 0; nIndex < m_sInPortDefType.nBufferCountActual; nIndex++)
{
OMX_CONF_INIT_STRUCT_PTR (&m_sInBufList.pBufArr[nIndex], OMX_BUFFERHEADERTYPE);
}
m_sInBufList.pBufHdrList = (OMX_BUFFERHEADERTYPE**)malloc(sizeof(OMX_BUFFERHEADERTYPE*) *
m_sInPortDefType.nBufferCountActual);
if (m_sInBufList.pBufHdrList == NULL)
{
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
m_sInBufList.nSizeOfList = 0;
m_sInBufList.nAllocSize = 0;
m_sInBufList.nWritePos = 0;
m_sInBufList.nReadPos = 0;
m_sInBufList.nAllocBySelfFlags = 0;
m_sInBufList.nSizeOfList = 0;
m_sInBufList.nBufArrSize = m_sInPortDefType.nBufferCountActual;
m_sInBufList.eDir = OMX_DirInput;
// Initialize the output buffer list
memset(&m_sOutBufList, 0x0, sizeof(BufferList));
m_sOutBufList.pBufArr = (OMX_BUFFERHEADERTYPE*)malloc(sizeof(OMX_BUFFERHEADERTYPE) *
m_sOutPortDefType.nBufferCountActual);
if (m_sOutBufList.pBufArr == NULL)
{
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
memset(m_sOutBufList.pBufArr, 0,
sizeof(OMX_BUFFERHEADERTYPE) * m_sOutPortDefType.nBufferCountActual);
for (nIndex = 0; nIndex < m_sOutPortDefType.nBufferCountActual; nIndex++)
{
OMX_CONF_INIT_STRUCT_PTR(&m_sOutBufList.pBufArr[nIndex], OMX_BUFFERHEADERTYPE);
}
m_sOutBufList.pBufHdrList = (OMX_BUFFERHEADERTYPE**)malloc(sizeof(OMX_BUFFERHEADERTYPE*) *
m_sOutPortDefType.nBufferCountActual);
if (m_sOutBufList.pBufHdrList == NULL)
{
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
m_sOutBufList.nSizeOfList = 0;
m_sOutBufList.nAllocSize = 0;
m_sOutBufList.nWritePos = 0;
m_sOutBufList.nReadPos = 0;
m_sOutBufList.nAllocBySelfFlags = 0;
m_sOutBufList.nSizeOfList = 0;
m_sOutBufList.nBufArrSize = m_sOutPortDefType.nBufferCountActual;
m_sOutBufList.eDir = OMX_DirOutput;
// Create the pipe used to send commands to the thread
err = pipe(m_cmdpipe);
if (err)
{
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
// Create the pipe used to send commands to the venc drv thread
err = pipe(m_venc_cmdpipe);
if (err)
{
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
// Create the pipe used to send command data to the thread
err = pipe(m_cmddatapipe);
if (err)
{
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
// Create the component thread
err = pthread_create(&m_thread_id, NULL, ComponentThread, this);
if ( err || !m_thread_id )
{
loge("create ComponentThread error!!!");
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
// Create venc thread
err = pthread_create(&m_venc_thread_id, NULL, ComponentVencThread, this);
if ( err || !m_venc_thread_id )
{
loge("create ComponentVencThread error!!!");
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
// init some param
m_useAndroidBuffer = OMX_FALSE;
m_useMetaDataInBuffers = OMX_FALSE;
m_prependSPSPPSToIDRFrames = OMX_FALSE;
memset(&mVideoExtParams, 0, sizeof(OMX_VIDEO_PARAMS_EXTENDED));
memset(&mVideoSuperFrame, 0, sizeof(OMX_VIDEO_PARAMS_SUPER_FRAME));
memset(&mVideoSVCSkip, 0, sizeof(OMX_VIDEO_PARAMS_SVC));
memset(&mVideoVBR, 0, sizeof(OMX_VIDEO_PARAMS_VBR));
if (strcmp(calling_process, HW_VIDEO_CALL_APK) == 0)
{
mVideoSuperFrame.bEnable = OMX_TRUE;
logd("VideoSuperFrame Enable HW_VIDOE_CALL:%s,F:%s,L:%d",
HW_VIDEO_CALL_APK,__FUNCTION__,__LINE__);
}
mIonFd = CdcIonOpen();
if (mIonFd < 0)
{
loge("open %s failed \n", ION_DEV_NAME);
eRet = OMX_ErrorInsufficientResources;
goto EXIT;
}
for(i=0; i<NUM_MAX_IN_BUFFERS; i++)
{
mInputBufInfo[i].nAwBufId = -1;
}
#if SAVE_BITSTREAM
OutFile = fopen("/data/camera/bitstream.dat", "wb");
if(OutFile == NULL)
{
loge("open save output file error\n");
eRet = OMX_ErrorInsufficientResources;
}
else
logd("open outFile '/data/camera/bitstream.dat'\n");
#endif
EXIT:
return eRet;
}
OMX_ERRORTYPE omx_venc::get_component_version(OMX_IN OMX_HANDLETYPE pHComp,
OMX_OUT OMX_STRING pComponentName,
OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
OMX_OUT OMX_UUIDTYPE* pComponentUUID)
{
logv(" COMPONENT_GET_VERSION");
CEDARC_UNUSE(pComponentUUID);
if (!pHComp || !pComponentName || !pComponentVersion || !pSpecVersion)
{
return OMX_ErrorBadParameter;
}
strcpy((char*)pComponentName, (char*)m_cName);
pComponentVersion->s.nVersionMajor = 1;
pComponentVersion->s.nVersionMinor = 1;
pComponentVersion->s.nRevision = 0;
pComponentVersion->s.nStep = 0;
pSpecVersion->s.nVersionMajor = 1;
pSpecVersion->s.nVersionMinor = 1;
pSpecVersion->s.nRevision = 0;
pSpecVersion->s.nStep = 0;
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_venc::send_command(OMX_IN OMX_HANDLETYPE pHComp,
OMX_IN OMX_COMMANDTYPE eCmd,
OMX_IN OMX_U32 uParam1,
OMX_IN OMX_PTR pCmdData)
{
ThrCmdType eCmdNative;
OMX_ERRORTYPE eError = OMX_ErrorNone;
CEDARC_UNUSE(pHComp);
if (m_state == OMX_StateInvalid)
{
loge("ERROR: Send Command in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (eCmd == OMX_CommandMarkBuffer && pCmdData == NULL)
{
loge("ERROR: Send OMX_CommandMarkBuffer command but pCmdData invalid.");
return OMX_ErrorBadParameter;
}
switch (eCmd)
{
case OMX_CommandStateSet:
{
logv(" COMPONENT_SEND_COMMAND: OMX_CommandStateSet");
eCmdNative = SetState;
break;
}
case OMX_CommandFlush:
{
logv(" COMPONENT_SEND_COMMAND: OMX_CommandFlush");
eCmdNative = Flush;
if ((int)uParam1 > 1 && (int)uParam1 != -1)
{
loge("Error: Send OMX_CommandFlush command but uParam1 invalid.");
return OMX_ErrorBadPortIndex;
}
break;
}
case OMX_CommandPortDisable:
{
logv(" COMPONENT_SEND_COMMAND: OMX_CommandPortDisable");
eCmdNative = StopPort;
break;
}
case OMX_CommandPortEnable:
{
logv(" COMPONENT_SEND_COMMAND: OMX_CommandPortEnable");
eCmdNative = RestartPort;
break;
}
case OMX_CommandMarkBuffer:
{
logv(" COMPONENT_SEND_COMMAND: OMX_CommandMarkBuffer");
eCmdNative = MarkBuf;
if (uParam1 > 0)
{
loge("Error: Send OMX_CommandMarkBuffer command but uParam1 invalid.");
return OMX_ErrorBadPortIndex;
}
break;
}
default:
{
return OMX_ErrorBadPortIndex;
}
}
post_event(eCmdNative, uParam1, pCmdData);
return eError;
}
OMX_ERRORTYPE omx_venc::get_parameter(OMX_IN OMX_HANDLETYPE pHComp,
OMX_IN OMX_INDEXTYPE eParamIndex,
OMX_INOUT OMX_PTR pParamData)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
CEDARC_UNUSE(pHComp);
if (m_state == OMX_StateInvalid)
{
logv("Get Param in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (pParamData == NULL)
{
logv("Get Param in Invalid pParamData \n");
return OMX_ErrorBadParameter;
}
switch (eParamIndex)
{
case OMX_IndexParamVideoInit:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamVideoInit");
memcpy(pParamData, &m_sPortParam, sizeof(OMX_PORT_PARAM_TYPE));
break;
}
case OMX_IndexParamPortDefinition:
{
// android::CallStack stack;
// stack.update(1, 100);
// stack.dump("get_parameter");
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamPortDefinition");
if (((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nPortIndex ==
m_sInPortDefType.nPortIndex)
{
memcpy(pParamData, &m_sInPortDefType, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
}
else if (((OMX_PARAM_PORTDEFINITIONTYPE*)(pParamData))->nPortIndex ==
m_sOutPortDefType.nPortIndex)
{
memcpy(pParamData, &m_sOutPortDefType, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
logv(" width = %d, height = %d", (int)m_sOutPortDefType.format.video.nFrameWidth,
(int)m_sOutPortDefType.format.video.nFrameHeight);
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoPortFormat:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamVideoPortFormat");
OMX_VIDEO_PARAM_PORTFORMATTYPE * param_portformat_type =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)(pParamData);
if (param_portformat_type->nPortIndex == m_sInPortFormatType.nPortIndex)
{
if (param_portformat_type->nIndex > m_sInPortFormatType.nIndex)
{
eError = OMX_ErrorNoMore;
}
else
{
param_portformat_type->eCompressionFormat = (OMX_VIDEO_CODINGTYPE)0;
param_portformat_type->eColorFormat =
m_inputcolorFormats[param_portformat_type->nIndex];
}
}
else if (((OMX_VIDEO_PARAM_PORTFORMATTYPE*)(pParamData))->nPortIndex ==
m_sOutPortFormatType.nPortIndex)
{
if (((OMX_VIDEO_PARAM_PORTFORMATTYPE*)(pParamData))->nIndex >
m_sOutPortFormatType.nIndex)
{
eError = OMX_ErrorNoMore;
}
else
{
memcpy(pParamData, &m_sOutPortFormatType,
sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
}
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamStandardComponentRole:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamStandardComponentRole");
OMX_PARAM_COMPONENTROLETYPE* comp_role;
comp_role = (OMX_PARAM_COMPONENTROLETYPE *) pParamData;
comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
comp_role->nSize = sizeof(*comp_role);
strncpy((char*)comp_role->cRole, (const char*)m_cRole, OMX_MAX_STRINGNAME_SIZE);
break;
}
case OMX_IndexParamPriorityMgmt:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamPriorityMgmt");
memcpy(pParamData, &m_sPriorityMgmtType, sizeof(OMX_PRIORITYMGMTTYPE));
break;
}
case OMX_IndexParamCompBufferSupplier:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamCompBufferSupplier");
OMX_PARAM_BUFFERSUPPLIERTYPE* pBuffSupplierParam =
(OMX_PARAM_BUFFERSUPPLIERTYPE*)pParamData;
if (pBuffSupplierParam->nPortIndex == 1)
{
pBuffSupplierParam->eBufferSupplier = m_sOutBufSupplierType.eBufferSupplier;
}
else if (pBuffSupplierParam->nPortIndex == 0)
{
pBuffSupplierParam->eBufferSupplier = m_sInBufSupplierType.eBufferSupplier;
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoBitrate:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamVideoBitrate");
if (((OMX_VIDEO_PARAM_BITRATETYPE*)(pParamData))->nPortIndex ==
m_sOutPutBitRateType.nPortIndex)
{
memcpy(pParamData,&m_sOutPutBitRateType, sizeof(OMX_VIDEO_PARAM_BITRATETYPE));
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoAvc:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamVideoAvc");
OMX_VIDEO_PARAM_AVCTYPE* pComponentParam = (OMX_VIDEO_PARAM_AVCTYPE*)pParamData;
if (pComponentParam->nPortIndex == m_sH264Type.nPortIndex)
{
memcpy(pComponentParam, &m_sH264Type, sizeof(OMX_VIDEO_PARAM_AVCTYPE));
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamAudioInit:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamAudioInit");
OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) pParamData;
audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
audioPortParamType->nPorts = 0;
audioPortParamType->nStartPortNumber = 0;
break;
}
case OMX_IndexParamImageInit:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamImageInit");
OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) pParamData;
imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
imagePortParamType->nPorts = 0;
imagePortParamType->nStartPortNumber = 0;
break;
}
case OMX_IndexParamOtherInit:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamOtherInit");
OMX_PORT_PARAM_TYPE *otherPortParamType = (OMX_PORT_PARAM_TYPE *) pParamData;
otherPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
otherPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
otherPortParamType->nPorts = 0;
otherPortParamType->nStartPortNumber = 0;
break;
}
case OMX_IndexParamVideoH263:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamVideoH263");
logv("get_parameter: OMX_IndexParamVideoH263, do nothing.\n");
break;
}
case OMX_IndexParamVideoMpeg4:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamVideoMpeg4");
logv("get_parameter: OMX_IndexParamVideoMpeg4, do nothing.\n");
break;
}
case OMX_IndexParamVideoProfileLevelQuerySupported:
{
VIDEO_PROFILE_LEVEL_TYPE* pProfileLevel = NULL;
OMX_U32 nNumberOfProfiles = 0;
OMX_VIDEO_PARAM_PROFILELEVELTYPE *pParamProfileLevel =
(OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pParamData;
pParamProfileLevel->nPortIndex = m_sOutPortDefType.nPortIndex;
/* Choose table based on compression format */
switch (m_sOutPortDefType.format.video.eCompressionFormat)
{
case OMX_VIDEO_CodingAVC:
{
pProfileLevel = SupportedAVCProfileLevels;
nNumberOfProfiles = sizeof(SupportedAVCProfileLevels) /
sizeof (VIDEO_PROFILE_LEVEL_TYPE);
break;
}
case OMX_VIDEO_CodingHEVC:
{
pProfileLevel = SupportedHEVCProfileLevels;
nNumberOfProfiles = sizeof(SupportedHEVCProfileLevels) /
sizeof (VIDEO_PROFILE_LEVEL_TYPE);
break;
}
case OMX_VIDEO_CodingH263:
{
pProfileLevel = SupportedH263ProfileLevels;
nNumberOfProfiles = sizeof(SupportedH263ProfileLevels) /
sizeof (VIDEO_PROFILE_LEVEL_TYPE);
break;
}
default:
{
return OMX_ErrorBadParameter;
}
}
if (pParamProfileLevel->nProfileIndex >= (nNumberOfProfiles - 1))
{
return OMX_ErrorBadParameter;
}
/* Point to table entry based on index */
pProfileLevel += pParamProfileLevel->nProfileIndex;
/* -1 indicates end of table */
if (pProfileLevel->nProfile != -1)
{
pParamProfileLevel->eProfile = pProfileLevel->nProfile;
pParamProfileLevel->eLevel = pProfileLevel->nLevel;
eError = OMX_ErrorNone;
}
else
{
eError = OMX_ErrorNoMore;
}
break;
}
default:
{
switch ((VIDENC_CUSTOM_INDEX)eParamIndex)
{
case VideoEncodeCustomParamextendedVideo:
{
logd("get VideoEncodeCustomParamextendedVideo");
memcpy(pParamData,&mVideoExtParams, sizeof(OMX_VIDEO_PARAMS_EXTENDED));
break;
}
case VideoEncodeCustomParamextendedVideoSuperframe:
{
logd("get VideoEncodeCustomParamextendedVideoSuperframe");
memcpy(pParamData,&mVideoSuperFrame, sizeof(OMX_VIDEO_PARAMS_SUPER_FRAME));
break;
}
case VideoEncodeCustomParamextendedVideoSVCSkip:
{
logd("get VideoEncodeCustomParamextendedVideoSVCSkip");
memcpy(pParamData, &mVideoSVCSkip, sizeof(OMX_VIDEO_PARAMS_SVC));
break;
}
case VideoEncodeCustomParamextendedVideoVBR:
{
logd("get VideoEncodeCustomParamextendedVideoVBR\n");
memcpy(pParamData, &mVideoVBR, sizeof(OMX_VIDEO_PARAMS_VBR));
break;
}
case VideoEncodeCustomParamStoreANWBufferInMetadata:
{
break;
}
case VideoEncodeCustomParamextendedVideoPSkip:
{
logd("get VideoEncodeCustomParamextendedVideoPSkip\n");
break;
}
default:
{
switch ((OMX_INDEXEXTTYPE)eParamIndex)
{
case OMX_IndexParamVideoHevc:
{
logv(" COMPONENT_GET_PARAMETER: OMX_IndexParamVideoHevc");
OMX_VIDEO_PARAM_HEVCTYPE* pComponentParam
= (OMX_VIDEO_PARAM_HEVCTYPE*)pParamData;
if (pComponentParam->nPortIndex == m_sH265Type.nPortIndex)
{
memcpy(pComponentParam,
&m_sH265Type, sizeof(OMX_VIDEO_PARAM_HEVCTYPE));
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamConsumerUsageBits:
{
OMX_U32 *usageBits = (OMX_U32 *)pParamData;
/*usageBits = GRALLOC_USAGE_HW_2D;*/
break;
}
default:
{
loge("getparameter: unknown param %p\n", pParamData);
eError = OMX_ErrorUnsupportedIndex;
break;
}
}
}
break;
}
break;
}
}
return eError;
}
OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE pHComp,
OMX_IN OMX_INDEXTYPE eParamIndex,
OMX_IN OMX_PTR pParamData)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
CEDARC_UNUSE(pHComp);
if (m_state == OMX_StateInvalid)
{
logv("Set Param in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (pParamData == NULL)
{
logv("Get Param in Invalid pParamData \n");
return OMX_ErrorBadParameter;
}
logv("set_parameter, eParamIndex: %x", eParamIndex);
switch (eParamIndex)
{
case OMX_IndexParamPortDefinition:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamPortDefinition");
if (((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nPortIndex ==
m_sInPortDefType.nPortIndex)
{
logv("in, nPortIndex: %d",
(int)(((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual));
if (((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual !=
m_sInPortDefType.nBufferCountActual)
{
int nBufCnt;
int nIndex;
pthread_mutex_lock(&m_inBufMutex);
if (m_sInBufList.pBufArr != NULL)
free(m_sInBufList.pBufArr);
if (m_sInBufList.pBufHdrList != NULL)
free(m_sInBufList.pBufHdrList);
nBufCnt = ((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual;
logv(" allocate %d buffers.", (int)nBufCnt);
m_sInBufList.pBufArr =
(OMX_BUFFERHEADERTYPE*)malloc(sizeof(OMX_BUFFERHEADERTYPE)* nBufCnt);
m_sInBufList.pBufHdrList =
(OMX_BUFFERHEADERTYPE**)malloc(sizeof(OMX_BUFFERHEADERTYPE*)* nBufCnt);
for (nIndex = 0; nIndex < nBufCnt; nIndex++)
{
OMX_CONF_INIT_STRUCT_PTR (&m_sInBufList.pBufArr[nIndex],
OMX_BUFFERHEADERTYPE);
}
m_sInBufList.nSizeOfList = 0;
m_sInBufList.nAllocSize = 0;
m_sInBufList.nWritePos = 0;
m_sInBufList.nReadPos = 0;
m_sInBufList.nAllocBySelfFlags = 0;
m_sInBufList.nSizeOfList = 0;
m_sInBufList.nBufArrSize = nBufCnt;
m_sInBufList.eDir = OMX_DirInput;
pthread_mutex_unlock(&m_inBufMutex);
}
memcpy(&m_sInPortDefType, pParamData, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
logd("init_input_port: stride = %d, width = %d, height = %d",
(int)m_sInPortDefType.format.video.nStride,
(int)m_sInPortDefType.format.video.nFrameWidth,
(int)m_sInPortDefType.format.video.nFrameHeight);
}
else if (((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nPortIndex ==
m_sOutPortDefType.nPortIndex)
{
logv("out, nPortIndex: %d",
(int)((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual);
if (((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual !=
m_sOutPortDefType.nBufferCountActual)
{
int nBufCnt;
int nIndex;
pthread_mutex_lock(&m_outBufMutex);
if (m_sOutBufList.pBufArr != NULL)
{
free(m_sOutBufList.pBufArr);
}
if (m_sOutBufList.pBufHdrList != NULL)
{
free(m_sOutBufList.pBufHdrList);
}
nBufCnt = ((OMX_PARAM_PORTDEFINITIONTYPE *)(pParamData))->nBufferCountActual;
logv(" allocate %d buffers.", (int)nBufCnt);
// Initialize the output buffer list
m_sOutBufList.pBufArr =
(OMX_BUFFERHEADERTYPE*)malloc(sizeof(OMX_BUFFERHEADERTYPE) * nBufCnt);
m_sOutBufList.pBufHdrList =
(OMX_BUFFERHEADERTYPE**) malloc(sizeof(OMX_BUFFERHEADERTYPE*) * nBufCnt);
for (nIndex = 0; nIndex < nBufCnt; nIndex++)
{
OMX_CONF_INIT_STRUCT_PTR (&m_sOutBufList.pBufArr[nIndex],
OMX_BUFFERHEADERTYPE);
}
m_sOutBufList.nSizeOfList = 0;
m_sOutBufList.nAllocSize = 0;
m_sOutBufList.nWritePos = 0;
m_sOutBufList.nReadPos = 0;
m_sOutBufList.nAllocBySelfFlags = 0;
m_sOutBufList.nSizeOfList = 0;
m_sOutBufList.nBufArrSize = nBufCnt;
m_sOutBufList.eDir = OMX_DirOutput;
pthread_mutex_unlock(&m_outBufMutex);
}
memcpy(&m_sOutPortDefType, pParamData, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
m_sOutPortDefType.nBufferSize =
m_sOutPortDefType.format.video.nFrameWidth *
m_sOutPortDefType.format.video.nFrameHeight * 3 / 2;
m_sOutPortDefType.nBufferSize = \
omx_venc_align(m_sOutPortDefType.nBufferSize, BUF_ALIGN_SIZE);
m_framerate = (m_sInPortDefType.format.video.xFramerate);
logd("m_framerate: %d", (int)m_framerate);
}
else
eError = OMX_ErrorBadPortIndex;
break;
}
case OMX_IndexParamVideoPortFormat:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamVideoPortFormat");
OMX_VIDEO_PARAM_PORTFORMATTYPE * param_portformat_type =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)(pParamData);
if (param_portformat_type->nPortIndex == m_sInPortFormatType.nPortIndex)
{
if (param_portformat_type->nIndex > m_sInPortFormatType.nIndex)
{
eError = OMX_ErrorNoMore;
}
else
{
m_sInPortFormatType.eColorFormat = param_portformat_type->eColorFormat;
m_sInPortDefType.format.video.eColorFormat = m_sInPortFormatType.eColorFormat;
}
}
else if (((OMX_VIDEO_PARAM_PORTFORMATTYPE*)(pParamData))->nPortIndex ==
m_sOutPortFormatType.nPortIndex)
{
if (((OMX_VIDEO_PARAM_PORTFORMATTYPE*)(pParamData))->nIndex >
m_sOutPortFormatType.nIndex)
{
eError = OMX_ErrorNoMore;
}
else
{
memcpy(&m_sOutPortFormatType, pParamData,
sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
}
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamStandardComponentRole:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamStandardComponentRole");
OMX_PARAM_COMPONENTROLETYPE *comp_role;
comp_role = (OMX_PARAM_COMPONENTROLETYPE *) pParamData;
logv("set_parameter: OMX_IndexParamStandardComponentRole %s\n", comp_role->cRole);
if ((OMX_StateLoaded == m_state)
/* && !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)*/)
{
logv("Set Parameter called in valid state");
}
else
{
logv("Set Parameter called in Invalid State\n");
return OMX_ErrorIncorrectStateOperation;
}
if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.avc",
OMX_MAX_STRINGNAME_SIZE))
{
if (!strncmp((char*)comp_role->cRole, "video_encoder.avc",
OMX_MAX_STRINGNAME_SIZE))
{
strncpy((char*)m_cRole,"video_encoder.avc", OMX_MAX_STRINGNAME_SIZE);
}
else
{
logv("Setparameter: unknown Index %s\n", comp_role->cRole);
eError =OMX_ErrorUnsupportedSetting;
}
}
else if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.hevc",
OMX_MAX_STRINGNAME_SIZE))
{
if (!strncmp((char*)comp_role->cRole, "video_encoder.hevc",
OMX_MAX_STRINGNAME_SIZE))
{
strncpy((char*)m_cRole,"video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE);
}
else
{
logv("Setparameter: unknown Index %s\n", comp_role->cRole);
eError =OMX_ErrorUnsupportedSetting;
}
}
else if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.mjpeg",
OMX_MAX_STRINGNAME_SIZE))
{
if (!strncmp((char*)comp_role->cRole, "video_encoder.mjpeg",
OMX_MAX_STRINGNAME_SIZE))
{
strncpy((char*)m_cRole,"video_encoder.mjpeg", OMX_MAX_STRINGNAME_SIZE);
}
else
{
logv("Setparameter: unknown Index %s\n", comp_role->cRole);
eError =OMX_ErrorUnsupportedSetting;
}
}
else
{
logv("Setparameter: unknown param %s\n", m_cName);
eError = OMX_ErrorInvalidComponentName;
}
break;
}
case OMX_IndexParamPriorityMgmt:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamPriorityMgmt");
if (m_state != OMX_StateLoaded)
{
logv("Set Parameter called in Invalid State\n");
return OMX_ErrorIncorrectStateOperation;
}
OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) pParamData;
m_sPriorityMgmtType.nGroupID = priorityMgmtype->nGroupID;
m_sPriorityMgmtType.nGroupPriority = priorityMgmtype->nGroupPriority;
break;
}
case OMX_IndexParamCompBufferSupplier:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamCompBufferSupplier");
OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
(OMX_PARAM_BUFFERSUPPLIERTYPE*) pParamData;
logv("set_parameter: OMX_IndexParamCompBufferSupplier %d\n",
bufferSupplierType->eBufferSupplier);
if (bufferSupplierType->nPortIndex == 0)
m_sInBufSupplierType.eBufferSupplier = bufferSupplierType->eBufferSupplier;
else if (bufferSupplierType->nPortIndex == 1)
m_sOutBufSupplierType.eBufferSupplier = bufferSupplierType->eBufferSupplier;
else
eError = OMX_ErrorBadPortIndex;
break;
}
case OMX_IndexParamVideoBitrate:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamVideoBitrate");
OMX_VIDEO_PARAM_BITRATETYPE* pComponentParam =
(OMX_VIDEO_PARAM_BITRATETYPE*)pParamData;
if (pComponentParam->nPortIndex == m_sOutPutBitRateType.nPortIndex)
{
memcpy(&m_sOutPutBitRateType,pComponentParam, sizeof(OMX_VIDEO_PARAM_BITRATETYPE));
if (!m_sOutPutBitRateType.nTargetBitrate)
{
m_sOutPutBitRateType.nTargetBitrate = DEFAULT_BITRATE;
}
m_sOutPortDefType.format.video.nBitrate = m_sOutPutBitRateType.nTargetBitrate;
if (m_state == OMX_StateExecuting && m_encoder)
{
post_message_to_venc(this, OMX_Venc_Cmd_ChangeBitrate);
}
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoAvc:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamVideoAvc");
OMX_VIDEO_PARAM_AVCTYPE* pComponentParam = (OMX_VIDEO_PARAM_AVCTYPE*)pParamData;
if (pComponentParam->nPortIndex == m_sH264Type.nPortIndex)
{
memcpy(&m_sH264Type,pComponentParam, sizeof(OMX_VIDEO_PARAM_AVCTYPE));
//CalculateBufferSize(pCompPortOut->pPortDef, pComponentPrivate);
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoH263:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamVideoH263");
logv("set_parameter: OMX_IndexParamVideoH263, do nothing.\n");
break;
}
case OMX_IndexParamVideoMpeg4:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamVideoMpeg4");
logv("set_parameter: OMX_IndexParamVideoMpeg4, do nothing.\n");
break;
}
case OMX_IndexParamVideoIntraRefresh:
{
OMX_VIDEO_PARAM_INTRAREFRESHTYPE* pComponentParam =
(OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)pParamData;
if (pComponentParam->nPortIndex == 1 &&
pComponentParam->eRefreshMode == OMX_VIDEO_IntraRefreshCyclic)
{
int mbWidth, mbHeight;
mbWidth = (m_sInPortDefType.format.video.nFrameWidth + 15)/16;
mbHeight = (m_sInPortDefType.format.video.nFrameHeight + 15)/16;
m_vencCyclicIntraRefresh.bEnable = 1;
m_vencCyclicIntraRefresh.nBlockNumber = mbWidth*mbHeight/pComponentParam->nCirMBs;
logd("m_vencCyclicIntraRefresh.nBlockNumber: %d",
m_vencCyclicIntraRefresh.nBlockNumber);
}
break;
}
default:
{
#ifdef __ANDROID__
switch ((VIDENC_CUSTOM_INDEX)eParamIndex)
{
case VideoEncodeCustomParamStoreMetaDataInBuffers:
{
OMX_BOOL bFlag = ((StoreMetaDataInBuffersParams*)pParamData)->bStoreMetaData;;
if (((StoreMetaDataInBuffersParams*)pParamData)->nPortIndex == 0)
{
m_useMetaDataInBuffers = bFlag;
}
else
{
if (bFlag)
{
eError = OMX_ErrorUnsupportedSetting;
}
}
logd(" COMPONENT_SET_PARAMETER: \
VideoEncodeCustomParamStoreMetaDataInBuffers %d",
m_useMetaDataInBuffers);
break;
}
case VideoEncodeCustomParamPrependSPSPPSToIDRFrames:
{
m_prependSPSPPSToIDRFrames =
((PrependSPSPPSToIDRFramesParams*)pParamData)->bEnable;
logd(" COMPONENT_SET_PARAMETER: \
VideoEncodeCustomParamPrependSPSPPSToIDRFrames %d",
m_prependSPSPPSToIDRFrames);
break;
}
case VideoEncodeCustomParamEnableAndroidNativeBuffers:
{
OMX_BOOL bFlag = ((EnableAndroidNativeBuffersParams*)pParamData)->enable;
OMX_U32 index = ((EnableAndroidNativeBuffersParams*)pParamData)->nPortIndex;
logd("COMPONENT_SET_PARAMETER: \
VideoEncodeCustomParamEnableAndroidNativeBuffers, \
nPortIndex: %d,enable:%d", (int)index, (int)bFlag);
if(index == 0)
m_useAndroidBuffer = bFlag;
break;
}
case VideoEncodeCustomParamextendedVideo:
{
logd("set VideoEncodeCustomParamextendedVideo");
memcpy(&mVideoExtParams, pParamData, sizeof(OMX_VIDEO_PARAMS_EXTENDED));
break;
}
case VideoEncodeCustomParamextendedVideoSuperframe:
{
logd("set VideoEncodeCustomParamextendedVideoSuperframe");
memcpy(&mVideoSuperFrame, pParamData, sizeof(OMX_VIDEO_PARAMS_SUPER_FRAME));
break;
}
case VideoEncodeCustomParamextendedVideoSVCSkip:
{
logd("set VideoEncodeCustomParamextendedVideoSVCSkip\n");
memcpy(&mVideoSVCSkip, pParamData, sizeof(OMX_VIDEO_PARAMS_SVC));
break;
}
case VideoEncodeCustomParamextendedVideoVBR:
{
logd("set VideoEncodeCustomParamextendedVideoVBR\n");
memcpy(&mVideoVBR, pParamData, sizeof(OMX_VIDEO_PARAMS_VBR));
break;
}
case VideoEncodeCustomParamStoreANWBufferInMetadata:
{
OMX_BOOL bFlag = ((StoreMetaDataInBuffersParams*)pParamData)->bStoreMetaData;
OMX_U32 index = ((StoreMetaDataInBuffersParams*)pParamData)->nPortIndex;
logd("=== VideoEncodeCustomParamStoreANWBufferInMetadata, flag: %d", bFlag);
if(index == 0)
m_useAndroidBuffer = bFlag;
break;
}
case VideoEncodeCustomParamextendedVideoPSkip:
{
logd("set VideoEncodeCustomParamextendedVideoPSkip\n");
m_usePSkip = (*(OMX_BOOL *)pParamData);
break;
}
default:
{
switch ((OMX_INDEXEXTTYPE)eParamIndex)
{
case OMX_IndexParamVideoHevc:
{
logv(" COMPONENT_SET_PARAMETER: OMX_IndexParamVideoHevc");
OMX_VIDEO_PARAM_HEVCTYPE* pComponentParam
= (OMX_VIDEO_PARAM_HEVCTYPE*)pParamData;
if (pComponentParam->nPortIndex == m_sH265Type.nPortIndex)
{
memcpy(&m_sH265Type,
pComponentParam, sizeof(OMX_VIDEO_PARAM_HEVCTYPE));
//CalculateBufferSize(pCompPortOut->pPortDef, pComponentPrivate);
}
else
{
eError = OMX_ErrorBadPortIndex;
}
break;
}
default:
{
loge("Setparameter: unknown param %x\n", eParamIndex);
eError = OMX_ErrorUnsupportedIndex;
break;
}
}
}
}
#else
eError = OMX_ErrorUnsupportedIndex;
#endif
}
}
return eError;
}
OMX_ERRORTYPE omx_venc::get_config(OMX_IN OMX_HANDLETYPE pHComp,
OMX_IN OMX_INDEXTYPE eConfigIndex,
OMX_INOUT OMX_PTR pConfigData)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
logv(" COMPONENT_GET_CONFIG: index = %d", eConfigIndex);
CEDARC_UNUSE(pHComp);
CEDARC_UNUSE(pConfigData);
if (m_state == OMX_StateInvalid)
{
logv("get_config in Invalid State\n");
return OMX_ErrorInvalidState;
}
switch (eConfigIndex)
{
default:
{
logv("get_config: unknown param %d\n",eConfigIndex);
eError = OMX_ErrorUnsupportedIndex;
}
}
return eError;
}
OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE pHComp,
OMX_IN OMX_INDEXTYPE eConfigIndex,
OMX_IN OMX_PTR pConfigData)
{
logv(" COMPONENT_SET_CONFIG: index = %d", eConfigIndex);
CEDARC_UNUSE(pHComp);
if (m_state == OMX_StateInvalid)
{
logv("set_config in Invalid State\n");
return OMX_ErrorInvalidState;
}
OMX_ERRORTYPE eError = OMX_ErrorNone;
switch (eConfigIndex)
{
case OMX_IndexConfigVideoIntraVOPRefresh:
{
if (m_state == OMX_StateExecuting && m_encoder)
{
post_message_to_venc(this, OMX_Venc_Cmd_RequestIDRFrame);
logd("venc, OMX_Venc_Cmd_RequestIDRFrame");
}
break;
}
case OMX_IndexConfigVideoBitrate:
{
OMX_VIDEO_CONFIG_BITRATETYPE* pData = (OMX_VIDEO_CONFIG_BITRATETYPE*)(pConfigData);
if (pData->nPortIndex == 1)
{
if (m_state == OMX_StateExecuting && m_encoder)
{
m_sOutPortDefType.format.video.nBitrate = pData->nEncodeBitrate;
post_message_to_venc(this, OMX_Venc_Cmd_ChangeBitrate);
logv("FUNC:%s, LINE:%d , pData->nEncodeBitrate = %d",
__FUNCTION__,__LINE__,pData->nEncodeBitrate);
}
}
break;
}
case OMX_IndexConfigVideoFramerate:
{
OMX_CONFIG_FRAMERATETYPE* pData = (OMX_CONFIG_FRAMERATETYPE*)(pConfigData);
logd("Microphone, FUNC:%s, LINE:%d", __FUNCTION__,__LINE__);
if (pData->nPortIndex == 0)
{
if (m_state == OMX_StateExecuting && m_encoder)
{
m_sInPortDefType.format.video.xFramerate = pData->xEncodeFramerate;
m_framerate = (m_sInPortDefType.format.video.xFramerate);
post_message_to_venc(this, OMX_Venc_Cmd_ChangeFramerate);
logv("FUNC:%s, LINE:%d , pData->xEncodeFramerate = %d",
__FUNCTION__,__LINE__,m_framerate);
}
}
break;
}
default:
{
logv("get_config: unknown param %d\n",eConfigIndex);
eError = OMX_ErrorUnsupportedIndex;
break;
}
}
return eError;
}
OMX_ERRORTYPE omx_venc::get_extension_index(OMX_IN OMX_HANDLETYPE pHComp,
OMX_IN OMX_STRING pParamName,
OMX_OUT OMX_INDEXTYPE* pIndexType)
{
unsigned int nIndex;
OMX_ERRORTYPE eError = OMX_ErrorUndefined;
logv(" COMPONENT_GET_EXTENSION_INDEX: param name = %s", pParamName);
if (m_state == OMX_StateInvalid)
{
logv("Get Extension Index in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (pHComp == NULL)
{
return OMX_ErrorBadParameter;
}
if(strcmp((char *)pParamName, "OMX.google.android.index.storeANWBufferInMetadata")
== 0)
{
logw("do not support OMX.google.android.index.storeANWBufferInMetadata\n");
return OMX_ErrorUnsupportedIndex;
}
for (nIndex = 0; nIndex < sizeof(sVideoEncCustomParams)/sizeof(VIDDEC_CUSTOM_PARAM); nIndex++)
{
if (strcmp((char *)pParamName, (char *)&(sVideoEncCustomParams[nIndex].cCustomParamName))
== 0)
{
*pIndexType = sVideoEncCustomParams[nIndex].nCustomParamIndex;
eError = OMX_ErrorNone;
break;
}
}
return eError;
}
OMX_ERRORTYPE omx_venc::get_state(OMX_IN OMX_HANDLETYPE pHComp, OMX_OUT OMX_STATETYPE* pState)
{
logv(" COMPONENT_GET_STATE");
if (pHComp == NULL || pState == NULL)
{
return OMX_ErrorBadParameter;
}
*pState = m_state;
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_venc::component_tunnel_request(OMX_IN OMX_HANDLETYPE pHComp,
OMX_IN OMX_U32 uPort,
OMX_IN OMX_HANDLETYPE pPeerComponent,
OMX_IN OMX_U32 uPeerPort,
OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup)
{
logv(" COMPONENT_TUNNEL_REQUEST");
CEDARC_UNUSE(pHComp);
CEDARC_UNUSE(uPort);
CEDARC_UNUSE(pPeerComponent);
CEDARC_UNUSE(uPeerPort);
CEDARC_UNUSE(pTunnelSetup);
logv("Error: component_tunnel_request Not Implemented\n");
return OMX_ErrorNotImplemented;
}
OMX_ERRORTYPE omx_venc::use_buffer(OMX_IN OMX_HANDLETYPE hComponent,
OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
OMX_IN OMX_U32 nPortIndex,
OMX_IN OMX_PTR pAppPrivate,
OMX_IN OMX_U32 nSizeBytes,
OMX_IN OMX_U8* pBuffer)
{
OMX_PARAM_PORTDEFINITIONTYPE* pPortDef;
OMX_U32 nIndex = 0x0;
logv(" COMPONENT_USE_BUFFER");
// logd("-------nPortIndex: %d, nSizeBytes: %d", (int)nPortIndex, (int)nSizeBytes);
if (hComponent == NULL || ppBufferHdr == NULL || pBuffer == NULL)
{
return OMX_ErrorBadParameter;
}
if (nPortIndex == m_sInPortDefType.nPortIndex)
pPortDef = &m_sInPortDefType;
else if (nPortIndex == m_sOutPortDefType.nPortIndex)
pPortDef = &m_sOutPortDefType;
else
return OMX_ErrorBadParameter;
if (!pPortDef->bEnabled)
return OMX_ErrorIncorrectStateOperation;
if (pPortDef->bPopulated)
return OMX_ErrorBadParameter;
// Find an empty position in the BufferList and allocate memory for the buffer header.
// Use the buffer passed by the client to initialize the actual buffer
// inside the buffer header.
if (nPortIndex == m_sInPortDefType.nPortIndex)
{
pthread_mutex_lock(&m_inBufMutex);
logv("vencInPort: use_buffer");
if ((int)m_sInBufList.nAllocSize >= m_sInBufList.nBufArrSize)
{
pthread_mutex_unlock(&m_inBufMutex);
return OMX_ErrorInsufficientResources;
}
nIndex = m_sInBufList.nAllocSize;
m_sInBufList.nAllocSize++;
m_sInBufList.pBufArr[nIndex].pBuffer = pBuffer;
m_sInBufList.pBufArr[nIndex].nAllocLen = nSizeBytes;
m_sInBufList.pBufArr[nIndex].pAppPrivate = pAppPrivate;
m_sInBufList.pBufArr[nIndex].nInputPortIndex = nPortIndex;
m_sInBufList.pBufArr[nIndex].nOutputPortIndex = 0xFFFFFFFE;
*ppBufferHdr = &m_sInBufList.pBufArr[nIndex];
if (m_sInBufList.nAllocSize == pPortDef->nBufferCountActual)
{
pPortDef->bPopulated = OMX_TRUE;
}
pthread_mutex_unlock(&m_inBufMutex);
}
else
{
pthread_mutex_lock(&m_outBufMutex);
logv("vencOutPort: use_buffer");
if ((int)m_sOutBufList.nAllocSize >= m_sOutBufList.nBufArrSize)
{
pthread_mutex_unlock(&m_outBufMutex);
return OMX_ErrorInsufficientResources;
}
nIndex = m_sOutBufList.nAllocSize;
m_sOutBufList.nAllocSize++;
m_sOutBufList.pBufArr[nIndex].pBuffer = pBuffer;
m_sOutBufList.pBufArr[nIndex].nAllocLen = nSizeBytes;
m_sOutBufList.pBufArr[nIndex].pAppPrivate = pAppPrivate;
m_sOutBufList.pBufArr[nIndex].nInputPortIndex = 0xFFFFFFFE;
m_sOutBufList.pBufArr[nIndex].nOutputPortIndex = nPortIndex;
*ppBufferHdr = &m_sOutBufList.pBufArr[nIndex];
if (m_sOutBufList.nAllocSize == pPortDef->nBufferCountActual)
{
pPortDef->bPopulated = OMX_TRUE;
}
pthread_mutex_unlock(&m_outBufMutex);
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_venc::allocate_buffer(OMX_IN OMX_HANDLETYPE hComponent,
OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
OMX_IN OMX_U32 nPortIndex,
OMX_IN OMX_PTR pAppPrivate,
OMX_IN OMX_U32 nSizeBytes)
{
OMX_S8 nIndex = 0x0;
OMX_PARAM_PORTDEFINITIONTYPE* pPortDef;
logv(" COMPONENT_ALLOCATE_BUFFER");
if (hComponent == NULL || ppBufferHdr == NULL)
return OMX_ErrorBadParameter;
if (nPortIndex == m_sInPortDefType.nPortIndex)
{
logv("port_in: nPortIndex=%d", (int)nPortIndex);
pPortDef = &m_sInPortDefType;
}
else
{
logv("port_out: nPortIndex=%d",(int)nPortIndex);
if (nPortIndex == m_sOutPortDefType.nPortIndex)
{
logv("port_out: nPortIndex=%d", (int)nPortIndex);
pPortDef = &m_sOutPortDefType;
}
else
{
logv("allocate_buffer fatal error! nPortIndex=%d", (int)nPortIndex);
return OMX_ErrorBadParameter;
}
}
if (!pPortDef->bEnabled)
return OMX_ErrorIncorrectStateOperation;
if (pPortDef->bPopulated)
return OMX_ErrorBadParameter;
// Find an empty position in the BufferList and allocate memory for the buffer header
// and the actual buffer
if (nPortIndex == m_sInPortDefType.nPortIndex)
{
pthread_mutex_lock(&m_inBufMutex);
logv("vencInPort: malloc vbs");
if ((int)m_sInBufList.nAllocSize >= m_sInBufList.nBufArrSize)
{
pthread_mutex_unlock(&m_inBufMutex);
return OMX_ErrorInsufficientResources;
}
nIndex = m_sInBufList.nAllocSize;
m_sInBufList.pBufArr[nIndex].pBuffer = (OMX_U8*)malloc(nSizeBytes);
if (!m_sInBufList.pBufArr[nIndex].pBuffer)
{
pthread_mutex_unlock(&m_inBufMutex);
return OMX_ErrorInsufficientResources;
}
m_sInBufList.nAllocBySelfFlags |= (1<<nIndex);
m_sInBufList.pBufArr[nIndex].nAllocLen = nSizeBytes;
m_sInBufList.pBufArr[nIndex].pAppPrivate = pAppPrivate;
m_sInBufList.pBufArr[nIndex].nInputPortIndex = nPortIndex;
m_sInBufList.pBufArr[nIndex].nOutputPortIndex = 0xFFFFFFFE;
*ppBufferHdr = &m_sInBufList.pBufArr[nIndex];
m_sInBufList.nAllocSize++;
if (m_sInBufList.nAllocSize == pPortDef->nBufferCountActual)
{
pPortDef->bPopulated = OMX_TRUE;
}
pthread_mutex_unlock(&m_inBufMutex);
}
else
{
logv("vencOutPort: malloc frame");
// android::CallStack stack;
// stack.update(1, 100);
// stack.dump("allocate_buffer_for_frame");
pthread_mutex_lock(&m_outBufMutex);
if ((int)m_sOutBufList.nAllocSize >= m_sOutBufList.nBufArrSize)
{
pthread_mutex_unlock(&m_outBufMutex);
return OMX_ErrorInsufficientResources;
}
nIndex = m_sOutBufList.nAllocSize;
m_sOutBufList.pBufArr[nIndex].pBuffer = (OMX_U8*)malloc(nSizeBytes);
if (!m_sOutBufList.pBufArr[nIndex].pBuffer)
{
pthread_mutex_unlock(&m_outBufMutex);
return OMX_ErrorInsufficientResources;
}
m_sOutBufList.nAllocBySelfFlags |= (1<<nIndex);
m_sOutBufList.pBufArr[nIndex].nAllocLen = nSizeBytes;
m_sOutBufList.pBufArr[nIndex].pAppPrivate = pAppPrivate;
m_sOutBufList.pBufArr[nIndex].nInputPortIndex = 0xFFFFFFFE;
m_sOutBufList.pBufArr[nIndex].nOutputPortIndex = nPortIndex;
*ppBufferHdr = &m_sOutBufList.pBufArr[nIndex];
m_sOutBufList.nAllocSize++;
if (m_sOutBufList.nAllocSize == pPortDef->nBufferCountActual)
{
pPortDef->bPopulated = OMX_TRUE;
}
pthread_mutex_unlock(&m_outBufMutex);
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_venc::free_buffer(OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_U32 nPortIndex,
OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr)
{
OMX_PARAM_PORTDEFINITIONTYPE* pPortDef;
OMX_S32 nIndex;
logv(" COMPONENT_FREE_BUFFER, nPortIndex = %d, pBufferHdr = %p",
(int)nPortIndex, pBufferHdr);
if (hComponent == NULL || pBufferHdr == NULL)
{
return OMX_ErrorBadParameter;
}
// Match the pBufferHdr to the appropriate entry in the BufferList
// and free the allocated memory
if (nPortIndex == m_sInPortDefType.nPortIndex)
{
pPortDef = &m_sInPortDefType;
pthread_mutex_lock(&m_inBufMutex);
logv("vencInPort: free_buffer");
for (nIndex = 0; nIndex < m_sInBufList.nBufArrSize; nIndex++)
{
if (pBufferHdr == &m_sInBufList.pBufArr[nIndex])
{
break;
}
}
if (nIndex == m_sInBufList.nBufArrSize)
{
pthread_mutex_unlock(&m_inBufMutex);
return OMX_ErrorBadParameter;
}
if (m_sInBufList.nAllocBySelfFlags & (1<<nIndex))
{
free(m_sInBufList.pBufArr[nIndex].pBuffer);
m_sInBufList.pBufArr[nIndex].pBuffer = NULL;
m_sInBufList.nAllocBySelfFlags &= ~(1<<nIndex);
}
m_sInBufList.nAllocSize--;
if (m_sInBufList.nAllocSize == 0)
{
pPortDef->bPopulated = OMX_FALSE;
}
pthread_mutex_unlock(&m_inBufMutex);
}
else if (nPortIndex == m_sOutPortDefType.nPortIndex)
{
pPortDef = &m_sOutPortDefType;
pthread_mutex_lock(&m_outBufMutex);
logv("vencOutPort: free_buffer");
for (nIndex = 0; nIndex < m_sOutBufList.nBufArrSize; nIndex++)
{
logv("pBufferHdr = %p, &m_sOutBufList.pBufArr[%d] = %p", pBufferHdr,
(int)nIndex, &m_sOutBufList.pBufArr[nIndex]);
if (pBufferHdr == &m_sOutBufList.pBufArr[nIndex])
break;
}
logv("index = %d", (int)nIndex);
if (nIndex == m_sOutBufList.nBufArrSize)
{
pthread_mutex_unlock(&m_outBufMutex);
return OMX_ErrorBadParameter;
}
if (m_sOutBufList.nAllocBySelfFlags & (1<<nIndex))
{
free(m_sOutBufList.pBufArr[nIndex].pBuffer);
m_sOutBufList.pBufArr[nIndex].pBuffer = NULL;
m_sOutBufList.nAllocBySelfFlags &= ~(1<<nIndex);
}
m_sOutBufList.nAllocSize--;
if (m_sOutBufList.nAllocSize == 0)
{
pPortDef->bPopulated = OMX_FALSE;
}
pthread_mutex_unlock(&m_outBufMutex);
}
else
{
return OMX_ErrorBadParameter;
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_venc::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr)
{
ThrCmdType eCmdNative = EmptyBuf;
mEmptyBufCnt++;
if (mEmptyBufCnt >= PRINT_FRAME_CNT)
{
logd("venc, empty_this_buffer %d times",PRINT_FRAME_CNT);
mEmptyBufCnt = 0;
}
logv(" venc , FUNC:%s, LINE: %d",__FUNCTION__,__LINE__);
if (hComponent == NULL || pBufferHdr == NULL)
{
return OMX_ErrorBadParameter;
}
if (!m_sInPortDefType.bEnabled)
{
return OMX_ErrorIncorrectStateOperation;
}
if (pBufferHdr->nInputPortIndex != 0x0 || pBufferHdr->nOutputPortIndex != OMX_NOPORT)
{
return OMX_ErrorBadPortIndex;
}
if (m_state != OMX_StateExecuting && m_state != OMX_StatePause)
{
return OMX_ErrorIncorrectStateOperation;
}
//fwrite(pBufferHdr->pBuffer, 1, pBufferHdr->nFilledLen, ph264File);
//logv("BHF[0x%x],len[%d]", pBufferHdr->nFlags, pBufferHdr->nFilledLen);
// Put the command and data in the pipe
post_event(eCmdNative, 0, (OMX_PTR)pBufferHdr);
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_venc::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr)
{
ThrCmdType eCmdNative = FillBuf;
mFillBufCnt++;
if (mFillBufCnt >= PRINT_FRAME_CNT)
{
logd("venc, fill_this_buffer %d times",PRINT_FRAME_CNT);
mFillBufCnt = 0;
}
// logv(" COMPONENT_FILL_THIS_BUFFER");
logv("vencOutPort: fill_this_buffer");
if (hComponent == NULL || pBufferHdr == NULL)
{
return OMX_ErrorBadParameter;
}
if (!m_sOutPortDefType.bEnabled)
{
return OMX_ErrorIncorrectStateOperation;
}
if (pBufferHdr->nOutputPortIndex != 0x1 || pBufferHdr->nInputPortIndex != OMX_NOPORT)
{
return OMX_ErrorBadPortIndex;
}
if (m_state != OMX_StateExecuting && m_state != OMX_StatePause)
{
return OMX_ErrorIncorrectStateOperation;
}
// Put the command and data in the pipe
post_event(eCmdNative, 0, (OMX_PTR)pBufferHdr);
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_venc::set_callbacks(OMX_IN OMX_HANDLETYPE pHComp,
OMX_IN OMX_CALLBACKTYPE* pCallbacks,
OMX_IN OMX_PTR pAppData)
{
logv(" COMPONENT_SET_CALLBACKS");
if (pHComp == NULL || pCallbacks == NULL || pAppData == NULL)
{
return OMX_ErrorBadParameter;
}
memcpy(&m_Callbacks, pCallbacks, sizeof(OMX_CALLBACKTYPE));
m_pAppData = pAppData;
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_venc::component_deinit(OMX_IN OMX_HANDLETYPE pHComp)
{
logv(" COMPONENT_DEINIT");
OMX_ERRORTYPE eError = OMX_ErrorNone;
ThrCmdType eCmdNative = Stop;
OMX_S32 nIndex = 0;
logd("component_deinit");
CEDARC_UNUSE(pHComp);
// In case the client crashes, check for nAllocSize parameter.
// If this is greater than zero, there are elements in the list that are not free'd.
// In that case, free the elements.
if (m_sInBufList.nAllocSize > 0)
{
for (nIndex=0; nIndex<m_sInBufList.nBufArrSize; nIndex++)
{
if (m_sInBufList.pBufArr[nIndex].pBuffer != NULL)
{
if (m_sInBufList.nAllocBySelfFlags & (1<<nIndex))
{
free(m_sInBufList.pBufArr[nIndex].pBuffer);
m_sInBufList.pBufArr[nIndex].pBuffer = NULL;
}
}
}
if (m_sInBufList.pBufArr != NULL)
{
free(m_sInBufList.pBufArr);
}
if (m_sInBufList.pBufHdrList != NULL)
{
free(m_sInBufList.pBufHdrList);
}
memset(&m_sInBufList, 0, sizeof(struct _BufferList));
m_sInBufList.nBufArrSize = m_sInPortDefType.nBufferCountActual;
}
if (m_sOutBufList.nAllocSize > 0)
{
for (nIndex=0; nIndex<m_sOutBufList.nBufArrSize; nIndex++)
{
if (m_sOutBufList.pBufArr[nIndex].pBuffer != NULL)
{
if (m_sOutBufList.nAllocBySelfFlags & (1<<nIndex))
{
free(m_sOutBufList.pBufArr[nIndex].pBuffer);
m_sOutBufList.pBufArr[nIndex].pBuffer = NULL;
}
}
}
if (m_sOutBufList.pBufArr != NULL)
{
free(m_sOutBufList.pBufArr);
}
if (m_sOutBufList.pBufHdrList != NULL)
{
free(m_sOutBufList.pBufHdrList);
}
memset(&m_sOutBufList, 0, sizeof(struct _BufferList));
m_sOutBufList.nBufArrSize = m_sOutPortDefType.nBufferCountActual;
}
// Put the command and data in the pipe
//write(m_cmdpipe[1], &eCmdNative, sizeof(eCmdNative));
//write(m_cmddatapipe[1], &eCmdNative, sizeof(eCmdNative));
post_event(eCmdNative, eCmdNative, NULL);
// Wait for thread to exit so we can get the status into "error"
pthread_join(m_thread_id, (void**)&eError);
pthread_join(m_venc_thread_id, (void**)&eError);
// close the pipe handles
close(m_cmdpipe[0]);
close(m_cmdpipe[1]);
close(m_cmddatapipe[0]);
close(m_cmddatapipe[1]);
close(m_venc_cmdpipe[0]);
close(m_venc_cmdpipe[1]);
#if SAVE_BITSTREAM
if (OutFile)
{
fclose(OutFile);
OutFile = NULL;
}
#endif
return eError;
}
OMX_ERRORTYPE omx_venc::use_EGL_image(OMX_IN OMX_HANDLETYPE pHComp,
OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
OMX_IN OMX_U32 uPort,
OMX_IN OMX_PTR pAppData,
OMX_IN void* pEglImage)
{
logv("Error : use_EGL_image: Not Implemented \n");
CEDARC_UNUSE(pHComp);
CEDARC_UNUSE(ppBufferHdr);
CEDARC_UNUSE(uPort);
CEDARC_UNUSE(pAppData);
CEDARC_UNUSE(pEglImage);
return OMX_ErrorNotImplemented;
}
OMX_ERRORTYPE omx_venc::component_role_enum(OMX_IN OMX_HANDLETYPE pHComp,
OMX_OUT OMX_U8* pRole,
OMX_IN OMX_U32 uIndex)
{
logv(" COMPONENT_ROLE_ENUM");
OMX_ERRORTYPE eRet = OMX_ErrorNone;
CEDARC_UNUSE(pHComp);
if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.avc", OMX_MAX_STRINGNAME_SIZE))
{
if ((0 == uIndex) && pRole)
{
strncpy((char *)pRole, "video_encoder.avc", OMX_MAX_STRINGNAME_SIZE);
logv("component_role_enum: pRole %s\n", pRole);
}
else
{
eRet = OMX_ErrorNoMore;
}
}
else if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.mjpeg", OMX_MAX_STRINGNAME_SIZE))
{
if ((0 == uIndex) && pRole)
{
strncpy((char *)pRole, "video_encoder.mjpeg", OMX_MAX_STRINGNAME_SIZE);
logv("component_role_enum: pRole %s\n", pRole);
}
else
{
eRet = OMX_ErrorNoMore;
}
}
else if (!strncmp((char*)m_cName, "OMX.allwinner.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE))
{
if ((0 == uIndex) && pRole)
{
strncpy((char *)pRole, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE);
logv("component_role_enum: pRole %s\n", pRole);
}
else
{
eRet = OMX_ErrorNoMore;
}
}
else
{
logd("\nERROR:Querying pRole on Unknown Component\n");
eRet = OMX_ErrorInvalidComponentName;
}
return eRet;
}
OMX_ERRORTYPE omx_venc::post_event(OMX_IN ThrCmdType eCmdNative,
OMX_IN OMX_U32 uParam1,
OMX_IN OMX_PTR pCmdData)
{
pthread_mutex_lock(&m_pipeMutex);
write(m_cmdpipe[1], &eCmdNative, sizeof(eCmdNative));
// In case of MarkBuf, the pCmdData parameter is used to carry the data.
// In other cases, the nParam1 parameter carries the data.
if (eCmdNative == MarkBuf || eCmdNative == EmptyBuf || eCmdNative == FillBuf)
write(m_cmddatapipe[1], &pCmdData, sizeof(OMX_PTR));
else
write(m_cmddatapipe[1], &uParam1, sizeof(uParam1));
pthread_mutex_unlock(&m_pipeMutex);
return OMX_ErrorNone;
}
int waitPipeDataToRead(int nPipeFd, int nTimeUs)
{
fd_set rfds;
struct timeval timeout;
FD_ZERO(&rfds);
FD_SET(nPipeFd, &rfds);
// Check for new command
timeout.tv_sec = 0;
timeout.tv_usec = nTimeUs;
select(nPipeFd+1, &rfds, NULL, NULL, &timeout);
if (FD_ISSET(nPipeFd, &rfds))
{
return 1;
}
else
{
return 0;
}
}
void setSuperFrameCfg(omx_venc* pVenc)
{
VencSuperFrameConfig sSuperFrameCfg;
VideoEncSetParameter(pVenc->m_encoder, VENC_IndexParamFramerate, &pVenc->m_framerate);
switch (pVenc->mVideoSuperFrame.eSuperFrameMode)
{
case OMX_VIDEO_SUPERFRAME_NONE:
sSuperFrameCfg.eSuperFrameMode = VENC_SUPERFRAME_NONE;
break;
case OMX_VIDEO_SUPERFRAME_REENCODE:
sSuperFrameCfg.eSuperFrameMode = VENC_SUPERFRAME_REENCODE;
break;
case OMX_VIDEO_SUPERFRAME_DISCARD:
sSuperFrameCfg.eSuperFrameMode = VENC_SUPERFRAME_DISCARD;
break;
default:
logd("the omx venc do not support the superFrame mode:%d\n", \
pVenc->mVideoSuperFrame.eSuperFrameMode);
sSuperFrameCfg.eSuperFrameMode = VENC_SUPERFRAME_NONE;
break;
}
if(!pVenc->mVideoSuperFrame.nMaxIFrameBits && !pVenc->mVideoSuperFrame.nMaxPFrameBits)
{
sSuperFrameCfg.nMaxIFrameBits = pVenc->m_sOutPortDefType.format.video.nBitrate /
pVenc->m_framerate*3;
sSuperFrameCfg.nMaxPFrameBits = pVenc->m_sOutPortDefType.format.video.nBitrate /
pVenc->m_framerate*2;
if (pVenc->m_framerate <= 10)
{
sSuperFrameCfg.nMaxIFrameBits = pVenc->m_sOutPortDefType.format.video.nBitrate /
pVenc->m_framerate * 2;
sSuperFrameCfg.nMaxPFrameBits = pVenc->m_sOutPortDefType.format.video.nBitrate /
pVenc->m_framerate*3/2;
}
}
else
{
sSuperFrameCfg.nMaxIFrameBits = pVenc->mVideoSuperFrame.nMaxIFrameBits;
sSuperFrameCfg.nMaxPFrameBits = pVenc->mVideoSuperFrame.nMaxPFrameBits;
}
logd("setSuperFrameCfg, pSelf->m_framerate: %d, bitrate: %d\n",
(int)pVenc->m_framerate, (int)pVenc->m_sOutPortDefType.format.video.nBitrate);
logd("bitRate/frameRate:%d, nMaxIFrameBits:%d, nMaxPFrameBits:%d\n",\
(int)pVenc->m_sOutPortDefType.format.video.nBitrate/(int)pVenc->m_framerate,\
sSuperFrameCfg.nMaxIFrameBits, sSuperFrameCfg.nMaxPFrameBits);
VideoEncSetParameter(pVenc->m_encoder, VENC_IndexParamSuperFrameConfig, &sSuperFrameCfg);
}
void setSVCSkipCfg(omx_venc* pVenc)
{
VencH264SVCSkip SVCSkip;
unsigned int total_ratio;
memset(&SVCSkip, 0, sizeof(VencH264SVCSkip));
logd("setSVCSkipCfg, pSelf->mVideoSVCSkip.uTemporalSVC: %d, LayerRatio[0-3]: [%d %d %d %d]\n",\
(int)pVenc->mVideoSVCSkip.eSvcLayer, (int)pVenc->mVideoSVCSkip.uLayerRatio[0],\
(int)pVenc->mVideoSVCSkip.uLayerRatio[1], (int)pVenc->mVideoSVCSkip.uLayerRatio[2],\
(int)pVenc->mVideoSVCSkip.uLayerRatio[3]);
SVCSkip.nTemporalSVC = NO_T_SVC;
SVCSkip.nSkipFrame = NO_SKIP;
switch(pVenc->mVideoSVCSkip.eSvcLayer)
{
case OMX_VIDEO_NO_SVC:
SVCSkip.nTemporalSVC = NO_T_SVC;
SVCSkip.nSkipFrame = NO_SKIP;
break;
case OMX_VIDEO_LAYER_2:
SVCSkip.nTemporalSVC = T_LAYER_2;
SVCSkip.nSkipFrame = SKIP_2;
break;
case OMX_VIDEO_LAYER_3:
SVCSkip.nTemporalSVC = T_LAYER_3;
SVCSkip.nSkipFrame = SKIP_4;
break;
case OMX_VIDEO_LAYER_4:
SVCSkip.nTemporalSVC = T_LAYER_4;
SVCSkip.nSkipFrame = SKIP_8;
break;
default:
SVCSkip.nTemporalSVC = NO_T_SVC;
SVCSkip.nSkipFrame = NO_SKIP;
break;
}
total_ratio = pVenc->mVideoSVCSkip.uLayerRatio[0] + pVenc->mVideoSVCSkip.uLayerRatio[1] +\
pVenc->mVideoSVCSkip.uLayerRatio[2] + pVenc->mVideoSVCSkip.uLayerRatio[3];
if(total_ratio != 100)
{
logd("the set layer ratio sum is %d, not 100, so use the encoder default layer ratio\n",\
total_ratio);
SVCSkip.bEnableLayerRatio = 0;
}
else
{
SVCSkip.bEnableLayerRatio = 1;
for(int i=0; i<4; i++)
SVCSkip.nLayerRatio[i] = pVenc->mVideoSVCSkip.uLayerRatio[i];
}
VideoEncSetParameter(pVenc->m_encoder, VENC_IndexParamH264SVCSkip, &SVCSkip);
}
void init_h264_param(omx_venc* pVenc)
{
memset(&pVenc->m_vencH264Param, 0, sizeof(VencH264Param));
//* h264 param
pVenc->m_vencH264Param.bEntropyCodingCABAC = 1;
pVenc->m_vencH264Param.nBitrate = pVenc->m_sOutPutBitRateType.nTargetBitrate; /* bps */
pVenc->m_vencH264Param.nFramerate = pVenc->m_framerate; /* fps */
pVenc->m_vencH264Param.nCodingMode = VENC_FRAME_CODING;
pVenc->m_vencH264Param.nMaxKeyInterval = (pVenc->m_sH264Type.nPFrames + 1);
if (pVenc->m_vencH264Param.nMaxKeyInterval < 0)
{
pVenc->m_vencH264Param.nMaxKeyInterval = 30;
}
//set profile
switch (pVenc->m_sH264Type.eProfile)
{
case 1:
pVenc->m_vencH264Param.sProfileLevel.nProfile = VENC_H264ProfileBaseline;
break;
case 2:
pVenc->m_vencH264Param.sProfileLevel.nProfile = VENC_H264ProfileMain;
break;
case 8:
pVenc->m_vencH264Param.sProfileLevel.nProfile = VENC_H264ProfileHigh;
break;
default:
pVenc->m_vencH264Param.sProfileLevel.nProfile = VENC_H264ProfileBaseline;
break;
}
if (pVenc->mIsFromVideoeditor)
{
logd ("Called from Videoeditor,set VENC_H264ProfileBaseline");
pVenc->m_vencH264Param.sProfileLevel.nProfile = VENC_H264ProfileBaseline;
}
logd("profile-venc=%d, profile-omx=%d, frame_rate:%d, bit_rate:%d, idr:%d, eColorFormat:%08x\n",
pVenc->m_vencH264Param.sProfileLevel.nProfile,
pVenc->m_sH264Type.eProfile,pVenc->m_vencH264Param.nFramerate,
pVenc->m_vencH264Param.nBitrate,pVenc->m_vencH264Param.nMaxKeyInterval,
pVenc->m_sInPortFormatType.eColorFormat);
//set level
switch (pVenc->m_sH264Type.eLevel)
{
case 0x100:
{
pVenc->m_vencH264Param.sProfileLevel.nLevel = VENC_H264Level3;
break;
}
case 0x200:
{
pVenc->m_vencH264Param.sProfileLevel.nLevel = VENC_H264Level31;
break;
}
case 0x400:
{
pVenc->m_vencH264Param.sProfileLevel.nLevel = VENC_H264Level32;
break;
}
case 0x800:
{
pVenc->m_vencH264Param.sProfileLevel.nLevel = VENC_H264Level4;
break;
}
case 0x1000:
{
pVenc->m_vencH264Param.sProfileLevel.nLevel = VENC_H264Level41;
break;
}
case 0x2000:
{
pVenc->m_vencH264Param.sProfileLevel.nLevel = VENC_H264Level42;
break;
}
case 0x4000:
{
pVenc->m_vencH264Param.sProfileLevel.nLevel = VENC_H264Level5;
break;
}
case 0x8000:
{
pVenc->m_vencH264Param.sProfileLevel.nLevel = VENC_H264Level51;
break;
}
default:
{
pVenc->m_vencH264Param.sProfileLevel.nLevel = VENC_H264Level41;
break;
}
}
pVenc->m_vencH264Param.sQPRange.nMinqp = 6;
pVenc->m_vencH264Param.sQPRange.nMaxqp = 45;
if (pVenc->mVideoVBR.bEnable)
{
pVenc->m_vencH264Param.sQPRange.nMinqp = pVenc->mVideoVBR.uQpMin;
pVenc->m_vencH264Param.sQPRange.nMaxqp = pVenc->mVideoVBR.uQpMax;
pVenc->m_vencH264Param.nBitrate = pVenc->mVideoVBR.uBitRate;
if(pVenc->mVideoVBR.sMdParam.bMotionDetectEnable)
{
OMX_VIDEO_PARAMS_MD sMD_param;
sMD_param.bMotionDetectEnable = pVenc->mVideoVBR.sMdParam.bMotionDetectEnable;
sMD_param.nMotionDetectRatio = pVenc->mVideoVBR.sMdParam.nMotionDetectRatio;
sMD_param.nStaticDetectRatio = pVenc->mVideoVBR.sMdParam.nStaticDetectRatio;
sMD_param.nMaxNumStaticFrame = pVenc->mVideoVBR.sMdParam.nMaxNumStaticFrame;
sMD_param.nStaticBitsRatio = pVenc->mVideoVBR.sMdParam.nStaticBitsRatio;
sMD_param.dMV64x64Ratio = pVenc->mVideoVBR.sMdParam.dMV64x64Ratio;
sMD_param.sMVXTh = pVenc->mVideoVBR.sMdParam.sMVXTh;
sMD_param.sMVYTh = pVenc->mVideoVBR.sMdParam.sMVYTh;
VideoEncSetParameter(pVenc->m_encoder,\
VENC_IndexParamMotionDetectEnable, &sMD_param);
}
logd("use VBR\n");
}
VideoEncSetParameter(pVenc->m_encoder, VENC_IndexParamH264Param, &pVenc->m_vencH264Param);
if (pVenc->mVideoSuperFrame.bEnable)
{
setSuperFrameCfg(pVenc);
logd("use setSuperFrameCfg");
}
if (pVenc->mVideoSVCSkip.bEnable)
{
setSVCSkipCfg(pVenc);
}
#if 0 //* do not use this function right now
if (pVenc->m_vencCyclicIntraRefresh.bEnable)
{
VideoEncSetParameter(pVenc->m_encoder, VENC_IndexParamH264CyclicIntraRefresh,
&pVenc->m_vencCyclicIntraRefresh);
}
#endif
}
void init_h265_param(omx_venc* pVenc)
{
memset(&pVenc->m_vencH265Param, 0, sizeof(VencH264Param));
//* h265 param
pVenc->m_vencH265Param.nBitrate = pVenc->m_sOutPutBitRateType.nTargetBitrate; /* bps */
pVenc->m_vencH265Param.nFramerate = pVenc->m_framerate; /* fps */
pVenc->m_vencH265Param.idr_period = pVenc->m_sH265Type.nKeyFrameInterval;
if (pVenc->m_vencH265Param.idr_period <= 0)
pVenc->m_vencH265Param.idr_period = 30;
else if(pVenc->m_vencH265Param.idr_period > 128)
pVenc->m_vencH265Param.idr_period = 128;
pVenc->m_vencH265Param.nGopSize = 30;
pVenc->m_vencH265Param.nIntraPeriod = pVenc->m_vencH265Param.idr_period;
//set profile
switch (pVenc->m_sH265Type.eProfile)
{
case OMX_VIDEO_HEVCProfileMain:
pVenc->m_vencH265Param.sProfileLevel.nProfile = VENC_H265ProfileMain;
break;
default:
pVenc->m_vencH265Param.sProfileLevel.nProfile = VENC_H265ProfileMain;
break;
}
logd("profile-venc=%d, profile-omx=%d, frame_rate:%d, bit_rate:%d, idr:%d, eColorFormat:%08x\n",
pVenc->m_vencH265Param.sProfileLevel.nProfile,
pVenc->m_sH265Type.eProfile,pVenc->m_vencH265Param.nFramerate,
pVenc->m_vencH265Param.nBitrate,pVenc->m_vencH265Param.idr_period,
pVenc->m_sInPortFormatType.eColorFormat);
//set level
switch (pVenc->m_sH265Type.eLevel)
{
case OMX_VIDEO_HEVCMainTierLevel1:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level1;
break;
}
case OMX_VIDEO_HEVCMainTierLevel2:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level2;
break;
}
case OMX_VIDEO_HEVCMainTierLevel21:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level21;
break;
}
case OMX_VIDEO_HEVCMainTierLevel3:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level3;
break;
}
case OMX_VIDEO_HEVCMainTierLevel31:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level31;
break;
}
case OMX_VIDEO_HEVCMainTierLevel41:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level41;
break;
}
case OMX_VIDEO_HEVCMainTierLevel5:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level5;
break;
}
case OMX_VIDEO_HEVCMainTierLevel51:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level51;
break;
}
case OMX_VIDEO_HEVCMainTierLevel52:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level52;
break;
}
case OMX_VIDEO_HEVCMainTierLevel6:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level6;
break;
}
case OMX_VIDEO_HEVCMainTierLevel61:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level61;
break;
}
case OMX_VIDEO_HEVCMainTierLevel62:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level62;
break;
}
default:
{
pVenc->m_vencH265Param.sProfileLevel.nLevel = VENC_H265Level51;
break;
}
}
pVenc->m_vencH265Param.sQPRange.nMinqp = 6;
pVenc->m_vencH265Param.sQPRange.nMaxqp = 45;
pVenc->m_vencH265Param.nQPInit = 30;
VideoEncSetParameter(pVenc->m_encoder, VENC_IndexParamH265Param, &pVenc->m_vencH265Param);
if (pVenc->mVideoSuperFrame.bEnable)
{
setSuperFrameCfg(pVenc);
logd("use setSuperFrameCfg");
}
#if 0 //* do not use this function right now
if (pVenc->m_vencCyclicIntraRefresh.bEnable)
{
VideoEncSetParameter(pVenc->m_encoder, VENC_IndexParamH264CyclicIntraRefresh,
&pVenc->m_vencCyclicIntraRefresh);
}
#endif
}
int openVencDriver(omx_venc* pVenc)
{
VencBaseConfig sBaseConfig;
int result;
memset(&sBaseConfig, 0, sizeof(VencBaseConfig));
int size_y;
int size_c;
char calling_process[256];
pVenc->m_encoder = VideoEncCreate(pVenc->m_vencCodecType);
if (pVenc->m_encoder == NULL)
{
pVenc->m_Callbacks.EventHandler(&pVenc->mOmxCmp, pVenc->m_pAppData,
OMX_EventError, OMX_ErrorHardware, 0 , NULL);
logw("VideoEncCreate fail");
return -1;
}
if (pVenc->m_vencCodecType == VENC_CODEC_H264)
init_h264_param(pVenc);
else if(pVenc->m_vencCodecType == VENC_CODEC_H265)
init_h265_param(pVenc);
switch (pVenc->m_sInPortFormatType.eColorFormat)
{
#if (CONF_ANDROID_MAJOR_VER >= 7)
//* android 7.0 cannot get mIsFromCts, so we extend OMX_COLOR_FormatYVU420SemiPlanar
case OMX_COLOR_FormatYUV420SemiPlanar:
{
pVenc->m_vencColorFormat = VENC_PIXEL_YUV420SP;
break;
}
case OMX_COLOR_FormatYVU420SemiPlanar:
{
pVenc->m_vencColorFormat = VENC_PIXEL_YVU420SP;
break;
}
#else
case OMX_COLOR_FormatYUV420SemiPlanar:
{
#if 0
if(pVenc->mIsFromCts)
{
pVenc->m_vencColorFormat = VENC_PIXEL_YUV420SP;
}
else//* from camera
{
pVenc->m_vencColorFormat = VENC_PIXEL_YVU420SP;
}
#endif
pVenc->m_vencColorFormat = VENC_PIXEL_YUV420SP;
break;
}
#endif
case OMX_COLOR_FormatAndroidOpaque:
{
pVenc->m_vencColorFormat = VENC_PIXEL_ARGB; //maybe change this later;
break;
}
default:
{
break;
}
}
if (!pVenc->m_useMetaDataInBuffers && !pVenc->m_useAndroidBuffer)
{
pVenc->m_useAllocInputBuffer = OMX_TRUE;
}
else
{
#if 0
//* just work on chip-a80 and chip-a23, remove now
if (pVenc->m_sInPortFormatType.eColorFormat ==
OMX_COLOR_FormatAndroidOpaque && pVenc->mIsFromCts)
{
VENC_COLOR_SPACE colorSpace = VENC_BT601;
if (VideoEncSetParameter(pVenc->m_encoder, VENC_IndexParamRgb2Yuv, &colorSpace) != 0)
{
pVenc->m_useAllocInputBuffer = OMX_TRUE;
pVenc->m_vencColorFormat = VENC_PIXEL_YUV420SP;
//use ImgRGBA2YUV420SP_neon convert argb to yuv420sp
}
else
{
logd("use bt601 ok");
pVenc->m_useAllocInputBuffer = OMX_FALSE;
}
}
else
#endif
{
pVenc->m_useAllocInputBuffer = OMX_FALSE;
}
}
logd("omx_venc base_config info: src_wxh:%dx%d, dis_wxh:%dx%d, stride:%d\n",
(int)pVenc->m_sInPortDefType.format.video.nFrameWidth,
(int)pVenc->m_sInPortDefType.format.video.nFrameHeight,
(int)pVenc->m_sOutPortDefType.format.video.nFrameWidth,
(int)pVenc->m_sOutPortDefType.format.video.nFrameHeight,
(int)pVenc->m_sInPortDefType.format.video.nStride);
if(pVenc->m_sOutPortDefType.format.video.nFrameWidth == 176 && pVenc->m_sOutPortDefType.format.video.nFrameHeight == 144)
{
pVenc->m_sOutPortDefType.format.video.nFrameWidth = pVenc->m_sInPortDefType.format.video.nFrameWidth;
pVenc->m_sOutPortDefType.format.video.nFrameHeight = pVenc->m_sInPortDefType.format.video.nFrameHeight;
}
sBaseConfig.nInputWidth= pVenc->m_sInPortDefType.format.video.nFrameWidth;
sBaseConfig.nInputHeight = pVenc->m_sInPortDefType.format.video.nFrameHeight;
sBaseConfig.nStride = pVenc->m_sInPortDefType.format.video.nStride;
if (pVenc->mVideoExtParams.bEnableScaling)
{
sBaseConfig.nDstWidth = pVenc->mVideoExtParams.ui16ScaledWidth;
sBaseConfig.nDstHeight = pVenc->mVideoExtParams.ui16ScaledHeight;
}else
{
sBaseConfig.nDstWidth = pVenc->m_sOutPortDefType.format.video.nFrameWidth;
sBaseConfig.nDstHeight = pVenc->m_sOutPortDefType.format.video.nFrameHeight;
}
sBaseConfig.eInputFormat = pVenc->m_vencColorFormat;
sBaseConfig.memops = MemAdapterGetOpsS();
#ifdef CONF_GPU_IMG
if (pVenc->m_sInPortFormatType.eColorFormat == OMX_COLOR_FormatAndroidOpaque)
sBaseConfig.nStride = (sBaseConfig.nStride + 31) & (~31);
#endif
if(pVenc->m_usePSkip)
VideoEncSetParameter(pVenc->m_encoder, VENC_IndexParamSetPSkip, &pVenc->m_usePSkip);
result = VideoEncInit(pVenc->m_encoder, &sBaseConfig);
if (result != 0)
{
VideoEncDestroy(pVenc->m_encoder);
pVenc->m_encoder = NULL;
pVenc->m_Callbacks.EventHandler(&pVenc->mOmxCmp, pVenc->m_pAppData,
OMX_EventError, OMX_ErrorHardware, 0 , NULL);
logw("VideoEncInit, failed, result: %d\n", result);
return -1;
}
if (pVenc->m_vencCodecType == VENC_CODEC_H264)
{
result = VideoEncGetParameter(pVenc->m_encoder,
VENC_IndexParamH264SPSPPS, &pVenc->m_headdata);
}
else if (pVenc->m_vencCodecType == VENC_CODEC_H265)
{
result = VideoEncGetParameter(pVenc->m_encoder,
VENC_IndexParamH265Header, &pVenc->m_headdata);
}
if(result < 0)
{
loge("get sps info error\n");
VideoEncUnInit(pVenc->m_encoder);
VideoEncDestroy(pVenc->m_encoder);
pVenc->m_Callbacks.EventHandler(&pVenc->mOmxCmp, pVenc->m_pAppData,
OMX_EventError, OMX_ErrorHardware, 0 , NULL);
return -1;
}
size_y = sBaseConfig.nStride*sBaseConfig.nInputHeight;
size_c = size_y>>1;
pVenc->m_vencAllocBufferParam.nBufferNum = pVenc->m_sOutPortDefType.nBufferCountActual;
pVenc->m_vencAllocBufferParam.nSizeY = size_y;
pVenc->m_vencAllocBufferParam.nSizeC = size_c;
pVenc->m_firstFrameFlag = OMX_TRUE;
pVenc->mFirstInputFrame = OMX_TRUE;
if (pVenc->m_useAllocInputBuffer)
{
result = AllocInputBuffer(pVenc->m_encoder, &pVenc->m_vencAllocBufferParam);
if (result !=0 )
{
VideoEncUnInit(pVenc->m_encoder);
VideoEncDestroy(pVenc->m_encoder);
loge("AllocInputBuffer,error");
pVenc->m_Callbacks.EventHandler(&pVenc->mOmxCmp, pVenc->m_pAppData,
OMX_EventError, OMX_ErrorHardware, 0 , NULL);
return -1;
}
}
#if PRINTF_FRAME_SIZE
timeval cur_time1;
gettimeofday(&cur_time1, NULL);
pVenc->mTimeStart = cur_time1.tv_sec * 1000000LL + cur_time1.tv_usec;
#endif
return 0;
}
void closeVencDriver(omx_venc* pVenc)
{
if (pVenc->m_useAllocInputBuffer)
{
// ReleaseAllocInputBuffer(pVenc->m_encoder);
pVenc->m_useAllocInputBuffer = OMX_FALSE;
}
VideoEncUnInit(pVenc->m_encoder);
VideoEncDestroy(pVenc->m_encoder);
pVenc->m_encoder = NULL;
}
/*
* Component Thread
* The ComponentThread function is exeuted in a separate pThread and
* is used to implement the actual component functions.
*/
/*****************************************************************************/
static void* ComponentThread(void* pThreadData)
{
int result;
int i;
int fd1;
fd_set rfds;
OMX_U32 pCmdData;
ThrCmdType cmd;
// Variables related to encoder buffer handling
OMX_BUFFERHEADERTYPE* pInBufHdr = NULL;
OMX_BUFFERHEADERTYPE* pOutBufHdr = NULL;
OMX_MARKTYPE* pMarkBuf = NULL;
OMX_U8* pInBuf = NULL;
OMX_U32 nInBufSize;
OMX_BOOL bNoNeedSleep = OMX_TRUE;
int nInputBufferStep = OMX_VENC_STEP_GET_INPUTBUFFER;
// Variables related to encoder timeouts
OMX_U32 nTimeout;
OMX_BOOL port_setting_match;
OMX_BOOL nInBufEos;
OMX_BOOL nVencNotifyEosFlag;
OMX_PTR pMarkData;
OMX_HANDLETYPE hMarkTargetComponent;
struct timeval timeout;
port_setting_match = OMX_TRUE;
nInBufEos = OMX_FALSE;
nVencNotifyEosFlag = OMX_FALSE;
pMarkData = NULL;
hMarkTargetComponent = NULL;
VencInputBuffer sInputBuffer;
VencInputBuffer sInputBuffer_return;
VencOutputBuffer sOutputBuffer;
// Recover the pointer to my component specific data
omx_venc* pSelf = static_cast<omx_venc*>(pThreadData);
while (1)
{
fd1 = pSelf->m_cmdpipe[0];
FD_ZERO(&rfds);
FD_SET(fd1, &rfds);
// Check for new command
timeout.tv_sec = 0;
timeout.tv_usec = 0;
i = select(pSelf->m_cmdpipe[0]+1, &rfds, NULL, NULL, &timeout);
if (FD_ISSET(pSelf->m_cmdpipe[0], &rfds))
{
// retrieve command and data from pipe
read(pSelf->m_cmdpipe[0], &cmd, sizeof(cmd));
read(pSelf->m_cmddatapipe[0], &pCmdData, sizeof(pCmdData));
// State transition command
if (cmd == SetState)
{
logd("x set state command, cmd = %d, pCmdData = %d.", (int)cmd, (int)pCmdData);
// If the parameter states a transition to the same state
// raise a same state transition error.
if (pSelf->m_state == (OMX_STATETYPE)(pCmdData))
{
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError, OMX_ErrorSameState, 0 , NULL);
}
else
{
// transitions/callbacks made based on state transition table
// pCmdData contains the target state
switch ((OMX_STATETYPE)(pCmdData))
{
case OMX_StateInvalid:
{
pSelf->m_state = OMX_StateInvalid;
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError, OMX_ErrorInvalidState,
0 , NULL);
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandStateSet,
pSelf->m_state, NULL);
break;
}
case OMX_StateLoaded:
{
if (pSelf->m_state == OMX_StateIdle ||
pSelf->m_state == OMX_StateWaitForResources)
{
nTimeout = 0x0;
while (1)
{
// Transition happens only when the ports are unpopulated
if (!pSelf->m_sInPortDefType.bPopulated &&
!pSelf->m_sOutPortDefType.bPopulated)
{
pSelf->m_state = OMX_StateLoaded;
pSelf->m_Callbacks.EventHandler(
&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete, OMX_CommandStateSet,
pSelf->m_state, NULL);
break;
}
else if (nTimeout++ > OMX_MAX_TIMEOUTS)
{
pSelf->m_Callbacks.EventHandler(
&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError, OMX_ErrorInsufficientResources,
0 , NULL);
logw("Transition to loaded failed\n");
break;
}
usleep(OMX_TIMEOUT*1000);
}
}
else
{
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp,
pSelf->m_pAppData,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0 , NULL);
}
break;
}
case OMX_StateIdle:
{
if (pSelf->m_state == OMX_StateInvalid)
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0 , NULL);
else
{
// Return buffers if currently in pause and executing
if (pSelf->m_state == OMX_StatePause ||
pSelf->m_state == OMX_StateExecuting)
{
// venc should in idle state before stop
post_message_to_venc_and_wait(pSelf, OMX_Venc_Cmd_Enc_Idle);
if (pSelf->m_useAllocInputBuffer)
{
if (nInputBufferStep == OMX_VENC_STEP_GET_ALLOCBUFFER)
{
pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp,
pSelf->m_pAppData,
pInBufHdr);
}
}
else
{
if (nInputBufferStep == OMX_VENC_STEP_ADD_BUFFER_TO_ENC)
{
pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp,
pSelf->m_pAppData,
pInBufHdr);
}
//* check used buffer
while (0 == AlreadyUsedInputBuffer(pSelf->m_encoder,
&sInputBuffer_return))
{
pInBufHdr =
(OMX_BUFFERHEADERTYPE*)sInputBuffer_return.nID;
pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp,
pSelf->m_pAppData,
pInBufHdr);
}
}
pthread_mutex_lock(&pSelf->m_inBufMutex);
while (pSelf->m_sInBufList.nSizeOfList > 0)
{
OMX_S32 in_pos = pSelf->m_sInBufList.nReadPos++;
pSelf->m_sInBufList.nSizeOfList--;
pSelf->m_Callbacks.EmptyBufferDone(
&pSelf->mOmxCmp, pSelf->m_pAppData,
pSelf->m_sInBufList.pBufHdrList[in_pos]);
if (pSelf->m_sInBufList.nReadPos >=
pSelf->m_sInBufList.nBufArrSize)
{
pSelf->m_sInBufList.nReadPos = 0;
}
}
pthread_mutex_unlock(&pSelf->m_inBufMutex);
pthread_mutex_lock(&pSelf->m_outBufMutex);
while (pSelf->m_sOutBufList.nSizeOfList > 0)
{
OMX_S32 out_pos = pSelf->m_sOutBufList.nReadPos++;
pSelf->m_sOutBufList.nSizeOfList--;
pSelf->m_Callbacks.FillBufferDone(
&pSelf->mOmxCmp, pSelf->m_pAppData,
pSelf->m_sOutBufList.pBufHdrList[out_pos]);
if (pSelf->m_sOutBufList.nReadPos >=
pSelf->m_sOutBufList.nBufArrSize)
{
pSelf->m_sOutBufList.nReadPos = 0;
}
}
pthread_mutex_unlock(&pSelf->m_outBufMutex);
post_message_to_venc_and_wait(pSelf, OMX_Venc_Cmd_Close);
}
else
{
//* init encoder
//post_message_to_venc_and_wait(pSelf, OMX_Venc_Cmd_Open);
}
nTimeout = 0x0;
while (1)
{
logv("pSelf->m_sInPortDefType.bPopulated:%d, \
pSelf->m_sOutPortDefType.bPopulated: %d",
pSelf->m_sInPortDefType.bPopulated,
pSelf->m_sOutPortDefType.bPopulated);
// Ports have to be populated before transition completes
if ((!pSelf->m_sInPortDefType.bEnabled &&
!pSelf->m_sOutPortDefType.bEnabled) ||
(pSelf->m_sInPortDefType.bPopulated &&
pSelf->m_sOutPortDefType.bPopulated))
{
pSelf->m_state = OMX_StateIdle;
pSelf->m_Callbacks.EventHandler(
&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete, OMX_CommandStateSet,
pSelf->m_state, NULL);
break;
}
else if (nTimeout++ > OMX_MAX_TIMEOUTS)
{
pSelf->m_Callbacks.EventHandler(
&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError, OMX_ErrorInsufficientResources,
0 , NULL);
logw("Idle transition failed\n");
break;
}
usleep(OMX_TIMEOUT*1000);
}
}
break;
}
case OMX_StateExecuting:
{
// Transition can only happen from pause or idle state
if (pSelf->m_state == OMX_StateIdle || pSelf->m_state == OMX_StatePause)
{
// Return buffers if currently in pause
if (pSelf->m_state == OMX_StatePause)
{
loge("encode component do not support OMX_StatePause");
pthread_mutex_lock(&pSelf->m_inBufMutex);
while (pSelf->m_sInBufList.nSizeOfList > 0)
{
OMX_S32 in_pos = pSelf->m_sInBufList.nReadPos++;
pSelf->m_sInBufList.nSizeOfList--;
pSelf->m_Callbacks.EmptyBufferDone(
&pSelf->mOmxCmp, pSelf->m_pAppData,
pSelf->m_sInBufList.pBufHdrList[in_pos]);
if (pSelf->m_sInBufList.nReadPos >=
pSelf->m_sInBufList.nBufArrSize)
{
pSelf->m_sInBufList.nReadPos = 0;
}
}
pthread_mutex_unlock(&pSelf->m_inBufMutex);
pthread_mutex_lock(&pSelf->m_outBufMutex);
while (pSelf->m_sOutBufList.nSizeOfList > 0)
{
OMX_S32 out_pos = pSelf->m_sOutBufList.nReadPos++;
pSelf->m_sOutBufList.nSizeOfList--;
pSelf->m_Callbacks.FillBufferDone(
&pSelf->mOmxCmp, pSelf->m_pAppData,
pSelf->m_sOutBufList.pBufHdrList[out_pos]);
if (pSelf->m_sOutBufList.nReadPos >=
pSelf->m_sOutBufList.nBufArrSize)
{
pSelf->m_sOutBufList.nReadPos = 0;
}
}
pthread_mutex_unlock(&pSelf->m_outBufMutex);
}
pSelf->m_state = OMX_StateExecuting;
pSelf->m_Callbacks.EventHandler(
&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete, OMX_CommandStateSet,
pSelf->m_state, NULL);
post_message_to_venc_and_wait(pSelf, OMX_Venc_Cmd_Open);
}
else
{
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0 , NULL);
}
nInBufEos = OMX_FALSE; //if need it
pMarkData = NULL;
hMarkTargetComponent = NULL;
break;
}
case OMX_StatePause:
{
loge("encode component do not support OMX_StatePause");
// Transition can only happen from idle or executing state
if (pSelf->m_state == OMX_StateIdle ||
pSelf->m_state == OMX_StateExecuting)
{
pSelf->m_state = OMX_StatePause;
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandStateSet,
pSelf->m_state, NULL);
}
else
{
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0 , NULL);
}
break;
}
case OMX_StateWaitForResources:
{
if (pSelf->m_state == OMX_StateLoaded)
{
pSelf->m_state = OMX_StateWaitForResources;
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandStateSet,
pSelf->m_state, NULL);
}
else
{
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0 , NULL);
}
break;
}
default:
{
loge("unknowed OMX_State");
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0 , NULL);
break;
}
}
}
}
else if (cmd == StopPort)
{
logd("x stop port command, pCmdData = %d.", (int)pCmdData);
// Stop Port(s)
// pCmdData contains the port index to be stopped.
// It is assumed that 0 is input and 1 is output port for this component
// The pCmdData value -1 means that both input and output ports will be stopped.
if (pCmdData == 0x0 || (int)pCmdData == -1)
{
// Return all input buffers
pthread_mutex_lock(&pSelf->m_inBufMutex);
while (pSelf->m_sInBufList.nSizeOfList > 0)
{
pSelf->m_sInBufList.nSizeOfList--;
pSelf->m_Callbacks.EmptyBufferDone(
&pSelf->mOmxCmp, pSelf->m_pAppData,
pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nReadPos++]);
if (pSelf->m_sInBufList.nReadPos >= pSelf->m_sInBufList.nBufArrSize)
pSelf->m_sInBufList.nReadPos = 0;
}
pthread_mutex_unlock(&pSelf->m_inBufMutex);
// Disable port
pSelf->m_sInPortDefType.bEnabled = OMX_FALSE;
}
if (pCmdData == 0x1 || (int)pCmdData == -1)
{
// Return all output buffers
pthread_mutex_lock(&pSelf->m_outBufMutex);
while (pSelf->m_sOutBufList.nSizeOfList > 0)
{
pSelf->m_sOutBufList.nSizeOfList--;
pSelf->m_Callbacks.FillBufferDone(
&pSelf->mOmxCmp, pSelf->m_pAppData,
pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos++]);
if (pSelf->m_sOutBufList.nReadPos >= pSelf->m_sOutBufList.nBufArrSize)
pSelf->m_sOutBufList.nReadPos = 0;
}
pthread_mutex_unlock(&pSelf->m_outBufMutex);
// Disable port
pSelf->m_sOutPortDefType.bEnabled = OMX_FALSE;
}
// Wait for all buffers to be freed
nTimeout = 0x0;
while (1)
{
if (pCmdData == 0x0 && !pSelf->m_sInPortDefType.bPopulated)
{
// Return cmdcomplete event if input unpopulated
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandPortDisable, 0x0, NULL);
break;
}
if (pCmdData == 0x1 && !pSelf->m_sOutPortDefType.bPopulated)
{
// Return cmdcomplete event if output unpopulated
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandPortDisable, 0x1, NULL);
break;
}
if ((int)pCmdData == -1 && !pSelf->m_sInPortDefType.bPopulated &&
!pSelf->m_sOutPortDefType.bPopulated)
{
// Return cmdcomplete event if inout & output unpopulated
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandPortDisable, 0x0, NULL);
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandPortDisable, 0x1, NULL);
break;
}
if (nTimeout++ > OMX_MAX_TIMEOUTS)
{
pSelf->m_Callbacks.EventHandler(
&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError,
OMX_ErrorPortUnresponsiveDuringDeallocation, 0, NULL);
break;
}
usleep(OMX_TIMEOUT*1000);
}
}
else if (cmd == RestartPort)
{
logd("x restart port command.");
// Restart Port(s)
// pCmdData contains the port index to be restarted.
// It is assumed that 0 is input and 1 is output port for this component.
// The pCmdData value -1 means both input and output ports will be restarted.
if (pCmdData == 0x0 || (int)pCmdData == -1)
pSelf->m_sInPortDefType.bEnabled = OMX_TRUE;
if (pCmdData == 0x1 || (int)pCmdData == -1)
pSelf->m_sOutPortDefType.bEnabled = OMX_TRUE;
// Wait for port to be populated
nTimeout = 0x0;
while (1)
{
// Return cmdcomplete event if input port populated
if (pCmdData == 0x0 && (pSelf->m_state == OMX_StateLoaded ||
pSelf->m_sInPortDefType.bPopulated))
{
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandPortEnable, 0x0, NULL);
break;
}
// Return cmdcomplete event if output port populated
else if (pCmdData == 0x1 && (pSelf->m_state == OMX_StateLoaded ||
pSelf->m_sOutPortDefType.bPopulated))
{
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandPortEnable, 0x1, NULL);
break;
}
// Return cmdcomplete event if input and output ports populated
else if ((int)pCmdData == -1 && (pSelf->m_state == OMX_StateLoaded ||
(pSelf->m_sInPortDefType.bPopulated &&
pSelf->m_sOutPortDefType.bPopulated)))
{
pSelf->m_Callbacks.EventHandler(
&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete, OMX_CommandPortEnable, 0x0, NULL);
pSelf->m_Callbacks.EventHandler(
&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete, OMX_CommandPortEnable, 0x1, NULL);
break;
}
else if (nTimeout++ > OMX_MAX_TIMEOUTS)
{
pSelf->m_Callbacks.EventHandler(
&pSelf->mOmxCmp, pSelf->m_pAppData, OMX_EventError,
OMX_ErrorPortUnresponsiveDuringAllocation, 0, NULL);
break;
}
usleep(OMX_TIMEOUT*1000);
}
if (port_setting_match == OMX_FALSE)
port_setting_match = OMX_TRUE;
}
else if (cmd == Flush)
{
logd("x flush command.");
// Flush port(s)
// pCmdData contains the port index to be flushed.
// It is assumed that 0 is input and 1 is output port for this component
// The pCmdData value -1 means that both input and output ports will be flushed.
if (pCmdData == 0x0 || (int)pCmdData == -1)
{
// Return all input buffers and send cmdcomplete
pthread_mutex_lock(&pSelf->m_inBufMutex);
while (pSelf->m_sInBufList.nSizeOfList > 0)
{
pSelf->m_sInBufList.nSizeOfList--;
pSelf->m_Callbacks.EmptyBufferDone(
&pSelf->mOmxCmp, pSelf->m_pAppData,
pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nReadPos++]);
if (pSelf->m_sInBufList.nReadPos >= pSelf->m_sInBufList.nBufArrSize)
pSelf->m_sInBufList.nReadPos = 0;
}
pthread_mutex_unlock(&pSelf->m_inBufMutex);
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandFlush, 0x0, NULL);
}
if (pCmdData == 0x1 || (int)pCmdData == -1)
{
// Return all output buffers and send cmdcomplete
pthread_mutex_lock(&pSelf->m_outBufMutex);
while (pSelf->m_sOutBufList.nSizeOfList > 0)
{
pSelf->m_sOutBufList.nSizeOfList--;
pSelf->m_Callbacks.FillBufferDone(
&pSelf->mOmxCmp, pSelf->m_pAppData,
pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos++]);
if (pSelf->m_sOutBufList.nReadPos >= pSelf->m_sOutBufList.nBufArrSize)
pSelf->m_sOutBufList.nReadPos = 0;
}
pthread_mutex_unlock(&pSelf->m_outBufMutex);
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventCmdComplete,
OMX_CommandFlush, 0x1, NULL);
}
}
else if (cmd == Stop)
{
logd("x stop command.");
post_message_to_venc_and_wait(pSelf, OMX_Venc_Cmd_Stop);
// Kill thread
goto EXIT;
}
else if (cmd == FillBuf)
{
logv("LINE %d", __LINE__);
OMX_BUFFERHEADERTYPE* OutBufHdr = NULL;
// Fill buffer
pthread_mutex_lock(&pSelf->m_outBufMutex);
if (pSelf->m_sOutBufList.nSizeOfList <= pSelf->m_sOutBufList.nAllocSize)
{
pSelf->m_sOutBufList.nSizeOfList++;
OutBufHdr = pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nWritePos++]=
((OMX_BUFFERHEADERTYPE*) pCmdData);
if (pSelf->m_sOutBufList.nWritePos >= (int)pSelf->m_sOutBufList.nAllocSize)
{
pSelf->m_sOutBufList.nWritePos = 0;
}
}
logv("###[FillBuf ] OutBufHdr=%p", OutBufHdr);
pthread_mutex_unlock(&pSelf->m_outBufMutex);
}
else if (cmd == EmptyBuf)
{
logv("LINE %d", __LINE__);
OMX_BUFFERHEADERTYPE* inBufHdr = NULL;
// Empty buffer
pthread_mutex_lock(&pSelf->m_inBufMutex);
if (pSelf->m_sInBufList.nSizeOfList <= pSelf->m_sInBufList.nAllocSize)
{
pSelf->m_sInBufList.nSizeOfList++;
inBufHdr = pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nWritePos++] =
((OMX_BUFFERHEADERTYPE*) pCmdData);
if (pSelf->m_sInBufList.nWritePos >= (int)pSelf->m_sInBufList.nAllocSize)
pSelf->m_sInBufList.nWritePos = 0;
}
logv("###[EmptyBuf ] inBufHdr=%p", inBufHdr);
pthread_mutex_unlock(&pSelf->m_inBufMutex);
// Mark current buffer if there is outstanding command
if (pMarkBuf)
{
((OMX_BUFFERHEADERTYPE *)(pCmdData))->hMarkTargetComponent = &pSelf->mOmxCmp;
((OMX_BUFFERHEADERTYPE *)(pCmdData))->pMarkData = pMarkBuf->pMarkData;
pMarkBuf = NULL;
}
}
else if (cmd == MarkBuf)
{
if (!pMarkBuf)
pMarkBuf = (OMX_MARKTYPE *)(pCmdData);
}
}
// Buffer processing
// Only happens when the component is in executing state.
if(pSelf->m_encoder == NULL)
goto ENCODER_ERROR;
if (pSelf->m_state == OMX_StateExecuting &&
pSelf->m_sInPortDefType.bEnabled &&
pSelf->m_sOutPortDefType.bEnabled &&
port_setting_match)
{
//* check input buffer.
bNoNeedSleep = OMX_FALSE;
if (nInBufEos && (nInputBufferStep == OMX_VENC_STEP_GET_INPUTBUFFER))
{
post_message_to_venc_and_wait(pSelf, OMX_Venc_Cmd_Enc_Idle);
if (ValidBitstreamFrameNum(pSelf->m_encoder) <= 0)
{
pthread_mutex_lock(&pSelf->m_outBufMutex);
if (pSelf->m_sOutBufList.nSizeOfList > 0)
{
pSelf->m_sOutBufList.nSizeOfList--;
pOutBufHdr =
pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos++];
if (pSelf->m_sOutBufList.nReadPos >= (int)pSelf->m_sOutBufList.nAllocSize)
pSelf->m_sOutBufList.nReadPos = 0;
}
else
{
pOutBufHdr = NULL;
}
pthread_mutex_unlock(&pSelf->m_outBufMutex);
//* if no output buffer, wait for some time.
if (pOutBufHdr == NULL)
{
}
else
{
pOutBufHdr->nFlags &= ~OMX_BUFFERFLAG_CODECCONFIG;
pOutBufHdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
pOutBufHdr->nFlags |= OMX_BUFFERFLAG_EOS;
pOutBufHdr->nFilledLen = 0;
pSelf->m_Callbacks.FillBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData,
pOutBufHdr);
pOutBufHdr = NULL;
nInBufEos = OMX_FALSE;
}
}
}
if (nInputBufferStep == OMX_VENC_STEP_GET_INPUTBUFFER)
{
pthread_mutex_lock(&pSelf->m_inBufMutex);
if (pSelf->m_sInBufList.nSizeOfList > 0)
{
pSelf->m_sInBufList.nSizeOfList--;
pInBufHdr = pSelf->m_sInBufList.pBufHdrList[pSelf->m_sInBufList.nReadPos++];
if (pSelf->m_sInBufList.nReadPos >= (int)pSelf->m_sInBufList.nAllocSize)
pSelf->m_sInBufList.nReadPos = 0;
}
else
{
pInBufHdr = NULL;
}
pthread_mutex_unlock(&pSelf->m_inBufMutex);
if (pInBufHdr)
{
bNoNeedSleep = OMX_TRUE;
if (pInBufHdr->nFlags & OMX_BUFFERFLAG_EOS)
{
// Copy flag to output buffer header
nInBufEos = OMX_TRUE;
logd(" set up nInBufEos flag.: %p", pInBufHdr);
// Trigger event handler
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventBufferFlag, 0x1,
pInBufHdr->nFlags, NULL);
// Clear flag
pInBufHdr->nFlags = 0;
}
// Check for mark buffers
if (pInBufHdr->pMarkData)
{
// Copy mark to output buffer header
if (pOutBufHdr)
{
pMarkData = pInBufHdr->pMarkData;
// Copy handle to output buffer header
hMarkTargetComponent = pInBufHdr->hMarkTargetComponent;
}
}
// Trigger event handler
if (pInBufHdr->hMarkTargetComponent == &pSelf->mOmxCmp && pInBufHdr->pMarkData)
{
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventMark, 0, 0, pInBufHdr->pMarkData);
}
if (!pSelf->m_useAllocInputBuffer)
{
if (pInBufHdr->nFilledLen <= 0)
{
logw("skip this input buffer, pInBufHdr->nTimeStamp %lld",
pInBufHdr->nTimeStamp);
pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp,
pSelf->m_pAppData, pInBufHdr);
pInBufHdr = NULL;
}
else
{
#ifdef __ANDROID__
int buffer_type = *(int*)(pInBufHdr->pBuffer+pInBufHdr->nOffset);
buffer_handle_t bufferHanle = NULL;
unsigned long phyaddress = 0;
int ret = 0;
int share_fd = 0;
#if (CONF_ANDROID_MAJOR_VER >= 7)
if((buffer_type == kMetadataBufferTypeGrallocSource) || \
(buffer_type == kMetadataBufferTypeANWBuffer) || \
(buffer_type == kMetadataBufferTypeNativeHandleSource))
#else
if(buffer_type == kMetadataBufferTypeGrallocSource)
#endif
{
if (buffer_type == kMetadataBufferTypeGrallocSource)
{
bufferHanle = *(buffer_handle_t*)(pInBufHdr->pBuffer +
pInBufHdr->nOffset + 4);
}
#if (CONF_ANDROID_MAJOR_VER >= 7)
else if(buffer_type == kMetadataBufferTypeANWBuffer)
{
VideoNativeMetadata &nativeMeta = \
*(VideoNativeMetadata *)(pInBufHdr->pBuffer + \
pInBufHdr->nOffset);
ANativeWindowBuffer *buffer = \
(ANativeWindowBuffer *)nativeMeta.pBuffer;
bufferHanle = buffer->handle;
if (nativeMeta.nFenceFd >= 0) {
sp<Fence> fence = new Fence(nativeMeta.nFenceFd);
nativeMeta.nFenceFd = -1;
status_t err = fence->wait(FENCE_TIMEOUT_MS);
if (err != OK) {
ALOGE("Timed out waiting on input fence");
return NULL;
}
}
}
else if(buffer_type == kMetadataBufferTypeNativeHandleSource)
{
VideoNativeHandleMetadata &nativeHandleMeta = \
*(VideoNativeHandleMetadata *)(pInBufHdr->pBuffer + \
pInBufHdr->nOffset);
native_handle_t *nativeHandle = \
(native_handle_t *)nativeHandleMeta.pHandle;
bufferHanle = (buffer_handle_t)nativeHandle;
}
#endif
if (pSelf->m_sInPortFormatType.eColorFormat !=
OMX_COLOR_FormatAndroidOpaque)
{
logw("do not support this format: %d",
pSelf->m_sInPortFormatType.eColorFormat);
}
if(bufferHanle == NULL){
loge("omx_venc:bufferHandle is null\n");
}else{
}
if (bufferHanle)
{
int colorFormat;
//for mali GPU
private_handle_t* hnd = (private_handle_t *)(bufferHanle);
colorFormat = hnd->format;
switch (colorFormat)
{
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
{
if (pSelf->mFirstInputFrame)
{
pSelf->m_vencColorFormat = VENC_PIXEL_ABGR;
post_message_to_venc_and_wait(
pSelf, OMX_Venc_Cmd_ChangeColorFormat);
pSelf->mFirstInputFrame = OMX_FALSE;
logd("set color format to ABGR");
}
break;
}
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
{
if (pSelf->mFirstInputFrame)
{
pSelf->m_vencColorFormat = VENC_PIXEL_YVU420SP;
post_message_to_venc_and_wait(
pSelf, OMX_Venc_Cmd_ChangeColorFormat);
pSelf->mFirstInputFrame = OMX_FALSE;
logd("set color format to VENC_PIXEL_YVU420SP");
}
break;
}
case HAL_PIXEL_FORMAT_BGRA_8888:
{
logv("do nothing, defalt is ARGB");
break;
}
default:
{
logw("do not support this format: %d", colorFormat);
break;
}
}
if (pSelf->mIonFd != -1)
{
int ret = 0;
long long aw_buf_id = hnd->aw_buf_id;
int share_fd = hnd->share_fd;
ret = parse_omx_enc_input_buffer(pSelf,
aw_buf_id,
share_fd,
&phyaddress);
if(ret < 0)
loge("parse_omx_enc_input_buffer error\n");
}
else
{
loge("ion_open fail");
}
}
else
{
loge("bufferHanle is null");
}
logv("phyaddress: %lx", phyaddress);
// only support ARGB now
sInputBuffer.pAddrPhyY =
(unsigned char *)phyaddress;
sInputBuffer.pAddrPhyC =
sInputBuffer.pAddrPhyY +
ALIGN_16B(pSelf->m_sInPortDefType.format.video.nStride) *
ALIGN_16B(pSelf->m_sInPortDefType.format.video.nFrameHeight);
}
else
{
if (buffer_type != kMetadataBufferTypeCameraSource)
{
logw("skip this input buffer, error buffer type: %d",
buffer_type);
pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp,
pSelf->m_pAppData,
pInBufHdr);
//pInBufHdr = NULL;
}
else
{
memcpy(&sInputBuffer,
(pInBufHdr->pBuffer+pInBufHdr->nOffset + 4),
sizeof(VencInputBuffer));
share_fd = sInputBuffer.nShareBufFd;
ret = parse_omx_enc_input_buffer(pSelf,
(long long)sInputBuffer.nID,
share_fd,
&phyaddress);
if(ret < 0)
loge("parse_omx_enc_input_buffer error\n");
sInputBuffer.pAddrPhyY = (unsigned char*)phyaddress;
sInputBuffer.pAddrPhyC = sInputBuffer.pAddrPhyY +
pSelf->m_sInPortDefType.format.video.nStride *
pSelf->m_sInPortDefType.format.video.nFrameHeight;
}
}
//* clear flag
sInputBuffer.nFlag = 0;
sInputBuffer.nPts = pInBufHdr->nTimeStamp;
sInputBuffer.nID = (unsigned long)pInBufHdr;
if (pInBufHdr->nFlags & OMX_BUFFERFLAG_EOS)
{
sInputBuffer.nFlag |= VENC_BUFFERFLAG_EOS;
}
if (pSelf->mVideoExtParams.bEnableCropping)
{
if (pSelf->mVideoExtParams.ui16CropLeft ||
pSelf->mVideoExtParams.ui16CropTop)
{
sInputBuffer.bEnableCorp = 1;
sInputBuffer.sCropInfo.nLeft =
pSelf->mVideoExtParams.ui16CropLeft;
sInputBuffer.sCropInfo.nWidth =
pSelf->m_sOutPortDefType.format.video.nFrameWidth -
pSelf->mVideoExtParams.ui16CropLeft -
pSelf->mVideoExtParams.ui16CropRight;
sInputBuffer.sCropInfo.nTop =
pSelf->mVideoExtParams.ui16CropTop;
sInputBuffer.sCropInfo.nHeight =
pSelf->m_sOutPortDefType.format.video.nFrameHeight -
pSelf->mVideoExtParams.ui16CropTop -
pSelf->mVideoExtParams.ui16CropBottom;
}
}
result = AddOneInputBuffer(pSelf->m_encoder, &sInputBuffer);
if (result!=0)
{
nInputBufferStep = OMX_VENC_STEP_ADD_BUFFER_TO_ENC;
}
else
{
nInputBufferStep = OMX_VENC_STEP_GET_INPUTBUFFER;
}
#else
loge("do not support metadata input buffer");
#endif
}
}
else
{
int buffer_type = *(int*)(pInBufHdr->pBuffer+pInBufHdr->nOffset);
//if (pSelf->m_useMetaDataInBuffers && buffer_type !=
// kMetadataBufferTypeGrallocSource)
if (pInBufHdr->nFilledLen <= 0)
{
logw("skip this input buffer, pInBufHd:%p,"
"buffer_type=%08x,buf_size=%d",
pInBufHdr,buffer_type,
(int)pInBufHdr->nFilledLen);
pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp,
pSelf->m_pAppData, pInBufHdr);
pInBufHdr = NULL;
}
else
{
result = GetOneAllocInputBuffer(pSelf->m_encoder,
&sInputBuffer);
if (result !=0)
{
nInputBufferStep =
OMX_VENC_STEP_GET_ALLOCBUFFER;
}
else
{
int size_y;
int size_c;
switch (pSelf->m_sInPortFormatType.eColorFormat)
{
case OMX_COLOR_FormatYUV420SemiPlanar:
{
size_y =
pSelf->m_sInPortDefType.format.video.nStride *
pSelf->m_sInPortDefType.format.video.nFrameHeight;
size_c = size_y>>1;
break;
}
default:
{
size_y = pSelf->m_sInPortDefType.format.video.nStride *
pSelf->m_sInPortDefType.format.video.nFrameHeight;
size_c = size_y>>1;
break;
}
}
//* clear flag
sInputBuffer.nFlag = 0;
if (pInBufHdr->nFlags & OMX_BUFFERFLAG_EOS)
{
sInputBuffer.nFlag |= VENC_BUFFERFLAG_EOS;
}
sInputBuffer.nPts = pInBufHdr->nTimeStamp;
sInputBuffer.bEnableCorp = 0;
if (pSelf->m_sInPortFormatType.eColorFormat ==
OMX_COLOR_FormatAndroidOpaque)
{
#ifdef __ANDROID__
void* bufAddr;
buffer_handle_t bufferHanle;
int width;
int height;
//* get the argb buffer.
bufferHanle = *(buffer_handle_t*)(pInBufHdr->pBuffer +
pInBufHdr->nOffset + 4);
android::Rect rect(
(int)pSelf->m_sInPortDefType.format.video.nStride,
(int)pSelf->m_sInPortDefType.format.video.nFrameHeight);
GraphicBufferMapper::get().lock(
bufferHanle,
(GRALLOC_USAGE_HW_VIDEO_ENCODER |
GRALLOC_USAGE_SW_WRITE_OFTEN),
rect, &bufAddr);
width = pSelf->m_sInPortDefType.format.video.nStride;
height = pSelf->m_sInPortDefType.format.video.nFrameHeight;
#ifdef CONF_ARMV7_A_NEON
if (width % 32 == 0)
{
int widthandstride[2];
unsigned char* addr[2];
widthandstride[0] = width;
widthandstride[1] = width;
addr[0] = sInputBuffer.pAddrVirY;
addr[1] = sInputBuffer.pAddrVirC;
ImgRGBA2YUV420SP_neon((unsigned char *)bufAddr,
addr, widthandstride, height);
}
else
{
int widthandstride[2];
unsigned char* addr[2];
widthandstride[0] = width;
widthandstride[1] = (width + 31) & (~31);
addr[0] = sInputBuffer.pAddrVirY;
addr[1] = sInputBuffer.pAddrVirC;
ImgRGBA2YUV420SP_neon((unsigned char *)bufAddr, addr,
widthandstride, height);
}
#endif
CdcMemFlushCache(pSelf->memops, sInputBuffer.pAddrVirY,
width * height);
CdcMemFlushCache(pSelf->memops, sInputBuffer.pAddrVirC,
width * height / 2);
GraphicBufferMapper::get().unlock(bufferHanle);
#endif
}
else
{
if (pSelf->mVideoExtParams.bEnableCropping)
{
if (pSelf->mVideoExtParams.ui16CropLeft ||
pSelf->mVideoExtParams.ui16CropTop)
{
sInputBuffer.bEnableCorp = 1;
sInputBuffer.sCropInfo.nLeft =
pSelf->mVideoExtParams.ui16CropLeft;
sInputBuffer.sCropInfo.nWidth =
pSelf->m_sOutPortDefType.format.video.nFrameWidth -
pSelf->mVideoExtParams.ui16CropLeft -
pSelf->mVideoExtParams.ui16CropRight;
sInputBuffer.sCropInfo.nTop =
pSelf->mVideoExtParams.ui16CropTop;
sInputBuffer.sCropInfo.nHeight =
pSelf->m_sOutPortDefType.format.video.nFrameHeight -
pSelf->mVideoExtParams.ui16CropTop -
pSelf->mVideoExtParams.ui16CropBottom;
}
}
memcpy(sInputBuffer.pAddrVirY,
pInBufHdr->pBuffer + pInBufHdr->nOffset, size_y);
memcpy(sInputBuffer.pAddrVirC,
pInBufHdr->pBuffer + pInBufHdr->nOffset + size_y,
size_c);
}
pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp,
pSelf->m_pAppData, pInBufHdr);
FlushCacheAllocInputBuffer(pSelf->m_encoder, &sInputBuffer);
result = AddOneInputBuffer(pSelf->m_encoder, &sInputBuffer);
if (result!=0)
{
nInputBufferStep = OMX_VENC_STEP_ADD_BUFFER_TO_ENC;
}
else
{
nInputBufferStep = OMX_VENC_STEP_GET_INPUTBUFFER;
}
}
}
}
}
else
{
//* do nothing
}
}
else if (nInputBufferStep == OMX_VENC_STEP_GET_ALLOCBUFFER)
{
result = GetOneAllocInputBuffer(pSelf->m_encoder, &sInputBuffer);
if (result !=0)
{
nInputBufferStep = OMX_VENC_STEP_GET_ALLOCBUFFER;
}
else
{
int size_y;
int size_c;
switch (pSelf->m_sInPortFormatType.eColorFormat)
{
case OMX_COLOR_FormatYUV420SemiPlanar:
{
size_y = pSelf->m_sInPortDefType.format.video.nStride *
pSelf->m_sInPortDefType.format.video.nFrameHeight;
size_c = size_y>>1;
break;
}
default:
{
size_y = pSelf->m_sInPortDefType.format.video.nStride *
pSelf->m_sInPortDefType.format.video.nFrameHeight;
size_c = size_y>>1;
break;
}
}
//* clear flag
sInputBuffer.nFlag = 0;
if (pInBufHdr->nFlags & OMX_BUFFERFLAG_EOS)
{
sInputBuffer.nFlag |= VENC_BUFFERFLAG_EOS;
}
sInputBuffer.nPts = pInBufHdr->nTimeStamp;
sInputBuffer.bEnableCorp = 0;
if (pSelf->m_sInPortFormatType.eColorFormat == OMX_COLOR_FormatAndroidOpaque)
{
#ifdef __ANDROID__
void* bufAddr;
buffer_handle_t bufferHanle;
int width;
int height;
//* get the argb buffer.
bufferHanle = *(buffer_handle_t*)(pInBufHdr->pBuffer+pInBufHdr->nOffset
+ 4);
android::Rect rect((int)pSelf->m_sInPortDefType.format.video.nStride,
(int)pSelf->m_sInPortDefType.format.video.nFrameHeight);
GraphicBufferMapper::get().lock(bufferHanle,
(GRALLOC_USAGE_HW_VIDEO_ENCODER |
GRALLOC_USAGE_SW_WRITE_OFTEN),
rect, &bufAddr);
width = pSelf->m_sInPortDefType.format.video.nStride;
height = pSelf->m_sInPortDefType.format.video.nFrameHeight;
#ifdef CONF_ARMV7_A_NEON
if (width % 32 == 0)
{
int widthandstride[2];
unsigned char* addr[2];
widthandstride[0] = width;
widthandstride[1] = width;
addr[0] = sInputBuffer.pAddrVirY;
addr[1] = sInputBuffer.pAddrVirC;
ImgRGBA2YUV420SP_neon((unsigned char *)bufAddr, addr,
widthandstride, height);
}
else
{
int widthandstride[2];
unsigned char* addr[2];
widthandstride[0] = width;
widthandstride[1] = (width + 31) & (~31);
addr[0] = sInputBuffer.pAddrVirY;
addr[1] = sInputBuffer.pAddrVirC;
ImgRGBA2YUV420SP_neon((unsigned char *)bufAddr, addr,
widthandstride, height);
}
#endif
CdcMemFlushCache(pSelf->memops, sInputBuffer.pAddrVirY, width*height);
CdcMemFlushCache(pSelf->memops, sInputBuffer.pAddrVirC, width*height/2);
GraphicBufferMapper::get().unlock(bufferHanle);
#endif
}
else
{
memcpy(sInputBuffer.pAddrVirY,
pInBufHdr->pBuffer + pInBufHdr->nOffset, size_y);
memcpy(sInputBuffer.pAddrVirC,
pInBufHdr->pBuffer + pInBufHdr->nOffset + size_y, size_c);
}
pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData,
pInBufHdr);
result = AddOneInputBuffer(pSelf->m_encoder, &sInputBuffer);
if (result!=0)
{
nInputBufferStep = OMX_VENC_STEP_ADD_BUFFER_TO_ENC;
}
else
{
nInputBufferStep = OMX_VENC_STEP_GET_INPUTBUFFER;
}
}
bNoNeedSleep = OMX_TRUE;
}
else if (nInputBufferStep == OMX_VENC_STEP_ADD_BUFFER_TO_ENC)
{
result = AddOneInputBuffer(pSelf->m_encoder, &sInputBuffer);
if (result!=0)
{
nInputBufferStep = OMX_VENC_STEP_ADD_BUFFER_TO_ENC;
}
else
{
nInputBufferStep = OMX_VENC_STEP_GET_INPUTBUFFER;
bNoNeedSleep = OMX_TRUE;
}
}
//* check used buffer
if (0==AlreadyUsedInputBuffer(pSelf->m_encoder, &sInputBuffer_return))
{
bNoNeedSleep = OMX_TRUE;
if (pSelf->m_useAllocInputBuffer)
{
ReturnOneAllocInputBuffer(pSelf->m_encoder, &sInputBuffer_return);
}
else
{
pInBufHdr = (OMX_BUFFERHEADERTYPE*)sInputBuffer_return.nID;
pSelf->m_Callbacks.EmptyBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData,
pInBufHdr);
}
}
if (ValidBitstreamFrameNum(pSelf->m_encoder) > 0)
{
//* check output buffer
pthread_mutex_lock(&pSelf->m_outBufMutex);
if (pSelf->m_sOutBufList.nSizeOfList > 0)
{
pSelf->m_sOutBufList.nSizeOfList--;
pOutBufHdr = pSelf->m_sOutBufList.pBufHdrList[pSelf->m_sOutBufList.nReadPos++];
if (pSelf->m_sOutBufList.nReadPos >= (int)pSelf->m_sOutBufList.nAllocSize)
pSelf->m_sOutBufList.nReadPos = 0;
}
else
{
pOutBufHdr = NULL;
}
pthread_mutex_unlock(&pSelf->m_outBufMutex);
if (pOutBufHdr)
{
pOutBufHdr->nFlags &= ~OMX_BUFFERFLAG_CODECCONFIG;
pOutBufHdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
if (pSelf->m_firstFrameFlag
&& (pSelf->m_vencCodecType == VENC_CODEC_H264
|| pSelf->m_vencCodecType == VENC_CODEC_H265))
{
pOutBufHdr->nTimeStamp = 0; //fixed it later;
pOutBufHdr->nFilledLen = pSelf->m_headdata.nLength;
pOutBufHdr->nOffset = 0;
memcpy(pOutBufHdr->pBuffer, pSelf->m_headdata.pBuffer,
pOutBufHdr->nFilledLen);
pSelf->m_firstFrameFlag = OMX_FALSE;
pOutBufHdr->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
#if SAVE_BITSTREAM
if (OutFile)
{
fwrite(pOutBufHdr->pBuffer, 1, pOutBufHdr->nFilledLen, OutFile);
}
else
{
logw("open outfile failed");
}
#endif
pSelf->m_Callbacks.FillBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData,
pOutBufHdr);
pOutBufHdr = NULL;
}
else
{
GetOneBitstreamFrame(pSelf->m_encoder, &sOutputBuffer);
pOutBufHdr->nTimeStamp = sOutputBuffer.nPts;
pOutBufHdr->nFilledLen = sOutputBuffer.nSize0 + sOutputBuffer.nSize1;
pOutBufHdr->nOffset = 0;
#if PRINTF_FRAME_SIZE
pSelf->mFrameCnt++;
pSelf->mAllFrameSize += pOutBufHdr->nFilledLen;
timeval cur_time;
gettimeofday(&cur_time, NULL);
const uint64_t now_time = cur_time.tv_sec * 1000000LL + cur_time.tv_usec;
if (((now_time-pSelf->mTimeStart)/1000) >= pSelf->mTimeOut)
{
int bitrate_real = (pSelf->mAllFrameSize) /
((float)(now_time-pSelf->mTimeStart) / 1000000) * 8;
if (bitrate_real)
{
logd("venc bitrate real:%d,set:%ld , framerate real:%d,set:%ld , \
avg framesize real:%d,set:%ld ",
bitrate_real,
pSelf->m_sOutPortDefType.format.video.nBitrate,
pSelf->mFrameCnt,
pSelf->m_sInPortDefType.format.video.xFramerate,
bitrate_real/pSelf->mFrameCnt,
pSelf->m_sOutPortDefType.format.video.nBitrate /
(pSelf->m_sInPortDefType.format.video.xFramerate));
}
pSelf->mTimeStart = now_time;
pSelf->mFrameCnt = 0;
pSelf->mAllFrameSize = 0;
}
#endif
pOutBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
if (sOutputBuffer.nFlag & VENC_BUFFERFLAG_KEYFRAME)
{
pOutBufHdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
}
if (sOutputBuffer.nFlag & VENC_BUFFERFLAG_EOS)
{
pOutBufHdr->nFlags |= OMX_BUFFERFLAG_EOS;
}
if (pSelf->m_prependSPSPPSToIDRFrames ==
OMX_TRUE && (sOutputBuffer.nFlag & VENC_BUFFERFLAG_KEYFRAME))
{
memcpy(pOutBufHdr->pBuffer, pSelf->m_headdata.pBuffer,
pSelf->m_headdata.nLength);
memcpy(pOutBufHdr->pBuffer + pSelf->m_headdata.nLength,
sOutputBuffer.pData0, sOutputBuffer.nSize0);
if (sOutputBuffer.nSize1)
{
memcpy((pOutBufHdr->pBuffer + pSelf->m_headdata.nLength +
sOutputBuffer.nSize0),
sOutputBuffer.pData1, sOutputBuffer.nSize1);
}
pOutBufHdr->nFilledLen += pSelf->m_headdata.nLength;
}
else
{
memcpy(pOutBufHdr->pBuffer, sOutputBuffer.pData0,
sOutputBuffer.nSize0);
if (sOutputBuffer.nSize1)
{
memcpy(pOutBufHdr->pBuffer + sOutputBuffer.nSize0,
sOutputBuffer.pData1, sOutputBuffer.nSize1);
}
}
#if SAVE_BITSTREAM
if (OutFile)
{
fwrite(pOutBufHdr->pBuffer, 1, pOutBufHdr->nFilledLen, OutFile);
}
else
{
logw("open outfile failed");
}
#endif
FreeOneBitStreamFrame(pSelf->m_encoder, &sOutputBuffer);
// Check for mark buffers
if (pMarkData != NULL && hMarkTargetComponent != NULL)
{
if (ValidBitstreamFrameNum(pSelf->m_encoder) == 0)
{
// Copy mark to output buffer header
pOutBufHdr->pMarkData = pInBufHdr->pMarkData;
// Copy handle to output buffer header
pOutBufHdr->hMarkTargetComponent = pInBufHdr->hMarkTargetComponent;
pMarkData = NULL;
hMarkTargetComponent = NULL;
}
}
pSelf->m_Callbacks.FillBufferDone(&pSelf->mOmxCmp, pSelf->m_pAppData,
pOutBufHdr);
pOutBufHdr = NULL;
}
}
else
{
//* do nothing
}
}
ENCODER_ERROR:
if (!bNoNeedSleep)
{
logv("need sleep");
usleep(10*1000);
}
else
{
logv("no need sleep");
}
}
}
EXIT:
return (void*)OMX_ErrorNone;
}
static void* ComponentVencThread(void* pThreadData)
{
int result = 0;
int i;
int fd1;
fd_set rfds;
OMX_VENC_COMMANDTYPE cmd;
OMX_BOOL nEosFlag = OMX_FALSE;
struct timeval timeout;
int nSemVal;
int nRetSemGetValue;
int nStopFlag = 0;
int nWaitIdle = 0;
// Recover the pointer to my component specific data
omx_venc* pSelf = static_cast<omx_venc*>(pThreadData);
while (1)
{
fd1 = pSelf->m_venc_cmdpipe[0];
FD_ZERO(&rfds);
FD_SET(fd1, &rfds);
// Check for new command
timeout.tv_sec = 0;
timeout.tv_usec = 0;
i = select(pSelf->m_venc_cmdpipe[0]+1, &rfds, NULL, NULL, &timeout);
if (FD_ISSET(pSelf->m_venc_cmdpipe[0], &rfds))
{
// retrieve command and data from pipe
read(pSelf->m_venc_cmdpipe[0], &cmd, sizeof(cmd));
logv("(f:%s, l:%d) vdrvThread receive cmd[0x%x]", __FUNCTION__, __LINE__, cmd);
// State transition command
switch (cmd)
{
case OMX_Venc_Cmd_Open:
{
logv("(f:%s, l:%d) vencThread receive cmd[0x%x]", __FUNCTION__, __LINE__, cmd);
if (!pSelf->m_encoder)
{
openVencDriver(pSelf);
}
omx_sem_up(&pSelf->m_msg_sem);
logv("(f:%s, l:%d) vencThread receive cmd[0x%x]", __FUNCTION__, __LINE__, cmd);
break;
}
case OMX_Venc_Cmd_Close:
{
logv("(f:%s, l:%d) vencThread receive cmd[0x%x]", __FUNCTION__, __LINE__, cmd);
if (pSelf->m_encoder)
{
int ret;
ret = deparse_omx_enc_input_buffer(pSelf->mIonFd,
pSelf->m_encoder,
pSelf->mInputBufInfo);
if(ret < 0)
loge("deparse_omx_enc_input_buffer error\n");
closeVencDriver(pSelf);
}
omx_sem_up(&pSelf->m_msg_sem);
logv("(f:%s, l:%d) vencThread receive cmd[0x%x]", __FUNCTION__, __LINE__, cmd);
break;
}
case OMX_Venc_Cmd_Stop:
{
logv("(f:%s, l:%d) vencThread receive cmd[0x%x]", __FUNCTION__, __LINE__, cmd);
nStopFlag = 1;
omx_sem_up(&pSelf->m_msg_sem);
logv("(f:%s, l:%d) vencThread receive cmd[0x%x]", __FUNCTION__, __LINE__, cmd);
break;
}
case OMX_Venc_Cmd_Enc_Idle:
{
logv("(f:%s, l:%d) vencThread receive cmd[0x%x]", __FUNCTION__, __LINE__, cmd);
nWaitIdle = 1;
logv("(f:%s, l:%d) vencThread receive cmd[0x%x]", __FUNCTION__, __LINE__, cmd);
break;
}
case OMX_Venc_Cmd_ChangeBitrate:
{
logd("pSelf->m_framerate: %d, bitrate: %d", (int)pSelf->m_framerate,
(int) pSelf->m_sOutPortDefType.format.video.nBitrate);
VideoEncSetParameter(pSelf->m_encoder, VENC_IndexParamBitrate,
&pSelf->m_sOutPortDefType.format.video.nBitrate);
if (pSelf->mVideoSuperFrame.bEnable)
{
setSuperFrameCfg(pSelf);
}
break;
}
case OMX_Venc_Cmd_ChangeColorFormat:
{
VideoEncSetParameter(pSelf->m_encoder, VENC_IndexParamColorFormat,
&pSelf->m_vencColorFormat);
omx_sem_up(&pSelf->m_msg_sem);
break;
}
case OMX_Venc_Cmd_RequestIDRFrame:
{
int value = 1;
VideoEncSetParameter(pSelf->m_encoder,VENC_IndexParamForceKeyFrame, &value);
logd("(f:%s, l:%d) OMX_Venc_Cmd_RequestIDRFrame[0x%x]",
__FUNCTION__, __LINE__, cmd);
break;
}
case OMX_Venc_Cmd_ChangeFramerate:
{
logd("pSelf->m_framerate: %d, bitrate: %d", (int)pSelf->m_framerate,
(int)pSelf->m_sOutPortDefType.format.video.nBitrate);
VideoEncSetParameter(pSelf->m_encoder, VENC_IndexParamFramerate,
&pSelf->m_framerate);
if (pSelf->mVideoSuperFrame.bEnable)
setSuperFrameCfg(pSelf);
setSVCSkipCfg(pSelf);
break;
}
default:
{
logw("unknown cmd: %d", cmd);
break;
}
}
}
if (nStopFlag)
{
logd("vencThread detect nStopFlag[%d], exit!", (int)nStopFlag);
goto EXIT;
}
if (pSelf->m_state == OMX_StateExecuting && pSelf->m_encoder)
{
#if (OPEN_STATISTICS)
nTimeUs1 = GetNowUs();
#endif
result = VideoEncodeOneFrame(pSelf->m_encoder);
#if (OPEN_STATISTICS)
nTimeUs2 = GetNowUs();
logw("MicH264Enc, VideoEncodeOneFrame time %lld",(nTimeUs2-nTimeUs1));
#endif
if (result == VENC_RESULT_ERROR)
{
pSelf->m_Callbacks.EventHandler(&pSelf->mOmxCmp, pSelf->m_pAppData,
OMX_EventError, OMX_ErrorHardware,
0 , NULL);
loge("VideoEncodeOneFrame, failed, result: %d\n", result);
}
if (nWaitIdle && result == VENC_RESULT_NO_FRAME_BUFFER)
{
logv("input buffer idle \n");
omx_sem_up(&pSelf->m_msg_sem);
nWaitIdle = 0;
}
if (result != VENC_RESULT_OK)
{
waitPipeDataToRead(pSelf->m_venc_cmdpipe[0], 10 * 1000);
}
}
else
{
waitPipeDataToRead(pSelf->m_venc_cmdpipe[0], 10 * 1000);
}
}
EXIT:
return (void*)OMX_ErrorNone;
}