sdk-hwV1.3/external/eyesee-mpp/middleware/sun8iw21/media/component/VideoEnc_Component.c

9927 lines
408 KiB
C
Executable File

/******************************************************************************
Copyright (C), 2001-2016, Allwinner Tech. Co., Ltd.
******************************************************************************
File Name : VideoEnc_Component.c
Version : Initial Draft
Author : Allwinner BU3-PD2 Team
Created : 2016/05/09
Last Modified :
Description : mpp component implement
Function List :
History :
******************************************************************************/
//#define LOG_NDEBUG 0
#define LOG_TAG "VideoEnc_Component"
#include <utils/plat_log.h>
//ref platform headers
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/prctl.h>
#include <assert.h>
#include <sched.h>
#include <pthread.h>
#include <sys/syscall.h>
#include "plat_type.h"
#include "plat_errno.h"
#include "plat_defines.h"
#include "plat_math.h"
#include <plat_systrace.h>
#include "cdx_list.h"
//media api headers to app
#include "SystemBase.h"
#include "mm_common.h"
#include "mm_comm_video.h"
#include "mm_comm_venc.h"
#include "mpi_venc.h"
//media internal common headers.
#include "media_common.h"
#include <media_common_vcodec.h>
#include <mpi_videoformat_conversion.h>
#include "mm_component.h"
#include "ComponentCommon.h"
#include "tmessage.h"
#include "tsemaphore.h"
#include <vencoder.h>
#include <memoryAdapter.h>
#include <veAdapter.h>
#include "VideoEnc_Component.h"
#include <VencCompStream.h>
#include <EncodedStream.h>
#include <VideoFrameInfoNode.h>
#include <VIDEO_FRAME_INFO_S.h>
#include <mm_comm_venc_op.h>
#include "cedarx_demux.h"
#include <sunxi_camera_v2.h>
#include <media_debug.h>
#include "CapsEncppYUVData.h"
#include "FillVencSeiData.h"
//------------------------------------------------------------------------------------
//#define VIDEO_ENC_TIME_DEBUG
//#define STORE_TIMEOUT_VIDEO_FRAME
//#define ENABLE_ENCODE_STATISTICS
//#define VENC_IGNORE_ALL_FRAME
//#define STORE_VENC_IN_FRAME
//#define STORE_VENC_OUT_STREAM
//#define STORE_VENC_CH_ID (1)
#ifdef STORE_VENC_IN_FRAME
#define STORE_VENC_FRAME_FILE "/mnt/extsd/venc_frame.yuv"
#define STORE_VENC_FRAME_TOTAL_CNT (100)
static FILE* g_debug_fp_frame = NULL;
static unsigned int g_debug_frame_cnt = 0;
#endif
#ifdef STORE_VENC_OUT_STREAM
#define STORE_VENC_STREAM_FILE "/mnt/extsd/venc_stream.raw"
static FILE* g_debug_fp_stream = NULL;
static unsigned int g_debug_stream_cnt = 0;
#endif
static int SendOrigFrameToVencLib(VIDEOENCDATATYPE *pVideoEncData, VideoFrameInfoNode *pFrameNode);
static void VideoEncSendBackInputFrame(VIDEOENCDATATYPE *pVideoEncData, VIDEO_FRAME_INFO_S *pFrameInfo);
static void* ComponentThread(void* pThreadData);
static int VencCompEventHandler (
VideoEncoder* pEncoder,
void* pAppData,
VencEventType eEvent,
unsigned int nData1,
unsigned int nData2,
void* pEventData)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *)pAppData;
switch(eEvent)
{
case VencEvent_UpdateMbModeInfo:
{
alogv("VencEvent_UpdateMbModeInfo got !!!!!!!");
/**
* The encoding has just been completed, but the encoding of the next frame has not yet started.
* Before encoding, set the encoding method of the frame to be encoded.
* The user can modify the encoding parameters before setting.
*/
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf, pVideoEncData->pAppData,
COMP_EventQpMapUpdateMBModeInfo,
0,
0,
&pVideoEncData->mMBModeCtrl);
if ((0 == pVideoEncData->mMBModeCtrl.mode_ctrl_en) || (NULL == pVideoEncData->mMBModeCtrl.p_map_info))
{
aloge("fatal error! Venc ModeCtrl: mode_ctrl_en=%d, p_map_info=%p",
pVideoEncData->mMBModeCtrl.mode_ctrl_en, pVideoEncData->mMBModeCtrl.p_map_info);
}
if (pVideoEncData->mMBModeCtrl.mode_ctrl_en == 1)
{
/**
* Notice: Only for P-frame, I-frame is NOT support.
* The encoding library only sets the QPMAP parameter for the P-frame,
* if the current frame is an I-frame, the QPMAP setting is ignored.
*/
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamMBModeCtrl, &pVideoEncData->mMBModeCtrl);
}
break;
}
case VencEvent_UpdateMbStatInfo:
{
alogv("VencEvent_UpdateMbStatInfo got !!!!!!!");
/**
* The encoding has just been completed, but the encoding of the next frame has not yet started.
* and the QpMap information of the frame that has just been encoded is obtained.
* GetMbSumInfo(pContext->pVideoEnc, &pVideoEncData->mMbSumInfo);
*/
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamMBSumInfoOutput, &pVideoEncData->mMbSumInfo);
VencMBSumInfo *pMbSumInfo = &pVideoEncData->mMbSumInfo;
if ((0 == pMbSumInfo->avg_qp) || (NULL == pMbSumInfo->p_mb_mad_qp_sse) || (NULL == pMbSumInfo->p_mb_bin_img) || (NULL == pMbSumInfo->p_mb_mv))
{
aloge("fatal error! Venc MBSumInfo: avg_mad=%d, avg_sse=%d, avg_qp=%d, avg_psnr=%lf, "
"p_mb_mad_qp_sse=%p, p_mb_bin_img=%p, p_mb_mv=%p",
pMbSumInfo->avg_mad, pMbSumInfo->avg_sse, pMbSumInfo->avg_qp, pMbSumInfo->avg_psnr,
pMbSumInfo->p_mb_mad_qp_sse, pMbSumInfo->p_mb_bin_img, pMbSumInfo->p_mb_mv);
}
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf, pVideoEncData->pAppData,
COMP_EventQpMapUpdateMBStatInfo,
0,
0,
&pVideoEncData->mMbSumInfo);
break;
}
case VencEvent_UpdateIspToVeParam:
{
VencIsp2VeParam *pIsp2VeParam = (VencIsp2VeParam *)pEventData;
if (pIsp2VeParam && 0 == pVideoEncData->mbDisableIsp2Ve)
{
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf, pVideoEncData->pAppData,
COMP_EventLinkageIsp2VeParam,
0,
0,
(void*)pIsp2VeParam);
}
break;
}
case VencEvent_UpdateVeToIspParam:
{
VencVe2IspParam *pVe2IspParam = (VencVe2IspParam *)pEventData;
if (pVe2IspParam && 0 == pVideoEncData->mbDisableVe2Isp)
{
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf, pVideoEncData->pAppData,
COMP_EventLinkageVe2IspParam,
0,
0,
(void*)pVe2IspParam);
}
break;
}
case VencEvent_UpdateIspMotionParam:
{
// TODO
break;
}
default:
alogv("fatal error! unknown event[0x%x]", eEvent);
break;
}
return 0;
}
static int VencCompInputBufferDone (
VideoEncoder* pEncoder,
void* pAppData,
VencCbInputBufferDoneInfo* pBufferDoneInfo)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *)pAppData;
(void)pEncoder;
if ((NULL == pVideoEncData) || (NULL == pBufferDoneInfo))
{
aloge("fatal error! invalid input params, %p, %p", pVideoEncData, pBufferDoneInfo);
return -1;
}
alogv("VencChn[%d] CompInputBufferDone got !!!!!!! mFlagOutputStream=%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mFlagOutputStream);
pVideoEncData->mEncodeTotalCnt++;
if (VENC_RESULT_OK == pBufferDoneInfo->nResult)
{
pVideoEncData->mEncodeSuccessCount++;
}
if (0 == pVideoEncData->mOnlineEnableFlag)
{
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if (!list_empty(&pVideoEncData->mBufQ.mUsingFrameList))
{
VideoFrameInfoNode *pFrameNode = list_first_entry(&pVideoEncData->mBufQ.mUsingFrameList, VideoFrameInfoNode, mList);
VencInputBuffer *pInputBuffer = pBufferDoneInfo->pInputBuffer;
if (NULL == pInputBuffer)
{
aloge("fatal error! VencChn[%d] invalid input params, %p", pVideoEncData->mMppChnInfo.mChnId, pInputBuffer);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
return -1;
}
if (pInputBuffer->nID != pFrameNode->VFrame.mId)
{
aloge("fatal error! VencChn[%d] input buf ID is NOT match, nID: %d, mId: %d", pVideoEncData->mMppChnInfo.mChnId,
pInputBuffer->nID, pFrameNode->VFrame.mId);
}
// save the venc result
pFrameNode->mResult = pBufferDoneInfo->nResult;
alogv("VencChn[%d] inputBuffer ID[%d], venc lib result[%d]", pVideoEncData->mMppChnInfo.mChnId, pInputBuffer->nID, pBufferDoneInfo->nResult);
list_move_tail(&pFrameNode->mList, &pVideoEncData->mBufQ.mUsedFrameList);
//pVideoEncData->mOutputStreamFromVeTimeMs = GetSysTimeByUsec()/1000;
if (0 == pVideoEncData->mOutputStreamCnt)
{
alogv("VencChn[%d] offline first output stream", pVideoEncData->mMppChnInfo.mChnId);
}
pVideoEncData->mOutputStreamCnt++;
alogv("input orig frame ID[%d] list: Using -> Used", pFrameNode->VFrame.mId);
if(pVideoEncData->mbEnableMotionSearch)
{
if (!(pInputBuffer->nFlag & VENC_BUFFERFLAG_KEYFRAME))
{
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamMotionSearchResult, (void*)&pVideoEncData->mMotionResult);
}
}
if (pVideoEncData->mbEnableRegionD3D)
{
if (!(pInputBuffer->nFlag & VENC_BUFFERFLAG_KEYFRAME))
{
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamRegionD3DResult, (void*)&pVideoEncData->mRegionD3DResult);
}
}
if (FALSE == pVideoEncData->mbForbidDiscardingFrame)
{
if (pVideoEncData->mWaitInputFrameUsingEmptyFlag)
{
pthread_cond_signal(&pVideoEncData->mInputFrameUsingEmptyCondition);
alogd("VencChn[%d] send cond signal inputFrameUsingEmptyCondition", pVideoEncData->mMppChnInfo.mChnId);
}
}
}
else
{
aloge("fatal error! VencChn[%d] Almost impossible, why input using frame list is empty but got venc empty buf done cb, "
"please check code, nID: %d", pVideoEncData->mMppChnInfo.mChnId, pBufferDoneInfo->pInputBuffer->nID);
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
else
{
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if (list_empty(&pVideoEncData->mBufQ.mIdleFrameList))
{
if (VENC_RESULT_DROP_FRAME != pBufferDoneInfo->nResult)
{
alogv("VencChn[%d] idle frame is empty, malloc one! result[%d]", pVideoEncData->mMppChnInfo.mChnId, pBufferDoneInfo->nResult);
}
if (pVideoEncData->mBufQ.buf_unused!=0)
{
aloge("fatal error! VencChn[%d] buf_unused must be zero!", pVideoEncData->mMppChnInfo.mChnId);
}
VideoFrameInfoNode *pNode = (VideoFrameInfoNode*)malloc(sizeof(VideoFrameInfoNode));
if (NULL == pNode)
{
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
aloge("fatal error! VencChn[%d] malloc fail!", pVideoEncData->mMppChnInfo.mChnId);
return ERR_VENC_NOMEM;
}
list_add_tail(&pNode->mList, &pVideoEncData->mBufQ.mIdleFrameList);
pVideoEncData->mBufQ.buf_unused++;
}
VideoFrameInfoNode *pFrameNode = list_first_entry(&pVideoEncData->mBufQ.mIdleFrameList, VideoFrameInfoNode, mList);
pFrameNode->mResult = pBufferDoneInfo->nResult;
alogv("VencChn[%d] VFrame ID[%d], venc lib result[%d]", pVideoEncData->mMppChnInfo.mChnId, pFrameNode->VFrame.mId, pBufferDoneInfo->nResult);
pVideoEncData->mBufQ.buf_unused--;
list_move_tail(&pFrameNode->mList, &pVideoEncData->mBufQ.mUsedFrameList);
if (0 == pVideoEncData->mOutputStreamCnt)
{
pVideoEncData->mCapTimeLapse.lastTimeStamp = 0;
alogd("VencChn[%d] online first output stream, init lastTimeStamp=0", pVideoEncData->mMppChnInfo.mChnId);
}
pVideoEncData->mOutputStreamCnt++;
alogv("input orig frame ID[%d] list: Using -> Used", pFrameNode->VFrame.mId);
VencInputBuffer *pInputBuffer = pBufferDoneInfo->pInputBuffer;
if (NULL == pInputBuffer)
{
aloge("fatal error! VencChn[%d] invalid input params, %p", pVideoEncData->mMppChnInfo.mChnId, pInputBuffer);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
return -1;
}
if (pVideoEncData->mbEnableMotionSearch)
{
if (!(pInputBuffer->nFlag & VENC_BUFFERFLAG_KEYFRAME))
{
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamMotionSearchResult, (void*)&pVideoEncData->mMotionResult);
}
}
if (pVideoEncData->mbEnableRegionD3D)
{
if (!(pInputBuffer->nFlag & VENC_BUFFERFLAG_KEYFRAME))
{
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamRegionD3DResult, (void*)&pVideoEncData->mRegionD3DResult);
}
}
if (FALSE == pVideoEncData->mbForbidDiscardingFrame)
{
if (pVideoEncData->mWaitInputFrameUsingEmptyFlag)
{
pthread_cond_signal(&pVideoEncData->mInputFrameUsingEmptyCondition);
alogd("send cond signal inputFrameUsingEmptyCondition");
}
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
if (TRUE == pVideoEncData->mbForbidDiscardingFrame)
{
cdx_sem_up_unique(&pVideoEncData->mInputFrameBufDoneSem);
alogv("send sem inputFrameBufDoneSem");
}
else
{
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if (0 == pVideoEncData->mFlagOutputStream)
{
pVideoEncData->mFlagOutputStream = 1;
message_t msg;
msg.command = VEncComp_OutputStreamAvailable;
put_message(&pVideoEncData->cmd_queue, &msg);
alogv("VencChn[%d] send message VEncComp OutputStreamAvailable", pVideoEncData->mMppChnInfo.mChnId);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
return 0;
}
static int SoftFrameRateCtrlDestroy(SoftFrameRateCtrl *pThiz)
{
pThiz->enable = FALSE;
pThiz->mBasePts = -1;
pThiz->mCurrentWantedPts = -1;
pThiz->mFrameCounter = 0;
return 0;
}
static VIDEOENCBUFFERMANAGER *VideoEncBufferInit(void)
{
VIDEOENCBUFFERMANAGER *manager;
manager = (VIDEOENCBUFFERMANAGER*)malloc(sizeof(VIDEOENCBUFFERMANAGER));
if (NULL == manager)
{
aloge("Failed to alloc VIDEOENCBUFFERMANAGER(%s)", strerror(errno));
return NULL;
}
memset(manager, 0, sizeof(VIDEOENCBUFFERMANAGER));
manager->buffer = (unsigned char*)malloc(COMPRESSED_SRC_ENC_BUF_LEN * sizeof(unsigned char));
if (NULL == manager->buffer)
{
aloge("Failed to alloc buffer(%s)", strerror(errno));
free(manager);
return NULL;
}
pthread_mutex_init(&manager->lock ,NULL);
return manager;
}
static void VideoEncBufferDeInit(VIDEOENCBUFFERMANAGER *manager)
{
if (NULL == manager)
{
return;
}
pthread_mutex_destroy(&manager->lock);
free(manager->buffer);
free(manager);
}
static ERRORTYPE VideoEncBufferPushFrame(VIDEOENCBUFFERMANAGER *manager, FRAMEDATATYPE *frame)
{
ERRORTYPE eError = SUCCESS;
unsigned int length;
unsigned int flag = FRAME_BEGIN_FLAG;
unsigned char *ptr, *ptr_ori;
if (manager == NULL)
{
aloge("Buffer manager is NULL!");
return ERR_VENC_NULL_PTR;
}
length = frame->info.size + sizeof(FRAMEINFOTYPE) + sizeof(unsigned int);
pthread_mutex_lock(&manager->lock);
if (manager->writePos > manager->readPos)
{
if (manager->writePos + length <= COMPRESSED_SRC_ENC_BUF_LEN)
{
ptr_ori = ptr = manager->buffer + manager->writePos;
memcpy(ptr, &flag, sizeof(unsigned int));
ptr += sizeof(unsigned int);
memcpy(ptr, &frame->info, sizeof(FRAMEINFOTYPE));
ptr += sizeof(FRAMEINFOTYPE);
memcpy(ptr, (void*)frame->addrY, frame->info.size);
ptr += frame->info.size;
manager->writePos += (ptr - ptr_ori);
manager->count++;
manager->mUnprefetchFrameNum++;
if (manager->writePos + sizeof(unsigned int) <= COMPRESSED_SRC_ENC_BUF_LEN)
{
memset(ptr, 0, sizeof(unsigned int));
}
}
else
{
if (length <= manager->readPos)
{
ptr_ori = ptr = manager->buffer;
memcpy(ptr, &flag, sizeof(unsigned int));
ptr += sizeof(unsigned int);
memcpy(ptr, &frame->info, sizeof(FRAMEINFOTYPE));
ptr += sizeof(FRAMEINFOTYPE);
memcpy(ptr, (void*)frame->addrY, frame->info.size);
ptr += frame->info.size;
manager->writePos = (ptr - ptr_ori);
manager->count++;
manager->mUnprefetchFrameNum++;
}
else
{
alogw("Buffer full, %d frames, writePos=%d, readPos=%d, frame_size=%d!",
manager->count, manager->writePos, manager->readPos, frame->info.size);
eError = ERR_VENC_BUF_FULL;
}
}
}
else if (manager->writePos < manager->readPos)
{
if (manager->readPos - manager->writePos >= length)
{
ptr_ori = ptr = manager->buffer + manager->writePos;
memcpy(ptr, &flag, sizeof(unsigned int));
ptr += sizeof(unsigned int);
memcpy(ptr, &frame->info, sizeof(FRAMEINFOTYPE));
ptr += sizeof(FRAMEINFOTYPE);
memcpy(ptr, (void*)frame->addrY, frame->info.size);
ptr += frame->info.size;
manager->writePos += (ptr - ptr_ori);
manager->count++;
manager->mUnprefetchFrameNum++;
}
else
{
alogw("Buffer full, %d frames, writePos=%d, readPos=%d, frame_size=%d!",
manager->count, manager->writePos, manager->readPos, frame->info.size);
eError = ERR_VENC_BUF_FULL;
}
}
else
{
if (manager->count == 0)
{
if(manager->mUnprefetchFrameNum != 0)
{
aloge("fatal error! unprefetchNum[%d]!=0", manager->mUnprefetchFrameNum);
}
manager->readPos = manager->prefetchPos = 0;
ptr_ori = ptr = manager->buffer;
memcpy(ptr, &flag, sizeof(unsigned int));
ptr += sizeof(unsigned int);
memcpy(ptr, &frame->info, sizeof(FRAMEINFOTYPE));
ptr += sizeof(FRAMEINFOTYPE);
memcpy(ptr, (void*)frame->addrY, frame->info.size);
ptr += frame->info.size;
manager->writePos = (ptr - ptr_ori);
manager->count++;
manager->mUnprefetchFrameNum++;
}
else
{
alogw("Buffer full, %d frames, writePos=%d, readPos=%d, frame_size=%d!",
manager->count, manager->writePos, manager->readPos, frame->info.size);
eError = ERR_VENC_BUF_FULL;
}
}
pthread_mutex_unlock(&manager->lock);
return eError;
}
static ERRORTYPE VideoEncBufferGetFrame(VIDEOENCBUFFERMANAGER *manager, FRAMEDATATYPE *frame)
{
ERRORTYPE eError = SUCCESS;
if (manager == NULL)
{
aloge("Buffer manager is NULL!");
return ERR_VENC_ILLEGAL_PARAM;
}
pthread_mutex_lock(&manager->lock);
if (manager->mUnprefetchFrameNum > 0)
{
unsigned int flag;
unsigned char *ptr;
if (manager->prefetchPos + sizeof(unsigned int) < COMPRESSED_SRC_ENC_BUF_LEN)
{
memcpy(&flag, manager->buffer+manager->prefetchPos, sizeof(unsigned int));
if (flag == FRAME_BEGIN_FLAG)
{
ptr = manager->buffer + manager->prefetchPos;
}
else
{
ptr = manager->buffer;
}
}
else
{
ptr = manager->buffer;
}
ptr += sizeof(unsigned int);
memcpy(&frame->info, ptr, sizeof(FRAMEINFOTYPE));
ptr += sizeof(FRAMEINFOTYPE);
frame->addrY = (char*)ptr;
manager->mUnprefetchFrameNum--;
ptr += frame->info.size;
manager->prefetchPos = ptr - manager->buffer;
}
else
{
//alogw("Buffer empty!");
eError = ERR_VENC_BUF_EMPTY;
}
pthread_mutex_unlock(&manager->lock);
return eError;
}
static ERRORTYPE VideoEncBufferReleaseFrame(VIDEOENCBUFFERMANAGER *manager, FRAMEDATATYPE *releaseFrame)
{
FRAMEDATATYPE frame;
ERRORTYPE eError = SUCCESS;
if (manager == NULL)
{
aloge("Buffer manager is NULL!");
return ERR_VENC_ILLEGAL_PARAM;
}
pthread_mutex_lock(&manager->lock);
if (manager->count > 0)
{
unsigned int flag;
if (manager->readPos + sizeof(unsigned int) < COMPRESSED_SRC_ENC_BUF_LEN)
{
memcpy(&flag, manager->buffer+manager->readPos, sizeof(unsigned int));
if (flag != FRAME_BEGIN_FLAG)
{
manager->readPos = 0;
memcpy(&flag, manager->buffer+manager->readPos, sizeof(unsigned int));
}
}
else
{
manager->readPos = 0;
memcpy(&flag, manager->buffer+manager->readPos, sizeof(unsigned int));
}
if(flag != FRAME_BEGIN_FLAG)
{
aloge("fatal error! data header flag[0x%x] wrong", flag);
}
manager->readPos += sizeof(unsigned int);
memcpy(&frame.info, manager->buffer + manager->readPos, sizeof(FRAMEINFOTYPE));
frame.addrY = (char*)manager->buffer + manager->readPos + sizeof(FRAMEINFOTYPE);
if(releaseFrame->addrY!=frame.addrY
|| releaseFrame->info.timeStamp!=frame.info.timeStamp
|| releaseFrame->info.bufferId!=frame.info.bufferId
|| releaseFrame->info.size!=frame.info.size)
{
aloge("fatal error! frame not match!addrY[%p]timeStamp[%lld]bufferId[%d]size[%d]!=[%p][%lld][%d][%d]",
releaseFrame->addrY, releaseFrame->info.timeStamp, releaseFrame->info.bufferId, releaseFrame->info.size,
frame.addrY, frame.info.timeStamp, frame.info.bufferId, frame.info.size);
}
manager->readPos += sizeof(FRAMEINFOTYPE) + frame.info.size;
manager->count--;
}
else
{
//alogw("Buffer empty!");
aloge("fatal error! count==0, check code!");
eError = ERR_VENC_BUF_EMPTY;
}
pthread_mutex_unlock(&manager->lock);
return eError;
}
static ERRORTYPE configVencSuperFrameConfigByVENC_SUPERFRAME_CFG_S(VencSuperFrameConfig *pDst, VENC_SUPERFRAME_CFG_S* pSrc)
{
memset(pDst, 0, sizeof(VencSuperFrameConfig));
switch(pSrc->enSuperFrmMode)
{
case SUPERFRM_NONE:
pDst->eSuperFrameMode = VENC_SUPERFRAME_NONE;
break;
case SUPERFRM_DISCARD:
pDst->eSuperFrameMode = VENC_SUPERFRAME_DISCARD;
break;
case SUPERFRM_REENCODE:
pDst->eSuperFrameMode = VENC_SUPERFRAME_REENCODE;
break;
default:
aloge("fatal error! wrong superFrmMode[0x%x]", pSrc->enSuperFrmMode);
pDst->eSuperFrameMode = VENC_SUPERFRAME_NONE;
break;
}
pDst->nMaxIFrameBits = pSrc->SuperIFrmBitsThr;
pDst->nMaxPFrameBits = pSrc->SuperPFrmBitsThr;
pDst->nMaxRencodeTimes = pSrc->MaxRencodeTimes;
pDst->nMaxP2IFrameBitsRatio = pSrc->MaxP2IFrameBitsRatio;
return SUCCESS;
}
/*******************************************************************************
Function name: estimateBitRate
Description:
only estimate fixqp mode bitRate
Parameters:
Return:
Kbit/s
Time: 2017/6/15
*******************************************************************************/
static int estimateBitRate(VENC_CHN_ATTR_S *pVEncChnAttr)
{
int bitRateKb = 24*1024*1024 >> 10;
if(VENC_RC_MODE_H264FIXQP == pVEncChnAttr->RcAttr.mRcMode)
{
int nArea = pVEncChnAttr->VeAttr.AttrH264e.PicWidth * pVEncChnAttr->VeAttr.AttrH264e.PicHeight;
if(nArea >= 3840*2160)
{
bitRateKb = 20*1024;
}
else if(nArea >= 1920*1080)
{
bitRateKb = 12*1024;
}
else if(nArea >= 1280*720)
{
bitRateKb = 8*1024;
}
else
{
bitRateKb = 4*1024;
}
}
else if(VENC_RC_MODE_H265FIXQP == pVEncChnAttr->RcAttr.mRcMode)
{
int nArea = pVEncChnAttr->VeAttr.AttrH265e.mPicWidth * pVEncChnAttr->VeAttr.AttrH265e.mPicHeight;
if(nArea >= 3840*2160)
{
bitRateKb = 10*1024;
}
else if(nArea >= 1920*1080)
{
bitRateKb = 6*1024;
}
else if(nArea >= 1280*720)
{
bitRateKb = 4*1024;
}
else
{
bitRateKb = 2*1024;
}
}
else if(VENC_RC_MODE_MJPEGFIXQP == pVEncChnAttr->RcAttr.mRcMode)
{
int nArea = pVEncChnAttr->VeAttr.AttrMjpeg.mPicWidth * pVEncChnAttr->VeAttr.AttrMjpeg.mPicHeight;
if(nArea >= 3840*2160)
{
bitRateKb = 40*1024;
}
else if(nArea >= 1920*1080)
{
bitRateKb = 24*1024;
}
else if(nArea >= 1280*720)
{
bitRateKb = 16*1024;
}
else
{
bitRateKb = 8*1024;
}
}
else
{
aloge("fatal error! unsupport rc mode[0x%x], use default[%d]Kbit/s", pVEncChnAttr->RcAttr.mRcMode, bitRateKb);
}
return bitRateKb;
}
static int setVbvBufferConfig(VideoEncoder *pCedarV, VIDEOENCDATATYPE *pVideoEncData)
{
#define VEValidSizeScope (0xfff0000/8)
int bitRateKb;
int nCacheSize;
int vbvSize;
int nMinSize;
int nThreshSize;
int nUsrStreamBufSize = 0;
int nUsrThreshSize = 0;
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
nMinSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicWidth*pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicHeight*3/2;
nThreshSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicWidth*pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicHeight;
nUsrStreamBufSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.BufSize;
nUsrThreshSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.mThreshSize;
}
else if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
nMinSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mPicWidth*pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mPicHeight*3/2;
nThreshSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mPicWidth*pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mPicHeight;
nUsrStreamBufSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mBufSize;
nUsrThreshSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mThreshSize;
}
else if(PT_MJPEG == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
nMinSize = pVideoEncData->mEncChnAttr.VeAttr.AttrMjpeg.mPicWidth*pVideoEncData->mEncChnAttr.VeAttr.AttrMjpeg.mPicHeight*3/2;
nThreshSize = pVideoEncData->mEncChnAttr.VeAttr.AttrMjpeg.mPicWidth*pVideoEncData->mEncChnAttr.VeAttr.AttrMjpeg.mPicHeight;
nUsrStreamBufSize = pVideoEncData->mEncChnAttr.VeAttr.AttrMjpeg.mBufSize;
nUsrThreshSize = pVideoEncData->mEncChnAttr.VeAttr.AttrMjpeg.mThreshSize;
}
else
{
alogw("unsupported venc type:0x%x, calculate minSize!", pVideoEncData->mEncChnAttr.VeAttr.Type);
nMinSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicWidth*pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicHeight*3/2;
nThreshSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicWidth*pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicHeight;
nUsrStreamBufSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.BufSize;
nUsrThreshSize = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.mThreshSize;
}
if(nThreshSize > 7*1024*1024)
{
alogw("Be careful! threshSize[%d]bytes too large, reduce to 7MB", nThreshSize);
nThreshSize = 7*1024*1024;
}
double nBufferSeconds = 4; //unit:s.
//int ret;
if (pVideoEncData->mVbvBufTime > 0)
{
nBufferSeconds = pVideoEncData->mVbvBufTime;
alogd("set vbv buffer to %lfs", nBufferSeconds);
}
unsigned int nBitRate;
nBitRate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
if(nBitRate > 0)
{
bitRateKb = nBitRate>>10;
}
else
{
alogd("bitRate=0, maybe rc mode[0x%x] is fixqp", pVideoEncData->mEncChnAttr.RcAttr.mRcMode);
bitRateKb = estimateBitRate(&pVideoEncData->mEncChnAttr);
}
nCacheSize = (bitRateKb*nBufferSeconds)*(1024/8);
vbvSize = nCacheSize + nThreshSize;
if (vbvSize < nMinSize)
{
vbvSize = nMinSize;
}
if(nUsrStreamBufSize > 0)
{
alogd("user set stream buffer size[%d]bytes", nUsrStreamBufSize);
vbvSize = nUsrStreamBufSize;
}
if(vbvSize%1024 != 0)
{
vbvSize = AWALIGN(vbvSize, 1024);
}
if(nUsrThreshSize > 0)
{
alogd("user set threshSize[%d]bytes", nUsrThreshSize);
nThreshSize = nUsrThreshSize;
}
#if (AWCHIP == AW_V5)
if(vbvSize + nThreshSize > VEValidSizeScope)
{
alogw("Be careful! vbvSize[%d] + threshSize[%d] > [%d]", vbvSize, nThreshSize, VEValidSizeScope);
vbvSize = VEValidSizeScope - nThreshSize;
if(vbvSize%1024 != 0)
{
vbvSize = (vbvSize/1024)*1024;
}
alogw("Be careful! decrease vbvSize to [%d]", vbvSize);
}
#elif (AWCHIP == AW_V316)
#else
#endif
if(vbvSize <= nThreshSize)
{
aloge("fatal error! vbvSize[%d] <= nThreshSize[%d]", vbvSize, nThreshSize);
}
// if (vbvSize > 24*1024*1024)
// {
// alogw("Be careful! vbvSize[%d] too large, exceed 24M byte", vbvSize);
// vbvSize = 24*1024*1024;
// }
alogd("bit rate is %dKb, set encode vbv size %d, frame length threshold %d", bitRateKb, vbvSize, nThreshSize);
VencSetParameter(pCedarV, VENC_IndexParamSetVbvSize, &vbvSize);
VencSetParameter(pCedarV, VENC_IndexParamSetFrameLenThreshold, &nThreshSize);
return 0;
}
/**
* VENC_ATTR_H264_S.mProfile : 0: baseline; 1:MP; 2:HP; 3: SVC-T [0,3];
* VENC_H264PROFILETYPE:
*
*/
VENC_H264PROFILETYPE map_VENC_ATTR_H264_S_Profile_to_VENC_H264PROFILETYPE(unsigned int nProfile)
{
VENC_H264PROFILETYPE vencProfileType = VENC_H264ProfileMain;
switch(nProfile)
{
case 0:
vencProfileType = VENC_H264ProfileBaseline;
break;
case 1:
vencProfileType = VENC_H264ProfileMain;
break;
case 2:
vencProfileType = VENC_H264ProfileHigh;
break;
case 3:
aloge("fatal error! not support SVC-T!");
break;
default:
aloge("fatal error! unknown h264 profile");
break;
}
return vencProfileType;
}
VENC_H264LEVELTYPE map_H264_LEVEL_E_to_VENC_H264LEVELTYPE(H264_LEVEL_E nLevel)
{
VENC_H264LEVELTYPE nVencLevel;
switch(nLevel)
{
case H264_LEVEL_1:
nVencLevel = VENC_H264Level1;
break;
case H264_LEVEL_11:
nVencLevel = VENC_H264Level11;
break;
case H264_LEVEL_12:
nVencLevel = VENC_H264Level12;
break;
case H264_LEVEL_13:
nVencLevel = VENC_H264Level13;
break;
case H264_LEVEL_2:
nVencLevel = VENC_H264Level2;
break;
case H264_LEVEL_21:
nVencLevel = VENC_H264Level21;
break;
case H264_LEVEL_22:
nVencLevel = VENC_H264Level22;
break;
case H264_LEVEL_3:
nVencLevel = VENC_H264Level3;
break;
case H264_LEVEL_31:
nVencLevel = VENC_H264Level31;
break;
case H264_LEVEL_32:
nVencLevel = VENC_H264Level32;
break;
case H264_LEVEL_4:
nVencLevel = VENC_H264Level4;
break;
case H264_LEVEL_41:
nVencLevel = VENC_H264Level41;
break;
case H264_LEVEL_42:
nVencLevel = VENC_H264Level42;
break;
case H264_LEVEL_5:
nVencLevel = VENC_H264Level5;
break;
case H264_LEVEL_51:
nVencLevel = VENC_H264Level51;
break;
case H264_LEVEL_52:
nVencLevel = VENC_H264Level52;
break;
default:
nVencLevel = VENC_H264LevelDefault;
break;
}
return nVencLevel;
}
VENC_H265PROFILETYPE map_VENC_ATTR_H265_S_Profile_to_VENC_H265PROFILETYPE(unsigned int nProfile)
{
VENC_H265PROFILETYPE vencProfileType = VENC_H265ProfileMain;
switch(nProfile)
{
case 0:
vencProfileType = VENC_H265ProfileMain;
break;
case 1:
vencProfileType = VENC_H265ProfileMain10;
break;
case 2:
vencProfileType = VENC_H265ProfileMainStill;
break;
default:
aloge("fatal error! unknown h265 profile");
break;
}
return vencProfileType;
}
VENC_H265LEVELTYPE map_H265_LEVEL_E_to_VENC_H265LEVELTYPE(H265_LEVEL_E nLevel)
{
VENC_H265LEVELTYPE nVencLevel;
switch(nLevel)
{
case H265_LEVEL_1:
nVencLevel = VENC_H265Level1;
break;
case H265_LEVEL_2:
nVencLevel = VENC_H265Level2;
break;
case H265_LEVEL_21:
nVencLevel = VENC_H265Level21;
break;
case H265_LEVEL_3:
nVencLevel = VENC_H265Level3;
break;
case H265_LEVEL_31:
nVencLevel = VENC_H265Level31;
break;
case H265_LEVEL_4:
nVencLevel = VENC_H265Level4;
break;
case H265_LEVEL_41:
nVencLevel = VENC_H265Level41;
break;
case H265_LEVEL_5:
nVencLevel = VENC_H265Level5;
break;
case H265_LEVEL_51:
nVencLevel = VENC_H265Level51;
break;
case H265_LEVEL_52:
nVencLevel = VENC_H265Level52;
break;
case H265_LEVEL_6:
nVencLevel = VENC_H265Level6;
break;
case H265_LEVEL_61:
nVencLevel = VENC_H265Level61;
break;
case H265_LEVEL_62:
nVencLevel = VENC_H265Level62;
break;
default:
nVencLevel = VENC_H265LevelDefault;
break;
}
return nVencLevel;
}
static inline int map_ROTATE_E_to_VENC_Rotate_Angle(ROTATE_E rotate)
{
int angle = 0;
switch(rotate)
{
case ROTATE_NONE:
angle = 0;
break;
case ROTATE_90:
angle = 90;
break;
case ROTATE_180:
angle = 180;
break;
case ROTATE_270:
angle = 270;
break;
case ROTATE_BUTT:
default:
aloge("fatal error! unsupported roate angle!");
break;
}
return angle;
}
static VENC_COLOR_SPACE map_v4l2_colorspace_to_VENC_COLOR_SPACE(enum v4l2_colorspace eV4l2Csc)
{
VENC_COLOR_SPACE eVencCsc;
switch((int)eV4l2Csc)
{
case V4L2_COLORSPACE_JPEG:
eVencCsc = VENC_YCC;
break;
case V4L2_COLORSPACE_REC709:
case V4L2_COLORSPACE_REC709_PART_RANGE:
eVencCsc = VENC_BT709;
break;
default:
aloge("fatal error! unsupported v4l2 color space[0x%x]!", eV4l2Csc);
eVencCsc = VENC_YCC;
break;
}
return eVencCsc;
}
static int checkColorSpaceFullRange(int nColorSpace) //enum v4l2_colorspace or enum user_v4l2_colorspace
{
int nFullRangeFlag = 0;
switch(nColorSpace)
{
case V4L2_COLORSPACE_JPEG:
case V4L2_COLORSPACE_REC709:
{
nFullRangeFlag = 1;
break;
}
case V4L2_COLORSPACE_REC709_PART_RANGE:
{
nFullRangeFlag = 0;
break;
}
default:
{
aloge("fatal error! unsupported v4l2 color space[0x%x]!", nColorSpace);
nFullRangeFlag = 1;
break;
}
}
return nFullRangeFlag;
}
static eVeLbcMode map_VENC_REF_FRAME_LBC_MODE_E_to_VeRecRefLbcMode(VENC_REF_FRAME_LBC_MODE_E VeRefFrameLbcMode)
{
eVeLbcMode rec_lbc_mode = LBC_MODE_DISABLE;
switch (VeRefFrameLbcMode)
{
case VENC_REF_FRAME_LBC_MODE_2_0X:
{
rec_lbc_mode = LBC_MODE_2_0X;
break;
}
case VENC_REF_FRAME_LBC_MODE_2_5X:
{
rec_lbc_mode = LBC_MODE_2_5X;
break;
}
case VENC_REF_FRAME_LBC_MODE_NO_LOSSY:
{
rec_lbc_mode = LBC_MODE_NO_LOSSY;
break;
}
case VENC_REF_FRAME_LBC_MODE_DEFAULT:
case VENC_REF_FRAME_LBC_MODE_1_5X:
default:
{
rec_lbc_mode = LBC_MODE_1_5X;
break;
}
}
return rec_lbc_mode;
}
static int CedarvEncInit(VIDEOENCDATATYPE *pVideoEncData)
{
int ret = 0;
VideoEncoder *pCedarV = NULL;
MediaDebugLoadMppVencParams(pVideoEncData, NULL);
alogv("VencChn[%d] Create VeType=%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
if(PT_JPEG == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
pCedarV = VencCreate(VENC_CODEC_JPEG);
}
else if(PT_MJPEG == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
pCedarV = VencCreate(VENC_CODEC_JPEG);
}
else if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
pCedarV = VencCreate(VENC_CODEC_H264);
}
else if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
pCedarV = VencCreate(VENC_CODEC_H265);
}
else
{
aloge("fatal error! unknown venc type:0x%x", pVideoEncData->mEncChnAttr.VeAttr.Type);
ret = ERR_VENC_ILLEGAL_PARAM;
}
//pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
pVideoEncData->mbCedarvVideoEncInitFlag = FALSE;
//pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
pVideoEncData->pCedarV = pCedarV;
if(pVideoEncData->pCedarV)
{
/* init default param base on ProductMode */
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
SIZE_S PicSize;
GetEncodeDstSizeFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr, &PicSize);
int nBitRate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
if (PRODUCT_NUM <= pVideoEncData->mEncChnAttr.RcAttr.mProductMode ||
0 == nBitRate || 0 == pVideoEncData->mFrameRateInfo.DstFrmRate ||
0 == PicSize.Width || 0 == PicSize.Height)
{
alogw("fatal error! VencChn[%d] invalid params, product_mode=%d, bitrate=%d, dst_fps=%d, dst_wxh=%dx%d",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.RcAttr.mProductMode, nBitRate,
pVideoEncData->mFrameRateInfo.DstFrmRate, PicSize.Width, PicSize.Height);
return ERR_VENC_ILLEGAL_PARAM;
}
VencProductModeInfo ProductInfo;
memset(&ProductInfo, 0, sizeof(VencProductModeInfo));
ProductInfo.eProductMode = pVideoEncData->mEncChnAttr.RcAttr.mProductMode;
ProductInfo.nBitrate = nBitRate;
ProductInfo.nFrameRate = pVideoEncData->mFrameRateInfo.DstFrmRate;
ProductInfo.nDstWidth = PicSize.Width;
ProductInfo.nDstHeight = PicSize.Height;
int ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamProductCase, (void*)&ProductInfo);
if (ret)
{
aloge("fatal error! VencChn[%d] set ProductCase failed, ret=%d", pVideoEncData->mMppChnInfo.mChnId, ret);
}
}
}
return ret;
}
static int getMostSuitabeleGopSize(int GopSize, int MaxKeyInterval)
{
int i = 0;
int nTemp = 0;
int nGopSize = GopSize;
int nMaxKeyInterval = MaxKeyInterval;
if (0 == nGopSize)
{
nGopSize = nMaxKeyInterval;
}
if (nGopSize > 64)
{
if (nMaxKeyInterval >= 1 && nMaxKeyInterval <= 64)
{
nGopSize = nMaxKeyInterval;
}
else
{
i = 1;
while (1)
{
nTemp = nMaxKeyInterval/i;
if (nTemp <= 64)
{
break;
}
i++;
}
nGopSize = nMaxKeyInterval/i;
}
alogd("user set invalid gopSize[%d], use most suitable gopsize[%d].", GopSize, nGopSize);
}
return nGopSize;
}
static ERRORTYPE change_VENC_CHN_ATTR_BitRate(VENC_CHN_ATTR_S *pCurAttr, VENC_CHN_ATTR_S *pChnAttr)
{
ERRORTYPE eRet = SUCCESS;
if (pChnAttr->RcAttr.mRcMode == pCurAttr->RcAttr.mRcMode)
{
switch (pChnAttr->RcAttr.mRcMode)
{
case VENC_RC_MODE_H264CBR:
pCurAttr->RcAttr.mAttrH264Cbr.mBitRate = pChnAttr->RcAttr.mAttrH264Cbr.mBitRate;
break;
case VENC_RC_MODE_H264VBR:
pCurAttr->RcAttr.mAttrH264Vbr.mMaxBitRate = pChnAttr->RcAttr.mAttrH264Vbr.mMaxBitRate;
break;
case VENC_RC_MODE_H264FIXQP:
break;
case VENC_RC_MODE_H264ABR:
pCurAttr->RcAttr.mAttrH264Abr.mMaxBitRate = pChnAttr->RcAttr.mAttrH264Abr.mMaxBitRate;
break;
case VENC_RC_MODE_H265CBR:
pCurAttr->RcAttr.mAttrH265Cbr.mBitRate = pChnAttr->RcAttr.mAttrH265Cbr.mBitRate;
break;
case VENC_RC_MODE_H265VBR:
pCurAttr->RcAttr.mAttrH265Vbr.mMaxBitRate = pChnAttr->RcAttr.mAttrH265Vbr.mMaxBitRate;
break;
case VENC_RC_MODE_H265FIXQP:
break;
case VENC_RC_MODE_H265ABR:
pCurAttr->RcAttr.mAttrH265Abr.mMaxBitRate = pChnAttr->RcAttr.mAttrH265Abr.mMaxBitRate;
break;
case VENC_RC_MODE_MJPEGCBR:
pCurAttr->RcAttr.mAttrMjpegeCbr.mBitRate = pChnAttr->RcAttr.mAttrMjpegeCbr.mBitRate;;
break;
case VENC_RC_MODE_MJPEGFIXQP:
break;
default:
eRet = FAILURE;
alogw("unsupported temporary: chn attr RcAttr RcMode[0x%x]", pChnAttr->RcAttr.mRcMode);
break;
}
}
else
{
eRet = FAILURE;
}
return eRet;
}
static void VideoEncMBInfoInit(VencMBInfo *pMBInfo, VENC_CHN_ATTR_S *pChnAttr)
{
unsigned int mb_num = 0;
if ((NULL == pMBInfo) || (NULL == pChnAttr))
{
aloge("fatal error! invalid input params! %p,%p", pMBInfo, pChnAttr);
return;
}
#if (AWCHIP == AW_V853)
// calc mb num
if (PT_H264 == pChnAttr->VeAttr.Type)
{
unsigned int pic_mb_width = AWALIGN(pChnAttr->VeAttr.AttrH264e.PicWidth, 16) >> 4;
unsigned int pic_mb_height = AWALIGN(pChnAttr->VeAttr.AttrH264e.PicHeight, 16) >> 4;
unsigned int total_mb_num = pic_mb_width * pic_mb_height;
pMBInfo->num_mb = total_mb_num;
}
else if (PT_H265 == pChnAttr->VeAttr.Type)
{
unsigned int pic_mb_width = AWALIGN(pChnAttr->VeAttr.AttrH265e.mPicWidth, 16) >> 4;
unsigned int pic_mb_height = AWALIGN(pChnAttr->VeAttr.AttrH265e.mPicHeight, 16) >> 4;
unsigned int total_mb_num = pic_mb_width * pic_mb_height;
pMBInfo->num_mb = total_mb_num;
}
else
{
aloge("fatal error! Unexpected venc type:0x%x, QPMAP only for H264/H265!", pChnAttr->VeAttr.Type);
return;
}
#else
// calc mb num
if (PT_H264 == pChnAttr->VeAttr.Type)
{
unsigned int pic_mb_width = AWALIGN(pChnAttr->VeAttr.AttrH264e.PicWidth, 16) >> 4;
unsigned int pic_mb_height = AWALIGN(pChnAttr->VeAttr.AttrH264e.PicHeight, 16) >> 4;
unsigned int total_mb_num = pic_mb_width * pic_mb_height;
pMBInfo->num_mb = total_mb_num;
}
else if (PT_H265 == pChnAttr->VeAttr.Type)
{
unsigned int pic_4ctu_width = AWALIGN(pChnAttr->VeAttr.AttrH265e.mPicWidth, 128) >> 5;
unsigned int pic_ctu_height = AWALIGN(pChnAttr->VeAttr.AttrH265e.mPicHeight, 32) >> 5;
unsigned int total_ctu_num = pic_4ctu_width * pic_ctu_height;
pMBInfo->num_mb = total_ctu_num;
}
else
{
aloge("fatal error! Unexpected venc type:0x%x, QPMAP only for H264/H265!", pChnAttr->VeAttr.Type);
return;
}
#endif
mb_num = pMBInfo->num_mb;
// malloc mb info p_para
if (NULL == pMBInfo->p_para)
{
pMBInfo->p_para = (VencMBInfoPara *)malloc(sizeof(VencMBInfoPara) * mb_num);
if (NULL == pMBInfo->p_para)
{
aloge("fatal error! malloc pMBInfo->p_para fail! size=%d", sizeof(VencMBInfoPara) * mb_num);
return;
}
}
else
{
alogw("init mb info repeated? pMBInfo->p_para is not NULL!");
}
memset(pMBInfo->p_para, 0, sizeof(VencMBInfoPara) * mb_num);
alogd("mb_num=%d, pMBInfo->p_para=%p", mb_num, pMBInfo->p_para);
}
static void VideoEncMBInfoDeinit(VencMBInfo *pMBInfo)
{
if (NULL == pMBInfo)
{
aloge("fatal error! invalid input params!");
return;
}
if (pMBInfo->p_para)
{
free(pMBInfo->p_para);
pMBInfo->p_para = NULL;
}
pMBInfo->num_mb = 0;
}
static int checkIsVencScalerReduce(VENC_CHN_ATTR_S *pChnAttr, VENC_CROP_CFG_S *pCrop)
{
unsigned int SrcWidth = pChnAttr->VeAttr.SrcPicWidth;
unsigned int SrcHeight= pChnAttr->VeAttr.SrcPicHeight;
unsigned int DstWidth = 0;
unsigned int DstHeight = 0;
if(pCrop!=NULL && pCrop->bEnable)
{
SrcWidth = pCrop->Rect.Width;
SrcHeight = pCrop->Rect.Height;
}
if (PT_JPEG == pChnAttr->VeAttr.Type)
{
DstWidth = pChnAttr->VeAttr.AttrJpeg.PicWidth;
DstHeight = pChnAttr->VeAttr.AttrJpeg.PicHeight;
}
else if (PT_MJPEG == pChnAttr->VeAttr.Type)
{
DstWidth = pChnAttr->VeAttr.AttrMjpeg.mPicWidth;
DstHeight = pChnAttr->VeAttr.AttrMjpeg.mPicHeight;
}
else if (PT_H264 == pChnAttr->VeAttr.Type)
{
DstWidth = pChnAttr->VeAttr.AttrH264e.PicWidth;
DstHeight = pChnAttr->VeAttr.AttrH264e.PicHeight;
}
else if (PT_H265 == pChnAttr->VeAttr.Type)
{
DstWidth = pChnAttr->VeAttr.AttrH265e.mPicWidth;
DstHeight = pChnAttr->VeAttr.AttrH265e.mPicHeight;
}
else
{
aloge("fatal error! unknown venc type:0x%x", pChnAttr->VeAttr.Type);
}
alogv("Src Width:%d, Height:%d, Dst Width:%d, Height:%d", SrcWidth, SrcHeight, DstWidth, DstHeight);
DstWidth = AWALIGN(DstWidth, 16);
DstHeight = AWALIGN(DstHeight, 16);
if (SrcWidth > DstWidth || SrcHeight > DstHeight)
return 1;
else
return 0;
}
static VencCbType gVencCompCbType = {
.EventHandler = VencCompEventHandler,
.InputBufferDone = VencCompInputBufferDone,
};
static int CedarvVideoEncInit(VIDEOENCDATATYPE *pVideoEncData)
{
int ret = SUCCESS;
if(pVideoEncData->pCedarV)
{
alogv("vencChn[%d] type[%d] init", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
int IsScalerReduce = checkIsVencScalerReduce(&pVideoEncData->mEncChnAttr, &pVideoEncData->mCropCfg);
if (IsScalerReduce && pVideoEncData->mEncChnAttr.EncppAttr.mbEncppEnable)
{
aloge("fatal error! veChn[%d] vencType[%d] Exception Case: ScalerReduce[%d] and Encpp enable[%d] can not be used at the same time.",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type, IsScalerReduce, pVideoEncData->mEncChnAttr.EncppAttr.mbEncppEnable);
pVideoEncData->mbExceptionCase = TRUE;
return ERR_VENC_ILLEGAL_PARAM;
}
if ((IsScalerReduce || pVideoEncData->mCropCfg.bEnable) && VENC_PIXEL_LBC_AW
== map_PIXEL_FORMAT_E_to_VENC_PIXEL_FMT(pVideoEncData->mEncChnAttr.VeAttr.PixelFormat))
{
aloge("fatal error! Exception Case: (ScalerReduce[%d] or crop[%d]) and LBC Pix can not be used at the same time.",
IsScalerReduce, pVideoEncData->mCropCfg.bEnable);
pVideoEncData->mbExceptionCase = TRUE;
return ERR_VENC_ILLEGAL_PARAM;
}
if (pVideoEncData->mEncChnAttr.VeAttr.mVeRecRefBufReduceEnable && SUPERFRM_REENCODE == pVideoEncData->mSuperFrmParam.enSuperFrmMode)
{
aloge("fatal error! Exception Case: VeRecRefBufReduce enable and SUPERFRM_REENCODE can not be used at the same time.");
pVideoEncData->mbExceptionCase = TRUE;
}
if (pVideoEncData->mbExceptionCase)
{
aloge("fatal error! Exception Case, Please make the configuration correct first!");
return ERR_VENC_ILLEGAL_PARAM;
}
VencBaseConfig baseConfig;
unsigned int nDstWidth = 0;
unsigned int nDstHeight = 0;
unsigned int nSrcStride = 0;
unsigned int nDstFrameRate = 0;
if(PT_JPEG == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
int jpegEncMode = 0; //0:jpeg; 1:mjpeg
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegEncMode, &jpegEncMode);
int rotate = map_ROTATE_E_to_VENC_Rotate_Angle(pVideoEncData->mEncChnAttr.VeAttr.Rotate);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamRotation, &rotate);
if(pVideoEncData->mEncChnAttr.VeAttr.AttrJpeg.BufSize > 0)
{
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSetVbvSize, &pVideoEncData->mEncChnAttr.VeAttr.AttrJpeg.BufSize);
}
if(pVideoEncData->mEncChnAttr.VeAttr.AttrJpeg.mThreshSize > 0)
{
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSetFrameLenThreshold, &pVideoEncData->mEncChnAttr.VeAttr.AttrJpeg.mThreshSize);
}
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegQuality, (void*)&pVideoEncData->mJpegParam.Qfactor);
nDstWidth = pVideoEncData->mEncChnAttr.VeAttr.AttrJpeg.PicWidth;
nDstHeight = pVideoEncData->mEncChnAttr.VeAttr.AttrJpeg.PicHeight;
nSrcStride = AWALIGN(pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth, 16);
VencJpegVideoSignal sVideoSignal;
memset(&sVideoSignal, 0, sizeof(VencJpegVideoSignal));
sVideoSignal.src_colour_primaries = map_v4l2_colorspace_to_VENC_COLOR_SPACE(pVideoEncData->mEncChnAttr.VeAttr.mColorSpace);
sVideoSignal.dst_colour_primaries = sVideoSignal.src_colour_primaries;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegVideoSignal, &sVideoSignal);
}
else if (PT_MJPEG == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
int jpegEncMode = 1; //0:jpeg; 1:mjpeg
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegEncMode, &jpegEncMode);
switch(pVideoEncData->mEncChnAttr.RcAttr.mRcMode)
{
case VENC_RC_MODE_MJPEGCBR:
{
int nBitRate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
alogd("mjpeg set init nBitRate:%d", nBitRate);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamBitrate, (void*)&nBitRate);
VencBitRateRange bitRateRange;
memcpy(&bitRateRange, &pVideoEncData->mEncChnAttr.RcAttr.mAttrMjpegeCbr.mBitRateRange, sizeof(VencBitRateRange));
/* set the recommended value if usr not config, other values have default values in the library */
if (0 == bitRateRange.bitRateMin)
bitRateRange.bitRateMin = nBitRate;
if (0 == bitRateRange.bitRateMax)
bitRateRange.bitRateMax = nBitRate;
if (0 == bitRateRange.nQualityTh)
bitRateRange.nQualityTh = 85;
if (0 == bitRateRange.nMinQuality)
bitRateRange.nMinQuality = 10;
if (0 == bitRateRange.nMaxQuality)
bitRateRange.nMaxQuality = 100;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSetBitRateRange, (void*)&bitRateRange);
alogd("mjpeg set init Qfactor:%d", pVideoEncData->mJpegParam.Qfactor);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegQuality, (void*)&pVideoEncData->mJpegParam.Qfactor);
break;
}
case VENC_RC_MODE_MJPEGFIXQP:
{
alogw("not support temporary!");
int jpegQuality = pVideoEncData->mEncChnAttr.RcAttr.mAttrMjpegeFixQp.mQfactor; //70
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegQuality, &jpegQuality);
break;
}
default:
{
aloge("fatal error! wrong mjpeg rc mode[0x%x], check code!", pVideoEncData->mEncChnAttr.RcAttr.mRcMode);
break;
}
}
//int nDstFrameRate;
if(pVideoEncData->mFrameRateInfo.DstFrmRate > 0)
{
nDstFrameRate = pVideoEncData->mFrameRateInfo.DstFrmRate;
}
else
{
nDstFrameRate = 25;
}
alogd("mjpeg set init Framerate:%d", nDstFrameRate);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamFramerate, (void*)&nDstFrameRate);
setVbvBufferConfig(pVideoEncData->pCedarV, pVideoEncData);
nDstWidth = pVideoEncData->mEncChnAttr.VeAttr.AttrMjpeg.mPicWidth;
nDstHeight = pVideoEncData->mEncChnAttr.VeAttr.AttrMjpeg.mPicHeight;
nSrcStride = AWALIGN(pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth, 16);
int rotate = map_ROTATE_E_to_VENC_Rotate_Angle(pVideoEncData->mEncChnAttr.VeAttr.Rotate);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamRotation, &rotate);
VencJpegVideoSignal sVideoSignal;
memset(&sVideoSignal, 0, sizeof(VencJpegVideoSignal));
sVideoSignal.src_colour_primaries = map_v4l2_colorspace_to_VENC_COLOR_SPACE(pVideoEncData->mEncChnAttr.VeAttr.mColorSpace);
sVideoSignal.dst_colour_primaries = sVideoSignal.src_colour_primaries;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegVideoSignal, &sVideoSignal);
}
else if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
VencH264Param h264Param;
memset(&h264Param, 0, sizeof(VencH264Param));
h264Param.nCodingMode = VENC_FRAME_CODING;
h264Param.bEntropyCodingCABAC = 1;
h264Param.nBitrate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
//int nDstFrameRate;
if(pVideoEncData->mFrameRateInfo.DstFrmRate > 0)
{
nDstFrameRate = pVideoEncData->mFrameRateInfo.DstFrmRate;
}
else
{
nDstFrameRate = 25;
}
// keep Qp and IFrameInterval for dynamic adjust vencoder param
if(0 == pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval)
{
pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval = nDstFrameRate;
}
h264Param.nMaxKeyInterval = pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval;
h264Param.sProfileLevel.nProfile = map_VENC_ATTR_H264_S_Profile_to_VENC_H264PROFILETYPE(pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.Profile);
h264Param.sProfileLevel.nLevel = map_H264_LEVEL_E_to_VENC_H264LEVELTYPE(pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.mLevel);//VENC_H264Level51;
//h264Param.bLongRefEnable = (unsigned char)pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.mbLongTermRef;
switch(pVideoEncData->mEncChnAttr.RcAttr.mRcMode)
{
case VENC_RC_MODE_H264CBR:
{
h264Param.sRcParam.eRcMode = AW_CBR;
int minQp = pVideoEncData->mRcParam.ParamH264Cbr.mMinQp;
int maxQp = pVideoEncData->mRcParam.ParamH264Cbr.mMaxQp;
if (!(minQp>=1 && minQp<=51))
{
alogw("h264CBR minQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 1", minQp);
pVideoEncData->mRcParam.ParamH264Cbr.mMinQp = 1;
}
if (!(maxQp>=minQp && maxQp>=1 && maxQp<=51))
{
alogw("h264CBR maxQp should in range:[minQp,51]! but usr_SetVal: %d! change it to default: 51", maxQp);
pVideoEncData->mRcParam.ParamH264Cbr.mMaxQp = 51;
}
h264Param.sQPRange.nMinqp = pVideoEncData->mRcParam.ParamH264Cbr.mMinQp;
h264Param.sQPRange.nMaxqp = pVideoEncData->mRcParam.ParamH264Cbr.mMaxQp;
h264Param.sQPRange.nMaxPqp = pVideoEncData->mRcParam.ParamH264Cbr.mMaxPqp;
h264Param.sQPRange.nMinPqp = pVideoEncData->mRcParam.ParamH264Cbr.mMinPqp;
h264Param.sQPRange.nQpInit = pVideoEncData->mRcParam.ParamH264Cbr.mQpInit;
h264Param.sQPRange.bEnMbQpLimit = pVideoEncData->mRcParam.ParamH264Cbr.mbEnMbQpLimit;
break;
}
case VENC_RC_MODE_H264VBR:
{
h264Param.sRcParam.eRcMode = AW_VBR;
int minQp = pVideoEncData->mRcParam.ParamH264Vbr.mMinQp;
int maxQp = pVideoEncData->mRcParam.ParamH264Vbr.mMaxQp;
if (!(minQp>=1 && minQp<=51))
{
alogw("h264VBR minQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 1", minQp);
pVideoEncData->mRcParam.ParamH264Vbr.mMinQp = 1;
}
if (!(maxQp>=minQp && maxQp>=1 && maxQp<=51))
{
alogw("h264VBR maxQp should in range:[minQp,51]! but usr_SetVal: %d! change it to default: 51", maxQp);
pVideoEncData->mRcParam.ParamH264Vbr.mMaxQp = 51;
}
h264Param.sQPRange.nMinqp = pVideoEncData->mRcParam.ParamH264Vbr.mMinQp;
h264Param.sQPRange.nMaxqp = pVideoEncData->mRcParam.ParamH264Vbr.mMaxQp;
h264Param.sQPRange.nMaxPqp = pVideoEncData->mRcParam.ParamH264Vbr.mMaxPqp;
h264Param.sQPRange.nMinPqp = pVideoEncData->mRcParam.ParamH264Vbr.mMinPqp;
h264Param.sQPRange.nQpInit = pVideoEncData->mRcParam.ParamH264Vbr.mQpInit;
h264Param.sQPRange.bEnMbQpLimit = pVideoEncData->mRcParam.ParamH264Vbr.mbEnMbQpLimit;
h264Param.sRcParam.sVbrParam.uMaxBitRate = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Vbr.mMaxBitRate;
h264Param.sRcParam.sVbrParam.nMovingTh = pVideoEncData->mRcParam.ParamH264Vbr.mMovingTh;
h264Param.sRcParam.sVbrParam.nQuality = pVideoEncData->mRcParam.ParamH264Vbr.mQuality;
h264Param.sRcParam.sVbrParam.nIFrmBitsCoef = pVideoEncData->mRcParam.ParamH264Vbr.mIFrmBitsCoef;
h264Param.sRcParam.sVbrParam.nPFrmBitsCoef = pVideoEncData->mRcParam.ParamH264Vbr.mPFrmBitsCoef;
break;
}
case VENC_RC_MODE_H264FIXQP:
{
h264Param.sRcParam.eRcMode = AW_FIXQP;
h264Param.sRcParam.sFixQp.bEnable = 1;
int IQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264FixQp.mIQp;
int PQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264FixQp.mPQp;
if (!(IQp>=1 && IQp<=51))
{
alogw("h264FixQp IQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 30!", IQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH264FixQp.mIQp = 30;
}
if (!(PQp>=1 && PQp<=51))
{
alogw("h264FixQp PQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 30!", PQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH264FixQp.mPQp = 30;
}
h264Param.sRcParam.sFixQp.nIQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264FixQp.mIQp;
h264Param.sRcParam.sFixQp.nPQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264FixQp.mPQp;
break;
}
case VENC_RC_MODE_H264ABR:
{
h264Param.sRcParam.eRcMode = AW_AVBR;
int minQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMinQp;
int maxQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMaxQp;
if (!(minQp>=1 && minQp<=51))
{
alogw("h264ABR minQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 1", minQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMinQp = 1;
}
if (!(maxQp>=minQp && maxQp>=1 && maxQp<=51))
{
alogw("h264ABR maxQp should in range:[minQp,51]! but usr_SetVal: %d! change it to default: 51", maxQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMaxQp = 51;
}
h264Param.sQPRange.nMinqp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMinQp;
h264Param.sQPRange.nMaxqp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMaxQp;
int minIQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMinIQp;
if (!(minIQp>=20 && minIQp<=40))
{
alogw("uMinIQp should be in [20,40]! usr_SetVal:%d, change to defaultVal:30!", minIQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMinIQp = 30;
}
h264Param.sRcParam.uMinIQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMinIQp;
h264Param.sRcParam.sVbrParam.uMaxBitRate = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mMaxBitRate;
//h264Param.sRcParam.sVbrParam.uRatioChangeQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mRatioChangeQp;
h264Param.sRcParam.sVbrParam.nQuality = pVideoEncData->mEncChnAttr.RcAttr.mAttrH264Abr.mQuality;
break;
}
case VENC_RC_MODE_H264QPMAP:
{
alogd("H264 set RcMode = AW_QPMAP");
h264Param.sRcParam.eRcMode = AW_QPMAP;
int minQp = pVideoEncData->mRcParam.ParamH264QpMap.mMinQp;
int maxQp = pVideoEncData->mRcParam.ParamH264QpMap.mMaxQp;
if (!(minQp>=1 && minQp<=51))
{
alogw("h264QPMAP minQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 1", minQp);
pVideoEncData->mRcParam.ParamH264QpMap.mMinQp = 1;
}
if (!(maxQp>=minQp && maxQp>=1 && maxQp<=51))
{
alogw("h264QPMAP maxQp should in range:[minQp,51]! but usr_SetVal: %d! change it to default: 51", maxQp);
pVideoEncData->mRcParam.ParamH264QpMap.mMaxQp = 51;
}
h264Param.sQPRange.nMinqp = pVideoEncData->mRcParam.ParamH264QpMap.mMinQp;
h264Param.sQPRange.nMaxqp = pVideoEncData->mRcParam.ParamH264QpMap.mMaxQp;
h264Param.sQPRange.nMaxPqp = pVideoEncData->mRcParam.ParamH264QpMap.mMaxPqp;
h264Param.sQPRange.nMinPqp = pVideoEncData->mRcParam.ParamH264QpMap.mMinPqp;
h264Param.sQPRange.nQpInit = pVideoEncData->mRcParam.ParamH264QpMap.mQpInit;
h264Param.sQPRange.bEnMbQpLimit = pVideoEncData->mRcParam.ParamH264QpMap.mbEnMbQpLimit;
break;
}
default:
{
aloge("fatal error! wrong h264 rc mode[0x%x], check code!", pVideoEncData->mEncChnAttr.RcAttr.mRcMode);
break;
}
}
h264Param.nFramerate = nDstFrameRate;
h264Param.nSrcFramerate = pVideoEncData->mFrameRateInfo.SrcFrmRate;
//config the GopParam
if(VENC_GOPMODE_NORMALP == pVideoEncData->mEncChnAttr.GopAttr.enGopMode)
{
//h264Param.bLongRefEnable = 0;
h264Param.sGopParam.bUseGopCtrlEn = 1;
h264Param.sGopParam.eGopMode = AW_NORMALP;
}
else
{
aloge("Sorry, this version do not support [%d] GopMode snd set VENC_GOPMODE_NORMALP GopMode!", pVideoEncData->mEncChnAttr.GopAttr.enGopMode);
h264Param.sGopParam.bUseGopCtrlEn = 1;
h264Param.sGopParam.eGopMode = AW_NORMALP;
}
h264Param.sGopParam.sRefParam.bAdvancedRefEn = pVideoEncData->mRefParam.bAdvancedRefEn;
h264Param.sGopParam.sRefParam.nBase = pVideoEncData->mRefParam.nBase;
h264Param.sGopParam.sRefParam.nEnhance = pVideoEncData->mRefParam.nEnhance;
h264Param.sGopParam.sRefParam.bRefBaseEn = pVideoEncData->mRefParam.bRefBaseEn;
if (pVideoEncData->mRefParam.bAdvancedRefEn)
{
alogd("h264 advancedRef:%d,%d,%d,%d", pVideoEncData->mRefParam.bAdvancedRefEn, pVideoEncData->mRefParam.nBase,
pVideoEncData->mRefParam.nEnhance, pVideoEncData->mRefParam.bRefBaseEn);
}
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264Param, &h264Param);
int nIFilterEnable = 0;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamIfilter, &nIFilterEnable);
VencH264VideoSignal sVideoSignal;
memset(&sVideoSignal, 0, sizeof(VencH264VideoSignal));
sVideoSignal.video_format = DEFAULT;
sVideoSignal.full_range_flag = checkColorSpaceFullRange((int)pVideoEncData->mEncChnAttr.VeAttr.mColorSpace);;
sVideoSignal.src_colour_primaries = map_v4l2_colorspace_to_VENC_COLOR_SPACE(pVideoEncData->mEncChnAttr.VeAttr.mColorSpace);
sVideoSignal.dst_colour_primaries = sVideoSignal.src_colour_primaries;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264VideoSignal, &sVideoSignal);
//int nPskip = 0;
//VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSetPSkip, &nPskip);
int nFastEnc = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.FastEncFlag ? 1 : 0;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamFastEnc, &nFastEnc);
int sliceHeight = 0;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSliceHeight, &sliceHeight);
unsigned char bPFrameIntraEn = (unsigned char)pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.mbPIntraEnable;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamPFrameIntraEn, (void*)&bPFrameIntraEn);
setVbvBufferConfig(pVideoEncData->pCedarV, pVideoEncData);
nDstWidth = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicWidth;
nDstHeight = pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.PicHeight;
nSrcStride = AWALIGN(pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth, 16);
int rotate = map_ROTATE_E_to_VENC_Rotate_Angle(pVideoEncData->mEncChnAttr.VeAttr.Rotate);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamRotation, &rotate);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamIQpOffset, &pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.IQpOffset);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamIsNightCaseFlag, (void*)&pVideoEncData->DayOrNight);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamHighPassFilter, &pVideoEncData->mVencHighPassFilter);
//VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSensorType, &pVideoEncData->mRcParam.sensor_type);
}
else if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
VencH265Param h265Param;
memset(&h265Param, 0, sizeof(VencH265Param));
h265Param.sProfileLevel.nProfile = map_VENC_ATTR_H265_S_Profile_to_VENC_H265PROFILETYPE(pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mProfile);
h265Param.sProfileLevel.nLevel = map_H265_LEVEL_E_to_VENC_H265LEVELTYPE(pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mLevel);//VENC_H265Level62;
//h265Param.bLongTermRef = (int)pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mbLongTermRef;
switch(pVideoEncData->mEncChnAttr.RcAttr.mRcMode)
{
case VENC_RC_MODE_H265CBR:
{
h265Param.sRcParam.eRcMode = AW_CBR;
int minQp = pVideoEncData->mRcParam.ParamH265Cbr.mMinQp;
int maxQp = pVideoEncData->mRcParam.ParamH265Cbr.mMaxQp;
if (!(minQp>=1 && minQp<=51))
{
alogw("h265CBR minQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 1", minQp);
pVideoEncData->mRcParam.ParamH265Cbr.mMinQp = 1;
}
if (!(maxQp>=minQp && maxQp>=1 && maxQp<=51))
{
alogw("h265CBR maxQp should in range:[minQp,51]! but usr_SetVal: %d! change it to default: 51", maxQp);
pVideoEncData->mRcParam.ParamH265Cbr.mMaxQp = 51;
}
h265Param.sQPRange.nMinqp = pVideoEncData->mRcParam.ParamH265Cbr.mMinQp;
h265Param.sQPRange.nMaxqp = pVideoEncData->mRcParam.ParamH265Cbr.mMaxQp;
h265Param.sQPRange.nMaxPqp = pVideoEncData->mRcParam.ParamH265Cbr.mMaxPqp;
h265Param.sQPRange.nMinPqp = pVideoEncData->mRcParam.ParamH265Cbr.mMinPqp;
h265Param.sQPRange.nQpInit = pVideoEncData->mRcParam.ParamH265Cbr.mQpInit;
h265Param.sQPRange.bEnMbQpLimit = pVideoEncData->mRcParam.ParamH265Cbr.mbEnMbQpLimit;
break;
}
case VENC_RC_MODE_H265VBR:
{
h265Param.sRcParam.eRcMode = AW_VBR;
int minQp = pVideoEncData->mRcParam.ParamH265Vbr.mMinQp;
int maxQp = pVideoEncData->mRcParam.ParamH265Vbr.mMaxQp;
if (!(minQp>=1 && minQp<=51))
{
alogw("h265VBR minQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 1", minQp);
pVideoEncData->mRcParam.ParamH265Vbr.mMinQp = 1;
}
if (!(maxQp>=minQp && maxQp>=1 && maxQp<=51))
{
alogw("h265VBR maxQp should in range:[minQp,51]! but usr_SetVal: %d! change it to default: 51", maxQp);
pVideoEncData->mRcParam.ParamH265Vbr.mMaxQp = 51;
}
h265Param.sQPRange.nMinqp = pVideoEncData->mRcParam.ParamH265Vbr.mMinQp;
h265Param.sQPRange.nMaxqp = pVideoEncData->mRcParam.ParamH265Vbr.mMaxQp;
h265Param.sQPRange.nMaxPqp = pVideoEncData->mRcParam.ParamH265Vbr.mMaxPqp;
h265Param.sQPRange.nMinPqp = pVideoEncData->mRcParam.ParamH265Vbr.mMinPqp;
h265Param.sQPRange.nQpInit = pVideoEncData->mRcParam.ParamH265Vbr.mQpInit;
h265Param.sQPRange.bEnMbQpLimit = pVideoEncData->mRcParam.ParamH265Vbr.mbEnMbQpLimit;
h265Param.sRcParam.sVbrParam.uMaxBitRate = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Vbr.mMaxBitRate;
h265Param.sRcParam.sVbrParam.nMovingTh = pVideoEncData->mRcParam.ParamH265Vbr.mMovingTh;
h265Param.sRcParam.sVbrParam.nQuality = pVideoEncData->mRcParam.ParamH265Vbr.mQuality;
h265Param.sRcParam.sVbrParam.nIFrmBitsCoef = pVideoEncData->mRcParam.ParamH265Vbr.mIFrmBitsCoef;
h265Param.sRcParam.sVbrParam.nPFrmBitsCoef = pVideoEncData->mRcParam.ParamH265Vbr.mPFrmBitsCoef;
break;
}
case VENC_RC_MODE_H265FIXQP:
{
h265Param.sRcParam.eRcMode = AW_FIXQP;
h265Param.sRcParam.sFixQp.bEnable = 1;
int IQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265FixQp.mIQp;
int PQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265FixQp.mPQp;
if (!(IQp>=1 && IQp<=51))
{
alogw("h265FixQp IQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 30!", IQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH265FixQp.mIQp = 30;
}
if (!(PQp>=1 && PQp<=51))
{
alogw("h265FixQp PQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 30!", PQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH265FixQp.mPQp = 30;
}
h265Param.sRcParam.sFixQp.nIQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265FixQp.mIQp;
h265Param.sRcParam.sFixQp.nPQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265FixQp.mPQp;
break;
}
case VENC_RC_MODE_H265ABR:
{
h265Param.sRcParam.eRcMode = AW_AVBR;
int minQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMinQp;
int maxQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMaxQp;
if (!(minQp>=1 && minQp<=51))
{
alogw("h265ABR minQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 1", minQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMinQp = 1;
}
if (!(maxQp>=minQp && maxQp>=1 && maxQp<=51))
{
alogw("h265ABR maxQp should in range:[minQp,51]! but usr_SetVal: %d! change it to default: 51", maxQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMaxQp = 51;
}
h265Param.sQPRange.nMinqp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMinQp;
h265Param.sQPRange.nMaxqp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMaxQp;
int minIQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMinIQp;
if (!(minIQp>=20 && minIQp<=40))
{
alogw("uMinIQp should be in [20,40]! usr_SetVal:%d, change to defaultVal:30!", minIQp);
pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMinIQp = 30;
}
h265Param.sRcParam.uMinIQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMinIQp;
h265Param.sRcParam.sVbrParam.uMaxBitRate = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mMaxBitRate;
//h265Param.sRcParam.sVbrParam.uRatioChangeQp = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mRatioChangeQp;
h265Param.sRcParam.sVbrParam.nQuality = pVideoEncData->mEncChnAttr.RcAttr.mAttrH265Abr.mQuality;
break;
}
case VENC_RC_MODE_H265QPMAP:
{
alogd("H265 set RcMode = AW_QPMAP");
h265Param.sRcParam.eRcMode = AW_QPMAP;
int minQp = pVideoEncData->mRcParam.ParamH265QpMap.mMinQp;
int maxQp = pVideoEncData->mRcParam.ParamH265QpMap.mMaxQp;
if (!(minQp>=1 && minQp<=51))
{
alogw("h265QPMAP minQp should in range:[1,51]! but usr_SetVal: %d! change it to default: 1", minQp);
pVideoEncData->mRcParam.ParamH265QpMap.mMinQp = 1;
}
if (!(maxQp>=minQp && maxQp>=1 && maxQp<=51))
{
alogw("h265QPMAP maxQp should in range:[minQp,51]! but usr_SetVal: %d! change it to default: 51", maxQp);
pVideoEncData->mRcParam.ParamH265QpMap.mMaxQp = 51;
}
h265Param.sQPRange.nMinqp = pVideoEncData->mRcParam.ParamH265QpMap.mMinQp;
h265Param.sQPRange.nMaxqp = pVideoEncData->mRcParam.ParamH265QpMap.mMaxQp;
h265Param.sQPRange.nMaxPqp = pVideoEncData->mRcParam.ParamH265QpMap.mMaxPqp;
h265Param.sQPRange.nMinPqp = pVideoEncData->mRcParam.ParamH265QpMap.mMinPqp;
h265Param.sQPRange.nQpInit = pVideoEncData->mRcParam.ParamH265QpMap.mQpInit;
h265Param.sQPRange.bEnMbQpLimit = pVideoEncData->mRcParam.ParamH265QpMap.mbEnMbQpLimit;
break;
}
default:
{
aloge("fatal error! wrong h265 rc mode[0x%x], check code!", pVideoEncData->mEncChnAttr.RcAttr.mRcMode);
break;
}
}
//int nDstFrameRate;
if(pVideoEncData->mFrameRateInfo.DstFrmRate > 0)
{
nDstFrameRate = pVideoEncData->mFrameRateInfo.DstFrmRate;
}
else
{
nDstFrameRate = 25;
}
h265Param.nFramerate = nDstFrameRate;
h265Param.nSrcFramerate = pVideoEncData->mFrameRateInfo.SrcFrmRate;
h265Param.nBitrate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
if(0 == pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval)
{
pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval = nDstFrameRate;
}
//set gop size
h265Param.idr_period = pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval;
h265Param.nIntraPeriod = pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval;
//h265Param.nGopSize = getMostSuitabeleGopSize(pVideoEncData->mEncChnAttr.GopAttr.mGopSize, pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval);
h265Param.nGopSize = pVideoEncData->mEncChnAttr.GopAttr.mGopSize;
/*
if(h265Param.nGopSize <= 0)
{
alogd("user set invalid gopSize[%d], use idr interval[%d] as default.", h265Param.nGopSize, h265Param.idr_period);
h265Param.nGopSize = h265Param.idr_period;
}
*/
h265Param.nQPInit = 26;
if(VENC_GOPMODE_NORMALP == pVideoEncData->mEncChnAttr.GopAttr.enGopMode)
{
//h265Param.bLongTermRef = 0;
h265Param.sGopParam.bUseGopCtrlEn = 1;
h265Param.sGopParam.eGopMode = AW_NORMALP;
}
else
{
aloge("Sorry, this version do not support [%d] GopMode snd set VENC_GOPMODE_NORMALP GopMode!", pVideoEncData->mEncChnAttr.GopAttr.enGopMode);
//h265Param.bLongTermRef = 0;
h265Param.sGopParam.bUseGopCtrlEn = 1;
h265Param.sGopParam.eGopMode = AW_NORMALP;
}
h265Param.sGopParam.sRefParam.bAdvancedRefEn = pVideoEncData->mRefParam.bAdvancedRefEn;
h265Param.sGopParam.sRefParam.nBase = pVideoEncData->mRefParam.nBase;
h265Param.sGopParam.sRefParam.nEnhance = pVideoEncData->mRefParam.nEnhance;
h265Param.sGopParam.sRefParam.bRefBaseEn = pVideoEncData->mRefParam.bRefBaseEn;
if (pVideoEncData->mRefParam.bAdvancedRefEn)
{
alogd("h265 advancedRef:%d,%d,%d,%d", pVideoEncData->mRefParam.bAdvancedRefEn, pVideoEncData->mRefParam.nBase,
pVideoEncData->mRefParam.nEnhance, pVideoEncData->mRefParam.bRefBaseEn);
}
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH265Param, &h265Param);
//VencSetParameter(pCedarV, VENC_IndexParamMaxKeyInterval, (void*)&pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval);
//unsigned int nVirIFrameInterval = pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mVirtualIFrameInterval;
//VencSetParameter(pCedarV, VENC_IndexParamVirtualIFrame, (void*)&nVirIFrameInterval);
int nFastEnc = pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mFastEncFlag ? 1 : 0;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamFastEnc, &nFastEnc);
unsigned char bPFrameIntraEn = (unsigned char)pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mbPIntraEnable;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamPFrameIntraEn, (void*)&bPFrameIntraEn);
setVbvBufferConfig(pVideoEncData->pCedarV, pVideoEncData);
nDstWidth = pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mPicWidth;
nDstHeight = pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mPicHeight;
nSrcStride = AWALIGN(pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth, 16);
int rotate = map_ROTATE_E_to_VENC_Rotate_Angle(pVideoEncData->mEncChnAttr.VeAttr.Rotate);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamRotation, &rotate);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamIQpOffset, &pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.IQpOffset);
VencH264VideoSignal sVideoSignal;
memset(&sVideoSignal, 0, sizeof(VencH264VideoSignal));
sVideoSignal.video_format = DEFAULT;
sVideoSignal.full_range_flag = checkColorSpaceFullRange((int)pVideoEncData->mEncChnAttr.VeAttr.mColorSpace);
sVideoSignal.src_colour_primaries = map_v4l2_colorspace_to_VENC_COLOR_SPACE(pVideoEncData->mEncChnAttr.VeAttr.mColorSpace);
sVideoSignal.dst_colour_primaries = sVideoSignal.src_colour_primaries;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamVUIVideoSignal, &sVideoSignal);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamIsNightCaseFlag, (void*)&pVideoEncData->DayOrNight);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamHighPassFilter, &pVideoEncData->mVencHighPassFilter);
//VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSensorType, &pVideoEncData->mRcParam.sensor_type);
}
else
{
aloge("fatal error! unknown venc type:0x%x", pVideoEncData->mEncChnAttr.VeAttr.Type);
}
if(pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth != nSrcStride)
{
aloge("fatal error! srcWidth[%d]!=srcStride[%d]", pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth, nSrcStride);
}
#ifdef ENABLE_ENCODE_STATISTICS
unsigned char bEnableStatistics = 1;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEncodeTimeEn, (void*)&bEnableStatistics);
#endif
if ((VENC_RC_MODE_H264QPMAP == pVideoEncData->mEncChnAttr.RcAttr.mRcMode) ||
(VENC_RC_MODE_H265QPMAP == pVideoEncData->mEncChnAttr.RcAttr.mRcMode))
{
VideoEncMBInfoInit(&pVideoEncData->mMBInfo, &pVideoEncData->mEncChnAttr);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamMBInfoOutput, &pVideoEncData->mMBInfo);
// Notice: for first frame, not set MBModeCtrl.
// VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamMBModeCtrl, &pVideoEncData->mMBModeCtrl);
}
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
if (pVideoEncData->mH264VuiParam.VuiTimeInfo.timing_info_present_flag)
{
/** timing_info_present_flag is the default param for H264. */
VencH264VideoTiming timeInfo;
memset(&timeInfo, 0, sizeof(VencH264VideoTiming));
timeInfo.fixed_frame_rate_flag = pVideoEncData->mH264VuiParam.VuiTimeInfo.fixed_frame_rate_flag;
timeInfo.num_units_in_tick = pVideoEncData->mH264VuiParam.VuiTimeInfo.num_units_in_tick;
timeInfo.time_scale = pVideoEncData->mH264VuiParam.VuiTimeInfo.time_scale;
alogd("H264 fixed_frame_rate_flag: %d, num_units_in_tick: %d, time_scale: %d",
timeInfo.fixed_frame_rate_flag, timeInfo.num_units_in_tick, timeInfo.time_scale);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264VideoTiming, &timeInfo);
}
}
else if (PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
if (pVideoEncData->mH265VuiParam.VuiTimeInfo.timing_info_present_flag)
{
VencH265TimingS timeInfo;
memset(&timeInfo, 0, sizeof(VencH265TimingS));
timeInfo.timing_info_present_flag = pVideoEncData->mH265VuiParam.VuiTimeInfo.timing_info_present_flag;
timeInfo.num_units_in_tick = pVideoEncData->mH265VuiParam.VuiTimeInfo.num_units_in_tick;
timeInfo.time_scale = pVideoEncData->mH265VuiParam.VuiTimeInfo.time_scale;
timeInfo.num_ticks_poc_diff_one = pVideoEncData->mH265VuiParam.VuiTimeInfo.num_ticks_poc_diff_one_minus1;
alogd("H265 timing_info_present_flag: %d, num_units_in_tick: %d, time_scale: %d, num_ticks_poc_diff_one: %d",
timeInfo.timing_info_present_flag, timeInfo.num_units_in_tick, timeInfo.time_scale, timeInfo.num_ticks_poc_diff_one);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH265Timing, &timeInfo);
}
}
if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
//init EnIFrmMbRcMoveStatus before Venc Init
if (pVideoEncData->mRcParam.EnIFrmMbRcMoveStatusEnable)
{
if (0 > pVideoEncData->mRcParam.EnIFrmMbRcMoveStatus || 4 < pVideoEncData->mRcParam.EnIFrmMbRcMoveStatus)
{
aloge("fatal error! VencChn[%d] EnIFrmMbRcMoveStatus %d is out of range [0,4]", pVideoEncData->mMppChnInfo.mChnId,
pVideoEncData->mRcParam.EnIFrmMbRcMoveStatus);
}
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEnIFrmMbRcMoveStatus, (void*)&pVideoEncData->mRcParam.EnIFrmMbRcMoveStatus);
}
if ((VENC_RC_MODE_H264VBR == pVideoEncData->mEncChnAttr.RcAttr.mRcMode) ||
(VENC_RC_MODE_H265VBR == pVideoEncData->mEncChnAttr.RcAttr.mRcMode))
{
if (pVideoEncData->mRcParam.mBitsRatioEnable)
{
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamIPTargetBitsRatio, (void*)&pVideoEncData->mRcParam.mBitsRatio);
}
}
//weak texture threshold
if (pVideoEncData->mRcParam.mWeakTextureThEnable)
{
if (0 > pVideoEncData->mRcParam.mWeakTextureTh || 100.0 < pVideoEncData->mRcParam.mWeakTextureTh)
{
aloge("fatal error! VencChn[%d] WeakTextureTh %d is out of range [0,100]", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mRcParam.mWeakTextureTh);
}
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamWeakTextTh, (void*)&pVideoEncData->mRcParam.mWeakTextureTh);
}
if (-1 != pVideoEncData->mD3DInIFrmEnable)
{
alogv("VencChn[%d] en_d3d_in_i_frm:%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mD3DInIFrmEnable);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEnD3DInIFrm, (void*)&pVideoEncData->mD3DInIFrmEnable);
}
if (-1 != pVideoEncData->mTightMbQpEnable)
{
alogv("VencChn[%d] en_tight_mb_qp:%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mTightMbQpEnable);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEnTightMbQp, (void*)&pVideoEncData->mTightMbQpEnable);
}
if ((unsigned char)(-1) != pVideoEncData->mExtremeD3D.en_extreme_d3d)
{
alogv("VencChn[%d] en_extreme_d3d:%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mExtremeD3D.en_extreme_d3d);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSetExtremeD3D, (void*)&pVideoEncData->mExtremeD3D);
}
}
// encpp sharp
alogv("veChn[%d], EncppEnable=%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.EncppAttr.mbEncppEnable);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEnableEncppSharp, (void*)&pVideoEncData->mEncChnAttr.EncppAttr.mbEncppEnable);
if (PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
unsigned int DropFrameNum = pVideoEncData->mEncChnAttr.VeAttr.mDropFrameNum;
alogd("DropFrameNum: %d", DropFrameNum);
if (DropFrameNum > 0)
{
if (FALSE == pVideoEncData->mbForbidDiscardingFrame)
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamDropFrame, (void*)&DropFrameNum);
else
aloge("fatal error, setting DropFrameNum is not supported in ForbidDiscardingFrame mode!");
}
}
alogv("GDC enable: %d", pVideoEncData->mEncChnAttr.GdcAttr.bGDC_en);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamGdcConfig, &pVideoEncData->mEncChnAttr.GdcAttr);
if (PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
int VeRecRefBufReduceEnable = pVideoEncData->mEncChnAttr.VeAttr.mVeRecRefBufReduceEnable;
alogd("VeRecRefBufReduceEnable: %d", VeRecRefBufReduceEnable);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEnableRecRefBufReduceFunc, &VeRecRefBufReduceEnable);
}
if (pVideoEncData->mForceConfWin.en_force_conf)
{
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamForceConfWin, (void*)&pVideoEncData->mForceConfWin);
unsigned int nDstWidthAlign = AWALIGN(nDstWidth, 16);
unsigned int nDstHeightAlign = AWALIGN(nDstHeight, 16);
alogd("ForceConfWin update dst width x height: %dx%d->%dx%d", nDstWidth, nDstHeight, nDstWidthAlign, nDstHeightAlign);
nDstWidth = nDstWidthAlign;
nDstHeight = nDstHeightAlign;
}
memset(&baseConfig, 0 ,sizeof(VencBaseConfig));
baseConfig.nInputWidth = pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth;
baseConfig.nInputHeight = pVideoEncData->mEncChnAttr.VeAttr.SrcPicHeight;
baseConfig.nStride = nSrcStride;
baseConfig.nDstWidth = nDstWidth;
baseConfig.nDstHeight = nDstHeight;
baseConfig.eOutputFormat = pVideoEncData->mEncChnAttr.VeAttr.OutputFormat;
baseConfig.eInputFormat = map_PIXEL_FORMAT_E_to_VENC_PIXEL_FMT(pVideoEncData->mEncChnAttr.VeAttr.PixelFormat);
switch(pVideoEncData->mEncChnAttr.VeAttr.PixelFormat)
{
case MM_PIXEL_FORMAT_YUV_AW_LBC_2_0X:
{
baseConfig.bLbcLossyComEnFlag1_5x = 0;
baseConfig.bLbcLossyComEnFlag2x = 1;
baseConfig.bLbcLossyComEnFlag2_5x = 0;
break;
}
case MM_PIXEL_FORMAT_YUV_AW_LBC_2_5X:
{
baseConfig.bLbcLossyComEnFlag1_5x = 0;
baseConfig.bLbcLossyComEnFlag2x = 0;
baseConfig.bLbcLossyComEnFlag2_5x = 1;
break;
}
case MM_PIXEL_FORMAT_YUV_AW_LBC_1_5X:
{
baseConfig.bLbcLossyComEnFlag1_5x = 1;
baseConfig.bLbcLossyComEnFlag2x = 0;
baseConfig.bLbcLossyComEnFlag2_5x = 1;
break;
}
case MM_PIXEL_FORMAT_YUV_AW_LBC_1_0X:
{
baseConfig.bLbcLossyComEnFlag1_5x = 0;
baseConfig.bLbcLossyComEnFlag2x = 0;
baseConfig.bLbcLossyComEnFlag2_5x = 0;
break;
}
default:
break;
}
baseConfig.bIsVbvNoCache = 1; //video encode config vbv buffer no cache!
//baseConfig.memops = pVideoEncData->mMemOps;
if (pVideoEncData->mEncChnAttr.VeAttr.mOnlineEnable)
{
baseConfig.bOnlineMode = 1;
baseConfig.bOnlineChannel = 1;
unsigned int OnlineShareBufNum = pVideoEncData->mEncChnAttr.VeAttr.mOnlineShareBufNum;
if ((2 < OnlineShareBufNum) || (0 >= OnlineShareBufNum))
{
baseConfig.nOnlineShareBufNum = 1;
alogw("user set OnlineShareBufNum=%d is invalid value, reset it to 1.", OnlineShareBufNum);
}
else
{
baseConfig.nOnlineShareBufNum = OnlineShareBufNum;
}
pVideoEncData->mOnlineEnableFlag = 1;
}
else
{
baseConfig.bOnlineMode = 1;
baseConfig.bOnlineChannel = 0;
pVideoEncData->mOnlineEnableFlag = 0;
}
alogv("Online Mode=%d, Channel=%d, ShareBufNum=%d, OnlineEnableFlag=%d",
baseConfig.bOnlineMode, baseConfig.bOnlineChannel, baseConfig.nOnlineShareBufNum, pVideoEncData->mOnlineEnableFlag);
baseConfig.rec_lbc_mode = map_VENC_REF_FRAME_LBC_MODE_E_to_VeRecRefLbcMode(pVideoEncData->mEncChnAttr.VeAttr.mVeRefFrameLbcMode);
alogv("rec_lbc_mode=%d", baseConfig.rec_lbc_mode);
ret = VencInit(pVideoEncData->pCedarV, &baseConfig);
if(VENC_RESULT_OK != ret)
{
aloge("fatal error vencInit fail:%x",ret);
if(VENC_RESULT_EFUSE_ERROR == ret)
{
return ERR_VENC_EFUSE_ERROR;
}
else if(VENC_RESULT_NO_MEMORY == ret)
{
return ERR_VENC_NOMEM;
}
else if(VENC_RESULT_NULL_PTR == ret)
{
return ERR_VENC_NULL_PTR;
}
}
else
{
alogv("Venc Init success");
int venclib_ret = VencSetCallbacks(pVideoEncData->pCedarV, &gVencCompCbType, (void *)pVideoEncData);
if (VENC_RESULT_OK != venclib_ret)
{
aloge("fatal error Venc SetCallbacks fail:%x", venclib_ret);
}
else
{
alogv("Venc SetCallbacks success");
}
// venclib_ret = VencStart(pVideoEncData->pCedarV);
// if (VENC_RESULT_OK != venclib_ret)
// {
// aloge("fatal error! Venc Start fail, ret=%d", venclib_ret);
// }
// else
// {
// alogv("Venc Start success");
// }
}
memcpy(&pVideoEncData->mBaseConfig, &baseConfig, sizeof(VencBaseConfig));
pVideoEncData->mbCedarvVideoEncInitFlag = TRUE;
pVideoEncData->mMemOps = baseConfig.memops;
pVideoEncData->mVeOpsS = baseConfig.veOpsS;
pVideoEncData->mpVeOpsSelf = baseConfig.pVeOpsSelf;
if(pVideoEncData->mVEFreq)
{
alogd("venc init VE freq to [%d]MHz", pVideoEncData->mVEFreq);
//CdcVeSetSpeed(baseConfig.veOpsS, baseConfig.pVeOpsSelf, pVideoEncData->mVEFreq);
VencSetFreq(pVideoEncData->pCedarV, pVideoEncData->mVEFreq);
}
//unsigned char nPrintParamsFlag = 0;
//VencGetParameter(pCedarV, VENC_IndexParamAllParams, (void*)&nPrintParamsFlag);
if((PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type) || (PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type))
{
if(VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSaveBSFile, (void*)&pVideoEncData->mSaveBSFile) != 0)
{
aloge("fatal error! can not save bs file!");
}
}
//open the proc to catch parame of VE.
if(VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamProcSet, (void*)&pVideoEncData->mProcSet) != 0)
{
aloge("fatal error! can not open proc info!");
}
if(VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamChannelNum, (void*)&pVideoEncData->mMppChnInfo.mChnId) != 0)
{
aloge("fatal error! set channel num[%d] fail", pVideoEncData->mMppChnInfo.mChnId);
}
if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
//init color2grey
unsigned char OpenColor2Grey = pVideoEncData->mColor2GreyParam.bColor2Grey?1:0;
alogd("Color2Grey: %d", OpenColor2Grey);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamChmoraGray,(void*)&OpenColor2Grey);
// config if drop overflow frame directly.
unsigned int bDropOverflowFrameFlag = pVideoEncData->mbDropOverflowFrameFlag;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamDropOverflowFrame, (void*)&bDropOverflowFrameFlag);
// set VencTargetBitsClipParam.
VencTargetBitsClipParam *pBitsClipParam = &pVideoEncData->mRcParam.mBitsClipParam;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamTargetBitsClipParam, (void*)pBitsClipParam);
// set VencAeDiffParam.
VencAeDiffParam *pAeDiffParam = &pVideoEncData->mRcParam.mAeDiffParam;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamAeDiffParam, (void*)pAeDiffParam);
}
alogv("vencChn[%d] type[%d] init done", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
}
else
{
aloge("fatal error! the video encoder do not creat!!");
}
return ret;
}
static ERRORTYPE config_VENC_STREAM_S_by_EncodedStream(VENC_STREAM_S *pDst, EncodedStream *pSrc, VIDEOENCDATATYPE *pVideoEncData)
{
if(pDst->mPackCount<1 || NULL==pDst->mpPack)
{
aloge("fatal error! wrong param[%d],[%p]!", pDst->mPackCount, pDst->mpPack);
return ERR_VENC_ILLEGAL_PARAM;
}
pDst->mpPack[0].mpAddr0 = pSrc->pBuffer;
pDst->mpPack[0].mpAddr1 = pSrc->pBufferExtra;
pDst->mpPack[0].mpAddr2 = pSrc->pBufferExtra2;
pDst->mpPack[0].mLen0 = pSrc->nBufferLen;
pDst->mpPack[0].mLen1 = pSrc->nBufferExtraLen;
pDst->mpPack[0].mLen2 = pSrc->nBufferExtraLen2;
pDst->mpPack[0].mPTS = pSrc->nTimeStamp;
pDst->mpPack[0].mbFrameEnd = TRUE;
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
pDst->mpPack[0].mDataType.enH264EType = (pSrc->nFlags & CEDARV_FLAG_KEYFRAME) ? H264E_NALU_ISLICE : H264E_NALU_PSLICE;
}
else if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
pDst->mpPack[0].mDataType.enH265EType = (pSrc->nFlags & CEDARV_FLAG_KEYFRAME) ? H265E_NALU_ISLICE : H265E_NALU_PSLICE;
}
else if(PT_MJPEG == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_JPEG == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
pDst->mpPack[0].mDataType.enJPEGEType = JPEGE_PACK_PIC;
}
else
{
alogw("fatal error! unsupported temporary!");
}
pDst->mpPack[0].mOffset = 0;
pDst->mpPack[0].mDataNum = 0;
pDst->mSeq = pSrc->nID;
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
//temporary not use h264 info.
memset(&pDst->mH264Info, 0, sizeof(VENC_STREAM_INFO_H264_S));
}
else if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
//temporary not use h265 info.
memset(&pDst->mH265Info, 0, sizeof(VENC_STREAM_INFO_H265_S));
}
else if(PT_MJPEG == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_JPEG == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
//temporary not use jpeg info.
memset(&pDst->mJpegInfo, 0, sizeof(VENC_STREAM_INFO_JPEG_S));
}
else
{
alogw("fatal error! unsupported temporary!");
}
return SUCCESS;
}
static ERRORTYPE config_VencOutputBuffer_By_EncodedStream(VencOutputBuffer* pDst, EncodedStream* pSrc)
{
if (pDst == NULL || pSrc == NULL)
{
aloge("fatal error! Empty pointer in config_VencOutputBuffer_By_EncodedStream");
return ERR_VENC_ILLEGAL_PARAM;
}
pDst->nID = pSrc->nID;
pDst->nPts = pSrc->nTimeStamp;
pDst->nFlag = 0;
if (pSrc->nFlags & CEDARV_FLAG_KEYFRAME)
{
pDst->nFlag |= VENC_BUFFERFLAG_KEYFRAME;
}
if (pSrc->nFlags & CEDARV_FLAG_EOS)
{
pDst->nFlag |= VENC_BUFFERFLAG_EOS;
}
if (pSrc->nFlags & CEDARV_FLAG_THUMB)
{
pDst->nFlag |= VENC_BUFFERFLAG_THUMB;
}
pDst->nSize0 = pSrc->nBufferLen;
pDst->nSize1 = pSrc->nBufferExtraLen;
pDst->nSize2 = pSrc->nBufferExtraLen2;
pDst->pData0 = pSrc->pBuffer;
pDst->pData1 = pSrc->pBufferExtra;
pDst->pData2 = pSrc->pBufferExtra2;
memcpy(&pDst->frame_info, &pSrc->video_frame_info, sizeof(FrameInfo));
return SUCCESS;
}
static ERRORTYPE config_EncodedStream_By_VencOutputBuffer(EncodedStream* pDst, VencOutputBuffer* pSrc, VIDEOENCDATATYPE *pVideoEncData)
{
if (pDst == NULL || pSrc == NULL)
{
aloge("fatal error! Empty pointer in config_EncodedStream_By_VencOutputBuffer");
return ERR_VENC_ILLEGAL_PARAM;
}
pDst->media_type = CDX_PacketVideo;
pDst->nID = pSrc->nID;
pDst->nFilledLen = pSrc->nSize0 + pSrc->nSize1;
pDst->nTobeFillLen = pDst->nFilledLen;
// for online timelapse: (1) change sensor output fps; (2) change vencode output stream fps.
pthread_mutex_lock(&pVideoEncData->mCapTimeLapseLock);
if (pVideoEncData->timeLapseEnable && pVideoEncData->mOnlineEnableFlag)
{
pDst->nTimeStamp = pVideoEncData->mCapTimeLapse.lastTimeStamp;
pVideoEncData->mCapTimeLapse.lastTimeStamp += pVideoEncData->mCapTimeLapse.videoFrameIntervalUs;
alogv("VencChn[%d] update pts=%d, cur timeStamp=%lld", pVideoEncData->mMppChnInfo.mChnId, pDst->nTimeStamp, GetSysTimeByUsec());
}
else
{
pDst->nTimeStamp = pSrc->nPts;
}
pthread_mutex_unlock(&pVideoEncData->mCapTimeLapseLock);
pDst->nFlags = 0;
if (pSrc->nFlag & VENC_BUFFERFLAG_KEYFRAME)
{
pDst->nFlags |= CEDARV_FLAG_KEYFRAME;
}
if (pSrc->nFlag & VENC_BUFFERFLAG_EOS)
{
pDst->nFlags |= CEDARV_FLAG_EOS;
}
if (pSrc->nFlag & VENC_BUFFERFLAG_THUMB)
{
pDst->nFlags |= CEDARV_FLAG_THUMB;
}
pDst->pBuffer = pSrc->pData0;
pDst->nBufferLen = pSrc->nSize0;
pDst->pBufferExtra = pSrc->pData1;
pDst->nBufferExtraLen = pSrc->nSize1;
pDst->pBufferExtra2 = pSrc->pData2;
pDst->nBufferExtraLen2 = pSrc->nSize2;
pDst->video_stream_type = VIDEO_TYPE_MAJOR;
memcpy(&pDst->video_frame_info, &pSrc->frame_info, sizeof(FrameInfo));
pDst->infoVersion = -1;
pDst->pChangedStreamsInfo = NULL;
pDst->duration = -1;
return SUCCESS;
}
static ERRORTYPE freeVideoFrameInfoNode(VideoFrameInfoNode *pNode)
{
free(pNode);
return SUCCESS;
}
static ERRORTYPE VideoEncConfigVencInputBufferRoiParam(VIDEOENCDATATYPE *pVideoEncData, VencInputBuffer *pEncBuf)
{
int i=0;
int cfg_num = AW_ARRAY_SIZE(pEncBuf->roi_param);
pEncBuf->bUseInputBufferRoi = 0;
if (!list_empty(&pVideoEncData->mRoiCfgList))
{
//alogd("set frame roi");
VEncRoiCfgNode *pEntry, *pTemp;
list_for_each_entry_safe(pEntry, pTemp, &pVideoEncData->mRoiCfgList, mList)
{
if (i >= cfg_num)
{
break;
}
pEncBuf->roi_param[i].bEnable = pEntry->mROI.bEnable;
pEncBuf->roi_param[i].index = pEntry->mROI.Index;
pEncBuf->roi_param[i].nQPoffset = pEntry->mROI.Qp;
pEncBuf->roi_param[i].roi_abs_flag = pEntry->mROI.bAbsQp;
pEncBuf->roi_param[i].sRect.nLeft = pEntry->mROI.Rect.X;
pEncBuf->roi_param[i].sRect.nTop = pEntry->mROI.Rect.Y;
pEncBuf->roi_param[i].sRect.nWidth = pEntry->mROI.Rect.Width;
pEncBuf->roi_param[i].sRect.nHeight = pEntry->mROI.Rect.Height;
if(pEntry->mROI.bEnable)
{
pEncBuf->bUseInputBufferRoi = 1;
}
alogv("ROIConfig i=%d, UseInputBufferRoi:%d, en:%d idx[%d]Qp[%d]AbsQp[%d] X[%d]Y[%d]W[%d]H[%d]",
i, pEncBuf->bUseInputBufferRoi, pEncBuf->roi_param[i].bEnable, pEncBuf->roi_param[i].index,
pEncBuf->roi_param[i].nQPoffset, pEncBuf->roi_param[i].roi_abs_flag,
pEncBuf->roi_param[i].sRect.nLeft, pEncBuf->roi_param[i].sRect.nTop,
pEncBuf->roi_param[i].sRect.nWidth, pEncBuf->roi_param[i].sRect.nHeight);
i++;
}
}
return SUCCESS;
}
//QPMap
/*
static ERRORTYPE checkMbMode(PARAM_IN VIDEOENCDATATYPE *pVideoEncData)
{
if (((PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type) || (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)) \
&& pVideoEncData->mMBmode.mMBmodeCtrl.mode_ctrl_en && pVideoEncData->mMBmode.mb_num)
{
//alogd("checkmb mode,num=%d", pVideoEncData->mMBmode.mb_num);
if (pVideoEncData->pCedarV)
{
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamMBModeCtrl, &pVideoEncData->mMBmode.mMBmodeCtrl);
}
}
return SUCCESS;
}
*/
/**
* only for dynamic attribute updating. Take effect immediately.
* must call it during vencoder working.
*/
static ERRORTYPE VideoEncUpdateQp(
PARAM_IN VIDEOENCDATATYPE *pVideoEncData,
PARAM_IN VENC_CHN_ATTR_S *pChnAttr)
{
VENC_CHN_ATTR_S *pCurAttr = &pVideoEncData->mEncChnAttr;
VENC_RC_PARAM_S *pCurRcParam = &pVideoEncData->mRcParam;
ERRORTYPE eError = SUCCESS;
int ret;
if(pCurAttr->RcAttr.mRcMode == pChnAttr->RcAttr.mRcMode)
{
switch(pChnAttr->RcAttr.mRcMode)
{
case VENC_RC_MODE_H264CBR:
{
break;
}
case VENC_RC_MODE_H264VBR:
{
break;
}
case VENC_RC_MODE_H264FIXQP:
{
if(pCurAttr->RcAttr.mAttrH264FixQp.mIQp != pChnAttr->RcAttr.mAttrH264FixQp.mIQp
|| pCurAttr->RcAttr.mAttrH264FixQp.mPQp != pChnAttr->RcAttr.mAttrH264FixQp.mPQp)
{
VencFixQP stH264FixQp;
stH264FixQp.bEnable = 1;
stH264FixQp.nIQp = pChnAttr->RcAttr.mAttrH264FixQp.mIQp;
stH264FixQp.nPQp = pChnAttr->RcAttr.mAttrH264FixQp.mPQp;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264FixQP, (void*)&stH264FixQp);
if (0 == ret)
{
pCurAttr->RcAttr.mAttrH264FixQp.mIQp = pChnAttr->RcAttr.mAttrH264FixQp.mIQp;
pCurAttr->RcAttr.mAttrH264FixQp.mPQp = pChnAttr->RcAttr.mAttrH264FixQp.mPQp;
}
else
{
eError = FAILURE;
}
}
break;
}
case VENC_RC_MODE_H264ABR:
{
if(pCurAttr->RcAttr.mAttrH264Abr.mMaxQp != pChnAttr->RcAttr.mAttrH264Abr.mMaxQp
|| pCurAttr->RcAttr.mAttrH264Abr.mMinQp != pChnAttr->RcAttr.mAttrH264Abr.mMinQp)
{
VencQPRange QpRange;
memset(&QpRange, 0, sizeof(QpRange));
QpRange.nMaxqp = pChnAttr->RcAttr.mAttrH264Abr.mMaxQp;
QpRange.nMinqp = pChnAttr->RcAttr.mAttrH264Abr.mMinQp;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264QPRange, (void*)&QpRange);
if (0 == ret)
{
pCurAttr->RcAttr.mAttrH264Abr.mMaxQp = pChnAttr->RcAttr.mAttrH264Abr.mMaxQp;
pCurAttr->RcAttr.mAttrH264Abr.mMinQp = pChnAttr->RcAttr.mAttrH264Abr.mMinQp;
}
else
{
eError = FAILURE;
}
}
break;
}
case VENC_RC_MODE_H265CBR:
{
break;
}
case VENC_RC_MODE_H265VBR:
{
break;
}
case VENC_RC_MODE_H265FIXQP:
{
if(pCurAttr->RcAttr.mAttrH265FixQp.mIQp != pChnAttr->RcAttr.mAttrH265FixQp.mIQp
|| pCurAttr->RcAttr.mAttrH265FixQp.mPQp != pChnAttr->RcAttr.mAttrH265FixQp.mPQp)
{
VencFixQP stH265FixQp;
stH265FixQp.bEnable = 1;
stH265FixQp.nIQp = pChnAttr->RcAttr.mAttrH265FixQp.mIQp;
stH265FixQp.nPQp = pChnAttr->RcAttr.mAttrH265FixQp.mPQp;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264FixQP, (void*)&stH265FixQp);
if (0 == ret)
{
pCurAttr->RcAttr.mAttrH265FixQp.mIQp = pChnAttr->RcAttr.mAttrH265FixQp.mIQp;
pCurAttr->RcAttr.mAttrH265FixQp.mPQp = pChnAttr->RcAttr.mAttrH265FixQp.mPQp;
}
else
{
eError = FAILURE;
}
}
break;
}
case VENC_RC_MODE_H265ABR:
{
if(pCurAttr->RcAttr.mAttrH265Abr.mMaxQp != pChnAttr->RcAttr.mAttrH265Abr.mMaxQp
|| pCurAttr->RcAttr.mAttrH265Abr.mMinQp != pChnAttr->RcAttr.mAttrH265Abr.mMinQp)
{
VencQPRange QpRange;
memset(&QpRange, 0, sizeof(QpRange));
QpRange.nMaxqp = pChnAttr->RcAttr.mAttrH265Abr.mMaxQp;
QpRange.nMinqp = pChnAttr->RcAttr.mAttrH265Abr.mMinQp;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264QPRange, (void*)&QpRange);
if (0 == ret)
{
pCurAttr->RcAttr.mAttrH265Abr.mMaxQp = pChnAttr->RcAttr.mAttrH265Abr.mMaxQp;
pCurAttr->RcAttr.mAttrH265Abr.mMinQp = pChnAttr->RcAttr.mAttrH265Abr.mMinQp;
}
else
{
eError = FAILURE;
}
}
break;
}
case VENC_RC_MODE_MJPEGFIXQP:
{
if(pCurAttr->RcAttr.mAttrMjpegeFixQp.mQfactor != pChnAttr->RcAttr.mAttrMjpegeFixQp.mQfactor)
{
int jpegQuality = pChnAttr->RcAttr.mAttrMjpegeFixQp.mQfactor;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegQuality, &jpegQuality);
if (0 == ret)
{
pCurAttr->RcAttr.mAttrMjpegeFixQp.mQfactor = pChnAttr->RcAttr.mAttrMjpegeFixQp.mQfactor;
}
else
{
eError = FAILURE;
}
}
break;
}
default:
{
//alogd("fatal error! other rc mode[0x%x] don't need set qp!", pChnAttr->RcAttr.mRcMode);
break;
}
}
}
else
{
aloge("fatal error! DstRcMode[0x%x]!=Cur[0x%x], wrong setting!", pChnAttr->RcAttr.mRcMode, pCurAttr->RcAttr.mRcMode);
eError = ERR_VENC_NOT_SUPPORT;
}
return eError;
}
ERRORTYPE VideoEncGetPortDefinition(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT COMP_PARAM_PORTDEFINITIONTYPE *pPortDef)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
if (pPortDef->nPortIndex == pVideoEncData->sInPortDef.nPortIndex)
{
memcpy(pPortDef, &pVideoEncData->sInPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
}
else if (pPortDef->nPortIndex == pVideoEncData->sOutPortDef.nPortIndex)
{
memcpy(pPortDef, &pVideoEncData->sOutPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
}
else // error
{
eError = ERR_VENC_ILLEGAL_PARAM;
}
return eError;
}
ERRORTYPE VideoEncSetPortDefinition(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_PARAM_PORTDEFINITIONTYPE *pPortDef)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
if (pPortDef->nPortIndex == pVideoEncData->sInPortDef.nPortIndex)
{ // inport definition
memcpy(&pVideoEncData->sInPortDef, pPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
}
else if (pPortDef->nPortIndex == pVideoEncData->sOutPortDef.nPortIndex)
{ // outport definition
memcpy(&pVideoEncData->sOutPortDef, pPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
}
else // error
{
eError = ERR_VENC_ILLEGAL_PARAM;
}
return eError;
}
ERRORTYPE VideoEncGetCompBufferSupplier(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
//find nPortIndex
BOOL bFindFlag = FALSE;
int i;
for(i=0; i<MAX_VENCODER_PORTS; i++)
{
if(pVideoEncData->sPortBufSupplier[i].nPortIndex == pPortBufSupplier->nPortIndex)
{
bFindFlag = TRUE;
memcpy(pPortBufSupplier, &pVideoEncData->sPortBufSupplier[i], sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
break;
}
}
if(bFindFlag)
{
eError = SUCCESS;
}
else
{
eError = ERR_VENC_ILLEGAL_PARAM;
}
return eError;
}
ERRORTYPE VideoEncSetCompBufferSupplier(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
//find nPortIndex
BOOL bFindFlag = FALSE;
int i;
for(i=0; i<MAX_VENCODER_PORTS; i++)
{
if(pVideoEncData->sPortBufSupplier[i].nPortIndex == pPortBufSupplier->nPortIndex)
{
bFindFlag = TRUE;
memcpy(&pVideoEncData->sPortBufSupplier[i], pPortBufSupplier, sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
break;
}
}
if(bFindFlag)
{
eError = SUCCESS;
}
else
{
eError = ERR_VENC_ILLEGAL_PARAM;
}
return eError;
}
ERRORTYPE VideoEncGetMPPChannelInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT MPP_CHN_S *pChn)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
copy_MPP_CHN_S(pChn, &pVideoEncData->mMppChnInfo);
return SUCCESS;
}
ERRORTYPE VideoEncSetMPPChannelInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN MPP_CHN_S *pChn)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
copy_MPP_CHN_S(&pVideoEncData->mMppChnInfo, pChn);
return SUCCESS;
}
ERRORTYPE VideoEncGetChannelFd(PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT int *pChnFd)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pChnFd = pVideoEncData->mOutputFrameNotifyPipeFds[0];
return SUCCESS;
}
ERRORTYPE VideoEncGetTunnelInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT COMP_INTERNAL_TUNNELINFOTYPE *pTunnelInfo)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = ERR_VENC_UNEXIST;
if(pVideoEncData->sInPortTunnelInfo.nPortIndex == pTunnelInfo->nPortIndex)
{
memcpy(pTunnelInfo, &pVideoEncData->sInPortTunnelInfo, sizeof(COMP_INTERNAL_TUNNELINFOTYPE));
eError = SUCCESS;
}
else if(pVideoEncData->sOutPortTunnelInfo.nPortIndex == pTunnelInfo->nPortIndex)
{
memcpy(pTunnelInfo, &pVideoEncData->sOutPortTunnelInfo, sizeof(COMP_INTERNAL_TUNNELINFOTYPE));
eError = SUCCESS;
}
else
{
eError = ERR_VENC_UNEXIST;
}
return eError;
}
ERRORTYPE VideoEncGetChnAttr(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_CHN_ATTR_S *pChnAttr)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (NULL == pChnAttr)
{
aloge("fatal error! invalid input param!");
return ERR_VENC_NULL_PTR;
}
*pChnAttr = pVideoEncData->mUserEncChnAttr;
return SUCCESS;
}
ERRORTYPE VideoEncSetChnAttr(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_CHN_ATTR_S *pChnAttr)
{
int ret;
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (NULL == pChnAttr)
{
aloge("fatal error! invalid input param!");
return ERR_VENC_NULL_PTR;
}
pVideoEncData->mUserEncChnAttr = *pChnAttr;
if (pChnAttr->VeAttr.mOnlineEnable)
{
alogd("vencChn[%d] enable online!", pVideoEncData->mMppChnInfo.mChnId);
}
#if (AWCHIP == AW_V853)
if (TRUE == pChnAttr->EncppAttr.mbEncppEnable)
{
unsigned int SrcPicWidthAlign = AWALIGN(pChnAttr->VeAttr.SrcPicWidth, 16);
unsigned int SrcPicHeightAlign = AWALIGN(pChnAttr->VeAttr.SrcPicHeight, 16);
alogv("VencChn[%d] update SrcPic Width:%d(%d), Height:%d(%d)", pVideoEncData->mMppChnInfo.mChnId, pChnAttr->VeAttr.SrcPicWidth,
SrcPicWidthAlign, pChnAttr->VeAttr.SrcPicHeight, SrcPicHeightAlign);
pChnAttr->VeAttr.SrcPicWidth = SrcPicWidthAlign;
pChnAttr->VeAttr.SrcPicHeight = SrcPicHeightAlign;
}
#endif
if(pVideoEncData->pCedarV && pVideoEncData->mbCedarvVideoEncInitFlag)
{
//when vencLib is exist, only can change dynamic attribute.
//changable param type: BitRate, Qp, IFrameInterval
if(pChnAttr->VeAttr.Type == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
VENC_CHN_ATTR_S *pCurAttr = &pVideoEncData->mEncChnAttr;
if(PT_H264 == pChnAttr->VeAttr.Type || PT_H265 == pChnAttr->VeAttr.Type)
{
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_KEYFRAMEINTERVAL)
{
alogv("[mpp venc debug mode] VencChn[%d] key_frame_interval has been configured.", pVideoEncData->mMppChnInfo.mChnId);
}
else
{
// IFrameInterval control
if (pCurAttr->VeAttr.MaxKeyInterval != pChnAttr->VeAttr.MaxKeyInterval)
{
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamMaxKeyInterval, (void*)&pChnAttr->VeAttr.MaxKeyInterval);
if (0 == ret)
{
pCurAttr->VeAttr.MaxKeyInterval = pChnAttr->VeAttr.MaxKeyInterval;
}
else
{
eError = FAILURE;
alogw("VENCType[%d] update max key interval fail!", pChnAttr->VeAttr.Type);
}
}
}
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_BITRATE)
{
alogv("[mpp venc debug mode] VencChn[%d] bitrate has been configured.", pVideoEncData->mMppChnInfo.mChnId);
}
else
{
// BitRate control
unsigned int nBitRate1 = GetBitRateFromVENC_CHN_ATTR_S(pChnAttr);
unsigned int nBitRate2 = GetBitRateFromVENC_CHN_ATTR_S(pCurAttr);
if(nBitRate1 != nBitRate2)
{
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamBitrate, (void*)&nBitRate1);
if (0 == ret)
{
change_VENC_CHN_ATTR_BitRate(pCurAttr, pChnAttr);
}
else
{
eError = FAILURE;
alogw("VENCType[%d] update bit rate fail!", pChnAttr->VeAttr.Type);
}
}
}
// Qp control
eError = VideoEncUpdateQp(pVideoEncData, pChnAttr);
if (SUCCESS != eError)
{
eError = FAILURE;
alogw("VENCType[%d] update Qp fail!", pChnAttr->VeAttr.Type);
}
// GDC control
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamGdcConfig, &pChnAttr->GdcAttr);
if (0 != ret)
{
eError = FAILURE;
alogw("VENCType[%d] update GDC fail!", pChnAttr->VeAttr.Type);
}
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_ENCPPENABLE)
{
alogv("[mpp venc debug mode] VencChn[%d] encpp_enable has been configured.", pVideoEncData->mMppChnInfo.mChnId);
}
else
{
if (pCurAttr->EncppAttr.mbEncppEnable != pChnAttr->EncppAttr.mbEncppEnable)
{
alogd("veChn[%d], update EncppEnable old=%d new=%d", pVideoEncData->mMppChnInfo.mChnId,
pCurAttr->EncppAttr.mbEncppEnable, pChnAttr->EncppAttr.mbEncppEnable);
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEnableEncppSharp, (void*)&pChnAttr->EncppAttr.mbEncppEnable);
if (0 != ret)
{
eError = FAILURE;
alogw("VencChn[%d] VENCType[%d] update EnableEncppSharp fail!", pVideoEncData->mMppChnInfo.mChnId, pChnAttr->VeAttr.Type);
}
pCurAttr->EncppAttr.mbEncppEnable = pChnAttr->EncppAttr.mbEncppEnable;
}
}
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_VEREFFRAMELBCMODE)
{
alogv("[mpp venc debug mode] VencChn[%d] VeRefFrameLbcMode has been configured.", pVideoEncData->mMppChnInfo.mChnId);
}
else
{
// RecRefLbcMode
if (pCurAttr->VeAttr.mVeRefFrameLbcMode != pChnAttr->VeAttr.mVeRefFrameLbcMode)
{
alogd("veChn[%d], update VeRefFrameLbcMode old=%d new=%d", pVideoEncData->mMppChnInfo.mChnId,
pCurAttr->VeAttr.mVeRefFrameLbcMode, pChnAttr->VeAttr.mVeRefFrameLbcMode);
eVeLbcMode rec_lbc_mode = map_VENC_REF_FRAME_LBC_MODE_E_to_VeRecRefLbcMode(pChnAttr->VeAttr.mVeRefFrameLbcMode);
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSetRecRefLbcMode, (void*)&rec_lbc_mode);
if (0 != ret)
{
eError = FAILURE;
alogw("VencChn[%d] VENCType[%d] update rec_lbc_mode %d fail!", pVideoEncData->mMppChnInfo.mChnId, pChnAttr->VeAttr.Type, rec_lbc_mode);
}
pCurAttr->VeAttr.mVeRefFrameLbcMode = pChnAttr->VeAttr.mVeRefFrameLbcMode;
}
}
}
else if(PT_MJPEG == pChnAttr->VeAttr.Type)
{
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_BITRATE)
{
alogv("[mpp venc debug mode] VencChn[%d] bitrate has been configured.", pVideoEncData->mMppChnInfo.mChnId);
}
else
{
// BitRate control
unsigned int nBitRate1 = GetBitRateFromVENC_CHN_ATTR_S(pChnAttr);
unsigned int nBitRate2 = GetBitRateFromVENC_CHN_ATTR_S(pCurAttr);
if(nBitRate1 != nBitRate2)
{
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamBitrate, (void*)&nBitRate1);
if (0 == ret)
{
change_VENC_CHN_ATTR_BitRate(pCurAttr, pChnAttr);
}
else
{
eError = FAILURE;
alogw("VENCType[%d] update bit rate fail!", pChnAttr->VeAttr.Type);
}
}
}
// Qp control
eError = VideoEncUpdateQp(pVideoEncData, pChnAttr);
if (SUCCESS != eError)
{
eError = FAILURE;
alogw("VENCType[%d] update Qp fail!", pChnAttr->VeAttr.Type);
}
// Dynamic change Video Encoder Picture Size, in StateExecuting just for JPEG and MJPEG.
int iPicEncDstWidth = 0;
int iPicEncDstHeight = 0;
if ((pCurAttr->VeAttr.AttrMjpeg.mPicWidth != pChnAttr->VeAttr.AttrMjpeg.mPicWidth)
|| (pCurAttr->VeAttr.AttrMjpeg.mPicHeight != pChnAttr->VeAttr.AttrMjpeg.mPicHeight))
{
alogd(" PT_MJPEG change encode Picture size from w*h [%d*%d] to w*h [%d*%d]."
,pCurAttr->VeAttr.AttrMjpeg.mPicWidth
,pCurAttr->VeAttr.AttrMjpeg.mPicHeight
,pChnAttr->VeAttr.AttrMjpeg.mPicWidth
,pChnAttr->VeAttr.AttrMjpeg.mPicHeight);
iPicEncDstWidth = pChnAttr->VeAttr.AttrMjpeg.mPicWidth;
iPicEncDstHeight = pChnAttr->VeAttr.AttrMjpeg.mPicHeight;
if ((iPicEncDstWidth > 0) && (iPicEncDstHeight > 0))
{
if(pVideoEncData->mbCedarvVideoEncInitFlag)
{
VencReset(pVideoEncData->pCedarV);
alogd("Venc Reset");
pVideoEncData->mBaseConfig.nDstWidth = iPicEncDstWidth;
pVideoEncData->mBaseConfig.nDstHeight = iPicEncDstHeight;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamUpdateBaseInfo, (void*)&pVideoEncData->mBaseConfig);
if (0 == ret)
{
pCurAttr->VeAttr.AttrMjpeg.mPicWidth = iPicEncDstWidth;
pCurAttr->VeAttr.AttrMjpeg.mPicHeight = iPicEncDstHeight;
}
else
{
eError = FAILURE;
alogw("VENC mjpeg update base info fail!");
}
}
}
else
{
aloge("fatal error! Invalid picture size w*h [%d * %d]", iPicEncDstWidth, iPicEncDstHeight);
//pChnAttr->VeAttr.AttrMjpeg.mPicWidth = pCurAttr->VeAttr.AttrMjpeg.mPicWidth;
//pChnAttr->VeAttr.AttrMjpeg.mPicHeight = pCurAttr->VeAttr.AttrMjpeg.mPicHeight;
eError = ERR_VENC_NOT_SUPPORT;
}
}
// GDC control
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamGdcConfig, &pChnAttr->GdcAttr);
if (0 != ret)
{
eError = FAILURE;
alogw("VENCType[%d] update GDC fail!", pChnAttr->VeAttr.Type);
}
}
else if(PT_JPEG == pChnAttr->VeAttr.Type)
{
// Dynamic change Video Encoder Picture Size, in StateExecuting just for JPEG and MJPEG.
int iPicEncDstWidth = 0;
int iPicEncDstHeight = 0;
if ((pCurAttr->VeAttr.AttrJpeg.PicWidth != pChnAttr->VeAttr.AttrJpeg.PicWidth)
|| (pCurAttr->VeAttr.AttrJpeg.PicHeight != pChnAttr->VeAttr.AttrJpeg.PicHeight))
{
alogd(" PT_JPEG change encode Picture size from w*h [%d*%d] to w*h [%d*%d] ."
,pCurAttr->VeAttr.AttrJpeg.PicWidth
,pCurAttr->VeAttr.AttrJpeg.PicHeight
,pChnAttr->VeAttr.AttrJpeg.PicWidth
,pChnAttr->VeAttr.AttrJpeg.PicHeight);
iPicEncDstWidth = pChnAttr->VeAttr.AttrJpeg.PicWidth;
iPicEncDstHeight = pChnAttr->VeAttr.AttrJpeg.PicHeight;
if ((iPicEncDstWidth > 0) && (iPicEncDstHeight > 0))
{
if(pVideoEncData->mbCedarvVideoEncInitFlag)
{
VencReset(pVideoEncData->pCedarV);
alogd("Venc Reset");
pVideoEncData->mBaseConfig.nDstWidth = iPicEncDstWidth;
pVideoEncData->mBaseConfig.nDstHeight = iPicEncDstHeight;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamUpdateBaseInfo, (void*)&pVideoEncData->mBaseConfig);
if (0 == ret)
{
pCurAttr->VeAttr.AttrJpeg.PicWidth = iPicEncDstWidth;
pCurAttr->VeAttr.AttrJpeg.PicHeight = iPicEncDstHeight;
}
else
{
eError = FAILURE;
alogw("VENC jpeg update base info fail!");
}
}
}
else
{
aloge("fatal error! Invalid picture size w*h [%d * %d]",iPicEncDstWidth ,iPicEncDstHeight);
//pChnAttr->VeAttr.AttrJpeg.PicWidth = pCurAttr->VeAttr.AttrJpeg.PicWidth;
//pChnAttr->VeAttr.AttrJpeg.PicHeight = pCurAttr->VeAttr.AttrJpeg.PicHeight;
eError = ERR_VENC_NOT_SUPPORT;
}
}
// GDC control
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamGdcConfig, &pChnAttr->GdcAttr);
if (0 != ret)
{
eError = FAILURE;
alogw("VENCType[%d] update GDC fail!", pChnAttr->VeAttr.Type);
}
}
else
{
aloge("fatal error! unsupport encode type: %d", pChnAttr->VeAttr.Type);
}
}
else
{
aloge("fatal error! venc type [0x%x]!=[0x%x]!", pChnAttr->VeAttr.Type, pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_NOT_SUPPORT;
}
}
else
{
if (PT_H264 == pChnAttr->VeAttr.Type || PT_H265 == pChnAttr->VeAttr.Type || PT_MJPEG == pChnAttr->VeAttr.Type)
{
if (0 != pVideoEncData->mFrameRateInfo.SrcFrmRate || 0 != pVideoEncData->mFrameRateInfo.DstFrmRate)
{
alogw("VencChn[%d] framerate info is not inited! src:%d, dst:%d", pVideoEncData->mMppChnInfo.mChnId,
pVideoEncData->mFrameRateInfo.SrcFrmRate, pVideoEncData->mFrameRateInfo.DstFrmRate);
}
VENC_FRAME_RATE_S stFrameRateInfo;
ret = GetFrameRateFromVENC_CHN_ATTR_S(pChnAttr, &stFrameRateInfo);
if (ret)
{
alogw("VencChn[%d] Get framerate from ChnAttr failed! ret=%d", pVideoEncData->mMppChnInfo.mChnId, ret);
}
VideoEncSetFrameRate(hComponent, &stFrameRateInfo);
}
pVideoEncData->mEncChnAttr = *pChnAttr;
eError = SUCCESS;
}
if(MM_PIXEL_FORMAT_BUTT == pVideoEncData->mEncChnAttr.VeAttr.PixelFormat)
{
alogd("VEnc component will be in compress mode!");
pVideoEncData->is_compress_source = 1;
}
else
{
pVideoEncData->is_compress_source = 0;
}
return eError;
}
static ERRORTYPE VideoEncGetRcParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_RC_PARAM_S *pRcParam)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pRcParam = pVideoEncData->mRcParam;
return SUCCESS;
}
static ERRORTYPE VideoEncSetRcParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_RC_PARAM_S *pRcParam)
{
int ret;
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV && pVideoEncData->mbCedarvVideoEncInitFlag)
{
//when vencLib is init, only can change dynamic attribute.
//changable param type: Qp
if(VENC_RC_MODE_H264CBR == pVideoEncData->mEncChnAttr.RcAttr.mRcMode)
{
VENC_PARAM_H264_CBR_S *pCurH264Cbr = &pVideoEncData->mRcParam.ParamH264Cbr;
VENC_PARAM_H264_CBR_S *pNewH264Cbr = &pRcParam->ParamH264Cbr;
// Qp control
if(pCurH264Cbr->mMaxQp != pNewH264Cbr->mMaxQp
|| pCurH264Cbr->mMinQp != pNewH264Cbr->mMinQp
|| pCurH264Cbr->mMaxPqp != pNewH264Cbr->mMaxPqp
|| pCurH264Cbr->mMinPqp != pNewH264Cbr->mMinPqp
|| pCurH264Cbr->mQpInit != pNewH264Cbr->mQpInit
|| pCurH264Cbr->mbEnMbQpLimit != pNewH264Cbr->mbEnMbQpLimit)
{
VencQPRange QpRange;
memset(&QpRange, 0, sizeof(QpRange));
QpRange.nMaxqp = pNewH264Cbr->mMaxQp;
QpRange.nMinqp = pNewH264Cbr->mMinQp;
QpRange.nMaxPqp = pNewH264Cbr->mMaxPqp;
QpRange.nMinPqp = pNewH264Cbr->mMinPqp;
QpRange.nQpInit = pNewH264Cbr->mQpInit;
QpRange.bEnMbQpLimit = pNewH264Cbr->mbEnMbQpLimit;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264QPRange, (void*)&QpRange);
if (0 == ret)
{
*pCurH264Cbr = *pNewH264Cbr;
}
else
{
alogw("VENC update Qp fail!");
eError = FAILURE;
}
}
}
else if(VENC_RC_MODE_H264VBR == pVideoEncData->mEncChnAttr.RcAttr.mRcMode)
{
VENC_PARAM_H264_VBR_S *pCurH264Vbr = &pVideoEncData->mRcParam.ParamH264Vbr;
VENC_PARAM_H264_VBR_S *pNewH264Vbr = &pRcParam->ParamH264Vbr;
// Qp control
if(pCurH264Vbr->mMaxQp != pNewH264Vbr->mMaxQp
|| pCurH264Vbr->mMinQp != pNewH264Vbr->mMinQp
|| pCurH264Vbr->mMaxPqp != pNewH264Vbr->mMaxPqp
|| pCurH264Vbr->mMinPqp != pNewH264Vbr->mMinPqp
|| pCurH264Vbr->mQpInit != pNewH264Vbr->mQpInit
|| pCurH264Vbr->mbEnMbQpLimit != pNewH264Vbr->mbEnMbQpLimit)
{
VencQPRange QpRange;
memset(&QpRange, 0, sizeof(QpRange));
QpRange.nMaxqp = pNewH264Vbr->mMaxQp;
QpRange.nMinqp = pNewH264Vbr->mMinQp;
QpRange.nMaxPqp = pNewH264Vbr->mMaxPqp;
QpRange.nMinPqp = pNewH264Vbr->mMinPqp;
QpRange.nQpInit = pNewH264Vbr->mQpInit;
QpRange.bEnMbQpLimit = pNewH264Vbr->mbEnMbQpLimit;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264QPRange, (void*)&QpRange);
if (0 == ret)
{
*pCurH264Vbr = *pNewH264Vbr;
}
else
{
alogw("VENC h264 vbr update Qp fail!");
eError = FAILURE;
}
}
}
else if(VENC_RC_MODE_H264QPMAP == pVideoEncData->mEncChnAttr.RcAttr.mRcMode)
{
VENC_PARAM_H264_QPMAP_S *pCurH264QpMap = &pVideoEncData->mRcParam.ParamH264QpMap;
VENC_PARAM_H264_QPMAP_S *pNewH264QpMap = &pRcParam->ParamH264QpMap;
// Qp control
if(pCurH264QpMap->mMaxQp != pNewH264QpMap->mMaxQp
|| pCurH264QpMap->mMinQp != pNewH264QpMap->mMinQp
|| pCurH264QpMap->mMaxPqp != pNewH264QpMap->mMaxPqp
|| pCurH264QpMap->mMinPqp != pNewH264QpMap->mMinPqp
|| pCurH264QpMap->mQpInit != pNewH264QpMap->mQpInit
|| pCurH264QpMap->mbEnMbQpLimit != pNewH264QpMap->mbEnMbQpLimit)
{
VencQPRange QpRange;
memset(&QpRange, 0, sizeof(QpRange));
QpRange.nMaxqp = pNewH264QpMap->mMaxQp;
QpRange.nMinqp = pNewH264QpMap->mMinQp;
QpRange.nMaxPqp = pNewH264QpMap->mMaxPqp;
QpRange.nMinPqp = pNewH264QpMap->mMinPqp;
QpRange.nQpInit = pNewH264QpMap->mQpInit;
QpRange.bEnMbQpLimit = pNewH264QpMap->mbEnMbQpLimit;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264QPRange, (void*)&QpRange);
if (0 == ret)
{
*pCurH264QpMap = *pNewH264QpMap;
}
else
{
alogw("VENC h264 QpMap update Qp fail!");
eError = FAILURE;
}
}
}
else if(VENC_RC_MODE_H265CBR == pVideoEncData->mEncChnAttr.RcAttr.mRcMode)
{
VENC_PARAM_H265_CBR_S *pCurH265Cbr = &pVideoEncData->mRcParam.ParamH265Cbr;
VENC_PARAM_H265_CBR_S *pNewH265Cbr = &pRcParam->ParamH265Cbr;
// Qp control
if(pCurH265Cbr->mMaxQp != pNewH265Cbr->mMaxQp
|| pCurH265Cbr->mMinQp != pNewH265Cbr->mMinQp
|| pCurH265Cbr->mMaxPqp != pNewH265Cbr->mMaxPqp
|| pCurH265Cbr->mMinPqp != pNewH265Cbr->mMinPqp
|| pCurH265Cbr->mQpInit != pNewH265Cbr->mQpInit
|| pCurH265Cbr->mbEnMbQpLimit != pNewH265Cbr->mbEnMbQpLimit)
{
VencQPRange QpRange;
memset(&QpRange, 0, sizeof(QpRange));
QpRange.nMaxqp = pNewH265Cbr->mMaxQp;
QpRange.nMinqp = pNewH265Cbr->mMinQp;
QpRange.nMaxPqp = pNewH265Cbr->mMaxPqp;
QpRange.nMinPqp = pNewH265Cbr->mMinPqp;
QpRange.nQpInit = pNewH265Cbr->mQpInit;
QpRange.bEnMbQpLimit = pNewH265Cbr->mbEnMbQpLimit;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264QPRange, (void*)&QpRange);
if (0 == ret)
{
*pCurH265Cbr = *pNewH265Cbr;
}
else
{
alogw("VENC h265 update Qp fail!");
eError = FAILURE;
}
}
}
else if(VENC_RC_MODE_H265VBR == pVideoEncData->mEncChnAttr.RcAttr.mRcMode)
{
VENC_PARAM_H265_VBR_S *pCurH265Vbr = &pVideoEncData->mRcParam.ParamH265Vbr;
VENC_PARAM_H265_VBR_S *pNewH265Vbr = &pRcParam->ParamH265Vbr;
// Qp control
if(pCurH265Vbr->mMaxQp != pNewH265Vbr->mMaxQp
|| pCurH265Vbr->mMaxQp != pNewH265Vbr->mMaxQp
|| pCurH265Vbr->mMaxPqp != pNewH265Vbr->mMaxPqp
|| pCurH265Vbr->mMinPqp != pNewH265Vbr->mMinPqp
|| pCurH265Vbr->mQpInit != pNewH265Vbr->mQpInit
|| pCurH265Vbr->mbEnMbQpLimit != pNewH265Vbr->mbEnMbQpLimit)
{
VencQPRange QpRange;
memset(&QpRange, 0, sizeof(QpRange));
QpRange.nMaxqp = pNewH265Vbr->mMaxQp;
QpRange.nMinqp = pNewH265Vbr->mMinQp;
QpRange.nMaxPqp = pNewH265Vbr->mMaxPqp;
QpRange.nMinPqp = pNewH265Vbr->mMinPqp;
QpRange.nQpInit = pNewH265Vbr->mQpInit;
QpRange.bEnMbQpLimit = pNewH265Vbr->mbEnMbQpLimit;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264QPRange, (void*)&QpRange);
if (0 == ret)
{
*pCurH265Vbr = *pNewH265Vbr;
}
else
{
alogw("VENC h265 vbr update Qp fail!");
eError = FAILURE;
}
}
}
else if(VENC_RC_MODE_H265QPMAP == pVideoEncData->mEncChnAttr.RcAttr.mRcMode)
{
VENC_PARAM_H265_QPMAP_S *pCurH265QpMap = &pVideoEncData->mRcParam.ParamH265QpMap;
VENC_PARAM_H265_QPMAP_S *pNewH265QpMap = &pRcParam->ParamH265QpMap;
// Qp control
if(pCurH265QpMap->mMaxQp != pNewH265QpMap->mMaxQp
|| pCurH265QpMap->mMaxQp != pNewH265QpMap->mMaxQp
|| pCurH265QpMap->mMaxPqp != pNewH265QpMap->mMaxPqp
|| pCurH265QpMap->mMinPqp != pNewH265QpMap->mMinPqp
|| pCurH265QpMap->mQpInit != pNewH265QpMap->mQpInit
|| pCurH265QpMap->mbEnMbQpLimit != pNewH265QpMap->mbEnMbQpLimit)
{
VencQPRange QpRange;
memset(&QpRange, 0, sizeof(QpRange));
QpRange.nMaxqp = pNewH265QpMap->mMaxQp;
QpRange.nMinqp = pNewH265QpMap->mMinQp;
QpRange.nMaxPqp = pNewH265QpMap->mMaxPqp;
QpRange.nMinPqp = pNewH265QpMap->mMinPqp;
QpRange.nQpInit = pNewH265QpMap->mQpInit;
QpRange.bEnMbQpLimit = pNewH265QpMap->mbEnMbQpLimit;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264QPRange, (void*)&QpRange);
if (0 == ret)
{
*pCurH265QpMap = *pNewH265QpMap;
}
else
{
alogw("VENC h265 QpMap update Qp fail!");
eError = FAILURE;
}
}
}
else
{
aloge("fatal error! unsupport venc rcMode[0x%x]!", pVideoEncData->mEncChnAttr.RcAttr.mRcMode);
eError = ERR_VENC_NOT_SUPPORT;
}
}
else
{
pVideoEncData->mRcParam = *pRcParam;
eError = SUCCESS;
}
return eError;
}
ERRORTYPE VideoEncGetVencChnState(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_CHN_STAT_S *pChnStat)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pVideoEncData->mStateLock);
if(COMP_StateIdle == pVideoEncData->state || COMP_StateExecuting == pVideoEncData->state)
{
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
//pChnStat->mLeftPics = ENC_FIFO_LEVEL - pVideoEncData->mBufQ.buf_unused;//?
//pChnStat->mLeftPics = 0;
int LeftPicsCounts = 0;
struct list_head *pEntry;
list_for_each(pEntry, &pVideoEncData->mBufQ.mReadyFrameList)
{
++LeftPicsCounts;
}
pChnStat->mLeftPics = LeftPicsCounts;
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
aloge("need implement mLeftStreamBytes!");
VbvInfo vbvInfo;
memset(&vbvInfo, 0, sizeof(VbvInfo));
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamVbvInfo, (void*)&vbvInfo);
pChnStat->mLeftStreamBytes = vbvInfo.coded_size;
pChnStat->mLeftStreamFrames = VencGetValidOutputBufNum(pVideoEncData->pCedarV);
if(pChnStat->mLeftStreamFrames > 0)
{
//because venclib only support one packBuf per frame even multi-slice.
pChnStat->mCurPacks = 1;
}
pthread_mutex_lock(&pVideoEncData->mRecvPicControlLock);
if(TRUE == pVideoEncData->mLimitedFramesFlag)
{
aloge("unsupported temporary!");
pChnStat->mLeftRecvPics = pVideoEncData->mRecvPicParam.mRecvPicNum - pVideoEncData->mCurRecvPicNum; //
pChnStat->mLeftEncPics = pChnStat->mLeftRecvPics + pChnStat->mLeftPics; //
}
else
{
pChnStat->mLeftRecvPics = 0;
pChnStat->mLeftEncPics = 0;
}
pthread_mutex_unlock(&pVideoEncData->mRecvPicControlLock);
eError = SUCCESS;
}
else
{
eError = ERR_VENC_NOT_PERM;
}
pthread_mutex_unlock(&pVideoEncData->mStateLock);
return eError;
}
ERRORTYPE VideoEncGetStream(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_STREAM_S *pStream,
PARAM_IN int nMilliSec)
{
ERRORTYPE eError;
int ret;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(COMP_StateIdle != pVideoEncData->state && COMP_StateExecuting != pVideoEncData->state)
{
alogw("call getStream in wrong state[0x%x]", pVideoEncData->state);
return ERR_VENC_NOT_PERM;
}
if(pVideoEncData->mOutputPortTunnelFlag)
{
aloge("fatal error! can't call getStream() in tunnel mode!");
return ERR_VENC_NOT_PERM;
}
if(pStream->mPackCount<1 || NULL==pStream->mpPack)
{
aloge("fatal error! wrong param[%d],[%p]!", pStream->mPackCount, pStream->mpPack);
return ERR_VENC_ILLEGAL_PARAM;
}
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
_TryToGetOutFrame:
if(!list_empty(&pVideoEncData->mReadyOutFrameList))
{
ENCODER_NODE_T *pEntry = list_first_entry(&pVideoEncData->mReadyOutFrameList, ENCODER_NODE_T, mList);
config_VENC_STREAM_S_by_EncodedStream(pStream, &pEntry->stEncodedStream, pVideoEncData);
list_move_tail(&pEntry->mList, &pVideoEncData->mUsedOutFrameList);
alogv("output stream ID[%d] list: Ready -> Used", pEntry->stEncodedStream.nID);
char tmpRdCh;
read(pVideoEncData->mOutputFrameNotifyPipeFds[0], &tmpRdCh, 1);
eError = SUCCESS;
}
else
{
if(0 == nMilliSec)
{
eError = ERR_VENC_BUF_EMPTY;
}
else if(nMilliSec < 0)
{
pVideoEncData->mWaitOutFrameFlag = TRUE;
while(list_empty(&pVideoEncData->mReadyOutFrameList))
{
pthread_cond_wait(&pVideoEncData->mOutFrameCondition, &pVideoEncData->mOutFrameListMutex);
}
pVideoEncData->mWaitOutFrameFlag = FALSE;
goto _TryToGetOutFrame;
}
else
{
pVideoEncData->mWaitOutFrameFlag = TRUE;
alogv("set waitOutFrameFlag = TRUE");
ret = pthread_cond_wait_timeout(&pVideoEncData->mOutFrameCondition, &pVideoEncData->mOutFrameListMutex, nMilliSec);
if(ETIMEDOUT == ret)
{
alogv("VencChn[%d] wait output frame timeout[%d]ms, ret[%d]", pVideoEncData->mMppChnInfo.mChnId, nMilliSec, ret);
eError = ERR_VENC_BUF_EMPTY;
pVideoEncData->mWaitOutFrameFlag = FALSE;
}
else if(0 == ret)
{
pVideoEncData->mWaitOutFrameFlag = FALSE;
goto _TryToGetOutFrame;
}
else
{
aloge("fatal error! pthread cond wait timeout ret[%d]", ret);
eError = ERR_VENC_BUF_EMPTY;
pVideoEncData->mWaitOutFrameFlag = FALSE;
}
}
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
return eError;
}
ERRORTYPE VideoEncReleaseStream(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_STREAM_S *pStream)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(COMP_StateIdle != pVideoEncData->state && COMP_StateExecuting != pVideoEncData->state)
{
alogw("call getStream in wrong state[0x%x]", pVideoEncData->state);
return ERR_VENC_NOT_PERM;
}
if(pVideoEncData->mOutputPortTunnelFlag)
{
aloge("fatal error! can't call getStream() in tunnel mode!");
return ERR_VENC_NOT_PERM;
}
if(pStream->mPackCount<1 || NULL==pStream->mpPack)
{
aloge("fatal error! wrong param[%d],[%p]!", pStream->mPackCount, pStream->mpPack);
return ERR_VENC_ILLEGAL_PARAM;
}
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if(!list_empty(&pVideoEncData->mUsedOutFrameList))
{
ENCODER_NODE_T *pEntry = list_first_entry(&pVideoEncData->mUsedOutFrameList, ENCODER_NODE_T, mList);
if (pVideoEncData->is_compress_source == 0)
{
if( (pStream->mpPack[0].mpAddr0 == pEntry->stEncodedStream.pBuffer)
&& (pStream->mpPack[0].mpAddr1 == pEntry->stEncodedStream.pBufferExtra)
)
{
VencOutputBuffer stOutputBuffer;
config_VencOutputBuffer_By_EncodedStream(&stOutputBuffer, &pEntry->stEncodedStream);
VencQueueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Used -> Idle", pEntry->stEncodedStream.nID);
eError = SUCCESS;
}
else
{
aloge("fatal error! venc stream[%p][%p] is not match UsedOutFrameList first entry[%p][%p]",
pStream->mpPack[0].mpAddr0, pStream->mpPack[0].mpAddr1,
pEntry->stEncodedStream.pBuffer, pEntry->stEncodedStream.pBufferExtra);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
if( (pStream->mpPack[0].mpAddr0 == pEntry->stEncodedStream.pBuffer)
&& (pStream->mpPack[0].mLen0 == pEntry->stEncodedStream.nBufferLen)
)
{
FRAMEDATATYPE frame;
frame.addrY = (char*)pEntry->stEncodedStream.pBuffer;
frame.info.timeStamp = pEntry->stEncodedStream.nTimeStamp;
frame.info.bufferId = pEntry->stEncodedStream.nID;
frame.info.size = pEntry->stEncodedStream.nBufferLen;
eError = VideoEncBufferReleaseFrame(pVideoEncData->buffer_manager, &frame);
if(eError != SUCCESS)
{
aloge("fatal error! videoEncBufferReleaseFrame fail[%d]", eError);
}
list_add_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
}
else
{
aloge("fatal error! venc stream[%p] is not match UsedOutFrameList first entry[%p]",
pStream->mpPack[0].mpAddr0, pEntry->stEncodedStream.pBuffer);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
if(pVideoEncData->mWaitOutFrameReturnFlag)
{
pVideoEncData->mWaitOutFrameReturnFlag = FALSE;
message_t msg;
msg.command = VEncComp_OutputFrameReturn;
put_message(&pVideoEncData->cmd_queue, &msg);
alogv("VencChn[%d] send message VEncComp OutputFrameReturn", pVideoEncData->mMppChnInfo.mChnId);
}
if (pVideoEncData->mWaitOutFrameFullFlag)
{
int cnt = 0,cnt1 = 0;
struct list_head *pList;
list_for_each(pList, &pVideoEncData->mIdleOutFrameList)
{
cnt++;
}
//added for fixing bug that one new encoded frm is added to readylist when out frm buffer
//is avaliable in case that decode process is suspended when vbv full is full.the new added
//frm registered in readylist will not be fetched out since the operation of app,such as the
// reset operation including the component destruction.
list_for_each(pList, &pVideoEncData->mReadyOutFrameList)
{
cnt1++;
}
if ((cnt+cnt1)>=pVideoEncData->mFrameNodeNum)
{
pthread_cond_signal(&pVideoEncData->mOutFrameFullCondition);
}
}
}
else
{
alogw("Be careful! venc stream[%p][%p] is not find, maybe reset channel before call this function?", pStream->mpPack[0].mpAddr0, pStream->mpPack[0].mpAddr1);
eError = ERR_VENC_ILLEGAL_PARAM;
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
return eError;
}
ERRORTYPE VideoEncGetStreamDuration(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT double *pTimeDuration)
{
//ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pTimeDuration = pVideoEncData->mVbvBufTime;
return SUCCESS;
}
ERRORTYPE VideoEncSetStreamDuration(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN double nTimeDuration)
{
//ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pVideoEncData->mVbvBufTime = nTimeDuration;
return SUCCESS;
}
ERRORTYPE VideoEncGetRoiCfg(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT VENC_ROI_CFG_S *pROI)
{
//ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
VEncRoiCfgNode *pEntry;
pthread_mutex_lock(&pVideoEncData->mRoiLock);
list_for_each_entry(pEntry, &pVideoEncData->mRoiCfgList, mList)
{
if (pROI->Index == pEntry->mROI.Index)
{
memcpy(pROI, &pEntry->mROI, sizeof(VENC_ROI_CFG_S));
return SUCCESS;
}
}
pthread_mutex_unlock(&pVideoEncData->mRoiLock);
return ERR_VENC_NOT_CONFIG;
}
ERRORTYPE VideoEncSetRoiCfg(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_ROI_CFG_S *pRoiCfg)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
BOOL findFlag = FALSE;
if (NULL == pRoiCfg)
{
aloge("fatal error, pRoiCfg is NULL!");
return ERR_VENC_NULL_PTR;
}
//int SrcPicWidth = pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth;
//int SrcPicHeight = pVideoEncData->mEncChnAttr.VeAttr.SrcPicHeight;
SIZE_S dstPicSize;
getPicSizeFromVENC_ATTR_S(&pVideoEncData->mEncChnAttr.VeAttr, &dstPicSize);
if ((pRoiCfg->Rect.X%16!=0) || (pRoiCfg->Rect.Y%16!=0) || (pRoiCfg->Rect.Width%16!=0) || (pRoiCfg->Rect.Height%16!=0)
|| (pRoiCfg->Rect.X+pRoiCfg->Rect.Width > dstPicSize.Width) || (pRoiCfg->Rect.Y+pRoiCfg->Rect.Height > dstPicSize.Height))
{
aloge("fatal error! ROI area setting is wrong with (%d,%d,%d,%d)! They must be integral multiple of 16 and is in SrcPic's internal area!",
pRoiCfg->Rect.X, pRoiCfg->Rect.Y, pRoiCfg->Rect.Width, pRoiCfg->Rect.Height);
return FAILURE;
}
pthread_mutex_lock(&pVideoEncData->mRoiLock);
if (!list_empty(&pVideoEncData->mRoiCfgList))
{
VEncRoiCfgNode *pEntry, *pTemp;
list_for_each_entry_safe(pEntry, pTemp, &pVideoEncData->mRoiCfgList, mList)
{
if (pEntry->mROI.Index == pRoiCfg->Index)
{
findFlag = TRUE;
memcpy(&pEntry->mROI, pRoiCfg, sizeof(VENC_ROI_CFG_S));
break;
}
}
}
if (FALSE == findFlag)
{
VEncRoiCfgNode *pRoiCfgNode = (VEncRoiCfgNode*)malloc(sizeof(VEncRoiCfgNode));
if (pRoiCfgNode != NULL)
{
memcpy(&pRoiCfgNode->mROI, pRoiCfg, sizeof(VENC_ROI_CFG_S));
list_add_tail(&pRoiCfgNode->mList, &pVideoEncData->mRoiCfgList);
}
else
{
aloge("fatal error, malloc RoiCfgNode failed! size=%d", sizeof(VEncRoiCfgNode));
pthread_mutex_unlock(&pVideoEncData->mRoiLock);
return ERR_VENC_NOMEM;
}
}
pthread_mutex_unlock(&pVideoEncData->mRoiLock);
if (pVideoEncData->mOnlineEnableFlag)
{
VencROIConfig sRoiConfig;
memset(&sRoiConfig, 0, sizeof(VencROIConfig));
sRoiConfig.bEnable = pRoiCfg->bEnable;
sRoiConfig.index = pRoiCfg->Index;
sRoiConfig.nQPoffset = pRoiCfg->Qp;
sRoiConfig.roi_abs_flag = pRoiCfg->bAbsQp;
sRoiConfig.sRect.nLeft = pRoiCfg->Rect.X;
sRoiConfig.sRect.nTop = pRoiCfg->Rect.Y;
sRoiConfig.sRect.nWidth = pRoiCfg->Rect.Width;
sRoiConfig.sRect.nHeight = pRoiCfg->Rect.Height;
alogv("ROIConfig en:%d idx[%d]Qp[%d]AbsQp[%d] X[%d]Y[%d]W[%d]H[%d]",
pRoiCfg->bEnable, pRoiCfg->Index, pRoiCfg->Qp, pRoiCfg->bAbsQp,
pRoiCfg->Rect.X, pRoiCfg->Rect.Y, pRoiCfg->Rect.Width, pRoiCfg->Rect.Height);
int ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamROIConfig, &sRoiConfig);
if (0 != ret)
{
aloge("fatal error, ROIConfig failed! ret=%d", ret);
return FAILURE;
}
}
return SUCCESS;
}
ERRORTYPE VideoEncGetRoiBgFrameRate(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_ROIBG_FRAME_RATE_S *pRoiBgFrameRate)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(NULL == pRoiBgFrameRate)
{
aloge("fatal error! null ptr!");
return ERR_VENC_NULL_PTR;
}
pthread_mutex_lock(&pVideoEncData->mRoiLock);
*pRoiBgFrameRate = pVideoEncData->mRoiBgFrameRate;
pthread_mutex_unlock(&pVideoEncData->mRoiLock);
return eError;
}
ERRORTYPE VideoEncSetRoiBgFrameRate(PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_ROIBG_FRAME_RATE_S *pRoiBgFrameRate)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(NULL == pRoiBgFrameRate)
{
aloge("fatal error! null ptr!");
return ERR_VENC_NULL_PTR;
}
pthread_mutex_lock(&pVideoEncData->mRoiLock);
pVideoEncData->mRoiBgFrameRate = *pRoiBgFrameRate;
if(pVideoEncData->pCedarV)
{
if(PT_H264 != pVideoEncData->mEncChnAttr.VeAttr.Type &&
PT_H265 != pVideoEncData->mEncChnAttr.VeAttr.Type)
{
alogw("may be venc[%d] do not support RoiGbFrameRate!", pVideoEncData->mEncChnAttr.VeAttr.Type);
}
VencAlterFrameRateInfo stInfo;
memset(&stInfo, 0, sizeof(VencAlterFrameRateInfo));
stInfo.bEnable = 1;
stInfo.bUseUserSetRoiInfo = 0;
stInfo.sRoiBgFrameRate.nSrcFrameRate = pVideoEncData->mRoiBgFrameRate.mSrcFrmRate;
stInfo.sRoiBgFrameRate.nDstFrameRate = pVideoEncData->mRoiBgFrameRate.mDstFrmRate;
int ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamAlterFrame,(void*)&stInfo);
if(0 == ret)
{
eError = SUCCESS;
}
else
{
aloge("fatal error! VENC IndexParamAlterFrame fail!");
eError = ERR_VENC_BUSY;
}
}
else
{
aloge("fatal error! why cedarc is not created?");
eError = ERR_VENC_NULL_PTR;
}
pthread_mutex_unlock(&pVideoEncData->mRoiLock);
return eError;
}
/*static __inline VENC_OVERLAY_ARGB_TYPE map_BitMapColor_Venc_ARGB_TYPE(VENC_OVERLAY_BITMAP_COLOR_E bitmapColor)
{
VENC_OVERLAY_ARGB_TYPE argb_type;
switch (bitmapColor)
{
case BITMAP_COLOR_ARGB8888:
argb_type = VENC_OVERLAY_ARGB8888;
break;
case BITMAP_COLOR_ARGB4444:
argb_type = VENC_OVERLAY_ARGB4444;
break;
case BITMAP_COLOR_ARGB1555:
argb_type = VENC_OVERLAY_ARGB1555;
break;
default:
argb_type = VENC_OVERLAY_ARGB8888;
break;
}
return argb_type;
}
//from low to high
static ERRORTYPE orderRegionByPriority(VENC_OVERLAY_INFO *pOverlayInfo)
{
int i, j;
int num;
VENC_OVERLAY_REGION_INFO_S tmpRegion;
num = pOverlayInfo->regionNum;
if (num > 1)
{
for (i=0; i < num-1; i++)
{
for (j=0; j< num-i-1; j++)
{
if (pOverlayInfo->region[j].nPriority > pOverlayInfo->region[j+1].nPriority)
{
memcpy(&tmpRegion, &pOverlayInfo->region[j], sizeof(VENC_OVERLAY_REGION_INFO_S));
memcpy(&pOverlayInfo->region[j], &pOverlayInfo->region[j+1], sizeof(VENC_OVERLAY_REGION_INFO_S));
memcpy(&pOverlayInfo->region[j+1], &tmpRegion, sizeof(VENC_OVERLAY_REGION_INFO_S));
}
}
}
}
return SUCCESS;
}*/
static ERRORTYPE VideoEncSetOsd(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencOverlayInfoS *pOverlayInfo)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE*) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (NULL == pOverlayInfo)
{
aloge("fatal error! null pointer in function para");
return FAILURE;
}
pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if (pVideoEncData->pCedarV != NULL && pVideoEncData->mbCedarvVideoEncInitFlag)
{
//pthread_mutex_lock(&pVideoEncData->mVencOverlayLock);
alogv("VencChn[%d] Set OverlayInfo %d-%d-%d-[%d]-%d--%d-%d-%d-%d--%p-%d--%d-%d-%d",
pVideoEncData->mMppChnInfo.mChnId,
pOverlayInfo->argb_type, pOverlayInfo->invert_mode, pOverlayInfo->invert_threshold,
pOverlayInfo->blk_num,
pOverlayInfo->overlayHeaderList[0].overlay_type,
pOverlayInfo->overlayHeaderList[0].start_mb_x,
pOverlayInfo->overlayHeaderList[0].start_mb_y,
pOverlayInfo->overlayHeaderList[0].end_mb_x,
pOverlayInfo->overlayHeaderList[0].end_mb_y,
pOverlayInfo->overlayHeaderList[0].overlay_blk_addr,
pOverlayInfo->overlayHeaderList[0].bitmap_size,
pOverlayInfo->overlayHeaderList[0].bforce_reverse_flag,
pOverlayInfo->overlayHeaderList[0].reverse_unit_mb_w_minus1,
pOverlayInfo->overlayHeaderList[0].reverse_unit_mb_h_minus1);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSetOverlay, (void*)pOverlayInfo);
//pthread_mutex_unlock(&pVideoEncData->mVencOverlayLock);
}
else
{
aloge("fatal error! VencChn[%d] has no vencLib[%p-%d]", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->pCedarV, pVideoEncData->mbCedarvVideoEncInitFlag);
}
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
return SUCCESS;
}
static ERRORTYPE VideoEncSetVEFreq(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN int nFreq)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE*) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pVideoEncData->mVEFreq = nFreq;
if(nFreq > 0)
{
//if(pVideoEncData->mVeOpsS && pVideoEncData->mpVeOpsSelf)
{
alogd("venc set VE freq to [%d]MHz", nFreq);
//CdcVeSetSpeed(pVideoEncData->mVeOpsS, pVideoEncData->mpVeOpsSelf, nFreq);
VencSetFreq(pVideoEncData->pCedarV, nFreq);
}
}
return SUCCESS;
}
ERRORTYPE VideoEncGetH264Vui(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_PARAM_H264_VUI_S *pVuiParam)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->pCedarV)
{
VencH264VideoTiming timeInfo;
memset(&timeInfo, 0, sizeof(VencH264VideoTiming));
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264VideoTiming, &timeInfo);
pVideoEncData->mH264VuiParam.VuiTimeInfo.fixed_frame_rate_flag = timeInfo.fixed_frame_rate_flag;
pVideoEncData->mH264VuiParam.VuiTimeInfo.num_units_in_tick = timeInfo.num_units_in_tick;
pVideoEncData->mH264VuiParam.VuiTimeInfo.time_scale = timeInfo.time_scale;
}
else
{
aloge("fatal error! vencLib is not create?");
}
memcpy(pVuiParam, &pVideoEncData->mH264VuiParam, sizeof(VENC_PARAM_H264_VUI_S));
return SUCCESS;
}
ERRORTYPE VideoEncSetH264Vui(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_PARAM_H264_VUI_S *pVuiParam)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->mbCedarvVideoEncInitFlag)
{
aloge("fatal error! The setting is invalid after CedarvVideoEnc Init.");
return FAILURE;
}
memcpy(&pVideoEncData->mH264VuiParam, pVuiParam, sizeof(VENC_PARAM_H264_VUI_S));
return SUCCESS;
}
ERRORTYPE VideoEncGetH265Vui(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_PARAM_H265_VUI_S *pVuiParam)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->pCedarV)
{
VencH265TimingS timeInfo;
memset(&timeInfo, 0, sizeof(VencH265TimingS));
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamH265Timing, &timeInfo);
pVideoEncData->mH265VuiParam.VuiTimeInfo.timing_info_present_flag = timeInfo.timing_info_present_flag;
pVideoEncData->mH265VuiParam.VuiTimeInfo.num_units_in_tick = timeInfo.num_units_in_tick;
pVideoEncData->mH265VuiParam.VuiTimeInfo.time_scale = timeInfo.time_scale;
pVideoEncData->mH265VuiParam.VuiTimeInfo.num_ticks_poc_diff_one_minus1 = timeInfo.num_ticks_poc_diff_one;
}
else
{
aloge("fatal error! vencLib is not create?");
}
memcpy(pVuiParam, &pVideoEncData->mH265VuiParam, sizeof(VENC_PARAM_H265_VUI_S));
return SUCCESS;
}
ERRORTYPE VideoEncSetH265Vui(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_PARAM_H265_VUI_S *pVuiParam)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->mbCedarvVideoEncInitFlag)
{
aloge("fatal error! The setting is invalid after CedarvVideoEnc Init.");
return FAILURE;
}
memcpy(&pVideoEncData->mH265VuiParam, pVuiParam, sizeof(VENC_PARAM_H265_VUI_S));
return SUCCESS;
}
ERRORTYPE VideoEncGetJpegParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_PARAM_JPEG_S *pJpegParam)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
memcpy(pJpegParam, &pVideoEncData->mJpegParam, sizeof(VENC_PARAM_JPEG_S));
return SUCCESS;
}
ERRORTYPE VideoEncSetJpegParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_PARAM_JPEG_S *pJpegParam)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
if(pVideoEncData->mJpegParam.Qfactor != pJpegParam->Qfactor)
{
alogv("jpeg Qfactor is change[%d]->[%d]", pVideoEncData->mJpegParam.Qfactor, pJpegParam->Qfactor);
}
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegQuality, &pJpegParam->Qfactor);
}
else
{
aloge("fatal error! vencLib is not create?");
}
memcpy(&pVideoEncData->mJpegParam, pJpegParam, sizeof(VENC_PARAM_JPEG_S));
return SUCCESS;
}
ERRORTYPE VideoEncGetJpegExifInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_EXIFINFO_S *pJpegExifInfo)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
memcpy(pJpegExifInfo, &pVideoEncData->mJpegExifInfo, sizeof(VENC_EXIFINFO_S));
return SUCCESS;
}
ERRORTYPE VideoEncSetJpegExifInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_EXIFINFO_S *pJpegExifInfo)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
if(0!=memcmp(&pVideoEncData->mJpegExifInfo, pJpegExifInfo, sizeof(VENC_EXIFINFO_S)))
{
alogv("jpeg exif info is not match.");
}
EXIFInfo stExifInfo;
memset(&stExifInfo, 0, sizeof(EXIFInfo));
memcpy(stExifInfo.CameraMake, pJpegExifInfo->CameraMake, INFO_LENGTH);
memcpy(stExifInfo.CameraModel, pJpegExifInfo->CameraModel, INFO_LENGTH);
memcpy(stExifInfo.DateTime, pJpegExifInfo->DateTime, DATA_TIME_LENGTH);
stExifInfo.ThumbWidth = pJpegExifInfo->ThumbWidth;
stExifInfo.ThumbHeight = pJpegExifInfo->ThumbHeight;
stExifInfo.Orientation = pJpegExifInfo->Orientation;
stExifInfo.ExposureTime.num = pJpegExifInfo->ExposureTime.num; //NUMERATOR32(pJpegExifInfo->fr32ExposureTime);
stExifInfo.ExposureTime.den = pJpegExifInfo->ExposureTime.den; //DENOMINATOR32(pJpegExifInfo->fr32ExposureTime);
stExifInfo.ExposureBiasValue.num = pJpegExifInfo->ExposureBiasValueNum.num;
stExifInfo.ExposureBiasValue.den = pJpegExifInfo->ExposureBiasValueNum.den;
stExifInfo.FNumber.num = pJpegExifInfo->FNumber.num; //NUMERATOR32(pJpegExifInfo->fr32FNumber);
stExifInfo.FNumber.den = pJpegExifInfo->FNumber.den; //DENOMINATOR32(pJpegExifInfo->fr32FNumber);
stExifInfo.ISOSpeed = pJpegExifInfo->ISOSpeed;
stExifInfo.Aperture = pJpegExifInfo->Aperture;
stExifInfo.MaxAperture = pJpegExifInfo->MaxAperture;
stExifInfo.MeteringMode = pJpegExifInfo->MeteringMode;
stExifInfo.LightSource = pJpegExifInfo->LightSource;
stExifInfo.FlashUsed = pJpegExifInfo->FlashUsed;
stExifInfo.FocalLength.num = pJpegExifInfo->FocalLength.num; //NUMERATOR32(pJpegExifInfo->fr32FocalLength);
stExifInfo.FocalLength.den = pJpegExifInfo->FocalLength.den; //DENOMINATOR32(pJpegExifInfo->fr32FocalLength);
stExifInfo.DigitalZoomRatio = pJpegExifInfo->DigitalZoomRatio;
stExifInfo.Contrast = pJpegExifInfo->Contrast;
stExifInfo.Saturation = pJpegExifInfo->Saturation;
stExifInfo.Sharpness = pJpegExifInfo->Sharpness;
stExifInfo.ExposureProgram = pJpegExifInfo->ExposureProgram;
stExifInfo.WhiteBalance = pJpegExifInfo->WhiteBalance;
stExifInfo.ExposureMode = pJpegExifInfo->ExposureMode;
stExifInfo.enableGpsInfo = pJpegExifInfo->enableGpsInfo;
stExifInfo.gps_latitude = pJpegExifInfo->gps_latitude;
stExifInfo.gps_longitude = pJpegExifInfo->gps_longitude;
stExifInfo.gps_altitude = pJpegExifInfo->gps_altitude;
stExifInfo.gps_timestamp = pJpegExifInfo->gps_timestamp;
memcpy(stExifInfo.gpsProcessingMethod, pJpegExifInfo->gpsProcessingMethod, GPS_PROCESS_METHOD_LENGTH);
memcpy(stExifInfo.CameraSerialNum, pJpegExifInfo->CameraSerialNum, 128);
stExifInfo.FocalLengthIn35mmFilm = pJpegExifInfo->FocalLengthIn35mmFilm;
memcpy(stExifInfo.ImageName, pJpegExifInfo->ImageName, 128);
memcpy(stExifInfo.ImageDescription, pJpegExifInfo->ImageDescription, 128);
stExifInfo.thumb_quality = pJpegExifInfo->thumb_quality;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegExifInfo, (void*)&stExifInfo);
}
else
{
aloge("fatal error! vencLib is not create?");
}
memcpy(&pVideoEncData->mJpegExifInfo, pJpegExifInfo, sizeof(VENC_EXIFINFO_S));
return SUCCESS;
}
ERRORTYPE VideoEncGetJpegThumbBuffer(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_JPEG_THUMB_BUFFER_S *pJpegThumbBuffer)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
EXIFInfo exif;
memset(&exif, 0, sizeof(EXIFInfo));
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamJpegExifInfo, &exif);
pJpegThumbBuffer->ThumbAddrVir = exif.ThumbAddrVir;
pJpegThumbBuffer->ThumbLen = exif.ThumbLen;
}
else
{
aloge("fatal error! vencLib is not create?");
}
return SUCCESS;
}
ERRORTYPE VideoEncGetHighPassFilter(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencHighPassFilter *pHightPassFilter)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(NULL != pHightPassFilter)
{
memcpy(pHightPassFilter,&pVideoEncData->mVencHighPassFilter,sizeof(VencHighPassFilter));
}
return SUCCESS;
}
ERRORTYPE VideoEncSetHighPassFilter(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencHighPassFilter *pHightPassFilter)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(NULL != pHightPassFilter)
{
memcpy(&pVideoEncData->mVencHighPassFilter,pHightPassFilter,sizeof(VencHighPassFilter));
}
if(pVideoEncData->pCedarV != NULL)
{
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamHighPassFilter, &pVideoEncData->mVencHighPassFilter);
}
return SUCCESS;
}
ERRORTYPE VideoEncGetDayOrNight(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT int *DayOrNight)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*DayOrNight = pVideoEncData->DayOrNight;
return SUCCESS;
}
ERRORTYPE VideoEncSetDayOrNight(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN int *DayOrNight)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pVideoEncData->DayOrNight = *DayOrNight;
if(pVideoEncData->pCedarV != NULL)
{
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamIsNightCaseFlag, (void*)&pVideoEncData->DayOrNight);
}
return SUCCESS;
}
ERRORTYPE VideoEncGetFrameRate(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_FRAME_RATE_S *pFrameRate)
{
//ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pVideoEncData->mFrameRateLock);
memcpy(pFrameRate, &pVideoEncData->mFrameRateInfo, sizeof(VENC_FRAME_RATE_S));
pthread_mutex_unlock(&pVideoEncData->mFrameRateLock);
return SUCCESS;
}
ERRORTYPE VideoEncSetFrameRate(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_FRAME_RATE_S *pFrameRate)
{
//ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pVideoEncData->mFrameRateLock);
if(pVideoEncData->state == COMP_StateExecuting)// executing state to adjst frm rate,to bkp old frm rate info
{
alogw("vencChn[%d] set_src_frm_rate:%d-%d-%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mFrameRateInfo.DstFrmRate,
pVideoEncData->mFrameRateInfo.SrcFrmRate,pFrameRate->DstFrmRate);
memcpy(&pVideoEncData->mPreFrameRateInfo, &pVideoEncData->mFrameRateInfo, sizeof(VENC_FRAME_RATE_S));
}
memcpy(&pVideoEncData->mFrameRateInfo, pFrameRate, sizeof(VENC_FRAME_RATE_S));
if (pVideoEncData->mFrameRateInfo.DstFrmRate < pVideoEncData->mFrameRateInfo.SrcFrmRate)
{
alogd("Low framerate mode, dst:%d, src:%d, enable soft frame rate control!", pVideoEncData->mFrameRateInfo.DstFrmRate,
pVideoEncData->mFrameRateInfo.SrcFrmRate);
pVideoEncData->mSoftFrameRateCtrl.enable = TRUE;
pVideoEncData->mSoftFrameRateCtrl.mBasePts = -1;
}
else
{
SoftFrameRateCtrlDestroy(&pVideoEncData->mSoftFrameRateCtrl);
if(pVideoEncData->mFrameRateInfo.DstFrmRate > pVideoEncData->mFrameRateInfo.SrcFrmRate)
{
alogd("Be careful! dstFrameRate[%d] > srcFrameRate[%d]", pVideoEncData->mFrameRateInfo.DstFrmRate, pVideoEncData->mFrameRateInfo.SrcFrmRate);
//pVideoEncData->mFrameRateInfo.DstFrmRate = pVideoEncData->mFrameRateInfo.SrcFrmRate;
}
}
if(pVideoEncData->timeLapseEnable)
{
pVideoEncData->mCapTimeLapse.videoFrameIntervalUs = (double)1000000/pVideoEncData->mFrameRateInfo.DstFrmRate;
alogd("Be careful! DstFrameRate is set now. Dst frame interval[%lf]us, timeLapseMode[%d]", pVideoEncData->mCapTimeLapse.videoFrameIntervalUs,
pVideoEncData->mCapTimeLapse.recType);
}
/* Cancel the restriction, in order to adapt to the dynamic frame rate setting of VE Lib. */
// if(pVideoEncData->state == COMP_StateIdle) // allow to adjust params of enc library only at idle state,added for dynamic frame rate condition.
{
if (pVideoEncData->pCedarV != NULL)
{
//if ((PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type) || (PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type))
{
int nDstFrameRate = pFrameRate->DstFrmRate;
alogd("vencChn[%d] set new framerate:%d", pVideoEncData->mMppChnInfo.mChnId, nDstFrameRate);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamFramerate, &nDstFrameRate);
}
}
}
//init roiBgFrameRate now.
pVideoEncData->mRoiBgFrameRate.mSrcFrmRate = pVideoEncData->mFrameRateInfo.DstFrmRate;
pVideoEncData->mRoiBgFrameRate.mDstFrmRate = pVideoEncData->mFrameRateInfo.DstFrmRate;
pthread_mutex_unlock(&pVideoEncData->mFrameRateLock);
return SUCCESS;
}
ERRORTYPE VideoEncGetTimeLapse(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT int64_t* pTimeLapse)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pTimeLapse = pVideoEncData->mCapTimeLapse.capFrameIntervalUs;
return SUCCESS;
}
ERRORTYPE VideoEncSetTimeLapse(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN int64_t* pTimeLapse)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
BOOL bPermitChange = FALSE;
pthread_mutex_lock(&pVideoEncData->mStateLock);
if(COMP_StateIdle == pVideoEncData->state)
{
bPermitChange = TRUE;
}
else if(COMP_StateExecuting == pVideoEncData->state || COMP_StatePause == pVideoEncData->state)
{
if(pVideoEncData->timeLapseEnable && COMP_RECORD_TYPE_TIMELAPSE==pVideoEncData->mCapTimeLapse.recType)
{
if(pTimeLapse!=NULL && *pTimeLapse > 0)
{
bPermitChange = TRUE;
}
}
}
if(FALSE == bPermitChange)
{
alogw("vencComp state[0x%x], timeLapseEnable[%d],type[%d], can't set timelapse!", pVideoEncData->state,
pVideoEncData->timeLapseEnable, pVideoEncData->mCapTimeLapse.recType);
eError = ERR_VENC_NOT_PERM;
goto _err0;
}
pthread_mutex_lock(&pVideoEncData->mCapTimeLapseLock);
if(pTimeLapse!=NULL && *pTimeLapse >= 0)
{
pVideoEncData->timeLapseEnable = TRUE;
pVideoEncData->mCapTimeLapse.capFrameIntervalUs = *pTimeLapse;
//if capFrameIntervalUs is 0, it means every input frame will be encoded, but reset its pts to play as another frame rate.
if(pVideoEncData->mCapTimeLapse.capFrameIntervalUs > 0)
{
pVideoEncData->mCapTimeLapse.recType = COMP_RECORD_TYPE_TIMELAPSE;
}
else
{
pVideoEncData->mCapTimeLapse.recType = COMP_RECORD_TYPE_SLOW;
}
if(pVideoEncData->mFrameRateInfo.DstFrmRate > 0)
{
pVideoEncData->mCapTimeLapse.videoFrameIntervalUs = (double)1000000/pVideoEncData->mFrameRateInfo.DstFrmRate;
}
else
{
pVideoEncData->mCapTimeLapse.videoFrameIntervalUs = 40000;
alogd("Be careful! timeLapseMode is [0x%x]! DstFrameRate is not set now, when set it, calculate dst frame interval!",
pVideoEncData->mCapTimeLapse.recType);
}
//pVideoEncData->mCapTimeLapse.lastCapTimeUs = 0;
//pVideoEncData->mCapTimeLapse.lastTimeStamp = 0;
alogd("SetTimeLapse: captureIntervalUs=%lf, dstFrameIntervalUs=%lf, recType=%d", pVideoEncData->mCapTimeLapse.capFrameIntervalUs,
pVideoEncData->mCapTimeLapse.videoFrameIntervalUs, pVideoEncData->mCapTimeLapse.recType);
}
else
{
pVideoEncData->timeLapseEnable = FALSE;
pVideoEncData->mCapTimeLapse.capFrameIntervalUs = -1;
}
pthread_mutex_unlock(&pVideoEncData->mCapTimeLapseLock);
_err0:
pthread_mutex_unlock(&pVideoEncData->mStateLock);
return eError;
}
ERRORTYPE VideoEncGetCropCfg(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_CROP_CFG_S *pCropCfg)
{
//ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
memcpy(pCropCfg, &pVideoEncData->mCropCfg, sizeof(VENC_CROP_CFG_S));
return SUCCESS;
}
ERRORTYPE VideoEncSetCropCfg(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_CROP_CFG_S *pCropCfg)
{
//ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_CROP)
{
alogd("[mpp venc debug mode] VencChn[%d] crop has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
if (pCropCfg->bEnable && VENC_PIXEL_LBC_AW == map_PIXEL_FORMAT_E_to_VENC_PIXEL_FMT(pVideoEncData->mEncChnAttr.VeAttr.PixelFormat))
{
aloge("fatal error! Exception Case: Crop and LBC Pix can not be used at the same time.");
pVideoEncData->mbExceptionCase = TRUE;
return ERR_VENC_ILLEGAL_PARAM;
}
int SrcPicWidth = pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth;
int SrcPicHeight = pVideoEncData->mEncChnAttr.VeAttr.SrcPicHeight;
if ((pCropCfg->Rect.X%16!=0) || (pCropCfg->Rect.Y%8!=0) || (pCropCfg->Rect.Width%16!=0) || (pCropCfg->Rect.Height%8!=0)
|| (pCropCfg->Rect.X+pCropCfg->Rect.Width > SrcPicWidth) || (pCropCfg->Rect.Y+pCropCfg->Rect.Height > SrcPicHeight))
{
aloge("fatal error! vencChn[%d] CropCfg is wrong with (%d,%d,%d,%d)! Must be multiple of 16, srcPicSize[%dx%d]!",
pVideoEncData->mMppChnInfo.mChnId, pCropCfg->Rect.X, pCropCfg->Rect.Y, pCropCfg->Rect.Width,
pCropCfg->Rect.Height, SrcPicWidth, SrcPicHeight);
return FAILURE;
}
else
{
memcpy(&pVideoEncData->mCropCfg, pCropCfg, sizeof(VENC_CROP_CFG_S));
return SUCCESS;
}
}
ERRORTYPE VideoEncGetStreamBufInfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_STREAM_BUF_INFO_S *pStreamBufInfo)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
alogw("need implement streamBufInfo");
eError = ERR_VENC_NOT_SUPPORT;
}
else
{
aloge("fatal error! video encoder lib is not build currently!");
eError = ERR_VENC_NOT_PERM;
}
return eError;
}
ERRORTYPE VideoEncGetSuperFrameCfg(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_SUPERFRAME_CFG_S* pSuperFrmParam)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pSuperFrmParam = pVideoEncData->mSuperFrmParam;
return SUCCESS;
}
ERRORTYPE VideoEncSetSuperFrameCfg(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_SUPERFRAME_CFG_S* pSuperFrmParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_SUPERFRM)
{
alogd("[mpp venc debug mode] VencChn[%d] super_frame has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
if (pVideoEncData->pCedarV != NULL)
{
if (pVideoEncData->mEncChnAttr.VeAttr.mVeRecRefBufReduceEnable && SUPERFRM_REENCODE == pSuperFrmParam->enSuperFrmMode)
{
aloge("fatal error! Exception Case: VeRecRefBufReduce enable and SUPERFRM_REENCODE can not be used at the same time.");
pVideoEncData->mbExceptionCase = TRUE;
return ERR_VENC_ILLEGAL_PARAM;
}
VencSuperFrameConfig stSuperFrameConfig;
configVencSuperFrameConfigByVENC_SUPERFRAME_CFG_S(&stSuperFrameConfig, pSuperFrmParam);
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSuperFrameConfig, (void*)&stSuperFrameConfig);
}
else
{
aloge("fatal error! why venclib is NULL?");
eError = ERR_VENC_SYS_NOTREADY;
}
pVideoEncData->mSuperFrmParam = *pSuperFrmParam;
return eError;
}
ERRORTYPE VideoEncGetIntraRefreshParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_PARAM_INTRA_REFRESH_S *pIntraRefresh)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pIntraRefresh = pVideoEncData->mEncIntraRefreshParam;
return SUCCESS;
}
ERRORTYPE VideoEncSetIntraRefreshParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_PARAM_INTRA_REFRESH_S *pIntraRefresh)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->pCedarV != NULL)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
VencCyclicIntraRefresh stIntraRefresh;
stIntraRefresh.bEnable = pIntraRefresh->bRefreshEnable;
stIntraRefresh.nBlockNumber = pIntraRefresh->RefreshLineNum;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264CyclicIntraRefresh, (void*)&stIntraRefresh);
pVideoEncData->mEncIntraRefreshParam = *pIntraRefresh;
if(pIntraRefresh->bRefreshEnable)
{ //PIntraRefresh base on PFrameIntraEn, so if enable refresh, must enable PFrameIntraEn.
unsigned char bPFrameIntraEn = 1;
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamPFrameIntraEn, (void*)&bPFrameIntraEn);
switch(pVideoEncData->mEncChnAttr.VeAttr.Type)
{
case PT_H264:
pVideoEncData->mEncChnAttr.VeAttr.AttrH264e.mbPIntraEnable = TRUE;
break;
case PT_H265:
pVideoEncData->mEncChnAttr.VeAttr.AttrH265e.mbPIntraEnable = TRUE;
break;
default:
aloge("fatal error! unsupport encode type:%d", pVideoEncData->mEncChnAttr.VeAttr.Type);
break;
}
}
}
else
{
aloge("fatal error! encodeType[0x%x] don't support intraRefresh", pVideoEncData->mEncChnAttr.VeAttr.Type);
}
}
else
{
aloge("fatal error! why venclib is NULL?");
}
return eError;
}
ERRORTYPE VideoEncGetSmartPParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencSmartFun *pSmartPParam)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pSmartPParam = pVideoEncData->mEncSmartPParam;
return SUCCESS;
}
ERRORTYPE VideoEncSetSmartPParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencSmartFun *pSmartPParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->pCedarV != NULL)
{
if ((PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type) || (PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type))
{
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSmartFuntion, (void*)pSmartPParam);
pVideoEncData->mEncSmartPParam = *pSmartPParam;
}
else
{
aloge("fatal error! encodeType[0x%x] don't support smartP", pVideoEncData->mEncChnAttr.VeAttr.Type);
}
}
else
{
aloge("fatal error! why venclib is NULL?");
}
return eError;
}
ERRORTYPE VideoEncGetBrightness(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencBrightnessS *pBrightness)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pBrightness = pVideoEncData->mEncBrightness;
return SUCCESS;
}
ERRORTYPE VideoEncSetBrightness(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencBrightnessS *pBrightness)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->pCedarV != NULL)
{
if (PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamBright, (void*)pBrightness);
pVideoEncData->mEncBrightness = *pBrightness;
}
else
{
aloge("fatal error! encodeType[0x%x] don't support to set brightness", pVideoEncData->mEncChnAttr.VeAttr.Type);
}
}
else
{
aloge("fatal error! why venclib is NULL?");
}
return eError;
}
ERRORTYPE VideoEncExtraData(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencHeaderData *pVencHeaderData)
{
ERRORTYPE eError = SUCCESS;
VENC_RESULT_TYPE vencRet = VENC_RESULT_ERROR;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(NULL == pVideoEncData->pCedarV)
{
if(pVideoEncData->is_compress_source == 0)
{
CedarvEncInit(pVideoEncData);
}
}
if(pVideoEncData->pCedarV != NULL)
{
pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if(!pVideoEncData->mbCedarvVideoEncInitFlag)
{
eError = CedarvVideoEncInit(pVideoEncData);
if(eError != SUCCESS)
{
aloge("fatal error! vdeclib init fail[0x%x]", eError);
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
goto _exit0;
}
pVideoEncData->mbCedarvVideoEncInitFlag = TRUE;
}
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
vencRet = VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264SPSPPS, (void*)pVencHeaderData); //VencHeaderData spsppsInfo;
}
else if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
vencRet = VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamH265Header, (void*)pVencHeaderData);
}
else
{
alogv("not support other venc type[0x%x]", pVideoEncData->mEncChnAttr.VeAttr.Type);
}
if(vencRet == VENC_RESULT_OK)
{
if(pVencHeaderData->pBuffer!=NULL && pVencHeaderData->nLength > 0)
{
if(NULL == pVideoEncData->mpVencHeaderData)
{
pVideoEncData->mpVencHeaderData = (VencHeaderData*)malloc(sizeof(VencHeaderData));
if(pVideoEncData->mpVencHeaderData)
{
memset(pVideoEncData->mpVencHeaderData, 0, sizeof(VencHeaderData));
}
else
{
aloge("fatal error! malloc fail!");
}
}
if(pVideoEncData->mpVencHeaderData)
{
if(pVideoEncData->mpVencHeaderData->pBuffer)
{
free(pVideoEncData->mpVencHeaderData->pBuffer);
pVideoEncData->mpVencHeaderData->pBuffer = NULL;
}
pVideoEncData->mpVencHeaderData->nLength = 0;
pVideoEncData->mpVencHeaderData->pBuffer = malloc(pVencHeaderData->nLength);
if(pVideoEncData->mpVencHeaderData->pBuffer)
{
memcpy(pVideoEncData->mpVencHeaderData->pBuffer, pVencHeaderData->pBuffer, pVencHeaderData->nLength);
pVideoEncData->mpVencHeaderData->nLength = pVencHeaderData->nLength;
alogv("vencChn[%d] VencHeader %p, size=%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mpVencHeaderData->pBuffer, pVencHeaderData->nLength);
}
else
{
aloge("fatal error! malloc fail!");
}
}
}
}
eError = SUCCESS;
}
else
{
eError = ERR_VENC_NULL_PTR;
//because in compressed mode, analysing key frame is under protection of mOutFrameListMutex.
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if(pVideoEncData->mpVencHeaderData)
{
if(pVideoEncData->mpVencHeaderData->pBuffer != NULL && pVideoEncData->mpVencHeaderData->nLength > 0)
{
pVencHeaderData->pBuffer = pVideoEncData->mpVencHeaderData->pBuffer;
pVencHeaderData->nLength = pVideoEncData->mpVencHeaderData->nLength;
eError = SUCCESS;
}
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
_exit0:
return eError;
}
/**
clear vencChn state.
1. release all input frames.
2. return all output streams to vencLib.
*/
ERRORTYPE VideoEncResetChannel(PARAM_IN COMP_HANDLETYPE hComponent, BOOL bForceReleaseOutFrameInNonTunnelMode)
{
//ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->state != COMP_StateIdle)
{
aloge("fatal error! must reset channel in stateIdle!");
return ERR_VENC_NOT_PERM;
}
VENC_RESULT_TYPE vencRet = VencFlush(pVideoEncData->pCedarV, VENC_FLUSH_INPUT_BUFFER);
if(vencRet != VENC_RESULT_OK)
{
aloge("fatal error! venc flush input buffer fail:%d", vencRet);
}
// return input frames
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
// Both used and using list should be empty, otherwise a warning will be given.
if (!list_empty(&pVideoEncData->mBufQ.mUsedFrameList))
{
int num = 0;
VideoFrameInfoNode *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mBufQ.mUsedFrameList, mList)
{
num++;
}
aloge("fatal error! vencChn[%d] usedFrameList is NOT empty! left frames num = [%d] ", pVideoEncData->mMppChnInfo.mChnId, num);
}
if (!list_empty(&pVideoEncData->mBufQ.mUsingFrameList))
{
int num = 0;
VideoFrameInfoNode *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mBufQ.mUsingFrameList, mList)
{
num++;
}
aloge("fatal error! vencChn[%d] usingFrameList is NOT empty! left frames num = [%d] ", pVideoEncData->mMppChnInfo.mChnId, num);
}
if (!list_empty(&pVideoEncData->mBufQ.mReadyFrameList))
{
int num = 0;
VideoFrameInfoNode *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mBufQ.mReadyFrameList, mList)
{
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
VideoEncSendBackInputFrame(pVideoEncData, &pEntry->VFrame);
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
list_move_tail(&pEntry->mList, &pVideoEncData->mBufQ.mIdleFrameList);
pVideoEncData->mBufQ.buf_unused++;
alogv("release input orig frame ID[%d], list: Ready -> Idle, buf unused[%d]", pEntry->VFrame.mId, pVideoEncData->mBufQ.buf_unused);
num++;
}
alogd("vencChn[%d] return input orig [%d]frames list: Ready -> Idle", pVideoEncData->mMppChnInfo.mChnId, num);
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
pthread_mutex_lock(&pVideoEncData->mRecvPicControlLock);
pVideoEncData->mLimitedFramesFlag = FALSE;
pVideoEncData->mRecvPicParam.mRecvPicNum = 0;
pVideoEncData->mCurRecvPicNum = 0;
pthread_mutex_unlock(&pVideoEncData->mRecvPicControlLock);
// return output frames to venclib.
if(FALSE == pVideoEncData->mOutputPortTunnelFlag)
{
//return output streams to venclib directly. Don't worry about user take streams,
//if user return stream after it, return ERR_VENC_ILLEGAL_PARAM.
//user must guarantee that he return all streams before call this function.
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if(!list_empty(&pVideoEncData->mUsedOutFrameList))
{
if(bForceReleaseOutFrameInNonTunnelMode)
{
alogd("Be careful! non-tunnel mode, force release usedOutFrameList");
int cnt = 0;
ENCODER_NODE_T *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mUsedOutFrameList, mList)
{
VencOutputBuffer stOutputBuffer;
config_VencOutputBuffer_By_EncodedStream(&stOutputBuffer, &pEntry->stEncodedStream);
VencQueueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Used -> Idle", pEntry->stEncodedStream.nID);
cnt++;
}
alogw("Be careful! non-tunnel mode, force release [%d] usedOutFrames", cnt);
}
else
{
alogd("Be careful! non-tunnel mode, usedOutFrameList is not empty, need wait in future.");
}
}
if(!list_empty(&pVideoEncData->mReadyOutFrameList))
{
if(bForceReleaseOutFrameInNonTunnelMode)
{
alogd("Be careful! non-tunnel mode, force release readyOutFrameList");
ENCODER_NODE_T *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mReadyOutFrameList, mList)
{
VencOutputBuffer stOutputBuffer;
config_VencOutputBuffer_By_EncodedStream(&stOutputBuffer, &pEntry->stEncodedStream);
VencQueueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Ready -> Idle", pEntry->stEncodedStream.nID);
char tmpRdCh;
read(pVideoEncData->mOutputFrameNotifyPipeFds[0], &tmpRdCh, 1);
}
}
else
{
alogd("Be careful! non-tunnel mode, readyOutFrameList is not empty, need wait in future.");
}
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
else
{
//verify all output frames back to venclib.
//when component turn to stateIdle, it will guarantee all output frames back.
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if(!list_empty(&pVideoEncData->mUsedOutFrameList))
{
alogd("Be careful! venc usedOutFrameList is not empty in tunnel mode!");
}
if(!list_empty(&pVideoEncData->mReadyOutFrameList))
{
aloge("fatal error! venc mReadyOutFrameList is not empty in tunnel mode!");
}
int cnt = 0;
struct list_head *pList;
list_for_each(pList, &pVideoEncData->mIdleOutFrameList)
{
cnt++;
}
if(cnt != pVideoEncData->mFrameNodeNum)
{
alogw("Be careful! venc output frames count not match [%d]!=[%d]", cnt, pVideoEncData->mFrameNodeNum);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
//alogd("success");
return SUCCESS;
}
ERRORTYPE VideoEncSetRecvPicParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_RECV_PIC_PARAM_S *pRecvPicParam)
{
//ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pVideoEncData->mRecvPicControlLock);
if(pRecvPicParam && pRecvPicParam->mRecvPicNum > 0)
{
pVideoEncData->mLimitedFramesFlag = TRUE;
pVideoEncData->mRecvPicParam = *pRecvPicParam;
}
else
{
pVideoEncData->mLimitedFramesFlag = FALSE;
pVideoEncData->mRecvPicParam.mRecvPicNum = 0;
}
pVideoEncData->mCurRecvPicNum = 0;
pthread_mutex_unlock(&pVideoEncData->mRecvPicControlLock);
return SUCCESS;
}
ERRORTYPE VideoEncGetRefParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_PARAM_REF_S *pstRefParam
)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(!pstRefParam)
{
aloge("fatal error, invalid input param!");
return ERR_VENC_ILLEGAL_PARAM;
}
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
pstRefParam->Base = pVideoEncData->mRefParam.nBase;
pstRefParam->bEnablePred = pVideoEncData->mRefParam.bRefBaseEn;
pstRefParam->Enhance = pVideoEncData->mRefParam.nEnhance;
}
else
{
alogd("the AdvancedRef only support H264 and H265!");
eError = ERR_VENC_NOT_SUPPORT; // no support to jpeg mjpeg.
}
return eError;
}
ERRORTYPE VideoEncSetRefParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_PARAM_REF_S *pstRefParam
)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(!pstRefParam)
{
aloge("fatal error, invalid input param!");
return ERR_VENC_ILLEGAL_PARAM;
}
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
if(pstRefParam->Base > 0)
{
pVideoEncData->mRefParam.bAdvancedRefEn = 1;
}
else
{
pVideoEncData->mRefParam.bAdvancedRefEn = 0;
}
if (pVideoEncData->mEncChnAttr.VeAttr.mVeRecRefBufReduceEnable && 0 != pVideoEncData->mRefParam.bAdvancedRefEn)
{
aloge("fatal error! Exception Case: VeRecRefBufReduce enable and AdvancedRef can not be used at the same time.");
pVideoEncData->mbExceptionCase = TRUE;
eError = ERR_VENC_ILLEGAL_PARAM;
}
pVideoEncData->mRefParam.nBase = pstRefParam->Base;
pVideoEncData->mRefParam.nEnhance = pstRefParam->Enhance;
pVideoEncData->mRefParam.bRefBaseEn = pstRefParam->bEnablePred;
}
else
{
alogd("the AdvancedRef only support H264 and H265!");
eError = ERR_VENC_NOT_SUPPORT; // no support to jpeg mjpeg.
}
return eError;
}
ERRORTYPE VideoEncGetColor2Grey(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_COLOR2GREY_S *pRecvPicParam
)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pRecvPicParam->bColor2Grey = pVideoEncData->mColor2GreyParam.bColor2Grey;
return SUCCESS;
}
ERRORTYPE VideoEncSetColor2Grey(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VENC_COLOR2GREY_S *pRecvPicParam
)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_COLOR2GREY)
{
alogd("[mpp venc debug mode] VencChn[%d] Color2Grey has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
if(!pRecvPicParam)
{
eError = ERR_VENC_ILLEGAL_PARAM;
return eError;
}
if(pVideoEncData->pCedarV)
{
// if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
// {
unsigned char OpenColor2Grey = pRecvPicParam->bColor2Grey?1:0;
alogd("vencChn[%d] set Color2Grey [%d]", pVideoEncData->mMppChnInfo.mChnId, OpenColor2Grey);
if(0 == VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamChmoraGray,(void*)&OpenColor2Grey))
{
pVideoEncData->mColor2GreyParam.bColor2Grey = pRecvPicParam->bColor2Grey;
eError = SUCCESS;
}
else
{
eError = ERR_VENC_BUSY;
}
// }
// else
// {
// alogd("the Color2Grey only support H264 and H265!");
// eError = ERR_VENC_NOT_SUPPORT; // no support to jpeg mjpeg.
// }
}
else
{
eError = ERR_VENC_NULL_PTR;
pVideoEncData->mColor2GreyParam = *pRecvPicParam;
}
return eError;
}
static ERRORTYPE VideoEncGet2DFilter(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT s2DfilterParam *p2DfilterParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (NULL == p2DfilterParam)
{
aloge("fatal error, invalid input param!");
eError = ERR_VENC_ILLEGAL_PARAM;
}
else
{
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
memcpy(p2DfilterParam, &pVideoEncData->m2DfilterParam, sizeof(s2DfilterParam));
}
else
{
alogd("the 2DNR only support H264 and H265!");
eError = ERR_VENC_NOT_SUPPORT; // no support to jpeg mjpeg.
}
}
return eError;
}
static ERRORTYPE VideoEncSet2DFilter(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN s2DfilterParam *p2DfilterParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_2DNR)
{
alogd("[mpp venc debug mode] VencChn[%d] 2dnr has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
if((pVideoEncData->pCedarV != NULL) && (p2DfilterParam != NULL))
{
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParam2DFilter, (void*)p2DfilterParam);
if(ret != 0)
{
aloge("fatal error! set 2DFilter failed!");
eError = FAILURE;
}
memcpy(&pVideoEncData->m2DfilterParam, p2DfilterParam, sizeof(s2DfilterParam));
}
else
{
alogd("the 2DNR only support H264 and H265!");
eError = ERR_VENC_NOT_SUPPORT; // no support to jpeg mjpeg.
}
}
return eError;
}
static ERRORTYPE VideoEncGet3DFilter(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT s3DfilterParam *p3DfilterParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (NULL == p3DfilterParam)
{
aloge("fatal error, invalid input param!");
eError = ERR_VENC_ILLEGAL_PARAM;
}
else
{
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
memcpy(p3DfilterParam, &pVideoEncData->m3DfilterParam, sizeof(s3DfilterParam));
}
else
{
alogd("the 3DNR only support H264 and H265!");
eError = ERR_VENC_NOT_SUPPORT; // no support to jpeg mjpeg.
}
}
return eError;
}
static ERRORTYPE VideoEncSet3DFilter(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN s3DfilterParam *p3DfilterParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_3DNR)
{
alogd("[mpp venc debug mode] VencChn[%d] 3dnr has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
if((pVideoEncData->pCedarV != NULL) && (p3DfilterParam != NULL))
{
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParam3DFilterNew, (void*)p3DfilterParam);
if(ret != 0)
{
aloge("fatal error! set 3DFilterNew failed!");
eError = FAILURE;
}
memcpy(&pVideoEncData->m3DfilterParam, p3DfilterParam, sizeof(s3DfilterParam));
}
else
{
alogd("the 3DNR only support H264 and H265!");
eError = ERR_VENC_NOT_SUPPORT; // no support to jpeg mjpeg.
}
}
return eError;
}
ERRORTYPE VideoEncGetHorizonFlip(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT BOOL *bpHorizonFlipFlag)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*bpHorizonFlipFlag = pVideoEncData->mHorizonFlipFlag;
return SUCCESS;
}
ERRORTYPE VideoEncSetHorizonFlip(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT BOOL bHorizonFlipFlag)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_MIRROR)
{
alogd("[mpp venc debug mode] VencChn[%d] mirror has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
if(pVideoEncData->pCedarV)
{
unsigned int OpenHorizonFlip = bHorizonFlipFlag?1:0;
if(0 == VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamHorizonFlip, (void*)&OpenHorizonFlip))
{
//alogd("set HorizonFlip [%d], in Venchn[%d]", OpenHorizonFlip, pVideoEncData->mMppChnInfo.mChnId);
pVideoEncData->mHorizonFlipFlag = bHorizonFlipFlag;
eError = SUCCESS;
}
else
{
eError = ERR_VENC_BUSY;
}
}
else
{
eError = ERR_VENC_NULL_PTR;
pVideoEncData->mHorizonFlipFlag = bHorizonFlipFlag;
}
return eError;
}
ERRORTYPE VideoEncSetAdaptiveIntraInP(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN BOOL bAdaptiveIntraInPFlag)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
unsigned char OpenAdaptiveIntraInPFlag = bAdaptiveIntraInPFlag?1:0;
if(0 == VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamAdaptiveIntraInP, (void*)&OpenAdaptiveIntraInPFlag))
{
//alogd("set AdaptiveIntraInP [%d], in Venchn[%d]", OpenAdaptiveIntraInPFlag, pVideoEncData->mMppChnInfo.mChnId);
pVideoEncData->mAdaptiveIntraInPFlag = bAdaptiveIntraInPFlag;
eError = SUCCESS;
}
else
{
eError = ERR_VENC_BUSY;
}
}
else
{
aloge("fatal error, the AdaptiveIntraInP just for H265!");
eError = ERR_VENC_NOT_SUPPORT;
}
}
else
{
eError = ERR_VENC_NULL_PTR;
pVideoEncData->mAdaptiveIntraInPFlag = bAdaptiveIntraInPFlag;
}
return eError;
}
ERRORTYPE VideoEncSetH264SVCSkip(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencH264SVCSkip *pSVCSkip)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
if(0 == VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264SVCSkip, (void*)pSVCSkip))
{
alogd("Venchn[%d] enable svcSkip:%d,%d", pVideoEncData->mMppChnInfo.mChnId, pSVCSkip->nTemporalSVC, pSVCSkip->nSkipFrame);
eError = SUCCESS;
}
else
{
eError = ERR_VENC_BUSY;
}
}
else
{
aloge("fatal error, SVC skip is just for H264!");
eError = ERR_VENC_NOT_SUPPORT;
}
}
else
{
aloge("fatal error! encLib is not created?");
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
ERRORTYPE VideoEncEnableNullSkip(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN BOOL bEnable)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
unsigned int bEnableFlag = (unsigned int)bEnable;
if(0 == VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSetNullFrame, (void*)&bEnableFlag))
{
eError = SUCCESS;
}
else
{
aloge("fatal error, vencType[0x%x] don't support nullSkip!", pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_BUSY;
}
}
else
{
aloge("fatal error, venclib is not created!");
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
ERRORTYPE VideoEncEnablePSkip(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN BOOL bEnable)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
unsigned int bEnableFlag = (unsigned int)bEnable;
if(0 == VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSetPSkip, (void*)&bEnableFlag))
{
eError = SUCCESS;
}
else
{
aloge("fatal error, vencType[0x%x] don't support pSkip!", pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_BUSY;
}
}
else
{
aloge("fatal error, venclib is not created!");
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
ERRORTYPE VideoEncForbidDiscardingFrame(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN BOOL bForbid)
{
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
// can NOT change the flag while ven component thread is executing
if (pVideoEncData->state == COMP_StateExecuting)
{
aloge("fatal error, venc component thread is executing, can not change this flag! ");
return FAILURE;
}
if (pVideoEncData->mOnlineEnableFlag && pVideoEncData->mbForbidDiscardingFrame)
{
aloge("fatal error, venc online, ForbidDiscardingFrame is not supported, please use offline channel.");
return FAILURE;
}
alogv("forbidDiscardingFrame flag will change from %d to %d ", pVideoEncData->mbForbidDiscardingFrame, bForbid);
pVideoEncData->mbForbidDiscardingFrame = bForbid;
return SUCCESS;
}
ERRORTYPE VideoEncGetCacheState(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT CacheState* pCacheState)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV != NULL) {
VbvInfo vbvInfo;
eError = VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamVbvInfo, (void*)&vbvInfo);
pCacheState->mValidSize = vbvInfo.coded_size / 1024;
pCacheState->mTotalSize = (vbvInfo.vbv_size-vbvInfo.maxFrameLen) / 1024;
pCacheState->mValidSizePercent = 100 * pCacheState->mValidSize / pCacheState->mTotalSize;
// struct list_head *pList;
// int cnt1 = 0;
// list_for_each(pList, &pVideoEncData->mReadyOutFrameList)
// {
// cnt1++;
// }
// int cnt2 = 0;
// list_for_each(pList, &pVideoEncData->mUsedOutFrameList)
// {
// cnt2++;
// }
// aloge("vbv_buff_st:%d-%d-%d-%d-%d",vbvInfo.coded_size,vbvInfo.vbv_size,vbvInfo.coded_frame_num,cnt1,cnt2);
}
return eError;
}
ERRORTYPE VideoEncRequestIDR(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN BOOL bInstant)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
if(0 == VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamForceKeyFrame, (void*)0))
{
alogd("VeChn[%d] sdk force I frame", pVideoEncData->mMppChnInfo.mChnId);
pVideoEncData->bForceKeyFrameFlag = TRUE;
eError = SUCCESS;
}
else
{
eError = ERR_VENC_BUSY;
}
}
else
{
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncSetMotionSearchParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencMotionSearchParam *pMotionParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if(pVideoEncData->pCedarV && pVideoEncData->mbCedarvVideoEncInitFlag)
{
alogd("VencChn[%d] motion_search en:%d, dis_default_para:%d, hor_region_num:%d, ver_region_num:%d, %d, %.2f, %.2f, %.2f",
pVideoEncData->mMppChnInfo.mChnId, pMotionParam->en_motion_search, pMotionParam->dis_default_para, pMotionParam->hor_region_num,
pMotionParam->ver_region_num, pMotionParam->large_mv_th, pMotionParam->large_mv_ratio_th, pMotionParam->non_zero_mv_ratio_th,
pMotionParam->large_sad_ratio_th);
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamMotionSearchParam, (void*)pMotionParam);
if(ret != 0)
{
aloge("fatal error! check code!");
eError = FAILURE;
}
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
pVideoEncData->mbEnableMotionSearch = FALSE;
if (TRUE == pMotionParam->en_motion_search)
{
if (pVideoEncData->mMotionResult.region)
{
alogw("Be careful! need free mMotionResult.region first!");
free(pVideoEncData->mMotionResult.region);
pVideoEncData->mMotionResult.region = NULL;
}
unsigned int size = 0;
if (0 == pMotionParam->dis_default_para)
size = DEFAULT_MOTION_SEARCH_HOR_REGION_NUM * DEFAULT_MOTION_SEARCH_VER_REGION_NUM * sizeof(VencMotionSearchRegion);
else
size = pMotionParam->hor_region_num * pMotionParam->ver_region_num * sizeof(VencMotionSearchRegion);
if (0 < size)
{
pVideoEncData->mMotionResult.region = (VencMotionSearchRegion*)malloc(size);
if (NULL == pVideoEncData->mMotionResult.region)
{
aloge("fatal error! malloc Region failed! size=%d", size);
eError = ERR_VENC_NOMEM;
}
else
{
memset(pVideoEncData->mMotionResult.region, 0, size);
pVideoEncData->mbEnableMotionSearch = TRUE;
alogv("vencChn[%d] MotionResult region %p, size=%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mMotionResult.region, size);
}
}
else
{
aloge("fatal error! invalid size=%d, hor_region_num:%d, ver_region_num:%d", size, pMotionParam->hor_region_num, pMotionParam->ver_region_num);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
if (pVideoEncData->mMotionResult.region)
{
free(pVideoEncData->mMotionResult.region);
pVideoEncData->mMotionResult.region = NULL;
}
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
else
{
aloge("fatal error! VencChn[%d] is not running", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NOT_PERM;
}
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
return eError;
}
static ERRORTYPE VideoEncGetMotionSearchParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencMotionSearchParam *pMotionParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if(pVideoEncData->pCedarV && pVideoEncData->mbCedarvVideoEncInitFlag)
{
ret = VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamMotionSearchParam, (void*)pMotionParam);
if(ret != 0)
{
aloge("fatal error! check code!");
eError = FAILURE;
}
}
else
{
aloge("fatal error! VencChn[%d] is not running", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NOT_PERM;
}
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
return eError;
}
static ERRORTYPE VideoEncGetMotionSearchResult(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencMotionSearchResult *pMotionResult)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if(pVideoEncData->mbEnableMotionSearch)
{
pMotionResult->total_region_num = pVideoEncData->mMotionResult.total_region_num;
pMotionResult->motion_region_num = pVideoEncData->mMotionResult.motion_region_num;
if (pMotionResult->region && pVideoEncData->mMotionResult.region && pMotionResult->total_region_num)
{
memcpy(pMotionResult->region, pVideoEncData->mMotionResult.region, pMotionResult->total_region_num * sizeof(VencMotionSearchRegion));
}
}
else
{
alogw("Be careful! motion search is not enable!");
eError = ERR_VENC_BUSY;
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
return eError;
}
ERRORTYPE VideoEncSaveBSFile(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencSaveBSFile* pSaveParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if((pVideoEncData->pCedarV != NULL) && (pSaveParam != NULL))
{
if (memcmp(&pVideoEncData->mSaveBSFile, pSaveParam, sizeof(VencSaveBSFile)) == 0)
{
aloge("user set the same SaveBSFile => filename:%s, enable:%u, start_time:%u, end_time:%u", pSaveParam->filename,
pSaveParam->save_bsfile_flag, pSaveParam->save_start_time, pSaveParam->save_end_time);
eError = ERR_VENC_ILLEGAL_PARAM;
}
else
{
memcpy(&pVideoEncData->mSaveBSFile, pSaveParam, sizeof(VencSaveBSFile));
if (pVideoEncData->mbCedarvVideoEncInitFlag)
{
if(VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamSaveBSFile, (void*)pSaveParam) != 0)
{
aloge("update VE SaveBsFile fail!");
eError = ERR_VENC_BUSY;
}
}
}
}
else
{
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
ERRORTYPE VideoEncUpdateProcSet(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VeProcSet* pVeProcSet)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if((pVideoEncData->pCedarV != NULL) && (pVeProcSet != NULL))
{
if (memcmp(&pVideoEncData->mProcSet, pVeProcSet, sizeof(VeProcSet)) == 0)
{
aloge("user set the same VeProcSet => enable:%u, freq:%u, BTTime:%u, FRTime:%u", pVeProcSet->bProcEnable,
pVeProcSet->nProcFreq, pVeProcSet->nStatisBitRateTime, pVeProcSet->nStatisFrRateTime);
eError = ERR_VENC_ILLEGAL_PARAM;
}
else
{
memcpy(&pVideoEncData->mProcSet, pVeProcSet, sizeof(VeProcSet));
if (pVideoEncData->mbCedarvVideoEncInitFlag)
{
//update proc set to catch parame of VE.
if(VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamProcSet, (void*)pVeProcSet) != 0)
{
aloge("update VE proc set fail!");
eError = ERR_VENC_BUSY;
}
}
}
}
else
{
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncCreateEncoder(PARAM_IN COMP_HANDLETYPE hComponent)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pVideoEncData->mStateLock);
if(COMP_StateIdle == pVideoEncData->state)
{
//create encoder
if(NULL == pVideoEncData->pCedarV)
{
if(pVideoEncData->is_compress_source == 0)
{
CedarvEncInit(pVideoEncData);
}
}
else
{
alogw("Be careful! vencLib already exists!");
}
eError = SUCCESS;
}
else
{
aloge("fatal error! venc state[%d] is not allowed to create vencLib!", pVideoEncData->state);
eError = ERR_VENC_INCORRECT_STATE_OPERATION;
}
pthread_mutex_unlock(&pVideoEncData->mStateLock);
return eError;
}
static ERRORTYPE VideoEncDestroyEncoder(PARAM_IN COMP_HANDLETYPE hComponent)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pVideoEncData->mStateLock);
if(COMP_StateIdle == pVideoEncData->state)
{
//output frames must all return! else return FAIL!
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
//wait all outFrame return.
int cnt;
struct list_head *pList;
int cnt1 = 0;
list_for_each(pList, &pVideoEncData->mReadyOutFrameList){cnt1++;}
int cnt2 = 0;
list_for_each(pList, &pVideoEncData->mUsedOutFrameList){cnt2++;}
cnt = 0;
list_for_each(pList, &pVideoEncData->mIdleOutFrameList){cnt++;}
if(cnt + cnt1 + cnt2 != pVideoEncData->mFrameNodeNum)
{
aloge("fatal error! why outFrame number is not match? check code! [%d-%d-%d]!=[%d]", cnt, cnt1, cnt2, pVideoEncData->mFrameNodeNum);
}
if(cnt+cnt1<pVideoEncData->mFrameNodeNum)
{
aloge("fatal error! not all outFrames are back,[%d-%d-%d,%d]! so can't destroy encLib", cnt, cnt1, cnt2, pVideoEncData->mFrameNodeNum);
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
pthread_mutex_unlock(&pVideoEncData->mStateLock);
return ERR_VENC_NOT_PERM;
}
cnt = 0;
while((!list_empty(&pVideoEncData->mReadyOutFrameList)))
{
ENCODER_NODE_T *pEntry = list_first_entry(&pVideoEncData->mReadyOutFrameList, ENCODER_NODE_T, mList);
if (pVideoEncData->is_compress_source == 0)
{
VencOutputBuffer stOutputBuffer;
config_VencOutputBuffer_By_EncodedStream(&stOutputBuffer, &pEntry->stEncodedStream);
VencQueueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Ready -> Idle", pEntry->stEncodedStream.nID);
if(FALSE == pVideoEncData->mOutputPortTunnelFlag)
{
char tmpRdCh;
read(pVideoEncData->mOutputFrameNotifyPipeFds[0], &tmpRdCh, 1);
}
cnt++;
}
}
if(cnt > 0)
{
alogd("release [%d] ready frames before destroy encLib!", cnt);
}
cnt = 0;
list_for_each(pList, &pVideoEncData->mIdleOutFrameList){cnt++;}
if(cnt<pVideoEncData->mFrameNodeNum)
{
aloge("fatal error! wait Venc idleOutFrameList full:%d-%d",cnt,pVideoEncData->mFrameNodeNum);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
//calculate input frames number.
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
cnt = 0;
list_for_each(pList, &pVideoEncData->mBufQ.mReadyFrameList){cnt++;}
alogd("there is [%d] input frames when destroy encLib", cnt);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
//destroy encoder
pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if (pVideoEncData->pCedarV != NULL)
{
VencDestroy(pVideoEncData->pCedarV);
pVideoEncData->mbCedarvVideoEncInitFlag = FALSE;
pVideoEncData->pCedarV = NULL;
VideoEncMBInfoDeinit(&pVideoEncData->mMBInfo);
}
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
eError = SUCCESS;
}
else
{
aloge("fatal error! venc state[%d] is not allowed to destroy vencLib!", pVideoEncData->state);
eError = ERR_VENC_INCORRECT_STATE_OPERATION;
}
pthread_mutex_unlock(&pVideoEncData->mStateLock);
return eError;
}
static ERRORTYPE VideoEncSetIsp2VeParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencIspMotionParam* pParam)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
if (0 == VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamIspMotionParam,(void*)pParam))
{
alogv("Venchn[%d] set Isp2VeParam:%d-%d", pVideoEncData->mMppChnInfo.mChnId, pParam->dis_default_para, pParam->large_mv_th);
eError = SUCCESS;
}
else
{
aloge("fatal error! VenChn[%d] set isp2VeParam[%p] fail!", pVideoEncData->mMppChnInfo.mChnId, pParam);
eError = ERR_VENC_BUSY;
}
}
else
{
aloge("fatal error! VenChn[%d] VeType %d is not support SetIsp2VeParam!", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncGetVe2IspParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencVe2IspParam* pParam)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->pCedarV)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
if (0 == VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamVe2IspParam, (void*)pParam))
{
alogv("VenChn[%d] get Ve2IspParam:%d-%d", pVideoEncData->mMppChnInfo.mChnId,
pParam->mMovingLevelInfo.is_overflow, pParam->mMovingLevelInfo.moving_level_table[0]);
eError = SUCCESS;
}
else
{
aloge("fatal error! VenChn[%d] get Ve2IspParam[%p] fail!", pVideoEncData->mMppChnInfo.mChnId, pParam);
eError = ERR_VENC_BUSY;
}
}
else
{
aloge("fatal error! VenChn[%d] VeType %d is not support GetVe2IspParam!", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncSetWbYuv(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN sWbYuvParam* pWbYuvParam)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->pCedarV)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
if (0 == VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEnableWbYuv,(void*)pWbYuvParam))
{
eError = SUCCESS;
}
else
{
aloge("fatal error! VenChn[%d] set pWbYuvParam[%p] fail!", pVideoEncData->mMppChnInfo.mChnId, pWbYuvParam);
eError = ERR_VENC_BUSY;
}
}
else
{
aloge("fatal error! VenChn[%d] VeType %d is not support EnableWbYuv!", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncGetWbYuv(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencThumbInfo* pThumbInfo)
{
ERRORTYPE eError;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->pCedarV)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
if (0 == VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamGetThumbYUV,(void*)pThumbInfo))
{
eError = SUCCESS;
}
else
{
alogv("fatal error! VenChn[%d] get wb-yuv [%p] fail!", pVideoEncData->mMppChnInfo.mChnId, pThumbInfo);
eError = ERR_VENC_BUSY;
}
}
else
{
aloge("fatal error! VenChn[%d] VeType %d is not support GetWbYuv!", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncSetRegionD3DParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencRegionD3DParam *pRegionD3DParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_REGIOND3D)
{
alogd("[mpp venc debug mode] VencChn[%d] region_d3d has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if(pVideoEncData->pCedarV && pVideoEncData->mbCedarvVideoEncInitFlag)
{
alogd("VencChn[%d] region_d3d en:%d, dis_default_para:%d, result_num:%d, region_num:%dx%d, expand_num:%dx%d,"
"lv_weak_th{%d,%d,%d,%d, %d,%d,%d,%d,%d}, {%.2f,%.2f,%.2f}, %u, {%u,%u,%u}, {%u,%u,%u,%u}",
pVideoEncData->mMppChnInfo.mChnId, pRegionD3DParam->en_region_d3d, pRegionD3DParam->dis_default_para,
pRegionD3DParam->result_num, pRegionD3DParam->hor_region_num, pRegionD3DParam->ver_region_num,
pRegionD3DParam->hor_expand_num, pRegionD3DParam->ver_expand_num,
pRegionD3DParam->lv_weak_th[0], pRegionD3DParam->lv_weak_th[1], pRegionD3DParam->lv_weak_th[2],
pRegionD3DParam->lv_weak_th[3], pRegionD3DParam->lv_weak_th[4], pRegionD3DParam->lv_weak_th[5],
pRegionD3DParam->lv_weak_th[6], pRegionD3DParam->lv_weak_th[7], pRegionD3DParam->lv_weak_th[8],
pRegionD3DParam->zero_mv_rate_th[0], pRegionD3DParam->zero_mv_rate_th[1], pRegionD3DParam->zero_mv_rate_th[2],
pRegionD3DParam->chroma_offset, pRegionD3DParam->static_coef[0], pRegionD3DParam->static_coef[1], pRegionD3DParam->static_coef[2],
pRegionD3DParam->motion_coef[0], pRegionD3DParam->motion_coef[1], pRegionD3DParam->motion_coef[2], pRegionD3DParam->motion_coef[3]);
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamRegionD3DParam, (void*)pRegionD3DParam);
if(ret != 0)
{
aloge("fatal error! check code!");
eError = FAILURE;
}
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
pVideoEncData->mbEnableRegionD3D = FALSE;
if (TRUE == pRegionD3DParam->en_region_d3d)
{
if (pVideoEncData->mRegionD3DResult.region)
{
alogw("Be careful! need free mRegionD3DResult.region first!");
free(pVideoEncData->mRegionD3DResult.region);
pVideoEncData->mRegionD3DResult.region = NULL;
}
unsigned int size = 0;
if (0 == pRegionD3DParam->dis_default_para)
size = DEFAULT_REGION_D3D_HOR_REGION_NUM * DEFAULT_REGION_D3D_VER_REGION_NUM * sizeof(VencRegionD3DRegion);
else
size = pRegionD3DParam->hor_region_num * pRegionD3DParam->ver_region_num * sizeof(VencRegionD3DRegion);
if (0 < size)
{
pVideoEncData->mRegionD3DResult.region = (VencRegionD3DRegion*)malloc(size);
if (NULL == pVideoEncData->mRegionD3DResult.region)
{
aloge("fatal error! malloc Region failed! size=%d", size);
eError = ERR_VENC_NOMEM;
}
else
{
memset(pVideoEncData->mRegionD3DResult.region, 0, size);
pVideoEncData->mbEnableRegionD3D = TRUE;
alogv("vencChn[%d] RegionD3DResult region %p, size=%d", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mRegionD3DResult.region, size);
}
}
else
{
aloge("fatal error! invalid size=%d, hor_region_num:%d, ver_region_num:%d", size, pRegionD3DParam->hor_region_num, pRegionD3DParam->ver_region_num);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
if (pVideoEncData->mRegionD3DResult.region)
{
free(pVideoEncData->mRegionD3DResult.region);
pVideoEncData->mRegionD3DResult.region = NULL;
}
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
memcpy(&pVideoEncData->mRegionD3DParam, pRegionD3DParam, sizeof(VencRegionD3DParam));
}
else
{
aloge("fatal error! VencChn[%d] is not running", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NOT_PERM;
}
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
return eError;
}
static ERRORTYPE VideoEncGetRegionD3DParam(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencRegionD3DParam *pRegionD3DParam)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if(pVideoEncData->pCedarV && pVideoEncData->mbCedarvVideoEncInitFlag)
{
ret = VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamRegionD3DParam, (void*)pRegionD3DParam);
if(ret != 0)
{
aloge("fatal error! check code!");
eError = FAILURE;
}
}
else
{
aloge("fatal error! VencChn[%d] is not running", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NOT_PERM;
}
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
return eError;
}
static ERRORTYPE VideoEncGetRegionD3DResult(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencRegionD3DResult *pRegionD3DResult)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if(pVideoEncData->mbEnableRegionD3D)
{
pRegionD3DResult->total_region_num = pVideoEncData->mRegionD3DResult.total_region_num;
pRegionD3DResult->static_region_num = pVideoEncData->mRegionD3DResult.static_region_num;
if (pRegionD3DResult->region && pVideoEncData->mRegionD3DResult.region && pRegionD3DResult->total_region_num)
{
memcpy(pRegionD3DResult->region, pVideoEncData->mRegionD3DResult.region, pRegionD3DResult->total_region_num * sizeof(VencRegionD3DRegion));
}
}
else
{
alogw("Be careful! region d3d is not enable!");
eError = ERR_VENC_BUSY;
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
return eError;
}
static ERRORTYPE VideoEncSetChromaQPOffset(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN int nChromaQPOffset)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_CHROMAQPOFFSET)
{
alogd("[mpp venc debug mode] VencChn[%d] ChromaQPOffset has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
if (pVideoEncData->pCedarV)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
pVideoEncData->mChromaQPOffset = nChromaQPOffset;
alogd("VencChn[%d] ChromaQPOffset:%d", pVideoEncData->mMppChnInfo.mChnId, nChromaQPOffset);
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamChromaQPOffset, (void*)&nChromaQPOffset);
if(ret != 0)
{
aloge("fatal error! check code!");
eError = FAILURE;
}
}
else
{
alogw("fatal error! VeType %d does not support this api, only H264/H265 supports it.", pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncSetH264ConstraintFlag(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencH264ConstraintFlag *pConstraintFlag)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_H264CONSTRAINTFLAG)
{
alogd("[mpp venc debug mode] VencChn[%d] h264_constraint_flag has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
if (pVideoEncData->pCedarV)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
alogd("VencChn[%d] constraint:%d %d %d %d %d %d", pVideoEncData->mMppChnInfo.mChnId, pConstraintFlag->constraint_0, pConstraintFlag->constraint_1,
pConstraintFlag->constraint_2, pConstraintFlag->constraint_3, pConstraintFlag->constraint_4, pConstraintFlag->constraint_5);
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264ConstraintFlag, (void*)pConstraintFlag);
if(ret != 0)
{
aloge("fatal error! check code!");
eError = FAILURE;
}
}
else
{
alogw("fatal error! VeType %d does not support this api, only H264 supports it.", pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncSetVe2IspD2DLimit(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencVe2IspD2DLimit *pD2DLimit)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->mbMediaDebugFlag & MEDIA_DEBUG_VENC_CONFIG_D2DLIMIT)
{
alogd("[mpp venc debug mode] VencChn[%d] d2d_limit has been configured.", pVideoEncData->mMppChnInfo.mChnId);
return SUCCESS;
}
if (pVideoEncData->pCedarV)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
alogd("VencChn[%d] en_d2d_limit:%d, d2d_level:%d %d %d %d %d %d", pVideoEncData->mMppChnInfo.mChnId, pD2DLimit->en_d2d_limit,
pD2DLimit->d2d_level[0], pD2DLimit->d2d_level[1], pD2DLimit->d2d_level[2],
pD2DLimit->d2d_level[3], pD2DLimit->d2d_level[4], pD2DLimit->d2d_level[5]);
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamVe2IspD2DLimit, (void*)pD2DLimit);
if(ret != 0)
{
aloge("fatal error! check code!");
eError = FAILURE;
}
}
else
{
alogw("fatal error! VeType %d does not support this api, only H264/H265 supports it.", pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncEnableSmallSearchRange(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN BOOL bEnable)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->pCedarV)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
alogd("VencChn[%d] en_small_search_range:%d", pVideoEncData->mMppChnInfo.mChnId, bEnable);
unsigned int bEnableFlag = (unsigned int)bEnable;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEnSmallSearchRange, (void*)&bEnableFlag);
if(ret != 0)
{
aloge("fatal error! VenChn[%d] EnSmallSearchRange failed! ret=%d", pVideoEncData->mMppChnInfo.mChnId, ret);
eError = FAILURE;
}
}
else
{
alogw("fatal error! VeType %d does not support this api, only H264/H265 supports it.", pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncSetRotVe2Isp(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencRotVe2Isp *pRotVe2Isp)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->pCedarV)
{
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
alogd("VencChn[%d] d2d %d lv_th[%d,%d] lv_level[%d,%d], d3d %d lv_th[%d,%d] lv_level[%d,%d]", pVideoEncData->mMppChnInfo.mChnId,
pRotVe2Isp->dis_default_d2d, pRotVe2Isp->d2d_min_lv_th, pRotVe2Isp->d2d_max_lv_th, pRotVe2Isp->d2d_min_lv_level, pRotVe2Isp->d2d_max_lv_level,
pRotVe2Isp->dis_default_d3d, pRotVe2Isp->d3d_min_lv_th, pRotVe2Isp->d3d_max_lv_th, pRotVe2Isp->d3d_min_lv_level, pRotVe2Isp->d3d_max_lv_level);
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamRotVe2Isp, (void*)pRotVe2Isp);
if(ret != 0)
{
aloge("fatal error! VenChn[%d] RotVe2Isp failed! ret=%d", pVideoEncData->mMppChnInfo.mChnId, ret);
eError = FAILURE;
}
}
else
{
alogw("fatal error! VeType %d does not support this api, only H264/H265 supports it.", pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncSetForceConfWin(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN VencForceConfWin *pConfWin)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
if (pVideoEncData->mbCedarvVideoEncInitFlag)
{
aloge("fatal error! The setting is invalid after CedarvVideoEnc Init.");
eError = ERR_VENC_INVALIDSTATE;
}
else
{
alogd("VencChn[%d] ForceConfWin en %d, left %d right %d top %d bottom %d", pVideoEncData->mMppChnInfo.mChnId,
pConfWin->en_force_conf, pConfWin->left_offset, pConfWin->right_offset, pConfWin->top_offset, pConfWin->bottom_offset);
memcpy(&pVideoEncData->mForceConfWin, pConfWin, sizeof(VencForceConfWin));
}
}
else
{
alogw("fatal error! VeType %d does not support this api, only H264/H265 supports it.", pVideoEncData->mEncChnAttr.VeAttr.Type);
eError = ERR_VENC_ILLEGAL_PARAM;
}
return eError;
}
static ERRORTYPE VideoEncGetOutputVencMBSuminfo(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencMBSumInfo *pMbSumInfo)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if ((VENC_RC_MODE_H264QPMAP == pVideoEncData->mEncChnAttr.RcAttr.mRcMode) ||
(VENC_RC_MODE_H265QPMAP == pVideoEncData->mEncChnAttr.RcAttr.mRcMode))
{
aloge("fatal error! QPMAP mode cannot be called!");
eError = FAILURE;
}
else
{
if(pVideoEncData->pCedarV && pVideoEncData->mbCedarvVideoEncInitFlag)
{
ret = VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamMBSumInfoOutput, (void*)pMbSumInfo);
if(ret != 0)
{
aloge("fatal error! Output MBSumInfo failed!");
eError = FAILURE;
}
}
else
{
aloge("fatal error! VencChn[%d] is not running", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NOT_PERM;
}
}
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
return eError;
}
static ERRORTYPE VideoEncGetInsertDataBufStatus(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VENC_BUF_STATUS *pBufStatus)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->mEncChnAttr.VeAttr.Type != PT_MJPEG)
{
aloge("fatal error! get insert data buf status only support MJPEG!");
eError = FAILURE;
}
else
{
if(pVideoEncData->pCedarV && pVideoEncData->mbCedarvVideoEncInitFlag)
{
ret = VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamInsertDataBufStatus, (void*)pBufStatus);
if(ret != 0)
{
aloge("fatal error! get insert data buf status fail!");
eError = FAILURE;
}
}
else
{
aloge("fatal error! VencChn[%d] is not running", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NOT_PERM;
}
}
return eError;
}
static ERRORTYPE VideoEncSetInsertData(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT VencInsertData *pInsertData)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->mEncChnAttr.VeAttr.Type != PT_MJPEG)
{
aloge("fatal error! insert data only support MJPEG!");
eError = FAILURE;
}
else
{
if(pVideoEncData->pCedarV && pVideoEncData->mbCedarvVideoEncInitFlag)
{
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamInsertData, (void*)pInsertData);
if(ret != 0)
{
aloge("fatal error! insert data fail!");
eError = FAILURE;
}
}
else
{
aloge("fatal error! VencChn[%d] is not running", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NOT_PERM;
}
}
return eError;
}
static ERRORTYPE VideoEncSetEncAndDecCase(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN BOOL bEnable)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->pCedarV)
{
alogd("VencChn[%d] set EncAndDecCase:%d", pVideoEncData->mMppChnInfo.mChnId, bEnable);
unsigned int bEnableFlag = (unsigned int)bEnable;
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamEncAndDecCase, (void*)&bEnableFlag);
if(ret != 0)
{
aloge("fatal error! VenChn[%d] EncAndDecCase failed! ret=%d", pVideoEncData->mMppChnInfo.mChnId, ret);
eError = FAILURE;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
static ERRORTYPE VideoEncSetLensMovingMaxQp(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN int nLensMovingMaxQp)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
int ret;
if (pVideoEncData->pCedarV)
{
alogd("VencChn[%d] set LensMovingMaxQp:%d", pVideoEncData->mMppChnInfo.mChnId, nLensMovingMaxQp);
ret = VencSetParameter(pVideoEncData->pCedarV, VENC_IndexParamLensMovingMaxQp, (void*)&nLensMovingMaxQp);
if(ret != 0)
{
aloge("fatal error! VenChn[%d] EncAndDecCase failed! ret=%d", pVideoEncData->mMppChnInfo.mChnId, ret);
eError = FAILURE;
}
}
else
{
aloge("fatal error! VenChn[%d] not init!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NULL_PTR;
}
return eError;
}
/*****************************************************************************/
ERRORTYPE VideoEncSendCommand(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_COMMANDTYPE Cmd,
PARAM_IN unsigned int nParam1,
PARAM_IN void* pCmdData)
{
VIDEOENCDATATYPE *pVideoEncData;
CompInternalMsgType eCmd;
ERRORTYPE eError = SUCCESS;
message_t msg;
alogv("VideoEncSendCommand: %d", Cmd);
pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(!pVideoEncData)
{
eError = ERR_VENC_ILLEGAL_PARAM;
goto COMP_CONF_CMD_FAIL;
}
if (pVideoEncData->state == COMP_StateInvalid)
{
eError = ERR_VENC_SYS_NOTREADY;
goto COMP_CONF_CMD_FAIL;
}
switch (Cmd)
{
case COMP_CommandStateSet:
eCmd = SetState;
break;
case COMP_CommandFlush:
eCmd = Flush;
break;
default:
alogw("impossible comp_command[0x%x]", Cmd);
eCmd = -1;
break;
}
if (eCmd == SetState)
{
if (nParam1 == COMP_StateExecuting)
alogv("set VencChn[%d] Comp StateExecuting", pVideoEncData->mMppChnInfo.mChnId);
if (nParam1 == COMP_StatePause)
alogv("set VencChn[%d] Comp StatePause", pVideoEncData->mMppChnInfo.mChnId);
if (nParam1 == COMP_StateIdle)
alogv("set VencChn[%d] Comp StateIdle", pVideoEncData->mMppChnInfo.mChnId);
if (nParam1 == COMP_StateLoaded)
alogv("set VencChn[%d] Comp StateLoaded", pVideoEncData->mMppChnInfo.mChnId);
}
msg.command = eCmd;
msg.para0 = nParam1;
put_message(&pVideoEncData->cmd_queue, &msg);
alogv("VencChn[%d] send message eCmd=%d", pVideoEncData->mMppChnInfo.mChnId, eCmd);
COMP_CONF_CMD_FAIL:
return eError;
}
/*****************************************************************************/
ERRORTYPE VideoEncGetState(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT COMP_STATETYPE* pState)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pState = pVideoEncData->state;
return eError;
}
/*****************************************************************************/
ERRORTYPE VideoEncSetCallbacks(PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_CALLBACKTYPE* pCallbacks, PARAM_IN void* pAppData)
{
VIDEOENCDATATYPE *pVideoEncData;
ERRORTYPE eError = SUCCESS;
pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(!pVideoEncData || !pCallbacks || !pAppData)
{
eError = ERR_VENC_ILLEGAL_PARAM;
goto COMP_CONF_CMD_FAIL;
}
pVideoEncData->pCallbacks = pCallbacks;
pVideoEncData->pAppData = pAppData;
COMP_CONF_CMD_FAIL: return eError;
}
ERRORTYPE VideoEncGetConfig(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_INDEXTYPE nIndex,
PARAM_IN void* pComponentConfigStructure)
{
ERRORTYPE eError = SUCCESS;
switch(nIndex)
{
case COMP_IndexParamPortDefinition:
{
eError = VideoEncGetPortDefinition(hComponent, (COMP_PARAM_PORTDEFINITIONTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexParamCompBufferSupplier:
{
eError = VideoEncGetCompBufferSupplier(hComponent, (COMP_PARAM_BUFFERSUPPLIERTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorMPPChannelInfo:
{
eError = VideoEncGetMPPChannelInfo(hComponent, (MPP_CHN_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorMPPChannelFd:
{
eError = VideoEncGetChannelFd(hComponent, (int*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorTunnelInfo:
{
eError = VideoEncGetTunnelInfo(hComponent, (COMP_INTERNAL_TUNNELINFOTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencChnAttr:
{
eError = VideoEncGetChnAttr(hComponent, (VENC_CHN_ATTR_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencChnPriority:
{
alogw("unsupported temporary get venc chn priority!");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencChnState:
{
eError = VideoEncGetVencChnState(hComponent, (VENC_CHN_STAT_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencGetStream:
{
VEncStream *pStream = (VEncStream*)pComponentConfigStructure;
eError = VideoEncGetStream(hComponent, pStream->pStream, pStream->nMilliSec);
break;
}
case COMP_IndexVendorVencStreamDuration:
{
eError = VideoEncGetStreamDuration(hComponent, (double*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRoiCfg:
{
eError = VideoEncGetRoiCfg(hComponent, (VENC_ROI_CFG_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRoiBgFrameRate:
{
eError = VideoEncGetRoiBgFrameRate(hComponent, (VENC_ROIBG_FRAME_RATE_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencH264SliceSplit:
{
alogw("need implement H264SliceSplit");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264InterPred:
{
alogw("need implement H264InterPred");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264IntraPred:
{
alogw("need implement H264IntraPred");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Trans:
{
alogw("need implement H264Trans");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Entropy:
{
alogw("need implement H264Entropy");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Poc:
{
alogw("need implement H264Poc");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Dblk:
{
alogw("need implement H264Dblk");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Vui:
{
eError = VideoEncGetH264Vui(hComponent, (VENC_PARAM_H264_VUI_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencH265Vui:
{
eError = VideoEncGetH265Vui(hComponent, (VENC_PARAM_H265_VUI_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencJpegParam:
{
eError = VideoEncGetJpegParam(hComponent, (VENC_PARAM_JPEG_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencJpegExifInfo:
{
eError = VideoEncGetJpegExifInfo(hComponent, (VENC_EXIFINFO_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencJpegThumbBuffer:
{
eError = VideoEncGetJpegThumbBuffer(hComponent, (VENC_JPEG_THUMB_BUFFER_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencMjpegParam:
{
alogw("need implement MjpegParam");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencFrameRate:
{
eError = VideoEncGetFrameRate(hComponent, (VENC_FRAME_RATE_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorTimeLapse:
{
eError = VideoEncGetTimeLapse(hComponent, (int64_t*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRcParam:
{
eError = VideoEncGetRcParam(hComponent, (VENC_RC_PARAM_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRefParam:
{
eError = VideoEncGetRefParam(hComponent, (VENC_PARAM_REF_S *) pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencColor2Grey:
{
eError = VideoEncGetColor2Grey(hComponent, (VENC_COLOR2GREY_S *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencCrop:
{
eError = VideoEncGetCropCfg(hComponent, (VENC_CROP_CFG_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencStreamBufInfo:
{
eError = VideoEncGetStreamBufInfo(hComponent, (VENC_STREAM_BUF_INFO_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRcPriority:
{
alogw("unsupported temporary: VencRcPriority");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265SliceSplit:
{
alogw("need implement H265SliceSplit");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265PredUnit:
{
alogw("need implement H265PredUnit");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265Trans:
{
alogw("need implement H265Trans");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265Entropy:
{
alogw("need implement H265Entropy");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265Dblk:
{
alogw("need implement H265Dblk");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265Sao:
{
alogw("need implement H265Sao");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencFrameLostStrategy:
{
alogw("need implement FrameLostStrategy");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencSuperFrameCfg:
{
eError = VideoEncGetSuperFrameCfg(hComponent, (VENC_SUPERFRAME_CFG_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencIntraRefresh:
{
eError = VideoEncGetIntraRefreshParam(hComponent, (VENC_PARAM_INTRA_REFRESH_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencSmartP:
{
//eError = VideoEncGetSmartPParam(hComponent, (VencSmartFun*)pComponentConfigStructure);
alogw("unsupported: VencSmartP");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencBrightness:
{
eError = VideoEncGetBrightness(hComponent, (VencBrightnessS*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorExtraData:
{
eError = VideoEncExtraData(hComponent, (VencHeaderData*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVenc2DFilter:
{
eError = VideoEncGet2DFilter(hComponent, (s2DfilterParam *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVenc3DFilter:
{
eError = VideoEncGet3DFilter(hComponent, (s3DfilterParam *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencCacheState:
{
eError = VideoEncGetCacheState(hComponent, (CacheState*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencHorizonFlip:
{
eError = VideoEncGetHorizonFlip(hComponent, (BOOL *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencHighPassFilter:
{
eError = VideoEncGetHighPassFilter(hComponent, (VencHighPassFilter*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencDayOrNight:
{
eError = VideoEncGetDayOrNight(hComponent, (int *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencMotionSearchParam:
{
eError = VideoEncGetMotionSearchParam(hComponent, (VencMotionSearchParam*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencMotionSearchResult:
{
eError = VideoEncGetMotionSearchResult(hComponent, (VencMotionSearchResult*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencVe2IspParam:
{
eError = VideoEncGetVe2IspParam(hComponent, (VencVe2IspParam*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencGetWbYuv:
{
eError = VideoEncGetWbYuv(hComponent, (VencThumbInfo*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRegionD3DParam:
{
eError = VideoEncGetRegionD3DParam(hComponent, (VencRegionD3DParam*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRegionD3DResult:
{
eError = VideoEncGetRegionD3DResult(hComponent, (VencRegionD3DResult*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencMBSuminfo:
{
eError = VideoEncGetOutputVencMBSuminfo(hComponent, (VencMBSumInfo *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencGetInsertDataBufStatus:
{
eError = VideoEncGetInsertDataBufStatus(hComponent, (VENC_BUF_STATUS *)pComponentConfigStructure);
break;
}
default:
{
aloge("fatal error! unknown getConfig Index[0x%x]", nIndex);
eError = ERR_VENC_NOT_SUPPORT;
break;
}
}
return eError;
}
ERRORTYPE VideoEncSetConfig(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_INDEXTYPE nIndex,
PARAM_IN void* pComponentConfigStructure)
{
ERRORTYPE eError = SUCCESS;
//int ret;
switch (nIndex)
{
case COMP_IndexParamPortDefinition:
{
eError = VideoEncSetPortDefinition(hComponent, (COMP_PARAM_PORTDEFINITIONTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexParamCompBufferSupplier:
{
eError = VideoEncSetCompBufferSupplier(hComponent, (COMP_PARAM_BUFFERSUPPLIERTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorMPPChannelInfo:
{
eError = VideoEncSetMPPChannelInfo(hComponent, (MPP_CHN_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencChnAttr:
{
eError = VideoEncSetChnAttr(hComponent, (VENC_CHN_ATTR_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencChnPriority:
{
alogw("unsupported temporary set venc chn priority!");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencResetChannel:
{
eError = VideoEncResetChannel(hComponent, TRUE);
break;
}
case COMP_IndexVendorVencRecvPicParam:
{
eError = VideoEncSetRecvPicParam(hComponent, (VENC_RECV_PIC_PARAM_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencReleaseStream:
{
eError = VideoEncReleaseStream(hComponent, (VENC_STREAM_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencUserData:
{
alogw("need implement Insert UserData?");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencStreamDuration: /**< reference: double */
{
eError = VideoEncSetStreamDuration(hComponent, *(double*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRequestIDR:
{
eError = VideoEncRequestIDR(hComponent, *(BOOL*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRoiCfg:
{
eError = VideoEncSetRoiCfg(hComponent, (VENC_ROI_CFG_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRoiBgFrameRate:
{
eError = VideoEncSetRoiBgFrameRate(hComponent, (VENC_ROIBG_FRAME_RATE_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencH264SliceSplit:
{
alogw("need implement H264SliceSplit");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264InterPred:
{
alogw("need implement H264InterPred");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264IntraPred:
{
alogw("need implement H264IntraPred");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Trans:
{
alogw("need implement H264Trans");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Entropy:
{
alogw("need implement H264Entropy");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Poc:
{
alogw("need implement H264Poc");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Dblk:
{
alogw("need implement H264Dblk");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH264Vui:
{
eError = VideoEncSetH264Vui(hComponent, (VENC_PARAM_H264_VUI_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencH265Vui:
{
eError = VideoEncSetH265Vui(hComponent, (VENC_PARAM_H265_VUI_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencJpegParam:
{
eError = VideoEncSetJpegParam(hComponent, (VENC_PARAM_JPEG_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencJpegExifInfo:
{
eError = VideoEncSetJpegExifInfo(hComponent, (VENC_EXIFINFO_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencMjpegParam:
{
alogw("need implement MjpegParam");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencFrameRate:
{
eError = VideoEncSetFrameRate(hComponent, (VENC_FRAME_RATE_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorTimeLapse:
{
eError = VideoEncSetTimeLapse(hComponent, (int64_t*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRcParam:
{
eError = VideoEncSetRcParam(hComponent, (VENC_RC_PARAM_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRefParam:
{
eError = VideoEncSetRefParam(hComponent, (VENC_PARAM_REF_S *) pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencColor2Grey:
{
eError = VideoEncSetColor2Grey(hComponent, (VENC_COLOR2GREY_S *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencCrop:
{
eError = VideoEncSetCropCfg(hComponent, (VENC_CROP_CFG_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencEnableIDR:
{
alogw("need implement EnableIDR");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencRcPriority:
{
alogw("need implement RcPriority");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265SliceSplit:
{
alogw("need implement H265SliceSplit");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265PredUnit:
{
alogw("need implement H265PredUnit");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265Trans:
{
alogw("need implement H265Trans");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265Entropy:
{
alogw("need implement H265Entropy");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265Dblk:
{
alogw("need implement H265Dblk");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencH265Sao:
{
alogw("need implement H265Sao");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencFrameLostStrategy:
{
alogw("need implement FrameLostStrategy");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencSuperFrameCfg:
{
eError = VideoEncSetSuperFrameCfg(hComponent, (VENC_SUPERFRAME_CFG_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencIntraRefresh:
{
eError = VideoEncSetIntraRefreshParam(hComponent, (VENC_PARAM_INTRA_REFRESH_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencSmartP:
{
//eError = VideoEncSetSmartPParam(hComponent, (VencSmartFun*)pComponentConfigStructure);
alogw("unsupported: VencSmartP");
eError = ERR_VENC_NOT_SUPPORT;
break;
}
case COMP_IndexVendorVencBrightness:
{
eError = VideoEncSetBrightness(hComponent, (VencBrightnessS*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencOsd:
{
eError = VideoEncSetOsd(hComponent, (VencOverlayInfoS*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVEFreq:
{
eError = VideoEncSetVEFreq(hComponent, *(int*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVenc2DFilter:
{
eError = VideoEncSet2DFilter(hComponent, (s2DfilterParam *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVenc3DFilter:
{
eError = VideoEncSet3DFilter(hComponent, (s3DfilterParam *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencHorizonFlip:
{
eError = VideoEncSetHorizonFlip(hComponent, *(BOOL *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencAdaptiveIntraInP:
{
eError = VideoEncSetAdaptiveIntraInP(hComponent, *(BOOL *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencH264SVCSkip:
{
eError = VideoEncSetH264SVCSkip(hComponent, (VencH264SVCSkip*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencEnableNullSkip:
{
eError = VideoEncEnableNullSkip(hComponent, *(BOOL *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencEnablePSkip:
{
eError = VideoEncEnablePSkip(hComponent, *(BOOL *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencForbidDiscardingFrame:
{
eError = VideoEncForbidDiscardingFrame(hComponent, *(BOOL *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorSaveBSFile:
{
eError = VideoEncSaveBSFile(hComponent, (VencSaveBSFile*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencProcSet:
{
eError = VideoEncUpdateProcSet(hComponent, (VeProcSet*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencHighPassFilter:
{
eError = VideoEncSetHighPassFilter(hComponent, (VencHighPassFilter*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencDayOrNight:
{
eError = VideoEncSetDayOrNight(hComponent, (int *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencCreateEncoder:
{
eError = VideoEncCreateEncoder(hComponent);
break;
}
case COMP_IndexVendorVencDestroyEncoder:
{
eError = VideoEncDestroyEncoder(hComponent);
break;
}
case COMP_IndexVendorVencMotionSearchParam:
{
eError = VideoEncSetMotionSearchParam(hComponent, (VencMotionSearchParam*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencIsp2VeParam:
{
eError = VideoEncSetIsp2VeParam(hComponent, (VencIspMotionParam*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencSetWbYuv:
{
eError = VideoEncSetWbYuv(hComponent, (sWbYuvParam*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRegionD3DParam:
{
eError = VideoEncSetRegionD3DParam(hComponent, (VencRegionD3DParam*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencChromaQPOffset:
{
eError = VideoEncSetChromaQPOffset(hComponent, *(int *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencH264ConstraintFlag:
{
eError = VideoEncSetH264ConstraintFlag(hComponent, (VencH264ConstraintFlag*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencVe2IspD2DLimit:
{
eError = VideoEncSetVe2IspD2DLimit(hComponent, (VencVe2IspD2DLimit*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencEnableSmallSearchRange:
{
eError = VideoEncEnableSmallSearchRange(hComponent, *(BOOL*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencRotVe2Isp:
{
eError = VideoEncSetRotVe2Isp(hComponent, (VencRotVe2Isp*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencForceConfWin:
{
eError = VideoEncSetForceConfWin(hComponent, (VencForceConfWin*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencSetInsertData:
{
eError = VideoEncSetInsertData(hComponent, (VencInsertData *)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencEncAndDecCase:
{
eError = VideoEncSetEncAndDecCase(hComponent, *(BOOL*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorVencLensMovingMaxQp:
{
eError = VideoEncSetLensMovingMaxQp(hComponent, *(int*)pComponentConfigStructure);
break;
}
default:
{
aloge("unknown Index[0x%x]", nIndex);
eError = ERR_VENC_ILLEGAL_PARAM;
break;
}
}
return eError;
}
ERRORTYPE VideoEncComponentTunnelRequest(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN unsigned int nPort,
PARAM_IN COMP_HANDLETYPE hTunneledComp,
PARAM_IN unsigned int nTunneledPort,
PARAM_INOUT COMP_TUNNELSETUPTYPE* pTunnelSetup)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pVideoEncData->state == COMP_StateExecuting)
{
alogw("Be careful! tunnel request may be some danger in StateExecuting");
}
else if(pVideoEncData->state != COMP_StateIdle)
{
aloge("fatal error! tunnel request can't be in state[0x%x]", pVideoEncData->state);
eError = ERR_VENC_INCORRECT_STATE_OPERATION;
goto COMP_CMD_FAIL;
}
COMP_PARAM_PORTDEFINITIONTYPE *pPortDef;
COMP_INTERNAL_TUNNELINFOTYPE *pPortTunnelInfo;
COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier;
BOOL bFindFlag;
int i;
bFindFlag = FALSE;
if(pVideoEncData->sInPortDef.nPortIndex == nPort)
{
pPortDef = &pVideoEncData->sInPortDef;
bFindFlag = TRUE;
}
if(FALSE == bFindFlag)
{
if(pVideoEncData->sOutPortDef.nPortIndex == nPort)
{
pPortDef = &pVideoEncData->sOutPortDef;
bFindFlag = TRUE;
}
}
if(FALSE == bFindFlag)
{
aloge("fatal error! portIndex[%d] wrong!", nPort);
eError = ERR_VENC_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
bFindFlag = FALSE;
if(pVideoEncData->sInPortTunnelInfo.nPortIndex == nPort)
{
pPortTunnelInfo = &pVideoEncData->sInPortTunnelInfo;
bFindFlag = TRUE;
}
if(FALSE == bFindFlag)
{
if(pVideoEncData->sOutPortTunnelInfo.nPortIndex == nPort)
{
pPortTunnelInfo = &pVideoEncData->sOutPortTunnelInfo;
bFindFlag = TRUE;
}
}
if(FALSE == bFindFlag)
{
aloge("fatal error! portIndex[%d] wrong!", nPort);
eError = ERR_VENC_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
bFindFlag = FALSE;
for(i=0; i<MAX_VENCODER_PORTS; i++)
{
if(pVideoEncData->sPortBufSupplier[i].nPortIndex == nPort)
{
pPortBufSupplier = &pVideoEncData->sPortBufSupplier[i];
bFindFlag = TRUE;
break;
}
}
if(FALSE == bFindFlag)
{
aloge("fatal error! portIndex[%d] wrong!", nPort);
eError = ERR_VENC_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
pPortTunnelInfo->nPortIndex = nPort;
pPortTunnelInfo->hTunnel = hTunneledComp;
pPortTunnelInfo->nTunnelPortIndex = nTunneledPort;
pPortTunnelInfo->eTunnelType = (pPortDef->eDomain == COMP_PortDomainOther) ? TUNNEL_TYPE_CLOCK : TUNNEL_TYPE_COMMON;
if(NULL==hTunneledComp && 0==nTunneledPort && NULL==pTunnelSetup)
{
alogd("omx_core cancel setup tunnel on port[%d]", nPort);
eError = SUCCESS;
if(pPortDef->eDir == COMP_DirOutput)
{
pVideoEncData->mOutputPortTunnelFlag = FALSE;
alogd("set outputPortTunnelFlag = FALSE");
}
else
{
pVideoEncData->mInputPortTunnelFlag = FALSE;
alogd("set inputPortTunnelFlag = FALSE");
}
goto COMP_CMD_FAIL;
}
if(pPortDef->eDir == COMP_DirOutput)
{
if (pVideoEncData->mOutputPortTunnelFlag) {
aloge("VEnc_Comp outport already bind, why bind again?!");
eError = FAILURE;
goto COMP_CMD_FAIL;
}
pTunnelSetup->nTunnelFlags = 0;
pTunnelSetup->eSupplier = pPortBufSupplier->eBufferSupplier;
pVideoEncData->mOutputPortTunnelFlag = TRUE;
alogd("set outputPortTunnelFlag = TRUE");
}
else
{
if (pVideoEncData->mInputPortTunnelFlag) {
aloge("VEnc_Comp inport already bind, why bind again?!");
eError = FAILURE;
goto COMP_CMD_FAIL;
}
//Check the data compatibility between the ports using one or more GetParameter calls.
//B checks if its input port is compatible with the output port of component A.
COMP_PARAM_PORTDEFINITIONTYPE out_port_def;
out_port_def.nPortIndex = nTunneledPort;
((MM_COMPONENTTYPE*)hTunneledComp)->GetConfig(hTunneledComp, COMP_IndexParamPortDefinition, &out_port_def);
if(out_port_def.eDir != COMP_DirOutput)
{
aloge("fatal error! tunnel port index[%d] direction is not output!", nTunneledPort);
eError = ERR_VENC_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
pPortDef->format = out_port_def.format;
//The component B informs component A about the final result of negotiation.
if(pTunnelSetup->eSupplier != pPortBufSupplier->eBufferSupplier)
{
alogw("Low probability! use input portIndex[%d] buffer supplier[%d] as final!", nPort, pPortBufSupplier->eBufferSupplier);
pTunnelSetup->eSupplier = pPortBufSupplier->eBufferSupplier;
}
COMP_PARAM_BUFFERSUPPLIERTYPE oSupplier;
oSupplier.nPortIndex = nTunneledPort;
((MM_COMPONENTTYPE*)hTunneledComp)->GetConfig(hTunneledComp, COMP_IndexParamCompBufferSupplier, &oSupplier);
oSupplier.eBufferSupplier = pTunnelSetup->eSupplier;
((MM_COMPONENTTYPE*)hTunneledComp)->SetConfig(hTunneledComp, COMP_IndexParamCompBufferSupplier, &oSupplier);
pVideoEncData->mInputPortTunnelFlag = TRUE;
alogd("set inputPortTunnelFlag = TRUE");
}
COMP_CMD_FAIL:
return eError;
}
/**
@return
SUCCESS: accept frame, and store frame in internal list, comp will return frame in internal thread.
ERR_VENC_INCORRECT_STATE_OPERATION: deny frame, only accept frame in executing state.
ERR_VENC_SYS_NOTREADY: deny frame.
ERR_VENC_BUF_FULL: deny frame.
ERR_VENC_EXIST: accept frame, use frame done, and don't store frame in internal list. return frame now.
ERR_VENC_NOMEM: no memory. deny frame.
ERR_VENC_NOT_PERM: deny frame because this frame is not meet condition, e.g., debug_ignore, time-lapse, softFrameRate.
ERR_VENC_NOT_SUPPORT: online mode not support EmptyThisBuffer().
*/
ERRORTYPE VideoEncEmptyThisBuffer(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_BUFFERHEADERTYPE* pBuffer)
{
ERRORTYPE eError = SUCCESS;
VIDEOENCDATATYPE *pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pthread_mutex_lock(&pVideoEncData->mStateLock);
if (pVideoEncData->state != COMP_StateExecuting)
{
alogd("vencChn[%d] send frame when venc state[0x%x] is not executing", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->state);
eError = ERR_VENC_INCORRECT_STATE_OPERATION;
goto _exit0;
}
if (pVideoEncData->mOnlineEnableFlag)
{
if (FALSE == pVideoEncData->mInputPortTunnelFlag)
{
aloge("fatal error! venc online, The input of venc component must be bound to virvi component.");
}
else
{
aloge("fatal error! venc online, csi&ve driver transfer data directly, please check virvi component.");
}
pthread_mutex_unlock(&pVideoEncData->mStateLock);
return ERR_VENC_NOT_SUPPORT;
}
pthread_mutex_lock(&pVideoEncData->mRecvPicControlLock);
if(pVideoEncData->mLimitedFramesFlag && pVideoEncData->mCurRecvPicNum >= pVideoEncData->mRecvPicParam.mRecvPicNum) //reach max recv number
{
alogd("the venc cahnnel[%d] had received %d frame, it is enough!", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mCurRecvPicNum);
eError = ERR_VENC_BUF_FULL;
goto ERROR;
}
VIDEO_FRAME_INFO_S *pEncFrame;
if(pVideoEncData->mInputPortTunnelFlag)
{
pEncFrame = (VIDEO_FRAME_INFO_S*)pBuffer->pOutputPortPrivate;
}
else
{
pEncFrame = (VIDEO_FRAME_INFO_S*)pBuffer->pAppPrivate;
}
int mModId = (pEncFrame->VFrame.mWhoSetFlag >> 16) & 0xFF;
if (MOD_ID_VIU == mModId)
{
pVideoEncData->mvipp_id = (pEncFrame->VFrame.mWhoSetFlag >> 8) & 0xFF;
}
else
{
pVideoEncData->mvipp_id = -1;
}
if(pVideoEncData->is_compress_source == 0)
{
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if(list_empty(&pVideoEncData->mBufQ.mIdleFrameList))
{
alogd("VencChn[%d] idle frame is empty, malloc one!", pVideoEncData->mMppChnInfo.mChnId);
if(pVideoEncData->mBufQ.buf_unused!=0)
{
aloge("fatal error! VencChn[%d] buf_unused must be zero!", pVideoEncData->mMppChnInfo.mChnId);
}
VideoFrameInfoNode *pNode = (VideoFrameInfoNode*)malloc(sizeof(VideoFrameInfoNode));
if(NULL == pNode)
{
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
aloge("fatal error! VencChn[%d] malloc fail!", pVideoEncData->mMppChnInfo.mChnId);
eError = ERR_VENC_NOMEM;
goto ERROR;
}
list_add_tail(&pNode->mList, &pVideoEncData->mBufQ.mIdleFrameList);
pVideoEncData->mBufQ.buf_unused++;
}
if (pVideoEncData->csi_first_frame)
{
pVideoEncData->csi_base_time = pEncFrame->VFrame.mpts;
pVideoEncData->mPrevInputPts = pEncFrame->VFrame.mpts;
pVideoEncData->mCapTimeLapse.lastCapTimeUs = 0;
pVideoEncData->mCapTimeLapse.lastTimeStamp = 0;
pVideoEncData->csi_first_frame = FALSE;
int64_t tm1 = CDX_GetSysTimeUsMonotonic();
// if(1920 == pEncFrame->VFrame.mWidth && 1080 == pEncFrame->VFrame.mHeight)//(pVideoEncData == g_pVideoEncData[0])
// {
// alogw("avsync_first video frame pts[%lld]us,tm1[%lld]us, vSize[%dx%d]",
// pEncFrame->VFrame.mpts, tm1, pEncFrame->VFrame.mWidth, pEncFrame->VFrame.mHeight);
// }
alogv("VencChn[%d]: first video frame pts[%lld]us,tm1[%lld]us, vSize[%dx%d], frmId[%d,%d]",
pVideoEncData->mMppChnInfo.mChnId, pEncFrame->VFrame.mpts, tm1, pEncFrame->VFrame.mWidth,
pEncFrame->VFrame.mHeight, pEncFrame->mId,pEncFrame->VFrame.mFramecnt);
}
if (pEncFrame->VFrame.mpts - pVideoEncData->mPrevInputPts >= 300*1000)
{
if(PT_JPEG != pVideoEncData->mEncChnAttr.VeAttr.Type)
{
alogd("Be careful! VencChn[%d] vencInputPts[%lld]-[%lld]=[%lld]us, vBufSize[%dx%d]", pVideoEncData->mMppChnInfo.mChnId,
pEncFrame->VFrame.mpts, pVideoEncData->mPrevInputPts, pEncFrame->VFrame.mpts - pVideoEncData->mPrevInputPts,
pEncFrame->VFrame.mWidth, pEncFrame->VFrame.mHeight);
}
}
pVideoEncData->mPrevInputPts = pEncFrame->VFrame.mpts;
bool bDiscardFrame = false;
//judge if discard this frame.
if (pVideoEncData->mbDebug_IgnoreAllFrame) // for debug
{
bDiscardFrame = true;
}
else
{
if (pVideoEncData->timeLapseEnable) //time-lapse
{
if (pVideoEncData->mbForbidDiscardingFrame)
{
aloge("fatal error! vencChn[%d] type:%d, forbid discarding frame!", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
}
pthread_mutex_lock(&pVideoEncData->mCapTimeLapseLock);
if (pVideoEncData->mCapTimeLapse.recType == COMP_RECORD_TYPE_TIMELAPSE)
{
if (pVideoEncData->mCapTimeLapse.lastCapTimeUs > 0
&& pEncFrame->VFrame.mpts < pVideoEncData->mCapTimeLapse.lastCapTimeUs + pVideoEncData->mCapTimeLapse.capFrameIntervalUs)
{
// The original input frame has been returned and no further processing is required.
bDiscardFrame = true;
}
}
pthread_mutex_unlock(&pVideoEncData->mCapTimeLapseLock);
}
else
{
pthread_mutex_lock(&pVideoEncData->mFrameRateLock);
if (pVideoEncData->mSoftFrameRateCtrl.enable) //soft frame rate
{
if (pVideoEncData->mbForbidDiscardingFrame)
{
aloge("fatal error! vencChn[%d] type:%d, forbid discarding frame!", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
}
if(pVideoEncData->mSoftFrameRateCtrl.mBasePts != -1 && pEncFrame->VFrame.mpts < pVideoEncData->mSoftFrameRateCtrl.mCurrentWantedPts)
{
// The original frame has been returned and no further processing is required.
bDiscardFrame = true;
}
}
pthread_mutex_unlock(&pVideoEncData->mFrameRateLock);
}
}
if(bDiscardFrame)
{
eError = ERR_VENC_NOT_PERM;
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
goto ERROR;
}
VideoFrameInfoNode *pFirstNode = list_first_entry(&pVideoEncData->mBufQ.mIdleFrameList, VideoFrameInfoNode, mList);
VIDEO_FRAME_INFO_S *pDstEncFrame = &pFirstNode->VFrame;
memcpy(pDstEncFrame, pEncFrame, sizeof(VIDEO_FRAME_INFO_S));
alogv("wr buf_id: %d, nTimeStamp: [%lld]us", pDstEncFrame->mId, pDstEncFrame->VFrame.mpts);
pVideoEncData->mBufQ.buf_unused--;
list_move_tail(&pFirstNode->mList, &pVideoEncData->mBufQ.mReadyFrameList);
alogv("input orig frame ID[%d] list: Idle -> Ready", pFirstNode->VFrame.mId);
if (FALSE == pVideoEncData->mbForbidDiscardingFrame) //allow to drop frame, e.g., h264,h265,mjpeg
{
int ret = SendOrigFrameToVencLib(pVideoEncData, pFirstNode);;
if (0 != ret)
{
aloge("fatal error! vencChn[%d] Send OrigFrameToVencLib fail, ret=%d", pVideoEncData->mMppChnInfo.mChnId, ret);
eError = ERR_VENC_SYS_NOTREADY;
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
goto ERROR;
}
else
{
list_move_tail(&pFirstNode->mList, &pVideoEncData->mBufQ.mUsingFrameList);
pVideoEncData->mInputFrameCnt++;
alogv("vencChn[%d] input orig frame ID[%d] list: Ready -> Using", pVideoEncData->mMppChnInfo.mChnId, pFirstNode->VFrame.mId);
}
}
else //only for jpeg continuous encoding.
{
if(0 == pVideoEncData->mFlagInputFrame)
{
pVideoEncData->mFlagInputFrame = 1;
message_t msg;
msg.command = VEncComp_InputFrameAvailable;
put_message(&pVideoEncData->cmd_queue, &msg);
alogv("VencChn[%d] send message VEncComp InputFrameAvailable", pVideoEncData->mMppChnInfo.mChnId);
}
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
else
{
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
FRAMEDATATYPE frame;
//VIDEO_FRAME_INFO_S *pEncFrame = (VIDEO_FRAME_INFO_S*)pBuffer->pAppPrivate;
if(pVideoEncData->csi_first_frame)
{
pVideoEncData->csi_base_time = pEncFrame->VFrame.mpts;
pVideoEncData->mPrevInputPts = pEncFrame->VFrame.mpts;
pVideoEncData->mCapTimeLapse.lastCapTimeUs = 0;
pVideoEncData->mCapTimeLapse.lastTimeStamp = 0;
pVideoEncData->csi_first_frame = FALSE;
}
frame.info.timeStamp = pEncFrame->VFrame.mpts;
frame.info.bufferId = pEncFrame->mId;
frame.info.size = pEncFrame->VFrame.mStride[0];
frame.addrY = (char*)pEncFrame->VFrame.mpVirAddr[0];
eError = VideoEncBufferPushFrame(pVideoEncData->buffer_manager, &frame);
if (eError != SUCCESS)
{
alogw("Be careful! current buffer queue is full!");
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
goto ERROR;
}
else
{
eError = ERR_VENC_EXIST;
}
//MM_COMPONENTTYPE *InputTunnelComp = (MM_COMPONENTTYPE *)(pVideoEncData->sInPortTunnelInfo.hTunnel);
//InputTunnelComp->FillThisBuffer(InputTunnelComp, pBuffer);
if(0 == pVideoEncData->mFlagInputFrame)
{
pVideoEncData->mFlagInputFrame = 1;
message_t msg;
msg.command = VEncComp_InputFrameAvailable;
put_message(&pVideoEncData->cmd_queue, &msg);
alogv("VencChn[%d] send message VEncComp InputFrameAvailable", pVideoEncData->mMppChnInfo.mChnId);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
if(pVideoEncData->mLimitedFramesFlag)
{
pVideoEncData->mCurRecvPicNum++;
}
ERROR:
pthread_mutex_unlock(&pVideoEncData->mRecvPicControlLock);
_exit0:
pthread_mutex_unlock(&pVideoEncData->mStateLock);
return eError;
}
ERRORTYPE VideoEncFillThisBuffer(
PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_BUFFERHEADERTYPE* pBuffer)
{
VIDEOENCDATATYPE *pVideoEncData;
ERRORTYPE eError = SUCCESS;
int ret;
pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pBuffer->nOutputPortIndex == pVideoEncData->sOutPortDef.nPortIndex)
{// output tunnel mode
EncodedStream *pOutFrame = (EncodedStream*)pBuffer->pOutputPortPrivate;
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
BOOL bFind = FALSE;
ENCODER_NODE_T *pEntry;
list_for_each_entry(pEntry, &pVideoEncData->mUsedOutFrameList, mList)
{
if (pEntry->stEncodedStream.nID == pOutFrame->nID)
{
bFind = TRUE;
break;
}
}
if (!bFind)
{
int num = 0;
list_for_each_entry(pEntry, &pVideoEncData->mUsedOutFrameList, mList)
{
num++;
aloge("[%d-%d-%d]", pEntry->stEncodedStream.nID, pOutFrame->nID, pBuffer->nInputPortIndex);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
aloge("fatal error! try to release one output buffer that never be used! ID = %d, inPortIndex:%d, usedOutCnt:%d",
pOutFrame->nID, pBuffer->nInputPortIndex, num);
return ERR_VENC_ILLEGAL_PARAM;
}
// release buffer
if (pVideoEncData->is_compress_source == 0)
{
VencOutputBuffer stOutputBuffer;
config_VencOutputBuffer_By_EncodedStream(&stOutputBuffer, pOutFrame);
ret = VencQueueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
if (ret != 0)
{
aloge("fatal error! Venc QueueOutputBuf fail[%d]", ret);
}
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Used -> Idle", pEntry->stEncodedStream.nID);
if(pVideoEncData->mWaitOutFrameReturnFlag)
{
pVideoEncData->mWaitOutFrameReturnFlag = FALSE;
message_t msg;
msg.command = VEncComp_OutputFrameReturn;
put_message(&pVideoEncData->cmd_queue, &msg);
alogv("VencChn[%d] send message VEncComp OutputFrameReturn", pVideoEncData->mMppChnInfo.mChnId);
}
if (pVideoEncData->mWaitOutFrameFullFlag)
{
int cnt = 0;
struct list_head *pList;
list_for_each(pList, &pVideoEncData->mIdleOutFrameList)
{
cnt++;
}
if (cnt>=pVideoEncData->mFrameNodeNum)
{
pthread_cond_signal(&pVideoEncData->mOutFrameFullCondition);
}
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
else
{ /* gushiming compressed source */
ERRORTYPE releaseOmxRet;
FRAMEDATATYPE frame;
frame.addrY = (char*)pOutFrame->pBuffer;
frame.info.timeStamp = pOutFrame->nTimeStamp;
frame.info.bufferId = pOutFrame->nID;
frame.info.size = pOutFrame->nBufferLen;
releaseOmxRet = VideoEncBufferReleaseFrame(pVideoEncData->buffer_manager, &frame);
if(releaseOmxRet != SUCCESS)
{
aloge("fatal error! videoEncBufferReleaseFrame fail[%d]", releaseOmxRet);
}
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Used -> Idle", pEntry->stEncodedStream.nID);
if (pVideoEncData->mWaitOutFrameFullFlag)
{
int cnt = 0;
struct list_head *pList;
list_for_each(pList, &pVideoEncData->mIdleOutFrameList)
{
cnt++;
}
if (cnt>=pVideoEncData->mFrameNodeNum)
{
pthread_cond_signal(&pVideoEncData->mOutFrameFullCondition);
}
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
}
else
{
aloge("fatal error! outPortIndex[%d]!=[%d]", pBuffer->nOutputPortIndex, pVideoEncData->sOutPortDef.nPortIndex);
}
//ERROR:
return eError;
}
/*****************************************************************************/
ERRORTYPE VideoEncComponentDeInit(PARAM_IN COMP_HANDLETYPE hComponent)
{
VIDEOENCDATATYPE *pVideoEncData;
ERRORTYPE eError = SUCCESS;
CompInternalMsgType eCmd = Stop;
message_t msg;
//int i = 0;
alogv("VideoEnc Component DeInit");
pVideoEncData = (VIDEOENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pVideoEncData->mEncodeTotalCnt != pVideoEncData->mEncodeSuccessCount)
{
unsigned int nBitRate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
alogw("Be careful! VencChn[%d] type[%d] vBufSize[%dx%d]: encode cnt[%d] success[%d] vbvful[%d] drop[%d] err[%d], bitRate[%d]Mbit",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type,
pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth, pVideoEncData->mEncChnAttr.VeAttr.SrcPicHeight,
pVideoEncData->mEncodeTotalCnt, pVideoEncData->mEncodeSuccessCount, pVideoEncData->mEncodeVbvFulDiscardFrameCnt,
pVideoEncData->mEncodeDropFrameCnt, pVideoEncData->mEncodeTimeoutCnt, nBitRate/(1000*1000));
}
#ifdef VIDEO_ENC_TIME_DEBUG
alogd("VencChn[%d] type[%d] vBufSize[%dx%d]: encodeSuccess Duration[%lld]ms, FrameCount[%d], averagePerFrame[%lld]ms",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type,
pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth, pVideoEncData->mEncChnAttr.VeAttr.SrcPicHeight,
pVideoEncData->mTotalEncodeSuccessDuration/1000, pVideoEncData->mEncodeSuccessCount,
pVideoEncData->mEncodeSuccessCount?pVideoEncData->mTotalEncodeSuccessDuration/pVideoEncData->mEncodeSuccessCount/1000:1);
#endif
SIZE_S dstPicSize;
if (SUCCESS == getPicSizeFromVENC_ATTR_S(&pVideoEncData->mEncChnAttr.VeAttr, &dstPicSize))
{
alogv("vencChn[%d],type[%d],vSrcSize[%dx%d],vDstSize[%dx%d]: max frameSize of this encoding process is [%d]Byte([%f]MB)",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type,
pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth, pVideoEncData->mEncChnAttr.VeAttr.SrcPicHeight,
dstPicSize.Width, dstPicSize.Height,
pVideoEncData->mStatMaxFrameSize, (float)pVideoEncData->mStatMaxFrameSize/(1024*1024));
}
else
{
aloge("fatal error! get dst size fail! check code!");
}
int cnt = 0;
struct list_head *pList;
list_for_each(pList, &pVideoEncData->mBufQ.mIdleFrameList)
{
cnt++;
}
if(pVideoEncData->mBufQ.buf_unused != cnt)
{
aloge("fatal error! inputFrames[%d]<[%d] must return all before!", ENC_FIFO_LEVEL-pVideoEncData->mBufQ.buf_unused, cnt);
}
if(!list_empty(&pVideoEncData->mBufQ.mUsedFrameList))
{
aloge("fatal error! why usedFrameList is not empty?");
}
if(!list_empty(&pVideoEncData->mBufQ.mUsingFrameList))
{
aloge("fatal error! why usingFrameList is not empty?");
}
if(!list_empty(&pVideoEncData->mBufQ.mReadyFrameList))
{
aloge("fatal error! why readyInputFrame is not empty?");
}
if(!list_empty(&pVideoEncData->mBufQ.mIdleFrameList))
{
VideoFrameInfoNode *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mBufQ.mIdleFrameList, mList)
{
list_del(&pEntry->mList);
freeVideoFrameInfoNode(pEntry);
}
}
// STAR ADD 2011-5-27
if (pVideoEncData->pCedarV != NULL)
{
VencDestroy(pVideoEncData->pCedarV);
pVideoEncData->pCedarV = NULL;
VideoEncMBInfoDeinit(&pVideoEncData->mMBInfo);
}
if(pVideoEncData->mpVencHeaderData)
{
if(pVideoEncData->mpVencHeaderData->pBuffer)
{
free(pVideoEncData->mpVencHeaderData->pBuffer);
pVideoEncData->mpVencHeaderData->pBuffer = NULL;
}
pVideoEncData->mpVencHeaderData->nLength = 0;
free(pVideoEncData->mpVencHeaderData);
pVideoEncData->mpVencHeaderData = NULL;
}
msg.command = eCmd;
put_message(&pVideoEncData->cmd_queue, &msg);
alogv("VencChn[%d] send message Stop", pVideoEncData->mMppChnInfo.mChnId);
//cdx_sem_up(&pVideoEncData->cdx_sem_wait_message);
alogv("wait VideoEnc component exit!...");
// Wait for thread to exit so we can get the status into "error"
pthread_join(pVideoEncData->thread_id, (void*) &eError);
//post_message_to_vbuf(pVideoEncData, OMX_VBufCommand_Exit, 0);
// Wait for thread to exit so we can get the status into "error"
//pthread_join(pVideoEncData->thread_buf_id, (void*) &eError);
//cdx_sem_deinit(&pVideoEncData->cdx_sem_wait_message);
//cdx_sem_deinit(&cdx_sem_fifo_ops);
if (pVideoEncData->mMotionResult.region)
{
free(pVideoEncData->mMotionResult.region);
pVideoEncData->mMotionResult.region = NULL;
}
if (pVideoEncData->mRegionD3DResult.region)
{
free(pVideoEncData->mRegionD3DResult.region);
pVideoEncData->mRegionD3DResult.region = NULL;
}
// free all SeiData buffer
FreeSeiDataBuffer(pVideoEncData);
pthread_mutex_destroy(&pVideoEncData->mutex_fifo_ops_lock);
pthread_cond_destroy(&pVideoEncData->mInputFrameUsingEmptyCondition);
cdx_sem_deinit(&pVideoEncData->mInputFrameBufDoneSem);
message_destroy(&pVideoEncData->cmd_queue);
if (pVideoEncData->buffer_manager != NULL) {
VideoEncBufferDeInit(pVideoEncData->buffer_manager);
pVideoEncData->buffer_manager = NULL;
}
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if(!list_empty(&pVideoEncData->mUsedOutFrameList))
{
aloge("fatal error! outUsedFrame must be 0!");
}
if(!list_empty(&pVideoEncData->mReadyOutFrameList))
{
aloge("fatal error! outReadyFrame must be 0!");
}
int nodeNum = 0;
if(!list_empty(&pVideoEncData->mIdleOutFrameList))
{
ENCODER_NODE_T *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mIdleOutFrameList, mList)
{
list_del(&pEntry->mList);
free(pEntry);
nodeNum++;
}
}
if(nodeNum!=pVideoEncData->mFrameNodeNum)
{
aloge("fatal error! frame node number is not match[%d][%d]", nodeNum, pVideoEncData->mFrameNodeNum);
}
if(pVideoEncData->mFrameNodeNum != BITSTREAM_FRAME_SIZE)
{
alogw("Low probability! VEncComp idle out frame total num: %d -> %d!", BITSTREAM_FRAME_SIZE, pVideoEncData->mFrameNodeNum);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
pthread_cond_destroy(&pVideoEncData->mOutFrameFullCondition);
pthread_cond_destroy(&pVideoEncData->mOutFrameCondition);
pthread_mutex_destroy(&pVideoEncData->mOutFrameListMutex);
pthread_mutex_destroy(&pVideoEncData->mStateLock);
close(pVideoEncData->mOutputFrameNotifyPipeFds[0]);
close(pVideoEncData->mOutputFrameNotifyPipeFds[1]);
pthread_mutex_destroy(&pVideoEncData->mCedarvVideoEncInitFlagLock);
//pthread_mutex_destroy(&pVideoEncData->mVencOverlayLock);
pthread_mutex_destroy(&pVideoEncData->mRecvPicControlLock);
//free mRoiCfgList element
pthread_mutex_lock(&pVideoEncData->mRoiLock);
if(!list_empty(&pVideoEncData->mRoiCfgList))
{
VEncRoiCfgNode *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mRoiCfgList, mList)
{
list_del(&pEntry->mList);
free(pEntry);
}
}
pthread_mutex_unlock(&pVideoEncData->mRoiLock);
pthread_mutex_destroy(&pVideoEncData->mRoiLock);
pthread_mutex_destroy(&pVideoEncData->mFrameRateLock);
pthread_mutex_destroy(&pVideoEncData->mCapTimeLapseLock);
if(pVideoEncData)
{
free(pVideoEncData);
}
#ifdef STORE_VENC_IN_FRAME
if (STORE_VENC_CH_ID == pVideoEncData->mMppChnInfo.mChnId)
{
if (g_debug_fp_frame != NULL)
{
fclose(g_debug_fp_frame);
g_debug_fp_frame = NULL;
}
alogd("save total frame cnt %d", g_debug_frame_cnt);
g_debug_frame_cnt = 0;
}
#endif
#ifdef STORE_VENC_OUT_STREAM
if (STORE_VENC_CH_ID == pVideoEncData->mMppChnInfo.mChnId)
{
if (g_debug_fp_stream != NULL)
{
fclose(g_debug_fp_stream);
g_debug_fp_stream = NULL;
}
alogd("save total stream cnt %d", g_debug_stream_cnt);
g_debug_stream_cnt = 0;
}
#endif
alogv("VideoEnc component exited!");
return eError;
}
/*****************************************************************************/
ERRORTYPE VideoEncComponentInit(PARAM_IN COMP_HANDLETYPE hComponent)
{
MM_COMPONENTTYPE *pComp;
VIDEOENCDATATYPE *pVideoEncData;
ERRORTYPE eError = SUCCESS;
unsigned int err;
int i = 0;
pComp = (MM_COMPONENTTYPE *) hComponent;
// Create private data
pVideoEncData = (VIDEOENCDATATYPE *) malloc(sizeof(VIDEOENCDATATYPE));
if (NULL == pVideoEncData)
{
aloge("fatal error! malloc pVideoEncData failed[%s]! size:%d", strerror(errno), sizeof(VIDEOENCDATATYPE));
return ERR_VENC_NOMEM;
}
memset(pVideoEncData, 0x0, sizeof(VIDEOENCDATATYPE));
pVideoEncData->mvipp_id = -1;
pVideoEncData->mbExceptionCase = FALSE;
pVideoEncData->mbMediaDebugFlag = 0;
pVideoEncData->mbDisableVe2Isp = 0;
pVideoEncData->mbDisableIsp2Ve = 0;
memset(&pVideoEncData->mFrameRateInfo, 0, sizeof(VENC_FRAME_RATE_S));
#ifdef VENC_IGNORE_ALL_FRAME
pVideoEncData->mbDebug_IgnoreAllFrame = 1;
#endif
err = pipe(pVideoEncData->mOutputFrameNotifyPipeFds);
if (err)
{
aloge("fatal error! pipe fail[0x%x]", err);
eError = ERR_VENC_NOMEM;
goto EXIT;
}
pVideoEncData->mBufQ.buf_unused = ENC_FIFO_LEVEL;
INIT_LIST_HEAD(&pVideoEncData->mBufQ.mIdleFrameList);
INIT_LIST_HEAD(&pVideoEncData->mBufQ.mReadyFrameList);
INIT_LIST_HEAD(&pVideoEncData->mBufQ.mUsingFrameList);
INIT_LIST_HEAD(&pVideoEncData->mBufQ.mUsedFrameList);
for (i = 0; i < ENC_FIFO_LEVEL; i++)
{
VideoFrameInfoNode *pNode = (VideoFrameInfoNode*)malloc(sizeof(VideoFrameInfoNode));
if(NULL == pNode)
{
aloge("fatal error! malloc fail!");
eError = ERR_VENC_NOMEM;
goto EXIT;
}
memset(pNode, 0, sizeof(VideoFrameInfoNode));
list_add_tail(&pNode->mList, &pVideoEncData->mBufQ.mIdleFrameList);
}
//pVideoEncData->mInputFrameToVeTimeMs = 0;
//pVideoEncData->mOutputStreamFromVeTimeMs = 0;
pVideoEncData->mLastSetSeiDataTimeMs = 0;
pVideoEncData->mLastSeiDataConfigLevel = 0;
pComp->pComponentPrivate = (void*) pVideoEncData;
pVideoEncData->state = COMP_StateLoaded;
pthread_mutex_init(&pVideoEncData->mStateLock,NULL);
pVideoEncData->hSelf = hComponent;
pthread_mutex_init(&pVideoEncData->mFrameRateLock, NULL);
pVideoEncData->timeLapseEnable = FALSE;
pthread_mutex_init(&pVideoEncData->mCapTimeLapseLock, NULL);
pVideoEncData->csi_first_frame = TRUE;
pthread_mutex_init(&pVideoEncData->mutex_fifo_ops_lock ,NULL);
cdx_sem_init(&pVideoEncData->mInputFrameBufDoneSem, 0);
pVideoEncData->mFlagInputFrame = 0;
INIT_LIST_HEAD(&pVideoEncData->mIdleOutFrameList);
INIT_LIST_HEAD(&pVideoEncData->mReadyOutFrameList);
INIT_LIST_HEAD(&pVideoEncData->mUsedOutFrameList);
INIT_LIST_HEAD(&pVideoEncData->mRoiCfgList);
pthread_mutex_init(&pVideoEncData->mRoiLock, NULL);
//init color2grey is close
pVideoEncData->mColor2GreyParam.bColor2Grey = FALSE;
//init HorizonFlip and AdaptiveIntraInPFlag is closed
pVideoEncData->mHorizonFlipFlag = FALSE;
pVideoEncData->mAdaptiveIntraInPFlag = FALSE;
//init procset
pVideoEncData->mProcSet.bProcEnable = 1;
pVideoEncData->mProcSet.nProcFreq = 120;
pVideoEncData->mProcSet.nStatisBitRateTime = 1000;
pVideoEncData->mProcSet.nStatisFrRateTime = 1000;
pVideoEncData->mJpegParam.Qfactor = 95;
//init SaveBsFile, disable it
memset(&pVideoEncData->mSaveBSFile, 0, sizeof(VencSaveBSFile));
//init RecvPic
pthread_mutex_init(&pVideoEncData->mRecvPicControlLock, NULL);
pVideoEncData->mLimitedFramesFlag = FALSE;
pVideoEncData->mRecvPicParam.mRecvPicNum = 0;
pVideoEncData->mCurRecvPicNum = 0;
pthread_mutex_init(&pVideoEncData->mCedarvVideoEncInitFlagLock, NULL);
pVideoEncData->mbCedarvVideoEncInitFlag = FALSE;
//pthread_mutex_init(&pVideoEncData->mVencOverlayLock, NULL);
pVideoEncData->mD3DInIFrmEnable = 0;
pVideoEncData->mTightMbQpEnable = 1;
pVideoEncData->mExtremeD3D.en_extreme_d3d = 0;
for(i=0;i<BITSTREAM_FRAME_SIZE;i++)
{
ENCODER_NODE_T *pNode = (ENCODER_NODE_T*)malloc(sizeof(ENCODER_NODE_T));
if(NULL == pNode)
{
aloge("fatal error! malloc fail[%s]!", strerror(errno));
break;
}
memset(pNode, 0, sizeof(ENCODER_NODE_T));
list_add_tail(&pNode->mList, &pVideoEncData->mIdleOutFrameList);
pVideoEncData->mFrameNodeNum++;
}
err = pthread_mutex_init(&pVideoEncData->mOutFrameListMutex, NULL);
if(err!=0)
{
aloge("fatal error! pthread mutex init fail!");
eError = ERR_VENC_NOMEM;
goto EXIT;
}
pthread_condattr_t condAttr;
pthread_condattr_init(&condAttr);
pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
err = pthread_cond_init(&pVideoEncData->mOutFrameFullCondition, &condAttr);
if(err!=0)
{
aloge("fatal error! pthread cond init fail!");
eError = ERR_VENC_NOMEM;
goto EXIT;
}
pthread_cond_init(&pVideoEncData->mOutFrameCondition, &condAttr);
pthread_cond_init(&pVideoEncData->mInputFrameUsingEmptyCondition, &condAttr);
// Fill in function pointers
pComp->SetCallbacks = VideoEncSetCallbacks;
pComp->SendCommand = VideoEncSendCommand;
pComp->GetConfig = VideoEncGetConfig;
pComp->SetConfig = VideoEncSetConfig;
pComp->GetState = VideoEncGetState;
pComp->ComponentTunnelRequest = VideoEncComponentTunnelRequest;
pComp->ComponentDeInit = VideoEncComponentDeInit;
pComp->EmptyThisBuffer = VideoEncEmptyThisBuffer;
pComp->FillThisBuffer = VideoEncFillThisBuffer;
// Initialize component data structures to default values
pVideoEncData->sPortParam.nPorts = 0x2;
pVideoEncData->sPortParam.nStartPortNumber = 0x0;
// Initialize the video parameters for input port
pVideoEncData->sInPortDef.nPortIndex = 0x0;
pVideoEncData->sInPortDef.bEnabled = TRUE;
pVideoEncData->sInPortDef.eDomain = COMP_PortDomainVideo;
pVideoEncData->sInPortDef.format.video.cMIMEType = "H264";
pVideoEncData->sInPortDef.format.video.nFrameWidth = 176;
pVideoEncData->sInPortDef.format.video.nFrameHeight = 144;
pVideoEncData->sInPortDef.eDir = COMP_DirInput;
pVideoEncData->sInPortDef.format.video.eCompressionFormat = PT_H264;
pVideoEncData->sInPortDef.format.video.eColorFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
// Initialize the video parameters for output port
pVideoEncData->sOutPortDef.nPortIndex = 0x1;
pVideoEncData->sOutPortDef.bEnabled = TRUE;
pVideoEncData->sOutPortDef.eDomain = COMP_PortDomainVideo;
pVideoEncData->sOutPortDef.format.video.cMIMEType = "YVU420";
pVideoEncData->sOutPortDef.format.video.nFrameWidth = 176;
pVideoEncData->sOutPortDef.format.video.nFrameHeight = 144;
pVideoEncData->sOutPortDef.eDir = COMP_DirOutput;
pVideoEncData->sOutPortDef.format.video.eCompressionFormat = PT_H264;
pVideoEncData->sOutPortDef.format.video.eColorFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
pVideoEncData->sPortBufSupplier[0].nPortIndex = 0x0;
pVideoEncData->sPortBufSupplier[0].eBufferSupplier = COMP_BufferSupplyOutput;
pVideoEncData->sPortBufSupplier[1].nPortIndex = 0x1;
pVideoEncData->sPortBufSupplier[1].eBufferSupplier = COMP_BufferSupplyOutput;
pVideoEncData->sInPortTunnelInfo.nPortIndex = 0x0;
pVideoEncData->sInPortTunnelInfo.eTunnelType = TUNNEL_TYPE_COMMON;
pVideoEncData->sOutPortTunnelInfo.nPortIndex = 0x1;
pVideoEncData->sOutPortTunnelInfo.eTunnelType = TUNNEL_TYPE_COMMON;
if (message_create(&pVideoEncData->cmd_queue)<0)
{
aloge("fatal error! message error!");
eError = ERR_VENC_NOMEM;
goto EXIT;
}
// Create the component thread
pthread_attr_t attr;
int rs;
/* init thread attr */
rs = pthread_attr_init (&attr);
assert (rs == 0);
//pthread_attr_setstacksize(&attr, 0x40000);
#if 0
struct sched_param schedParam;
/* get current sched policy */
int curPolicy;
int newPolicy = SCHED_FIFO;
rs = pthread_attr_getschedpolicy(&attr, &curPolicy);
assert (rs == 0);
if(curPolicy != newPolicy)
{
alogd("we will change venc thread sched policy [%d]->[%d]", curPolicy, newPolicy);
}
/* get priority scope of SCHED_FIFO policy */
int maxPriority = sched_get_priority_max(newPolicy);
assert(maxPriority != -1);
int minPriority = sched_get_priority_min(newPolicy);
assert(minPriority != -1);
alogd("priority[%d] scope[%d, %d]", newPolicy, minPriority, maxPriority);
/* set sched policy SCHED_FIFO */
rs = pthread_attr_setschedpolicy(&attr, newPolicy);
assert (rs == 0);
/* set priority */
rs = pthread_attr_getschedparam(&attr, &schedParam);
assert (rs == 0);
int curSchedPriority = schedParam.__sched_priority;
int newSchedPriority = (maxPriority + minPriority)/2;
if (curSchedPriority != newSchedPriority)
{
schedParam.__sched_priority = newSchedPriority;
rs = pthread_attr_setschedparam(&attr, &schedParam);
assert (rs == 0);
}
alogd("in schedPolicy[%d], change venc thread priority [%d]->[%d]", newPolicy, curSchedPriority, newSchedPriority);
#endif
err = pthread_create(&pVideoEncData->thread_id, &attr, ComponentThread, pVideoEncData);
/* destroy pthread_attr_t */
rs = pthread_attr_destroy (&attr);
assert (rs == 0);
if (err /*|| !pVideoEncData->thread_id*/)
{
eError = ERR_VENC_NOMEM;
goto EXIT;
}
alogv("create VideoEnc threadId:0x%lx", pVideoEncData->thread_id);
EXIT:
if(eError != SUCCESS)
{
aloge("fatal error! VideoEnc init fail[0x%x]", eError);
}
return eError;
}
/**
* analyse if compressed frame is key frame, and spspps info.
* @return true if it is key frame.
*/
static BOOL VideoEncAnalyseCompressedFrame(VIDEOENCDATATYPE* pVideoEncData, FRAMEDATATYPE *pCompressedFrame)
{
BOOL bKeyFrame;
if(PT_JPEG == pVideoEncData->mEncChnAttr.VeAttr.Type || PT_MJPEG == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
bKeyFrame = TRUE;
}
else if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
aloge("fatal error! need analyse h264 data!");
bKeyFrame = TRUE;
if(NULL == pVideoEncData->mpVencHeaderData)
{
//analyse spspps info of h264, nal_type 0x67, 0x68.
}
}
else if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
aloge("fatal error! need analyse h265 data!");
bKeyFrame = TRUE;
if(NULL == pVideoEncData->mpVencHeaderData)
{
//analyse spspps info of h265
}
}
else
{
aloge("fatal error! unknown encodeType[0x%x]", pVideoEncData->mEncChnAttr.VeAttr.Type);
bKeyFrame = FALSE;
}
return bKeyFrame;
}
/**
* statistics period is Key frame interval.
* If actual bitRate is 1.5 or more times than dstBitRate, print warning!
*/
static void statVideoBitRate(VIDEOENCDATATYPE *pVideoEncData, VencOutputBuffer *pVencOutputBuffer)
{
if(PT_H264!=pVideoEncData->mEncChnAttr.VeAttr.Type && PT_H265!=pVideoEncData->mEncChnAttr.VeAttr.Type)
{
return;
}
int nKeyFrameInterval = pVideoEncData->mEncChnAttr.VeAttr.MaxKeyInterval;
int nFrameRate = pVideoEncData->mFrameRateInfo.DstFrmRate;
unsigned int nBitRate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
if(pVencOutputBuffer->nFlag & VENC_BUFFERFLAG_KEYFRAME)
{
//deduce result, and compare to dstBitRate
if ((pVideoEncData->mFrameNumInKeyFrameInvertal) && (pVideoEncData->mFrameNumInKeyFrameInvertal == nKeyFrameInterval))
{
unsigned int nActualBitRate = (unsigned int)((int64_t)pVideoEncData->mBytesKeyFrameInterval*nFrameRate*8/pVideoEncData->mFrameNumInKeyFrameInvertal);
if (pVideoEncData->mbDebug_VencOutBitrateStatByKeyFrameInvertalFlag) // for debug by env
{
if (nBitRate)
{
float bitrateTimes = (float)nActualBitRate / nBitRate;
alogd("VencChn[%d] actual bitRate[%d Kbps] / dstBitRate[%d Kbps] = %.2f, [%d-%d-%d][VencCh%d-%s]",
pVideoEncData->mMppChnInfo.mChnId, nActualBitRate/1024, nBitRate/1024, bitrateTimes,
pVideoEncData->mBytesKeyFrameInterval, pVideoEncData->mFrameNumInKeyFrameInvertal, nFrameRate,
pVideoEncData->mMppChnInfo.mChnId, PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type ? "H264" : "H265");
}
}
else
{
if ((nBitRate) && (nActualBitRate/nBitRate >= 2))
{
alogw("VencChn[%d] Be careful! actual bitRate[%d] / dstBitRate[%d] = %d, too large! [%d-%d-%d]", pVideoEncData->mMppChnInfo.mChnId,
nActualBitRate, nBitRate, nActualBitRate/nBitRate, pVideoEncData->mBytesKeyFrameInterval,
pVideoEncData->mFrameNumInKeyFrameInvertal, nFrameRate);
}
}
}
else
{
if(pVideoEncData->mFrameNumInKeyFrameInvertal != 0)
{
alogw("keyFrameInterval is not match [%d]!=[%d], maybe forceIFrame or VeLib dropFrame, give up statistics! KeyFrameSize[%d]Bytes",
pVideoEncData->mFrameNumInKeyFrameInvertal, nKeyFrameInterval, pVideoEncData->mBytesKeyFrameInterval);
}
}
pVideoEncData->mFrameNumInKeyFrameInvertal = 0;
pVideoEncData->mBytesKeyFrameInterval = 0;
}
pVideoEncData->mFrameNumInKeyFrameInvertal++;
pVideoEncData->mBytesKeyFrameInterval += (pVencOutputBuffer->nSize0 + pVencOutputBuffer->nSize1);
}
/**
send frame to vencLib.
In time-lapse or slow-motion mode, encBuf.nPts need to be changed.
@return
0: success
-1: fatal error
-2: VencQueueInputBuf error
*/
static int SendOrigFrameToVencLib(VIDEOENCDATATYPE *pVideoEncData, VideoFrameInfoNode *pFrameNode)
{
VencInputBuffer encBuf;
VideoEncoder *pCedarV = NULL;
if ((NULL == pVideoEncData) || (NULL == pFrameNode))
{
aloge("fatal error! invalid input param!");
return -1;
}
pCedarV = pVideoEncData->pCedarV;
if (NULL == pCedarV)
{
aloge("fatal error! invalid input param!");
return -1;
}
memset(&encBuf, 0, sizeof(VencInputBuffer));
encBuf.nID = pFrameNode->VFrame.mId;
encBuf.nPts = (long long)pFrameNode->VFrame.VFrame.mpts/* - pVideoEncData->csi_base_time*/;
encBuf.nFlag = 0;
encBuf.pAddrPhyY = (unsigned char*)pFrameNode->VFrame.VFrame.mPhyAddr[0];
encBuf.pAddrPhyC = (unsigned char*)pFrameNode->VFrame.VFrame.mPhyAddr[1];
encBuf.pAddrVirY = (unsigned char*)pFrameNode->VFrame.VFrame.mpVirAddr[0];
encBuf.pAddrVirC = (unsigned char*)pFrameNode->VFrame.VFrame.mpVirAddr[1];
#ifdef STORE_VENC_IN_FRAME
if ((STORE_VENC_CH_ID == pVideoEncData->mMppChnInfo.mChnId) &&
(STORE_VENC_FRAME_TOTAL_CNT > g_debug_frame_cnt))
{
if (g_debug_fp_frame == NULL)
{
g_debug_fp_frame = fopen(STORE_VENC_FRAME_FILE, "wb");
assert(g_debug_fp_frame != NULL);
alogd("####### [DEBUG] open %s, VencChn%d #######", STORE_VENC_FRAME_FILE, STORE_VENC_CH_ID);
}
if (pFrameNode->VFrame.VFrame.mStride[0] > 0)
fwrite(encBuf.pAddrVirY, 1, pFrameNode->VFrame.VFrame.mStride[0], g_debug_fp_frame);
if (pFrameNode->VFrame.VFrame.mStride[1] > 0)
fwrite(encBuf.pAddrVirC, 1, pFrameNode->VFrame.VFrame.mStride[1], g_debug_fp_frame);
g_debug_frame_cnt++;
}
#endif
if (pVideoEncData->timeLapseEnable)
{
pthread_mutex_lock(&pVideoEncData->mCapTimeLapseLock);
if (pVideoEncData->mCapTimeLapse.recType == COMP_RECORD_TYPE_SLOW)
{
encBuf.nPts = pVideoEncData->mCapTimeLapse.lastTimeStamp;
pVideoEncData->mCapTimeLapse.lastTimeStamp += pVideoEncData->mCapTimeLapse.videoFrameIntervalUs;
}
else if (pVideoEncData->mCapTimeLapse.recType == COMP_RECORD_TYPE_TIMELAPSE)
{
if (pVideoEncData->mCapTimeLapse.lastCapTimeUs > 0
&& pFrameNode->VFrame.VFrame.mpts < pVideoEncData->mCapTimeLapse.lastCapTimeUs + pVideoEncData->mCapTimeLapse.capFrameIntervalUs)
{
pthread_mutex_unlock(&pVideoEncData->mCapTimeLapseLock);
// The original input frame has been returned and no further processing is required.
aloge("fatal error! time-lapse frame pts wrong![%lf-%lf-%lld]", pVideoEncData->mCapTimeLapse.lastCapTimeUs,
pVideoEncData->mCapTimeLapse.capFrameIntervalUs, pFrameNode->VFrame.VFrame.mpts);
return -1;
}
if(pVideoEncData->mCapTimeLapse.lastCapTimeUs <= 0)
{
pVideoEncData->mCapTimeLapse.lastCapTimeUs = pFrameNode->VFrame.VFrame.mpts;
}
else
{
int64_t n = (pFrameNode->VFrame.VFrame.mpts - pVideoEncData->mCapTimeLapse.lastCapTimeUs)/pVideoEncData->mCapTimeLapse.capFrameIntervalUs;
pVideoEncData->mCapTimeLapse.lastCapTimeUs += n*pVideoEncData->mCapTimeLapse.capFrameIntervalUs;
}
encBuf.nPts = pVideoEncData->mCapTimeLapse.lastTimeStamp;
pVideoEncData->mCapTimeLapse.lastTimeStamp += pVideoEncData->mCapTimeLapse.videoFrameIntervalUs;
alogv("VencChn[%d] offline timelapse pts=%lld vframepts=%lld", pVideoEncData->mMppChnInfo.mChnId, encBuf.nPts, pFrameNode->VFrame.VFrame.mpts);
}
pthread_mutex_unlock(&pVideoEncData->mCapTimeLapseLock);
}
else
{
pthread_mutex_lock(&pVideoEncData->mFrameRateLock);
if (pVideoEncData->mSoftFrameRateCtrl.enable)
{
if(-1 == pVideoEncData->mSoftFrameRateCtrl.mBasePts)
{
pVideoEncData->mSoftFrameRateCtrl.mBasePts = encBuf.nPts;
pVideoEncData->mSoftFrameRateCtrl.mCurrentWantedPts = pVideoEncData->mSoftFrameRateCtrl.mBasePts;
pVideoEncData->mSoftFrameRateCtrl.mFrameCounter = 0;
}
if(encBuf.nPts >= pVideoEncData->mSoftFrameRateCtrl.mCurrentWantedPts)
{
int videoFramerate = pVideoEncData->mFrameRateInfo.DstFrmRate*1000;
pVideoEncData->mSoftFrameRateCtrl.mFrameCounter++;
pVideoEncData->mSoftFrameRateCtrl.mCurrentWantedPts = pVideoEncData->mSoftFrameRateCtrl.mBasePts
+ (int64_t)pVideoEncData->mSoftFrameRateCtrl.mFrameCounter*(1000*1000) * 1000 / videoFramerate;
}
else
{
pthread_mutex_unlock(&pVideoEncData->mFrameRateLock);
// The original frame has been returned and no further processing is required.
aloge("fatal error! soft frame rate, pts wrong![%lld-%lld-%lld]", pVideoEncData->mSoftFrameRateCtrl.mBasePts,
pVideoEncData->mSoftFrameRateCtrl.mCurrentWantedPts, encBuf.nPts);
return -1;
}
}
pthread_mutex_unlock(&pVideoEncData->mFrameRateLock);
}
if (pVideoEncData->mCropCfg.bEnable)
{
encBuf.bEnableCorp = 1;
encBuf.sCropInfo.nLeft = pVideoEncData->mCropCfg.Rect.X;
encBuf.sCropInfo.nTop = pVideoEncData->mCropCfg.Rect.Y;
encBuf.sCropInfo.nWidth = pVideoEncData->mCropCfg.Rect.Width;
encBuf.sCropInfo.nHeight= pVideoEncData->mCropCfg.Rect.Height;
alogv("crop enable, Left:%d Top:%d Width:%d Height:%d", encBuf.sCropInfo.nLeft, encBuf.sCropInfo.nTop,
encBuf.sCropInfo.nWidth, encBuf.sCropInfo.nHeight);
}
else
{
int showWidth = pFrameNode->VFrame.VFrame.mOffsetRight - pFrameNode->VFrame.VFrame.mOffsetLeft;
int showHeight = pFrameNode->VFrame.VFrame.mOffsetBottom - pFrameNode->VFrame.VFrame.mOffsetTop;
if(showWidth != pFrameNode->VFrame.VFrame.mWidth || showHeight != pFrameNode->VFrame.VFrame.mHeight)
{
if ((MM_PIXEL_FORMAT_YUV_AW_LBC_2_0X == pFrameNode->VFrame.VFrame.mPixelFormat) ||
(MM_PIXEL_FORMAT_YUV_AW_LBC_2_5X == pFrameNode->VFrame.VFrame.mPixelFormat) ||
(MM_PIXEL_FORMAT_YUV_AW_LBC_1_5X == pFrameNode->VFrame.VFrame.mPixelFormat) ||
(MM_PIXEL_FORMAT_YUV_AW_LBC_1_0X == pFrameNode->VFrame.VFrame.mPixelFormat))
{
if(AWALIGN(showHeight, 16) != pFrameNode->VFrame.VFrame.mHeight)
{
aloge("fatal error! VencChn[%d] lbc format[%d] do not support crop![%dx%d, %dx%d]",
pVideoEncData->mMppChnInfo.mChnId, pFrameNode->VFrame.VFrame.mPixelFormat,
showWidth, showHeight, pFrameNode->VFrame.VFrame.mWidth, pFrameNode->VFrame.VFrame.mHeight);
}
}
else
{
encBuf.bEnableCorp = 1;
encBuf.sCropInfo.nLeft = pFrameNode->VFrame.VFrame.mOffsetLeft;
encBuf.sCropInfo.nTop = pFrameNode->VFrame.VFrame.mOffsetTop;
encBuf.sCropInfo.nWidth = showWidth;
encBuf.sCropInfo.nHeight= showHeight;
alogv("need enable crop. VencChn[%d] show size[%dx%d]!= frameSize[%dx%d], %d-%d-%d-%d--%d-%d!",
pVideoEncData->mMppChnInfo.mChnId,
showWidth, showHeight,
pFrameNode->VFrame.VFrame.mWidth,
pFrameNode->VFrame.VFrame.mHeight,
pFrameNode->VFrame.VFrame.mOffsetLeft,
pFrameNode->VFrame.VFrame.mOffsetRight,
pFrameNode->VFrame.VFrame.mOffsetTop,
pFrameNode->VFrame.VFrame.mOffsetBottom,
pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth,
pVideoEncData->mEncChnAttr.VeAttr.SrcPicHeight);
}
}
else
{
if(pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth != pFrameNode->VFrame.VFrame.mWidth
|| pVideoEncData->mEncChnAttr.VeAttr.SrcPicHeight != pFrameNode->VFrame.VFrame.mHeight)
{
alogw("fatal error! enc src_size[%dx%d]!= frameSize[%dx%d], %d-%d-%d-%d!",
pVideoEncData->mEncChnAttr.VeAttr.SrcPicWidth,
pVideoEncData->mEncChnAttr.VeAttr.SrcPicHeight,
pFrameNode->VFrame.VFrame.mWidth,
pFrameNode->VFrame.VFrame.mHeight,
pFrameNode->VFrame.VFrame.mOffsetLeft,
pFrameNode->VFrame.VFrame.mOffsetRight,
pFrameNode->VFrame.VFrame.mOffsetTop,
pFrameNode->VFrame.VFrame.mOffsetBottom);
}
encBuf.bEnableCorp = 0;
}
}
encBuf.ispPicVar = 0;
encBuf.envLV = pFrameNode->VFrame.VFrame.mEnvLV;
pthread_mutex_lock(&pVideoEncData->mRoiLock);
VideoEncConfigVencInputBufferRoiParam(pVideoEncData, &encBuf);
pthread_mutex_unlock(&pVideoEncData->mRoiLock);
encBuf.bNeedFlushCache = 0;
int ret = VencQueueInputBuf(pCedarV, &encBuf);
if (ret != 0)
{
aloge("fatal error! Venc QueueInputBuf fail, ret=%d", ret);
return -2;
}
return 0;
}
static void VideoEncSendBackInputFrame(VIDEOENCDATATYPE *pVideoEncData, VIDEO_FRAME_INFO_S *pFrameInfo)
{
COMP_BUFFERHEADERTYPE BufferHeader;
memset(&BufferHeader, 0, sizeof(COMP_BUFFERHEADERTYPE));
if (FALSE == pVideoEncData->mInputPortTunnelFlag)
{
BufferHeader.pAppPrivate = pFrameInfo;
pVideoEncData->pCallbacks->EmptyBufferDone(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
&BufferHeader);
}
else
{
BufferHeader.pOutputPortPrivate = pFrameInfo;
BufferHeader.nOutputPortIndex = pVideoEncData->sInPortTunnelInfo.nTunnelPortIndex;
BufferHeader.nInputPortIndex = pVideoEncData->sInPortTunnelInfo.nPortIndex;
COMP_FillThisBuffer(pVideoEncData->sInPortTunnelInfo.hTunnel, &BufferHeader);
}
alogv("release input FrameId[%d]", pFrameInfo->mId);
}
/**
wait and return using input frames, then return used input frames.
*/
static int ReturnUseOrigFrameBeforeSetStateIdle(VIDEOENCDATATYPE *pVideoEncData)
{
if (NULL == pVideoEncData)
{
aloge("fatal error! invalid input param");
return -1;
}
// Wait for usingFrameList is empty.
if (TRUE == pVideoEncData->mbForbidDiscardingFrame)
{
while (1)
{
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if (list_empty(&pVideoEncData->mBufQ.mUsingFrameList))
{
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
break;
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
// Wait for vencLib to finish processing.
alogd("wait for sem inputFrameBufDone 200ms ...");
int semRet = cdx_sem_down_timedwait(&pVideoEncData->mInputFrameBufDoneSem, 200); // unit: ms
if (ETIMEDOUT == semRet)
{
alogw("wait inputFrameBufDoneSem 200ms timeout.");
continue;
}
else if (0 != semRet)
{
aloge("fatal error! cdx sem_down_timedwait fail, ret=%d", semRet);
}
else
{
alogd("got sem inputFrameBufDone");
}
}
}
else
{
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
pVideoEncData->mWaitInputFrameUsingEmptyFlag = TRUE;
while (1)
{
if (list_empty(&pVideoEncData->mBufQ.mUsingFrameList))
{
alogd("VencChn[%d] input orig Using FrameList is empty", pVideoEncData->mMppChnInfo.mChnId);
break;
}
int cnt = 0;
struct list_head *pList;
list_for_each(pList, &pVideoEncData->mBufQ.mUsingFrameList)
{
cnt++;
}
alogw("wait for VencChn[%d] input orig usingFrameList empty, left frames cnt = [%d]", pVideoEncData->mMppChnInfo.mChnId, cnt);
pthread_cond_wait(&pVideoEncData->mInputFrameUsingEmptyCondition, &pVideoEncData->mutex_fifo_ops_lock);
alogw("wait for VencChn[%d] input orig usingFrameList empty done", pVideoEncData->mMppChnInfo.mChnId);
}
pVideoEncData->mWaitInputFrameUsingEmptyFlag = FALSE;
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
// for return Used orig list from VencComp InputBufferDone callback.
if (!list_empty(&pVideoEncData->mBufQ.mUsedFrameList))
{
int num = 0;
VideoFrameInfoNode *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mBufQ.mUsedFrameList, mList)
{
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
VideoEncSendBackInputFrame(pVideoEncData, &pEntry->VFrame);
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
list_move_tail(&pEntry->mList, &pVideoEncData->mBufQ.mIdleFrameList);
pVideoEncData->mBufQ.buf_unused++;
alogv("VencChn[%d] release input orig frame ID[%d], list: Used -> Idle, buf unused[%d]", pVideoEncData->mMppChnInfo.mChnId,
pEntry->VFrame.mId, pVideoEncData->mBufQ.buf_unused);
num++;
}
alogd("VencChn[%d] return input orig [%d]frames list: Used -> Idle", pVideoEncData->mMppChnInfo.mChnId, num);
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
return 0;
}
static int UpdateReadyOutFrameList_l(VIDEOENCDATATYPE *pVideoEncData, VencOutputBuffer *pOutputBuffer)
{
if ((NULL == pVideoEncData) || (NULL == pOutputBuffer))
{
aloge("fatal error! invalid input params, %p, %p", pVideoEncData, pOutputBuffer);
return -1;
}
if (list_empty(&pVideoEncData->mIdleOutFrameList))
{
alogv("VencChn[%d] idle out frame list is empty, curNum[%d], malloc more!", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mFrameNodeNum);
ENCODER_NODE_T *pNode = (ENCODER_NODE_T*)malloc(sizeof(ENCODER_NODE_T));
if (pNode)
{
memset(pNode, 0, sizeof(ENCODER_NODE_T));
list_add_tail(&pNode->mList, &pVideoEncData->mIdleOutFrameList);
pVideoEncData->mFrameNodeNum++;
}
else
{
aloge("fatal error! malloc fail[%s]!", strerror(errno));
return ERR_VENC_NOMEM;
}
}
ENCODER_NODE_T *pEntry = list_first_entry(&pVideoEncData->mIdleOutFrameList, ENCODER_NODE_T, mList);
statVideoBitRate(pVideoEncData, pOutputBuffer);
config_EncodedStream_By_VencOutputBuffer(&pEntry->stEncodedStream, pOutputBuffer, pVideoEncData);
if(pVideoEncData->bForceKeyFrameFlag)
{
if(pOutputBuffer->nFlag & VENC_BUFFERFLAG_KEYFRAME)
{
char strVencType[64];
switch(pVideoEncData->mEncChnAttr.VeAttr.Type)
{
case PT_H264:
{
snprintf(strVencType, sizeof(strVencType), "%s", "h264");
break;
}
case PT_H265:
{
snprintf(strVencType, sizeof(strVencType), "%s", "h265");
break;
}
default:
{
snprintf(strVencType, sizeof(strVencType), "%s", "unknown");
break;
}
}
alogd("VeChn[%d]-[%s] receive sdk force I frame", pVideoEncData->mMppChnInfo.mChnId, strVencType);
pVideoEncData->bForceKeyFrameFlag = FALSE;
}
}
SIZE_S dstPicSize;
if (SUCCESS == getPicSizeFromVENC_ATTR_S(&pVideoEncData->mEncChnAttr.VeAttr, &dstPicSize))
{
unsigned int outSize = pOutputBuffer->nSize0 + pOutputBuffer->nSize1;
if (outSize > dstPicSize.Width*dstPicSize.Height*3/4)
{
alogw("VencChn[%d] Impossible! large frameSize[%d]Byte([%f]MB), [%d][%d], dstSize[%dx%d]!", pVideoEncData->mMppChnInfo.mChnId,
outSize, (float)outSize/(1024*1024), pOutputBuffer->nSize0, pOutputBuffer->nSize1, dstPicSize.Width, dstPicSize.Height);
}
if (outSize > pVideoEncData->mStatMaxFrameSize)
{
pVideoEncData->mStatMaxFrameSize = outSize;
alogv("VencChn[%d] current max frameSize[%d]Byte([%f]MB), dstSize[%dx%d]!", pVideoEncData->mMppChnInfo.mChnId,
outSize, (float)outSize/(1024*1024), dstPicSize.Width, dstPicSize.Height);
}
pVideoEncData->mStatStreamSize += outSize;
}
list_move_tail(&pEntry->mList, &pVideoEncData->mReadyOutFrameList);
alogv("output stream ID[%d] list: Idle -> Ready", pEntry->stEncodedStream.nID);
if (FALSE == pVideoEncData->mOutputPortTunnelFlag)
{
char tmpWrCh = 'V';
write(pVideoEncData->mOutputFrameNotifyPipeFds[1], &tmpWrCh, 1);
}
#ifdef STORE_VENC_OUT_STREAM
if (STORE_VENC_CH_ID == pVideoEncData->mMppChnInfo.mChnId)
{
if (g_debug_fp_stream == NULL)
{
g_debug_fp_stream = fopen(STORE_VENC_STREAM_FILE, "wb");
assert(g_debug_fp_stream != NULL);
alogd("####### [DEBUG] open %s, VencChn%d #######", STORE_VENC_STREAM_FILE, STORE_VENC_CH_ID);
VencHeaderData stHeaderData;
memset(&stHeaderData, 0, sizeof(VencHeaderData));
if(PT_H264 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamH264SPSPPS, (void*)&stHeaderData);
}
else if(PT_H265 == pVideoEncData->mEncChnAttr.VeAttr.Type)
{
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamH265Header, (void*)&stHeaderData);
}
if (stHeaderData.nLength)
{
fwrite(stHeaderData.pBuffer, 1, stHeaderData.nLength, g_debug_fp_stream);
}
}
if (pOutputBuffer->nSize0 > 0)
fwrite(pOutputBuffer->pData0, 1, pOutputBuffer->nSize0, g_debug_fp_stream);
if (pOutputBuffer->nSize1 > 0)
fwrite(pOutputBuffer->pData1, 1, pOutputBuffer->nSize1, g_debug_fp_stream);
if (pOutputBuffer->nSize2 > 0)
fwrite(pOutputBuffer->pData2, 1, pOutputBuffer->nSize2, g_debug_fp_stream);
g_debug_stream_cnt++;
}
#endif
return 0;
}
static int ProcessReadyOutFrameList(VIDEOENCDATATYPE *pVideoEncData)
{
int ret = 0;
if (FALSE == pVideoEncData->mOutputPortTunnelFlag)
{
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if (!list_empty(&pVideoEncData->mReadyOutFrameList))
{
if (pVideoEncData->mWaitOutFrameFlag)
{
alogv("vencChn[%d] send cond signal OutFrameCondition", pVideoEncData->mMppChnInfo.mChnId);
pthread_cond_signal(&pVideoEncData->mOutFrameCondition);
}
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
ret = 0;
}
else
{
//send all readyOutFrames to next tunnel-component.
if (!list_empty(&pVideoEncData->mReadyOutFrameList))
{
int num = 0;
ENCODER_NODE_T *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mReadyOutFrameList, mList)
{
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
list_move_tail(&pEntry->mList, &pVideoEncData->mUsedOutFrameList);
alogv("output stream ID[%d] list: Ready -> Used", pEntry->stEncodedStream.nID);
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex); // unlock before calling Empty ThisBuffer
num++;
COMP_BUFFERHEADERTYPE obh;
obh.nOutputPortIndex = pVideoEncData->sOutPortTunnelInfo.nPortIndex;
obh.nInputPortIndex = pVideoEncData->sOutPortTunnelInfo.nTunnelPortIndex;
obh.pOutputPortPrivate = (void*)&pEntry->stEncodedStream;
alogv("pOutTunnelComp->Empty ThisBuffer for non-compress source");
ERRORTYPE omxRet = COMP_EmptyThisBuffer(pVideoEncData->sOutPortTunnelInfo.hTunnel, &obh);
if (SUCCESS == omxRet)
{
//Notes: Must move buf node to UsedList before calling Empty ThisBuffer
}
else
{
aloge("fatal error! VEnc output frame fail[0x%x], return frame to venc!", omxRet);
VencOutputBuffer stOutputBuffer;
config_VencOutputBuffer_By_EncodedStream(&stOutputBuffer, &pEntry->stEncodedStream);
int vencLibRet = VencQueueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
if (vencLibRet != 0)
{
aloge("fatal error! Venc QueueOutputBuf fail[%d], returning stream may cause vencLib bitStream management error!", vencLibRet);
}
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Used -> Idle", pEntry->stEncodedStream.nID);
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
}
}
ret = 0;
}
return ret;
}
/*
static int UpdateOutputFrameList(VIDEOENCDATATYPE *pVideoEncData, VencOutputBuffer *pOutputBuffer)
{
if ((NULL == pVideoEncData) || (NULL == pOutputBuffer))
{
aloge("fatal error! invalid input params, %p, %p", pVideoEncData, pOutputBuffer);
return -1;
}
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if (list_empty(&pVideoEncData->mIdleOutFrameList))
{
alogv("Low probability! VEncComp idle out frame list is empty, curNum[%d], malloc more!", pVideoEncData->mFrameNodeNum);
ENCODER_NODE_T *pNode = (ENCODER_NODE_T*)malloc(sizeof(ENCODER_NODE_T));
if (pNode)
{
memset(pNode, 0, sizeof(ENCODER_NODE_T));
list_add_tail(&pNode->mList, &pVideoEncData->mIdleOutFrameList);
pVideoEncData->mFrameNodeNum++;
}
else
{
aloge("fatal error! malloc fail[%s]!", strerror(errno));
return ERR_VENC_NOMEM;
}
}
ENCODER_NODE_T *pEntry = list_first_entry(&pVideoEncData->mIdleOutFrameList, ENCODER_NODE_T, mList);
statVideoBitRate(pVideoEncData, pOutputBuffer);
config_EncodedStream_By_VencOutputBuffer(&pEntry->stEncodedStream, pOutputBuffer, pVideoEncData);
SIZE_S dstPicSize;
if (SUCCESS == getPicSizeFromVENC_ATTR_S(&pVideoEncData->mEncChnAttr.VeAttr, &dstPicSize))
{
unsigned int outSize = pOutputBuffer->nSize0 + pOutputBuffer->nSize1;
if (outSize > dstPicSize.Width*dstPicSize.Height*3/4)
{
alogw("Impossible! large frameSize[%d]Byte([%f]MB), [%d][%d], dstSize[%dx%d]!", outSize, (float)outSize/(1024*1024), pOutputBuffer->nSize0, pOutputBuffer->nSize1, dstPicSize.Width, dstPicSize.Height);
}
if (outSize > pVideoEncData->mStatMaxFrameSize)
{
pVideoEncData->mStatMaxFrameSize = outSize;
alogd("current max frameSize[%d]Byte([%f]MB), dstSize[%dx%d]!", outSize, (float)outSize/(1024*1024), dstPicSize.Width, dstPicSize.Height);
}
pVideoEncData->mStatStreamSize += outSize;
}
if (TRUE == pVideoEncData->mOutputPortTunnelFlag)
{
list_move_tail(&pEntry->mList, &pVideoEncData->mUsedOutFrameList);
alogv("output stream ID[%d] list: Idle -> Used", pEntry->stEncodedStream.nID);
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex); // unlock before calling Empty ThisBuffer
MM_COMPONENTTYPE *pOutTunnelComp = (MM_COMPONENTTYPE*)(pVideoEncData->sOutPortTunnelInfo.hTunnel);
COMP_BUFFERHEADERTYPE obh;
obh.nOutputPortIndex = pVideoEncData->sOutPortTunnelInfo.nPortIndex;
obh.nInputPortIndex = pVideoEncData->sOutPortTunnelInfo.nTunnelPortIndex;
obh.pOutputPortPrivate = (void*)&pEntry->stEncodedStream;
alogv("pOutTunnelComp->Empty ThisBuffer for non-compress source");
ERRORTYPE omxRet = pOutTunnelComp->EmptyThisBuffer(pOutTunnelComp, &obh);
if (SUCCESS == omxRet)
{
//Notes: Must move buf node to UsedList before calling Empty ThisBuffer
}
else
{
alogd("Be careful! VEnc output frame fail[0x%x], return frame to venc!", omxRet);
int vencLibRet = VencQueueOutputBuf(pVideoEncData->pCedarV, pOutputBuffer);
if (vencLibRet != 0)
{
aloge("fatal error! Venc QueueOutputBuf fail, ret=%d", vencLibRet);
}
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Used -> Idle", pEntry->stEncodedStream.nID);
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
}
else
{
list_move_tail(&pEntry->mList, &pVideoEncData->mReadyOutFrameList);
alogv("output stream ID[%d] list: Idle -> Ready", pEntry->stEncodedStream.nID);
if (pVideoEncData->mWaitOutFrameFlag)
{
pthread_cond_signal(&pVideoEncData->mOutFrameCondition);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
char tmpWrCh = 'V';
write(pVideoEncData->mOutputFrameNotifyPipeFds[1], &tmpWrCh, 1);
}
return 0;
}
*/
static void SendVencErrorTimeoutCallback(VIDEOENCDATATYPE *pVideoEncData, VideoFrameInfoNode *pFrameNode)
{
if ((NULL == pVideoEncData) || (NULL == pFrameNode))
{
aloge("fatal error! invalid input params! %p,%p", pVideoEncData, pFrameNode);
return;
}
pVideoEncData->mEncodeTimeoutCnt++;
SIZE_S PicSize = {0, 0};
getPicSizeFromVENC_ATTR_S(&pVideoEncData->mEncChnAttr.VeAttr, &PicSize);
unsigned int nBitRate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
aloge("fatal error! encode Error! vencChn[%d],vencType[%d],pixelFormat[0x%x],PicSrcDstSize[%dx%d->%dx%d],"
"frameRate[%d->%d],bitRate[%d],timeLapse:[%d,%lf,%lf],frameId[%d],pts[%lld]us, cntr[%d/%d]",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type,
pFrameNode->VFrame.VFrame.mPixelFormat,
pFrameNode->VFrame.VFrame.mWidth, pFrameNode->VFrame.VFrame.mHeight,
PicSize.Width, PicSize.Height,
pVideoEncData->mFrameRateInfo.SrcFrmRate, pVideoEncData->mFrameRateInfo.DstFrmRate,
nBitRate,
pVideoEncData->timeLapseEnable,
pVideoEncData->mCapTimeLapse.capFrameIntervalUs, pVideoEncData->mCapTimeLapse.videoFrameIntervalUs,
pFrameNode->VFrame.mId, pFrameNode->VFrame.VFrame.mpts,
pVideoEncData->mEncodeTimeoutCnt, pVideoEncData->mEncodeTotalCnt);
//send callback message to notify encode error
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventError,
ERR_VENC_TIMEOUT,
0,
(void*)&pFrameNode->VFrame.VFrame.mpts);
}
static void SendVencVbvFullCallback(VIDEOENCDATATYPE *pVideoEncData)
{
if (NULL == pVideoEncData)
{
aloge("fatal error! invalid input param");
return;
}
if (0 == pVideoEncData->bitStreamBufFullCnt)
{
unsigned int nBitRate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
alogw("Be careful! vencChn[%d] encode [%d]frames, fail BsFull, validFrames[%d], bitRate[%d]Mbit",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncodeTotalCnt, VencGetValidOutputBufNum(pVideoEncData->pCedarV), nBitRate/(1000*1000));
}
if (0 == pVideoEncData->bitStreamBufFullCnt % 30)
{
//alogw("vbv full contiguous count:%d", pVideoEncData->bitStreamBufFullCnt);
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventRecVbvFull,
0,
0,
NULL);
}
pVideoEncData->bitStreamBufFullCnt++;
}
static void SendVencDropFrameCallback(VIDEOENCDATATYPE *pVideoEncData)
{
if (NULL == pVideoEncData)
{
aloge("fatal error! invalid input param");
return;
}
pVideoEncData->mEncodeDropFrameCnt++;
alogd("vencChn[%d] usr set DropFrameNum[%d], encode [%d]frames, fail EncodeDropFrameCnt[%d]",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.mDropFrameNum, pVideoEncData->mEncodeTotalCnt, pVideoEncData->mEncodeDropFrameCnt);
//send callback message to notify encode discard frame
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventDropFrame,
0,
0,
NULL);
}
/**
* Component Thread
* The Component Thread function is exeuted in a separate pThread and
* is used to implement the actual component functions.
*/
/*****************************************************************************/
static void* ComponentThread(void* pThreadData)
{
unsigned int cmddata;
CompInternalMsgType cmd;
VIDEOENCDATATYPE* pVideoEncData = (VIDEOENCDATATYPE*) pThreadData;
message_t cmd_msg;
alogv("VideoEncoder ComponentThread start run...");
sprintf(pVideoEncData->mThreadName, "VEncChn%d", pVideoEncData->mMppChnInfo.mChnId);
prctl(PR_SET_NAME, (unsigned long)pVideoEncData->mThreadName, 0, 0, 0);
while (1)
{
PROCESS_MESSAGE:
if (get_message(&pVideoEncData->cmd_queue, &cmd_msg) == 0)
{
cmd = cmd_msg.command;
cmddata = (unsigned int)cmd_msg.para0;
alogv("VideoEnc Component Thread get_message cmd:%d", cmd);
// State transition command
if (cmd == SetState)
{
pthread_mutex_lock(&pVideoEncData->mStateLock);
// If the parameter states a transition to the same state
// raise a same state transition error.
if (pVideoEncData->state == (COMP_STATETYPE) (cmddata))
pVideoEncData->pCallbacks->EventHandler(pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventError,
ERR_VENC_SAMESTATE,
0,
NULL);
else
{
// transitions/callbacks made based on state transition table
// cmddata contains the target state
switch ((COMP_STATETYPE) (cmddata))
{
case COMP_StateInvalid:
pVideoEncData->state = COMP_StateInvalid;
pVideoEncData->pCallbacks->EventHandler(pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventError,
ERR_VENC_INVALIDSTATE,
0,
NULL);
pVideoEncData->pCallbacks->EventHandler(pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pVideoEncData->state,
NULL);
break;
case COMP_StateLoaded:
{
if (pVideoEncData->state != COMP_StateIdle)
{
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventError,
ERR_VENC_INCORRECT_STATE_TRANSITION,
0,
NULL);
}
alogv("VencChn[%d] StateLoaded begin", pVideoEncData->mMppChnInfo.mChnId);
//MM_COMPONENTTYPE *InputTunnelComp = (MM_COMPONENTTYPE *)(pVideoEncData->sInPortTunnelInfo.hTunnel);
VideoEncResetChannel(pVideoEncData->hSelf, FALSE);
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
pVideoEncData->mWaitOutFrameFullFlag = TRUE;
//wait all outFrame return.
int cnt;
struct list_head *pList;
while(1)
{
int cnt1 = 0;
list_for_each(pList, &pVideoEncData->mReadyOutFrameList)
{
cnt1++;
}
int cnt2 = 0;
list_for_each(pList, &pVideoEncData->mUsedOutFrameList)
{
cnt2++;
}
cnt = 0;
list_for_each(pList, &pVideoEncData->mIdleOutFrameList)
{
cnt++;
}
if(cnt+cnt1<pVideoEncData->mFrameNodeNum)
{
alogw("wait VencChn[%d] idleOutFrameList full:%d-%d-%d-%d", pVideoEncData->mMppChnInfo.mChnId, cnt,cnt1,cnt2,
pVideoEncData->mFrameNodeNum);
pthread_cond_wait(&pVideoEncData->mOutFrameFullCondition, &pVideoEncData->mOutFrameListMutex);
alogw("wait VencChn[%d] idleOutFrameList full_done", pVideoEncData->mMppChnInfo.mChnId);
}
else
{
break;
}
}
// to force release the frm in readyoutlist after the one in usedoutlist,the frm releasing order is
// important for the vbv buffer in venc library.
//added for fixing bug that one new encoded frm is added to readylist when out frm buffer
//is avaliable in case that decode process is suspended when vbv full is full.the new added
//frm registered in readylist will not be fetched out since the operation of app,such as the
// reset operation including the component destruction.
while((!list_empty(&pVideoEncData->mReadyOutFrameList)))
{
ENCODER_NODE_T *pEntry = list_first_entry(&pVideoEncData->mReadyOutFrameList, ENCODER_NODE_T, mList);
if (pVideoEncData->is_compress_source == 0)
{
VencOutputBuffer stOutputBuffer;
config_VencOutputBuffer_By_EncodedStream(&stOutputBuffer, &pEntry->stEncodedStream);
VencQueueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Ready -> Idle", pEntry->stEncodedStream.nID);
if(FALSE == pVideoEncData->mOutputPortTunnelFlag)
{
char tmpRdCh;
read(pVideoEncData->mOutputFrameNotifyPipeFds[0], &tmpRdCh, 1);
}
}
}
cnt = 0;
list_for_each(pList, &pVideoEncData->mIdleOutFrameList)
{
cnt++;
}
if(cnt<pVideoEncData->mFrameNodeNum)
{
aloge("fatal error! wait Venc idleOutFrameList full:%d-%d",cnt,pVideoEncData->mFrameNodeNum);
}
pVideoEncData->mWaitOutFrameFullFlag = FALSE;
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
alogv("wait Venc idleOutFrameList full done");
pVideoEncData->state = COMP_StateLoaded;
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf, pVideoEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pVideoEncData->state,
NULL);
alogv("VencChn[%d] StateLoaded ok", pVideoEncData->mMppChnInfo.mChnId);
break;
}
case COMP_StateIdle:
{
if(pVideoEncData->state == COMP_StateLoaded)
{
//pVideoEncData->mMemOps = MemAdapterGetOpsS();
alogv("VencChn[%d]: loaded->idle ...", pVideoEncData->mMppChnInfo.mChnId);
//create vdeclib!
if(pVideoEncData->is_compress_source == 0)
{
CedarvEncInit(pVideoEncData);
}
else
{
alogd("VencChn[%d] component is in compress mode, create buffer manager.", pVideoEncData->mMppChnInfo.mChnId);
if (pVideoEncData->buffer_manager == NULL)
{
pVideoEncData->buffer_manager = VideoEncBufferInit();
}
}
pVideoEncData->state = COMP_StateIdle;
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pVideoEncData->state,
NULL);
}
else if(pVideoEncData->state == COMP_StatePause || pVideoEncData->state == COMP_StateExecuting)
{
alogv("VencChn[%d]: pause/executing[0x%x]->idle ...", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->state);
#ifdef ENABLE_ENCODE_STATISTICS
VencEncodeTimeS stEncodeStatistics;
memset(&stEncodeStatistics, 0, sizeof(VencEncodeTimeS));
if(pVideoEncData->pCedarV)
{
VencGetParameter(pVideoEncData->pCedarV, VENC_IndexParamGetEncodeTime, (void*)&stEncodeStatistics);
alogd("VencChn[%d] statistics: avrIdleTime[%d]us, avrEncTime[%d]us, maxIdleTime[%d]us, maxEncTime[%d]us; totalFrame:[%d]",
pVideoEncData->mMppChnInfo.mChnId, stEncodeStatistics.avr_empty_time, stEncodeStatistics.avr_enc_time,
stEncodeStatistics.max_empty_time, stEncodeStatistics.max_enc_time, stEncodeStatistics.frame_num);
}
#endif
if (0 == pVideoEncData->mOnlineEnableFlag)
{
VENC_RESULT_TYPE venclib_ret = VencPause(pVideoEncData->pCedarV);
if (VENC_RESULT_OK != venclib_ret)
{
aloge("fatal error! Venc Pause fail, ret=%d", venclib_ret);
}
venclib_ret = VencFlush(pVideoEncData->pCedarV, VENC_FLUSH_INPUT_BUFFER);
if(venclib_ret != VENC_RESULT_OK)
{
aloge("fatal error! venc flush input buffer fail:%d", venclib_ret);
}
ReturnUseOrigFrameBeforeSetStateIdle(pVideoEncData);
}
else
{
int venclib_ret = VencPause(pVideoEncData->pCedarV);
if (VENC_RESULT_OK != venclib_ret)
{
aloge("fatal error! Venc Pause fail, ret=%d", venclib_ret);
}
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if (!list_empty(&pVideoEncData->mBufQ.mUsedFrameList))
{
VideoFrameInfoNode *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pVideoEncData->mBufQ.mUsedFrameList, mList)
{
list_move_tail(&pEntry->mList, &pVideoEncData->mBufQ.mIdleFrameList);
pVideoEncData->mBufQ.buf_unused++;
}
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
pVideoEncData->state = COMP_StateIdle;
VideoEncResetChannel(pVideoEncData->hSelf, FALSE);
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pVideoEncData->state,
NULL);
}
else
{
aloge("fatal error! current state[0x%x] can't turn to idle!", pVideoEncData->state);
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventError,
ERR_VENC_INCORRECT_STATE_TRANSITION,
0,
NULL);
}
break;
}
case COMP_StateExecuting:
// Transition can only happen from pause or idle state
if (pVideoEncData->state == COMP_StateIdle || pVideoEncData->state == COMP_StatePause)
{
int eError = SUCCESS;
if( COMP_StateIdle == pVideoEncData->state)
{
if(NULL == pVideoEncData->pCedarV)
{
if(pVideoEncData->is_compress_source == 0)
{
CedarvEncInit(pVideoEncData);
}
}
pthread_mutex_lock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
if(pVideoEncData->pCedarV && !pVideoEncData->mbCedarvVideoEncInitFlag)
{
eError = CedarvVideoEncInit(pVideoEncData);
if(SUCCESS == eError)
{
pVideoEncData->mbCedarvVideoEncInitFlag = TRUE;
}
else
{
aloge("fatal error! vdeclib init fail[0x%x]", eError);
}
}
pthread_mutex_unlock(&pVideoEncData->mCedarvVideoEncInitFlagLock);
int venclib_ret = VencStart(pVideoEncData->pCedarV);
if (VENC_RESULT_OK != venclib_ret)
{
aloge("fatal error! Venc Start fail, ret=%d", venclib_ret);
eError = FAILURE;
}
}
else if (COMP_StatePause == pVideoEncData->state)
{
int venclib_ret = VencStart(pVideoEncData->pCedarV);
if (VENC_RESULT_OK != venclib_ret)
{
aloge("fatal error! Venc Start fail, ret=%d", venclib_ret);
eError = FAILURE;
}
}
if(SUCCESS == eError)
{
alogv("VencChn[%d]: idle/pause[0x%x]->executing ...", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->state);
pVideoEncData->state = COMP_StateExecuting;
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pVideoEncData->state,
NULL);
}
else
{
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventError,
ERR_VENC_INCORRECT_STATE_TRANSITION,
eError,
NULL);
}
}
else
{
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventError,
ERR_VENC_INCORRECT_STATE_TRANSITION,
0,
NULL);
}
break;
case COMP_StatePause:
// Transition can only happen from idle or executing state
if (pVideoEncData->state == COMP_StateIdle || pVideoEncData->state == COMP_StateExecuting)
{
int venclib_ret = VencPause(pVideoEncData->pCedarV);
if (VENC_RESULT_OK == venclib_ret)
{
alogd("VencChn[%d] Pause success", pVideoEncData->mMppChnInfo.mChnId);
pVideoEncData->state = COMP_StatePause;
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pVideoEncData->state,
NULL);
}
else
{
aloge("fatal error! Venc Pause fail, ret=%d", venclib_ret);
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf,
pVideoEncData->pAppData,
COMP_EventError,
ERR_VENC_INCORRECT_STATE_TRANSITION,
venclib_ret,
NULL);
}
}
else
{
pVideoEncData->pCallbacks->EventHandler(
pVideoEncData->hSelf, pVideoEncData->pAppData,
COMP_EventError,
ERR_VENC_INCORRECT_STATE_TRANSITION,
0,
NULL);
}
break;
default:
break;
}
}
pthread_mutex_unlock(&pVideoEncData->mStateLock);
}
else if (cmd == Flush)
{
}
else if (cmd == Stop)
{
// Kill thread
goto EXIT;
}
else if(cmd == VEncComp_InputFrameAvailable)
{
}
else if(cmd == VEncComp_OutputFrameReturn)
{
}
else if(cmd == VEncComp_OutputStreamAvailable)
{
}
//precede to process message
goto PROCESS_MESSAGE;
}
if (pVideoEncData->state == COMP_StateExecuting)
{
if (SendCropYuvToApp(pVideoEncData) == 0)
{
alogv("Have sent crop yuv data to app");
}
/*else
{
aloge("Failed to grab crop YUV data");
}*/
FillSeiDataToVencLib(pVideoEncData);
/* For Venc online mode and online channel.
* MPP Venc component do not need to participate in the management of the frame buffer.
* The dirver layer implements the logical management of the frame buffer.
* MPP Venc component only need to start from ve_driver obtains the encoded stream data.
*/
if (pVideoEncData->mOnlineEnableFlag)
{
// Request all output streams from the encoding library at once.
int reqCodedFrameCnt = 0;
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
while (1)
{
VencOutputBuffer stOutputBuffer;
int vencLibRet = VencDequeueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
alogv("Venc DequeueOutputBuf ret=%d", vencLibRet);
if (0 != vencLibRet)
{
break;
}
reqCodedFrameCnt++;
int ret = UpdateReadyOutFrameList_l(pVideoEncData, &stOutputBuffer);
if (0 != ret)
{
aloge("fatal error! update ReadyOutFrameList fail? check code!");
break;
}
}
pVideoEncData->mFlagOutputStream = 0;
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
//process ReadyOutFrameList. if tunnel mode, send frame to next component; if non-tunnel mode, signal if necessary.
ProcessReadyOutFrameList(pVideoEncData);
if (0 == reqCodedFrameCnt)
{
alogv("No encoded stream requested, wait for message");
TMessage_WaitQueueNotEmpty(&pVideoEncData->cmd_queue, 10*1000);
}
else
{
alogv("req CodedFrameCnt = %d", reqCodedFrameCnt);
}
// for online, processing venc result only, no need to return input orig frame
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if (!list_empty(&pVideoEncData->mBufQ.mUsedFrameList))
{
VideoFrameInfoNode *pUsedFrameNode = NULL;
VideoFrameInfoNode *pTmp = NULL;
list_for_each_entry_safe(pUsedFrameNode, pTmp, &pVideoEncData->mBufQ.mUsedFrameList, mList)
{
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
int result = pUsedFrameNode->mResult;
if (VENC_RESULT_ERROR == result)
{
SendVencErrorTimeoutCallback(pVideoEncData, pUsedFrameNode);
}
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
list_move_tail(&pUsedFrameNode->mList, &pVideoEncData->mBufQ.mIdleFrameList);
pVideoEncData->mBufQ.buf_unused++;
alogv("release input orig frame ID[%d], list: Used -> Idle, buf unused[%d]", pUsedFrameNode->VFrame.mId, pVideoEncData->mBufQ.buf_unused);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
// let's process encode result.
if (VENC_RESULT_OK != result)
{
if (VENC_RESULT_BITSTREAM_IS_FULL == result)
{
pVideoEncData->mEncodeVbvFulDiscardFrameCnt++;
SendVencVbvFullCallback(pVideoEncData);
if (FALSE == pVideoEncData->mOutputPortTunnelFlag)
{
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if (pVideoEncData->mWaitOutFrameFlag)
{
pthread_cond_signal(&pVideoEncData->mOutFrameCondition);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
}
else if (VENC_RESULT_DROP_FRAME == result)
{
SendVencDropFrameCallback(pVideoEncData);
alogw("chn[%d] encode result=%d(drop_frm)", pVideoEncData->mMppChnInfo.mChnId, result);
}
else if (VENC_RESULT_CONTINUE == result)
{
alogv("chn[%d] encode result=%d(continue)", pVideoEncData->mMppChnInfo.mChnId, result);
}
else
{
alogw("chn[%d] encode result=%d", pVideoEncData->mMppChnInfo.mChnId, result);
}
}
else
{
if (pVideoEncData->bitStreamBufFullCnt != 0)
{
unsigned int nBitRate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
alogw("vencChn[%d] fail BsFull[%d] contiguous count:%d, send vbvFull msg [%d]times, validFrames[%d], bitRate[%d]Mbit",
pVideoEncData->mMppChnInfo.mChnId, result, pVideoEncData->bitStreamBufFullCnt, pVideoEncData->bitStreamBufFullCnt/30+1,
VencGetValidOutputBufNum(pVideoEncData->pCedarV), nBitRate/(1000*1000));
pVideoEncData->bitStreamBufFullCnt = 0;
}
}
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
}
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
goto PROCESS_MESSAGE;
}
// For Venc offline mode or online mode but offline channel.
if (pVideoEncData->is_compress_source == 0)
{
if (FALSE == pVideoEncData->mbForbidDiscardingFrame) //allow to drop frame, e.g., h264,h265,mjpeg
{
// Request all output streams from the encoding library at once.
int reqCodedFrameCnt = 0;
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
while (1)
{
VencOutputBuffer stOutputBuffer;
int vencLibRet = VencDequeueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
alogv("vencChn[%d] DequeueOutputBuf ret=%d", pVideoEncData->mMppChnInfo.mChnId, vencLibRet);
if (0 != vencLibRet)
{
break;
}
// int streamSize = stOutputBuffer.nSize0+stOutputBuffer.nSize1+stOutputBuffer.nSize2;
// if(streamSize >= 100*1024)
// {
// alogd("vencChn[%d] encodeCnt[%d]: streamSize[%d]KB>=100KB", pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncodeTotalCnt, streamSize/1024);
// }
reqCodedFrameCnt++;
int ret = UpdateReadyOutFrameList_l(pVideoEncData, &stOutputBuffer);
if (0 != ret)
{
aloge("fatal error! update ReadyOutFrameList fail? check code!");
break;
}
}
pVideoEncData->mFlagOutputStream = 0;
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
//process ReadyOutFrameList. if tunnel mode, send frame to next component; if non-tunnel mode, signal if necessary.
ProcessReadyOutFrameList(pVideoEncData);
if (0 == reqCodedFrameCnt)
{
BOOL bInputUsedFrameFlag = TRUE;
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if (list_empty(&pVideoEncData->mBufQ.mUsedFrameList))
{
bInputUsedFrameFlag = FALSE;
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
if(FALSE == bInputUsedFrameFlag)
{
alogv("vencChn[%d] No encoded stream requested, wait for message", pVideoEncData->mMppChnInfo.mChnId);
int nMsgNum = TMessage_WaitQueueNotEmpty(&pVideoEncData->cmd_queue, 1000);
if(0 == nMsgNum)
{
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
int nReadyNum = 0;
int nUsingNum = 0;
int nUsedNum = 0;
struct list_head *pList;
list_for_each(pList, &pVideoEncData->mBufQ.mReadyFrameList)
{
nReadyNum++;
}
list_for_each(pList, &pVideoEncData->mBufQ.mUsingFrameList)
{
nUsingNum++;
}
list_for_each(pList, &pVideoEncData->mBufQ.mUsedFrameList)
{
nUsedNum++;
}
if(!(pVideoEncData->timeLapseEnable && (pVideoEncData->mCapTimeLapse.recType == COMP_RECORD_TYPE_TIMELAPSE)))
{
alogw("Be careful! vencChn[%d] timeout for waiting outputStream. input frames stat:ready[%d]+using[%d]+used[%d]=total[%d]",
pVideoEncData->mMppChnInfo.mChnId, nReadyNum, nUsingNum, nUsedNum, nReadyNum+nUsingNum+nUsedNum);
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
}
}
else
{
alogv("vencChn[%d] req CodedFrameCnt = %d", pVideoEncData->mMppChnInfo.mChnId, reqCodedFrameCnt);
}
// return input orig used frames, and process venc result.
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if (!list_empty(&pVideoEncData->mBufQ.mUsedFrameList))
{
alogv("return input orig frames");
VideoFrameInfoNode *pUsedFrameNode = NULL;
VideoFrameInfoNode *pTmp = NULL;
list_for_each_entry_safe(pUsedFrameNode, pTmp, &pVideoEncData->mBufQ.mUsedFrameList, mList)
{
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
int result = pUsedFrameNode->mResult;
if (VENC_RESULT_ERROR == result)
{
SendVencErrorTimeoutCallback(pVideoEncData, pUsedFrameNode);
}
// return input orig frame
VideoEncSendBackInputFrame(pVideoEncData, &pUsedFrameNode->VFrame);
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
list_move_tail(&pUsedFrameNode->mList, &pVideoEncData->mBufQ.mIdleFrameList);
pVideoEncData->mBufQ.buf_unused++;
alogv("vencChn[%d] release input orig frame ID[%d], list: Used -> Idle, buf unused[%d]", pVideoEncData->mMppChnInfo.mChnId,
pUsedFrameNode->VFrame.mId, pVideoEncData->mBufQ.buf_unused);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
// let's process encode result.
if (VENC_RESULT_OK != result)
{
if (VENC_RESULT_BITSTREAM_IS_FULL == result)
{
pVideoEncData->mEncodeVbvFulDiscardFrameCnt++;
SendVencVbvFullCallback(pVideoEncData);
if (FALSE == pVideoEncData->mOutputPortTunnelFlag)
{
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if (pVideoEncData->mWaitOutFrameFlag)
{
pthread_cond_signal(&pVideoEncData->mOutFrameCondition);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
}
else if (VENC_RESULT_DROP_FRAME == result)
{
SendVencDropFrameCallback(pVideoEncData);
alogw("chn[%d] encode result=%d(drop_frm)", pVideoEncData->mMppChnInfo.mChnId, result);
}
else
{
alogw("chn[%d] encode result=%d", pVideoEncData->mMppChnInfo.mChnId, result);
}
}
else
{
if (pVideoEncData->bitStreamBufFullCnt != 0)
{
unsigned int nBitRate = GetBitRateFromVENC_CHN_ATTR_S(&pVideoEncData->mEncChnAttr);
alogw("Be careful! vencChn[%d] encode [%d]frames, fail BsFull[%d] contiguous count:%d, send vbvFull msg [%d]times, validFrames[%d], bitRate[%d]Mbit",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncodeTotalCnt, result, pVideoEncData->bitStreamBufFullCnt,
pVideoEncData->bitStreamBufFullCnt/30+1, VencGetValidOutputBufNum(pVideoEncData->pCedarV), nBitRate/(1000*1000));
pVideoEncData->bitStreamBufFullCnt = 0;
}
}
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
}
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
else //forbid to drop frame, e.g., jpeg
{
if(pVideoEncData->mEncChnAttr.VeAttr.Type != PT_JPEG)
{
aloge("fatal error! VencChn[%d] forbid discarding frame, but encodeType[%d] is not jpeg!",
pVideoEncData->mMppChnInfo.mChnId, pVideoEncData->mEncChnAttr.VeAttr.Type);
}
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
// Forbid Discarding Frame flow, the execution will not continue when there is no input frame.
if ((list_empty(&pVideoEncData->mBufQ.mReadyFrameList)) &&
(list_empty(&pVideoEncData->mBufQ.mUsingFrameList)) &&
(list_empty(&pVideoEncData->mBufQ.mUsedFrameList)))
{
pVideoEncData->mFlagInputFrame = 0;
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
if(0 == TMessage_WaitQueueNotEmpty(&pVideoEncData->cmd_queue, 5000))
{
alogw("Be careful! wait timeout. jpeg input orig frame list: Ready & Using & Used are all empty");
}
goto PROCESS_MESSAGE;
}
VideoFrameInfoNode *pReadyFrameNode = list_first_entry(&pVideoEncData->mBufQ.mReadyFrameList, VideoFrameInfoNode, mList);
if (0 == pVideoEncData->mFlagDoNotSendOrigFrameToVencLib)
{
alogv("send only one orig ready frame to venc lib at once.");
int ret = SendOrigFrameToVencLib(pVideoEncData, pReadyFrameNode);
if (0 != ret)
{
aloge("fatal error! vencChn[%d] Send OrigFrameToVencLib fail, ret=%d", pVideoEncData->mMppChnInfo.mChnId, ret);
}
else
{
list_move_tail(&pReadyFrameNode->mList, &pVideoEncData->mBufQ.mUsingFrameList);
pVideoEncData->mInputFrameCnt++;
alogv("input orig frame ID[%d] list: Ready -> Using", pReadyFrameNode->VFrame.mId);
if(list_empty(&pVideoEncData->mBufQ.mReadyFrameList))
{
pVideoEncData->mFlagInputFrame = 0;
}
}
}
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
// wait for Venc CompInputBufferDone callback.
int semRet = cdx_sem_down_timedwait(&pVideoEncData->mInputFrameBufDoneSem, 200); // unit: ms
if (ETIMEDOUT == semRet)
{
alogw("vencChn[%d] wait inputFrameBufDoneSem 200ms timeout, goto PROCESS_MESSAGE, but DO NOT send orig frame to venc lib.",
pVideoEncData->mMppChnInfo.mChnId);
pVideoEncData->mFlagDoNotSendOrigFrameToVencLib = 1;
}
else if (0 == semRet)
{
// process encode result.
pVideoEncData->mFlagDoNotSendOrigFrameToVencLib = 0;
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
if (!list_empty(&pVideoEncData->mBufQ.mUsedFrameList))
{
VideoFrameInfoNode *pUsedFrameNode = list_first_entry(&pVideoEncData->mBufQ.mUsedFrameList, VideoFrameInfoNode, mList);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
int result = pUsedFrameNode->mResult;
alogv("venc frame ID[%d] result=%d", pUsedFrameNode->VFrame.mId, result);
if (VENC_RESULT_OK == result)
{
// Get coded frame from venc lib.
VencOutputBuffer stOutputBuffer;
int ret = VencDequeueOutputBuf(pVideoEncData->pCedarV, &stOutputBuffer);
if (0 != ret)
{
aloge("fatal error! Venc DequeueOutputBuf fail when result=OK, ret=%d", ret);
}
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
ret = UpdateReadyOutFrameList_l(pVideoEncData, &stOutputBuffer);
if (0 != ret)
{
aloge("fatal error! update ReadyOutFrameList fail? check code!");
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
//process ReadyOutFrameList. if tunnel mode, send frame to next component; if non-tunnel mode, signal if necessary.
//when forbid DiscardingFrame, only non-tunnel is available.
ProcessReadyOutFrameList(pVideoEncData);
// return input orig frame
VideoEncSendBackInputFrame(pVideoEncData, &pUsedFrameNode->VFrame);
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
list_move_tail(&pUsedFrameNode->mList, &pVideoEncData->mBufQ.mIdleFrameList);
pVideoEncData->mBufQ.buf_unused++;
alogv("release input orig frame ID[%d], list: Used -> Idle, buf unused[%d]", pUsedFrameNode->VFrame.mId, pVideoEncData->mBufQ.buf_unused);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
else if (VENC_RESULT_BITSTREAM_IS_FULL == result)
{
//pVideoEncData->mEncodeVbvFulDiscardFrameCnt++;
SendVencVbvFullCallback(pVideoEncData);
// wait for 200ms, if no message, will do coded again.
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
pVideoEncData->mWaitOutFrameReturnFlag = TRUE;
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
alogw("result=VBV FULL, wait for cmd queue message 200ms.");
if (TMessage_WaitQueueNotEmpty(&pVideoEncData->cmd_queue, 200) <= 0) // unit: ms
{
alogw("vencChn[%d] result=%d(bitstream full), will do venc again.", pVideoEncData->mMppChnInfo.mChnId, result);
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
list_move(&pUsedFrameNode->mList, &pVideoEncData->mBufQ.mReadyFrameList);
alogv("re-encode input orig frame ID[%d], list: Used -> Ready", pUsedFrameNode->VFrame.mId);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
}
else
{
if (VENC_RESULT_ERROR == result)
{
SendVencErrorTimeoutCallback(pVideoEncData, pUsedFrameNode);
}
// will do coded again.
//pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
//pVideoEncData->mWaitOutFrameReturnFlag = TRUE;
//pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
aloge("fatal error! vencChn[%d] result=%d, will do venc again.", pVideoEncData->mMppChnInfo.mChnId, result);
pthread_mutex_lock(&pVideoEncData->mutex_fifo_ops_lock);
list_move(&pUsedFrameNode->mList, &pVideoEncData->mBufQ.mReadyFrameList);
alogv("re-encode input orig frame ID[%d], list: Used -> Ready", pUsedFrameNode->VFrame.mId);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
// clear FlagStream, It's just a process step, not useful for the process of Forbid Discarding Frame.
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
pVideoEncData->mFlagOutputStream = 0;
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
else
{
aloge("fatal error! vencChn[%d] The input orig frame Used list is empty!", pVideoEncData->mMppChnInfo.mChnId);
pthread_mutex_unlock(&pVideoEncData->mutex_fifo_ops_lock);
}
}
else
{
aloge("fatal error! vencChn[%d] cdx sem_down_timedwait fail, ret=%d", pVideoEncData->mMppChnInfo.mChnId, semRet);
pVideoEncData->mFlagDoNotSendOrigFrameToVencLib = 0;
}
}
}
else
{ /* gushiming compressed source */
ERRORTYPE eError;
ERRORTYPE releaseOmxRet;
FRAMEDATATYPE frame;
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
if(list_empty(&pVideoEncData->mIdleOutFrameList))
{
aloge("fatal error! why idleOutFrameList is empty when in compressed source? wait 200ms");
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
usleep(200*1000);
continue;
}
ENCODER_NODE_T *pEntry = list_first_entry(&pVideoEncData->mIdleOutFrameList, ENCODER_NODE_T, mList);
memset(&pEntry->stEncodedStream, 0 , sizeof(EncodedStream));
eError = VideoEncBufferGetFrame(pVideoEncData->buffer_manager, &frame);
if (eError == SUCCESS)
{
pEntry->stEncodedStream.nFilledLen = (unsigned int)frame.info.size;
pEntry->stEncodedStream.pBuffer = (unsigned char*)frame.addrY;
pEntry->stEncodedStream.nBufferLen = (unsigned int)frame.info.size;
pEntry->stEncodedStream.pBufferExtra = NULL;
pEntry->stEncodedStream.nBufferExtraLen = 0;
if(VideoEncAnalyseCompressedFrame(pVideoEncData, &frame))
{
pEntry->stEncodedStream.nFlags |= CEDARV_FLAG_KEYFRAME;
}
pEntry->stEncodedStream.nTimeStamp = frame.info.timeStamp/* - pVideoEncData->csi_base_time*/;
pEntry->stEncodedStream.nID = frame.info.bufferId;
alogv("rd buf_id: %d, nTimeStamp: %lld", pEntry->stEncodedStream.nID, pEntry->stEncodedStream.nTimeStamp);
if (pVideoEncData->mOutputPortTunnelFlag)
{
list_move_tail(&pEntry->mList, &pVideoEncData->mUsedOutFrameList);
alogv("output stream ID[%d] list: Idle -> Used", pEntry->stEncodedStream.nID);
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex); //Notes: unlock before calling Empty ThisBuffer
if(!pVideoEncData->mbSendSpspps)
{
if(pVideoEncData->mpVencHeaderData)
{
if(pVideoEncData->mpVencHeaderData->pBuffer != NULL && pVideoEncData->mpVencHeaderData->nLength > 0)
{
ERRORTYPE ret = COMP_SetConfig(pVideoEncData->sOutPortTunnelInfo.hTunnel, COMP_IndexVendorExtraData, pVideoEncData->mpVencHeaderData);
if(SUCCESS == ret)
{
pVideoEncData->mbSendSpspps = TRUE;
}
else
{
aloge("fatal error! why set spspps fail[0x%x]?", ret);
}
}
}
}
MM_COMPONENTTYPE *pOutTunnelComp = (MM_COMPONENTTYPE*)(pVideoEncData->sOutPortTunnelInfo.hTunnel);
COMP_BUFFERHEADERTYPE obh;
obh.nOutputPortIndex = pVideoEncData->sOutPortTunnelInfo.nPortIndex;
obh.nInputPortIndex = pVideoEncData->sOutPortTunnelInfo.nTunnelPortIndex;
obh.pOutputPortPrivate = (void*)&pEntry->stEncodedStream;
alogd("pOutTunnelComp->Empty ThisBuffer for compress source");
ERRORTYPE omxRet = pOutTunnelComp->EmptyThisBuffer(pOutTunnelComp, &obh);
if (SUCCESS == omxRet)
{
// Must move to UsedList before calling Empty ThisBuffer
}
else
{
aloge("fatal error! VEnc output frame fail, return frame to buffer_manager!");
releaseOmxRet = VideoEncBufferReleaseFrame(pVideoEncData->buffer_manager, &frame);
if (releaseOmxRet != SUCCESS)
{
aloge("fatal error! videoEncBufferReleaseFrame fail[%d]", releaseOmxRet);
}
pthread_mutex_lock(&pVideoEncData->mOutFrameListMutex);
list_move_tail(&pEntry->mList, &pVideoEncData->mIdleOutFrameList);
alogv("output stream ID[%d] list: Used -> Idle", pEntry->stEncodedStream.nID);
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
}
else
{
list_add_tail(&pEntry->mList, &pVideoEncData->mReadyOutFrameList);
if (pVideoEncData->mWaitOutFrameFlag)
{
pthread_cond_signal(&pVideoEncData->mOutFrameCondition);
}
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
}
continue;
}
else
{
pVideoEncData->mFlagInputFrame = 0;
pthread_mutex_unlock(&pVideoEncData->mOutFrameListMutex);
TMessage_WaitQueueNotEmpty(&pVideoEncData->cmd_queue, 0);
continue;
}
}
}
else
{
alogv("Encoder Component Thread not OMX_StateExecuting\n");
TMessage_WaitQueueNotEmpty(&pVideoEncData->cmd_queue, 0);
}
}
EXIT:
alogv("VideoEncoder Component Thread stopped");
return (void*) SUCCESS;
}