📄 encinternalapi.c
字号:
/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- In the event of publication, the following notice is applicable: --
-- --
-- (C) COPYRIGHT 2003 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced on all copies. --
-- --
--------------------------------------------------------------------------------
--
-- Abstract : Encoder API helper functions
--
-------------------------------------------------------------------------------*/
#include "mp4encapi.h"
#include "enccontainer.h"
#include "encinternal.h"
#include "encregdrv.h"
#include "encmemory.h"
#include "ewl.h"
static void SetRcParameter(rateControl_s *rc);
static void GetRcParameter(rateControl_s *rc);
static void EndianSwap(u32 *buf, u32 wordCnt);
/*------------------------------------------------------------------------------
Check the config structure for valid values.
Return: 0 OK
-1 Invalid value
------------------------------------------------------------------------------*/
i32 CheckInitCfg(const MP4EncCfg * pEncCfg)
{
ASSERT(pEncCfg != NULL);
if(pEncCfg->width < 6 * 16 ||
pEncCfg->width > 40 * 16 || (pEncCfg->width / 4) * 4 != pEncCfg->width)
{
return -1;
}
if(pEncCfg->height < 6 * 16 || pEncCfg->height > (30 * 16))
{
return -1;
}
if(pEncCfg->frmRateNum == 0 || pEncCfg->frmRateNum >= (1 << 16))
{
return -1;
}
if(pEncCfg->frmRateDenom == 0)
{
return -1;
}
/* Check that stream type is valid */
if(pEncCfg->strmType > H263_STRM)
{
return -1;
}
/* Check that profile and level is valid for MPEG4 stream */
if((pEncCfg->strmType < H263_STRM) &&
(pEncCfg->profileAndLevel != MPEG4_SIMPLE_PROFILE_LEVEL_0) &&
(pEncCfg->profileAndLevel != MPEG4_SIMPLE_PROFILE_LEVEL_0B) &&
(pEncCfg->profileAndLevel != MPEG4_SIMPLE_PROFILE_LEVEL_1) &&
(pEncCfg->profileAndLevel != MPEG4_SIMPLE_PROFILE_LEVEL_2) &&
(pEncCfg->profileAndLevel != MPEG4_SIMPLE_PROFILE_LEVEL_3) &&
(pEncCfg->profileAndLevel != 50) && /* Main profile levels 2 - 4 */
(pEncCfg->profileAndLevel != 51) &&
(pEncCfg->profileAndLevel != 52) &&
(pEncCfg->profileAndLevel != MPEG4_ADV_SIMPLE_PROFILE_LEVEL_3) &&
(pEncCfg->profileAndLevel != MPEG4_ADV_SIMPLE_PROFILE_LEVEL_4) &&
(pEncCfg->profileAndLevel != MPEG4_ADV_SIMPLE_PROFILE_LEVEL_5))
{
return -1;
}
/* Check that profile and level is valid for H263 stream */
if((pEncCfg->strmType == H263_STRM) &&
(pEncCfg->profileAndLevel != H263_PROFILE_0_LEVEL_10) &&
(pEncCfg->profileAndLevel != H263_PROFILE_0_LEVEL_20) &&
(pEncCfg->profileAndLevel != H263_PROFILE_0_LEVEL_30) &&
(pEncCfg->profileAndLevel != H263_PROFILE_0_LEVEL_40) &&
(pEncCfg->profileAndLevel != H263_PROFILE_0_LEVEL_50) &&
(pEncCfg->profileAndLevel != H263_PROFILE_0_LEVEL_60) &&
(pEncCfg->profileAndLevel != H263_PROFILE_0_LEVEL_70))
{
return -1;
}
return 0;
}
/*------------------------------------------------------------------------------
Set ASIC parameters
Depending on encoding status do:
- start a new VOP
- continue previous VOP with new buffer
------------------------------------------------------------------------------*/
MP4EncRet SetVopParameters(EncContainer_t * pEncCont,
MP4EncIn * pEncIn, MP4EncOut * pEncOut)
{
u32 vopType;
stream_s stream;
preProcess_s *preProcess;
rateControl_s *rc;
vop_s *vop;
timeCode_s *timeCode;
svh_s *svh;
i32 tmp;
u32 offset;
preProcess = &pEncCont->inst.preProcess;
rc = &pEncCont->inst.rateControl;
vop = &pEncCont->inst.videoObjectPlane;
timeCode = &pEncCont->inst.timeCode;
svh = &pEncCont->inst.shortVideoHeader;
ASSERT(pEncCont);
ASSERT(pEncIn);
ASSERT(pEncOut);
vopType = pEncIn->vopType;
/* Setup ASIC depending on encoding status */
switch (pEncCont->encStatus)
{
case ENCSTAT_STRM_START:
case ENCSTAT_GOV_INSERTED:
case ENCSTAT_NEW_REF_IMG:
vopType = INTRA_VOP;
/* Fall through */
case ENCSTAT_START_VOP:
/* Starting a new VOP:
* - handle GOV header
* - update timecodes
* - perform rate control
* - write VOP headers
* - camera stabilization
* - set all encoding parameters to registers */
pEncCont->vopBytes = 0;
EncSetBuffer(&stream, (u8 *) pEncIn->pOutBuf, pEncIn->outBufSize);
if (pEncCont->inst.groupOfVideoObjectPlane.header == YES)
{
/* Write GOV header and return */
EncGoVopHdr(&stream, &pEncCont->inst.groupOfVideoObjectPlane);
if (stream.overflow != 0)
{
pEncOut->strmSize = 0;
pEncOut->vopType = NOTCODED_VOP;
return ENC_OUTPUT_BUFFER_OVERFLOW;
}
/* Insert just once */
pEncCont->inst.groupOfVideoObjectPlane.header = NO;
pEncOut->strmSize = stream.byteCnt;
pEncOut->vopType = NOTCODED_VOP;
GetTimeCode(timeCode, pEncOut);
pEncCont->encStatus = ENCSTAT_GOV_INSERTED;
return ENC_GOV_READY;
}
/* Vop time increment */
EncTimeIncrement(timeCode, pEncIn->timeIncr);
/* Store previous timecode, it is needed if this VOP is discarded */
EncCopyTimeCode(&pEncCont->timeCodePrev, timeCode);
/* VOP type, user define */
rc->vopTypeCur = (vopType_e)vopType;
EncBeforeVopRc(rc, timeCode->timeInc);
if (rc->vopCoded != YES)
{
/* Rate control decided to skip this VOP */
pEncOut->strmSize = stream.byteCnt;
pEncOut->vopType = NOTCODED_VOP;
GetTimeCode(timeCode, pEncOut);
pEncCont->encStatus = ENCSTAT_START_VOP;
return ENC_VOP_READY;
}
/* Final time code */
EncTimeCode(timeCode, &pEncCont->inst.groupOfVideoObjectPlane);
/* ASIC rate control parameters before VOP */
SetRcParameter(rc);
SetEncQP(rc->qpHdr);
/* Round control */
vop->roundControl ^= 1;
if ((svh->header == YES) && (svh->plusHeader == NO))
vop->roundControl = 0;
svh->roundControl = vop->roundControl;
ASSERT(vop->roundControl <= 1);
SetEncRoundingCtrl(vop->roundControl);
/* Write VOP header depending on stream type */
if (svh->header == YES)
{
svh->tempRef = timeCode->tempRef;
svh->vopType = rc->vopTypeCur;
EncSvhHdr(&stream, svh, rc->qpHdr);
SetEncGobFrmId(EncGobFrameId(&pEncCont->inst.shortVideoHeader));
}
else
{
vop->vopCoded = rc->vopCoded;
vop->vopType = rc->vopTypeCur;
vop->moduloTimeBase = timeCode->moduloTimeBase;
vop->vopTimeInc = timeCode->vopTimeInc;
EncVopHdr(&stream, vop, rc->qpHdr);
}
/* HEC */
if (vop->hec == YES)
{
tmp = 0;
SetEncHecEnable(1);
SetEncModTimeBase(vop->moduloTimeBase);
while ((1 << ++tmp) < vop->vopTimeIncRes) ;
SetEncVopTimeIncr(vop->vopTimeInc << (16 - tmp));
if (tmp == 16)
tmp = 0;
SetEncVopTimeIncrBits(tmp);
}
else
SetEncHecEnable(0);
/* Clear the ASIC output VP table */
pEncCont->asic.pVpSizeBuf[0] = 0;
/* setup the internal image buffers */
pEncCont->asic.chromaRef ^= 1; /* swap the chroma buffers */
/* Chrominance reference base must point to [offset] bytes before
* start of image data */
offset = (pEncCont->asic.width_mb * 16 + 2) * 4;
if (pEncCont->asic.chromaRef == 0)
{
SetEncRefChromaBase(EWL_Virt2Bus(pEncCont->asic.pChromRefImg1) -
offset);
SetEncInternalChromaBase(EWL_Virt2Bus
(pEncCont->asic.pChromRefImg2));
}
else
{
SetEncRefChromaBase(EWL_Virt2Bus(pEncCont->asic.pChromRefImg2) -
offset);
SetEncInternalChromaBase(EWL_Virt2Bus
(pEncCont->asic.pChromRefImg1));
}
/* Setup the new image */
preProcess->busAddrLumaY = pEncIn->busLuma;
/* Chrominance input */
if (pEncIn->busChromaU != 0 && pEncIn->busChromaV != 0)
{
preProcess->busAddrChromaU = pEncIn->busChromaU;
preProcess->busAddrChromaV = pEncIn->busChromaV;
}
else
{
preProcess->busAddrChromaU = preProcess->busAddrLumaY +
preProcess->lumWidthSrc * preProcess->lumHeightSrc;
preProcess->busAddrChromaV = preProcess->busAddrChromaU +
preProcess->chWidthSrc * (preProcess->lumHeightSrc/2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -