void Deringing_Chroma(
    uint8 *Rec_C,
    int width,
    int height,
    int16 *QP_store,
    int Combined,
    uint8 *pp_mod
)
{
    OSCL_UNUSED_ARG(Combined);
    /*----------------------------------------------------------------------------
    ; Define all local variables
    ----------------------------------------------------------------------------*/
    int thres;
    int v_blk, h_blk;
    int max_diff;
    int v_pel, h_pel;
    int max_blk, min_blk;
    int v0, h0;
    uint8 *ptr;
    int sum, sum1, incr;
    int32 addr_v;
    int sign_v[10], sum_v[10];
    int *ptr2, *ptr3;
    uint8 pelu, pelc, pell;
    incr = width - BLKSIZE;

    /*----------------------------------------------------------------------------
    ; Function body here
    ----------------------------------------------------------------------------*/
    /* chrominance */
    /* Do the first line (7 pixels at a time => Don't use MMX)*/
    for (h_blk = 0;h_blk < width;h_blk += BLKSIZE)
    {
        max_diff = (QP_store[h_blk>>3] >> 2) + 4;
        ptr = &Rec_C[h_blk];
        max_blk = min_blk = *ptr;
        FindMaxMin(ptr, &min_blk, &max_blk, width);
        h0 = ((h_blk - 1) >= 1) ? (h_blk - 1) : 1;

        if (max_blk - min_blk >= 4)
        {
            thres = (max_blk + min_blk + 1) >> 1;


            for (v_pel = 1;v_pel < BLKSIZE - 1;v_pel++)
            {
                addr_v = (int32)v_pel * width;
                ptr = &Rec_C[addr_v + h0 - 1];
                ptr2 = &sum_v[0];
                ptr3 = &sign_v[0];

                pelu = *(ptr - width);
                pelc = *ptr;
                pell = *(ptr + width);
                ptr++;
                *ptr2++ = pelu + (pelc << 1) + pell;
                *ptr3++ = INDEX(pelu, thres) + INDEX(pelc, thres) + INDEX(pell, thres);

                pelu = *(ptr - width);
                pelc = *ptr;
                pell = *(ptr + width);
                ptr++;
                *ptr2++ = pelu + (pelc << 1) + pell;
                *ptr3++ = INDEX(pelu, thres) + INDEX(pelc, thres) + INDEX(pell, thres);

                for (h_pel = h0;h_pel < h_blk + BLKSIZE - 1;h_pel++)
                {
                    pelu = *(ptr - width);
                    pelc = *ptr;
                    pell = *(ptr + width);

                    *ptr2 = pelu + (pelc << 1) + pell;
                    *ptr3 = INDEX(pelu, thres) + INDEX(pelc, thres) + INDEX(pell, thres);

                    sum1 = *(ptr3 - 2) + *(ptr3 - 1) + *ptr3;
                    if (sum1 == 0 || sum1 == 9)
                    {
                        sum = (*(ptr2 - 2) + (*(ptr2 - 1) << 1) + *ptr2 + 8) >> 4;

                        ptr--;
                        if (PV_ABS(*ptr - sum) > max_diff)
                        {
                            if (sum > *ptr)
                                sum = *ptr + max_diff;
                            else
                                sum = *ptr - max_diff;
                        }
                        *ptr++ = (uint8) sum;
                    }
                    ptr++;
                    ptr2++;
                    ptr3++;
                }
            }
        }
示例#2
0
/* Mad based variable bit allocation + QP calculation with a new quadratic method */
void calculateQuantizer_Multipass(void *input)
{
    VideoEncData *video = (VideoEncData *) input;
    MultiPass *pMP = video->pMP[video->currLayer];
    Vol *currVol = video->vol[video->currLayer];
    rateControl *rc = video->rc[video->currLayer];

    Int prev_QP, prev_actual_bits, curr_target, i, j;

    float curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP;


    if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
        return;

    /* Mad based variable bit allocation */
    targetBitCalculation((void*) video);

    if (rc->T <= 0 || video->sumMAD == 0)
    {
        if (rc->T < 0)  rc->Qc = 31;
        return;
    }

    /* ---------------------------------------------------------------------------------------------------*/
    /* current frame QP estimation */
    curr_target = rc->T;
    curr_mad = video->sumMAD / (float)currVol->nTotalMB;
    if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
    curr_RD  = (float)curr_target / curr_mad;

    /* Another version of search the optimal point */
    prev_actual_bits = pMP->pRDSamples[0][0].actual_bits;
    prev_mad = pMP->pRDSamples[0][0].mad;

    for (i = 0, j = 0; i < pMP->frameRange; i++)
    {
        if (pMP->pRDSamples[i][0].mad != 0 && prev_mad != 0 &&
                PV_ABS(prev_mad - curr_mad) > PV_ABS(pMP->pRDSamples[i][0].mad - curr_mad))
        {
            prev_mad = pMP->pRDSamples[i][0].mad;
            prev_actual_bits = pMP->pRDSamples[i][0].actual_bits;
            j = i;
        }
    }
    prev_QP = pMP->pRDSamples[j][0].QP;
    for (i = 1; i < pMP->samplesPerFrame[j]; i++)
    {
        if (PV_ABS(prev_actual_bits - curr_target) > PV_ABS(pMP->pRDSamples[j][i].actual_bits - curr_target))
        {
            prev_actual_bits = pMP->pRDSamples[j][i].actual_bits;
            prev_QP = pMP->pRDSamples[j][i].QP;
        }
    }

    // quadratic approximation
    prev_RD = (float)prev_actual_bits / prev_mad;
    //rc->Qc = (Int)(prev_QP * sqrt(prev_actual_bits/curr_target) + 0.4);
    if (prev_QP == 1) // 11/14/05, added this to allow getting out of QP = 1 easily
    {
        rc->Qc = (Int)(prev_RD / curr_RD + 0.5);
    }
    else
    {
        rc->Qc = (Int)(prev_QP * M4VENC_SQRT(prev_RD / curr_RD) + 0.9);

        if (prev_RD / curr_RD > 0.5 && prev_RD / curr_RD < 2.0)
            rc->Qc = (Int)(prev_QP * (M4VENC_SQRT(prev_RD / curr_RD) + prev_RD / curr_RD) / 2.0 + 0.9); /* Quadratic and linear approximation */
        else
            rc->Qc = (Int)(prev_QP * (M4VENC_SQRT(prev_RD / curr_RD) + M4VENC_POW(prev_RD / curr_RD, 1.0 / 3.0)) / 2.0 + 0.9);
    }
    //rc->Qc =(Int)(prev_QP * sqrt(prev_RD/curr_RD) + 0.4);
    // 11/08/05
    // lower bound on Qc should be a function of curr_mad
    // When mad is already low, lower bound on Qc doesn't have to be small.
    // Note, this doesn't work well for low complexity clip encoded at high bit rate
    // it doesn't hit the target bit rate due to this QP lower bound.
/// if((curr_mad < 8) && (rc->Qc < 12)) rc->Qc = 12;
//  else    if((curr_mad < 128) && (rc->Qc < 3)) rc->Qc = 3;

    if (rc->Qc < 1) rc->Qc = 1;
    if (rc->Qc > 31)    rc->Qc = 31;


    /* active bit resource protection */
    aver_QP = (pMP->encoded_frames == 0 ? 0 : pMP->sum_QP / (float)pMP->encoded_frames);
    average_mad = (pMP->encoded_frames == 0 ? 0 : pMP->sum_mad / (float)pMP->encoded_frames); /* this function is called from the scond encoded frame*/
    if (pMP->diff_counter == 0 &&
            ((float)rc->Qc <= aver_QP*1.1 || curr_mad <= average_mad*1.1) &&
            pMP->counter_BTsrc <= (pMP->counter_BTdst + (Int)(pMP->framerate*1.0 + 0.5)))
    {
        rc->TMN_TH -= (Int)(pMP->target_bits_per_frame / 10.0);
        rc->T = rc->TMN_TH - rc->TMN_W;
        pMP->counter_BTsrc++;
        pMP->diff_counter--;
    }

}
void	doDCACPrediction(
    VideoDecData *video,
    int comp,
    int16 *q_block,
    int *direction
)
{
    /*----------------------------------------------------------------------------
    ; Define all local variables
    ----------------------------------------------------------------------------*/
    int i;
    int mbnum = video->mbnum;
    int	nMBPerRow = video->nMBPerRow;
    int x_pos = video->mbnum_col;
    int y_pos = video->mbnum_row;
    int16 *AC_tmp;
    int QP_tmp;
    int16 *QP_store = video->QPMB + mbnum;
    int QP = video->QPMB[mbnum];
    int QP_half = QP >> 1;
    int32 val;
    int flag_0 = FALSE, flag_1 = FALSE;
    uint8 *slice_nb = video->sliceNo;
    typeDCStore *DC_store = video->predDC + mbnum;
    typeDCACStore *DCAC_row = video->predDCAC_row + x_pos;
    typeDCACStore *DCAC_col = video->predDCAC_col;

    uint ACpred_flag = (uint) video->acPredFlag[mbnum];

    int left_bnd, up_bnd;

    static const int Xpos[6] = { -1, 0, -1, 0, -1, -1};
    static const int Ypos[6] = { -1, -1, 0, 0, -1, -1};

    static const int Xtab[6] = {1, 0, 3, 2, 4, 5};
    static const int Ytab[6] = {2, 3, 0, 1, 4, 5};
    static const int Ztab[6] = {3, 2, 1, 0, 4, 5};

    /* I added these to speed up comparisons */
    static const int Pos0[6] = { 1, 1, 0, 0, 1, 1};
    static const int Pos1[6] = { 1, 0, 1, 0, 1, 1};

    static const int B_Xtab[6] = {0, 1, 0, 1, 2, 3};
    static const int B_Ytab[6] = {0, 0, 1, 1, 2, 3};

//	int *direction;		/* 0: HORIZONTAL, 1: VERTICAL */
    int block_A, block_B, block_C;
    int DC_pred;
    int y_offset, x_offset, x_tab, y_tab, z_tab;	/* speedup coefficients */
    int b_xtab, b_ytab;

    if (!comp && x_pos && !(video->headerInfo.Mode[mbnum-1]&INTRA_MASK)) /* not intra */
    {
        oscl_memset(DCAC_col, 0, sizeof(typeDCACStore));
    }
    if (!comp && y_pos && !(video->headerInfo.Mode[mbnum-nMBPerRow]&INTRA_MASK)) /* not intra */
    {
        oscl_memset(DCAC_row, 0, sizeof(typeDCACStore));
    }

    y_offset = Ypos[comp] * nMBPerRow;
    x_offset = Xpos[comp];
    x_tab = Xtab[comp];
    y_tab = Ytab[comp];
    z_tab = Ztab[comp];

    b_xtab = B_Xtab[comp];
    b_ytab = B_Ytab[comp];

    /*----------------------------------------------------------------------------
    ; Function body here
    ----------------------------------------------------------------------------*/
    /* Find the direction of prediction and the DC prediction */

    if (x_pos == 0 && y_pos == 0)
    {	/* top left corner */
        block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
        block_B = (comp == 3) ? DC_store[x_offset][z_tab] : mid_gray;
        block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[0][y_tab] : mid_gray;
    }
    else if (x_pos == 0)
    {	/* left edge */
        up_bnd   = Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow];

        block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
        block_B = ((comp == 1 && up_bnd) || comp == 3) ?  DC_store[y_offset+x_offset][z_tab] : mid_gray;
        block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
    }
    else if (y_pos == 0)
    { /* top row */
        left_bnd = Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1];

        block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
        block_B = ((comp == 2 && left_bnd) || comp == 3) ? DC_store[y_offset + x_offset][z_tab] : mid_gray;
        block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
    }
    else
    {
        up_bnd   = Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow];
        left_bnd = Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1];

        block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
        block_B = (((comp == 0 || comp == 4 || comp == 5) && slice_nb[mbnum] == slice_nb[mbnum-1-nMBPerRow]) ||
                   (comp == 1 && up_bnd) || (comp == 2 && left_bnd) || (comp == 3)) ? DC_store[y_offset+x_offset][z_tab] : mid_gray;
        block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
    }


    if ((PV_ABS((block_A - block_B))) < (PV_ABS((block_B - block_C))))
    {
        DC_pred = block_C;
        *direction = 1;
        if (ACpred_flag == 1)
        {
            if (flag_1)
            {
                AC_tmp = DCAC_row[0][b_xtab];
                QP_tmp = QP_store[y_offset];
                if (QP_tmp == QP)
                {
                    for (i = 1; i < 8; i++)
                    {
                        q_block[i] = *AC_tmp++;
                    }
                }
                else
                {
                    for (i = 1; i < 8; i++)
                    {
                        val = (int32)(*AC_tmp++) * QP_tmp;
                        q_block[i] = (val < 0) ? (int16)((val - QP_half) / QP) : (int16)((val + QP_half) / QP);
                        /* Vertical, top ROW of block C */
                    }
                }
            }
        }
    }
    else
    {
        DC_pred = block_A;
        *direction = 0;
        if (ACpred_flag == 1)
        {
            if (flag_0)
            {
                AC_tmp = DCAC_col[0][b_ytab];
                QP_tmp = QP_store[x_offset];
                if (QP_tmp == QP)
                {
                    for (i = 1; i < 8; i++)
                    {
                        q_block[i<<3] = *AC_tmp++;
                    }
                }
                else
                {
                    for (i = 1; i < 8; i++)
                    {
                        val = (int32)(*AC_tmp++) * QP_tmp;
                        q_block[i<<3] = (val < 0) ? (int16)((val - QP_half) / QP) : (int16)((val + QP_half) / QP);
                        /* Vertical, top ROW of block C */
                    }
                }
            }
        }
    }

    /* Now predict the DC coefficient */
    QP_tmp = (comp < 4) ? video->mblock->DCScalarLum : video->mblock->DCScalarChr;
    q_block[0] += (int16)((DC_pred + (QP_tmp >> 1)) * scale[QP_tmp] >> 18);
