Commit 5d7967a8 authored by Christophe Massiot's avatar Christophe Massiot

* Ajout d'un flag VDEC_SMP � commenter si on n'a qu'un seul

microprocesseur.
parent 57f09822
......@@ -285,8 +285,11 @@
#define VPAR_IDLE_SLEEP 100000
/* Time to sleep when waiting for a buffer (from vout or the video fifo). */
#define VPAR_OUTMEM_SLEEP 50000
/* The following directives only apply if you define VDEC_SMP below. */
/* 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. */
......@@ -299,15 +302,16 @@
* Video decoder configuration
*******************************************************************************/
//#define VDEC_SMP
#define VDEC_IDLE_SLEEP 100000
/* Number of video_decoder threads to launch on startup of the video_parser.
* It should always be less than half the number of macroblocks of a
* picture. */
* picture. Only available if you defined VDEC_SMP above. */
#define NB_VDEC 1
/* Maximum range of values out of the IDCT + motion compensation. Only
* used if you define MPEG2_COMPLIANT above. */
/* Maximum range of values out of the IDCT + motion compensation. */
#define VDEC_CROPRANGE 2048
/*******************************************************************************
......
......@@ -79,6 +79,7 @@ typedef struct vdec_thread_s
*****************************************************************************/
#ifndef OLD_DECODER
struct vpar_thread_s;
struct macroblock_s;
#endif
/* Thread management functions */
......@@ -87,6 +88,10 @@ p_vdec_thread_t vdec_CreateThread ( /* video_cfg_t *p_cfg, */ input_threa
vout_thread_t *p_vout, int *pi_status */ );
void vdec_DestroyThread ( vdec_thread_t *p_vdec /*, int *pi_status */ );
#else
#ifndef VDEC_SMP
int vdec_InitThread ( struct vdec_thread_s *p_vdec );
void vdec_DecodeMacroblock ( struct vdec_thread_s *p_vdec, struct macroblock_s *p_mb );
#endif
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 */ );
#endif
......@@ -15,6 +15,7 @@
* Macros
*****************************************************************************/
#ifdef VDEC_SMP
/* ?? 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 ) \
......@@ -25,12 +26,14 @@
#define VIDEO_FIFO_END( fifo ) ( (fifo).buffer[ (fifo).i_end ] )
#define VIDEO_FIFO_INCEND( fifo ) ( (fifo).i_end = ((fifo).i_end + 1) \
& VFIFO_SIZE )
#endif
/*****************************************************************************
* vpar_GetMacroblock : return a macroblock to be decoded
*****************************************************************************/
static __inline__ macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo )
{
#ifdef VDEC_SMP
macroblock_t * p_mb;
vlc_mutex_lock( &p_fifo->lock );
......@@ -50,6 +53,10 @@ static __inline__ macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo )
vlc_mutex_unlock( &p_fifo->lock );
return( p_mb );
#else
/* Shouldn't normally be used without SMP. */
return NULL;
#endif
}
/*****************************************************************************
......@@ -57,6 +64,7 @@ static __inline__ macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo )
*****************************************************************************/
static __inline__ macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo )
{
#ifdef VDEC_SMP
macroblock_t * p_mb;
#define P_buffer p_fifo->p_vpar->vbuffer
......@@ -75,6 +83,9 @@ static __inline__ macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo )
vlc_mutex_unlock( &P_buffer.lock );
#undef P_buffer
return( p_mb );
#else
return( &p_fifo->buffer );
#endif
}
/*****************************************************************************
......@@ -83,6 +94,7 @@ static __inline__ macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo )
static __inline__ void vpar_DecodeMacroblock( video_fifo_t * p_fifo,
macroblock_t * p_mb )
{
#ifdef VDEC_SMP
/* Place picture in the video FIFO */
vlc_mutex_lock( &p_fifo->lock );
......@@ -91,6 +103,8 @@ static __inline__ void vpar_DecodeMacroblock( video_fifo_t * p_fifo,
VIDEO_FIFO_INCEND( *p_fifo );
vlc_mutex_unlock( &p_fifo->lock );
#endif
/* Shouldn't normally be used without SMP. */
}
/*****************************************************************************
......@@ -100,6 +114,7 @@ static __inline__ void vpar_DecodeMacroblock( video_fifo_t * p_fifo,
static __inline__ void vpar_ReleaseMacroblock( video_fifo_t * p_fifo,
macroblock_t * p_mb )
{
#ifdef VDEC_SMP
boolean_t b_finished;
/* Unlink picture buffer */
......@@ -135,6 +150,18 @@ static __inline__ void vpar_ReleaseMacroblock( video_fifo_t * p_fifo,
P_buffer.pp_mb_free[ ++P_buffer.i_index ] = p_mb;
vlc_mutex_unlock( &P_buffer.lock );
#undef P_buffer
#else
p_mb->p_picture->i_deccount--;
if( p_mb->p_picture->i_deccount == 1 )
{
/* 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 );
}
#endif
}
/*****************************************************************************
......@@ -143,19 +170,20 @@ static __inline__ void vpar_ReleaseMacroblock( video_fifo_t * p_fifo,
static __inline__ void vpar_DestroyMacroblock( video_fifo_t * p_fifo,
macroblock_t * p_mb )
{
#ifdef VDEC_SMP
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);
b_finished = (p_mb->p_picture->i_deccount == 1);
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 */
/* Mark the picture to be trashed */
vout_DestroyPicture( p_fifo->p_vpar->p_vout, p_mb->p_picture );
/* Warn Synchro for its records. */
......@@ -178,6 +206,18 @@ fprintf(stderr, "Image trashee\n");
P_buffer.pp_mb_free[ ++P_buffer.i_index ] = p_mb;
vlc_mutex_unlock( &P_buffer.lock );
#undef P_buffer
#else
p_mb->p_picture->i_deccount--;
if( p_mb->p_picture->i_deccount == 1 )
{
/* Mark the picture to be trashed */
vout_DestroyPicture( p_fifo->p_vpar->p_vout, p_mb->p_picture );
/* Warn Synchro for its records. */
vpar_SynchroEnd( p_fifo->p_vpar );
}
#endif
}
/*****************************************************************************
......
......@@ -25,13 +25,17 @@ struct vpar_thread_s;
typedef struct video_fifo_s
{
#ifdef VDEC_SMP
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;
macroblock_t * buffer[VFIFO_SIZE + 1];
int i_start;
int i_end;
#else
macroblock_t buffer;
#endif
struct vpar_thread_s * p_vpar;
} video_fifo_t;
......@@ -42,6 +46,7 @@ typedef struct video_fifo_s
* This structure enables the parser to maintain a list of free
* macroblock_t structures
*****************************************************************************/
#ifdef VDEC_SMP
typedef struct video_buffer_s
{
vlc_mutex_t lock; /* buffer data lock */
......@@ -50,6 +55,7 @@ typedef struct video_buffer_s
macroblock_t * pp_mb_free[VFIFO_SIZE+1]; /* this is a LIFO */
int i_index;
} video_buffer_t;
#endif
/*****************************************************************************
* vpar_thread_t: video parser thread descriptor
......@@ -79,12 +85,13 @@ typedef struct vpar_thread_s
/* Output properties */
vout_thread_t * p_vout; /* video output thread */
int i_stream; /* video stream id */
/* Decoder properties */
struct vdec_thread_s * p_vdec[NB_VDEC];
struct vdec_thread_s * pp_vdec[NB_VDEC];
video_fifo_t vfifo;
#ifdef VDEC_SMP
video_buffer_t vbuffer;
#endif
/* Parser properties */
sequence_t sequence;
......
......@@ -93,7 +93,9 @@ typedef struct picture_parsing_s
int i_current_structure;
picture_t * p_picture;
#ifdef VDEC_SMP
macroblock_t * pp_mb[MAX_MB];
#endif
/* Relative to the current field */
int i_coding_type, i_structure;
......
......@@ -44,12 +44,14 @@
/*
* Local prototypes
*/
static int InitThread ( vdec_thread_t *p_vdec );
#ifdef VDEC_SMP
static int vdec_InitThread ( vdec_thread_t *p_vdec );
static void vdec_DecodeMacroblock( vdec_thread_t *p_vdec,
macroblock_t * p_mb );
#endif
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 DecodeMacroblock ( vdec_thread_t *p_vdec,
macroblock_t * p_mb );
/*******************************************************************************
* vdec_CreateThread: create a video decoder thread
......@@ -109,11 +111,13 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
/* Ask thread to kill itself */
p_vdec->b_die = 1;
/* Make sure the parser thread leaves the GetByte() function */
#ifdef VDEC_SMP
/* Make sure the decoder thread leaves the vpar_GetMacroblock() function */
vlc_mutex_lock( &(p_vdec->p_vpar->vfifo.lock) );
vlc_cond_signal( &(p_vdec->p_vpar->vfifo.wait) );
vlc_mutex_unlock( &(p_vdec->p_vpar->vfifo.lock) );
#endif
/* Waiting for the decoder thread to exit */
/* Remove this as soon as the "status" flag is implemented */
......@@ -123,13 +127,17 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
/* following functions are local */
/*******************************************************************************
* InitThread: initialize video decoder thread
* vdec_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
* modified inside this function.
*******************************************************************************/
static int InitThread( vdec_thread_t *p_vdec )
#ifdef VDEC_SMP
static int vdec_InitThread( vdec_thread_t *p_vdec )
#else
int vdec_InitThread( vdec_thread_t *p_vdec )
#endif
{
int i_dummy;
......@@ -233,7 +241,7 @@ static __inline__ void CopyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block,
}
/*******************************************************************************
* DecodeMacroblock : decode a macroblock of a picture
* vdec_DecodeMacroblock : decode a macroblock of a picture
*******************************************************************************/
#define DECODEBLOCKS( OPBLOCK ) \
{ \
......@@ -283,7 +291,11 @@ static __inline__ void CopyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block,
} \
}
static __inline__ void DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb )
#ifdef VDEC_SMP
static __inline__ void vdec_DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb )
#else
void vdec_DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb )
#endif
{
if( !(p_mb->i_mb_type & MB_INTRA) )
{
......@@ -321,7 +333,7 @@ static void RunThread( vdec_thread_t *p_vdec )
/*
* Initialize thread and free configuration
*/
p_vdec->b_error = InitThread( p_vdec );
p_vdec->b_error = vdec_InitThread( p_vdec );
if( p_vdec->b_error )
{
return;
......@@ -338,7 +350,7 @@ static void RunThread( vdec_thread_t *p_vdec )
if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL )
{
DecodeMacroblock( p_vdec, p_mb );
vdec_DecodeMacroblock( p_vdec, p_mb );
}
}
......
......@@ -42,8 +42,13 @@
*****************************************************************************/
void vpar_InitFIFO( vpar_thread_t * p_vpar )
{
#ifdef VDEC_SMP
int i_dummy;
#endif
p_vpar->vfifo.p_vpar = p_vpar;
#ifdef VDEC_SMP
/* Initialize mutex and cond */
vlc_mutex_init( &p_vpar->vfifo.lock );
vlc_cond_init( &p_vpar->vfifo.wait );
......@@ -51,7 +56,6 @@ void vpar_InitFIFO( vpar_thread_t * p_vpar )
/* Initialize FIFO properties */
p_vpar->vfifo.i_start = p_vpar->vfifo.i_end = 0;
p_vpar->vfifo.p_vpar = p_vpar;
/* Initialize buffer properties */
p_vpar->vbuffer.i_index = VFIFO_SIZE; /* all structures are available */
......@@ -60,4 +64,5 @@ void vpar_InitFIFO( vpar_thread_t * p_vpar )
p_vpar->vbuffer.pp_mb_free[i_dummy] = p_vpar->vbuffer.p_macroblocks
+ i_dummy;
}
#endif
}
......@@ -206,18 +206,30 @@ static int InitThread( vpar_thread_t *p_vpar )
/* Initialize video FIFO */
vpar_InitFIFO( p_vpar );
bzero( p_vpar->p_vdec, NB_VDEC*sizeof(vdec_thread_t *) );
memset( p_vpar->pp_vdec, 0, NB_VDEC*sizeof(vdec_thread_t *) );
#ifdef VDEC_SMP
/* Spawn video_decoder threads */
/* ??? modify the number of vdecs at runtime ? */
for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
{
if( (p_vpar->p_vdec[i_dummy] = vdec_CreateThread( p_vpar )) == NULL )
if( (p_vpar->pp_vdec[i_dummy] = vdec_CreateThread( p_vpar )) == NULL )
{
return( 1 );
}
}
#else
/* Fake a video_decoder thread */
if( (p_vpar->pp_vdec[0] = (vdec_thread_t *)malloc(sizeof( vdec_thread_t ))) == NULL
|| vdec_InitThread( p_vpar->pp_vdec[0] ) )
{
return( 1 );
}
p_vpar->pp_vdec[0]->b_die = 0;
p_vpar->pp_vdec[0]->b_error = 0;
p_vpar->pp_vdec[0]->p_vpar = p_vpar;
#endif
/* Initialize lookup tables */
#if defined(MPEG2_COMPLIANT) && !defined(VDEC_DFT)
......@@ -354,7 +366,9 @@ static void ErrorThread( vpar_thread_t *p_vpar )
*******************************************************************************/
static void EndThread( vpar_thread_t *p_vpar )
{
#ifdef VDEC_SMP
int i_dummy;
#endif
intf_DbgMsg("vpar debug: destroying video parser thread %p\n", p_vpar);
......@@ -385,14 +399,18 @@ static void EndThread( vpar_thread_t *p_vpar )
free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
}
#ifdef VDEC_SMP
/* Destroy vdec threads */
for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
{
if( p_vpar->p_vdec[i_dummy] != NULL )
vdec_DestroyThread( p_vpar->p_vdec[i_dummy] );
if( p_vpar->pp_vdec[i_dummy] != NULL )
vdec_DestroyThread( p_vpar->pp_vdec[i_dummy] );
else
break;
}
#else
free( p_vpar->pp_vdec[0] );
#endif
intf_DbgMsg("vpar debug: EndThread(%p)\n", p_vpar);
}
......@@ -37,7 +37,6 @@
#include "video_parser.h"
#include "video_fifo.h"
/*
* Local prototypes
*/
......@@ -790,13 +789,15 @@ i_count++;
memset( p_vpar->slice.pppi_pmv, 0, 8*sizeof(int) );
}
if( (p_mb = p_vpar->picture.pp_mb[i_mb_base + i_mb] =
vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
{
p_vpar->picture.b_error = 1;
intf_ErrMsg("vpar error: macroblock list is empty !\n");
return;
}
#ifdef VDEC_SMP
p_vpar->picture.pp_mb[i_mb_base + i_mb] = p_mb;
#endif
InitMacroblock( p_vpar, p_mb );
......@@ -810,16 +811,23 @@ i_count++;
/* Set the field we use for motion compensation */
p_mb->ppi_field_select[0][0] = p_mb->ppi_field_select[0][1]
= ( p_vpar->picture.i_current_structure == BOTTOM_FIELD );
#ifndef VDEC_SMP
/* Decode the macroblock NOW ! */
vdec_DecodeMacroblock( p_vpar->pp_vdec[0], p_mb );
#endif
}
/* Get a macroblock structure. */
if( (p_mb = p_vpar->picture.pp_mb[i_mb_base + *pi_mb_address] =
vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
{
p_vpar->picture.b_error = 1;
intf_ErrMsg("vpar error: macroblock list is empty !\n");
return;
}
#ifdef VDEC_SMP
p_vpar->picture.pp_mb[i_mb_base + *pi_mb_address] = p_mb;
#endif
InitMacroblock( p_vpar, p_mb );
......@@ -953,6 +961,12 @@ if( 0 )
{
p_mb->i_mb_type |= MB_MOTION_FORWARD;
}
#ifndef VDEC_SMP
/* Decode the macroblock NOW ! */
vdec_DecodeMacroblock( p_vpar->pp_vdec[0], p_mb );
#endif
/*
if( p_vpar->picture.i_coding_type != I_CODING_TYPE )//!(p_mb->b_P_coding_type & MB_INTRA) )
{
......@@ -1260,7 +1274,7 @@ if( i_parse >= 64 )
p_mb->ppi_blocks[i_b][i_pos] = b_sign ? -i_level : i_level;
}
fprintf( stderr, "Non intra MPEG2 end (%d)\n", i_b );
//p_vpar->picture.b_error = 1;
p_vpar->picture.b_error = 1;
}
/*****************************************************************************
......@@ -1500,5 +1514,5 @@ if( i_parse >= 64 )
}
fprintf( stderr, "MPEG2 end (%d)\n", i_b );
//p_vpar->b_error = 1;
p_vpar->picture.b_error = 1;
}
......@@ -518,9 +518,12 @@ static void PictureHeader( vpar_thread_t * p_vpar )
vpar_BMBType, vpar_DMBType};
int i_structure;
int i_mb_address, i_mb_base, i_mb;
int i_mb_address, i_mb_base;
boolean_t b_parsable;
u32 i_dummy;
#ifdef VDEC_SMP
int i_mb;
#endif
RemoveBits( &p_vpar->bit_stream, 10 ); /* temporal_reference */
p_vpar->picture.i_coding_type = GetBits( &p_vpar->bit_stream, 3 );
......@@ -609,11 +612,13 @@ static void PictureHeader( vpar_thread_t * p_vpar )
p_vpar->picture.i_coding_type,
NULL );
#ifdef VDEC_SMP
for( i_mb = 0; p_vpar->picture.pp_mb[i_mb] != NULL; i_mb++ )
{
vpar_DestroyMacroblock( &p_vpar->vfifo,
p_vpar->picture.pp_mb[i_mb] );
}
#endif
vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
}
......@@ -701,18 +706,34 @@ static void PictureHeader( vpar_thread_t * p_vpar )
P_picture->i_deccount = p_vpar->sequence.i_mb_size;
vlc_mutex_init( &p_vpar->picture.p_picture->lock_deccount );
memset( p_vpar->picture.pp_mb, 0, MAX_MB );
#ifdef VDEC_SMP
memset( p_vpar->picture.pp_mb, 0, MAX_MB*sizeof(macroblock_t *) );
#endif
/* FIXME ! remove asap */
//memset( P_picture->p_data, 0, (p_vpar->sequence.i_mb_size*384));
/* Update the reference pointers. */
ReferenceUpdate( p_vpar, p_vpar->picture.i_coding_type, P_picture );
#ifdef VDEC_SMP
/* Link referenced pictures for the decoder
* They are unlinked in vpar_ReleaseMacroblock() & vpar_DestroyMacroblock() */
if( p_vpar->picture.i_coding_type == P_CODING_TYPE ||
p_vpar->picture.i_coding_type == B_CODING_TYPE )
{
vout_LinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
}
if( p_vpar->picture.i_coding_type == B_CODING_TYPE )
{
vout_LinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
}
#endif
}
p_vpar->picture.i_current_structure |= i_structure;
p_vpar->picture.i_structure = i_structure;
/* Initialize picture data for decoding. */
if( p_vpar->picture.b_motion_field = (i_structure == BOTTOM_FIELD) )
if( (p_vpar->picture.b_motion_field = (i_structure == BOTTOM_FIELD)) )
{
i_mb_base = p_vpar->sequence.i_mb_size >> 1;
p_vpar->mb.i_l_y = 1;
......@@ -752,11 +773,17 @@ static void PictureHeader( vpar_thread_t * p_vpar )
{
/* Trash picture. */
//fprintf(stderr, "Image trashee\n");
for( i_mb = 1; p_vpar->picture.pp_mb[i_mb]; i_mb++ )
#ifdef VDEC_SMP
for( i_mb = 1; p_vpar->picture.pp_mb[i_mb] != NULL; i_mb++ )
{
vpar_DestroyMacroblock( &p_vpar->vfifo, p_vpar->picture.pp_mb[i_mb] );
}
vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
#endif
if( P_picture->i_deccount != 1 )
{
vout_DestroyPicture( p_vpar->p_vout, P_picture );
}
ReferenceReplace( p_vpar, p_vpar->picture.i_coding_type, NULL );
......@@ -769,28 +796,18 @@ static void PictureHeader( vpar_thread_t * p_vpar )
{
//fprintf(stderr, "Image parsee (%d)\n", p_vpar->picture.i_coding_type);
/* Frame completely parsed. */
#ifdef VDEC_SMP
for( i_mb = 1; p_vpar->picture.pp_mb[i_mb] != NULL; i_mb++ )
{
vpar_DecodeMacroblock( &p_vpar->vfifo, p_vpar->picture.pp_mb[i_mb] );
}
/* Link referenced pictures for the decoder
* They are unlinked in vpar_ReleaseMacroblock() & vpar_DestroyMacroblock() */
if( p_vpar->picture.i_coding_type == P_CODING_TYPE ||
p_vpar->picture.i_coding_type == B_CODING_TYPE )
{
vout_LinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
}
if( p_vpar->picture.i_coding_type == B_CODING_TYPE )
{
vout_LinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
}
/* Send signal to the video_decoder. */
vlc_mutex_lock( &p_vpar->vfifo.lock );
vlc_cond_signal( &p_vpar->vfifo.wait );
vlc_mutex_unlock( &p_vpar->vfifo.lock );
#endif
/* Prepare context for the next picture. */
P_picture = NULL;
p_vpar->picture.i_current_structure = 0;
......
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