void RCUpdateParams(AVCRateControl *rateCtrl, AVCEncObject *encvid)
{
    int32 prevFrameNum, newFrameNum;
    uint32 prevModTime;

    if (rateCtrl->frame_rate != rateCtrl->pMP->framerate)
    {
        /* this part for frame rate change */

        rateCtrl->pMP->frameRange = (int)(rateCtrl->frame_rate * 1.0); /* 1.0s time frame*/
        rateCtrl->pMP->frameRange = AVC_MAX(rateCtrl->pMP->frameRange, 5);
        rateCtrl->pMP->frameRange = AVC_MIN(rateCtrl->pMP->frameRange, 30);

        prevFrameNum = encvid->prevProcFrameNum;  // previous frame number

        // convert from frame num to time based on the previous frame rate
        prevModTime = (uint32)(prevFrameNum * 1000 / rateCtrl->pMP->framerate);  // offseted by modTimeRef

        // convert back from time to frame num based on new frame rate
        newFrameNum = (int32)((prevModTime * rateCtrl->frame_rate) / 1000);

        // assign the newFrameNum to prevFrameNum
        // note, this will cause the IDR frame to come earlier and later than expected !!
        encvid->prevProcFrameNum = newFrameNum;
    }

    // recalculate fixed values that are dependent on bitrate and framerate

    rateCtrl->bitsPerFrame = (int32)(rateCtrl->bitRate / rateCtrl->frame_rate);

    rateCtrl->max_BitVariance_num = (int)((OsclFloat)(rateCtrl->Bs - rateCtrl->VBV_fullness) / (rateCtrl->bitsPerFrame / 10.0)) - 5;
    if (rateCtrl->max_BitVariance_num < 0) rateCtrl->max_BitVariance_num += 5;

    /* no change to rateCtrl->cpbSize, rateCtrl->Bs, rateCtrl->low_bound, rateCtrl->VBV_fullness_offset*/

    /* keep continuity to the following values */
    /* rateCtrl->pMP->framePos, rateCtrl->TMN_TH, rateCtrl->TMN_W */
    /* rateCtrl->VBV_fullness, rateCtrl->pMP->counter_BTsrc, */

    /* reset some stats for CalculateQuantizerMultiPass and active bit resource protection */
    rateCtrl->pMP->sum_QP /= rateCtrl->pMP->encoded_frames;  // reset it to 1
    rateCtrl->pMP->encoded_frames = 1;
    rateCtrl->pMP->sum_mad = 0;
    rateCtrl->T = 0;

    /* Finalizing bitrate and framerate to pMP structure*/
    rateCtrl->pMP->bitrate = rateCtrl->bitRate;
    rateCtrl->pMP->framerate = rateCtrl->frame_rate;
    rateCtrl->pMP->target_bits_per_frame = rateCtrl->pMP->bitrate / rateCtrl->pMP->framerate;

    return ;
}
void RCInitChromaQP(AVCEncObject *encvid)
{
    AVCCommonObj *video = encvid->common;
    AVCMacroblock *currMB = video->currMB;
    int q_bits;

    /* we have to do the same thing for AVC_CLIP3(0,51,video->QSy) */

    video->QPy_div_6 = (currMB->QPy * 43) >> 8;
    video->QPy_mod_6 = currMB->QPy - 6 * video->QPy_div_6;
    currMB->QPc = video->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, currMB->QPy + video->currPicParams->chroma_qp_index_offset)];
    video->QPc_div_6 = (video->QPc * 43) >> 8;
    video->QPc_mod_6 = video->QPc - 6 * video->QPc_div_6;

    /* pre-calculate this to save computation */
    q_bits = 4 + video->QPy_div_6;
    if (video->slice_type == AVC_I_SLICE)
    {
        encvid->qp_const = 682 << q_bits;       // intra
    }
    else
    {
        encvid->qp_const = 342 << q_bits;       // inter
    }

    q_bits = 4 + video->QPc_div_6;
    if (video->slice_type == AVC_I_SLICE)
    {
        encvid->qp_const_c = 682 << q_bits;    // intra
    }
    else
    {
        encvid->qp_const_c = 342 << q_bits;    // inter
    }

    encvid->lambda_mode = QP2QUANT[AVC_MAX(0, currMB->QPy-SHIFT_QP)];
    encvid->lambda_motion = LAMBDA_FACTOR(encvid->lambda_mode);

    return ;
}
AVCEnc_Status InitRateControlModule(AVCHandle *avcHandle)
{
    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
    AVCCommonObj *video = encvid->common;
    AVCRateControl *rateCtrl = encvid->rateCtrl;
    double L1, L2, L3, bpp;
    int qp;
    int i, j;

    rateCtrl->basicUnit = video->PicSizeInMbs;

    rateCtrl->MADofMB = (double*) avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
                        video->PicSizeInMbs * sizeof(double), DEFAULT_ATTR);

    if (!rateCtrl->MADofMB)
    {
        goto CLEANUP_RC;
    }

    if (rateCtrl->rcEnable == TRUE)
    {
        rateCtrl->pMP = (MultiPass*) avcHandle->CBAVC_Malloc(encvid->avcHandle->userData, sizeof(MultiPass), DEFAULT_ATTR);
        if (!rateCtrl->pMP)
        {
            goto CLEANUP_RC;
        }
        oscl_memset(rateCtrl->pMP, 0, sizeof(MultiPass));
        rateCtrl->pMP->encoded_frames = -1; /* forget about the very first I frame */

        /* RDInfo **pRDSamples */
        rateCtrl->pMP->pRDSamples = (RDInfo **)avcHandle->CBAVC_Malloc(encvid->avcHandle->userData, (30 * sizeof(RDInfo *)), DEFAULT_ATTR);
        if (!rateCtrl->pMP->pRDSamples)
        {
            goto CLEANUP_RC;
        }

        for (i = 0; i < 30; i++)
        {
            rateCtrl->pMP->pRDSamples[i] = (RDInfo *)avcHandle->CBAVC_Malloc(encvid->avcHandle->userData, (32 * sizeof(RDInfo)), DEFAULT_ATTR);
            if (!rateCtrl->pMP->pRDSamples[i])
            {
                goto CLEANUP_RC;
            }
            for (j = 0; j < 32; j++)    oscl_memset(&(rateCtrl->pMP->pRDSamples[i][j]), 0, sizeof(RDInfo));
        }
        rateCtrl->pMP->frameRange = (int)(rateCtrl->frame_rate * 1.0); /* 1.0s time frame*/
        rateCtrl->pMP->frameRange = AVC_MAX(rateCtrl->pMP->frameRange, 5);
        rateCtrl->pMP->frameRange = AVC_MIN(rateCtrl->pMP->frameRange, 30);

        rateCtrl->pMP->framePos = -1;


        rateCtrl->bitsPerFrame = (int32)(rateCtrl->bitRate / rateCtrl->frame_rate);

        /* BX rate control */
        rateCtrl->skip_next_frame = 0; /* must be initialized */

        rateCtrl->Bs = rateCtrl->cpbSize;
        rateCtrl->TMN_W = 0;
        rateCtrl->VBV_fullness = (int)(rateCtrl->Bs * 0.5); /* rateCtrl->Bs */
        rateCtrl->encoded_frames = 0;

        rateCtrl->TMN_TH = rateCtrl->bitsPerFrame;

        rateCtrl->max_BitVariance_num = (int)((OsclFloat)(rateCtrl->Bs - rateCtrl->VBV_fullness) / (rateCtrl->bitsPerFrame / 10.0)) - 5;
        if (rateCtrl->max_BitVariance_num < 0) rateCtrl->max_BitVariance_num += 5;

        // Set the initial buffer fullness
        /* According to the spec, the initial buffer fullness needs to be set to 1/3 */
        rateCtrl->VBV_fullness = (int)(rateCtrl->Bs / 3.0 - rateCtrl->Bs / 2.0); /* the buffer range is [-Bs/2, Bs/2] */
        rateCtrl->pMP->counter_BTsrc = (int)((rateCtrl->Bs / 2.0 - rateCtrl->Bs / 3.0) / (rateCtrl->bitsPerFrame / 10.0));
        rateCtrl->TMN_W = (int)(rateCtrl->VBV_fullness + rateCtrl->pMP->counter_BTsrc * (rateCtrl->bitsPerFrame / 10.0));

        rateCtrl->low_bound = -rateCtrl->Bs / 2;
        rateCtrl->VBV_fullness_offset = 0;

        /* Setting the bitrate and framerate */
        rateCtrl->pMP->bitrate = rateCtrl->bitRate;
        rateCtrl->pMP->framerate = rateCtrl->frame_rate;
        rateCtrl->pMP->target_bits_per_frame = rateCtrl->pMP->bitrate / rateCtrl->pMP->framerate;

        /*compute the initial QP*/
        bpp = 1.0 * rateCtrl->bitRate / (rateCtrl->frame_rate * (video->PicSizeInMbs << 8));
        if (video->PicWidthInSamplesL == 176)
        {
            L1 = 0.1;
            L2 = 0.3;
            L3 = 0.6;
        }
        else if (video->PicWidthInSamplesL == 352)
        {
            L1 = 0.2;
            L2 = 0.6;
            L3 = 1.2;
        }
        else
        {
            L1 = 0.6;
            L2 = 1.4;
            L3 = 2.4;
        }

        if (rateCtrl->initQP == 0)
        {
            if (bpp <= L1)
                qp = 35;
            else if (bpp <= L2)
                qp = 25;
            else if (bpp <= L3)
                qp = 20;
            else
                qp = 15;
            rateCtrl->initQP = qp;
        }

        rateCtrl->Qc = rateCtrl->initQP;
    }

    return AVCENC_SUCCESS;

