2470 lines
76 KiB
C
Executable File
2470 lines
76 KiB
C
Executable File
/*
|
|
* Copyright (C) 2008-2015 Allwinner Technology Co. Ltd.
|
|
* Author: Ning Fang <fangning@allwinnertech.com>
|
|
* Caoyuan Yang <yangcaoyuan@allwinnertech.com>
|
|
*
|
|
* This software is confidential and proprietary and may be used
|
|
* only as expressly authorized by a licensing agreement from
|
|
* Softwinner Products.
|
|
*
|
|
* The entire notice above must be reproduced on all copies
|
|
* and should not be removed.
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
//#define LOG_TAG "venc"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <pthread.h>
|
|
#include <errno.h>
|
|
#include <dlfcn.h>
|
|
#include <dirent.h>
|
|
#include <sys/prctl.h>
|
|
|
|
#include "cdc_log.h"
|
|
#include "vencoder.h"
|
|
#include "FrameBufferManager.h"
|
|
#include "venc_device.h"
|
|
#include "EncAdapter.h"
|
|
#include "veAdapter.h"
|
|
#include "memoryAdapter.h"
|
|
#include "CdcUtil.h"
|
|
#include "cdc_version.h"
|
|
#include "CdcIniparserapi.h"
|
|
#include "EncoderList.h"
|
|
#if VENC_SUPPORT_EXT_PARAM
|
|
#include <CdcConfigParamParser.h>
|
|
#endif
|
|
#define MAX_FRAME_BUFFER_NUM 32
|
|
|
|
#define AW_ENCODER_SHOW_SPEED_INFO (0)
|
|
|
|
#define MAX_VENCODER_CHANNEL_NUM (16)
|
|
|
|
void* OnlineThreadProcess(void* param);
|
|
void* OfflineThreadProcess(void* param);
|
|
|
|
extern void* EncppCreate();
|
|
extern void EncppDestroy(void* encpp);
|
|
extern int EncppFunction(void* encpp,
|
|
VencEncppBufferInfo* pInBuffer,
|
|
VencEncppBufferInfo* pOutBuffer,
|
|
VencEncppFuncParam* pEncppFunction);
|
|
extern VENC_DEVICE* CreateSpecificEncoder(VENC_CODEC_TYPE format);
|
|
void AddVENCPlugin(void);
|
|
|
|
typedef enum VencoderCmd
|
|
{
|
|
VENCODER_CMD_SET_STATE_INIT = 0,
|
|
VENCODER_CMD_SET_STATE_EXECUT = 1,// sync cmd
|
|
VENCODER_CMD_SET_STATE_PAUSE = 2,// sync cmd
|
|
VENCODER_CMD_RESET = 3,// sync cmd
|
|
VENCODER_CMD_FLUSH = 4,// async cmd
|
|
VENCODER_CMD_EXIT = 5,// sync cmd
|
|
VENCODER_CMD_InputFrameAvailable = 6,// async cmd
|
|
VENCODER_CMD_OutputStreamAvailable = 7,// async cmd
|
|
|
|
}VencoderCmd;
|
|
|
|
#define VENC_SEM_WAIT_REPLY_NUM (VENCODER_CMD_EXIT + 1)
|
|
|
|
typedef enum VencoderState
|
|
{
|
|
VENCODER_STATE_IDLE = 0,
|
|
VENCODER_STATE_INITED = 1,
|
|
VENCODER_STATE_EXCUTING = 2,
|
|
VENCODER_STATE_PAUSE = 3,
|
|
}VencoderState;
|
|
|
|
typedef struct ShowSpeedInfoCtx
|
|
{
|
|
int bEnable;
|
|
|
|
int64_t nCurFrameStartTime;
|
|
int64_t nCurFrameEndTime;
|
|
|
|
int64_t nPeriodStartTime;
|
|
int64_t nPeriodEndTime;
|
|
int64_t nPeriodCostTotalTime;
|
|
int64_t nPeriodFrameNum;
|
|
|
|
int64_t nPeriodMaxTime;
|
|
int64_t nPeriodMinTime;
|
|
|
|
}ShowSpeedInfoCtx;
|
|
|
|
typedef struct OverlayParam
|
|
{
|
|
unsigned char* dataBuf;
|
|
unsigned int dataSize;
|
|
VencOverlayInfoS mOverlayInfo;
|
|
pthread_mutex_t mutex;
|
|
unsigned int bNeedUpdateFlag;
|
|
}OverlayParam;
|
|
|
|
typedef struct VencContext
|
|
{
|
|
unsigned int mDbgVbvFullContiguousCnt;
|
|
int nChannelId;
|
|
|
|
OverlayParam mOverlayParam;
|
|
VENC_DEVICE* pVEncDevice;
|
|
void* pEncoderHandle;
|
|
FrameBufferManager* pFBM;
|
|
VencBaseConfig baseConfig;
|
|
VencHeaderData headerData;
|
|
VencInputBuffer curEncInputbuffer;
|
|
VENC_CODEC_TYPE codecType;
|
|
unsigned int ICVersion;
|
|
int bInit;
|
|
struct ScMemOpsS *memops;
|
|
VeOpsS* veOpsS;
|
|
void* pVeOpsSelf;
|
|
ShowSpeedInfoCtx mShowSpeedInfoCtx;
|
|
pthread_t processThread;
|
|
VencoderState eState;
|
|
CdcMessageQueue* mq;
|
|
sem_t reply_sem[VENC_SEM_WAIT_REPLY_NUM];
|
|
|
|
unsigned int bNoInputFrameFlag;
|
|
pthread_mutex_t mInputFrameLock;
|
|
unsigned int bNoOutputStreamBufFlag;
|
|
pthread_mutex_t mOutputStreamLock;
|
|
VENC_RC_MODE eRcMode;
|
|
unsigned int bNeedUpdateMbStatInfoFlag;
|
|
unsigned int bNeedUpdateSharpParamFlag;
|
|
|
|
VencCbType* pCallbacks;
|
|
void* pAppData;
|
|
int bEnableResetWholeVE;
|
|
}VencContext;
|
|
|
|
typedef enum OnlineBufNumInfo
|
|
{
|
|
Had_No_Online_Channel,
|
|
Had_Online_Channel_One_Buf,
|
|
Had_Online_Channel_Two_Buf
|
|
}OnlineBufNumInfo;
|
|
|
|
typedef struct OnlineVencContext
|
|
{
|
|
VencContext *pVencCxt[MAX_VENCODER_CHANNEL_NUM];
|
|
pthread_t onlineThread;
|
|
int nValidChannelNum;
|
|
unsigned int bNoInputFrameFlag;
|
|
pthread_mutex_t mInputFrameLock;
|
|
unsigned int bNoOutputStreamBufFlag;
|
|
pthread_mutex_t mOutputStreamLock;
|
|
CdcMessageQueue* mq;
|
|
int nOnlineChannelIndex;
|
|
OnlineBufNumInfo eOnlineBufNum;
|
|
}OnlineVencContext;
|
|
|
|
static OnlineVencContext *pOnlineCxt = NULL;
|
|
static pthread_mutex_t OnlineMutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
#if VENC_SUPPORT_EXT_PARAM
|
|
#define VE_PARAM_DYNAMIC 0
|
|
#define VE_PARAM_STATIC 1
|
|
|
|
static int check_ve_param_file(int is_static, VencContext *pCurVencCxt, int ch_id);
|
|
#endif
|
|
extern struct ScMemOpsS* MemAdapterGetOpsS();
|
|
|
|
#if 0
|
|
extern VENC_DEVICE video_encoder_h264_ver1;
|
|
extern VENC_DEVICE video_encoder_jpeg;
|
|
extern VENC_DEVICE video_encoder_h264_ver2;
|
|
extern VENC_DEVICE video_encoder_h265;
|
|
extern VENC_DEVICE video_encoder_vp8;
|
|
|
|
VENC_DEVICE* video_encoder_devices[] =
|
|
{
|
|
&video_encoder_h264_ver1,
|
|
&video_encoder_jpeg,
|
|
&video_encoder_h264_ver2,
|
|
&video_encoder_h265,
|
|
//&video_encoder_vp8, // not any product use vp8 encoder now. (bz)
|
|
0
|
|
};
|
|
#endif
|
|
|
|
static int postMessgaeAndWait(VencContext* venc_ctx, int cmd, unsigned char* param1, unsigned char* param2)
|
|
{
|
|
CdcMessage msg;
|
|
memset(&msg, 0, sizeof(CdcMessage));
|
|
msg.messageId = cmd;
|
|
msg.params[0] = (uintptr_t)(&venc_ctx->reply_sem[cmd]);
|
|
msg.params[1] = (uintptr_t)venc_ctx;
|
|
msg.params[2] = (uintptr_t)param1;
|
|
msg.params[3] = (uintptr_t)param2;
|
|
|
|
if(venc_ctx->baseConfig.bOnlineMode == 0)
|
|
CdcMessageQueuePostMessage(venc_ctx->mq, &msg);
|
|
else
|
|
CdcMessageQueuePostMessage(pOnlineCxt->mq, &msg);
|
|
|
|
logv("********* cmd = %d, wait reply start", cmd);
|
|
CdcSemTimedWait(&venc_ctx->reply_sem[cmd], -1);
|
|
logv("********* cmd = %d, wait reply finish", cmd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static inline int64_t getCurrentTime(void)
|
|
{
|
|
struct timeval tv;
|
|
int64_t time;
|
|
gettimeofday(&tv,NULL);
|
|
time = tv.tv_sec*1000000 + tv.tv_usec;
|
|
return time;
|
|
}
|
|
|
|
|
|
static VENC_DEVICE *vencoderDeviceCreate(VENC_CODEC_TYPE type)
|
|
{
|
|
VENC_DEVICE *vencoder_device_handle;
|
|
|
|
VENC_DEVICE *match_interface = CreateSpecificEncoder(type);
|
|
|
|
logv("CreateSpecificEncoder: %p", match_interface);
|
|
if(match_interface == NULL)
|
|
{
|
|
loge("CreateSpecificEncoder failed");
|
|
return NULL;
|
|
}
|
|
|
|
vencoder_device_handle = (VENC_DEVICE *)malloc(sizeof(VENC_DEVICE));
|
|
if(vencoder_device_handle == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(vencoder_device_handle, match_interface, sizeof(VENC_DEVICE));
|
|
|
|
return vencoder_device_handle;
|
|
}
|
|
static void vencoderDeviceDestroy(void *handle)
|
|
{
|
|
if (handle != NULL) {
|
|
free(handle);
|
|
}
|
|
}
|
|
|
|
static int updateSpeedInfo(VencContext* venc_ctx)
|
|
{
|
|
ShowSpeedInfoCtx* pSpeedCtx = &venc_ctx->mShowSpeedInfoCtx;
|
|
|
|
pSpeedCtx->nPeriodFrameNum++;
|
|
|
|
pSpeedCtx->nCurFrameEndTime = getCurrentTime();
|
|
pSpeedCtx->nPeriodEndTime = getCurrentTime();
|
|
|
|
int64_t nCurFrameCostTime = pSpeedCtx->nCurFrameEndTime - pSpeedCtx->nCurFrameStartTime;
|
|
pSpeedCtx->nPeriodCostTotalTime += nCurFrameCostTime;
|
|
|
|
if(pSpeedCtx->nPeriodMaxTime < nCurFrameCostTime || pSpeedCtx->nPeriodMaxTime == 0)
|
|
pSpeedCtx->nPeriodMaxTime = nCurFrameCostTime;
|
|
|
|
if(pSpeedCtx->nPeriodMinTime > nCurFrameCostTime || pSpeedCtx->nPeriodMinTime == 0)
|
|
pSpeedCtx->nPeriodMinTime = nCurFrameCostTime;
|
|
|
|
int64_t nPeriodTime = pSpeedCtx->nPeriodEndTime - pSpeedCtx->nPeriodStartTime;
|
|
if(nPeriodTime > 1*1000*1000) //* 1 second
|
|
{
|
|
int64_t nHardwareSpeed = pSpeedCtx->nPeriodCostTotalTime/pSpeedCtx->nPeriodFrameNum;
|
|
int64_t nRealSpeed = nPeriodTime/pSpeedCtx->nPeriodFrameNum;
|
|
logd(" hardware_speed = %0.2f fps, real_speed = %0.2f fps, maxTime = %0.2f ms, minTime = %0.2f ms",
|
|
(float)1000*1000/nHardwareSpeed, (float)1000*1000/nRealSpeed,
|
|
(float)pSpeedCtx->nPeriodMaxTime/1000,
|
|
(float)pSpeedCtx->nPeriodMinTime/1000);
|
|
|
|
pSpeedCtx->nCurFrameStartTime = 0;
|
|
pSpeedCtx->nCurFrameEndTime = 0;
|
|
|
|
pSpeedCtx->nPeriodStartTime = 0;
|
|
pSpeedCtx->nPeriodEndTime = 0;
|
|
pSpeedCtx->nPeriodCostTotalTime = 0;
|
|
pSpeedCtx->nPeriodFrameNum = 0;
|
|
pSpeedCtx->nPeriodMaxTime = 0;
|
|
pSpeedCtx->nPeriodMinTime = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int encodeOneFrame(VideoEncoder* pEncoder)
|
|
{
|
|
int result = 0;
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
VencCbInputBufferDoneInfo mCbDoneInfo;
|
|
memset(&mCbDoneInfo, 0 , sizeof(VencCbInputBufferDoneInfo));
|
|
VencMBModeCtrl mMbModeCtl;
|
|
memset(&mMbModeCtl, 0, sizeof(VencMBModeCtrl));
|
|
int bBSBufIsFull = 0;
|
|
|
|
if(!venc_ctx) {
|
|
return -1;
|
|
}
|
|
|
|
pthread_mutex_lock(&venc_ctx->mOverlayParam.mutex);
|
|
if(venc_ctx->mOverlayParam.bNeedUpdateFlag)
|
|
{
|
|
venc_ctx->pVEncDevice->SetParameter(venc_ctx->pEncoderHandle, VENC_IndexParamSetOverlay, (void*)&venc_ctx->mOverlayParam.mOverlayInfo);
|
|
venc_ctx->mOverlayParam.bNeedUpdateFlag = 0;
|
|
}
|
|
pthread_mutex_unlock(&venc_ctx->mOverlayParam.mutex);
|
|
|
|
struct ScMemOpsS *_memops = venc_ctx->baseConfig.memops;
|
|
unsigned int phyOffset = EncAdapterGetVeAddrOffset();
|
|
|
|
if(venc_ctx->baseConfig.bOnlineChannel == 0)
|
|
{
|
|
if(VencFbmRequestValidBuffer(venc_ctx->pFBM, &venc_ctx->curEncInputbuffer) != 0)
|
|
{
|
|
return VENC_RESULT_NO_FRAME_BUFFER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memset(&venc_ctx->curEncInputbuffer, 0, sizeof(VencInputBuffer));
|
|
}
|
|
|
|
VencGetParameter((VideoEncoder* )venc_ctx, VENC_IndexParamBSbufIsFull, &bBSBufIsFull);
|
|
|
|
if(bBSBufIsFull == 1)
|
|
{
|
|
if(venc_ctx->mDbgVbvFullContiguousCnt == 0)
|
|
{
|
|
logw("bitstream empty buffer is full: id = %d", venc_ctx->nChannelId);
|
|
}
|
|
venc_ctx->mDbgVbvFullContiguousCnt++;
|
|
}
|
|
else if(venc_ctx->mDbgVbvFullContiguousCnt > 0)
|
|
{
|
|
logw("bitstream empty buffer is enough: id = %d", venc_ctx->nChannelId);
|
|
venc_ctx->mDbgVbvFullContiguousCnt = 0;
|
|
}
|
|
|
|
if(bBSBufIsFull == 1)
|
|
{
|
|
if(venc_ctx->baseConfig.bOnlineChannel == 0)
|
|
{
|
|
VencFbmReturnValidBuffer(venc_ctx->pFBM, &venc_ctx->curEncInputbuffer);
|
|
}
|
|
if(venc_ctx->pCallbacks->InputBufferDone)
|
|
{
|
|
result = VENC_RESULT_BITSTREAM_IS_FULL;
|
|
mCbDoneInfo.nResult = result;
|
|
mCbDoneInfo.pInputBuffer = &venc_ctx->curEncInputbuffer;
|
|
venc_ctx->pCallbacks->InputBufferDone(pEncoder, venc_ctx->pAppData, &mCbDoneInfo);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
venc_ctx->curEncInputbuffer.pAddrPhyY -= phyOffset;
|
|
venc_ctx->curEncInputbuffer.pAddrPhyC -= phyOffset;
|
|
|
|
if(venc_ctx->mShowSpeedInfoCtx.bEnable == 1)
|
|
{
|
|
venc_ctx->mShowSpeedInfoCtx.nCurFrameStartTime = getCurrentTime();
|
|
if(venc_ctx->mShowSpeedInfoCtx.nPeriodStartTime == 0)
|
|
venc_ctx->mShowSpeedInfoCtx.nPeriodStartTime = getCurrentTime();
|
|
}
|
|
|
|
if(venc_ctx->curEncInputbuffer.bEnableCorp == 1)
|
|
{
|
|
if(venc_ctx->baseConfig.bOnlineChannel == 1 || venc_ctx->baseConfig.eInputFormat == VENC_PIXEL_LBC_AW)
|
|
{
|
|
logw("online-mode and lbc-format are not support crop function, online = %d, inputformat = %d",
|
|
venc_ctx->baseConfig.bOnlineChannel, venc_ctx->baseConfig.eInputFormat);
|
|
venc_ctx->curEncInputbuffer.bEnableCorp = 0;
|
|
}
|
|
}
|
|
|
|
//* update encpp sharp param before do encode frame
|
|
if(venc_ctx->pCallbacks->EventHandler)
|
|
{
|
|
VencIsp2VeParam mIsp2VeParam = {0};
|
|
|
|
int ret = venc_ctx->pCallbacks->EventHandler((VideoEncoder *)venc_ctx, venc_ctx->pAppData,
|
|
VencEvent_UpdateIspToVeParam, 0, 0, &mIsp2VeParam);
|
|
if(ret == 0)
|
|
{
|
|
VencSetParameter((VideoEncoder *)venc_ctx, VENC_IndexParamEnCameraMove, &mIsp2VeParam.mEnCameraMove);
|
|
VencSetParameter((VideoEncoder *)venc_ctx, VENC_IndexParamEnvLv, &mIsp2VeParam.mEnvLv);
|
|
VencSetParameter((VideoEncoder *)venc_ctx, VENC_IndexParamAeWeightLum, &mIsp2VeParam.mAeWeightLum);
|
|
VencSetParameter((VideoEncoder *)venc_ctx, VENC_IndexParamIspAeStatus, &mIsp2VeParam.mIspAeStatus);
|
|
if(venc_ctx->bNeedUpdateSharpParamFlag == 1)
|
|
VencSetParameter((VideoEncoder *)venc_ctx, VENC_IndexParamSharpConfig, &mIsp2VeParam.mSharpParam);
|
|
}
|
|
|
|
if(venc_ctx->eRcMode == AW_QPMAP)
|
|
{
|
|
venc_ctx->pCallbacks->EventHandler((VideoEncoder *)venc_ctx, venc_ctx->pAppData,
|
|
VencEvent_UpdateMbModeInfo, 0, 0, &mMbModeCtl);
|
|
if(mMbModeCtl.mode_ctrl_en == 1)
|
|
VencSetParameter((VideoEncoder *)venc_ctx, VENC_IndexParamMBModeCtrl, &mMbModeCtl);
|
|
}
|
|
|
|
venc_ctx->pCallbacks->EventHandler((VideoEncoder *)venc_ctx, venc_ctx->pAppData,
|
|
VencEvent_UpdateIspMotionParam, 0, 0, NULL);
|
|
}
|
|
|
|
logv("pAddrPhyY = %p, pAddrPhyC = %p", venc_ctx->curEncInputbuffer.pAddrPhyY, venc_ctx->curEncInputbuffer.pAddrPhyC);
|
|
CdcVeLock(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf);
|
|
result = venc_ctx->pVEncDevice->encode(venc_ctx->pEncoderHandle, &venc_ctx->curEncInputbuffer);
|
|
CdcVeUnLock(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf);
|
|
if(venc_ctx->pCallbacks->EventHandler)
|
|
{
|
|
if(venc_ctx->bNeedUpdateMbStatInfoFlag == 1)
|
|
{
|
|
venc_ctx->pCallbacks->EventHandler((VideoEncoder *)venc_ctx, venc_ctx->pAppData,
|
|
VencEvent_UpdateMbStatInfo, 0, 0, NULL);
|
|
}
|
|
|
|
if(venc_ctx->codecType == VENC_CODEC_H265 || venc_ctx->codecType == VENC_CODEC_H264)
|
|
{
|
|
VencVe2IspParam mVe2IspParam;
|
|
if(venc_ctx->pVEncDevice->GetParameter(venc_ctx->pEncoderHandle, VENC_IndexParamVe2IspParam, &mVe2IspParam) == 0)
|
|
{
|
|
venc_ctx->pCallbacks->EventHandler((VideoEncoder *)venc_ctx, venc_ctx->pAppData,
|
|
VencEvent_UpdateVeToIspParam, 0, 0, &mVe2IspParam);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(venc_ctx->baseConfig.bOnlineChannel == 0)
|
|
{
|
|
VencFbmReturnValidBuffer(venc_ctx->pFBM, &venc_ctx->curEncInputbuffer);
|
|
mCbDoneInfo.nResult = result;
|
|
mCbDoneInfo.pInputBuffer = &venc_ctx->curEncInputbuffer;
|
|
venc_ctx->pCallbacks->InputBufferDone(pEncoder, venc_ctx->pAppData, &mCbDoneInfo);
|
|
}
|
|
else
|
|
{
|
|
if(venc_ctx->pCallbacks && venc_ctx->pCallbacks->InputBufferDone)
|
|
{
|
|
mCbDoneInfo.nResult = result;
|
|
mCbDoneInfo.pInputBuffer = &venc_ctx->curEncInputbuffer;
|
|
venc_ctx->pCallbacks->InputBufferDone(pEncoder, venc_ctx->pAppData, &mCbDoneInfo);
|
|
}
|
|
}
|
|
|
|
if(venc_ctx->mShowSpeedInfoCtx.bEnable == 1 && result == VENC_RESULT_OK)
|
|
{
|
|
updateSpeedInfo(venc_ctx);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void enableCheckOnlineStatus()
|
|
{
|
|
int i = 0;
|
|
int bHadOnlineChannel = 0;
|
|
int bHadOfflineChannel = 0;
|
|
int OnlineIndex = 0;
|
|
for(i = 0; i < MAX_VENCODER_CHANNEL_NUM; i++)
|
|
{
|
|
if(pOnlineCxt->pVencCxt[i])
|
|
{
|
|
if(pOnlineCxt->pVencCxt[i]->baseConfig.bOnlineChannel == 0)
|
|
bHadOfflineChannel = 1;
|
|
else if(pOnlineCxt->pVencCxt[i]->baseConfig.bOnlineChannel == 1)
|
|
{
|
|
bHadOnlineChannel = 1;
|
|
OnlineIndex = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
//* we need check online status when had onlineChannel and offlineChannel
|
|
unsigned int bEnableCheckOnlineStatus = 0;
|
|
if(bHadOnlineChannel == 1 && bHadOfflineChannel == 1)
|
|
{
|
|
logd("setup bEnableCheckOnlineStatus to 1");
|
|
bEnableCheckOnlineStatus = 1;
|
|
VencSetParameter((VideoEncoder*)pOnlineCxt->pVencCxt[OnlineIndex],
|
|
VENC_IndexParamEnableCheckOnlineStatus,
|
|
&bEnableCheckOnlineStatus);
|
|
}
|
|
else if(bHadOnlineChannel == 1)
|
|
{
|
|
logd("setup bEnableCheckOnlineStatus to 0");
|
|
bEnableCheckOnlineStatus = 0;
|
|
VencSetParameter((VideoEncoder*)pOnlineCxt->pVencCxt[OnlineIndex],
|
|
VENC_IndexParamEnableCheckOnlineStatus,
|
|
&bEnableCheckOnlineStatus);
|
|
}
|
|
|
|
}
|
|
|
|
static void flushInputBuffer(VideoEncoder* pEncoder)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
VencCbInputBufferDoneInfo mCbDoneInfo;
|
|
|
|
memset(&mCbDoneInfo, 0 , sizeof(VencCbInputBufferDoneInfo));
|
|
|
|
if(venc_ctx->baseConfig.bOnlineChannel == 0) {
|
|
while (VencFbmGetValidBufferNum(venc_ctx->pFBM)) {
|
|
if (VencFbmRequestValidBuffer(venc_ctx->pFBM, &venc_ctx->curEncInputbuffer) != 0) {
|
|
logw("no inputbuffer break!");
|
|
break;
|
|
}
|
|
VencFbmReturnValidBuffer(venc_ctx->pFBM, &venc_ctx->curEncInputbuffer);
|
|
if(venc_ctx->pCallbacks->InputBufferDone)
|
|
{
|
|
mCbDoneInfo.nResult = VENC_RESULT_DROP_FRAME;
|
|
mCbDoneInfo.pInputBuffer = &venc_ctx->curEncInputbuffer;
|
|
venc_ctx->pCallbacks->InputBufferDone(pEncoder, venc_ctx->pAppData, &mCbDoneInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
//reset input buffer
|
|
VencFbmReset(venc_ctx->pFBM);
|
|
|
|
}
|
|
|
|
VideoEncoder* VencCreate(VENC_CODEC_TYPE eCodecType)
|
|
{
|
|
VencContext* venc_ctx = NULL;
|
|
int i = 0;
|
|
int loglevel;
|
|
|
|
const char* loglevelFilePath = CdcGetConfigParamterString("cdc_log_level_file_path", NULL);
|
|
loglevel = CdcGetSpecifyFilePathLogLevel(loglevelFilePath);
|
|
if(loglevel == 0)
|
|
{
|
|
loglevel = CdcGetConfigParamterInt("cdc_log_level", 3);
|
|
}
|
|
if(loglevel < 2 || 6 < loglevel)
|
|
{
|
|
loglevel = 3;
|
|
}
|
|
|
|
logd("now cedarc log level:%d", loglevel);
|
|
cdc_log_set_level(loglevel);
|
|
|
|
LogVersionInfo();
|
|
|
|
AddVENCPlugin();
|
|
|
|
venc_ctx = (VencContext*)malloc(sizeof(VencContext));
|
|
if(!venc_ctx){
|
|
loge("malloc VencContext fail!");
|
|
return NULL;
|
|
}
|
|
|
|
memset(venc_ctx, 0,sizeof(VencContext));
|
|
|
|
venc_ctx->codecType = eCodecType;
|
|
venc_ctx->bInit = 0;
|
|
|
|
if(pthread_mutex_init(&venc_ctx->mInputFrameLock, NULL) != 0)
|
|
{
|
|
loge("init mutex failed");
|
|
free(venc_ctx);
|
|
return NULL;
|
|
}
|
|
if(pthread_mutex_init(&venc_ctx->mOutputStreamLock, NULL) != 0)
|
|
{
|
|
loge("init mutex failed");
|
|
free(venc_ctx);
|
|
return NULL;
|
|
}
|
|
if(pthread_mutex_init(&venc_ctx->mOverlayParam.mutex, NULL) != 0)
|
|
{
|
|
loge("init mutex failed");
|
|
free(venc_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
int type = VE_OPS_TYPE_NORMAL;
|
|
venc_ctx->veOpsS = GetVeOpsS(type);
|
|
if(venc_ctx->veOpsS == NULL)
|
|
{
|
|
loge("get ve ops failed , type = %d",type);
|
|
free(venc_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
VeConfig mVeConfig;
|
|
memset(&mVeConfig, 0, sizeof(VeConfig));
|
|
mVeConfig.nDecoderFlag = 0;
|
|
mVeConfig.nEncoderFlag = 1;
|
|
mVeConfig.nEnableAfbcFlag = 0;
|
|
mVeConfig.nFormat = eCodecType;
|
|
mVeConfig.nWidth = 0;
|
|
mVeConfig.nResetVeMode = 0;
|
|
venc_ctx->pVeOpsSelf = CdcVeInit(venc_ctx->veOpsS, &mVeConfig);
|
|
if(venc_ctx->pVeOpsSelf == NULL)
|
|
{
|
|
loge("init ve ops failed");
|
|
CdcVeRelease(venc_ctx->veOpsS,venc_ctx->pVeOpsSelf);
|
|
free(venc_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
char* baseAddr = CdcVeGetGroupRegAddr(venc_ctx->veOpsS,
|
|
venc_ctx->pVeOpsSelf,
|
|
REG_GROUP_VETOP);
|
|
CdcVeLock(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf);
|
|
venc_ctx->ICVersion = EncAdapterGetICVersion(baseAddr);
|
|
CdcVeUnLock(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf);
|
|
|
|
//for h264 enc use new driver from ic_1708
|
|
if(eCodecType == VENC_CODEC_H264 && venc_ctx->ICVersion >= 0x1708)
|
|
eCodecType = VENC_CODEC_H264_VER2;
|
|
|
|
venc_ctx->pVEncDevice = vencoderDeviceCreate(eCodecType);
|
|
if(venc_ctx->pVEncDevice == NULL)
|
|
{
|
|
loge("VencoderDeviceCreate failed\n");
|
|
free(venc_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
venc_ctx->memops = MemAdapterGetOpsS();
|
|
if (venc_ctx->memops == NULL)
|
|
{
|
|
loge("MemAdapterGetOpsS failed\n");
|
|
free(venc_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
if(EncAdapterInitializeMem(venc_ctx->memops) != 0)
|
|
{
|
|
loge("can not set up memory runtime environment.");
|
|
free(venc_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
venc_ctx->baseConfig.veOpsS = venc_ctx->veOpsS;
|
|
venc_ctx->baseConfig.pVeOpsSelf = venc_ctx->pVeOpsSelf;
|
|
venc_ctx->baseConfig.memops = venc_ctx->memops;
|
|
|
|
venc_ctx->pEncoderHandle =
|
|
venc_ctx->pVEncDevice->open(&venc_ctx->baseConfig, venc_ctx->ICVersion);
|
|
if(!venc_ctx->pEncoderHandle)
|
|
{
|
|
logd("open VEncDevice error\n");
|
|
vencoderDeviceDestroy(venc_ctx->pVEncDevice);
|
|
venc_ctx->pVEncDevice = NULL;
|
|
free(venc_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
venc_ctx->mq = CdcMessageQueueCreate(16, "venc_thread");
|
|
for(i = 0; i < VENC_SEM_WAIT_REPLY_NUM; i++)
|
|
{
|
|
sem_init(&venc_ctx->reply_sem[i], 0, 0);
|
|
}
|
|
|
|
#if(AW_ENCODER_SHOW_SPEED_INFO)
|
|
venc_ctx->mShowSpeedInfoCtx.bEnable = 1;
|
|
#endif
|
|
|
|
venc_ctx->eState = VENCODER_STATE_IDLE;
|
|
|
|
return (VideoEncoder*)venc_ctx;
|
|
}
|
|
|
|
void VencDestroy(VideoEncoder* pEncoder)
|
|
{
|
|
int i = 0;
|
|
int ret = 0;
|
|
int nRealValidChannelNum = 0;
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if (pEncoder == NULL) {
|
|
loge("pEncoder is NULL.");
|
|
return ;
|
|
}
|
|
|
|
if(venc_ctx->eState != VENCODER_STATE_IDLE)
|
|
{
|
|
if(venc_ctx->baseConfig.bOnlineMode == 0)
|
|
{
|
|
postMessgaeAndWait(venc_ctx, VENCODER_CMD_EXIT, NULL, NULL);
|
|
pthread_join(venc_ctx->processThread, (void**)&ret);
|
|
}
|
|
else
|
|
{
|
|
pthread_mutex_lock(&OnlineMutex);
|
|
if(pOnlineCxt)
|
|
{
|
|
postMessgaeAndWait(venc_ctx, VENCODER_CMD_EXIT, NULL, NULL);
|
|
|
|
//* need re-enable checkOnlineStatus when had channel destroy
|
|
enableCheckOnlineStatus();
|
|
|
|
PRINTF_CODE_POS
|
|
for(i = 0; i < MAX_VENCODER_CHANNEL_NUM; i++)
|
|
{
|
|
if(pOnlineCxt->pVencCxt[i])
|
|
nRealValidChannelNum++;
|
|
}
|
|
PRINTF_CODE_POS
|
|
logd("nRealValidChannelNum = %d", nRealValidChannelNum);
|
|
if(nRealValidChannelNum == 0)
|
|
{
|
|
pthread_join(pOnlineCxt->onlineThread, (void**)&ret);
|
|
|
|
if(pOnlineCxt->mq)
|
|
CdcMessageQueueDestroy(pOnlineCxt->mq);
|
|
|
|
pthread_mutex_destroy(&pOnlineCxt->mInputFrameLock);
|
|
pthread_mutex_destroy(&pOnlineCxt->mOutputStreamLock);
|
|
|
|
free(pOnlineCxt);
|
|
pOnlineCxt = NULL;
|
|
}
|
|
}
|
|
pthread_mutex_unlock(&OnlineMutex);
|
|
}
|
|
|
|
venc_ctx->pVEncDevice->uninit(venc_ctx->pEncoderHandle);
|
|
|
|
if(venc_ctx->ICVersion == 0x1639)
|
|
{
|
|
if(venc_ctx->baseConfig.nDstWidth >= 3840 || venc_ctx->baseConfig.nDstHeight >= 2160)
|
|
{
|
|
CdcVeUnInitEncoderPerformance(venc_ctx->baseConfig.veOpsS, venc_ctx->baseConfig.pVeOpsSelf, 1);
|
|
}
|
|
else
|
|
{
|
|
CdcVeUnInitEncoderPerformance(venc_ctx->baseConfig.veOpsS, venc_ctx->baseConfig.pVeOpsSelf, 0);
|
|
logd("VeUninitEncoderPerformance");
|
|
}
|
|
}
|
|
|
|
flushInputBuffer(pEncoder);
|
|
|
|
if(venc_ctx->pFBM)
|
|
{
|
|
VencFbmDestroy(venc_ctx->pFBM);
|
|
venc_ctx->pFBM = NULL;
|
|
}
|
|
|
|
venc_ctx->eState = VENCODER_STATE_IDLE;
|
|
}
|
|
|
|
if(venc_ctx->mq)
|
|
{
|
|
CdcMessageQueueDestroy(venc_ctx->mq);
|
|
}
|
|
for(i = 0; i < VENC_SEM_WAIT_REPLY_NUM; i++)
|
|
{
|
|
sem_destroy(&venc_ctx->reply_sem[i]);
|
|
}
|
|
pthread_mutex_destroy(&venc_ctx->mInputFrameLock);
|
|
pthread_mutex_destroy(&venc_ctx->mOutputStreamLock);
|
|
pthread_mutex_destroy(&venc_ctx->mOverlayParam.mutex);
|
|
|
|
if(venc_ctx->mOverlayParam.dataBuf)
|
|
free(venc_ctx->mOverlayParam.dataBuf);
|
|
|
|
if(venc_ctx->pVEncDevice)
|
|
{
|
|
venc_ctx->pVEncDevice->close(venc_ctx->pEncoderHandle);
|
|
vencoderDeviceDestroy(venc_ctx->pVEncDevice);
|
|
venc_ctx->pVEncDevice = NULL;
|
|
venc_ctx->pEncoderHandle = NULL;
|
|
}
|
|
|
|
EncAdpaterRelease(venc_ctx->memops);
|
|
|
|
if(venc_ctx->veOpsS)
|
|
{
|
|
if(venc_ctx->baseConfig.bOnlineChannel)
|
|
CdcVeSetOnlineChannel(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf, 0);
|
|
|
|
CdcVeRelease(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf);
|
|
}
|
|
|
|
free(venc_ctx);
|
|
}
|
|
|
|
int VencInit(VideoEncoder* pEncoder, VencBaseConfig* pConfig)
|
|
{
|
|
int i = 0;
|
|
int result = 0;
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
PRINTF_CODE_POS
|
|
|
|
if(pEncoder == NULL || pConfig == NULL || venc_ctx->bInit)
|
|
{
|
|
loge("InitVideoEncoder, param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
if(venc_ctx->eState != VENCODER_STATE_IDLE)
|
|
{
|
|
logw("the state[%d] is not idle when call init", venc_ctx->eState);
|
|
return VENC_RESULT_ERROR;
|
|
}
|
|
|
|
logd("bOnlineMode = %d, bOnlineChannel = %d", pConfig->bOnlineMode, pConfig->bOnlineChannel);
|
|
logd("lbc2.5 = %d, 2.0 = %d, 1.5 = %d, format = %d",
|
|
pConfig->bLbcLossyComEnFlag2_5x,
|
|
pConfig->bLbcLossyComEnFlag2x, pConfig->bLbcLossyComEnFlag1_5x, pConfig->eInputFormat);
|
|
|
|
pConfig->memops = venc_ctx->memops;
|
|
pConfig->veOpsS = venc_ctx->veOpsS;
|
|
pConfig->pVeOpsSelf = venc_ctx->pVeOpsSelf;
|
|
|
|
venc_ctx->pFBM = VencFbmCreate(MAX_FRAME_BUFFER_NUM, pConfig->memops,
|
|
(void *)venc_ctx->veOpsS, venc_ctx->pVeOpsSelf);
|
|
|
|
if(venc_ctx->pFBM == NULL)
|
|
{
|
|
|
|
loge("venc_ctx->pFBM == NULL");
|
|
return VENC_RESULT_NO_MEMORY;
|
|
}
|
|
|
|
//logd("(f:%s, l:%d)", __FUNCTION__, __LINE__);
|
|
|
|
if(venc_ctx->ICVersion == 0x1639)
|
|
{
|
|
if(pConfig->nDstWidth >= 3840 || pConfig->nDstHeight>= 2160)
|
|
{
|
|
CdcVeInitEncoderPerformance(pConfig->veOpsS, pConfig->pVeOpsSelf, 1);
|
|
}
|
|
else
|
|
{
|
|
CdcVeInitEncoderPerformance(pConfig->veOpsS, pConfig->pVeOpsSelf, 0);
|
|
logd("VeInitEncoderPerformance");
|
|
}
|
|
}
|
|
|
|
//logd("(f:%s, l:%d)", __FUNCTION__, __LINE__);
|
|
|
|
memcpy(&venc_ctx->baseConfig, pConfig, sizeof(VencBaseConfig));
|
|
|
|
venc_ctx->baseConfig.veOpsS = venc_ctx->veOpsS;
|
|
venc_ctx->baseConfig.pVeOpsSelf = venc_ctx->pVeOpsSelf;
|
|
#if VENC_SUPPORT_EXT_PARAM
|
|
check_ve_param_file(VE_PARAM_STATIC, venc_ctx, venc_ctx->nChannelId);
|
|
#endif
|
|
result = venc_ctx->pVEncDevice->init(venc_ctx->pEncoderHandle, &venc_ctx->baseConfig);
|
|
if(VENC_RESULT_OK == result)
|
|
{
|
|
venc_ctx->bInit = 1;
|
|
}
|
|
else
|
|
{
|
|
loge("venc_init_fail");
|
|
}
|
|
|
|
if(pConfig->bOnlineMode == 1)
|
|
{
|
|
int bNeedCreateThreadFlag = 0;
|
|
pthread_mutex_lock(&OnlineMutex);
|
|
if(pOnlineCxt == NULL)
|
|
{
|
|
pOnlineCxt = calloc(1, sizeof(OnlineVencContext));
|
|
if(pOnlineCxt == NULL)
|
|
{
|
|
loge("calloc failed, size = %d", sizeof(OnlineVencContext));
|
|
}
|
|
pOnlineCxt->nOnlineChannelIndex = -1;
|
|
pOnlineCxt->eOnlineBufNum = Had_No_Online_Channel;
|
|
|
|
pOnlineCxt->mq = CdcMessageQueueCreate(32, "vencOn_thread");
|
|
|
|
if(pthread_mutex_init(&pOnlineCxt->mInputFrameLock, NULL) != 0)
|
|
{
|
|
loge("init mutex failed");
|
|
free(pOnlineCxt);
|
|
pthread_mutex_unlock(&OnlineMutex);
|
|
return VENC_RESULT_ERROR;
|
|
}
|
|
if(pthread_mutex_init(&pOnlineCxt->mOutputStreamLock, NULL) != 0)
|
|
{
|
|
loge("init mutex failed");
|
|
free(pOnlineCxt);
|
|
pthread_mutex_unlock(&OnlineMutex);
|
|
return VENC_RESULT_ERROR;
|
|
}
|
|
bNeedCreateThreadFlag = 1;
|
|
}
|
|
|
|
if(pOnlineCxt)
|
|
{
|
|
for(i = 0; i < MAX_VENCODER_CHANNEL_NUM; i++)
|
|
{
|
|
if(pOnlineCxt->pVencCxt[i] == NULL)
|
|
{
|
|
venc_ctx->nChannelId = i;
|
|
pOnlineCxt->pVencCxt[i] = venc_ctx;
|
|
pOnlineCxt->nValidChannelNum++;
|
|
|
|
if(venc_ctx->baseConfig.bOnlineChannel == 1)
|
|
pOnlineCxt->nOnlineChannelIndex = i;
|
|
|
|
break;
|
|
}
|
|
}
|
|
if(i >= MAX_VENCODER_CHANNEL_NUM)
|
|
{
|
|
loge("cannot find empty pVencCxt: %d", i);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if(pConfig->bOnlineChannel)
|
|
{
|
|
if(pConfig->nOnlineShareBufNum == 1)
|
|
pOnlineCxt->eOnlineBufNum = Had_Online_Channel_One_Buf;
|
|
if(pConfig->nOnlineShareBufNum == 2)
|
|
pOnlineCxt->eOnlineBufNum = Had_Online_Channel_Two_Buf;
|
|
}
|
|
logd("pOnlineCxt->eOnlineBufNum = %d", pOnlineCxt->eOnlineBufNum);
|
|
|
|
enableCheckOnlineStatus();
|
|
|
|
if(bNeedCreateThreadFlag == 1)
|
|
pthread_create(&pOnlineCxt->onlineThread, NULL, OnlineThreadProcess, NULL);
|
|
|
|
pthread_mutex_unlock(&OnlineMutex);
|
|
|
|
}
|
|
else
|
|
{
|
|
pthread_create(&venc_ctx->processThread, NULL, OfflineThreadProcess, (void*)venc_ctx);
|
|
}
|
|
|
|
PRINTF_CODE_POS
|
|
|
|
postMessgaeAndWait(venc_ctx, VENCODER_CMD_SET_STATE_INIT, NULL, NULL);
|
|
return result;
|
|
}
|
|
|
|
int VencStart(VideoEncoder* pEncoder)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("VencoderStart, param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
if(venc_ctx->eState != VENCODER_STATE_INITED && venc_ctx->eState != VENCODER_STATE_PAUSE)
|
|
{
|
|
logw("the state[%d] is not inited or pause when call start", venc_ctx->eState);
|
|
return VENC_RESULT_ERROR;
|
|
}
|
|
PRINTF_CODE_POS
|
|
|
|
postMessgaeAndWait(venc_ctx, VENCODER_CMD_SET_STATE_EXECUT, NULL, NULL);
|
|
return VENC_RESULT_OK;
|
|
}
|
|
|
|
int VencPause(VideoEncoder* pEncoder)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("VencoderPause, param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
if(venc_ctx->eState != VENCODER_STATE_EXCUTING)
|
|
{
|
|
logw("the state[%d] is not excuting when call pause", venc_ctx->eState);
|
|
return VENC_RESULT_ERROR;
|
|
}
|
|
|
|
postMessgaeAndWait(venc_ctx, VENCODER_CMD_SET_STATE_PAUSE, NULL, NULL);
|
|
return VENC_RESULT_OK;
|
|
}
|
|
|
|
int VencReset(VideoEncoder* pEncoder)
|
|
{
|
|
int result = 0;
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("VencReset, param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
if(venc_ctx->eState != VENCODER_STATE_EXCUTING && venc_ctx->eState != VENCODER_STATE_PAUSE)
|
|
{
|
|
logw("the state[%d] is not excuting or pause when call reset", venc_ctx->eState);
|
|
return VENC_RESULT_ERROR;
|
|
}
|
|
|
|
postMessgaeAndWait(venc_ctx, VENCODER_CMD_RESET, NULL, NULL);
|
|
return result;
|
|
}
|
|
|
|
int VencFlush(VideoEncoder* pEncoder, VencFlushType eFlushType)
|
|
{
|
|
int result = 0;
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("VencReset, param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
if(venc_ctx->eState == VENCODER_STATE_IDLE)
|
|
{
|
|
logw("flush invalid when state is idle");
|
|
return VENC_RESULT_ERROR;
|
|
}
|
|
|
|
postMessgaeAndWait(venc_ctx, VENCODER_CMD_FLUSH, (unsigned char*)eFlushType, NULL);
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
static int updateOverlayParam(VencContext* venc_ctx, VencOverlayInfoS *pSrcOverlayInfo)
|
|
{
|
|
int i = 0;
|
|
int totalOverlayDataLen = 0;
|
|
OverlayParam* pDstOverlay = &venc_ctx->mOverlayParam;
|
|
unsigned char* pCurBuf = NULL;
|
|
|
|
|
|
pthread_mutex_lock(&pDstOverlay->mutex);
|
|
|
|
for(i = 0; i < pSrcOverlayInfo->blk_num; i++)
|
|
totalOverlayDataLen += pSrcOverlayInfo->overlayHeaderList[i].bitmap_size;
|
|
|
|
if(totalOverlayDataLen > pDstOverlay->dataSize)
|
|
{
|
|
if(pDstOverlay->dataBuf)
|
|
free(pDstOverlay->dataBuf);
|
|
pDstOverlay->dataBuf = malloc(totalOverlayDataLen);
|
|
if(pDstOverlay->dataBuf == NULL)
|
|
{
|
|
loge("malloc failed, size = %d", totalOverlayDataLen);
|
|
pthread_mutex_unlock(&pDstOverlay->mutex);
|
|
return -1;
|
|
}
|
|
memset(pDstOverlay->dataBuf, 0, totalOverlayDataLen);
|
|
pDstOverlay->dataSize = totalOverlayDataLen;
|
|
}
|
|
|
|
memcpy(&pDstOverlay->mOverlayInfo, pSrcOverlayInfo, sizeof(VencOverlayInfoS));
|
|
pCurBuf = pDstOverlay->dataBuf;
|
|
for(i = 0; i < pSrcOverlayInfo->blk_num; i++)
|
|
{
|
|
memcpy(pCurBuf, pSrcOverlayInfo->overlayHeaderList[i].overlay_blk_addr, pSrcOverlayInfo->overlayHeaderList[i].bitmap_size);
|
|
pDstOverlay->mOverlayInfo.overlayHeaderList[i].overlay_blk_addr = pCurBuf;
|
|
pDstOverlay->mOverlayInfo.overlayHeaderList[i].bitmap_size = pSrcOverlayInfo->overlayHeaderList[i].bitmap_size;
|
|
pCurBuf += pSrcOverlayInfo->overlayHeaderList[i].bitmap_size;
|
|
}
|
|
pDstOverlay->bNeedUpdateFlag = 1;
|
|
|
|
pthread_mutex_unlock(&pDstOverlay->mutex);
|
|
return 0;
|
|
}
|
|
|
|
int VencGetParameter(VideoEncoder* pEncoder, VENC_INDEXTYPE indexType, void* paramData)
|
|
{
|
|
CEDARC_UNUSE(VencGetParameter);
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("Type(%d) pEncoder is NULL!", indexType);
|
|
return -1;
|
|
}
|
|
|
|
return venc_ctx->pVEncDevice->GetParameter(venc_ctx->pEncoderHandle, indexType, paramData);
|
|
}
|
|
|
|
int VencSetParameter(VideoEncoder* pEncoder, VENC_INDEXTYPE indexType, void* paramData)
|
|
{
|
|
int ret = 0;
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
int setParamInThread = 0;
|
|
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("Type(%d) pEncoder is NULL!", indexType);
|
|
return -1;
|
|
}
|
|
|
|
if(indexType == VENC_IndexParamH264Param)
|
|
{
|
|
VencH264Param *pH264Param = (VencH264Param *)paramData;
|
|
venc_ctx->eRcMode = pH264Param->sRcParam.eRcMode;
|
|
}
|
|
else if(indexType == VENC_IndexParamH265Param)
|
|
{
|
|
VencH265Param *pH265Param = (VencH265Param *)paramData;
|
|
venc_ctx->eRcMode = pH265Param->sRcParam.eRcMode;
|
|
}
|
|
else if(indexType == VENC_IndexParamMBInfoOutput)
|
|
{
|
|
VencMBInfo *pMBInfo = (VencMBInfo *)paramData;
|
|
if(pMBInfo->num_mb > 0 && pMBInfo->p_para)
|
|
venc_ctx->bNeedUpdateMbStatInfoFlag = 1;
|
|
}
|
|
else if(indexType == VENC_IndexParamEnableEncppSharp)
|
|
{
|
|
venc_ctx->bNeedUpdateSharpParamFlag = *((unsigned int*)paramData);
|
|
}
|
|
else if(indexType == VENC_IndexParamEncAndDecCase)
|
|
{
|
|
//* enable "reset the whole ve when call resetVe()"
|
|
int ve_is_decoding = *((int *)paramData);
|
|
venc_ctx->bEnableResetWholeVE = ve_is_decoding ? 1 : 0;
|
|
}
|
|
|
|
if(indexType == VENC_IndexParamSetOverlay)
|
|
{
|
|
return updateOverlayParam(venc_ctx, (VencOverlayInfoS *)paramData);
|
|
}
|
|
|
|
if(indexType == VENC_IndexParamEnableRecRefBufReduceFunc)
|
|
{
|
|
if(venc_ctx->bInit == 1)
|
|
{
|
|
logw("The encoder has been initialized, Please use this interface before initialization.");
|
|
return 0;
|
|
}
|
|
}
|
|
logv("indexType = %d, gdcIndex = %d", indexType, VENC_IndexParamGdcConfig);
|
|
//* sync mutex in sub-encoder when gdc and sharp config, as it will call every frame
|
|
//* and if sync by CdcVeLock, it cost too much time
|
|
if(indexType == VENC_IndexParamGdcConfig || indexType == VENC_IndexParamSharpConfig)
|
|
{
|
|
ret = venc_ctx->pVEncDevice->SetParameter(venc_ctx->pEncoderHandle, indexType, paramData);
|
|
}
|
|
else
|
|
{
|
|
CdcVeLock(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf);
|
|
ret = venc_ctx->pVEncDevice->SetParameter(venc_ctx->pEncoderHandle, indexType, paramData);
|
|
CdcVeUnLock(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int VencGetValidOutputBufNum(VideoEncoder* pEncoder)
|
|
{
|
|
CEDARC_UNUSE(VencGetValidOutputBufNum);
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
return venc_ctx->pVEncDevice->ValidBitStreamFrameNum(venc_ctx->pEncoderHandle);
|
|
}
|
|
|
|
int VencDequeueOutputBuf(VideoEncoder* pEncoder, VencOutputBuffer* pBuffer)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(venc_ctx == NULL || pBuffer == NULL)
|
|
{
|
|
loge("param is NULL venc_ctx %p pBuffer %p", venc_ctx, pBuffer);
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
if(venc_ctx->pVEncDevice->GetOneBitStreamFrame(venc_ctx->pEncoderHandle, pBuffer)!=0)
|
|
{
|
|
return VENC_RESULT_BITSTREAM_IS_EMPTY;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int VencQueueOutputBuf(VideoEncoder* pEncoder, VencOutputBuffer* pBuffer)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(!venc_ctx || (venc_ctx->baseConfig.bOnlineMode && !pOnlineCxt) || !pBuffer) {
|
|
loge("param is NULL venc_ctx %p pBuffer %p", venc_ctx, pBuffer);
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
if(venc_ctx->pVEncDevice->FreeOneBitStreamFrame(venc_ctx->pEncoderHandle, pBuffer)!=0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if(venc_ctx->baseConfig.bOnlineMode == 0)
|
|
{
|
|
pthread_mutex_lock(&venc_ctx->mOutputStreamLock);
|
|
if(venc_ctx->bNoOutputStreamBufFlag == 1)
|
|
{
|
|
CdcMessage msg;
|
|
memset(&msg, 0, sizeof(CdcMessage));
|
|
msg.messageId = VENCODER_CMD_OutputStreamAvailable;
|
|
CdcMessageQueuePostMessage(venc_ctx->mq, &msg);
|
|
venc_ctx->bNoOutputStreamBufFlag = 0;
|
|
}
|
|
pthread_mutex_unlock(&venc_ctx->mOutputStreamLock);
|
|
}
|
|
else
|
|
{
|
|
//* just send msg for online channel; not for offline channel.
|
|
//* if you do not understand, please look func of checkIsReady_online1Buf()
|
|
pthread_mutex_lock(&pOnlineCxt->mOutputStreamLock);
|
|
if(venc_ctx->baseConfig.bOnlineChannel == 1 && pOnlineCxt->bNoOutputStreamBufFlag == 1)
|
|
{
|
|
CdcMessage msg;
|
|
memset(&msg, 0, sizeof(CdcMessage));
|
|
msg.messageId = VENCODER_CMD_OutputStreamAvailable;
|
|
CdcMessageQueuePostMessage(pOnlineCxt->mq, &msg);
|
|
pOnlineCxt->bNoOutputStreamBufFlag = 0;
|
|
}
|
|
pthread_mutex_unlock(&pOnlineCxt->mOutputStreamLock);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int VencAllocateInputBuf(VideoEncoder* pEncoder, VencAllocateBufferParam *pBufferParam, VencInputBuffer* dst_inputBuf)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(pEncoder == NULL || pBufferParam == NULL || dst_inputBuf == NULL)
|
|
{
|
|
loge("param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
if(venc_ctx->pFBM == NULL)
|
|
{
|
|
loge("venc_ctx->pFBM == NULL, must call InitVideoEncoder firstly");
|
|
return VENC_RESULT_NO_RESOURCE;
|
|
}
|
|
PRINTF_CODE_POS
|
|
|
|
if(VencFbmAllocateBuffer(venc_ctx->pFBM, pBufferParam, dst_inputBuf)!=0)
|
|
{
|
|
loge("allocat inputbuffer failed");
|
|
return VENC_RESULT_NO_MEMORY;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int VencQueueInputBuf(VideoEncoder* pEncoder, VENC_IN VencInputBuffer *inputbuffer)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
int nSemCnt = 0;
|
|
|
|
if(pEncoder == NULL || inputbuffer == NULL || (venc_ctx->baseConfig.bOnlineMode && !pOnlineCxt))
|
|
{
|
|
loge("param is NULL: pEncoder = %p, inputbuffer = %p", pEncoder, inputbuffer);
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
if(venc_ctx->pFBM == NULL)
|
|
{
|
|
|
|
loge("venc_ctx->pFBM == NULL, must call InitVideoEncoder firstly");
|
|
return VENC_RESULT_NO_RESOURCE;
|
|
}
|
|
|
|
if(VencFbmAddValidBuffer(venc_ctx->pFBM, inputbuffer) != 0)
|
|
{
|
|
logv("AddValidBuffer failed");
|
|
return -1;
|
|
}
|
|
|
|
if(venc_ctx->baseConfig.bOnlineMode == 0)
|
|
{
|
|
pthread_mutex_lock(&venc_ctx->mInputFrameLock);
|
|
if(venc_ctx->bNoInputFrameFlag == 1)
|
|
{
|
|
venc_ctx->bNoInputFrameFlag = 0;
|
|
CdcMessage msg;
|
|
memset(&msg, 0, sizeof(CdcMessage));
|
|
msg.messageId = VENCODER_CMD_InputFrameAvailable;
|
|
CdcMessageQueuePostMessage(venc_ctx->mq, &msg);
|
|
}
|
|
pthread_mutex_unlock(&venc_ctx->mInputFrameLock);
|
|
}
|
|
else
|
|
{
|
|
pthread_mutex_lock(&pOnlineCxt->mInputFrameLock);
|
|
if(pOnlineCxt->bNoInputFrameFlag == 1)
|
|
{
|
|
pOnlineCxt->bNoInputFrameFlag = 0;
|
|
CdcMessage msg;
|
|
memset(&msg, 0, sizeof(CdcMessage));
|
|
msg.messageId = VENCODER_CMD_InputFrameAvailable;
|
|
CdcMessageQueuePostMessage(pOnlineCxt->mq, &msg);
|
|
}
|
|
pthread_mutex_unlock(&pOnlineCxt->mInputFrameLock);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int VencGetValidInputBufNum(VideoEncoder* pEncoder)
|
|
{
|
|
CEDARC_UNUSE(VencGetValidInputBufNum);
|
|
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
return VencFbmGetValidBufferNum(venc_ctx->pFBM);
|
|
}
|
|
|
|
int VencGetVeIommuAddr(VideoEncoder* pEncoder, struct user_iommu_param *pIommuBuf)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(venc_ctx == NULL || pIommuBuf == NULL)
|
|
{
|
|
loge("param is NULL, venc_ctx %p pIommuBuf %p", venc_ctx, pIommuBuf);
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
CdcVeGetIommuAddr(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf, pIommuBuf);
|
|
return VENC_RESULT_OK;
|
|
}
|
|
|
|
int VencFreeVeIommuAddr(VideoEncoder* pEncoder, struct user_iommu_param *pIommuBuf)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(venc_ctx == NULL || pIommuBuf == NULL)
|
|
{
|
|
loge("param is NULL, venc_ctx %p pIommuBuf %p", venc_ctx, pIommuBuf);
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
CdcVeFreeIommuAddr(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf, pIommuBuf);
|
|
return VENC_RESULT_OK;
|
|
}
|
|
|
|
int VencSetFreq(VideoEncoder* pEncoder, int nVeFreq)
|
|
{
|
|
CEDARC_UNUSE(VencSetFreq);
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
int ret;
|
|
ret = CdcVeSetSpeed(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf, nVeFreq);
|
|
if(ret < 0)
|
|
loge("VideoEncoderSetFreq %d error, ret is %d\n", nVeFreq, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int VencSetDdrMode(VideoEncoder* pEncoder, int nDdrType)
|
|
{
|
|
CEDARC_UNUSE(VencSetDdrMode);
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
if(venc_ctx == NULL)
|
|
{
|
|
loge("param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
CdcVeSetDdrMode(venc_ctx->veOpsS, venc_ctx->pVeOpsSelf, nDdrType);
|
|
|
|
return VENC_RESULT_OK;
|
|
}
|
|
|
|
int VencSetCallbacks(VideoEncoder* pEncoder, VencCbType* pCallbacks, void* pAppData)
|
|
{
|
|
VencContext* venc_ctx = (VencContext*)pEncoder;
|
|
|
|
if(pEncoder == NULL || pCallbacks == NULL)
|
|
{
|
|
loge("VencSetCallbacks, param is NULL: %p, %p", pEncoder, pCallbacks);
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
venc_ctx->pCallbacks = pCallbacks;
|
|
venc_ctx->pAppData = pAppData;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int VencJpegEnc(JpegEncInfo* pJpegInfo, EXIFInfo* pExifInfo, void* pOutBuffer, int* pOutBufferSize)
|
|
{
|
|
CEDARC_UNUSE(VencJpegEnc);
|
|
|
|
VencAllocateBufferParam bufferParam;
|
|
VideoEncoder* pVideoEnc = NULL;
|
|
VencInputBuffer inputBuffer;
|
|
VencOutputBuffer outputBuffer;
|
|
int result = 0;
|
|
struct user_iommu_param iommu_buffer;
|
|
int ion_fd = -1;
|
|
aw_ion_user_handle_t handle_ion = ION_USER_HANDLE_INIT_VALUE;
|
|
int nBufFd = -1;
|
|
unsigned char memory_type;
|
|
|
|
if (!pJpegInfo || !pExifInfo || !pOutBuffer || !pOutBufferSize)
|
|
{
|
|
loge("param is null, pJpegInfo %p pExifInfo %p pOutBuffer %p pOutBufferSize %p",
|
|
pJpegInfo, pExifInfo, pOutBuffer, pOutBufferSize);
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
memory_type = CdcIonGetMemType();
|
|
memset(&inputBuffer, 0, sizeof(VencInputBuffer));
|
|
|
|
logd("memory_type[%d](0:normal, 1:iommu), pAddrPhyY[%p], pAddrPhyC[%p],\
|
|
quality[%d], nShareBufFd[%d], cropFlag[%d]\n",
|
|
memory_type,
|
|
pJpegInfo->pAddrPhyY,
|
|
pJpegInfo->pAddrPhyC,
|
|
pJpegInfo->quality,
|
|
pJpegInfo->nShareBufFd,
|
|
pJpegInfo->bEnableCorp);
|
|
logd("input_size[%dx%d], output_size[%dx%d], stride[%d], color_format[%d]\n",
|
|
pJpegInfo->sBaseInfo.nInputWidth,
|
|
pJpegInfo->sBaseInfo.nInputHeight,
|
|
pJpegInfo->sBaseInfo.nDstWidth,
|
|
pJpegInfo->sBaseInfo.nDstHeight,
|
|
pJpegInfo->sBaseInfo.nStride,
|
|
pJpegInfo->sBaseInfo.eInputFormat);
|
|
logd("thumb_size[%dx%d]\n",
|
|
pExifInfo->ThumbWidth,
|
|
pExifInfo->ThumbHeight);
|
|
|
|
pVideoEnc = VencCreate(VENC_CODEC_JPEG);
|
|
|
|
VencSetParameter(pVideoEnc, VENC_IndexParamJpegExifInfo, pExifInfo);
|
|
VencSetParameter(pVideoEnc, VENC_IndexParamJpegQuality, &pJpegInfo->quality);
|
|
|
|
if(VencInit(pVideoEnc, &pJpegInfo->sBaseInfo) != 0)
|
|
{
|
|
result = -1;
|
|
goto ERROR;
|
|
}
|
|
|
|
if(pJpegInfo->bNoUseAddrPhy)
|
|
{
|
|
bufferParam.nSizeY = pJpegInfo->sBaseInfo.nStride*pJpegInfo->sBaseInfo.nInputHeight;
|
|
bufferParam.nSizeC = bufferParam.nSizeY>>1;
|
|
|
|
if(VencAllocateInputBuf(pVideoEnc, &bufferParam, &inputBuffer)<0)
|
|
{
|
|
result = -1;
|
|
goto ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//get ion fd
|
|
ion_fd = CdcIonOpen();
|
|
if (ion_fd < 0)
|
|
{
|
|
loge("open ion fd failed \n");
|
|
result = -1;
|
|
goto ERROR;
|
|
}
|
|
|
|
//import ion buffer handle
|
|
result = CdcIonImport(ion_fd, pJpegInfo->nShareBufFd, &handle_ion);
|
|
if (result < 0)
|
|
{
|
|
loge("CdcIonImport get handle failed\n");
|
|
result = -1;
|
|
goto ERROR;
|
|
}
|
|
|
|
//get ion buffer fd
|
|
nBufFd = CdcIonGetFd(ion_fd, (uintptr_t)handle_ion);
|
|
if (nBufFd < 0)
|
|
{
|
|
loge("CdcIonGetFd get fd failed\n");
|
|
result = -1;
|
|
goto ERROR;
|
|
}
|
|
|
|
//get iommu addr
|
|
if(memory_type == MEMORY_IOMMU)
|
|
{
|
|
iommu_buffer.fd = nBufFd;
|
|
VencGetVeIommuAddr(pVideoEnc, &iommu_buffer);
|
|
inputBuffer.pAddrPhyY = (unsigned char*)(uintptr_t)iommu_buffer.iommu_addr;
|
|
inputBuffer.pAddrPhyC = inputBuffer.pAddrPhyY +
|
|
pJpegInfo->sBaseInfo.nStride * ((pJpegInfo->sBaseInfo.nInputHeight + 15) & (~15));
|
|
}
|
|
else
|
|
{
|
|
inputBuffer.pAddrPhyY = (unsigned char *) CdcIonGetPhyAdr(ion_fd,
|
|
(uintptr_t)handle_ion);
|
|
inputBuffer.pAddrPhyC = inputBuffer.pAddrPhyY +
|
|
pJpegInfo->sBaseInfo.nStride * pJpegInfo->sBaseInfo.nInputHeight;
|
|
}
|
|
}
|
|
|
|
VencStart(pVideoEnc);
|
|
|
|
inputBuffer.bEnableCorp = pJpegInfo->bEnableCorp;
|
|
inputBuffer.sCropInfo.nLeft = pJpegInfo->sCropInfo.nLeft;
|
|
inputBuffer.sCropInfo.nTop = pJpegInfo->sCropInfo.nTop;
|
|
inputBuffer.sCropInfo.nWidth = pJpegInfo->sCropInfo.nWidth;
|
|
inputBuffer.sCropInfo.nHeight = pJpegInfo->sCropInfo.nHeight;
|
|
|
|
if(pJpegInfo->bNoUseAddrPhy)
|
|
{
|
|
memcpy(inputBuffer.pAddrVirY, pJpegInfo->pAddrPhyY, bufferParam.nSizeY);
|
|
memcpy(inputBuffer.pAddrVirC, pJpegInfo->pAddrPhyC, bufferParam.nSizeC);
|
|
inputBuffer.bNeedFlushCache = 1;
|
|
}
|
|
|
|
VencQueueInputBuf(pVideoEnc, &inputBuffer);
|
|
|
|
result = -1;
|
|
int timeoutNum = 400;
|
|
while(result != 0)
|
|
{
|
|
result = VencDequeueOutputBuf(pVideoEnc, &outputBuffer);
|
|
usleep(5*1000);
|
|
timeoutNum--;
|
|
if(timeoutNum <= 0)
|
|
{
|
|
loge("dequeue out buffer timeout");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(result == 0)
|
|
{
|
|
memcpy(pOutBuffer, outputBuffer.pData0, outputBuffer.nSize0);
|
|
if(outputBuffer.nSize1)
|
|
{
|
|
memcpy(((unsigned char*)pOutBuffer + outputBuffer.nSize0), \
|
|
outputBuffer.pData1, outputBuffer.nSize1);
|
|
*pOutBufferSize = outputBuffer.nSize0 + outputBuffer.nSize1;
|
|
}
|
|
else
|
|
{
|
|
*pOutBufferSize = outputBuffer.nSize0;
|
|
}
|
|
|
|
VencQueueOutputBuf(pVideoEnc, &outputBuffer);
|
|
}
|
|
|
|
//deattach buf fd from ve
|
|
if(memory_type == MEMORY_IOMMU)
|
|
VencFreeVeIommuAddr(pVideoEnc, &iommu_buffer);
|
|
|
|
//close buf fd
|
|
if(nBufFd != -1)
|
|
{
|
|
result = CdcIonClose(nBufFd);
|
|
if(result < 0)
|
|
{
|
|
loge("CdcIonClose close buf fd error\n");
|
|
result = -1;
|
|
goto ERROR;
|
|
}
|
|
}
|
|
|
|
//free ion handle
|
|
if(handle_ion)
|
|
{
|
|
result = CdcIonFree(ion_fd, handle_ion);
|
|
if(result < 0)
|
|
{
|
|
loge("CdcIonFree free ion_handle error\n");
|
|
goto ERROR;
|
|
}
|
|
}
|
|
|
|
if (ion_fd != -1)
|
|
{
|
|
result = CdcIonClose(ion_fd);
|
|
if(result < 0)
|
|
{
|
|
loge("CdcIonClose ion fd error\n");
|
|
goto ERROR;
|
|
}
|
|
ion_fd = -1;
|
|
}
|
|
|
|
ERROR:
|
|
|
|
if(pVideoEnc)
|
|
{
|
|
VencPause(pVideoEnc);
|
|
VencDestroy(pVideoEnc);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VideoEncoderEncpp* VencEncppCreate()
|
|
{
|
|
int loglevel;
|
|
|
|
const char* loglevelFilePath = CdcGetConfigParamterString("cdc_log_level_file_path", NULL);
|
|
loglevel = CdcGetSpecifyFilePathLogLevel(loglevelFilePath);
|
|
if(loglevel == 0)
|
|
{
|
|
loglevel = CdcGetConfigParamterInt("cdc_log_level", 3);
|
|
}
|
|
if(loglevel < 2 || 6 < loglevel)
|
|
{
|
|
loglevel = 3;
|
|
}
|
|
|
|
logd("now cedarc log level:%d", loglevel);
|
|
cdc_log_set_level(loglevel);
|
|
|
|
LogVersionInfo();
|
|
|
|
return (VideoEncoderEncpp*)EncppCreate();
|
|
}
|
|
|
|
int VencEncppDestroy(VideoEncoderEncpp* pEncpp)
|
|
{
|
|
|
|
if(pEncpp == NULL)
|
|
{
|
|
loge("param is NULL");
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
EncppDestroy((void*)pEncpp);
|
|
return VENC_RESULT_OK;
|
|
}
|
|
|
|
int VencEncppFunction(VideoEncoderEncpp* pEncpp,
|
|
VencEncppBufferInfo* pInBuffer,
|
|
VencEncppBufferInfo* pOutBuffer,
|
|
VencEncppFuncParam* pEncppFunction)
|
|
{
|
|
|
|
if (!pEncpp || !pInBuffer || !pOutBuffer || !pEncppFunction)
|
|
{
|
|
loge("param is null, pEncpp %p pInBuffer %p pOutBuffer %p pEncppFunction %p",
|
|
pEncpp, pInBuffer, pOutBuffer, pEncppFunction);
|
|
return VENC_RESULT_NULL_PTR;
|
|
}
|
|
|
|
int ret = EncppFunction((void*)pEncpp, pInBuffer, pOutBuffer, pEncppFunction);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* /proc/[pid]/maps */
|
|
static int GetLocalPathFromProcessMapsVenc(char *localPath, int len)
|
|
{
|
|
#define LOCAL_LIB "libvencoder.so"
|
|
|
|
char path[512] = {0};
|
|
char line[1024] = {0};
|
|
FILE *file = NULL;
|
|
char *strLibPos = NULL;
|
|
int ret = -1;
|
|
|
|
memset(localPath, 0x00, len);
|
|
|
|
sprintf(path, "/proc/%d/maps", getpid());
|
|
file = fopen(path, "r");
|
|
if (file == NULL)
|
|
{
|
|
loge("fopen failure, errno(%d)", errno);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
while (fgets(line, 1023, file) != NULL)
|
|
{
|
|
if ((strLibPos = strstr(line, LOCAL_LIB)) != NULL)
|
|
{
|
|
char *rootPathPos = NULL;
|
|
int localPathLen = 0;
|
|
rootPathPos = strchr(line, '/');
|
|
if (rootPathPos == NULL)
|
|
{
|
|
loge("some thing error, cur line '%s'", line);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
localPathLen = strLibPos - rootPathPos - 1;
|
|
if (localPathLen > len -1)
|
|
{
|
|
loge("localPath too long :%s ", localPath);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
memcpy(localPath, rootPathPos, localPathLen);
|
|
ret = 0;
|
|
goto out;
|
|
}
|
|
}
|
|
loge("Are you kidding? not found?");
|
|
|
|
out:
|
|
if (file)
|
|
{
|
|
fclose(file);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
typedef void VENCPluginEntry(void);
|
|
|
|
void AddVENCPluginSingle(char *lib)
|
|
{
|
|
void *libFd = NULL;
|
|
if(lib == NULL)
|
|
{
|
|
loge(" open lib == NULL ");
|
|
return;
|
|
}
|
|
|
|
libFd = dlopen(lib, RTLD_NOW);
|
|
|
|
VENCPluginEntry *PluginInit = NULL;
|
|
|
|
if (libFd == NULL)
|
|
{
|
|
loge("dlopen '%s' fail: %s", lib, dlerror());
|
|
return ;
|
|
}
|
|
|
|
PluginInit = dlsym(libFd, "CedarPluginVENCInit");
|
|
if (PluginInit == NULL)
|
|
{
|
|
logw("Invalid plugin, CedarPluginVDInit not found.");
|
|
return;
|
|
}
|
|
logv("vencoder open lib: %s", lib);
|
|
PluginInit(); /* init plugin */
|
|
return ;
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_COMPILE_STATIC_LIB
|
|
|
|
extern void CedarPluginVENCInit_h264();
|
|
extern void CedarPluginVENCInit_h265();
|
|
extern void CedarPluginVENCInit_jpeg();
|
|
|
|
void AddVENCPlugin(void)
|
|
{
|
|
|
|
#ifdef CONF_ENABLE_VENC_H264
|
|
CedarPluginVENCInit_h264();
|
|
#endif
|
|
|
|
#ifdef CONF_ENABLE_VENC_H265
|
|
CedarPluginVENCInit_h265();
|
|
#endif
|
|
|
|
#ifdef CONF_ENABLE_VENC_JPEG
|
|
CedarPluginVENCInit_jpeg();
|
|
#endif
|
|
|
|
}
|
|
#else
|
|
|
|
/* executive when load */
|
|
//static void AddVDPlugin(void) __attribute__((constructor));
|
|
void AddVENCPlugin(void)
|
|
{
|
|
CEDARC_UNUSE(AddVENCPlugin);
|
|
char localPath[512];
|
|
char slash[4] = "/";
|
|
char loadLib[512];
|
|
struct dirent **namelist = NULL;
|
|
int num = 0, index = 0;
|
|
int pathLen = 0;
|
|
int ret;
|
|
|
|
logd("add vencoder plugin from so");
|
|
|
|
memset(localPath, 0, 512);
|
|
memset(loadLib, 0, 512);
|
|
//scan_local_path:
|
|
ret = GetLocalPathFromProcessMapsVenc(localPath, 512);
|
|
if (ret != 0)
|
|
{
|
|
logw("get local path failure, scan /system/lib ");
|
|
goto scan_system_lib;
|
|
}
|
|
|
|
num = scandir(localPath, &namelist, NULL, NULL);
|
|
if (num <= 0)
|
|
{
|
|
logw("scandir failure, errno(%d), scan /system/lib ", errno);
|
|
goto scan_system_lib;
|
|
}
|
|
strcat(localPath, slash);
|
|
pathLen = strlen(localPath);
|
|
strcpy(loadLib, localPath);
|
|
logw("get local path: %s", localPath);
|
|
for(index = 0; index < num; index++)
|
|
{
|
|
if((strstr((namelist[index])->d_name, "libvenc_h264.so") != NULL) ||
|
|
(strstr((namelist[index])->d_name, "libvenc_h265.so") != NULL) ||
|
|
(strstr((namelist[index])->d_name, "libvenc_jpeg.so") != NULL))
|
|
{
|
|
loadLib[pathLen] = '\0';
|
|
strcat(loadLib, (namelist[index])->d_name);
|
|
logw("load so: %s ", loadLib);
|
|
AddVENCPluginSingle(loadLib);
|
|
}
|
|
free(namelist[index]);
|
|
namelist[index] = NULL;
|
|
}
|
|
|
|
scan_system_lib:
|
|
// TODO: scan /system/lib
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
static int doReset(VencContext *pVencCxt)
|
|
{
|
|
int ret = 0;
|
|
//reset input buffer
|
|
ret = VencFbmReset(pVencCxt->pFBM);
|
|
if(ret)
|
|
return -1;
|
|
|
|
//reset output buffer
|
|
ret = pVencCxt->pVEncDevice->ResetBitStreamFrame(pVencCxt->pEncoderHandle);
|
|
if(ret)
|
|
return -1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int doFlush(VencContext *pVencCxt, VencFlushType eFlushType)
|
|
{
|
|
int ret = 0;
|
|
int nOutputUnReturnNum = 0;
|
|
|
|
if(eFlushType == VENC_FLUSH_INPUT_BUFFER)
|
|
{
|
|
flushInputBuffer((VideoEncoder *) pVencCxt);
|
|
}
|
|
else if(eFlushType == VENC_FLUSH_OUTPUT_BUFFER)
|
|
{
|
|
nOutputUnReturnNum = pVencCxt->pVEncDevice->GetBitStreamUnReturnNum(pVencCxt->pEncoderHandle);
|
|
if(nOutputUnReturnNum == 0)
|
|
{
|
|
ret = pVencCxt->pVEncDevice->ResetBitStreamFrame(pVencCxt->pEncoderHandle);
|
|
if(ret)
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
loge("flush output buffer failed as caller not return all output buffer to vencoder, nOutputUnReturnNum = %d", nOutputUnReturnNum);
|
|
}
|
|
}
|
|
else if(eFlushType == VENC_FLUSH_IN_AND_OUT_BUFFER)
|
|
{
|
|
flushInputBuffer((VideoEncoder *) pVencCxt);
|
|
|
|
nOutputUnReturnNum = pVencCxt->pVEncDevice->GetBitStreamUnReturnNum(pVencCxt->pEncoderHandle);
|
|
if(nOutputUnReturnNum == 0)
|
|
{
|
|
ret = pVencCxt->pVEncDevice->ResetBitStreamFrame(pVencCxt->pEncoderHandle);
|
|
if(ret)
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
loge("flush output buffer failed as caller not return all output buffer to vencoder, nOutputUnReturnNum = %d", nOutputUnReturnNum);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
online-2-buf & all offline-channel:
|
|
1. check in-frame of all channel, if had, continue encode;
|
|
2. no need check out-frame;
|
|
*/
|
|
static void checkIsReady_online2Buf()
|
|
{
|
|
int i = 0;
|
|
VencContext *pCurVencCxt = NULL;
|
|
unsigned int bOnlineChannelInFrameIsReady = 0;
|
|
unsigned int bNeedContinueDoEncode = 0;
|
|
unsigned int bBSBufIsFull = 0;
|
|
unsigned int bHadInFrame = 0;
|
|
unsigned int bHadOutFrame = 0;
|
|
unsigned int nActiveOnlineChannelNum = 0;
|
|
unsigned int nActiveOfflineChannelNum = 0;
|
|
unsigned int bJustHadOnlineActiveChannel = 0;
|
|
unsigned int bOnlineChannelHadIdleOutFrame = 0;
|
|
|
|
pOnlineCxt->bNoInputFrameFlag = 0;
|
|
pOnlineCxt->bNoOutputStreamBufFlag = 0;
|
|
|
|
//*check whether need wait for in-frame
|
|
pthread_mutex_lock(&pOnlineCxt->mInputFrameLock);
|
|
pthread_mutex_lock(&pOnlineCxt->mOutputStreamLock);
|
|
for(i = 0; i < MAX_VENCODER_CHANNEL_NUM; i++)
|
|
{
|
|
if(pOnlineCxt->pVencCxt[i])
|
|
{
|
|
pCurVencCxt = pOnlineCxt->pVencCxt[i];
|
|
bHadInFrame = 0;
|
|
bHadOutFrame = 0;
|
|
|
|
if(pCurVencCxt->eState != VENCODER_STATE_EXCUTING)
|
|
continue;
|
|
|
|
VencGetParameter((VideoEncoder* )pCurVencCxt, VENC_IndexParamBSbufIsFull, &bBSBufIsFull);
|
|
if(bBSBufIsFull == 0)
|
|
bHadOutFrame = 1;
|
|
|
|
if(pCurVencCxt->baseConfig.bOnlineChannel == 0)
|
|
{
|
|
nActiveOfflineChannelNum++;
|
|
if(VencGetValidInputBufNum((VideoEncoder*)pCurVencCxt) > 0)
|
|
bHadInFrame = 1;
|
|
}
|
|
else
|
|
{
|
|
nActiveOnlineChannelNum++;
|
|
if (pCurVencCxt->codecType != VENC_CODEC_JPEG)
|
|
VencGetParameter((VideoEncoder* )pCurVencCxt, VENC_IndexParamCheckOnlineStatus, &bOnlineChannelInFrameIsReady);
|
|
if(bOnlineChannelInFrameIsReady == 1)
|
|
bHadInFrame = 1;
|
|
if(bBSBufIsFull == 0)
|
|
{
|
|
bOnlineChannelHadIdleOutFrame = 1;
|
|
}
|
|
}
|
|
|
|
if(bHadInFrame == 1 && bHadOutFrame == 1)
|
|
bNeedContinueDoEncode = 1;
|
|
|
|
logv("bNeedContinueDoEncode = %d, bHadInFrame = %d, bHadOutFrame = %d, i = %d",
|
|
bNeedContinueDoEncode, bHadInFrame, bHadOutFrame, i);
|
|
}
|
|
}
|
|
|
|
//* JustHadOnlineActiveChannel also need wait sem when had no OutFrame;
|
|
if(nActiveOfflineChannelNum == 0 && nActiveOnlineChannelNum == 1)
|
|
bJustHadOnlineActiveChannel = 1;
|
|
|
|
if(bJustHadOnlineActiveChannel == 1)
|
|
{
|
|
if(0 == bNeedContinueDoEncode)
|
|
{
|
|
if(1 == bOnlineChannelHadIdleOutFrame)
|
|
{
|
|
bNeedContinueDoEncode = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(bNeedContinueDoEncode == 0)
|
|
{
|
|
logv("** need wait for inputframe");
|
|
pOnlineCxt->bNoInputFrameFlag = 1;
|
|
pOnlineCxt->bNoOutputStreamBufFlag = 1;
|
|
}
|
|
pthread_mutex_unlock(&pOnlineCxt->mOutputStreamLock);
|
|
pthread_mutex_unlock(&pOnlineCxt->mInputFrameLock);
|
|
|
|
if(bNeedContinueDoEncode == 0)
|
|
CdcMessageQueueWaitMessage(pOnlineCxt->mq, 200);
|
|
|
|
return ;
|
|
}
|
|
|
|
/*
|
|
online-1-buf:
|
|
1. check in-frame of all offline-channel, if had, continue encode; -- (bOfflineChannelHadInFrame = 1)
|
|
2. check out-frame of online-channle, if had, continue encode; -- (bOnlineChannelHadOutFrame = 1)
|
|
3. if(bOfflineChannelHadInFrame == 0 && bOnlineChannelHadOutFrame == 0), wait for it
|
|
*/
|
|
static void checkIsReady_online1Buf()
|
|
{
|
|
int i = 0;
|
|
VencContext *pCurVencCxt = NULL;
|
|
//*check whether need wait for in-frame
|
|
unsigned int bOfflineChannelHadInFrame = 0;
|
|
unsigned int bOnlineChannelHadOutFrame = 0;
|
|
unsigned int bBSBufIsFull = 0;
|
|
unsigned int bNeedWaitForMsg = 0;
|
|
|
|
pOnlineCxt->bNoInputFrameFlag = 0;
|
|
pOnlineCxt->bNoOutputStreamBufFlag = 0;
|
|
|
|
pthread_mutex_lock(&pOnlineCxt->mInputFrameLock);
|
|
pthread_mutex_lock(&pOnlineCxt->mOutputStreamLock);
|
|
for(i = 0; i < MAX_VENCODER_CHANNEL_NUM; i++)
|
|
{
|
|
if(pOnlineCxt->pVencCxt[i])
|
|
{
|
|
pCurVencCxt = pOnlineCxt->pVencCxt[i];
|
|
|
|
if(pCurVencCxt->eState != VENCODER_STATE_EXCUTING)
|
|
continue;
|
|
|
|
//* check in-frame of offline channel
|
|
//* check out-frame of online channel
|
|
if(pCurVencCxt->baseConfig.bOnlineChannel == 0)
|
|
{
|
|
if(VencGetValidInputBufNum((VideoEncoder*)pCurVencCxt) > 0)
|
|
bOfflineChannelHadInFrame = 1;
|
|
}
|
|
else
|
|
{
|
|
VencGetParameter((VideoEncoder* )pCurVencCxt, VENC_IndexParamBSbufIsFull, &bBSBufIsFull);
|
|
if(bBSBufIsFull == 0)
|
|
bOnlineChannelHadOutFrame = 1;
|
|
}
|
|
}
|
|
}
|
|
if(bOfflineChannelHadInFrame == 0 && bOnlineChannelHadOutFrame == 0)
|
|
{
|
|
logv("** need wait for inputframe");
|
|
pOnlineCxt->bNoInputFrameFlag = 1;
|
|
pOnlineCxt->bNoOutputStreamBufFlag = 1;
|
|
bNeedWaitForMsg = 1;
|
|
}
|
|
pthread_mutex_unlock(&pOnlineCxt->mOutputStreamLock);
|
|
pthread_mutex_unlock(&pOnlineCxt->mInputFrameLock);
|
|
|
|
if(bNeedWaitForMsg == 1)
|
|
CdcMessageQueueWaitMessage(pOnlineCxt->mq, 200);
|
|
|
|
return ;
|
|
}
|
|
#if VENC_SUPPORT_EXT_PARAM
|
|
|
|
#define VE_PARAM_FILE_PATH "/tmp/ve_param_file_path.conf"
|
|
#define VE_PARAM_XML_NAME "/etc/ve_param_"
|
|
|
|
void ve_param_set_res(VideoEncoder* pVideoEnc, VencParamFromFiles *p_ve_param)
|
|
{
|
|
VencContext *pCurVencCxt = (VencContext*)pVideoEnc;
|
|
pCurVencCxt->baseConfig.nInputWidth = p_ve_param->nInputWidth;
|
|
pCurVencCxt->baseConfig.nInputHeight = p_ve_param->nInputHeight;
|
|
pCurVencCxt->baseConfig.nDstWidth = p_ve_param->nDstWidth;
|
|
pCurVencCxt->baseConfig.nDstHeight = p_ve_param->nDstHeight;
|
|
}
|
|
|
|
void ve_param_set_pxl_format(VideoEncoder* pVideoEnc, VencParamFromFiles *p_ve_param)
|
|
{
|
|
VencContext *pCurVencCxt = (VencContext*)pVideoEnc;
|
|
pCurVencCxt->baseConfig.eInputFormat = p_ve_param->eInputFormat;
|
|
pCurVencCxt->baseConfig.eOutputFormat = p_ve_param->eOutputFormat;
|
|
}
|
|
|
|
static int check_ve_param_file(int is_static, VencContext *pCurVencCxt, int ch_id)
|
|
{
|
|
char ve_param_filename[256] = {0};
|
|
char ve_param_filename_used[256] = {0};
|
|
VencParamFromFiles st_ve_param;
|
|
XML_Parser parser = NULL;
|
|
FILE *xml_file = NULL;
|
|
FILE *path_file = NULL;
|
|
|
|
memset(&st_ve_param, 0, sizeof(VencParamFromFiles));
|
|
st_ve_param.is_static = is_static;
|
|
st_ve_param.pVideoEnc = (VideoEncoder*)pCurVencCxt;
|
|
st_ve_param.codecType = pCurVencCxt->codecType;
|
|
|
|
path_file = fopen(VE_PARAM_FILE_PATH, "r");
|
|
if(path_file) {
|
|
char line[256] = {0};
|
|
int file_size = 0;
|
|
|
|
fseek(path_file, 0, SEEK_END);
|
|
file_size = ftell(path_file);
|
|
rewind(path_file);
|
|
if (file_size > sizeof(line)) {
|
|
loge("file_size large than %d, please change.", sizeof(line));
|
|
fclose(path_file);
|
|
goto ERROR_FOPEN_XML_FILE;
|
|
}
|
|
if (fgets(line, sizeof(line), path_file) != NULL) {
|
|
if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0';
|
|
snprintf(ve_param_filename, sizeof(ve_param_filename), "%s%d.xml", line, ch_id);
|
|
//logd("read xml file path: %s", ve_param_filename);
|
|
} else {
|
|
logw("read failed, maybe %s context is null, use %s\n", VE_PARAM_FILE_PATH, VE_PARAM_XML_NAME);
|
|
snprintf(ve_param_filename, sizeof(ve_param_filename), "%s%d.xml", VE_PARAM_XML_NAME, ch_id);
|
|
}
|
|
fclose(path_file);
|
|
} else {
|
|
snprintf(ve_param_filename, sizeof(ve_param_filename), "%s%d.xml", VE_PARAM_XML_NAME, ch_id);
|
|
}
|
|
if (access(ve_param_filename, F_OK) == 0) {
|
|
if (is_static)
|
|
logd("static get param xml file: %s", ve_param_filename);
|
|
else
|
|
logd("dynamic get param xml file: %s", ve_param_filename);
|
|
xml_file = fopen(ve_param_filename, "r");
|
|
if(xml_file) {
|
|
if (ParserCreateAndParse(parser, &st_ve_param, xml_file ) != 0)
|
|
goto CREATE_ERROR;
|
|
|
|
if (is_static) {
|
|
logd("static_set_ve_param done!");
|
|
} else {
|
|
char *tmp = strstr(ve_param_filename, ".xml");
|
|
strncpy(ve_param_filename_used, ve_param_filename, tmp - ve_param_filename);
|
|
strcat(ve_param_filename_used, "_used");
|
|
strcat(ve_param_filename_used, tmp);
|
|
rename(ve_param_filename, ve_param_filename_used);
|
|
logd("dynamic_set_ve_param done! change file name to %s", ve_param_filename_used);
|
|
}
|
|
} else {
|
|
loge("Please push %s.xml", ve_param_filename);
|
|
goto ERROR_FOPEN_XML_FILE;
|
|
}
|
|
}
|
|
|
|
CREATE_ERROR:
|
|
if (xml_file)
|
|
fclose(xml_file);
|
|
ERROR_FOPEN_XML_FILE:
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
void* OnlineThreadProcess(void* param)
|
|
{
|
|
int i = 0;
|
|
int ret = 0;
|
|
VencContext *pCurVencCxt = NULL;
|
|
VencInputBuffer mInputBuffer;
|
|
memset(&mInputBuffer, 0, sizeof(VencInputBuffer));
|
|
CdcMessage msg;
|
|
memset(&msg, 0, sizeof(CdcMessage));
|
|
sem_t* pReplySem = NULL;
|
|
int bHadNoOfflineChannel = 0;
|
|
int bHadOnlineChannel = 0;
|
|
int bNeedProcessMsg = 0;
|
|
int nRealValidChannelNum = 0;
|
|
int bNeedWaitForInputFrame = 0;
|
|
int bThreadExcutingState = 0;
|
|
int bBSBufIsFull = 0;
|
|
int bNeedWaitForOutputBuf = 0;
|
|
|
|
int bOfflineChannelHadNoInFrame = 0;
|
|
int tmp_cnt = 0;
|
|
int maxLoopEncodeCnt = 10;
|
|
|
|
logd("online thread start");
|
|
prctl(PR_SET_NAME, (unsigned long)"OnlineVenc", 0, 0, 0);
|
|
while(1)
|
|
{
|
|
//* process message
|
|
tmp_cnt++;
|
|
if(CdcMessageQueueTryGetMessage(pOnlineCxt->mq, &msg, 0) == 0)
|
|
{
|
|
pCurVencCxt = (VencContext *)msg.params[1];
|
|
|
|
if(msg.messageId == VENCODER_CMD_SET_STATE_INIT)
|
|
{
|
|
pCurVencCxt->eState = VENCODER_STATE_INITED;
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_SET_STATE_EXECUT)
|
|
{
|
|
//* disable "reset the whole ve when call resetVe()"
|
|
if(pCurVencCxt->veOpsS && pCurVencCxt->pVeOpsSelf && pCurVencCxt->baseConfig.bOnlineChannel && pCurVencCxt->bEnableResetWholeVE == 0)
|
|
CdcVeSetOnlineChannel(pCurVencCxt->veOpsS, pCurVencCxt->pVeOpsSelf, 1);
|
|
|
|
pCurVencCxt->eState = VENCODER_STATE_EXCUTING;
|
|
if(pCurVencCxt->baseConfig.bOnlineChannel == 1)
|
|
bHadOnlineChannel = 1;
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_SET_STATE_PAUSE)
|
|
{
|
|
pCurVencCxt->eState = VENCODER_STATE_PAUSE;
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_RESET)
|
|
{
|
|
doReset(pCurVencCxt);
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_FLUSH)
|
|
{
|
|
VencFlushType eFlushType = (VencFlushType)msg.params[2];
|
|
doFlush(pCurVencCxt, eFlushType);
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_EXIT)
|
|
{
|
|
for(i = 0; i < MAX_VENCODER_CHANNEL_NUM; i++)
|
|
{
|
|
if(pOnlineCxt->pVencCxt[i] == pCurVencCxt)
|
|
{
|
|
if(pCurVencCxt->baseConfig.bOnlineChannel == 1)
|
|
pOnlineCxt->eOnlineBufNum = Had_No_Online_Channel;
|
|
|
|
pOnlineCxt->pVencCxt[i] = NULL;
|
|
pOnlineCxt->nValidChannelNum--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_InputFrameAvailable)
|
|
{
|
|
pOnlineCxt->bNoInputFrameFlag = 0;
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_OutputStreamAvailable)
|
|
{
|
|
pOnlineCxt->bNoOutputStreamBufFlag = 0;
|
|
}
|
|
pReplySem = (sem_t*)msg.params[0];
|
|
logv("pReplySem = %p, pCurVencCxt = %p, cmd = %d, cnt = %d", pReplySem, pCurVencCxt, msg.messageId, tmp_cnt);
|
|
if(pReplySem)
|
|
sem_post(pReplySem);
|
|
}
|
|
|
|
nRealValidChannelNum = 0;
|
|
bThreadExcutingState = 0;
|
|
for(i = 0; i < MAX_VENCODER_CHANNEL_NUM; i++)
|
|
{
|
|
if(pOnlineCxt->pVencCxt[i])
|
|
nRealValidChannelNum++;
|
|
|
|
if(pOnlineCxt->pVencCxt[i] && pOnlineCxt->pVencCxt[i]->eState == VENCODER_STATE_EXCUTING)
|
|
bThreadExcutingState = 1;
|
|
}
|
|
logv("nRealValidChannelNum = %d", nRealValidChannelNum);
|
|
|
|
if(nRealValidChannelNum <= 0)
|
|
{
|
|
logd("exit the loop process, nRealValidChannelNum = %d",nRealValidChannelNum);
|
|
break;
|
|
}
|
|
|
|
if(bThreadExcutingState == 1)
|
|
{
|
|
//* do encode frame of offline-channel first;
|
|
for(i = 0; i < MAX_VENCODER_CHANNEL_NUM; i++)
|
|
{
|
|
if(pOnlineCxt->nOnlineChannelIndex == i)
|
|
continue;
|
|
|
|
if(pOnlineCxt->pVencCxt[i])
|
|
{
|
|
pCurVencCxt = pOnlineCxt->pVencCxt[i];
|
|
#if VENC_SUPPORT_EXT_PARAM
|
|
check_ve_param_file(VE_PARAM_DYNAMIC, pCurVencCxt, i);
|
|
#endif
|
|
logv("pCurVencCxt = %p, i = %d", pCurVencCxt, i);
|
|
if(pCurVencCxt->eState == VENCODER_STATE_EXCUTING)
|
|
{
|
|
if(pOnlineCxt->eOnlineBufNum == Had_No_Online_Channel)
|
|
{
|
|
int64_t start_t = getCurrentTime();
|
|
ret = encodeOneFrame((VideoEncoder*)pCurVencCxt);
|
|
int64_t end_t = getCurrentTime();
|
|
if (ret == VENC_RESULT_OK)
|
|
logv("offline[%d] encoder, ret = %d, time = %lld ms, cnt = %d",i, ret, (end_t - start_t)/1000, tmp_cnt);
|
|
|
|
}
|
|
else
|
|
{
|
|
//* encode all in-frame of every offline channel when had online channel
|
|
ret = VENC_RESULT_OK;
|
|
maxLoopEncodeCnt = 10;
|
|
while(ret == VENC_RESULT_OK)
|
|
{
|
|
int64_t start_t = getCurrentTime();
|
|
ret = encodeOneFrame((VideoEncoder*)pCurVencCxt);
|
|
int64_t end_t = getCurrentTime();
|
|
if (ret == VENC_RESULT_OK)
|
|
logv("offline[%d] encoder, ret = %d, time = %lld ms, cnt = %d",i, ret, (end_t - start_t)/1000, tmp_cnt);
|
|
maxLoopEncodeCnt--;
|
|
if(maxLoopEncodeCnt <= 0)
|
|
{
|
|
logw("loop do encode cnt exceed maxCnt[10]");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//* do encode frame of online-channel;
|
|
if(pOnlineCxt->nOnlineChannelIndex >= 0)
|
|
{
|
|
pCurVencCxt = pOnlineCxt->pVencCxt[pOnlineCxt->nOnlineChannelIndex];
|
|
if(pCurVencCxt)
|
|
{
|
|
if(pCurVencCxt->eState == VENCODER_STATE_EXCUTING)
|
|
{
|
|
int64_t start_t = getCurrentTime();
|
|
ret = encodeOneFrame((VideoEncoder*)pCurVencCxt);
|
|
int64_t end_t = getCurrentTime();
|
|
if (ret == 0)
|
|
{
|
|
logv("online[%d] encoder, ret = %d, time = %lld ms, cnt = %d, ",
|
|
pOnlineCxt->nOnlineChannelIndex, ret, (end_t - start_t)/1000, tmp_cnt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
logv("pOnlineCxt->eOnlineBufNum = %d", pOnlineCxt->eOnlineBufNum);
|
|
if(pOnlineCxt->eOnlineBufNum == Had_Online_Channel_One_Buf)
|
|
checkIsReady_online1Buf();
|
|
else if(pOnlineCxt->eOnlineBufNum == Had_Online_Channel_Two_Buf || pOnlineCxt->eOnlineBufNum == Had_No_Online_Channel)
|
|
checkIsReady_online2Buf();
|
|
else
|
|
loge("eOnlineBufNum[%d] is error", pOnlineCxt->eOnlineBufNum);
|
|
|
|
}
|
|
else
|
|
{
|
|
CdcMessageQueueWaitMessage(pOnlineCxt->mq, 200);
|
|
}
|
|
}
|
|
|
|
logd("exit the thread");
|
|
return 0;
|
|
}
|
|
|
|
void* OfflineThreadProcess(void* param)
|
|
{
|
|
int ret = 0;
|
|
VencContext *pVencCxt = (VencContext *)param;
|
|
sem_t* pReplySem = NULL;
|
|
VencInputBuffer mInputBuffer;
|
|
memset(&mInputBuffer, 0, sizeof(VencInputBuffer));
|
|
CdcMessage msg;
|
|
memset(&msg, 0, sizeof(CdcMessage));
|
|
int bExitFlag = 0;
|
|
int bNeedWaitMsg = 0;
|
|
|
|
logd("offline thread start");
|
|
char strThreadName[32];
|
|
sprintf(strThreadName, "OfflineVencChn%d", pVencCxt->nChannelId);
|
|
prctl(PR_SET_NAME, (unsigned long)strThreadName, 0, 0, 0);
|
|
while(1)
|
|
{
|
|
//* process message
|
|
if(CdcMessageQueueTryGetMessage(pVencCxt->mq, &msg, 0) == 0)
|
|
{
|
|
if(msg.messageId == VENCODER_CMD_SET_STATE_INIT)
|
|
pVencCxt->eState = VENCODER_STATE_INITED;
|
|
else if(msg.messageId == VENCODER_CMD_SET_STATE_EXECUT)
|
|
pVencCxt->eState = VENCODER_STATE_EXCUTING;
|
|
else if(msg.messageId == VENCODER_CMD_SET_STATE_PAUSE)
|
|
pVencCxt->eState = VENCODER_STATE_PAUSE;
|
|
else if(msg.messageId == VENCODER_CMD_RESET)
|
|
{
|
|
doReset(pVencCxt);
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_FLUSH)
|
|
{
|
|
VencFlushType eFlushType = (VencFlushType)msg.params[2];
|
|
doFlush(pVencCxt, eFlushType);
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_EXIT)
|
|
{
|
|
bExitFlag = 1;
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_InputFrameAvailable)
|
|
{
|
|
pVencCxt->bNoInputFrameFlag = 0;
|
|
}
|
|
else if(msg.messageId == VENCODER_CMD_OutputStreamAvailable)
|
|
{
|
|
pVencCxt->bNoOutputStreamBufFlag = 0;
|
|
}
|
|
|
|
pReplySem = (sem_t*)msg.params[0];
|
|
logv("pReplySem = %p, cmd = %d",pReplySem, msg.messageId);
|
|
if(pReplySem)
|
|
sem_post(pReplySem);
|
|
}
|
|
|
|
if(bExitFlag == 1)
|
|
{
|
|
logd("exit the loop process");
|
|
break;
|
|
}
|
|
|
|
//* do encode frame
|
|
if(pVencCxt->eState == VENCODER_STATE_EXCUTING)
|
|
{
|
|
#if VENC_SUPPORT_EXT_PARAM
|
|
check_ve_param_file(VE_PARAM_DYNAMIC, pVencCxt, pVencCxt->nChannelId);
|
|
#endif
|
|
ret = encodeOneFrame((VideoEncoder*)pVencCxt);
|
|
if(ret == VENC_RESULT_NO_FRAME_BUFFER)
|
|
{
|
|
bNeedWaitMsg = 0;
|
|
pthread_mutex_lock(&pVencCxt->mInputFrameLock);
|
|
if(VencFbmGetValidBufferNum(pVencCxt->pFBM) <= 0)
|
|
{
|
|
pVencCxt->bNoInputFrameFlag = 1;
|
|
bNeedWaitMsg = 1;
|
|
}
|
|
pthread_mutex_unlock(&pVencCxt->mInputFrameLock);
|
|
|
|
if(bNeedWaitMsg == 1)
|
|
CdcMessageQueueWaitMessage(pVencCxt->mq, 200);
|
|
|
|
continue;
|
|
}
|
|
else if(ret == VENC_RESULT_BITSTREAM_IS_FULL)
|
|
{
|
|
int bBSBufIsFull = 0;
|
|
bNeedWaitMsg = 0;
|
|
pthread_mutex_lock(&pVencCxt->mOutputStreamLock);
|
|
VencGetParameter((VideoEncoder* )pVencCxt, VENC_IndexParamBSbufIsFull, &bBSBufIsFull);
|
|
if(bBSBufIsFull == 1)
|
|
{
|
|
pVencCxt->bNoOutputStreamBufFlag = 1;
|
|
bNeedWaitMsg = 1;
|
|
}
|
|
pthread_mutex_unlock(&pVencCxt->mOutputStreamLock);
|
|
|
|
if(bNeedWaitMsg == 1)
|
|
CdcMessageQueueWaitMessage(pVencCxt->mq, 200);
|
|
|
|
continue;
|
|
}
|
|
|
|
//if (ret == 0)
|
|
// logv("encoder, ret = %d, time = %lld ms",ret, (end_t - start_t)/1000);
|
|
}
|
|
else
|
|
{
|
|
CdcMessageQueueWaitMessage(pVencCxt->mq, 200);
|
|
}
|
|
}
|
|
|
|
logd("exit the thread");
|
|
return 0;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|