123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- /*------------------------------------------------------------------------------
- -- --
- -- This software is confidential and proprietary and may be used --
- -- only as expressly authorized by a licensing agreement from --
- -- --
- -- Hantro Products Oy. --
- -- --
- -- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY --
- -- ALL RIGHTS RESERVED --
- -- --
- -- The entire notice above must be reproduced --
- -- on all copies and should not be removed. --
- -- --
- --------------------------------------------------------------------------------
- --
- -- Abstract : Encoder initialization and setup
- --
- ------------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------------
- 1. Include headers
- ------------------------------------------------------------------------------*/
- #include "H264Init.h"
- #include "enccommon.h"
- #include "ewl.h"
- /*------------------------------------------------------------------------------
- 2. External compiler flags
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- 3. Module defines
- ------------------------------------------------------------------------------*/
- #define H264ENC_MIN_ENC_WIDTH 132 /* 144 - 12 pixels overfill */
- #define H264ENC_MAX_ENC_WIDTH 4080
- #define H264ENC_MIN_ENC_HEIGHT 96
- #define H264ENC_MAX_ENC_HEIGHT 4080
- #define H264ENC_MAX_MBS_PER_PIC 65025 /* 4080x4080 */
- /* Level 51 MB limit is increased to enable max resolution */
- #define H264ENC_MAX_LEVEL 51
- #define H264ENC_DEFAULT_QP 26
- /*------------------------------------------------------------------------------
- 4. Local function prototypes
- ------------------------------------------------------------------------------*/
- static bool_e SetParameter(h264Instance_s * inst,
- const H264EncConfig * pEncCfg);
- static bool_e CheckParameter(const h264Instance_s * inst);
- /*------------------------------------------------------------------------------
- H264CheckCfg
- Function checks that the configuration is valid.
- Input pEncCfg Pointer to configuration structure.
- Return ENCHW_OK The configuration is valid.
- ENCHW_NOK Some of the parameters in configuration are not valid.
- ------------------------------------------------------------------------------*/
- bool_e H264CheckCfg(const H264EncConfig * pEncCfg)
- {
- ASSERT(pEncCfg);
- if ((pEncCfg->streamType != H264ENC_BYTE_STREAM) &&
- (pEncCfg->streamType != H264ENC_NAL_UNIT_STREAM))
- return ENCHW_NOK;
- /* Encoded image width limits, multiple of 4 */
- if(pEncCfg->width < H264ENC_MIN_ENC_WIDTH ||
- pEncCfg->width > H264ENC_MAX_ENC_WIDTH || (pEncCfg->width & 0x3) != 0)
- return ENCHW_NOK;
- /* Encoded image height limits, multiple of 2 */
- if(pEncCfg->height < H264ENC_MIN_ENC_HEIGHT ||
- pEncCfg->height > H264ENC_MAX_ENC_HEIGHT || (pEncCfg->height & 0x1) != 0)
- return ENCHW_NOK;
- /* total macroblocks per picture limit */
- if(((pEncCfg->height + 15) / 16) * ((pEncCfg->width + 15) / 16) >
- H264ENC_MAX_MBS_PER_PIC)
- {
- return ENCHW_NOK;
- }
- /* Check frame rate */
- if(pEncCfg->frameRateNum < 1 || pEncCfg->frameRateNum > ((1 << 20) - 1))
- return ENCHW_NOK;
- if(pEncCfg->frameRateDenom < 1)
- {
- return ENCHW_NOK;
- }
- /* special allowal of 1000/1001, 0.99 fps by customer request */
- if(pEncCfg->frameRateDenom > pEncCfg->frameRateNum &&
- !(pEncCfg->frameRateDenom == 1001 && pEncCfg->frameRateNum == 1000))
- {
- return ENCHW_NOK;
- }
- /* check level */
- if((pEncCfg->level > H264ENC_MAX_LEVEL) &&
- (pEncCfg->level != H264ENC_LEVEL_1_b))
- {
- return ENCHW_NOK;
- }
- /* check HW limitations */
- {
- EWLHwConfig_t cfg = EWLReadAsicConfig();
- /* is H.264 encoding supported */
- if(cfg.h264Enabled == EWL_HW_CONFIG_NOT_SUPPORTED)
- {
- return ENCHW_NOK;
- }
- /* max width supported */
- if(cfg.maxEncodedWidth < pEncCfg->width)
- {
- return ENCHW_NOK;
- }
- }
- return ENCHW_OK;
- }
- /*------------------------------------------------------------------------------
- H264Init
- Function initializes the Encoder and create new encoder instance.
- Input pEncCfg Encoder configuration.
- instAddr Pointer to instance will be stored in this address
- Return H264ENC_OK
- H264ENC_MEMORY_ERROR
- H264ENC_EWL_ERROR
- H264ENC_EWL_MEMORY_ERROR
- H264ENC_INVALID_ARGUMENT
- ------------------------------------------------------------------------------*/
- H264EncRet H264Init(const H264EncConfig * pEncCfg, h264Instance_s ** instAddr)
- {
- h264Instance_s *inst = NULL;
- const void *ewl = NULL;
- H264EncRet ret = H264ENC_OK;
- EWLInitParam_t param;
- ASSERT(pEncCfg);
- ASSERT(instAddr);
- *instAddr = NULL;
- param.clientType = EWL_CLIENT_TYPE_H264_ENC;
- /* Init EWL */
- if((ewl = EWLInit(¶m)) == NULL)
- return H264ENC_EWL_ERROR;
- /* Encoder instance */
- inst = (h264Instance_s *) EWLcalloc(1, sizeof(h264Instance_s));
- if(inst == NULL)
- {
- ret = H264ENC_MEMORY_ERROR;
- goto err;
- }
- /* Default values */
- H264SeqParameterSetInit(&inst->seqParameterSet);
- H264PicParameterSetInit(&inst->picParameterSet);
- H264SliceInit(&inst->slice);
- /* Set parameters depending on user config */
- if(SetParameter(inst, pEncCfg) != ENCHW_OK)
- {
- ret = H264ENC_INVALID_ARGUMENT;
- goto err;
- }
- /* Check and init the rest of parameters */
- if(CheckParameter(inst) != ENCHW_OK)
- {
- ret = H264ENC_INVALID_ARGUMENT;
- goto err;
- }
- if(H264InitRc(&inst->rateControl) != ENCHW_OK)
- {
- return H264ENC_INVALID_ARGUMENT;
- }
- /* Initialize ASIC */
- inst->asic.ewl = ewl;
- (void) EncAsicControllerInit(&inst->asic);
- /* Allocate internal SW/HW shared memories */
- if(EncAsicMemAlloc_V2(&inst->asic,
- (u32) inst->preProcess.lumWidth,
- (u32) inst->preProcess.lumHeight,
- ASIC_H264, inst->numRefBuffsLum,
- inst->numRefBuffsChr) != ENCHW_OK)
- {
- ret = H264ENC_EWL_MEMORY_ERROR;
- goto err;
- }
- *instAddr = inst;
- /* init VUI */
- {
- const h264VirtualBuffer_s *vb = &inst->rateControl.virtualBuffer;
- H264SpsSetVuiTimigInfo(&inst->seqParameterSet,
- vb->timeScale, vb->unitsInTic);
- }
- if(inst->seqParameterSet.levelIdc >= 31)
- inst->asic.regs.h264Inter4x4Disabled = 1;
- else
- inst->asic.regs.h264Inter4x4Disabled = 0;
- inst->asic.regs.skipPenalty = 1;
- return ret;
- err:
- if(inst != NULL)
- EWLfree(inst);
- if(ewl != NULL)
- (void) EWLRelease(ewl);
- return ret;
- }
- /*------------------------------------------------------------------------------
- H264Shutdown
- Function frees the encoder instance.
- Input h264Instance_s * Pointer to the encoder instance to be freed.
- After this the pointer is no longer valid.
- ------------------------------------------------------------------------------*/
- void H264Shutdown(h264Instance_s * data)
- {
- const void *ewl;
- ASSERT(data);
- ewl = data->asic.ewl;
- EncAsicMemFree_V2(&data->asic);
- EWLfree(data);
- (void) EWLRelease(ewl);
- }
- /*------------------------------------------------------------------------------
- SetParameter
- Set all parameters in instance to valid values depending on user config.
- ------------------------------------------------------------------------------*/
- bool_e SetParameter(h264Instance_s * inst, const H264EncConfig * pEncCfg)
- {
- i32 width, height, tmp, bps;
- ASSERT(inst);
- /* Internal images, next macroblock boundary */
- width = 16 * ((pEncCfg->width + 15) / 16);
- height = 16 * ((pEncCfg->height + 15) / 16);
- /* stream type */
- if(pEncCfg->streamType == H264ENC_BYTE_STREAM)
- {
- inst->asic.regs.h264StrmMode = ASIC_H264_BYTE_STREAM;
- inst->picParameterSet.byteStream = ENCHW_YES;
- inst->seqParameterSet.byteStream = ENCHW_YES;
- inst->rateControl.sei.byteStream = ENCHW_YES;
- inst->slice.byteStream = ENCHW_YES;
- }
- else
- {
- inst->asic.regs.h264StrmMode = ASIC_H264_NAL_UNIT;
- inst->picParameterSet.byteStream = ENCHW_NO;
- inst->seqParameterSet.byteStream = ENCHW_NO;
- inst->rateControl.sei.byteStream = ENCHW_NO;
- inst->slice.byteStream = ENCHW_NO;
- }
- if(pEncCfg->viewMode == H264ENC_BASE_VIEW_SINGLE_BUFFER)
- {
- inst->numViews = 1;
- inst->numRefBuffsLum = 1;
- inst->numRefBuffsChr = 2;
- }
- else if(pEncCfg->viewMode == H264ENC_BASE_VIEW_DOUBLE_BUFFER)
- {
- inst->numViews = 1;
- inst->numRefBuffsLum = 2;
- inst->numRefBuffsChr = 2;
- }
- else if(pEncCfg->viewMode == H264ENC_MVC_STEREO_INTER_VIEW_PRED)
- {
- inst->numViews = 2;
- inst->numRefBuffsLum = 1;
- inst->numRefBuffsChr = 2;
- }
- else
- {
- inst->numViews = 2;
- inst->numRefBuffsLum = 2;
- inst->numRefBuffsChr = 3;
- }
- /* Slice */
- inst->slice.sliceSize = 0;
- /* Macroblock */
- inst->mbPerFrame = width / 16 * height / 16;
- inst->mbPerRow = width / 16;
- inst->mbPerCol = height / 16;
- /* Disable intra and ROI areas by default */
- inst->asic.regs.intraAreaTop = inst->asic.regs.intraAreaBottom = inst->mbPerCol;
- inst->asic.regs.intraAreaLeft = inst->asic.regs.intraAreaRight = inst->mbPerRow;
- inst->asic.regs.roi1Top = inst->asic.regs.roi1Bottom = inst->mbPerCol;
- inst->asic.regs.roi1Left = inst->asic.regs.roi1Right = inst->mbPerRow;
- inst->asic.regs.roi2Top = inst->asic.regs.roi2Bottom = inst->mbPerCol;
- inst->asic.regs.roi2Left = inst->asic.regs.roi2Right = inst->mbPerRow;
- /* Sequence parameter set */
- inst->seqParameterSet.levelIdc = pEncCfg->level;
- inst->seqParameterSet.picWidthInMbsMinus1 = width / 16 - 1;
- inst->seqParameterSet.picHeightInMapUnitsMinus1 = height / 16 - 1;
- /* Set cropping parameters if required */
- if( pEncCfg->width%16 || pEncCfg->height%16 )
- {
- inst->seqParameterSet.frameCropping = ENCHW_YES;
- inst->seqParameterSet.frameCropRightOffset = (width - pEncCfg->width) / 2 ;
- inst->seqParameterSet.frameCropBottomOffset = (height - pEncCfg->height) / 2;
- }
- /* Level 1b is indicated with levelIdc == 11 and constraintSet3 */
- if(pEncCfg->level == H264ENC_LEVEL_1_b)
- {
- inst->seqParameterSet.levelIdc = 11;
- inst->seqParameterSet.constraintSet3 = ENCHW_YES;
- }
- /* Get the index for the table of level maximum values */
- tmp = H264GetLevelIndex(inst->seqParameterSet.levelIdc);
- if(tmp == INVALID_LEVEL)
- return ENCHW_NOK;
- inst->seqParameterSet.levelIdx = tmp;
- #if 1 /* enforce maximum frame size in level */
- if(inst->mbPerFrame > H264MaxFS[inst->seqParameterSet.levelIdx])
- {
- return ENCHW_NOK;
- }
- #endif
- #if 0 /* enforce macroblock rate limit in level */
- {
- u32 mb_rate =
- (pEncCfg->frameRateNum * inst->mbPerFrame) /
- pEncCfg->frameRateDenom;
- if(mb_rate > H264MaxMBPS[inst->seqParameterSet.levelIdx])
- {
- return ENCHW_NOK;
- }
- }
- #endif
- /* Picture parameter set */
- inst->picParameterSet.picInitQpMinus26 = (i32) H264ENC_DEFAULT_QP - 26;
- /* Rate control setup */
- /* Maximum bitrate for the specified level */
- bps = H264MaxBR[inst->seqParameterSet.levelIdx];
- {
- h264RateControl_s *rc = &inst->rateControl;
- rc->outRateDenom = pEncCfg->frameRateDenom;
- rc->outRateNum = pEncCfg->frameRateNum;
- rc->mbPerPic = (width / 16) * (height / 16);
- rc->mbRows = height / 16;
- {
- h264VirtualBuffer_s *vb = &rc->virtualBuffer;
- vb->bitRate = bps;
- vb->unitsInTic = pEncCfg->frameRateDenom;
- vb->timeScale = pEncCfg->frameRateNum;
- vb->bufferSize = H264MaxCPBS[inst->seqParameterSet.levelIdx];
- }
- rc->hrd = ENCHW_YES;
- rc->picRc = ENCHW_YES;
- rc->mbRc = ENCHW_YES;
- rc->picSkip = ENCHW_NO;
- rc->qpHdr = H264ENC_DEFAULT_QP;
- rc->qpMin = 10;
- rc->qpMax = 51;
- rc->frameCoded = ENCHW_YES;
- rc->sliceTypeCur = ISLICE;
- rc->sliceTypePrev = PSLICE;
- rc->gopLen = 150;
- /* Default initial value for intra QP delta */
- rc->intraQpDelta = -3;
- rc->fixedIntraQp = 0;
- }
- /* no SEI by default */
- inst->rateControl.sei.enabled = ENCHW_NO;
- /* Pre processing */
- inst->preProcess.lumWidth = pEncCfg->width;
- inst->preProcess.lumWidthSrc =
- H264GetAllowedWidth(pEncCfg->width, H264ENC_YUV420_PLANAR);
- inst->preProcess.lumHeight = pEncCfg->height;
- inst->preProcess.lumHeightSrc = pEncCfg->height;
- inst->preProcess.horOffsetSrc = 0;
- inst->preProcess.verOffsetSrc = 0;
- inst->preProcess.rotation = ROTATE_0;
- inst->preProcess.inputFormat = H264ENC_YUV420_PLANAR;
- inst->preProcess.videoStab = 0;
- inst->preProcess.colorConversionType = 0;
- EncSetColorConversion(&inst->preProcess, &inst->asic);
- return ENCHW_OK;
- }
- /*------------------------------------------------------------------------------
- CheckParameter
- ------------------------------------------------------------------------------*/
- bool_e CheckParameter(const h264Instance_s * inst)
- {
- /* Check crop */
- if(EncPreProcessCheck(&inst->preProcess) != ENCHW_OK)
- {
- return ENCHW_NOK;
- }
- return ENCHW_OK;
- }
- /*------------------------------------------------------------------------------
- Round the width to the next multiple of 8 or 16 depending on YUV type.
- ------------------------------------------------------------------------------*/
- i32 H264GetAllowedWidth(i32 width, H264EncPictureType inputType)
- {
- if(inputType == H264ENC_YUV420_PLANAR)
- {
- /* Width must be multiple of 16 to make
- * chrominance row 64-bit aligned */
- return ((width + 15) / 16) * 16;
- }
- else
- { /* H264ENC_YUV420_SEMIPLANAR */
- /* H264ENC_YUV422_INTERLEAVED_YUYV */
- /* H264ENC_YUV422_INTERLEAVED_UYVY */
- return ((width + 7) / 8) * 8;
- }
- }
|