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++; } } }
/* 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; }
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 } }