Commit 9c11fac3 authored by Christophe Massiot's avatar Christophe Massiot

* modules/stream_out/transrate: Rewrote the transrater to use a SAD error

  estimation ; if the error is too high, lower the quantizer scale.
parent a7bac1e6
SOURCES_stream_out_transrate = transrate.c frame.c getvlc.h putvlc.h SOURCES_stream_out_transrate = transrate.c frame.c block.c getvlc.h putvlc.h
This diff is collapsed.
This diff is collapsed.
...@@ -395,3 +395,4 @@ static const MBAtab MBA_11 [] = { ...@@ -395,3 +395,4 @@ static const MBAtab MBA_11 [] = {
{ 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
{ 7, 7}, { 7, 7}, { 7, 7}, { 7, 7} { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}
}; };
// put blk /* vlc.h, variable length code tables (used by routines in putvlc.c) */
/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
/*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license fee or
* royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
* any and all warranties, whether express, implied, or statuary, including any
* implied warranties or merchantability or of fitness for a particular
* purpose. In no event shall the copyright-holder be liable for any
* incidental, punitive, or consequential damages of any kind whatsoever
* arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and user's
* customers, employees, agents, transferees, successors, and assigns.
*
* The MPEG Software Simulation Group does not represent or warrant that the
* programs furnished hereunder are free of infringement of any third-party
* patents.
*
* Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
* are subject to royalty fees to patent holders. Many of these patents are
* general enough such that they are unavoidable regardless of implementation
* design.
*
*/
/* type definitions for variable length code table entries */ /* type definitions for variable length code table entries */
...@@ -16,6 +43,28 @@ typedef struct ...@@ -16,6 +43,28 @@ typedef struct
} sVLCtable; } sVLCtable;
/* data from ISO/IEC 13818-2 DIS, Annex B, variable length code tables */
/* Table B-1, variable length codes for macroblock_address_increment
*
* indexed by [macroblock_address_increment-1]
* 'macroblock_escape' is treated elsewhere
*/
const static VLCtable addrinctab[33]=
{
{0x01,1}, {0x03,3}, {0x02,3}, {0x03,4},
{0x02,4}, {0x03,5}, {0x02,5}, {0x07,7},
{0x06,7}, {0x0b,8}, {0x0a,8}, {0x09,8},
{0x08,8}, {0x07,8}, {0x06,8}, {0x17,10},
{0x16,10}, {0x15,10}, {0x14,10}, {0x13,10},
{0x12,10}, {0x23,11}, {0x22,11}, {0x21,11},
{0x20,11}, {0x1f,11}, {0x1e,11}, {0x1d,11},
{0x1c,11}, {0x1b,11}, {0x1a,11}, {0x19,11},
{0x18,11}
};
/* Table B-2, B-3, B-4 variable length codes for macroblock_type /* Table B-2, B-3, B-4 variable length codes for macroblock_type
* *
* indexed by [macroblock_type] * indexed by [macroblock_type]
...@@ -79,7 +128,6 @@ const static VLCtable cbptable[64]= ...@@ -79,7 +128,6 @@ const static VLCtable cbptable[64]=
}; };
/* Table B-14, DCT coefficients table zero /* Table B-14, DCT coefficients table zero
* *
* indexed by [run][level-1] * indexed by [run][level-1]
...@@ -226,3 +274,27 @@ const static VLCtable dct_code_tab2a[30][5]= ...@@ -226,3 +274,27 @@ const static VLCtable dct_code_tab2a[30][5]=
{{0x1c,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1c,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}},
{{0x1b,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}} {{0x1b,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}
}; };
/* MPEG-4 matrices */
static const uint8_t mpeg4_default_intra_matrix[64] = {
8, 17, 18, 19, 21, 23, 25, 27,
17, 18, 19, 21, 23, 25, 27, 28,
20, 21, 22, 23, 24, 26, 28, 30,
21, 22, 23, 24, 26, 28, 30, 32,
22, 23, 24, 26, 28, 30, 32, 35,
23, 24, 26, 28, 30, 32, 35, 38,
25, 26, 28, 30, 32, 35, 38, 41,
27, 28, 30, 32, 35, 38, 41, 45,
};
static const uint8_t mpeg4_default_non_intra_matrix[64] = {
16, 17, 18, 19, 20, 21, 22, 23,
17, 18, 19, 20, 21, 22, 23, 24,
18, 19, 20, 21, 22, 23, 24, 25,
19, 20, 21, 22, 23, 24, 26, 27,
20, 21, 22, 23, 25, 26, 27, 28,
21, 22, 23, 24, 26, 27, 28, 30,
22, 23, 24, 26, 27, 28, 30, 31,
23, 24, 25, 27, 28, 30, 31, 33,
};
...@@ -49,9 +49,6 @@ static int Send( sout_stream_t *, sout_stream_id_t *, block_t * ); ...@@ -49,9 +49,6 @@ static int Send( sout_stream_t *, sout_stream_id_t *, block_t * );
static int transrate_video_process( sout_stream_t *, sout_stream_id_t *, block_t *, block_t ** ); static int transrate_video_process( sout_stream_t *, sout_stream_id_t *, block_t *, block_t ** );
void E_(process_frame)( sout_stream_t *p_stream,
sout_stream_id_t *id, block_t *in, block_t **out );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -68,8 +65,8 @@ struct sout_stream_sys_t ...@@ -68,8 +65,8 @@ struct sout_stream_sys_t
int i_vbitrate; int i_vbitrate;
mtime_t i_shaping_delay; mtime_t i_shaping_delay;
int b_mpeg4_matrix;
mtime_t i_first_frame;
mtime_t i_dts, i_pts; mtime_t i_dts, i_pts;
}; };
...@@ -113,7 +110,11 @@ static int Open( vlc_object_t *p_this ) ...@@ -113,7 +110,11 @@ static int Open( vlc_object_t *p_this )
} }
} }
p_sys->i_first_frame = 0; p_sys->b_mpeg4_matrix = 0;
if( sout_cfg_find( p_stream->p_cfg, "mpeg4-matrix" ) )
{
p_sys->b_mpeg4_matrix = 1;
}
msg_Dbg( p_stream, "codec video %dkb/s max gop="I64Fd"us", msg_Dbg( p_stream, "codec video %dkb/s max gop="I64Fd"us",
p_sys->i_vbitrate / 1024, p_sys->i_shaping_delay ); p_sys->i_vbitrate / 1024, p_sys->i_shaping_delay );
...@@ -167,7 +168,7 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -167,7 +168,7 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
id->i_next_gop_size = 0; id->i_next_gop_size = 0;
memset( &id->tr, 0, sizeof( transrate_t ) ); memset( &id->tr, 0, sizeof( transrate_t ) );
id->tr.bs.i_byte_in = id->tr.bs.i_byte_out = 0; id->tr.bs.i_byte_in = id->tr.bs.i_byte_out = 0;
id->tr.fact_x = 1.0; id->tr.mpeg4_matrix = p_sys->b_mpeg4_matrix;
/* open output stream */ /* open output stream */
id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt ); id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
...@@ -261,25 +262,19 @@ static int transrate_video_process( sout_stream_t *p_stream, ...@@ -261,25 +262,19 @@ static int transrate_video_process( sout_stream_t *p_stream,
/ (id->i_next_gop_duration / 1000); / (id->i_next_gop_duration / 1000);
mtime_t i_new_bitrate; mtime_t i_new_bitrate;
if ( i_bitrate > p_stream->p_sys->i_vbitrate ) id->tr.i_total_input = id->i_next_gop_size;
{ id->tr.i_remaining_input = id->i_next_gop_size;
tr->fact_x = (double)i_bitrate / p_stream->p_sys->i_vbitrate; id->tr.i_wanted_output = (p_stream->p_sys->i_vbitrate)
}
else
{
tr->fact_x = 1.0;
}
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->i_next_gop_duration / 1000) / 8000;
id->tr.i_new_gop_size = 0; id->tr.i_current_output = 0;
id->p_current_buffer = id->p_next_gop; id->p_current_buffer = id->p_next_gop;
while ( id->p_current_buffer != NULL ) while ( id->p_current_buffer != NULL )
{ {
block_t * p_next = id->p_current_buffer->p_next; block_t * p_next = id->p_current_buffer->p_next;
if ( tr->fact_x == 1.0 ) if ( !p_stream->p_sys->b_mpeg4_matrix
&& id->tr.i_wanted_output >= id->tr.i_total_input )
{ {
bs->i_byte_out += id->p_current_buffer->i_buffer; bs->i_byte_out += id->p_current_buffer->i_buffer;
id->p_current_buffer->p_next = NULL; id->p_current_buffer->p_next = NULL;
...@@ -287,25 +282,33 @@ static int transrate_video_process( sout_stream_t *p_stream, ...@@ -287,25 +282,33 @@ static int transrate_video_process( sout_stream_t *p_stream,
} }
else else
{ {
E_(process_frame)( p_stream, id, id->p_current_buffer, out ); if ( process_frame( p_stream, id, id->p_current_buffer,
block_Release( id->p_current_buffer); out, 0 ) < 0 )
{
id->p_current_buffer->p_next = NULL;
block_ChainAppend( out, id->p_current_buffer );
if ( p_stream->p_sys->b_mpeg4_matrix )
id->tr.i_wanted_output = id->tr.i_total_input;
}
else
{
block_Release( id->p_current_buffer );
}
} }
id->p_current_buffer = p_next; id->p_current_buffer = p_next;
} }
if ( tr->fact_x != 1.0 ) if ( id->tr.i_wanted_output < id->tr.i_total_input )
{ {
i_new_bitrate = (mtime_t)tr->i_new_gop_size * 8000 i_new_bitrate = (mtime_t)tr->i_current_output * 8000
/ (id->i_next_gop_duration / 1001); / (id->i_next_gop_duration / 1000);
if (i_new_bitrate > p_stream->p_sys->i_vbitrate + 300000) if (i_new_bitrate > p_stream->p_sys->i_vbitrate + 300000)
msg_Err(p_stream, "%lld -> %lld (%f, r:%f) d=%lld", msg_Err(p_stream, "%lld -> %lld d=%lld",
i_bitrate, i_new_bitrate, tr->fact_x, i_bitrate, i_new_bitrate,
(float)i_bitrate / i_new_bitrate,
id->i_next_gop_duration); id->i_next_gop_duration);
else else
msg_Dbg(p_stream, "%lld -> %lld (%f, r:%f) d=%lld", msg_Dbg(p_stream, "%lld -> %lld d=%lld",
i_bitrate, i_new_bitrate, tr->fact_x, i_bitrate, i_new_bitrate,
(float)i_bitrate / i_new_bitrate,
id->i_next_gop_duration); id->i_next_gop_duration);
} }
......
...@@ -64,6 +64,9 @@ typedef struct ...@@ -64,6 +64,9 @@ typedef struct
// seq header // seq header
unsigned int horizontal_size_value; unsigned int horizontal_size_value;
unsigned int vertical_size_value; unsigned int vertical_size_value;
uint8_t intra_quantizer_matrix [64];
uint8_t non_intra_quantizer_matrix [64];
int mpeg4_matrix;
// pic header // pic header
unsigned int picture_coding_type; unsigned int picture_coding_type;
...@@ -76,7 +79,7 @@ typedef struct ...@@ -76,7 +79,7 @@ typedef struct
unsigned int concealment_motion_vectors; unsigned int concealment_motion_vectors;
unsigned int q_scale_type; unsigned int q_scale_type;
unsigned int intra_vlc_format; unsigned int intra_vlc_format;
/* unsigned int alternate_scan; */ const uint8_t * scan;
// slice or mb // slice or mb
// quantizer_scale_code // quantizer_scale_code
...@@ -84,12 +87,16 @@ typedef struct ...@@ -84,12 +87,16 @@ typedef struct
unsigned int new_quantizer_scale; unsigned int new_quantizer_scale;
unsigned int last_coded_scale; unsigned int last_coded_scale;
int h_offset, v_offset; int h_offset, v_offset;
vlc_bool_t b_error;
// mb // mb
double quant_corr, fact_x, current_fact_x; double qrate;
int level_i, level_p; int i_admissible_error, i_minimum_error;
ssize_t i_current_gop_size, i_wanted_gop_size, i_new_gop_size; /* input buffers */
ssize_t i_total_input, i_remaining_input;
/* output buffers */
ssize_t i_current_output, i_wanted_output;
} transrate_t; } transrate_t;
...@@ -107,3 +114,102 @@ struct sout_stream_id_t ...@@ -107,3 +114,102 @@ struct sout_stream_id_t
}; };
#ifdef HAVE_BUILTIN_EXPECT
#define likely(x) __builtin_expect ((x) != 0, 1)
#define unlikely(x) __builtin_expect ((x) != 0, 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif
#define BITS_IN_BUF (8)
#define LOG(msg) fprintf (stderr, msg)
#define LOGF(format, args...) fprintf (stderr, format, args)
static inline void bs_write( bs_transrate_t *s, unsigned int val, int n )
{
assert(n < 32);
assert(!(val & (0xffffffffU << n)));
while (unlikely(n >= s->i_bit_out))
{
s->p_w[0] = (s->i_bit_out_cache << s->i_bit_out ) | (val >> (n - s->i_bit_out));
s->p_w++;
n -= s->i_bit_out;
s->i_bit_out_cache = 0;
val &= ~(0xffffffffU << n);
s->i_bit_out = BITS_IN_BUF;
}
if (likely(n))
{
s->i_bit_out_cache = (s->i_bit_out_cache << n) | val;
s->i_bit_out -= n;
}
assert(s->i_bit_out > 0);
assert(s->i_bit_out <= BITS_IN_BUF);
}
static inline void bs_refill( bs_transrate_t *s )
{
assert((s->p_r - s->p_c) >= 1);
s->i_bit_in_cache |= s->p_c[0] << (24 - s->i_bit_in);
s->i_bit_in += 8;
s->p_c++;
}
static inline void bs_flush( bs_transrate_t *s, unsigned int n )
{
assert(s->i_bit_in >= n);
s->i_bit_in_cache <<= n;
s->i_bit_in -= n;
assert( (!n) || ((n>0) && !(s->i_bit_in_cache & 0x1)) );
while (unlikely(s->i_bit_in < 24)) bs_refill( s );
}
static inline unsigned int bs_read( bs_transrate_t *s, unsigned int n )
{
unsigned int Val = ((unsigned int)s->i_bit_in_cache) >> (32 - n);
bs_flush( s, n );
return Val;
}
static inline unsigned int bs_copy( bs_transrate_t *s, unsigned int n )
{
unsigned int Val = bs_read( s, n);
bs_write(s, Val, n);
return Val;
}
static inline void bs_flush_read( bs_transrate_t *s )
{
int i = s->i_bit_in & 0x7;
if( i )
{
assert(((unsigned int)s->i_bit_in_cache) >> (32 - i) == 0);
s->i_bit_in_cache <<= i;
s->i_bit_in -= i;
}
s->p_c += -1 * (s->i_bit_in >> 3);
s->i_bit_in = 0;
}
static inline void bs_flush_write( bs_transrate_t *s )
{
if( s->i_bit_out != 8 ) bs_write(s, 0, s->i_bit_out);
}
int scale_quant( transrate_t *tr, double qrate );
int transrate_mb( transrate_t *tr, RunLevel blk[6][65], RunLevel new_blk[6][65], int i_cbp, int intra );
void get_intra_block_B14( transrate_t *tr, RunLevel *blk );
void get_intra_block_B15( transrate_t *tr, RunLevel *blk );
int get_non_intra_block( transrate_t *tr, RunLevel *blk );
void putnonintrablk( bs_transrate_t *bs, RunLevel *blk);
void putintrablk( bs_transrate_t *bs, RunLevel *blk, int vlcformat);
int process_frame( sout_stream_t *p_stream, sout_stream_id_t *id,
block_t *in, block_t **out, int i_handicap );
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