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 targetBitCalculation(AVCEncObject *encvid, AVCCommonObj *video, AVCRateControl *rateCtrl, MultiPass *pMP)
{
    OSCL_UNUSED_ARG(encvid);
    OsclFloat curr_mad;//, average_mad;
    int diff_counter_BTsrc, diff_counter_BTdst, prev_counter_diff, curr_counter_diff, bound;
    /* BT = Bit Transfer, for pMP->counter_BTsrc, pMP->counter_BTdst */

    /* some stuff about frame dropping remained here to be done because pMP cannot be inserted into updateRateControl()*/
    updateRC_PostProc(rateCtrl, pMP);

    /* update pMP->counter_BTsrc and pMP->counter_BTdst to avoid interger overflow */
    if (pMP->counter_BTsrc > 1000 && pMP->counter_BTdst > 1000)
    {
        pMP->counter_BTsrc -= 1000;
        pMP->counter_BTdst -= 1000;
    }

    /* ---------------------------------------------------------------------------------------------------*/
    /* target calculation */
    curr_mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs;
    if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
    diff_counter_BTsrc = diff_counter_BTdst = 0;
    pMP->diff_counter = 0;


    /*1.calculate average mad */
    pMP->sum_mad += curr_mad;
    //average_mad = (pMP->encoded_frames < 1 ? curr_mad : pMP->sum_mad/(OsclFloat)(pMP->encoded_frames+1)); /* this function is called from the scond encoded frame*/
    //pMP->aver_mad = average_mad;
    if (pMP->encoded_frames >= 0) /* pMP->encoded_frames is set to -1 initially, so forget about the very first I frame */
        pMP->aver_mad = (pMP->aver_mad * pMP->encoded_frames + curr_mad) / (pMP->encoded_frames + 1);

    if (pMP->overlapped_win_size > 0 && pMP->encoded_frames_prev >= 0)
        pMP->aver_mad_prev = (pMP->aver_mad_prev * pMP->encoded_frames_prev + curr_mad) / (pMP->encoded_frames_prev + 1);

    /*2.average_mad, mad ==> diff_counter_BTsrc, diff_counter_BTdst */
    if (pMP->overlapped_win_size == 0)
    {
        /* original verison */
        if (curr_mad > pMP->aver_mad*1.1)
        {
            if (curr_mad / (pMP->aver_mad + 0.0001) > 2)
                diff_counter_BTdst = (int)(oscl_sqrt(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.4) - 10;
            //diff_counter_BTdst = (int)((sqrt(curr_mad/pMP->aver_mad)*2+curr_mad/pMP->aver_mad)/(3*0.1) + 0.4) - 10;
            else
                diff_counter_BTdst = (int)(curr_mad / (pMP->aver_mad + 0.0001) * 10 + 0.4) - 10;
        }
        else /* curr_mad <= average_mad*1.1 */
            //diff_counter_BTsrc = 10 - (int)((sqrt(curr_mad/pMP->aver_mad) + pow(curr_mad/pMP->aver_mad, 1.0/3.0))/(2.0*0.1) + 0.4);
            diff_counter_BTsrc = 10 - (int)(oscl_sqrt(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.5);

        /* actively fill in the possible gap */
        if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
                curr_mad <= pMP->aver_mad*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
            diff_counter_BTsrc = 1;

    }
    else if (pMP->overlapped_win_size > 0)
    {
        /* transition time: use previous average mad "pMP->aver_mad_prev" instead of the current average mad "pMP->aver_mad" */
        if (curr_mad > pMP->aver_mad_prev*1.1)
        {
            if (curr_mad / pMP->aver_mad_prev > 2)
                diff_counter_BTdst = (int)(oscl_sqrt(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.4) - 10;
            //diff_counter_BTdst = (int)((M4VENC_SQRT(curr_mad/pMP->aver_mad_prev)*2+curr_mad/pMP->aver_mad_prev)/(3*0.1) + 0.4) - 10;
            else
                diff_counter_BTdst = (int)(curr_mad / (pMP->aver_mad_prev + 0.0001) * 10 + 0.4) - 10;
        }
        else /* curr_mad <= average_mad*1.1 */
            //diff_counter_BTsrc = 10 - (Int)((sqrt(curr_mad/pMP->aver_mad_prev) + pow(curr_mad/pMP->aver_mad_prev, 1.0/3.0))/(2.0*0.1) + 0.4);
            diff_counter_BTsrc = 10 - (int)(oscl_sqrt(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.5);

        /* actively fill in the possible gap */
        if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
                curr_mad <= pMP->aver_mad_prev*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
            diff_counter_BTsrc = 1;

        if (--pMP->overlapped_win_size <= 0)    pMP->overlapped_win_size = 0;
    }


    /* if difference is too much, do clipping */
    /* First, set the upper bound for current bit allocation variance: 80% of available buffer */
    bound = (int)((rateCtrl->Bs / 2 - rateCtrl->VBV_fullness) * 0.6 / (pMP->target_bits_per_frame / 10)); /* rateCtrl->Bs */
    diff_counter_BTsrc =  AVC_MIN(diff_counter_BTsrc, bound);
    diff_counter_BTdst =  AVC_MIN(diff_counter_BTdst, bound);

    /* Second, set another upper bound for current bit allocation: 4-5*bitrate/framerate */
    bound = 50;
//  if(video->encParams->RC_Type == CBR_LOWDELAY)
//  not necessary       bound = 10;  -- For Low delay */

    diff_counter_BTsrc =  AVC_MIN(diff_counter_BTsrc, bound);
    diff_counter_BTdst =  AVC_MIN(diff_counter_BTdst, bound);


    /* Third, check the buffer */
    prev_counter_diff = pMP->counter_BTdst - pMP->counter_BTsrc;
    curr_counter_diff = prev_counter_diff + (diff_counter_BTdst - diff_counter_BTsrc);

    if (AVC_ABS(prev_counter_diff) >= rateCtrl->max_BitVariance_num || AVC_ABS(curr_counter_diff) >= rateCtrl->max_BitVariance_num)
    {   //diff_counter_BTsrc = diff_counter_BTdst = 0;

        if (curr_counter_diff > rateCtrl->max_BitVariance_num && diff_counter_BTdst)
        {
            diff_counter_BTdst = (rateCtrl->max_BitVariance_num - prev_counter_diff) + diff_counter_BTsrc;
            if (diff_counter_BTdst < 0) diff_counter_BTdst = 0;
        }

        else if (curr_counter_diff < -rateCtrl->max_BitVariance_num && diff_counter_BTsrc)
        {
            diff_counter_BTsrc = diff_counter_BTdst - (-rateCtrl->max_BitVariance_num - prev_counter_diff);
            if (diff_counter_BTsrc < 0) diff_counter_BTsrc = 0;
        }
    }


    /*3.diff_counter_BTsrc, diff_counter_BTdst ==> TMN_TH */
    rateCtrl->TMN_TH = (int)(pMP->target_bits_per_frame);
    pMP->diff_counter = 0;

    if (diff_counter_BTsrc)
    {
        rateCtrl->TMN_TH -= (int)(pMP->target_bits_per_frame * diff_counter_BTsrc * 0.1);
        pMP->diff_counter = -diff_counter_BTsrc;
    }
    else if (diff_counter_BTdst)
    {
        rateCtrl->TMN_TH += (int)(pMP->target_bits_per_frame * diff_counter_BTdst * 0.1);
        pMP->diff_counter = diff_counter_BTdst;
    }


    /*4.update pMP->counter_BTsrc, pMP->counter_BTdst */
    pMP->counter_BTsrc += diff_counter_BTsrc;
    pMP->counter_BTdst += diff_counter_BTdst;


    /*5.target bit calculation */
    rateCtrl->T = rateCtrl->TMN_TH - rateCtrl->TMN_W;

    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 ;
}
Пример #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;
        }
    }
}