Commit 54f82a15 authored by Christophe Massiot's avatar Christophe Massiot

Un bon morceau du parseur.

Stef, je ne t'oublie pas, demain t'auras du boulot, promis :)
parent a6dfb286
......@@ -62,6 +62,7 @@ typedef struct undec_picture_s
boolean_t b_mpeg2;
int i_mb_height, i_mb_width;
int i_structure;
mtime_t i_pts;
macroblock_info_t * p_mb_info;
......@@ -87,15 +88,32 @@ typedef struct undec_picture_s
/*******************************************************************************
* pel_lookup_table_t : lookup table for pixels
*******************************************************************************/
typedef struct pel_lookup_table_s {
#ifdef BIG_PICTURES
u32 * pi_pel;
# define PEL_P u32
#else
u16 * pi_pel;
# define PEL_P u16
#endif
typedef struct pel_lookup_table_s {
PEL_P * pi_pel;
/* When the size of the picture changes, this structure is freed, so we
* keep a reference count. */
int i_refcount;
vlc_mutex_t lock;
} pel_lookup_table_t;
#define LINK_LOOKUP(p_l) \
vlc_mutex_lock( (p_l)->lock ); \
(p_l)->i_refcount++; \
vlc_mutex_unlock( (p_l)->lock );
#define UNLINK_LOOKUP(p_l) \
vlc_mutex_lock( (p_l)->lock ); \
(p_l)->i_refcount--; \
if( (p_l)->i_refcount <= 0 ) \
{ \
vlc_mutex_unlock( (p_l)->lock ); \
free( p_l ); \
} \
vlc_mutex_unlock( (p_l)->lock );
......@@ -22,9 +22,20 @@
*******************************************************************************/
typedef struct sequence_s
{
u32 i_height, i_width;
u16 i_height, i_width;
u16 i_mb_height, i_mb_width;
unsigned int i_aspect_ratio;
double frame_rate;
double d_frame_rate;
unsigned int i_chroma_format;
boolean_t b_mpeg2;
boolean_t b_progressive;
/* Parser context */
picture_t * p_forward, p_backward;
pel_lookup_table_t * p_frame_lum_lookup, p_field_lum_lookup;
pel_lookup_table_t * p_frame_chroma_lookup, p_field_chroma_lookup;
quant_matrix_t intra_quant, nonintra_quant;
quant_matrix_t chroma_intra_quant, chroma_nonintra_quant;
} sequence_t;
/*******************************************************************************
......
/*****************************************************************************
* vpar_blocks.h : video parser blocks management
* (c)1999 VideoLAN
*****************************************************************************
*****************************************************************************
* Requires:
* "config.h"
* "common.h"
* "mtime.h"
* "vlc_thread.h"
* "input.h"
* "video.h"
* "video_output.h"
* "decoder_fifo.h"
* "video_fifo.h"
*****************************************************************************/
/*****************************************************************************
* quant_matrix_t : Quantization Matrix
*****************************************************************************
* ??
*****************************************************************************/
typedef struct quant_matrix_s
{
int pi_matrix[64];
boolean_t b_allocated;
/* Has the matrix been allocated by vpar_headers ? */
} quant_matrix_t;
extern int * pi_default_intra_quant;
extern int * pi_default_nonintra_quant;
......@@ -55,6 +55,7 @@ void vpar_InitFIFO( vpar_thread_t * p_vpar )
for( i_dummy = 0; i_dummy < VFIFO_SIZE + 1; i_dummy++ )
{
p_vpar->vfifo.pp_undec_free[i_dummy] = p_vpar->vfifo.p_undec_p + i;
p_vpar->vfifo.p_undec_p[i].p_mb_info = NULL;
}
}
......
......@@ -166,13 +166,22 @@ static int InitThread( vpar_thread_t *p_vpar )
p_vpar->i_stream = vout_CreateStream( p_vpar->p_vout );
if( p_vpar->i_stream < 0 ) /* error */
{
return( 1 );
return( 1 );
}
/* Initialize parsing data */
/* ?? */
#endif
/* Initialize parsing data */
p_vpar->sequence.p_forward = p_vpar->sequence.p_backward = NULL;
p_vpar->sequence.p_frame_lum_lookup
= p_vpar->sequence.p_field_lum_lookup
= p_vpar->sequence.p_frame_chroma_lookup
= p_vpar->sequence.p_field_chroma_lookup
= NULL;
p_vpar->sequence.intra_quant.b_allocated = FALSE;
p_vpar->sequence.nonintra_quant.b_allocated = FALSE;
p_vpar->sequence.chroma_intra_quant.b_allocated = FALSE;
p_vpar->sequence.chroma_nonintra_quant.b_allocated = FALSE;
/* Initialize other properties */
#ifdef STATS
p_vpar->c_loops = 0;
......@@ -255,7 +264,7 @@ static void RunThread( vpar_thread_t *p_vpar )
*/
if( p_vpar->b_error )
{
ErrorThread( p_vpar );
ErrorThread( p_vpar );
}
/* End of thread */
......
......@@ -110,18 +110,272 @@ static __inline__ void NextStartCode( vpar_thread_t * p_vpar )
/*****************************************************************************
* SequenceHeader : Parse the next sequence header
*****************************************************************************/
#define RESERVED -1
static double d_frame_rate_table[16] =
{
0.0,
((23.0*1000.0)/1001.0),
24.0,
25.0,
((30.0*1000.0)/1001.0),
30.0,
50.0,
((60.0*1000.0)/1001.0),
60.0,
RESERVED,
RESERVED,
RESERVED,
RESERVED,
RESERVED,
RESERVED,
RESERVED
};
static void SequenceHeader( vpar_thread_t * p_vpar )
{
int i_frame_rate_code;
int i_height_save, i_width_save;
i_height_save = p_vpar->sequence.i_height;
i_width_save = p_vpar->sequence.i_width;
p_vpar->sequence.i_height = ntohl( GetBits( p_vpar->bit_stream, 12 ) );
p_vpar->sequence.i_width = ntohl( GetBits( p_vpar->bit_stream, 12 ) );
p_vpar->sequence.i_ratio = GetBits( p_vpar->bit_stream, 4 );
i_frame_rate_code = GetBits( p_vpar->bit_stream, 4 );
p_vpar->sequence.d_frame_rate =
d_frame_rate_table( GetBits( p_vpar->bit_stream, 4 ) );
/* We don't need bit_rate_value, marker_bit, vbv_buffer_size,
* constrained_parameters_flag */
DumpBits( p_vpar->bits_stream, 30 );
DumpBits( p_vpar->bit_stream, 30 );
/*
* Quantization matrices
*/
if( GetBits( p_vpar->bit_stream, 1 ) ) /* load_intra_quantizer_matrix */
{
LoadMatrix( p_vpar, &p_vpar->sequence.intra_quant );
}
else
{
/* Use default matrix. */
LinkMatrix( &p_vpar->sequence.intra_quant, pi_default_intra_quant );
}
if( GetBits( p_vpar->bit_stream, 1 ) ) /* load_non_intra_quantizer_matrix */
{
LoadMatrix( p_vpar, &p_vpar->sequence.nonintra_quant );
}
else
{
/* Use default matrix. */
LinkMatrix( &p_vpar->sequence.nonintra_quant, pi_default_nonintra_quant );
}
/* Unless later overwritten by a matrix extension, we have the same
* matrices for luminance and chrominance. */
LinkMatrix( &p_vpar->sequence.chroma_intra_quant,
p_vpar->sequence.intra_quant.pi_matrix );
LinkMatrix( &p_vpar->sequence.chroma_nonintra_quant,
p_vpar->sequence.nonintra_quant.pi_matrix );
/*
* Sequence Extension
*/
if( ShowBits( p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
{
int i_dummy;
/* Parse sequence_extension */
DumpBits32( &p_vpar->bit_stream );
/* extension_start_code_identifier, profile_and_level_indication */
DumpBits( &p_vpar->bit_stream, 12 );
p_vpar->sequence.b_progressive = GetBits( &p_vpar->bit_stream, 1 );
p_vpar->sequence.i_chroma_format = GetBits( &p_vpar->bit_stream, 2 );
p_vpar->sequence.i_width |= GetBits( &p_vpar->bit_stream, 2 ) << 12;
p_vpar->sequence.i_height |= GetBits( &p_vpar->bit_stream, 2 ) << 12;
/* bit_rate_extension, marker_bit, vbv_buffer_size_extension, low_delay */
DumpBits( &p_vpar->bit_stream, 22 );
/* frame_rate_extension_n */
i_dummy = GetBits( &p_vpar->bit_stream, 2 );
/* frame_rate_extension_d */
p_vpar->sequence.d_frame_rate *= (i_dummy + 1)
/ (GetBits( &p_vpar->bit_stream, 5 ) + 1);
/* Extension and User data */
ExtensionAndUserData( p_vpar );
}
else
{
/* It's an MPEG-1 stream. Put adequate parameters. */
p_vpar->sequence.b_progressive = 1;
p_vpar->i_chroma_format = CHROMA_420;
}
p_vpar->sequence.i_mb_width = (p_vpar->sequence.i_width + 15) / 16;
p_vpar->sequence.i_mb_height = (p_vpar->sequence.b_progressive) ?
(p_vpar->sequence.i_height + 15) / 16 :
2 * (p_vpar->sequence.i_height + 31) / 32;
p_vpar->sequence.i_width = (p_vpar->sequence.i_mb_width * 16);
p_vpar->sequence.i_height = (p_vpar->sequence.i_mb_height * 16);
if( p_vpar->sequence.i_width != i_width_save
|| p_vpar->sequence.i_height != i_height_save
|| p_vpar->sequence.p_frame_lum_lookup == NULL )
{
int i_x, i_y;
pel_lookup_table * p_fr, p_fl;
int i_fr, i_fl;
static int pi_chroma_size[4] = {0, 2, 1, 0}
#define Sequence p_vpar->sequence
/* The size of the pictures has changed. Probably a new sequence.
* We must recalculate the lookup matrices. */
/* First unlink the previous lookup matrices so that they can
* be freed in the future. */
if( Sequence.p_frame_lum_lookup != NULL )
{
UNLINK_LOOKUP( Sequence.p_frame_lum_lookup );
UNLINK_LOOKUP( Sequence.p_field_lum_lookup );
UNLINK_LOOKUP( Sequence.p_frame_chroma_lookup );
UNLINK_LOOKUP( Sequence.p_field_chroma_lookup );
}
/* Allocate the new lookup tables. */
Sequence.p_frame_lum_lookup
= (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) *
Sequence.i_width * Sequence.i_height );
Sequence.p_field_lum_lookup
= (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) *
Sequence.i_width * Sequence.i_height );
Sequence.p_frame_chroma_lookup
= (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) *
Sequence.i_width * Sequence.i_height
>> pi_chroma_size[Sequence.i_chroma_format] );
Sequence.p_field_chroma_lookup
= (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) *
Sequence.i_width * Sequence.i_height
>> pi_chroma_size[Sequence.i_chroma_format] );
if( !Sequence.p_frame_lum_lookup ||!Sequence.p_field_lum_lookup
|| !Sequence.p_frame_chroma_lookup
||!Sequence.p_field_chroma_lookup )
{
intf_DbgMsg("vpar error: not enough memory for lookup tables");
p_vpar->b_error = 1;
return;
}
/* Fill in the luminance lookup tables */
p_fr = &Sequence.p_frame_lum_lookup->pi_pel;
p_fl = &Sequence.p_field_lum_lookup->pi_pel;
i_fr = i_fl = 0;
for( i_y = 0; i_y < Sequence.i_height; i_y++ )
{
int i_mb_y, i_b_y, i_pos_y;
i_mb_y = i_y >> 4;
i_b_y = (i_y & 15) >> 3;
i_pos_y = (i_y & 7);
for( i_x = 0; i_x < Sequence.i_width; i_x++ )
{
int i_mb_x, i_b_x, i_pos_x;
i_mb_x = i_x >> 4;
i_b_x = (i_x & 15) >> 3;
i_pos_x = (i_x & 7);
p_fl[i_fr + i_x] = p_fr[i_fr + i_x]
= (i_mb_y*Sequence.i_mb_width + i_mb_y)*256
+ ((i_b_y << 1) + i_b_x)*64
+ i_pos_y*8 + i_pos_x;
}
i_fr += Sequence.i_width;
i_fl += Sequence.i_width << 1;
if( i_fl == Sequence.i_width*Sequence.i_height )
{
i_fl = Sequence.i_width;
}
}
/* Fill in the chrominance lookup tables */
p_fr = &Sequence.p_frame_chroma_lookup->pi_pel;
p_fl = &Sequence.p_field_chroma_lookup->pi_pel;
i_fr = i_fl = 0;
switch( p_vpar->i_chroma_format )
{
case CHROMA_444:
/* That's the same as luminance */
memcopy( &Sequence.p_frame_croma_lookup->pi_pel,
&Sequence.p_frame_lum_lookup->pi_pel,
sizeof(PEL_P)*Sequence.i_height*Sequence.i_width );
memcopy( &Sequence.p_field_croma_lookup->pi_pel,
&Sequence.p_field_lum_lookup->pi_pel,
sizeof(PEL_P)*Sequence.i_height*Sequence.i_width );
case CHROMA_422:
for( i_y = 0; i_y < Sequence.i_height; i_y++ )
{
int i_mb_y, i_b_y, i_pos_y;
i_mb_y = i_y >> 4;
i_b_y = (i_y & 15) >> 3;
i_pos_y = (i_y & 7);
for( i_x = 0; i_x < (Sequence.i_width >> 1); i_x++ )
{
int i_mb_x, i_pos_x;
i_mb_x = i_x >> 3;
i_pos_x = (i_x & 7);
p_fl[i_fr + i_x] = p_fr[i_fr + i_x]
= (i_mb_y*Sequence.i_mb_width + i_mb_y)*128
+ i_b_y*64
+ i_pos_y*8 + i_pos_x;
}
i_fr += Sequence.i_width >> 1;
i_fl += Sequence.i_width;
if( i_fl == (Sequence.i_width*Sequence.i_height >> 1) )
{
i_fl = (Sequence.i_width >> 1);
}
}
case CHROMA_420:
for( i_y = 0; i_y < (Sequence.i_height >> 1); i_y++ )
{
int i_mb_y, i_pos_y;
i_mb_y = i_y >> 3;
i_pos_y = (i_y & 7);
for( i_x = 0; i_x < (Sequence.i_width >> 1); i_x++ )
{
int i_mb_x, i_pos_x;
i_mb_x = i_x >> 3;
i_pos_x = (i_x & 7);
p_fl[i_fr + i_x] = p_fr[i_fr + i_x]
= (i_mb_y*Sequence.i_mb_width + i_mb_y)*64
+ i_pos_y*8 + i_pos_x;
}
i_fr += Sequence.i_width >> 1;
i_fl += Sequence.i_width;
if( i_fl == (Sequence.i_width*Sequence.i_height >> 2) )
{
i_fl = Sequence.i_width >> 1;
}
}
} /* switch */
/* Link the new lookup tables so that they don't get freed all
* the time. */
LINK_LOOKUP( Sequence.p_frame_lum_lookup );
LINK_LOOKUP( Sequence.p_field_lum_lookup );
LINK_LOOKUP( Sequence.p_frame_chroma_lookup );
LINK_LOOKUP( Sequence.p_field_chroma_lookup );
#undef Sequence
}
}
/*****************************************************************************
......@@ -129,12 +383,136 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
*****************************************************************************/
static void GroupHeader( vpar_thread_t * p_vpar )
{
/* Nothing to do, we don't care */
DumpBits( &p_vpar->bit_stream, 27 );
ExtensionAndUserData( p_vpar );
}
/*****************************************************************************
* PictureHeader : Parse the next picture header
*****************************************************************************/
static void PictureHeader( vpar_thread_t * p_vpar )
{
int i_coding_type;
mtime_t i_pts;
undec_picture_t * p_undec_p;
DumpBits( &p_vpar->bit_stream, 10 ); /* temporal_reference */
i_coding_type = GetBits( &p_vpar->bit_stream, 3 );
if( ((i_coding_type == P_CODING_TYPE) &&
(p_vpar->sequence.p_forward == NULL)) ||
((i_coding_type == B_CODING_TYPE) &&
(p_vpar->sequence.p_forward == NULL ||
p_vpar->sequence.p_backward == NULL)) )
{
/* The picture cannot be decoded because we lack one of the
* reference frames */
/* Update the reference pointers */
ReferenceUpdate( p_vpar, i_coding_type, NULL );
/* Warn Synchro we have trashed a picture */
vpar_SynchroTrash( p_vpar, i_coding_type );
return;
}
if( !(i_pts = vpar_SynchroChoose( p_vpar, i_coding_type )) )
{
/* Synchro has decided not to decode the picture */
/* Update the reference pointers */
ReferenceUpdate( p_vpar, i_coding_type, NULL );
return;
}
/* OK, now we are sure we will decode the picture. Get a structure. */
p_undec_p = vpar_NewPicture( &p_vpar->vfifo );
/* Request a buffer from the video_output. */
p_undec_p->p_picture = vout_CreatePicture( p_vpar->p_vout,
SPLITTED_YUV_PICTURE,
p_vpar->sequence.i_width,
p_vpar->sequence.i_height,
p_vpar->sequence.i_chroma_format );
/* Initialize values */
p_undec_p->i_coding_type = i_conding_type;
p_undec_p->b_mpeg2 = p_vpar->sequence.b_mpeg2;
p_undec_p->i_mb_height = p_vpar->sequence.i_mb_height;
p_undec_p->i_mb_width = p_vpar->sequence.i_mb_width;
p_undec_p->i_pts = i_pts;
}
/*****************************************************************************
* ReferenceUpdate : Update the reference pointers when we have a new picture
*****************************************************************************/
static void __inline__ ReferenceUpdate( vpar_thread_t * p_vpar,
int i_coding_type,
picture_t * p_newref )
{
if( i_coding_type != B_CODING_TYPE )
{
/* The P picture would have become the new p_backward reference. */
vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
p_vpar->sequence.p_forward = p_vpar->sequence.p_backward;
p_vpar->sequence.p_backward = p_newref;
}
}
/*****************************************************************************
* ExtensionAndUserData : Parse the extension_and_user_data structure
*****************************************************************************/
static void ExtensionAndUserData( vpar_thread_t * p_vpar )
{
/* Nothing to do, we don't care. */
DumpBits( &p_vpar->bit_stream, 27 );
ExtensionAndUserData( p_vpar );
}
/*****************************************************************************
* LoadMatrix : Load a quantization matrix
*****************************************************************************/
static void LoadMatrix( vpar_thread_t * p_vpar, quant_matrix_t * p_matrix )
{
int i_dummy;
if( !p_matrix->b_allocated )
{
/* Allocate a piece of memory to load the matrix. */
p_matrix->pi_matrix = (int *)malloc( 64*sizeof(int) );
p_matrix->b_allocated = TRUE;
}
for( i_dummy = 0; i_dummy < 64; i_dummy++ )
{
p_matrix->pi_matrix[pi_scan[SCAN_ZIGZAG][i_dummy]]
= GetBits( p_vpar->bit_stream, 8 );
}
#ifdef FOURIER_IDCT
/* Discrete Fourier Transform requires the quantization matrices to
* be normalized before using them. */
vdec_NormQuantMatrix( p_matrix->pi_matrix );
#endif
}
/*****************************************************************************
* LinkMatrix : Link a quantization matrix to another
*****************************************************************************/
static void LinkMatrix( quant_matrix_t * p_matrix, int * pi_array )
{
int i_dummy;
if( p_matrix->b_allocated )
{
/* Deallocate the piece of memory. */
free( p_matrix->pi_matrix );
p_matrix->b_allocated = FALSE;
}
p_matrix->pi_matrix = pi_array;
}
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