CLEANUP_RC:

    CleanupRateControlModule(avcHandle);
    return AVCENC_MEMORY_FAIL;

}
void RCInitFrameQP(AVCEncObject *encvid)
{
    AVCCommonObj *video = encvid->common;
    AVCRateControl *rateCtrl = encvid->rateCtrl;
    AVCPicParamSet *picParam = video->currPicParams;
    MultiPass *pMP = rateCtrl->pMP;

    if (rateCtrl->rcEnable == TRUE)
    {
        /* frame layer rate control */
        if (rateCtrl->encoded_frames == 0)
        {
            video->QPy = rateCtrl->Qc = rateCtrl->initQP;
        }
        else
        {
            calculateQuantizer_Multipass(encvid, video, rateCtrl, pMP);
            video->QPy = rateCtrl->Qc;
        }

        rateCtrl->NumberofHeaderBits = 0;
        rateCtrl->NumberofTextureBits = 0;
        rateCtrl->numFrameBits = 0; // reset

        /* update pMP->framePos */
        if (++pMP->framePos == pMP->frameRange) pMP->framePos = 0;

        if (rateCtrl->T == 0)
        {
            pMP->counter_BTdst = (int)(rateCtrl->frame_rate * 7.5 + 0.5); /* 0.75s time frame */
            pMP->counter_BTdst = AVC_MIN(pMP->counter_BTdst, (int)(rateCtrl->max_BitVariance_num / 2 * 0.40)); /* 0.75s time frame may go beyond VBV buffer if we set the buffer size smaller than 0.75s */
            pMP->counter_BTdst = AVC_MAX(pMP->counter_BTdst, (int)((rateCtrl->Bs / 2 - rateCtrl->VBV_fullness) * 0.30 / (rateCtrl->TMN_TH / 10.0) + 0.5)); /* At least 30% of VBV buffer size/2 */
            pMP->counter_BTdst = AVC_MIN(pMP->counter_BTdst, 20); /* Limit the target to be smaller than 3C */

            pMP->target_bits = rateCtrl->T = rateCtrl->TMN_TH = (int)(rateCtrl->TMN_TH * (1.0 + pMP->counter_BTdst * 0.1));
            pMP->diff_counter = pMP->counter_BTdst;
        }

        /* collect the necessary data: target bits, actual bits, mad and QP */
        pMP->target_bits = rateCtrl->T;
        pMP->QP  = video->QPy;

        pMP->mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs; //ComputeFrameMAD(video, rateCtrl);
        if (pMP->mad < MAD_MIN) pMP->mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */

        pMP->bitrate = rateCtrl->bitRate; /* calculated in RCVopQPSetting */
        pMP->framerate = rateCtrl->frame_rate;

        /* first pass encoding */
        pMP->nRe_Quantized = 0;

    } // rcEnable
    else
    {
        video->QPy = rateCtrl->initQP;
    }

//  printf(" %d ",video->QPy);

    if (video->CurrPicNum == 0 && encvid->outOfBandParamSet == FALSE)
    {
        picParam->pic_init_qs_minus26 = 0;
        picParam->pic_init_qp_minus26 = video->QPy - 26;
    }

    // need this for motion estimation
    encvid->lambda_mode = QP2QUANT[AVC_MAX(0, video->QPy-SHIFT_QP)];
    encvid->lambda_motion = LAMBDA_FACTOR(encvid->lambda_mode);
    return ;
}
Esempio n. 5
0
/* follow the text rather than the JM, it's quite different. */
void FmoGenerateType3MapUnitMap(AVCCommonObj *video, AVCPicParamSet* pps, int *mapUnitToSliceGroupMap,
                                int PicWidthInMbs)
{
    uint i, k;
    int leftBound, topBound, rightBound, bottomBound;
    int x, y, xDir, yDir;
    int mapUnitVacant;
    uint PicSizeInMapUnits = video->PicSizeInMapUnits;
    uint MapUnitsInSliceGroup0 = video->MapUnitsInSliceGroup0;

    for (i = 0; i < PicSizeInMapUnits; i++)
    {
        mapUnitToSliceGroupMap[ i ] = 1;
    }

    x = (PicWidthInMbs - pps->slice_group_change_direction_flag) / 2;
    y = (video->PicHeightInMapUnits - pps->slice_group_change_direction_flag) / 2;

    leftBound   = x;
    topBound    = y;
    rightBound  = x;
    bottomBound = y;

    xDir =  pps->slice_group_change_direction_flag - 1;
    yDir =  pps->slice_group_change_direction_flag;

    for (k = 0; k < MapUnitsInSliceGroup0; k += mapUnitVacant)
    {
        mapUnitVacant = (mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ]  ==  1);
        if (mapUnitVacant)
        {
            mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] = 0;
        }

        if (xDir  ==  -1  &&  x  ==  leftBound)
        {
            leftBound = AVC_MAX(leftBound - 1, 0);
            x = leftBound;
            xDir = 0;
            yDir = 2 * pps->slice_group_change_direction_flag - 1;
        }
        else if (xDir  ==  1  &&  x  ==  rightBound)
        {
            rightBound = AVC_MIN(rightBound + 1, (int)PicWidthInMbs - 1);
            x = rightBound;
            xDir = 0;
            yDir = 1 - 2 * pps->slice_group_change_direction_flag;
        }
        else if (yDir  ==  -1  &&  y  ==  topBound)
        {
            topBound = AVC_MAX(topBound - 1, 0);
            y = topBound;
            xDir = 1 - 2 * pps->slice_group_change_direction_flag;
            yDir = 0;
        }
        else  if (yDir  ==  1  &&  y  ==  bottomBound)
        {
            bottomBound = AVC_MIN(bottomBound + 1, (int)video->PicHeightInMapUnits - 1);
            y = bottomBound;
            xDir = 2 * pps->slice_group_change_direction_flag - 1;
            yDir = 0;
        }
        else
        {
            x = x + xDir;
            y = y + yDir;
        }
    }
}