Commit 047ca4f8 authored by Christophe Massiot's avatar Christophe Massiot

D�but du d�codeur + d�but du parseur.

�videmment �a compile pas et on n'est pas sortis de l'auberge, m'enfin...
parent eee7f389
/*******************************************************************************
* undec_picture.h: undecoded pictures type
* (c)1999 VideoLAN
*******************************************************************************
* This header is required by all modules which have to handle pictures. It
* includes all common video types and constants.
*******************************************************************************
* Requires:
* "config.h"
* "common.h"
* "video.h"
*******************************************************************************/
/*******************************************************************************
* macroblock_info_t : information on a macroblock
*******************************************************************************/
typedef struct
{
int i_mb_type;
int i_motion_type;
int i_dct_type;
(void *) p_idct_function[12](coeff_t * p_block);
int ppp_motion_vectors[2][2][2];
int pi_field_select[2][2];
} macroblock_info_t;
/* Macroblock types */
#define MB_INTRA 1
#define MB_PATTERN 2
#define MB_MOTION_BACKWARD 4
#define MB_MOTION_FORWARD 8
#define MB_QUANT 16
/* Motion types */
#define MOTION_FIELD 1
#define MOTION_FRAME 2
#define MOTION_16X8 2
#define MOTION_DMV 3
/*******************************************************************************
* undec_link_t : link to an undecoded picture
*******************************************************************************/
typedef struct undec_link_s
{
struct undec_picture_s * p_undec;
picture_t ** pp_frame;
} undec_link_t
/*******************************************************************************
* undec_picture_t: undecoded picture
*******************************************************************************
* Any picture destined to be decoded by a video decoder thread should be
* stored in this structure from it's creation to it's effective display.
*******************************************************************************/
typedef struct undec_picture_s
{
/* Picture data */
picture_t * p_picture;
int i_coding_type;
boolean_t b_mpeg2;
int i_mb_height, i_mb_width;
int i_structure;
macroblock_info_t * p_mb_info;
picture_t * p_backward_ref;
picture_t * p_forward_ref;
undec_link_t pp_referencing_undec[MAX_REFERENCING_UNDEC];
} undec_picture_t;
/* Pictures types */
#define I_CODING_TYPE 1
#define P_CODING_TYPE 2
#define B_CODING_TYPE 3
#define D_CODING_TYPE 4 /* MPEG-1 ONLY */
/* other values are reserved */
/* Structures */
#define TOP_FIRST 1
#define BOTTOM_FIRST 2
#define FRAME_STRUCTURE 3
/*******************************************************************************
* pel_lookup_table_t : lookup table for pixels
*******************************************************************************/
typedef struct pel_lookup_table_s {
#ifdef BIG_PICTURES
u32 * pi_pel;
#else
u16 * pi_pel;
#endif
/* 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;
/*****************************************************************************
* vdec_motion.h : types for the motion compensation algorithm
* (c)1999 VideoLAN
*****************************************************************************
*****************************************************************************
* Requires:
* "config.h"
* "common.h"
* "vlc_thread.h"
* "video_parser.h"
* "undec_picture.h"
*****************************************************************************/
/*****************************************************************************
* Function pointers
*****************************************************************************/
typedef void (*f_motion_mb_t)( coeff_t *, pel_lookup_table_t *,
int, coeff_t *, int, int, int, int, int );
typedef void (*f_motion_t)( vdec_thread_t *, undec_picture_t *, int,
f_motion_mb_t );
/*****************************************************************************
* Prototypes
*****************************************************************************/
void vdec_MotionMacroblock420( coeff_t * p_src, pel_lookup_table_t * p_lookup,
int i_width_line,
coeff_t * p_dest, int i_dest_x, i_dest_y,
int i_stride_line,
i_mv1_x, i_mv1_y, i_mv2_x, i_mv2_y );
/*****************************************************************************
* video_fifo.h : FIFO for the pool of video_decoders
* (c)1999 VideoLAN
*****************************************************************************
*****************************************************************************
* Requires:
* "config.h"
* "common.h"
* "vlc_thread.h"
* "video_parser.h"
* "undec_picture.h"
*****************************************************************************/
/*****************************************************************************
* Macros
*****************************************************************************/
/* ?? move to inline functions */
#define VIDEO_FIFO_ISEMPTY( fifo ) ( (fifo).i_start == (fifo).i_end )
#define VIDEO_FIFO_ISFULL( fifo ) ( ( ( (fifo).i_end + 1 - (fifo).i_start ) \
& VFIFO_SIZE ) == 0 )
#define VIDEO_FIFO_START( fifo ) ( (fifo).buffer[ (fifo).i_start ] )
#define VIDEO_FIFO_INCSTART( fifo ) ( (fifo).i_start = ((fifo).i_start + 1) \
& VFIFO_SIZE )
#define VIDEO_FIFO_END( fifo ) ( (fifo).buffer[ (fifo).i_end ] )
#define VIDEO_FIFO_INCEND( fifo ) ( (fifo).i_end = ((fifo).i_end + 1) \
& VFIFO_SIZE )
/*****************************************************************************
* video_fifo_t
*****************************************************************************
* This rotative FIFO contains undecoded pictures that are to be decoded
*****************************************************************************/
typedef struct video_fifo_s
{
vlc_mutex_t lock; /* fifo data lock */
vlc_cond_t wait; /* fifo data conditional variable */
/* buffer is an array of undec_picture_t pointers */
undec_picture_t * buffer[VFIFO_SIZE + 1];
int i_start;
int i_end;
struct video_parser_s * p_vpar;
} video_fifo_t;
/*****************************************************************************
* video_buffer_t
*****************************************************************************
* This structure enables the parser to maintain a list of free
* undec_picture_t structures
*****************************************************************************/
typedef struct video_buffer_s
{
vlc_mutex_t lock; /* buffer data lock */
undec_picture_t p_undec_p[VFIFO_SIZE + 1];
undec_picture_t * pp_undec_free[VFIFO_SIZE+1]; /* this is a LIFO */
int i_index;
} video_buffer_t;
/*****************************************************************************
* Prototypes
*****************************************************************************/
undec_picture_t * vpar_GetPicture( video_fifo_t * p_fifo );
undec_picture_t * vpar_NewPicture( video_fifo_t * p_fifo );
void vpar_DecodePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p );
void vpar_ReleasePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p );
void vpar_DestroyPicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p );
......@@ -11,9 +11,22 @@
* "input.h"
* "video.h"
* "video_output.h"
* "parser_fifo.h"
* "decoder_fifo.h"
* "video_fifo.h"
*******************************************************************************/
/*******************************************************************************
* sequence_t : sequence descriptor
*******************************************************************************
* ??
*******************************************************************************/
typedef struct sequence_s
{
u32 i_height, i_width;
unsigned int i_aspect_ratio;
double frame_rate;
} sequence_t;
/*******************************************************************************
* vpar_thread_t: video parser thread descriptor
*******************************************************************************
......@@ -35,7 +48,7 @@ typedef struct vpar_thread_s
/* Input properties */
parser_fifo_t fifo; /* PES input fifo */
decoder_fifo_t fifo; /* PES input fifo */
/* The bit stream structure handles the PES stream at the bit level */
bit_stream_t bit_stream;
......@@ -44,11 +57,19 @@ typedef struct vpar_thread_s
vout_thread_t * p_vout; /* video output thread */
int i_stream; /* video stream id */
/* Decoder properties */
struct vdec_thread_s * p_vdec[MAX_VDEC];
video_fifo_t vfifo;
video_buffer_t vbuffer;
/* Parser properties */
sequence_t sequence;
#ifdef STATS
/* Statistics */
count_t c_loops; /* number of loops */
count_t c_idle_loops; /* number of idle loops */
count_t c_sequences; /* number of sequences */
count_t c_pictures; /* number of pictures read */
count_t c_i_pictures; /* number of I pictures read */
count_t c_p_pictures; /* number of P pictures read */
......@@ -60,6 +81,19 @@ typedef struct vpar_thread_s
#endif
} vpar_thread_t;
/*******************************************************************************
* Standard start codes
*******************************************************************************/
#define PICTURE_START_CODE 0x100
#define SLICE_START_CODE_MIN 0x101
#define SLICE_START_CODE_MAX 0x1AF
#define USER_DATA_START_CODE 0x1B2
#define SEQUENCE_HEADER_CODE 0x1B3
#define SEQUENCE_ERROR_CODE 0x1B4
#define EXTENSION_START_CODE 0x1B5
#define SEQUENCE_END_CODE 0x1B7
#define GROUP_START_CODE 0x1B8
/*******************************************************************************
* Prototypes
*******************************************************************************/
......@@ -67,7 +101,7 @@ typedef struct vpar_thread_s
/* Thread management functions */
vpar_thread_t * vpar_CreateThread ( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
vout_thread_t *p_vout, int *pi_status */ );
void vpar_DestroyThread ( vpar_thread_t *p_vpar /*, int *pi_status */ );
void vpar_DestroyThread ( vpar_thread_t *p_vpar /*, int *pi_status */ );
/* Time management functions */
/* ?? */
......
/*****************************************************************************
* vdec_motion.c : motion compensation routines
* (c)1999 VideoLAN
*****************************************************************************/
/* ?? passer en terminate/destroy avec les signaux supplmentaires */
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/uio.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "intf_msg.h"
#include "debug.h" /* ?? temporaire, requis par netlist.h */
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "video.h"
#include "video_output.h"
#include "video_parser.h"
#include "undec_picture.h"
#include "video_fifo.h"
#include "video_decoder.h"
/*
* Local prototypes
*/
/*****************************************************************************
* vdec_MotionCompensation : motion compensation
*****************************************************************************/
void vdec_MotionFrame( vdec_thread_t * p_vdec,
undec_picture_t * p_undec_p, int i_mb,
f_motion_mb_t pf_mb_motion )
{
static int p_chroma_nb_blocks[4] = {1, 2, 4};
static int p_chroma_nb_elems[4] = {0, 64, 128, 256};
int i_mb_x, i_mb_y; /* Position of our macroblock in the final picture */
elem_t * p_y, p_u, p_v; /* Pointers to our picture's data */
#define P_mb_info p_undec_p->p_mb_info[i_mb]
i_mb_x = (i_mb << 5) % p_undec_p->p_picture->i_width;
i_mb_y = (i_mb << 5) / p_undec_p->p_picture->i_width;
p_y = &p_undec_p->p_picture->p_y[256*i_mb];
p_u = &p_undec_p->p_picture->p_u[p_chroma_nb_elems[p_undec_p->p_picture->i_chroma_type]*i_mb];
p_v = &p_undec_p->p_picture->p_v[p_chroma_nb_elems[p_undec_p->p_picture->i_chroma_type]*i_mb];
if( (p_undec_p->i_coding_type == P_CODING_TYPE) ||
(P_mb_info->i_mb_type & MB_MOTION_FORWARD) )
{
if( (P_mb_info->i_motion_type == MOTION_FRAME) ||
!(P_mb_info->i_mb_type & MB_INTRA) )
{
MotionBlock( p_undec_p->p_forward->p_u,
p_undec_p->p_forward->p_lookup_lum,
p_undec_p->p_picture->i_width,
p_u, i_mb_x, i_mb_y,
p_undec_p->p_picture->i_width,
p_undec_p->ppp_motion_vectors[0][0][0],
p_undec_p->ppp_motion_vectors[0][0][1] );
}
}
}
/*****************************************************************************
* MotionMacroblock : motion compensation for a macroblock
*****************************************************************************/
void vdec_MotionMacroblock420( coeff_t * p_src, pel_lookup_table_t * p_lookup,
int i_width_line,
coeff_t * p_dest, int i_dest_x, i_dest_y,
int i_stride_line,
i_mv1_x, i_mv1_y, i_mv2_x, i_mv2_y )
{
/* Luminance */
MotionBlock( p_undec_p->p_forward->p_u, p_undec_p->p_forward->p_lookup_lum,
p_undec_p->p_picture->i_width, p_u, i_mb_x, i_mb_y,
p_undec_p->p_picture->i_width,
p_undec_p->ppp_motion_vectors[0][0][0],
p_undec_p->ppp_motion_vectors[0][0][1] );
}
/*****************************************************************************
* MotionBlock : motion compensation for one 8x8 block
*****************************************************************************/
void __inline__ MotionBlock( coeff_t * p_src, pel_lookup_table_t * p_lookup,
int i_width_line,
coeff_t * p_dest, int i_dest_x, i_dest_y,
int i_stride_line,
i_mv1_x, i_mv1_y, i_mv2_x, i_mv2_y )
{
static (void *) ComponentMode( coeff_t * p_src,
pel_lookup_table_t * p_lookup,
coeff_t * p_dest, int i_dest_x, i_dest_y,
int i_stride_line, i_mv_x, i_mv_y )[4]
= { ComponentNN, ComponentNH, ComponentHN,
ComponentHH };
int i_mode;
i_mode = (i_mv_x & 1) | ((i_mv_y & 1) << 1);
ComponentMode[i_mode]( p_src, p_lookup, i_width_line,
p_dest, i_dest_x, i_dest_y,
i_stride_line, i_mv_x >> 1, i_mv_y >> 1 );
}
/*****************************************************************************
* ComponentNN : motion compensation without half pel
*****************************************************************************/
void ComponentNN( coeff_t * p_src, pel_lookup_table_t * p_lookup,
int i_width_line,
coeff_t * p_dest, int i_dest_x, i_dest_y,
int i_stride_line, i_mv1_x, i_mv1_y, i_mv2_x, i_mv2_y )
{
int i_vpos;
register int i_hpos, i_src_loc;
i_src_loc = (i_dest_y + i_mv_y)*i_width_line + i_dest_x + i_mv_x;
for( i_vpos = 0; i_vpos < 8; i_vpos++ )
{
for( i_hpos = 0; i_hpos < 8; i_hpos++ )
{
p_dest[i_hpos] += p_src[p_lookup->pi_pel[i_src_loc + i_hpos]];
}
p_dest += 8;
i_src_loc += i_stride_line;
}
}
......@@ -30,27 +30,31 @@
#include "decoder_fifo.h"
#include "video.h"
#include "video_output.h"
#include "video_parser.h"
#include "undec_picture.h"
#include "video_fifo.h"
#include "video_decoder.h"
/*
* Local prototypes
*/
//static int CheckConfiguration ( video_cfg_t *p_cfg );
static int InitThread ( vdec_thread_t *p_vdec );
static void RunThread ( vdec_thread_t *p_vdec );
static void ErrorThread ( vdec_thread_t *p_vdec );
static void EndThread ( vdec_thread_t *p_vdec );
static void DecodePicture ( vdec_thread_t *p_vdec,
undec_picture_t * p_undec_p );
/*******************************************************************************
* vdec_CreateThread: create a generic decoder thread
* vdec_CreateThread: create a video decoder thread
*******************************************************************************
* This function creates a new video decoder thread, and returns a pointer
* to its description. On error, it returns NULL.
* Following configuration properties are used:
* ??
*******************************************************************************/
vdec_thread_t * vdec_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
vout_thread_t *p_vout, int *pi_status */ )
vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
{
vdec_thread_t * p_vdec;
......@@ -59,7 +63,7 @@ vdec_thread_t * vdec_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_i
/* Allocate the memory needed to store the thread's structure */
if ( (p_vdec = (vdec_thread_t *)malloc( sizeof(vdec_thread_t) )) == NULL )
{
intf_ErrMsg("adec error: not enough memory for vdec_CreateThread() to create the new thread\n");
intf_ErrMsg("vdec error: not enough memory for vdec_CreateThread() to create the new thread\n");
return( NULL );
}
......@@ -70,21 +74,13 @@ vdec_thread_t * vdec_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_i
p_vdec->b_error = 0;
/*
* Initialize the input properties
* Initialize the parser properties
*/
/* Initialize the decoder fifo's data lock and conditional variable and set * its buffer as empty */
vlc_mutex_init( &p_vdec->fifo.data_lock );
vlc_cond_init( &p_vdec->fifo.data_wait );
p_vdec->fifo.i_start = 0;
p_vdec->fifo.i_end = 0;
/* Initialize the bit stream structure */
p_vdec->bit_stream.p_input = p_input;
p_vdec->bit_stream.p_decoder_fifo = &p_vdec->fifo;
p_vdec->bit_stream.fifo.buffer = 0;
p_vdec->bit_stream.fifo.i_available = 0;
p_vdec->p_vpar = p_vpar;
/* Spawn the video decoder thread */
if ( vlc_thread_create(&p_vdec->thread_id, "video decoder", (vlc_thread_func)RunThread, (void *)p_vdec) )
if ( vlc_thread_create(&p_vdec->thread_id, "video decoder",
(vlc_thread_func)RunThread, (void *)p_vdec) )
{
intf_ErrMsg("vdec error: can't spawn video decoder thread\n");
free( p_vdec );
......@@ -96,9 +92,9 @@ vdec_thread_t * vdec_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_i
}
/*******************************************************************************
* vdec_DestroyThread: destroy a generic decoder thread
* vdec_DestroyThread: destroy a video decoder thread
*******************************************************************************
* Destroy a terminated thread. This function will return 0 if the thread could
* Destroy and terminate thread. This function will return 0 if the thread could
* be destroyed, and non 0 else. The last case probably means that the thread
* was still active, and another try may succeed.
*******************************************************************************/
......@@ -108,10 +104,6 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
/* Ask thread to kill itself */
p_vdec->b_die = 1;
/* Make sure the decoder thread leaves the GetByte() function */
vlc_mutex_lock( &(p_vdec->fifo.data_lock) );
vlc_cond_signal( &(p_vdec->fifo.data_wait) );
vlc_mutex_unlock( &(p_vdec->fifo.data_lock) );
/* Waiting for the decoder thread to exit */
/* Remove this as soon as the "status" flag is implemented */
......@@ -121,22 +113,7 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
/* following functions are local */
/*******************************************************************************
* CheckConfiguration: check vdec_CreateThread() configuration
*******************************************************************************
* Set default parameters where required. In DEBUG mode, check if configuration
* is valid.
*******************************************************************************/
#if 0
static int CheckConfiguration( video_cfg_t *p_cfg )
{
/* ?? */
return( 0 );
}
#endif
/*******************************************************************************
* InitThread: initialize vdec output thread
* InitThread: initialize video decoder thread
*******************************************************************************
* This function is called from RunThread and performs the second step of the
* initialization. It returns 0 on success. Note that the thread's flag are not
......@@ -144,41 +121,12 @@ static int CheckConfiguration( video_cfg_t *p_cfg )
*******************************************************************************/
static int InitThread( vdec_thread_t *p_vdec )
{
intf_DbgMsg("vdec debug: initializing video decoder thread %p\n", p_vdec);
/* Our first job is to initialize the bit stream structure with the
* beginning of the input stream */
vlc_mutex_lock( &p_vdec->fifo.data_lock );
while ( DECODER_FIFO_ISEMPTY(p_vdec->fifo) )
{
vlc_cond_wait( &p_vdec->fifo.data_wait, &p_vdec->fifo.data_lock );
}
p_vdec->bit_stream.p_ts = DECODER_FIFO_START( p_vdec->fifo )->p_first_ts;
p_vdec->bit_stream.i_byte = p_vdec->bit_stream.p_ts->i_payload_start;
vlc_mutex_unlock( &p_vdec->fifo.data_lock );
#if 0
/* ?? */
/* Create video stream */
p_vdec->i_stream = vout_CreateStream( p_vdec->p_vout );
if( p_vdec->i_stream < 0 ) /* error */
{
return( 1 );
}
/* Initialize decoding data */
/* ?? */
#endif
/* Initialize other properties */
#ifdef STATS
p_vdec->c_loops = 0;
p_vdec->c_idle_loops = 0;
p_vdec->c_pictures = 0;
p_vdec->c_i_pictures = 0;
p_vdec->c_p_pictures = 0;
p_vdec->c_b_pictures = 0;
p_vdec->c_decoded_pictures = 0;
p_vdec->c_decoded_i_pictures = 0;
p_vdec->c_decoded_p_pictures = 0;
......@@ -191,15 +139,15 @@ static int InitThread( vdec_thread_t *p_vdec )
}
/*******************************************************************************
* RunThread: generic decoder thread
* RunThread: video decoder thread
*******************************************************************************
* Generic decoder thread. This function does only returns when the thread is
* Video decoder thread. This function does only return when the thread is
* terminated.
*******************************************************************************/
static void RunThread( vdec_thread_t *p_vdec )
{
intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)\n", p_vdec, getpid());
intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)\n",
p_vdec, getpid());
/*
* Initialize thread and free configuration
......@@ -211,16 +159,18 @@ static void RunThread( vdec_thread_t *p_vdec )
}
p_vdec->b_run = 1;
/* REMOVE ME !!!!! */
p_vdec->b_error = 1;
/*
* Main loop - it is not executed if an error occured during
* initialization
*/
while( (!p_vdec->b_die) && (!p_vdec->b_error) )
{
/* ?? */
undec_picture_t * p_undec_p;
if( (p_undec_p = GetPicture( p_vdec->p_vpar->p_fifo )) != NULL )
{
DecodePicture( p_vdec, p_undec_p );
}
}