Commit 796346ac authored by Christophe Massiot's avatar Christophe Massiot

* Optimisation de vdec_motion.c et video_decoder.c ;

* Passage des fonctions de la video_fifo en inline ;
* Correction d'un bug provoquant un overflow des messages dans
vpar_headers.c.
parent e6521494
......@@ -62,7 +62,7 @@
#define DEBUG_INTF
#define DEBUG_INPUT
#define DEBUG_AUDIO
#define DEBUG_VIDEO
//#define DEBUG_VIDEO
/* Debugging log file - if defined, a file can be used to store all messages. If
* DEBUG_LOG_ONLY is defined, debug messages will only be printed to the log and
......@@ -285,6 +285,8 @@
#define VPAR_IDLE_SLEEP 100000
#define VPAR_OUTMEM_SLEEP 50000
/* Number of macroblock buffers available. It should be always greater than
* twice the number of macroblocks in a picture. VFIFO_SIZE + 1 should also
* be a power of two. */
......
......@@ -19,7 +19,6 @@ struct vpar_thread_s;
struct motion_arg_s;
typedef void (*f_motion_t)( struct macroblock_s* );
typedef void (*f_chroma_motion_t)( struct macroblock_s*, struct motion_arg_s* );
/*****************************************************************************
* Prototypes
......@@ -29,14 +28,21 @@ typedef void (*f_chroma_motion_t)( struct macroblock_s*, struct motion_arg_s* );
void vdec_MotionDummy( struct macroblock_s * p_mb );
/* Motion compensation */
void vdec_MotionFieldField( struct macroblock_s * p_mb );
void vdec_MotionField16x8( struct macroblock_s * p_mb );
void vdec_MotionFieldField420( struct macroblock_s * p_mb );
void vdec_MotionField16x8420( struct macroblock_s * p_mb );
void vdec_MotionFieldDMV( struct macroblock_s * p_mb );
void vdec_MotionFrameFrame( struct macroblock_s * p_mb );
void vdec_MotionFrameField( struct macroblock_s * p_mb );
void vdec_MotionFrameFrame420( struct macroblock_s * p_mb );
void vdec_MotionFrameField420( struct macroblock_s * p_mb );
void vdec_MotionFrameDMV( struct macroblock_s * p_mb );
/* Motion compensation functions for the 3 chroma formats */
void vdec_Motion420( struct macroblock_s * p_mb, struct motion_arg_s * p_motion );
void vdec_Motion422( struct macroblock_s * p_mb, struct motion_arg_s * p_motion );
void vdec_Motion444( struct macroblock_s * p_mb, struct motion_arg_s * p_motion );
void vdec_MotionFieldField422( struct macroblock_s * p_mb );
void vdec_MotionField16x8422( struct macroblock_s * p_mb );
void vdec_MotionFieldDMV( struct macroblock_s * p_mb );
void vdec_MotionFrameFrame422( struct macroblock_s * p_mb );
void vdec_MotionFrameField422( struct macroblock_s * p_mb );
void vdec_MotionFrameDMV( struct macroblock_s * p_mb );
void vdec_MotionFieldField444( struct macroblock_s * p_mb );
void vdec_MotionField16x8444( struct macroblock_s * p_mb );
void vdec_MotionFieldDMV( struct macroblock_s * p_mb );
void vdec_MotionFrameFrame444( struct macroblock_s * p_mb );
void vdec_MotionFrameField444( struct macroblock_s * p_mb );
void vdec_MotionFrameDMV( struct macroblock_s * p_mb );
\ No newline at end of file
......@@ -74,13 +74,6 @@ typedef struct vdec_thread_s
#endif
} vdec_thread_t;
/*****************************************************************************
* Function pointers
*****************************************************************************/
#ifndef OLD_DECODER
typedef void (*f_addb_t)( vdec_thread_t *, dctelem_t*, yuv_data_t*, int );
#endif
/*****************************************************************************
* Prototypes
*****************************************************************************/
......@@ -96,7 +89,4 @@ void vdec_DestroyThread ( vdec_thread_t *p_vdec /*, int *pi_sta
#else
vdec_thread_t * vdec_CreateThread ( struct vpar_thread_s *p_vpar /*, int *pi_status */ );
void vdec_DestroyThread ( vdec_thread_t *p_vdec /*, int *pi_status */ );
void vdec_AddBlock( vdec_thread_t *, dctelem_t*, yuv_data_t*, int );
void vdec_CopyBlock( vdec_thread_t *, dctelem_t*, yuv_data_t*, int );
void vdec_DummyBlock( vdec_thread_t *, dctelem_t*, yuv_data_t*, int );
#endif
......@@ -27,46 +27,160 @@
& VFIFO_SIZE )
/*****************************************************************************
* video_fifo_t
*****************************************************************************
* This rotative FIFO contains undecoded macroblocks that are to be decoded
* vpar_GetMacroblock : return a macroblock to be decoded
*****************************************************************************/
struct vpar_thread_s;
static __inline__ macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo )
{
macroblock_t * p_mb;
vlc_mutex_lock( &p_fifo->lock );
while( VIDEO_FIFO_ISEMPTY( *p_fifo ) )
{
vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
if( p_fifo->p_vpar->b_die )
{
vlc_mutex_unlock( &p_fifo->lock );
return( NULL );
}
}
p_mb = VIDEO_FIFO_START( *p_fifo );
VIDEO_FIFO_INCSTART( *p_fifo );
typedef struct video_fifo_s
vlc_mutex_unlock( &p_fifo->lock );
return( p_mb );
}
/*****************************************************************************
* vpar_NewMacroblock : return a buffer for the parser
*****************************************************************************/
static __inline__ macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo )
{
vlc_mutex_t lock; /* fifo data lock */
vlc_cond_t wait; /* fifo data conditional variable */
macroblock_t * p_mb;
/* buffer is an array of undec_picture_t pointers */
macroblock_t * buffer[VFIFO_SIZE + 1];
int i_start;
int i_end;
#define P_buffer p_fifo->p_vpar->vbuffer
vlc_mutex_lock( &P_buffer.lock );
while( P_buffer.i_index == -1 )
{
/* No more structures available. This should not happen ! */
intf_DbgMsg("vpar debug: macroblock list is empty, delaying\n");
vlc_mutex_unlock( &P_buffer.lock );
msleep(VPAR_OUTMEM_SLEEP);
vlc_mutex_lock( &P_buffer.lock );
}
struct vpar_thread_s * p_vpar;
} video_fifo_t;
p_mb = P_buffer.pp_mb_free[ P_buffer.i_index-- ];
vlc_mutex_unlock( &P_buffer.lock );
#undef P_buffer
return( p_mb );
}
/*****************************************************************************
* video_buffer_t
*****************************************************************************
* This structure enables the parser to maintain a list of free
* macroblock_t structures
* vpar_DecodeMacroblock : put a macroblock in the video fifo
*****************************************************************************/
static __inline__ void vpar_DecodeMacroblock( video_fifo_t * p_fifo,
macroblock_t * p_mb )
{
/* Place picture in the video FIFO */
vlc_mutex_lock( &p_fifo->lock );
/* By construction, the video FIFO cannot be full */
VIDEO_FIFO_END( *p_fifo ) = p_mb;
VIDEO_FIFO_INCEND( *p_fifo );
vlc_mutex_unlock( &p_fifo->lock );
}
/*****************************************************************************
* vpar_ReleaseMacroblock : release a macroblock and put the picture in the
* video output heap, if it is finished
*****************************************************************************/
static __inline__ void vpar_ReleaseMacroblock( video_fifo_t * p_fifo,
macroblock_t * p_mb )
{
boolean_t b_finished;
/* Unlink picture buffer */
vlc_mutex_lock( &p_mb->p_picture->lock_deccount );
p_mb->p_picture->i_deccount--;
b_finished = (p_mb->p_picture->i_deccount == 1);
vlc_mutex_unlock( &p_mb->p_picture->lock_deccount );
//fprintf(stderr, "%d ", p_mb->p_picture->i_deccount);
/* Test if it was the last block of the picture */
if( b_finished )
{
//fprintf(stderr, "Image decodee\n");
/* Mark the picture to be displayed */
vout_DisplayPicture( p_fifo->p_vpar->p_vout, p_mb->p_picture );
/* Warn Synchro for its records. */
vpar_SynchroEnd( p_fifo->p_vpar );
/* Unlink referenced pictures */
if( p_mb->p_forward != NULL )
{
vout_UnlinkPicture( p_fifo->p_vpar->p_vout, p_mb->p_forward );
}
if( p_mb->p_backward != NULL )
{
vout_UnlinkPicture( p_fifo->p_vpar->p_vout, p_mb->p_backward );
}
}
/* Release the macroblock_t structure */
#define P_buffer p_fifo->p_vpar->vbuffer
vlc_mutex_lock( &P_buffer.lock );
P_buffer.pp_mb_free[ ++P_buffer.i_index ] = p_mb;
vlc_mutex_unlock( &P_buffer.lock );
#undef P_buffer
}
/*****************************************************************************
* vpar_DestroyMacroblock : destroy a macroblock in case of error
*****************************************************************************/
typedef struct video_buffer_s
static __inline__ void vpar_DestroyMacroblock( video_fifo_t * p_fifo,
macroblock_t * p_mb )
{
vlc_mutex_t lock; /* buffer data lock */
boolean_t b_finished;
/* Unlink picture buffer */
vlc_mutex_lock( &p_mb->p_picture->lock_deccount );
p_mb->p_picture->i_deccount--;
b_finished = (p_mb->p_picture->i_deccount == 0);
vlc_mutex_unlock( &p_mb->p_picture->lock_deccount );
/* Test if it was the last block of the picture */
if( b_finished )
{
fprintf(stderr, "Image trashee\n");
/* Mark the picture to be displayed */
vout_DestroyPicture( p_fifo->p_vpar->p_vout, p_mb->p_picture );
/* Warn Synchro for its records. */
vpar_SynchroEnd( p_fifo->p_vpar );
/* Unlink referenced pictures */
if( p_mb->p_forward != NULL )
{
vout_UnlinkPicture( p_fifo->p_vpar->p_vout, p_mb->p_forward );
}
if( p_mb->p_backward != NULL )
{
vout_UnlinkPicture( p_fifo->p_vpar->p_vout, p_mb->p_backward );
}
}
macroblock_t p_macroblocks[VFIFO_SIZE + 1];
macroblock_t * pp_mb_free[VFIFO_SIZE+1]; /* this is a LIFO */
int i_index;
} video_buffer_t;
/* Release the macroblock_t structure */
#define P_buffer p_fifo->p_vpar->vbuffer
vlc_mutex_lock( &P_buffer.lock );
P_buffer.pp_mb_free[ ++P_buffer.i_index ] = p_mb;
vlc_mutex_unlock( &P_buffer.lock );
#undef P_buffer
}
/*****************************************************************************
* Prototypes
*****************************************************************************/
void vpar_InitFIFO( struct vpar_thread_s * p_vpar );
macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo );
macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo );
void vpar_DecodeMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb );
void vpar_ReleaseMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb );
void vpar_DestroyMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb );
......@@ -16,6 +16,41 @@
* "vpar_headers.h"
*****************************************************************************/
/*****************************************************************************
* video_fifo_t
*****************************************************************************
* This rotative FIFO contains undecoded macroblocks that are to be decoded
*****************************************************************************/
struct vpar_thread_s;
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 */
macroblock_t * buffer[VFIFO_SIZE + 1];
int i_start;
int i_end;
struct vpar_thread_s * p_vpar;
} video_fifo_t;
/*****************************************************************************
* video_buffer_t
*****************************************************************************
* This structure enables the parser to maintain a list of free
* macroblock_t structures
*****************************************************************************/
typedef struct video_buffer_s
{
vlc_mutex_t lock; /* buffer data lock */
macroblock_t p_macroblocks[VFIFO_SIZE + 1];
macroblock_t * pp_mb_free[VFIFO_SIZE+1]; /* this is a LIFO */
int i_index;
} video_buffer_t;
/*****************************************************************************
* vpar_thread_t: video parser thread descriptor
*****************************************************************************
......
......@@ -80,9 +80,9 @@
#include "vdec_motion.h"
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "video_fifo.h"
#include "vpar_synchro.h"
#include "video_parser.h"
#include "video_fifo.h"
#endif
/* Interface */
......
......@@ -21,6 +21,7 @@
typedef struct macroblock_s
{
int i_mb_type; /* macroblock type */
int i_coded_block_pattern;
int i_structure;
int i_current_structure;
boolean_t b_P_coding_type; /* Is it P_CODING_TYPE ? */
......@@ -39,7 +40,6 @@ typedef struct macroblock_s
/* Motion compensation information */
f_motion_t pf_motion; /* function to use for motion comp */
f_chroma_motion_t pf_chroma_motion;
picture_t * p_backward;
picture_t * p_forward;
int ppi_field_select[2][2];
......@@ -51,7 +51,6 @@ typedef struct macroblock_s
boolean_t b_motion_field;
/* AddBlock information */
f_addb_t pf_addb[12]; /* pointer to the Add function */
yuv_data_t * p_data[12]; /* pointer to the position
* in the final picture */
int i_addb_l_stride, i_addb_c_stride;
......
......@@ -34,9 +34,9 @@
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "video_fifo.h"
#include "vpar_synchro.h"
#include "video_parser.h"
#include "video_fifo.h"
/*
* Local prototypes
......
This diff is collapsed.
......@@ -37,9 +37,9 @@
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "video_fifo.h"
#include "vpar_synchro.h"
#include "video_parser.h"
#include "video_fifo.h"
/*
* Local prototypes
......@@ -165,54 +165,6 @@ static int InitThread( vdec_thread_t *p_vdec )
return( 0 );
}
/*******************************************************************************
* RunThread: video decoder thread
*******************************************************************************
* 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());
/*
* Initialize thread and free configuration
*/
p_vdec->b_error = InitThread( p_vdec );
if( p_vdec->b_error )
{
return;
}
p_vdec->b_run = 1;
/*
* Main loop - it is not executed if an error occured during
* initialization
*/
while( (!p_vdec->b_die) && (!p_vdec->b_error) )
{
macroblock_t * p_mb;
if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL )
{
DecodeMacroblock( p_vdec, p_mb );
}
}
/*
* Error loop
*/
if( p_vdec->b_error )
{
ErrorThread( p_vdec );
}
/* End of thread */
EndThread( p_vdec );
p_vdec->b_run = 0;
}
/*******************************************************************************
* ErrorThread: RunThread() error loop
*******************************************************************************
......@@ -244,60 +196,10 @@ static void EndThread( vdec_thread_t *p_vdec )
}
/*******************************************************************************
* DecodeMacroblock : decode a macroblock of a picture
* AddBlock : add a block
*******************************************************************************/
static void DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb )
{
int i_b;
/*
* Motion Compensation (ISO/IEC 13818-2 section 7.6)
*/
(*p_mb->pf_motion)( p_mb );
/* luminance */
for( i_b = 0; i_b < 4; i_b++ )
{
/*
* Inverse DCT (ISO/IEC 13818-2 section Annex A)
*/
(p_mb->pf_idct[i_b])( p_vdec, p_mb->ppi_blocks[i_b],
p_mb->pi_sparse_pos[i_b] );
/*
* Adding prediction and coefficient data (ISO/IEC 13818-2 section 7.6.8)
*/
(p_mb->pf_addb[i_b])( p_vdec, p_mb->ppi_blocks[i_b],
p_mb->p_data[i_b], p_mb->i_addb_l_stride );
}
/* chrominance */
for( i_b = 4; i_b < 4 + p_mb->i_chroma_nb_blocks; i_b++ )
{
/*
* Inverse DCT (ISO/IEC 13818-2 section Annex A)
*/
(p_mb->pf_idct[i_b])( p_vdec, p_mb->ppi_blocks[i_b],
p_mb->pi_sparse_pos[i_b] );
/*
* Adding prediction and coefficient data (ISO/IEC 13818-2 section 7.6.8)
*/
(p_mb->pf_addb[i_b])( p_vdec, p_mb->ppi_blocks[i_b],
p_mb->p_data[i_b], p_mb->i_addb_c_stride );
}
/*
* Decoding is finished, release the macroblock and free
* unneeded memory.
*/
vpar_ReleaseMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
}
/*******************************************************************************
* vdec_AddBlock : add a block
*******************************************************************************/
void vdec_AddBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, yuv_data_t * p_data, int i_incr )
static __inline__ void AddBlock( vdec_thread_t * p_vdec, dctelem_t * p_block,
yuv_data_t * p_data, int i_incr )
{
int i_x, i_y;
......@@ -313,19 +215,17 @@ void vdec_AddBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, yuv_data_t * p_
}
/*******************************************************************************
* vdec_CopyBlock : copy a block
* CopyBlock : copy a block
*******************************************************************************/
void vdec_CopyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, yuv_data_t * p_data, int i_incr )
static __inline__ void CopyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block,
yuv_data_t * p_data, int i_incr )
{
int i_y;
int i_x, i_y;
for( i_y = 0; i_y < 8; i_y++ )
{
int i_x;
for( i_x = 0; i_x < 8; i_x++ )
{
/* ??? Why does the reference decoder add 128 ??? */
*p_data++ = p_vdec->pi_crop[*p_block++];
}
p_data += i_incr;
......@@ -333,8 +233,124 @@ void vdec_CopyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, yuv_data_t * p
}
/*******************************************************************************
* vdec_DummyBlock : dummy function that does nothing
* DecodeMacroblock : decode a macroblock of a picture
*******************************************************************************/
#define DECODEBLOCKS( OPBLOCK ) \
{ \
int i_b, i_mask; \
\
i_mask = 1 << (3 + p_mb->i_chroma_nb_blocks); \
\
/* luminance */ \
for( i_b = 0; i_b < 4; i_b++, i_mask >>= 1 ) \
{ \
if( p_mb->i_coded_block_pattern & i_mask ) \
{ \
/* \
* Inverse DCT (ISO/IEC 13818-2 section Annex A) \
*/ \
(p_mb->pf_idct[i_b])( p_vdec, p_mb->ppi_blocks[i_b], \
p_mb->pi_sparse_pos[i_b] ); \
\
/* \
* Adding prediction and coefficient data (ISO/IEC 13818-2 \
* section 7.6.8) \
*/ \
OPBLOCK( p_vdec, p_mb->ppi_blocks[i_b], \
p_mb->p_data[i_b], p_mb->i_addb_l_stride ); \
} \
} \
\
/* chrominance */ \
for( i_b = 4; i_b < 4 + p_mb->i_chroma_nb_blocks; \
i_b++, i_mask >>= 1 ) \
{ \
if( p_mb->i_coded_block_pattern & i_mask ) \
{ \
/* \
* Inverse DCT (ISO/IEC 13818-2 section Annex A) \
*/ \
(p_mb->pf_idct[i_b])( p_vdec, p_mb->ppi_blocks[i_b], \
p_mb->pi_sparse_pos[i_b] ); \
\
/* \
* Adding prediction and coefficient data (ISO/IEC 13818-2 \
* section 7.6.8) \
*/ \
OPBLOCK( p_vdec, p_mb->ppi_blocks[i_b], \
p_mb->p_data[i_b], p_mb->i_addb_c_stride ); \
} \
} \
}
static __inline__ void DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb )
{
if( !(p_mb->i_mb_type & MB_INTRA) )
{
/*
* Motion Compensation (ISO/IEC 13818-2 section 7.6)
*/
p_mb->pf_motion( p_mb );
DECODEBLOCKS( AddBlock )
}
else
{
DECODEBLOCKS( CopyBlock )
}
/*
* Decoding is finished, release the macroblock and free
* unneeded memory.
*/
vpar_ReleaseMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
}
/*******************************************************************************
* RunThread: video decoder thread
*******************************************************************************
* Video decoder thread. This function does only return when the thread is
* terminated.
*******************************************************************************/
void vdec_DummyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, yuv_data_t * p_data, int i_incr )
static void RunThread( vdec_thread_t *p_vdec )
{
intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)\n",
p_vdec, getpid());
/*
* Initialize thread and free configuration
*/
p_vdec->b_error = InitThread( p_vdec );
if( p_vdec->b_error )
{
return;
}
p_vdec->b_run = 1;
/*
* Main loop - it is not executed if an error occured during
* initialization
*/
while( (!p_vdec->b_die) && (!p_vdec->b_error) )
{
macroblock_t * p_mb;
if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL )
{
DecodeMacroblock( p_vdec, p_mb );
}
}
/*
* Error loop
*/
if( p_vdec->b_error )
{
ErrorThread( p_vdec );
}
/* End of thread */
EndThread( p_vdec );
p_vdec->b_run = 0;
}
......@@ -33,9 +33,9 @@
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "video_fifo.h"
#include "vpar_synchro.h"
#include "video_parser.h"
#include "video_fifo.h"
/*****************************************************************************
* vpar_InitFIFO : initialize the video FIFO
......@@ -61,154 +61,3 @@ void vpar_InitFIFO( vpar_thread_t * p_vpar )
+ i_dummy;
}
}
/*****************************************************************************
* vpar_GetMacroblock : return a macroblock to be decoded
*****************************************************************************/
macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo )
{
macroblock_t * p_mb;
vlc_mutex_lock( &p_fifo->lock );
while( VIDEO_FIFO_ISEMPTY( *p_fifo ) )
{
vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
if( p_fifo->p_vpar->b_die )
{
vlc_mutex_unlock( &p_fifo->lock );
return( NULL );
}
}
p_mb = VIDEO_FIFO_START( *p_fifo );
VIDEO_FIFO_INCSTART( *p_fifo );
vlc_mutex_unlock( &p_fifo->lock );
return( p_mb );
}
/*****************************************************************************
* vpar_NewMacroblock : return a buffer for the parser
*****************************************************************************/
macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo )
{
macroblock_t * p_mb;
#define P_buffer p_fifo->p_vpar->vbuffer
vlc_mutex_lock( &P_buffer.lock );
while( P_buffer.i_index == -1 )
{
/* No more structures available. This should not happen ! */
intf_DbgMsg("vpar debug: macroblock list is empty, delaying\n");
vlc_mutex_unlock( &P_buffer.lock );
msleep(VPAR_IDLE_SLEEP);
vlc_mutex_lock( &P_buffer.lock );
}
p_mb = P_buffer.pp_mb_free[ P_buffer.i_index-- ];
vlc_mutex_unlock( &P_buffer.lock );
#undef P_buffer
return( p_mb );
}
/*****************************************************************************
* vpar_DecodeMacroblock : put a macroblock in the video fifo
*****************************************************************************/
void vpar_DecodeMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb )
{
/* Place picture in the video FIFO */
vlc_mutex_lock( &p_fifo->lock );
/* By construction, the video FIFO cannot be full */
VIDEO_FIFO_END( *p_fifo ) = p_mb;
VIDEO_FIFO_INCEND( *p_fifo );
vlc_mutex_unlock( &p_fifo->lock );
}
/*****************************************************************************
* vpar_ReleaseMacroblock : release a macroblock and put the picture in the
* video output heap, if it is finished
*****************************************************************************/
void vpar_ReleaseMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb )
{
boolean_t b_finished;
/* Unlink picture buffer */
vlc_mutex_lock( &p_mb->p_picture->lock_deccount );
p_mb->p_picture->i_deccount--;
b_finished = (p_mb->p_picture->i_deccount == 1);
vlc_mutex_unlock( &p_mb->p_picture->lock_deccount );
//fprintf(stderr, "%d ", p_mb->p_picture->i_deccount);
/* Test if it was the last block of the picture */
if( b_finished )
{
//fprintf(stderr, "Image decodee\n");
/* Mark the picture to be displayed */
vout_DisplayPicture( p_fifo->p_vpar->p_vout, p_mb->