Commit 2613ac41 authored by Christophe Massiot's avatar Christophe Massiot

* input: new cr-average option, allowing to configure the

  CR_AVERAGE #define in input_clock.c (useful for PVR input)
* modules/codec/ffmpeg/encoder.c, modules/stream_out/transcode.c : fixes
  for older version of ffmpeg
* modules/stream_out/transrate/transrate.c : misc optimizations
parent 55bb1c7a
......@@ -4,7 +4,7 @@
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-intf.h,v 1.100 2003/11/24 00:39:00 fenrir Exp $
* $Id: input_ext-intf.h,v 1.101 2003/11/29 18:36:13 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -309,6 +309,7 @@ struct input_thread_t
access_sys_t * p_access_data;
size_t i_mtu;
int i_pts_delay; /* internal caching */
int i_cr_average;
/* Stream */
stream_t *s;
......
......@@ -2,7 +2,7 @@
* encoder.c: video and audio encoder using the ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: encoder.c,v 1.16 2003/11/29 18:06:12 fenrir Exp $
* $Id: encoder.c,v 1.17 2003/11/29 18:36:13 massiot Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
......@@ -326,7 +326,7 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
frame.pict_type = 0;
frame.repeat_pict = p_pict->i_nb_fields;
#if LIBAVCODEC_BUILD >= 468
#if LIBAVCODEC_BUILD >= 4684
frame.interlaced_frame = !p_pict->b_progressive;
frame.top_field_first = p_pict->b_top_field_first;
#endif
......
......@@ -2,7 +2,7 @@
* transcode.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: transcode.c,v 1.55 2003/11/27 22:44:51 massiot Exp $
* $Id: transcode.c,v 1.56 2003/11/29 18:36:13 massiot Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
......@@ -1383,7 +1383,9 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream,
pic.b_progressive = 1; /* ffmpeg doesn't support interlaced encoding */
pic.i_nb_fields = frame->repeat_pict;
#if LIBAVCODEC_BUILD >= 4684
pic.b_top_field_first = frame->top_field_first;
#endif
/* Interpolate the next PTS
* (needed by the mpeg video packetizer which can send pts <= 0 ) */
......
......@@ -6,7 +6,7 @@
* 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>
......@@ -194,7 +194,10 @@ typedef struct
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;
......@@ -233,7 +236,6 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
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 */
......@@ -300,11 +302,17 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
* 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:
//
......@@ -468,11 +476,12 @@ static int scale_quant( unsigned int q_scale_type, double quant )
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];
}
......@@ -480,7 +489,8 @@ static int increment_quant( transrate_t *tr, int 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;
......@@ -502,19 +512,19 @@ static int getNewQuant( transrate_t *tr, int curQuant)
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:
......@@ -940,26 +950,26 @@ static void get_intra_block_B14( bs_transrate_t *bs, const int i_qscale, const i
{
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 */
}
......@@ -1159,19 +1169,20 @@ static int get_non_intra_block_drop( transrate_t *tr, RunLevel *blk)
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--;
}
}
}
}
......@@ -1819,9 +1830,15 @@ static int do_next_start_code( transrate_t *tr )
{
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 )
{
......@@ -1881,6 +1898,8 @@ static void process_frame( sout_stream_t *p_stream,
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 );
......@@ -1898,7 +1917,50 @@ static void process_frame( sout_stream_t *p_stream,
*(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 ( ; ; )
{
......@@ -1947,11 +2009,21 @@ static void process_frame( sout_stream_t *p_stream,
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,
......@@ -1966,7 +2038,7 @@ 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 */
......@@ -1987,7 +2059,7 @@ static int transrate_video_process( sout_stream_t *p_stream,
}
if( b_gop )
if( b_gop && id->i_next_gop_duration >= 300000 )
{
while ( id->p_current_buffer != NULL )
{
......@@ -2012,10 +2084,19 @@ static int transrate_video_process( sout_stream_t *p_stream,
/ (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;
......@@ -2027,14 +2108,15 @@ static int transrate_video_process( sout_stream_t *p_stream,
{
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;
}
}
......
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id: input.c,v 1.267 2003/11/28 17:04:31 fenrir Exp $
* $Id: input.c,v 1.268 2003/11/29 18:36:13 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -180,6 +180,7 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
p_input->pf_demux = NULL;
p_input->pf_rewind = NULL;
p_input->pf_demux_control = NULL;
p_input->i_cr_average = config_GetInt( p_input, "cr-average" );
/* Access */
p_input->p_access = NULL;
......
......@@ -2,7 +2,7 @@
* 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>
*
......@@ -61,6 +61,12 @@
* 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 );
......@@ -68,12 +74,6 @@ static void ClockNewRef( pgrm_descriptor_t * p_pgrm,
* 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
......@@ -291,12 +291,12 @@ void input_ClockManageRef( input_thread_t * p_input,
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
{
......
......@@ -2,7 +2,7 @@
* libvlc.h: main libvlc header
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id: libvlc.h,v 1.109 2003/11/27 05:46:01 fenrir Exp $
* $Id: libvlc.h,v 1.110 2003/11/29 18:36:13 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -257,6 +257,11 @@ static char *ppsz_language_text[] =
#define INPUT_CAT_LONGTEXT N_( " " )
#define CR_AVERAGE_TEXT N_("Clock reference average counter")
#define CR_AVERAGE_LONGTEXT N_( \
"When using the PVR input (or a very irregular source), you should " \
"set this to 10000.")
#define SERVER_PORT_TEXT N_("Server port")
#define SERVER_PORT_LONGTEXT N_( \
"This is the port used for UDP streams. By default, we chose 1234.")
......@@ -669,6 +674,8 @@ vlc_module_begin();
/* Input options */
add_category_hint( N_("Input"), INPUT_CAT_LONGTEXT , VLC_FALSE );
add_integer( "cr-average", 40, NULL, CR_AVERAGE_TEXT,
CR_AVERAGE_LONGTEXT, VLC_FALSE );
add_integer( "server-port", 1234, NULL,
SERVER_PORT_TEXT, SERVER_PORT_LONGTEXT, VLC_FALSE );
add_integer( "mtu", 1500, NULL, MTU_TEXT, MTU_LONGTEXT, VLC_TRUE );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment