* Copyright (C) 2003 Antoine Missout
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
- * $Id: transrate.c,v 1.4 2003/11/22 17:03:57 fenrir Exp $
+ * $Id: transrate.c,v 1.5 2003/11/29 18:36:13 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
int h_offset, v_offset;
// mb
- double quant_corr, fact_x;
+ double quant_corr, fact_x, current_fact_x;
+ int level_i, level_p;
+
+ ssize_t i_current_gop_size, i_wanted_gop_size, i_new_gop_size;
} transrate_t;
id->i_next_gop_size = 0;
memset( &id->tr, 0, sizeof( transrate_t ) );
id->tr.bs.i_byte_in = id->tr.bs.i_byte_out = 0;
- id->tr.quant_corr = 0.0;
id->tr.fact_x = 1.0;
/* open output stream */
* transrater, code from M2VRequantizer http://www.metakine.com/
****************************************************************************/
-// toggles:
-// #define NDEBUG // turns off asserts
/* This is awful magic --Meuuh */
//#define REACT_DELAY (1024.0*128.0)
-#define REACT_DELAY (1024.0*4.0)
+#define REACT_DELAY (256.0)
+
+#define QUANT_I (1.7)
+
+#define QUANT_P (1.4)
+
+#define QUANT_P_INC (0.1)
+
+#define B_HANDICAP 5
// notes:
//
static int increment_quant( transrate_t *tr, int quant )
{
- if( tr->q_scale_type)
+ if( tr->q_scale_type )
{
- assert(quant >= 1 && quant <= 112);
+ assert(quant >= 1 && quant <= 112 );
quant = map_non_linear_mquant[quant] + 1;
- if( tr->quant_corr < -60.0f) quant++;
+ if( tr->picture_coding_type == P_TYPE )
+ quant += tr->level_p;
if( quant > 31) quant = 31;
quant = non_linear_mquant_table[quant];
}
{
assert(!(quant & 1));
quant += 2;
- if( tr->quant_corr < -60.0f) quant += 2;
+ if( tr->picture_coding_type == P_TYPE )
+ quant += 2 * tr->level_p;
if (quant > 62) quant = 62;
}
return quant;
double calc_quant, quant_to_use;
int mquant = 0;
- tr->quant_corr = (((bs->i_byte_in - (bs->p_r - 4 - bs->p_c)) / tr->fact_x) - (bs->i_byte_out + (bs->p_w - bs->p_ow))) / REACT_DELAY;
- calc_quant = curQuant * tr->fact_x;
- quant_to_use = calc_quant - tr->quant_corr;
-
- switch (tr->picture_coding_type )
+ switch ( tr->picture_coding_type )
{
case I_TYPE:
case P_TYPE:
- mquant = increment_quant( tr, curQuant);
+ mquant = increment_quant( tr, curQuant );
break;
case B_TYPE:
- mquant = intmax(scale_quant( tr->q_scale_type, quant_to_use), increment_quant( tr, curQuant));
+ tr->quant_corr = (((bs->i_byte_in - (bs->p_r - 4 - bs->p_c)) / tr->fact_x) - (bs->i_byte_out + (bs->p_w - bs->p_ow))) / REACT_DELAY + B_HANDICAP;
+ calc_quant = curQuant * tr->current_fact_x;
+ quant_to_use = calc_quant - tr->quant_corr;
+
+ mquant = intmax(scale_quant( tr->q_scale_type, quant_to_use), increment_quant( tr, curQuant) );
break;
default:
{
tab = DCT_B14_10 + (UBITS (bs->i_bit_in_cache, 10) - 8);
i += tab->run;
- if (i < 64) goto normal_code;
+ if (i < 64 ) goto normal_code;
}
else if (bs->i_bit_in_cache >= 0x00800000)
{
tab = DCT_13 + (UBITS (bs->i_bit_in_cache, 13) - 16);
i += tab->run;
- if (i < 64) goto normal_code;
+ if (i < 64 ) goto normal_code;
}
else if (bs->i_bit_in_cache >= 0x00200000)
{
tab = DCT_15 + (UBITS (bs->i_bit_in_cache, 15) - 16);
i += tab->run;
- if (i < 64) goto normal_code;
+ if (i < 64 ) goto normal_code;
}
else
{
tab = DCT_16 + UBITS (bs->i_bit_in_cache, 16);
- bs_flush( bs, 16);
+ bs_flush( bs, 16 );
i += tab->run;
- if (i < 64) goto normal_code;
+ if (i < 64 ) goto normal_code;
}
break; /* illegal, check needed to avoid buffer overflow */
}
if (blk != sblk)
{
blk--;
- // remove more coeffs if very late
- if ((tr->quant_corr < -60.0f) && (blk != sblk))
+ }
+
+ // remove more coeffs if very late
+ if (tr->level_p >= 4 && (blk != sblk))
+ {
+ blk--;
+ if (tr->level_p >= 5 && (blk != sblk))
{
blk--;
- if ((tr->quant_corr < -80.0f) && (blk != sblk))
+ if (tr->level_p >= 6 && (blk != sblk))
{
blk--;
- if ((tr->quant_corr < -100.0f) && (blk != sblk))
- {
+ if (tr->level_p >= 7 && (blk != sblk))
blk--;
- if ((tr->quant_corr < -120.0f) && (blk != sblk))
- blk--;
- }
}
}
}
{
uint8_t *outTemp = bs->p_w, *inTemp = bs->p_c;
+#if 0
if( ( tr->picture_coding_type == B_TYPE && tr->quant_corr < 2.5f ) || // don't recompress if we're in advance!
( tr->picture_coding_type == P_TYPE && tr->quant_corr < -2.5f ) ||
( tr->picture_coding_type == I_TYPE && tr->quant_corr < -5.0f ) )
+#else
+ if( ( tr->picture_coding_type == B_TYPE ) ||
+ ( tr->picture_coding_type == P_TYPE && tr->level_p ) ||
+ ( tr->picture_coding_type == I_TYPE && tr->level_i ) )
+#endif
{
if( !tr->horizontal_size_value || !tr->vertical_size_value )
{
sout_buffer_t *p_out;
+ double next_fact_x = 1.0;
+
/* The output buffer can't be bigger than the input buffer. */
p_out = sout_BufferNew( p_stream->p_sout, in->i_size );
*(in->p_buffer + in->i_size + 1) = 0;
*(in->p_buffer + in->i_size + 2) = 1;
*(in->p_buffer + in->i_size + 3) = 0;
- bs->i_byte_in += in->i_size;
+
+ /* Calculate how late we are */
+ tr->quant_corr = 0.0 + B_HANDICAP;
+ tr->level_i = 0;
+ tr->level_p = 0;
+ bs->i_byte_in = in->i_size;
+ bs->i_byte_out = 0;
+
+ if (tr->i_current_gop_size - in->i_size > 100)
+ {
+ if (tr->i_wanted_gop_size == in->i_size)
+ {
+ next_fact_x = 1.0;
+ }
+ else if ( tr->i_wanted_gop_size < in->i_size )
+ {
+ /* We're really late */
+ next_fact_x = 10.0;
+ }
+ else
+ {
+ next_fact_x = ((double)(tr->i_current_gop_size - in->i_size)) /
+ (tr->i_wanted_gop_size - in->i_size);
+ }
+
+ if (next_fact_x > QUANT_I)
+ {
+ tr->level_i = 1;
+ }
+ if (next_fact_x > QUANT_P)
+ {
+ tr->level_p = 1 + (next_fact_x - QUANT_P) / (QUANT_P_INC);
+ }
+ }
+ if ( tr->i_wanted_gop_size < 0 )
+ {
+ /* We're really late */
+ tr->current_fact_x = 3.0;
+ }
+ else
+ {
+ tr->current_fact_x = ((double)(tr->i_current_gop_size) /
+ (tr->i_wanted_gop_size));
+ }
for ( ; ; )
{
break;
}
- tr->quant_corr = (((bs->i_byte_in - (bs->p_r - 4 - bs->p_c)) / tr->fact_x) - (bs->i_byte_out + (bs->p_w - bs->p_ow))) / REACT_DELAY;
+ tr->quant_corr = (((bs->i_byte_in - (bs->p_r - 4 - bs->p_c)) / tr->fact_x) - (bs->i_byte_out + (bs->p_w - bs->p_ow))) / REACT_DELAY + B_HANDICAP;
}
bs->i_byte_out += bs->p_w - bs->p_ow;
p_out->i_size = bs->p_w - bs->p_ow;
+ tr->i_current_gop_size -= in->i_size;
+ tr->i_wanted_gop_size -= p_out->i_size;
+ tr->i_new_gop_size += bs->i_byte_out;
+
+#if 0
+ msg_Dbg( p_stream, "%d: %d -> %d (r: %f, n:%f, corr:%f)",
+ tr->picture_coding_type, in->i_size, p_out->i_size,
+ (float)in->i_size / p_out->i_size,
+ next_fact_x, tr->quant_corr);
+#endif
}
static int transrate_video_process( sout_stream_t *p_stream,
if( GetDWBE( in->p_buffer ) != 0x100 )
{
uint8_t *p = in->p_buffer;
- uint8_t *p_end = &in->p_buffer[in->i_buffer];
+ uint8_t *p_end = &in->p_buffer[in->i_size];
uint32_t code = GetDWBE( p );
/* We may have a GOP */
}
- if( b_gop )
+ if( b_gop && id->i_next_gop_duration >= 300000 )
{
while ( id->p_current_buffer != NULL )
{
/ (id->i_next_gop_duration / 1000);
static mtime_t i_old_bitrate = 0;
static mtime_t i_old_duration = 0;
- if (i_old_bitrate)
+ if (i_old_bitrate && tr->fact_x != 1.0)
{
- msg_Dbg(p_stream, "bitrate = %lld -> %lld", i_old_bitrate,
- (mtime_t)bs->i_byte_out * 8000 / (i_old_duration / 1000));
+ mtime_t i_new_bitrate = tr->i_new_gop_size * 8000 / (i_old_duration / 1000);
+ if (i_new_bitrate > p_stream->p_sys->i_vbitrate + 300000)
+ msg_Err(p_stream, "%lld -> %lld (%f, r:%f)",
+ i_old_bitrate, i_new_bitrate, tr->fact_x,
+ (float)i_old_bitrate / i_new_bitrate);
+#if 0
+ else
+ msg_Dbg(p_stream, "%lld -> %lld (%f, r:%f)",
+ i_old_bitrate, i_new_bitrate, tr->fact_x,
+ (float)i_old_bitrate / i_new_bitrate);
+#endif
}
i_old_bitrate = i_bitrate;
i_old_duration = id->i_next_gop_duration;
{
tr->fact_x = 1.0;
}
- msg_Dbg(p_stream, "new fact_x = %f", tr->fact_x);
+ id->tr.i_current_gop_size = id->i_next_gop_size;
+ id->tr.i_wanted_gop_size = (p_stream->p_sys->i_vbitrate)
+ * (id->i_next_gop_duration / 1000) / 8000;
+ id->tr.i_new_gop_size = 0;
id->p_current_buffer = id->p_next_gop;
id->p_next_gop = NULL;
id->i_next_gop_duration = 0;
id->i_next_gop_size = 0;
- bs->i_byte_in = 0;
- bs->i_byte_out = 0;
}
}
* input_clock.c: Clock/System date convertions, stream management
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: input_clock.c,v 1.42 2003/09/07 22:51:11 fenrir Exp $
+ * $Id: input_clock.c,v 1.43 2003/11/29 18:36:13 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* in all the FIFOs, but it may be not enough.
*/
+/* p_input->i_cr_average : Maximum number of samples used to compute the
+ * dynamic average value.
+ * We use the following formula :
+ * new_average = (old_average * c_average + new_sample_value) / (c_average +1)
+ */
+
static void ClockNewRef( pgrm_descriptor_t * p_pgrm,
mtime_t i_clock, mtime_t i_sysdate );
* Constants
*****************************************************************************/
-/* Maximum number of samples used to compute the dynamic average value.
- * We use the following formula :
- * new_average = (old_average * c_average + new_sample_value) / (c_average +1)
- */
-#define CR_MAX_AVERAGE_COUNTER 40
-
/* Maximum gap allowed between two CRs. */
#define CR_MAX_GAP 2000000
mtime_t i_extrapoled_clock = ClockCurrent( p_input, p_pgrm );
/* Bresenham algorithm to smooth variations. */
- if( p_pgrm->c_average_count == CR_MAX_AVERAGE_COUNTER )
+ if( p_pgrm->c_average_count == p_input->i_cr_average )
{
p_pgrm->delta_cr = ( p_pgrm->delta_cr
- * (CR_MAX_AVERAGE_COUNTER - 1)
+ * (p_input->i_cr_average - 1)
+ ( i_extrapoled_clock - i_clock ) )
- / CR_MAX_AVERAGE_COUNTER;
+ / p_input->i_cr_average;
}
else
{