3 |
* XviD Standard Plugins |
* XviD Standard Plugins |
4 |
* - single-pass bitrate controller implementation - |
* - single-pass bitrate controller implementation - |
5 |
* |
* |
6 |
* Copyright(C) 2002 Benjamin Lambert <foxer@hotmail.com> |
* Copyright(C) 2002-2004 Benjamin Lambert <foxer@hotmail.com> |
7 |
* 2002-2003 Edouard Gomez <ed.gomez@free.fr> |
* 2002-2003 Edouard Gomez <ed.gomez@free.fr> |
8 |
* |
* |
9 |
* This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
20 |
* along with this program; if not, write to the Free Software |
* along with this program; if not, write to the Free Software |
21 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
22 |
* |
* |
23 |
* $Id: plugin_single.c,v 1.2 2004-03-22 22:36:24 edgomez Exp $ |
* $Id: plugin_single.c,v 1.3 2004-08-10 22:34:32 edgomez Exp $ |
24 |
* |
* |
25 |
****************************************************************************/ |
****************************************************************************/ |
26 |
|
|
186 |
rc->time += (double) data->fincr / data->fbase; |
rc->time += (double) data->fincr / data->fbase; |
187 |
rc->total_size += data->length; |
rc->total_size += data->length; |
188 |
|
|
|
if(data->type == XVID_TYPE_BVOP) |
|
|
return (0); |
|
|
|
|
|
rc->rtn_quant = data->quant; |
|
|
|
|
189 |
/* Compute the deviation from expected total size */ |
/* Compute the deviation from expected total size */ |
190 |
deviation = |
deviation = |
191 |
rc->total_size - rc->bytes_per_sec * rc->time; |
rc->total_size - rc->bytes_per_sec * rc->time; |
192 |
|
|
|
|
|
|
if (data->quant >= 2) { |
|
|
|
|
193 |
averaging_period = (double) rc->averaging_period; |
averaging_period = (double) rc->averaging_period; |
194 |
|
|
195 |
|
/* calculate the sequence quality */ |
196 |
rc->sequence_quality -= rc->sequence_quality / averaging_period; |
rc->sequence_quality -= rc->sequence_quality / averaging_period; |
197 |
|
|
198 |
rc->sequence_quality += |
rc->sequence_quality += |
199 |
2.0 / (double) data->quant / averaging_period; |
2.0 / (double) data->quant / averaging_period; |
200 |
|
|
201 |
|
/* clamp the sequence quality to 10% to 100% |
202 |
|
* to try to avoid using the highest |
203 |
|
* and lowest quantizers 'too' much */ |
204 |
if (rc->sequence_quality < 0.1) |
if (rc->sequence_quality < 0.1) |
205 |
rc->sequence_quality = 0.1; |
rc->sequence_quality = 0.1; |
206 |
|
else if (rc->sequence_quality > 1.0) |
207 |
|
rc->sequence_quality = 1.0; |
208 |
|
|
209 |
|
/* factor this frame's size into the average framesize |
210 |
|
* but skip using ivops as they are usually very large |
211 |
|
* and as such, usually disrupt quantizer distribution */ |
212 |
if (data->type != XVID_TYPE_IVOP) { |
if (data->type != XVID_TYPE_IVOP) { |
213 |
reaction_delay_factor = (double) rc->reaction_delay_factor; |
reaction_delay_factor = (double) rc->reaction_delay_factor; |
214 |
rc->avg_framesize -= rc->avg_framesize / reaction_delay_factor; |
rc->avg_framesize -= rc->avg_framesize / reaction_delay_factor; |
215 |
rc->avg_framesize += data->length / reaction_delay_factor; |
rc->avg_framesize += data->length / reaction_delay_factor; |
216 |
} |
} |
217 |
|
|
218 |
} |
/* don't change the quantizer between pvops */ |
219 |
|
if (data->type == XVID_TYPE_BVOP) |
220 |
|
return (0); |
221 |
|
|
222 |
|
/* calculate the quality_scale which will be used |
223 |
|
* to drag the target quality up or down, depending |
224 |
|
* on if avg_framesize is >= target_framesize */ |
225 |
quality_scale = |
quality_scale = |
226 |
rc->target_framesize / rc->avg_framesize * rc->target_framesize / |
rc->target_framesize / rc->avg_framesize * |
227 |
rc->avg_framesize; |
rc->target_framesize / rc->avg_framesize; |
228 |
|
|
229 |
|
/* use the current sequence_quality as the |
230 |
|
* base_quality which will be dragged around |
231 |
|
* |
232 |
|
* 0.06452 = 6.452% quality (quant:31) */ |
233 |
base_quality = rc->sequence_quality; |
base_quality = rc->sequence_quality; |
234 |
if (quality_scale >= 1.0) { |
if (quality_scale >= 1.0) { |
235 |
base_quality = 1.0 - (1.0 - base_quality) / quality_scale; |
base_quality = 1.0 - (1.0 - base_quality) / quality_scale; |
239 |
|
|
240 |
overflow = -((double) deviation / (double) rc->buffer); |
overflow = -((double) deviation / (double) rc->buffer); |
241 |
|
|
242 |
|
/* clamp overflow to 1 buffer unit to avoid very |
243 |
|
* large bursts of bitrate following still scenes */ |
244 |
|
if (overflow > rc->target_framesize) |
245 |
|
overflow = rc->target_framesize; |
246 |
|
else if (overflow < -rc->target_framesize) |
247 |
|
overflow = -rc->target_framesize; |
248 |
|
|
249 |
|
/* apply overflow / buffer to get the target_quality */ |
250 |
target_quality = |
target_quality = |
251 |
base_quality + (base_quality - |
base_quality + (base_quality - |
252 |
0.06452) * overflow / rc->target_framesize; |
0.06452) * overflow / rc->target_framesize; |
253 |
|
|
254 |
|
/* clamp the target_quality to quant 1-31 |
255 |
|
* 2.0 = 200% quality (quant:1) */ |
256 |
if (target_quality > 2.0) |
if (target_quality > 2.0) |
257 |
target_quality = 2.0; |
target_quality = 2.0; |
258 |
else if (target_quality < 0.06452) |
else if (target_quality < 0.06452) |
260 |
|
|
261 |
rtn_quant = (int) (2.0 / target_quality); |
rtn_quant = (int) (2.0 / target_quality); |
262 |
|
|
263 |
|
/* accumulate quant <-> quality error and apply if >= 1.0 */ |
264 |
if (rtn_quant > 0 && rtn_quant < 31) { |
if (rtn_quant > 0 && rtn_quant < 31) { |
265 |
rc->quant_error[rtn_quant - 1] += 2.0 / target_quality - rtn_quant; |
rc->quant_error[rtn_quant - 1] += 2.0 / target_quality - rtn_quant; |
266 |
if (rc->quant_error[rtn_quant - 1] >= 1.0) { |
if (rc->quant_error[rtn_quant - 1] >= 1.0) { |
267 |
rc->quant_error[rtn_quant - 1] -= 1.0; |
rc->quant_error[rtn_quant - 1] -= 1.0; |
268 |
rtn_quant++; |
rtn_quant++; |
269 |
|
rc->rtn_quant++; |
270 |
} |
} |
271 |
} |
} |
272 |
|
|
273 |
/* prevent rapid quantization change */ |
/* prevent rapid quantization change */ |
274 |
if (rtn_quant > data->quant + 1) |
if (rtn_quant > rc->rtn_quant + 1) { |
275 |
rtn_quant = data->quant + 1; |
if (rtn_quant > rc->rtn_quant + 3) |
276 |
else if (rtn_quant < data->quant - 1) |
if (rtn_quant > rc->rtn_quant + 5) |
277 |
rtn_quant = data->quant - 1; |
rtn_quant = rc->rtn_quant + 3; |
278 |
|
else |
279 |
|
rtn_quant = rc->rtn_quant + 2; |
280 |
|
else |
281 |
|
rtn_quant = rc->rtn_quant + 1; |
282 |
|
} |
283 |
|
else if (rtn_quant < rc->rtn_quant - 1) { |
284 |
|
if (rtn_quant < rc->rtn_quant - 3) |
285 |
|
if (rtn_quant < rc->rtn_quant - 5) |
286 |
|
rtn_quant = rc->rtn_quant - 3; |
287 |
|
else |
288 |
|
rtn_quant = rc->rtn_quant - 2; |
289 |
|
else |
290 |
|
rtn_quant = rc->rtn_quant - 1; |
291 |
|
} |
292 |
|
|
293 |
rc->rtn_quant = rtn_quant; |
rc->rtn_quant = rtn_quant; |
294 |
|
|