Commit d0c9b479 authored by Christophe Massiot's avatar Christophe Massiot

* Rewrote the video decoder to take advantage of several processors (SMP mode) ;

* Fixed a bug in the video decoder initialization :-p ;
* Added --smp option and several hooks in src/input/input_ext-intf.c ;
* Grayscale mode now turns off chroma IDCT.
parent 18f5cd99
......@@ -30,7 +30,7 @@ AC3_SPDIF := ac3_spdif ac3_iec958
LPCM_DECODER := lpcm_decoder_thread
AUDIO_DECODER := audio_decoder adec_generic adec_layer1 adec_layer2 adec_math
SPU_DECODER := spu_decoder
VIDEO_DECODER := video_parser vpar_headers vpar_blocks vpar_synchro video_fifo video_decoder
VIDEO_DECODER := video_parser vpar_headers vpar_blocks vpar_synchro vpar_pool video_decoder
MISC := mtime tests modules netutils
C_OBJ := $(INTERFACE:%=src/interface/%.o) \
......
......@@ -439,13 +439,6 @@
* that raising this level dramatically lengthens the compilation time. */
#define VPAR_OPTIM_LEVEL 2
/* 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. */
#define VFIFO_SIZE 8191
/* Maximum number of macroblocks in a picture. */
#define MAX_MB 2048
......@@ -456,26 +449,16 @@
* Video decoder configuration
*****************************************************************************/
//#define VDEC_SMP
#define VDEC_IDLE_SLEEP ((int)(0.100*CLOCK_FREQ))
/* 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. Only available if you defined VDEC_SMP above. */
#define NB_VDEC 1
/* Maximum range of values out of the IDCT + motion compensation. */
#define VDEC_CROPRANGE 2048
/* Nice increments for decoders -- necessary for x11 scheduling */
#define VDEC_NICE 3
/*****************************************************************************
* Generic decoder configuration
*****************************************************************************/
/* Environment variable containing the SMP value. */
#define VDEC_SMP_VAR "vlc_smp"
#define GDEC_IDLE_SLEEP ((int)(0.100*CLOCK_FREQ))
/* No SMP by default, since it slows down things on non-smp machines. */
#define VDEC_SMP_DEFAULT 0
/*****************************************************************************
* Messages and console interfaces configuration
......
......@@ -4,7 +4,7 @@
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-intf.h,v 1.40 2001/06/27 09:53:56 massiot Exp $
* $Id: input_ext-intf.h,v 1.41 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -205,6 +205,7 @@ typedef struct stream_descriptor_s
/* New status and rate requested by the interface */
int i_new_status, i_new_rate;
int b_new_mute; /* int because it can be -1 */
vlc_cond_t stream_wait; /* interface -> input in case of a
* status change request */
......@@ -229,6 +230,8 @@ typedef struct stream_descriptor_s
stream_ctrl_t control;
} stream_descriptor_t;
#define MUTE_NO_CHANGE -1
/*****************************************************************************
* i_p_config_t
*****************************************************************************
......@@ -360,7 +363,6 @@ struct input_thread_s * input_CreateThread ( struct playlist_item_s *,
void input_DestroyThread( struct input_thread_s *, int *pi_status );
void input_SetStatus( struct input_thread_s *, int );
void input_SetRate ( struct input_thread_s *, int );
void input_Seek ( struct input_thread_s *, off_t );
void input_DumpStream( struct input_thread_s * );
char * input_OffsetToTime( struct input_thread_s *, char * psz_buffer, off_t );
......@@ -368,5 +370,8 @@ int input_ChangeES ( struct input_thread_s *, struct es_descriptor_s *, u8 );
int input_ToggleES ( struct input_thread_s *,
struct es_descriptor_s *,
boolean_t );
int input_ChangeArea( input_thread_t *, input_area_t * );
int input_ChangeArea( struct input_thread_s *, struct input_area_s * );
int input_ToggleGrayscale( struct input_thread_s * );
int input_ToggleMute( struct input_thread_s * );
int input_SetSMP( struct input_thread_s *, int );
......@@ -3,7 +3,7 @@
* but exported to plug-ins
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: input_ext-plugins.h,v 1.1 2001/07/17 09:48:07 massiot Exp $
* $Id: input_ext-plugins.h,v 1.2 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -74,8 +74,7 @@ void input_EndDecoder( struct input_thread_s *, struct es_descriptor_s * );
void input_DecodePES ( struct decoder_fifo_s *, struct pes_packet_s * );
void input_EscapeDiscontinuity( struct input_thread_s *,
struct pgrm_descriptor_s * );
void input_EscapeAudioDiscontinuity( struct input_thread_s *,
struct pgrm_descriptor_s * );
void input_EscapeAudioDiscontinuity( struct input_thread_s * );
/*****************************************************************************
* Prototypes from input_clock.c
......
......@@ -62,7 +62,6 @@ typedef struct module_symbols_s
int ( * network_ChannelJoin ) ( int );
void ( * input_SetStatus ) ( struct input_thread_s *, int );
void ( * input_SetRate ) ( struct input_thread_s *, int );
void ( * input_Seek ) ( struct input_thread_s *, off_t );
void ( * input_DumpStream ) ( struct input_thread_s * );
char * ( * input_OffsetToTime ) ( struct input_thread_s *, char *, off_t );
......@@ -152,7 +151,6 @@ typedef struct module_symbols_s
(p_symbols)->network_ChannelCreate = network_ChannelCreate; \
(p_symbols)->network_ChannelJoin = network_ChannelJoin; \
(p_symbols)->input_SetStatus = input_SetStatus; \
(p_symbols)->input_SetRate = input_SetRate; \
(p_symbols)->input_Seek = input_Seek; \
(p_symbols)->input_DumpStream = input_DumpStream; \
(p_symbols)->input_OffsetToTime = input_OffsetToTime; \
......@@ -238,7 +236,6 @@ extern module_symbols_t* p_symbols;
# define network_ChannelJoin(a) p_symbols->network_ChannelJoin(a)
# define input_SetStatus(a,b) p_symbols->input_SetStatus(a,b)
# define input_SetRate(a,b) p_symbols->input_SetRate(a,b)
# define input_Seek(a,b) p_symbols->input_Seek(a,b)
# define input_DumpStream(a) p_symbols->input_DumpStream(a)
# define input_OffsetToTime(a,b,c) p_symbols->input_OffsetToTime(a,b,c)
......
......@@ -4,7 +4,7 @@
* of the reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: stream_control.h,v 1.5 2001/02/08 13:52:34 massiot Exp $
* $Id: stream_control.h,v 1.6 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -39,7 +39,9 @@ typedef struct stream_ctrl_s
int i_rate;
boolean_t b_mute;
boolean_t b_bw; /* black & white */
boolean_t b_grayscale; /* use color or grayscale */
int i_smp; /* number of symmetrical threads to launch
* to decode the video | 0 == disabled */
} stream_ctrl_t;
/* Possible status : */
......
......@@ -3,7 +3,7 @@
* This header provides a portable threads implementation.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: threads.h,v 1.19 2001/06/14 20:21:04 sam Exp $
* $Id: threads.h,v 1.20 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
......@@ -491,6 +491,74 @@ static __inline__ int vlc_cond_signal( vlc_cond_t *p_condvar )
#endif
}
/*****************************************************************************
* vlc_cond_broadcast: start all threads waiting on condition completion
*****************************************************************************/
/*
* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
* Only works with pthreads, you need to adapt it for others
* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
*/
static __inline__ int vlc_cond_broadcast( vlc_cond_t *p_condvar )
{
#if defined( PTH_INIT_IN_PTH_H )
return pth_cond_notify( p_condvar, FALSE );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
return pthread_cond_broadcast( p_condvar );
#elif defined( HAVE_CTHREADS_H )
/* condition_signal() */
if ( p_condvar->queue.head || p_condvar->implications )
{
cond_signal( (condition_t)p_condvar );
}
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( !p_condvar )
{
return B_BAD_VALUE;
}
if( p_condvar->init < 2000 )
{
return B_NO_INIT;
}
while( p_condvar->thread != -1 )
{
thread_info info;
if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
{
return 0;
}
if( info.state != B_THREAD_SUSPENDED )
{
/* The waiting thread is not suspended so it could
* have been interrupted beetwen the unlock and the
* suspend_thread line. That is why we sleep a little
* before retesting p_condver->thread. */
snooze( 10000 );
}
else
{
/* Ok, we have to wake up that thread */
resume_thread( p_condvar->thread );
return 0;
}
}
return 0;
#elif defined( WIN32 )
/* Try to release one waiting thread. */
PulseEvent ( *p_condvar );
return 0;
#endif
}
/*****************************************************************************
* vlc_cond_wait: wait until condition completion
*****************************************************************************/
......
......@@ -2,7 +2,7 @@
* vdec_common.h : structures from the video decoder exported to plug-ins
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: vdec_ext-plugins.h,v 1.1 2001/07/17 09:48:07 massiot Exp $
* $Id: vdec_ext-plugins.h,v 1.2 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -98,24 +98,13 @@ typedef struct macroblock_s
*****************************************************************************/
typedef struct vdec_thread_s
{
/* Thread properties and locks */
boolean_t b_die; /* `die' flag */
boolean_t b_run; /* `run' flag */
boolean_t b_error; /* `error' flag */
boolean_t b_active; /* `active' flag */
vlc_thread_t thread_id; /* id for thread functions */
boolean_t b_die;
/* IDCT iformations */
void * p_idct_data;
dctelem_t p_pre_idct[64*64];
/* Macroblock copy functions */
void ( * pf_decode_init ) ( struct vdec_thread_s * );
void ( * pf_decode_mb_c ) ( struct vdec_thread_s *, struct macroblock_s * );
void ( * pf_decode_mb_bw )( struct vdec_thread_s *, struct macroblock_s * );
void * p_idct_data;
/* Input properties */
struct vpar_thread_s * p_vpar; /* video_parser thread */
struct vdec_pool_s * p_pool;
} vdec_thread_t;
......@@ -4,7 +4,7 @@
* includes all common video types and constants.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: video.h,v 1.30 2001/05/07 04:42:42 sam Exp $
* $Id: video.h,v 1.31 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
......@@ -71,11 +71,6 @@ typedef struct picture_s
int i_display_height; /* useful picture height */
int i_aspect_ratio; /* aspect ratio */
/* Macroblock counter - the decoder use it to verify if it has
* decoded all the macroblocks of the picture */
int i_deccount;
vlc_mutex_t lock_deccount;
/* Picture data - data can always be freely modified. p_data itself
* (the pointer) should NEVER be modified. In YUV format, the p_y, p_u and
* p_v data pointers refers to different areas of p_data, and should not
......
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input.c,v 1.126 2001/07/17 09:48:08 massiot Exp $
* $Id: input.c,v 1.127 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -138,6 +138,7 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
p_input->stream.i_selected_es_number = 0;
p_input->stream.i_pgrm_number = 0;
p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
p_input->stream.b_new_mute = MUTE_NO_CHANGE;
p_input->stream.i_mux_rate = 0;
/* no stream, no area */
......@@ -154,7 +155,10 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
p_input->stream.control.i_status = PLAYING_S;
p_input->stream.control.i_rate = DEFAULT_RATE;
p_input->stream.control.b_mute = 0;
p_input->stream.control.b_bw = 0;
p_input->stream.control.b_grayscale = main_GetIntVariable(
VOUT_GRAYSCALE_VAR, VOUT_GRAYSCALE_DEFAULT );
p_input->stream.control.i_smp = main_GetIntVariable(
VDEC_SMP_VAR, VDEC_SMP_DEFAULT );
/* Setup callbacks */
p_input->pf_file_open = FileOpen;
......@@ -322,6 +326,20 @@ static void RunThread( input_thread_t *p_input )
p_input->stream.p_newly_selected_es = NULL;
}
if( p_input->stream.b_new_mute != MUTE_NO_CHANGE )
{
if( p_input->stream.b_new_mute )
{
input_EscapeAudioDiscontinuity( p_input );
}
vlc_mutex_lock( &p_input->stream.control.control_lock );
p_input->stream.control.b_mute = p_input->stream.b_new_mute;
vlc_mutex_unlock( &p_input->stream.control.control_lock );
p_input->stream.b_new_mute = MUTE_NO_CHANGE;
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
i_error = p_input->pf_read( p_input, pp_packets );
......
......@@ -2,7 +2,7 @@
* input_clock.c: Clock/System date convertions, stream management
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_clock.c,v 1.19 2001/07/17 09:48:08 massiot Exp $
* $Id: input_clock.c,v 1.20 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -197,7 +197,7 @@ int input_ClockManageControl( input_thread_t * p_input,
/* Feed the audio decoders with a NULL packet to avoid
* discontinuities. */
input_EscapeAudioDiscontinuity( p_input, p_pgrm );
input_EscapeAudioDiscontinuity( p_input );
}
p_input->stream.i_new_status = UNDEF_S;
......
......@@ -2,7 +2,7 @@
* input_dec.c: Functions for the management of decoders
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_dec.c,v 1.12 2001/07/17 09:48:08 massiot Exp $
* $Id: input_dec.c,v 1.13 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -147,20 +147,24 @@ void input_EscapeDiscontinuity( input_thread_t * p_input,
/*****************************************************************************
* input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
*****************************************************************************/
void input_EscapeAudioDiscontinuity( input_thread_t * p_input,
pgrm_descriptor_t * p_pgrm )
void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
{
int i_es, i;
int i_pgrm, i_es, i;
for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
for( i_pgrm = 0; i_pgrm < p_input->stream.i_pgrm_number; i_pgrm++ )
{
es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
pgrm_descriptor_t * p_pgrm = p_input->stream.pp_programs[i_pgrm];
if( p_es->p_decoder_fifo != NULL && p_es->b_audio )
for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
{
for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
if( p_es->p_decoder_fifo != NULL && p_es->b_audio )
{
input_NullPacket( p_input, p_es );
for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
{
input_NullPacket( p_input, p_es );
}
}
}
}
......
......@@ -2,7 +2,7 @@
* input_ext-intf.c: services to the interface
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input_ext-intf.c,v 1.26 2001/07/17 09:48:08 massiot Exp $
* $Id: input_ext-intf.c,v 1.27 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -128,14 +128,6 @@ void input_SetStatus( input_thread_t * p_input, int i_mode )
vlc_mutex_unlock( &p_input->stream.stream_lock );
}
/*****************************************************************************
* input_SetRate: change the reading rate
*****************************************************************************/
void input_SetRate( input_thread_t * p_input, int i_mode )
{
; /* FIXME: stub */
}
/*****************************************************************************
* input_Seek: changes the stream postion
*****************************************************************************/
......@@ -339,3 +331,55 @@ int input_ChangeArea( input_thread_t * p_input, input_area_t * p_area )
return 0;
}
/****************************************************************************
* input_ToggleGrayscale: change to grayscale or color output
****************************************************************************/
int input_ToggleGrayscale( input_thread_t * p_input )
{
/* No need to warn the input thread since only the decoders and outputs
* worry about it. */
vlc_mutex_lock( &p_input->stream.control.control_lock );
p_input->stream.control.b_grayscale =
!p_input->stream.control.b_grayscale;
intf_WarnMsg( 3, "input warning: changing to %s output",
p_input->stream.control.b_grayscale ? "grayscale" : "color" );
vlc_mutex_unlock( &p_input->stream.control.control_lock );
return 0;
}
/****************************************************************************
* input_ToggleMute: activate/deactivate mute mode
****************************************************************************/
int input_ToggleMute( input_thread_t * p_input )
{
/* We need to feed the decoders with 0, and only input can do that, so
* pass the message to the input thread. */
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.b_new_mute = !p_input->stream.control.b_mute;
intf_WarnMsg( 3, "input warning: %s mute mode",
p_input->stream.control.b_mute ? "activating" : "deactivating" );
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0;
}
/****************************************************************************
* input_SetSMP: change the number of video decoder threads
****************************************************************************/
int input_SetSMP( input_thread_t * p_input, int i_smp )
{
/* No need to warn the input thread since only the decoders
* worry about it. */
vlc_mutex_lock( &p_input->stream.control.control_lock );
p_input->stream.control.i_smp = i_smp;
vlc_mutex_unlock( &p_input->stream.control.control_lock );
return 0;
}
......@@ -4,7 +4,7 @@
* interface, such as command line.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: interface.c,v 1.79 2001/05/15 14:49:48 stef Exp $
* $Id: interface.c,v 1.80 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
......@@ -394,6 +394,13 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
break;
case INTF_KEY_TOGGLE_VOLUME: /* toggle mute */
/* Start/stop feeding audio data. */
if( p_intf->p_input != NULL )
{
input_ToggleMute( p_intf->p_input );
}
/* Start/stop playing sound. */
vlc_mutex_lock( &p_aout_bank->lock );
for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
{
......
......@@ -4,7 +4,7 @@
* and spawn threads.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: main.c,v 1.107 2001/07/16 22:00:45 gbazin Exp $
* $Id: main.c,v 1.108 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -113,6 +113,7 @@
#define OPT_COLOR 164
#define OPT_FULLSCREEN 165
#define OPT_OVERLAY 166
#define OPT_SMP 167
#define OPT_CHANNELS 170
#define OPT_SERVER 171
......@@ -183,6 +184,7 @@ static const struct option longopts[] =
{ "yuv", 1, 0, OPT_YUV },
{ "fullscreen", 0, 0, OPT_FULLSCREEN },
{ "overlay", 0, 0, OPT_OVERLAY },
{ "smp", 1, 0, OPT_SMP },
/* DVD options */
{ "dvdtitle", 1, 0, 't' },
......@@ -693,6 +695,9 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
case OPT_YUV: /* --yuv */
main_PutPszVariable( YUV_METHOD_VAR, optarg );
break;
case OPT_SMP: /* --smp */
main_PutIntVariable( VDEC_SMP_VAR, atoi(optarg) );
break;
/* DVD options */
case 't':
......@@ -836,6 +841,7 @@ static void Usage( int i_fashion )
"\n --idct <module> \tIDCT method"
"\n --yuv <module> \tYUV method"
"\n --synchro <type> \tforce synchro algorithm"
"\n --smp <number of threads> \tuse several processors"
"\n"
"\n -t, --dvdtitle <num> \tchoose DVD title"
"\n -T, --dvdchapter <num> \tchoose DVD chapter"
......@@ -887,7 +893,8 @@ static void Usage( int i_fashion )
"\n " MOTION_METHOD_VAR "=<method name> \tmotion compensation method"
"\n " IDCT_METHOD_VAR "=<method name> \tIDCT method"
"\n " YUV_METHOD_VAR "=<method name> \tYUV method"
"\n " VPAR_SYNCHRO_VAR "={I|I+|IP|IP+|IPB} \tsynchro algorithm" );
"\n " VPAR_SYNCHRO_VAR "={I|I+|IP|IP+|IPB} \tsynchro algorithm"
"\n " VDEC_SMP_VAR "=<number of threads> \tuse several processors" );
/* DVD parameters */
intf_MsgImm( "\nDVD parameters:"
......
......@@ -2,7 +2,7 @@
* video_decoder.c : video decoder thread
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: video_decoder.c,v 1.53 2001/07/17 09:48:08 massiot Exp $
* $Id: video_decoder.c,v 1.54 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Gal Hendryckx <jimmy@via.ecp.fr>
......@@ -50,32 +50,20 @@
#include "vdec_ext-plugins.h"
#include "video_decoder.h"
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "vpar_synchro.h"
#include "video_parser.h"
#include "video_fifo.h"
#include "vpar_pool.h"
/*
* Local prototypes
*/
#ifdef VDEC_SMP
static int vdec_InitThread ( vdec_thread_t *p_vdec );
#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 );
/*****************************************************************************
* 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:
* XXX??
*****************************************************************************/
vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
vdec_thread_t * vdec_CreateThread( vdec_pool_t * p_pool )
{
vdec_thread_t * p_vdec;
......@@ -92,12 +80,11 @@ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
* Initialize the thread properties
*/
p_vdec->b_die = 0;
p_vdec->b_error = 0;
/*
* Initialize the parser properties
*/
p_vdec->p_vpar = p_vpar;
p_vdec->p_pool = p_pool;
/* Spawn the video decoder thread */
if ( vlc_thread_create(&p_vdec->thread_id, "video decoder",
......@@ -114,27 +101,20 @@ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
/*****************************************************************************
* vdec_DestroyThread: destroy a video decoder thread
*****************************************************************************
* 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.
*****************************************************************************/
void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
void vdec_DestroyThread( vdec_thread_t *p_vdec )
{
intf_DbgMsg("vdec debug: requesting termination of video decoder thread %p", p_vdec);
/* Ask thread to kill itself */
p_vdec->b_die = 1;
#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
vlc_mutex_lock( &p_vdec->p_pool->lock );
vlc_cond_broadcast( &p_vdec->p_pool->wait_undecoded );
vlc_mutex_unlock( &p_vdec->p_pool->lock );
/* Waiting for the decoder thread to exit */
/* Remove this as soon as the "status" flag is implemented */
vlc_thread_join( p_vdec->thread_id );
}
......@@ -144,65 +124,28 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
* 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.
* initialization.
*****************************************************************************/
#ifdef VDEC_SMP
static int vdec_InitThread( vdec_thread_t *p_vdec )
#else
int vdec_InitThread( vdec_thread_t *p_vdec )
#endif
void vdec_InitThread( vdec_thread_t *p_vdec )
{
intf_DbgMsg("vdec debug: initializing video decoder thread %p", p_vdec);
p_vdec->p_idct_data = NULL;
p_vdec->pf_decode_init = p_vdec->p_vpar->pf_decode_init;
p_vdec->pf_decode_mb_c = p_vdec->p_vpar->pf_decode_mb_c;
p_vdec->pf_decode_mb_bw = p_vdec->p_vpar->pf_decode_mb_bw;
p_vdec->pf_decode_init( p_vdec );
#ifdef VDEC_SMP
/* Re-nice ourself */
if( nice(VDEC_NICE) == -1 )
{
intf_WarnMsg( 2, "vdec warning : couldn't nice() (%s)",
strerror(errno) );
}
#endif
p_vdec->p_pool->pf_decode_init( p_vdec );
p_vdec->p_pool->pf_idct_init( p_vdec );
/* Mark thread as running and return */
intf_DbgMsg("vdec debug: InitThread(%p) succeeded", p_vdec);
return( 0 );
}
/*****************************************************************************
* ErrorThread: RunThread() error loop
*****************************************************************************
* This function is called when an error occured during thread main's loop. The
* thread can still receive feed, but must be ready to terminate as soon as
* possible.
*****************************************************************************/
static void ErrorThread( vdec_thread_t *p_vdec )
{
macroblock_t * p_mb;
/* Wait until a `die' order */
while( !p_vdec->b_die )
{
p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo );
vpar_DestroyMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
}
}
/*****************************************************************************
* EndThread: thread destruction
* vdec_EndThread: thread destruction
*****************************************************************************
* This function is called when the thread ends after a sucessful
* initialization.
*****************************************************************************/
static void EndThread( vdec_thread_t *p_vdec )
void vdec_EndThread( vdec_thread_t *p_vdec )
{
intf_DbgMsg("vdec debug: EndThread(%p)", p_vdec);
......@@ -210,6 +153,8 @@ static void EndThread( vdec_thread_t *p_vdec )
{
free( p_vdec->p_idct_data );
}
free( p_vdec );
}
/*****************************************************************************
......@@ -223,44 +168,26 @@ static void RunThread( vdec_thread_t *p_vdec )
intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)",
p_vdec, getpid());
/*
* Initialize thread and free configuration
*/
p_vdec->b_error = vdec_InitThread( p_vdec );
if( p_vdec->b_error )
{
return;