//		q_block[0] += (DC_pred+(QP_tmp>>1))/QP_tmp;

    /*----------------------------------------------------------------------------
    ; Return nothing or data or data pointer
    ----------------------------------------------------------------------------*/
    return;
}
示例#4
0
void targetBitCalculation(void *input)
{
    VideoEncData *video = (VideoEncData *) input;
    MultiPass *pMP = video->pMP[video->currLayer];
    Vol *currVol = video->vol[video->currLayer];
    rateControl *rc = video->rc[video->currLayer];

    float 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 */

    if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
        return;

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

    /* 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 = video->sumMAD / (float)currVol->nTotalMB;
    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/(float)(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)  /*  7/31/03 */
        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)(M4VENC_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)(M4VENC_SQRT(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.5);
        //diff_counter_BTsrc = 10 - (Int)(curr_mad/pMP->aver_mad/0.1 + 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)(M4VENC_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)(M4VENC_SQRT(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.5);
        //diff_counter_BTsrc = 10 - (Int)(curr_mad/pMP->aver_mad_prev/0.1 + 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)((rc->Bs / 2 - rc->VBV_fullness) * 0.6 / (pMP->target_bits_per_frame / 10)); /* rc->Bs */
    diff_counter_BTsrc =  PV_MIN(diff_counter_BTsrc, bound);
    diff_counter_BTdst =  PV_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;     /*  1/17/02 -- For Low delay */

    diff_counter_BTsrc =  PV_MIN(diff_counter_BTsrc, bound);
    diff_counter_BTdst =  PV_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 (PV_ABS(prev_counter_diff) >= rc->max_BitVariance_num || PV_ABS(curr_counter_diff) >= rc->max_BitVariance_num) // PV_ABS(curr_counter_diff) >= PV_ABS(prev_counter_diff) )
    {   //diff_counter_BTsrc = diff_counter_BTdst = 0;

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

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


    /*3.diff_counter_BTsrc, diff_counter_BTdst ==> TMN_TH */
    //rc->TMN_TH = (Int)((float)pMP->bitrate/pMP->framerate);
    rc->TMN_TH = (Int)(pMP->target_bits_per_frame);
    pMP->diff_counter = 0;

    if (diff_counter_BTsrc)
    {
        rc->TMN_TH -= (Int)(pMP->target_bits_per_frame * diff_counter_BTsrc * 0.1);
        pMP->diff_counter = -diff_counter_BTsrc;
    }
    else if (diff_counter_BTdst)
    {
        rc->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 */
    rc->T = rc->TMN_TH - rc->TMN_W;
    //rc->T = rc->TMN_TH - (Int)((float)rc->TMN_W/rc->frameRate);

    if (video->encParams->H263_Enabled && rc->T > video->encParams->maxFrameSize)
    {
        rc->T = video->encParams->maxFrameSize;  //  added this 11/07/05
    }

}