/* Mad based variable bit allocation + QP calculation with a new quadratic method */ void calculateQuantizer_Multipass(AVCEncObject *encvid, AVCCommonObj *video, AVCRateControl *rateCtrl, MultiPass *pMP) { int prev_actual_bits = 0, curr_target, /*pos=0,*/i, j; OsclFloat Qstep, prev_QP = 0.625; OsclFloat curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP; /* Mad based variable bit allocation */ targetBitCalculation(encvid, video, rateCtrl, pMP); if (rateCtrl->T <= 0 || rateCtrl->totalSAD == 0) { if (rateCtrl->T < 0) rateCtrl->Qc = RC_MAX_QUANT; return; } /* ---------------------------------------------------------------------------------------------------*/ /* current frame QP estimation */ curr_target = rateCtrl->T; 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 */ curr_RD = (OsclFloat)curr_target / curr_mad; if (rateCtrl->skip_next_frame == -1) // previous was skipped { i = pMP->framePos; prev_mad = pMP->pRDSamples[i][0].mad; prev_QP = pMP->pRDSamples[i][0].QP; prev_actual_bits = pMP->pRDSamples[i][0].actual_bits; } else { /* Another version of search the optimal point */ prev_mad = 0.0; i = 0; while (i < pMP->frameRange && prev_mad < 0.001) /* find first one with nonzero prev_mad */ { prev_mad = pMP->pRDSamples[i][0].mad; i++; } if (i < pMP->frameRange) { prev_actual_bits = pMP->pRDSamples[i-1][0].actual_bits; for (j = 0; i < pMP->frameRange; i++) { if (pMP->pRDSamples[i][0].mad != 0 && AVC_ABS(prev_mad - curr_mad) > AVC_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 = QP2Qstep(pMP->pRDSamples[j][0].QP); for (i = 1; i < pMP->samplesPerFrame[j]; i++) { if (AVC_ABS(prev_actual_bits - curr_target) > AVC_ABS(pMP->pRDSamples[j][i].actual_bits - curr_target)) { prev_actual_bits = pMP->pRDSamples[j][i].actual_bits; prev_QP = QP2Qstep(pMP->pRDSamples[j][i].QP); } } } } // quadratic approximation if (prev_mad > 0.001) // only when prev_mad is greater than 0, otherwise keep using the same QP { prev_RD = (OsclFloat)prev_actual_bits / prev_mad; //rateCtrl->Qc = (Int)(prev_QP * sqrt(prev_actual_bits/curr_target) + 0.4); if (prev_QP == 0.625) // added this to allow getting out of QP = 0 easily { Qstep = (int)(prev_RD / curr_RD + 0.5); } else { // rateCtrl->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) Qstep = (int)(prev_QP * (oscl_sqrt(prev_RD / curr_RD) + prev_RD / curr_RD) / 2.0 + 0.9); /* Quadratic and linear approximation */ else Qstep = (int)(prev_QP * (oscl_sqrt(prev_RD / curr_RD) + oscl_pow(prev_RD / curr_RD, 1.0 / 3.0)) / 2.0 + 0.9); } // 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) && (rateCtrl->Qc < 12)) rateCtrl->Qc = 12; // else if((curr_mad < 128) && (rateCtrl->Qc < 3)) rateCtrl->Qc = 3; rateCtrl->Qc = Qstep2QP(Qstep); if (rateCtrl->Qc < RC_MIN_QUANT) rateCtrl->Qc = RC_MIN_QUANT; if (rateCtrl->Qc > RC_MAX_QUANT) rateCtrl->Qc = RC_MAX_QUANT; } /* active bit resource protection */ aver_QP = (pMP->encoded_frames == 0 ? 0 : pMP->sum_QP / (OsclFloat)pMP->encoded_frames); average_mad = (pMP->encoded_frames == 0 ? 0 : pMP->sum_mad / (OsclFloat)pMP->encoded_frames); /* this function is called from the scond encoded frame*/ if (pMP->diff_counter == 0 && ((OsclFloat)rateCtrl->Qc <= aver_QP*1.1 || curr_mad <= average_mad*1.1) && pMP->counter_BTsrc <= (pMP->counter_BTdst + (int)(pMP->framerate*1.0 + 0.5))) { rateCtrl->TMN_TH -= (int)(pMP->target_bits_per_frame / 10.0); rateCtrl->T = rateCtrl->TMN_TH - rateCtrl->TMN_W; pMP->counter_BTsrc++; pMP->diff_counter--; } }
/* 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--; } }