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) \
* 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
* 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
* 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>
*
/* 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 */
stream_ctrl_t control;
} stream_descriptor_t;
+#define MUTE_NO_CHANGE -1
+
/*****************************************************************************
* i_p_config_t
*****************************************************************************
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 );
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 );
* 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>
*
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
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 );
(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; \
# 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)
* 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>
*
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 : */
* 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>
#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
*****************************************************************************/
* 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>
*
*****************************************************************************/
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;
* 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>
*
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
* 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>
*
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 */
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;
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 );
* 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>
*
/* 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;
* 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>
*
/*****************************************************************************
* 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 );
+ }
}
}
}
* 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>
*
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
*****************************************************************************/
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;
+}
+
* 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>
*
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++ )
{
* 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>
#define OPT_COLOR 164
#define OPT_FULLSCREEN 165
#define OPT_OVERLAY 166
+#define OPT_SMP 167
#define OPT_CHANNELS 170
#define OPT_SERVER 171
{ "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' },
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':
"\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"
"\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:"
* 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>
* Gaël Hendryckx <jimmy@via.ecp.fr>
#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;
* 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",
/*****************************************************************************
* 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 );
}
* 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);
{
free( p_vdec->p_idct_data );
}
+
+ free( 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;
- }
- p_vdec->b_run = 1;
+ vdec_InitThread( p_vdec );
/*
- * Main loop - it is not executed if an error occured during
- * initialization
+ * Main loop
*/
- while( (!p_vdec->b_die) && (!p_vdec->b_error) )
+ while( !p_vdec->b_die )
{
macroblock_t * p_mb;
- if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL )
+ if( (p_mb = vpar_GetMacroblock( p_vdec->p_pool, &p_vdec->b_die )) != NULL )
{
- p_vdec->pf_decode_mb_c( p_vdec, p_mb );
+ p_vdec->p_pool->pf_vdec_decode( p_vdec, p_mb );
/* Decoding is finished, release the macroblock and free
* unneeded memory. */
- vpar_ReleaseMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
+ p_vdec->p_pool->pf_free_mb( p_vdec->p_pool, p_mb );
}
}
- /*
- * Error loop
- */
- if( p_vdec->b_error )
- {
- ErrorThread( p_vdec );
- }
-
/* End of thread */
- EndThread( p_vdec );
- p_vdec->b_run = 0;
+ vdec_EndThread( p_vdec );
}
* video_decoder.h : video decoder thread
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_decoder.h,v 1.3 2001/07/17 09:48:08 massiot Exp $
+ * $Id: video_decoder.h,v 1.4 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
-/*****************************************************************************
- * Requires:
- * "config.h"
- * "common.h"
- * "mtime.h"
- * "threads.h"
- * "input.h"
- * "video.h"
- * "video_output.h"
- * "decoder_fifo.h"
- *****************************************************************************/
-
/*****************************************************************************
* Prototypes
*****************************************************************************/
struct macroblock_s;
/* Thread management functions */
-#ifndef VDEC_SMP
-int vdec_InitThread ( struct vdec_thread_s *p_vdec );
-#endif
+void vdec_InitThread ( struct vdec_thread_s *p_vdec );
+void vdec_EndThread ( struct vdec_thread_s *p_vdec );
void vdec_DecodeMacroblock ( struct vdec_thread_s *p_vdec,
struct macroblock_s *p_mb );
void vdec_DecodeMacroblockC ( struct vdec_thread_s *p_vdec,
struct macroblock_s *p_mb );
void vdec_DecodeMacroblockBW ( struct vdec_thread_s *p_vdec,
struct macroblock_s *p_mb );
-struct vdec_thread_s * vdec_CreateThread( struct vpar_thread_s *p_vpar );
+struct vdec_thread_s * vdec_CreateThread( struct vdec_pool_s * );
void vdec_DestroyThread ( struct vdec_thread_s *p_vdec );
+++ /dev/null
-/*****************************************************************************
- * video_fifo.c : video FIFO management
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_fifo.c,v 1.2 2001/07/17 09:48:08 massiot Exp $
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include "defs.h"
-
-#include <string.h> /* memcpy(), memset() */
-
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-
-#include "intf_msg.h"
-
-#include "stream_control.h"
-#include "input_ext-dec.h"
-
-#include "video.h"
-#include "video_output.h"
-
-#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"
-
-/*****************************************************************************
- * vpar_InitFIFO : initialize the video FIFO
- *****************************************************************************/
-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 );
- vlc_mutex_init( &p_vpar->vbuffer.lock );
-
- /* Initialize FIFO properties */
- p_vpar->vfifo.i_start = p_vpar->vfifo.i_end = 0;
-
- /* Initialize buffer properties */
- p_vpar->vbuffer.i_index = VFIFO_SIZE; /* all structures are available */
- for( i_dummy = 0; i_dummy < VFIFO_SIZE + 1; i_dummy++ )
- {
- p_vpar->vbuffer.pp_mb_free[i_dummy] = p_vpar->vbuffer.p_macroblocks
- + i_dummy;
- }
-#endif
-}
-
+++ /dev/null
-/*****************************************************************************
- * video_fifo.h : FIFO for the pool of video_decoders
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_fifo.h,v 1.6 2001/07/17 09:48:08 massiot Exp $
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Requires:
- * "config.h"
- * "common.h"
- * "threads.h"
- * "video_parser.h"
- * "undec_picture.h"
- *****************************************************************************/
-
-/*****************************************************************************
- * Macros
- *****************************************************************************/
-
-#ifdef VDEC_SMP
-/* FIXME: 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 )
-#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 );
- while( VIDEO_FIFO_ISEMPTY( *p_fifo ) )
- {
- vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
- if( p_fifo->p_vpar->p_fifo->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 );
-#else
- /* Shouldn't normally be used without SMP. */
- return NULL;
-#endif
-}
-
-/*****************************************************************************
- * vpar_NewMacroblock : return a buffer for the parser
- *****************************************************************************/
-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
- 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");
- vlc_mutex_unlock( &P_buffer.lock );
- if( p_fifo->p_vpar->p_fifo->b_die )
- {
- return( NULL );
- }
- msleep(VPAR_OUTMEM_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 );
-#else
- return( &p_fifo->buffer );
-#endif
-}
-
-/*****************************************************************************
- * 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 )
-{
-#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 == 1);
- vlc_mutex_unlock( &p_mb->p_picture->lock_deccount );
-//intf_DbgMsg( "%d ", p_mb->p_picture->i_deccount );
- /* Test if it was the last block of the picture */
- if( b_finished )
- {
-//intf_DbgMsg( "Image decodee" );
- /* 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, 0 );
-
- /* 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
-
-#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, 0 );
- }
-#endif
-}
-
-/*****************************************************************************
- * vpar_DecodeMacroblock : put a macroblock in the video 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 );
-
- /* 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 );
-#else
- p_fifo->p_vpar->pf_decode_mb_c( p_fifo->p_vpar->pp_vdec[0], p_mb );
- vpar_ReleaseMacroblock( &p_fifo->p_vpar->vfifo, p_mb );
-#endif
-}
-
-/*****************************************************************************
- * vpar_DestroyMacroblock : destroy a macroblock in case of error
- *****************************************************************************/
-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 == 1);
- vlc_mutex_unlock( &p_mb->p_picture->lock_deccount );
-
- /* Test if it was the last block of the picture */
- if( b_finished )
- {
- intf_DbgMsg( "Image trashee" );
- /* 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, 1 );
-
- /* 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
-
-#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, 1 );
- }
-#endif
-}
-
-/*****************************************************************************
- * vpar_FreeMacroblock : destroy a macroblock in case of error, without
- * updating the macroblock counters
- *****************************************************************************/
-static __inline__ void vpar_FreeMacroblock( video_fifo_t * p_fifo,
- macroblock_t * p_mb )
-{
-#ifdef VDEC_SMP
- /* 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
-
-#else
- ;
-#endif
-}
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-void vpar_InitFIFO( struct vpar_thread_s * p_vpar );
* video_parser.c : video parser thread
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_parser.c,v 1.2 2001/07/17 09:48:08 massiot Exp $
+ * $Id: video_parser.c,v 1.3 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
#include "video_output.h"
#include "vdec_ext-plugins.h"
-#include "video_decoder.h"
-
-#include "vpar_blocks.h"
-#include "vpar_headers.h"
-#include "vpar_synchro.h"
+#include "vpar_pool.h"
#include "video_parser.h"
-#include "video_fifo.h"
/*
* Local prototypes
p_vpar->p_config = p_config;
p_vpar->p_vout = NULL;
+ /* Spawn the video parser thread */
+ if ( vlc_thread_create( &p_vpar->thread_id, "video parser",
+ (vlc_thread_func_t)RunThread, (void *)p_vpar ) )
+ {
+ intf_ErrMsg("vpar error: can't spawn video parser thread");
+ module_Unneed( p_vpar->p_idct_module );
+ module_Unneed( p_vpar->p_motion_module );
+ free( p_vpar );
+ return( 0 );
+ }
+
+ intf_DbgMsg("vpar debug: video parser thread (%p) created", p_vpar);
+ return( p_vpar->thread_id );
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * InitThread: initialize vpar output 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( vpar_thread_t *p_vpar )
+{
+ intf_DbgMsg("vpar debug: initializing video parser thread %p", p_vpar);
+
/*
* Choose the best motion compensation module
*/
#undef S
#undef M
- /*
- * Choose the best IDCT module
- */
+ /*
+ * Choose the best IDCT module
+ */
p_vpar->p_idct_module = module_Need( MODULE_CAPABILITY_IDCT, NULL );
if( p_vpar->p_idct_module == NULL )
}
#define f p_vpar->p_idct_module->p_functions->idct.functions.idct
- p_vpar->pf_idct_init = f.pf_idct_init;
+ p_vpar->pool.pf_idct_init = f.pf_idct_init;
p_vpar->pf_sparse_idct = f.pf_sparse_idct;
p_vpar->pf_idct = f.pf_idct;
p_vpar->pf_norm_scan = f.pf_norm_scan;
- p_vpar->pf_decode_init = f.pf_decode_init;
+ p_vpar->pool.pf_decode_init = f.pf_decode_init;
p_vpar->pf_decode_mb_c = f.pf_decode_mb_c;
p_vpar->pf_decode_mb_bw = f.pf_decode_mb_bw;
#undef f
- /* Spawn the video parser thread */
- if ( vlc_thread_create( &p_vpar->thread_id, "video parser",
- (vlc_thread_func_t)RunThread, (void *)p_vpar ) )
- {
- intf_ErrMsg("vpar error: can't spawn video parser thread");
- module_Unneed( p_vpar->p_idct_module );
- module_Unneed( p_vpar->p_motion_module );
- free( p_vpar );
- return( 0 );
- }
-
- intf_DbgMsg("vpar debug: video parser thread (%p) created", p_vpar);
- return( p_vpar->thread_id );
-}
-
-/* following functions are local */
-
-/*****************************************************************************
- * InitThread: initialize vpar output 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( vpar_thread_t *p_vpar )
-{
-#ifdef VDEC_SMP
- int i_dummy;
-#endif
-
- intf_DbgMsg("vpar debug: initializing video parser thread %p", p_vpar);
-
+ /* Initialize input bitstream */
p_vpar->p_config->decoder_config.pf_init_bit_stream( &p_vpar->bit_stream,
p_vpar->p_config->decoder_config.p_decoder_fifo, BitstreamCallback,
(void *)p_vpar );
sizeof(p_vpar->pc_malformed_pictures));
#endif
- /* Initialize video FIFO */
- vpar_InitFIFO( p_vpar );
-
- memset( p_vpar->pp_vdec, 0, NB_VDEC*sizeof(vdec_thread_t *) );
-
-#ifdef VDEC_SMP
- /* Spawn video_decoder threads */
- /* FIXME: modify the number of vdecs at runtime ?? */
- for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
- {
- if( (p_vpar->pp_vdec[i_dummy] = vdec_CreateThread( p_vpar )) == NULL )
- {
- return( 1 );
- }
- }
-#else
- /* Fake a video_decoder thread */
- p_vpar->pp_vdec[0] = (vdec_thread_t *)malloc(sizeof( vdec_thread_t ));
-
- if( p_vpar->pp_vdec[0] == NULL )
- {
- 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;
-
- if( vdec_InitThread( p_vpar->pp_vdec[0] ) )
- {
- return( 1 );
- }
-
-# if !defined(SYS_BEOS) && !defined(WIN32)
-# if VDEC_NICE
- /* Re-nice ourself */
- if( nice(VDEC_NICE) == -1 )
- {
- intf_WarnMsg( 2, "vpar warning : couldn't nice() (%s)",
- strerror(errno) );
- }
-# endif
-# endif
-#endif
-
/* Initialize lookup tables */
vpar_InitMbAddrInc( p_vpar );
vpar_InitDCTTables( p_vpar );
*/
vpar_SynchroInit( p_vpar );
+ /* Spawn optional video decoder threads */
+ vpar_InitPool( p_vpar );
+
/* Mark thread as running and return */
intf_DbgMsg("vpar debug: InitThread(%p) succeeded", p_vpar);
return( 0 );
{
/* End of sequence */
break;
- };
+ }
}
}
*****************************************************************************/
static void EndThread( vpar_thread_t *p_vpar )
{
-#ifdef VDEC_SMP
- int i_dummy;
-#endif
-
intf_DbgMsg("vpar debug: destroying video parser thread %p", p_vpar);
/* Release used video buffers. */
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->pp_vdec[i_dummy] != NULL )
- vdec_DestroyThread( p_vpar->pp_vdec[i_dummy] );
- else
- break;
- }
-#else
- free( p_vpar->pp_vdec[0] );
-#endif
+ vpar_EndPool( p_vpar );
free( p_vpar->p_config );
-#ifdef VDEC_SMP
- /* Destroy lock and cond */
- vlc_mutex_destroy( &(p_vpar->vbuffer.lock) );
- vlc_cond_destroy( &(p_vpar->vfifo.wait) );
- vlc_mutex_destroy( &(p_vpar->vfifo.lock) );
-#endif
-
- vlc_mutex_destroy( &(p_vpar->synchro.fifo_lock) );
-
module_Unneed( p_vpar->p_idct_module );
module_Unneed( p_vpar->p_motion_module );
* video_parser.h : video parser thread
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_parser.h,v 1.10 2001/07/17 09:48:08 massiot Exp $
+ * $Id: video_parser.h,v 1.11 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Jean-Marc Dressler <polux@via.ecp.fr>
+ * Stéphane Borel <stef@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
+/*
+ * Block parsing structures
+ */
+
/*****************************************************************************
- * Requires:
- * "config.h"
- * "common.h"
- * "mtime.h"
- * "threads.h"
- * "input.h"
- * "video.h"
- * "video_output.h"
- * "decoder_fifo.h"
- * "video_fifo.h"
- * "vpar_headers.h"
+ * macroblock_parsing_t : macroblock context & predictors
*****************************************************************************/
+typedef struct
+{
+ unsigned char i_quantizer_scale; /* scale of the quantization
+ * matrices */
+ int pi_dc_dct_pred[3]; /* ISO/IEC 13818-2 7.2.1 */
+ int pppi_pmv[2][2][2]; /* Motion vect predictors, 7.6.3 */
+ int i_motion_dir;/* Used for the next skipped macroblock */
+
+ /* Context used to optimize block parsing */
+ int i_motion_type, i_mv_count, i_mv_format;
+ boolean_t b_dmv, b_dct_type;
+
+ /* Coordinates of the upper-left pixel of the macroblock, in lum and
+ * chroma */
+ int i_l_x, i_l_y, i_c_x, i_c_y;
+} macroblock_parsing_t;
/*****************************************************************************
- * video_fifo_t
- *****************************************************************************
- * This rotative FIFO contains undecoded macroblocks that are to be decoded
+ * lookup_t : entry type for lookup tables *
*****************************************************************************/
-struct vpar_thread_s;
+typedef struct lookup_s
+{
+ int i_value;
+ int i_length;
+} lookup_t;
-typedef struct video_fifo_s
+/*****************************************************************************
+ * ac_lookup_t : special entry type for lookup tables about ac coefficients
+ *****************************************************************************/
+typedef struct dct_lookup_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;
-#else
- macroblock_t buffer;
+ char i_run;
+ char i_level;
+ char i_length;
+} dct_lookup_t;
+
+/*****************************************************************************
+ * Standard codes
+ *****************************************************************************/
+
+/* Macroblock Address Increment types */
+#define MB_ADDRINC_ESCAPE 8
+#define MB_ADDRINC_STUFFING 15
+
+/* Error constant for lookup tables */
+#define MB_ERROR (-1)
+
+/* Scan */
+#define SCAN_ZIGZAG 0
+#define SCAN_ALT 1
+
+/* Constant for block decoding */
+#define DCT_EOB 64
+#define DCT_ESCAPE 65
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+extern u8 pi_default_intra_quant[64];
+extern u8 pi_default_nonintra_quant[64];
+extern u8 pi_scan[2][64];
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vpar_InitCrop( struct vpar_thread_s* p_vpar );
+void vpar_InitMbAddrInc( struct vpar_thread_s * p_vpar );
+void vpar_InitPMBType( struct vpar_thread_s * p_vpar );
+void vpar_InitBMBType( struct vpar_thread_s * p_vpar );
+void vpar_InitCodedPattern( struct vpar_thread_s * p_vpar );
+void vpar_InitDCTTables( struct vpar_thread_s * p_vpar );
+void vpar_InitScanTable( struct vpar_thread_s * p_vpar );
+
+typedef void (*f_picture_data_t)( struct vpar_thread_s * p_vpar,
+ int i_mb_base );
+#define PROTO_PICD( FUNCNAME ) \
+void FUNCNAME( struct vpar_thread_s * p_vpar, int i_mb_base );
+
+PROTO_PICD( vpar_PictureDataGENERIC )
+#if (VPAR_OPTIM_LEVEL > 0)
+PROTO_PICD( vpar_PictureData1I )
+PROTO_PICD( vpar_PictureData1P )
+PROTO_PICD( vpar_PictureData1B )
+PROTO_PICD( vpar_PictureData1D )
+PROTO_PICD( vpar_PictureData2IF )
+PROTO_PICD( vpar_PictureData2PF )
+PROTO_PICD( vpar_PictureData2BF )
#endif
+#if (VPAR_OPTIM_LEVEL > 1)
+PROTO_PICD( vpar_PictureData2IT )
+PROTO_PICD( vpar_PictureData2PT )
+PROTO_PICD( vpar_PictureData2BT )
+PROTO_PICD( vpar_PictureData2IB )
+PROTO_PICD( vpar_PictureData2PB )
+PROTO_PICD( vpar_PictureData2BB )
+#endif
+
- struct vpar_thread_s * p_vpar;
-} video_fifo_t;
+/*
+ * Headers parsing structures
+ */
+
+/*****************************************************************************
+ * quant_matrix_t : Quantization Matrix
+ *****************************************************************************/
+typedef struct quant_matrix_s
+{
+ u8 * pi_matrix;
+ boolean_t b_allocated;
+ /* Has the matrix been allocated by vpar_headers ? */
+} quant_matrix_t;
/*****************************************************************************
- * video_buffer_t
+ * sequence_t : sequence descriptor
*****************************************************************************
- * This structure enables the parser to maintain a list of free
- * macroblock_t structures
+ * This structure should only be changed when reading the sequence header,
+ * or exceptionnally some extension structures (like quant_matrix).
*****************************************************************************/
-#ifdef VDEC_SMP
-typedef struct video_buffer_s
+typedef struct sequence_s
{
- vlc_mutex_t lock; /* buffer data lock */
+ u32 i_height, i_width; /* height and width of the lum
+ * comp of the picture */
+ u32 i_size; /* total number of pel of the lum comp */
+ u32 i_mb_height, i_mb_width, i_mb_size;
+ /* the same, in macroblock units */
+ unsigned int i_aspect_ratio; /* height/width display ratio */
+ unsigned int i_matrix_coefficients;/* coeffs of the YUV transform */
+ int i_frame_rate; /* theoritical frame rate in fps*1001 */
+ boolean_t b_mpeg2; /* guess */
+ boolean_t b_progressive; /* progressive (ie.
+ * non-interlaced) frame */
+ unsigned int i_scalable_mode; /* scalability ; unsupported, but
+ * modifies the syntax of the binary
+ * stream. */
+ quant_matrix_t intra_quant, nonintra_quant;
+ quant_matrix_t chroma_intra_quant, chroma_nonintra_quant;
+ /* current quantization matrices */
+
+ /* Chromatic information */
+ unsigned int i_chroma_format; /* see CHROMA_* below */
+ int i_chroma_nb_blocks; /* number of chroma blocks */
+ u32 i_chroma_width;/* width of a line of the chroma comp */
+ u32 i_chroma_mb_width, i_chroma_mb_height;
+ /* size of a macroblock in the chroma buffer
+ * (eg. 8x8 or 8x16 or 16x16) */
+
+ /* Parser context */
+ picture_t * p_forward; /* current forward reference frame */
+ picture_t * p_backward; /* current backward reference frame */
+ mtime_t next_pts, next_dts;
+ int i_current_rate;
+ boolean_t b_expect_discontinuity; /* reset the frame predictors
+ * after the current frame */
+
+ /* Copyright extension */
+ boolean_t b_copyright_flag; /* Whether the following
+ information is significant
+ or not. */
+ u8 i_copyright_id;
+ boolean_t b_original;
+ u64 i_copyright_nb;
+} sequence_t;
- 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;
+/*****************************************************************************
+ * picture_parsing_t : parser context descriptor
+ *****************************************************************************
+ * This structure should only be changed when reading the picture header.
+ *****************************************************************************/
+typedef struct picture_parsing_s
+{
+ /* ISO/CEI 11172-2 backward compatibility */
+ boolean_t pb_full_pel_vector[2];
+ int i_forward_f_code, i_backward_f_code;
+
+ /* Values from the picture_coding_extension. Please refer to ISO/IEC
+ * 13818-2. */
+ int ppi_f_code[2][2];
+ int i_intra_dc_precision;
+ boolean_t b_frame_pred_frame_dct, b_q_scale_type;
+ boolean_t b_intra_vlc_format;
+ boolean_t b_alternate_scan, b_progressive;
+ boolean_t b_top_field_first, b_concealment_mv;
+ boolean_t b_repeat_first_field;
+ /* Relative to the current field */
+ int i_coding_type, i_structure;
+ boolean_t b_frame_structure; /* i_structure == FRAME_STRUCTURE */
+
+ picture_t * p_picture; /* picture buffer from vout */
+ int i_current_structure; /* current parsed structure of
+ * p_picture (second field ?) */
+ boolean_t b_error; /* parsing error, try to recover */
+
+ int i_l_stride, i_c_stride;
+ /* number of coeffs to jump when changing
+ * lines (different with field pictures) */
+} picture_parsing_t;
+
+/*****************************************************************************
+ * Standard codes
+ *****************************************************************************/
+#define PICTURE_START_CODE 0x100L
+#define SLICE_START_CODE_MIN 0x101L
+#define SLICE_START_CODE_MAX 0x1AFL
+#define USER_DATA_START_CODE 0x1B2L
+#define SEQUENCE_HEADER_CODE 0x1B3L
+#define SEQUENCE_ERROR_CODE 0x1B4L
+#define EXTENSION_START_CODE 0x1B5L
+#define SEQUENCE_END_CODE 0x1B7L
+#define GROUP_START_CODE 0x1B8L
+
+/* extension start code IDs */
+#define SEQUENCE_EXTENSION_ID 1
+#define SEQUENCE_DISPLAY_EXTENSION_ID 2
+#define QUANT_MATRIX_EXTENSION_ID 3
+#define COPYRIGHT_EXTENSION_ID 4
+#define SEQUENCE_SCALABLE_EXTENSION_ID 5
+#define PICTURE_DISPLAY_EXTENSION_ID 7
+#define PICTURE_CODING_EXTENSION_ID 8
+#define PICTURE_SPATIAL_SCALABLE_EXTENSION_ID 9
+#define PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID 10
+
+/* scalable modes */
+#define SC_NONE 0
+#define SC_DP 1
+#define SC_SPAT 2
+#define SC_SNR 3
+#define SC_TEMP 4
+
+/* Chroma types */
+#define CHROMA_420 1
+#define CHROMA_422 2
+#define CHROMA_444 3
+
+/* 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 */
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+int vpar_NextSequenceHeader( struct vpar_thread_s * p_vpar );
+int vpar_ParseHeader( struct vpar_thread_s * p_vpar );
+
+
+/*
+ * Synchronization management
+ */
+
+/*****************************************************************************
+ * video_synchro_t : timers for the video synchro
+ *****************************************************************************/
+#define MAX_PIC_AVERAGE 8
+
+/* Read the discussion on top of vpar_synchro.c for more information. */
+typedef struct video_synchro_s
+{
+ /* synchro algorithm */
+ int i_type;
+
+ /* date of the beginning of the decoding of the current picture */
+ mtime_t decoding_start;
+
+ /* stream properties */
+ unsigned int i_n_p, i_n_b;
+
+ /* decoding values */
+ mtime_t p_tau[4]; /* average decoding durations */
+ unsigned int pi_meaningful[4]; /* number of durations read */
+ /* and p_vout->render_time (read with p_vout->change_lock) */
+
+ /* stream context */
+ unsigned int i_eta_p, i_eta_b;
+ boolean_t b_dropped_last; /* for special synchros below */
+ mtime_t backward_pts, current_pts;
+ int i_current_period; /* period to add to the next picture */
+ int i_backward_period; /* period to add after the next
+ * reference picture
+ * (backward_period * period / 2) */
+
+#ifdef STATS
+ unsigned int i_trashed_pic, i_not_chosen_pic, i_pic;
#endif
+} video_synchro_t;
+
+/* Synchro algorithms */
+#define VPAR_SYNCHRO_DEFAULT 0
+#define VPAR_SYNCHRO_I 1
+#define VPAR_SYNCHRO_Iplus 2
+#define VPAR_SYNCHRO_IP 3
+#define VPAR_SYNCHRO_IPplus 4
+#define VPAR_SYNCHRO_IPB 5
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vpar_SynchroInit ( struct vpar_thread_s * p_vpar );
+boolean_t vpar_SynchroChoose ( struct vpar_thread_s * p_vpar,
+ int i_coding_type, int i_structure );
+void vpar_SynchroTrash ( struct vpar_thread_s * p_vpar,
+ int i_coding_type, int i_structure );
+void vpar_SynchroDecode ( struct vpar_thread_s * p_vpar,
+ int i_coding_type, int i_structure );
+void vpar_SynchroEnd ( struct vpar_thread_s * p_vpar,
+ int i_coding_type, int i_structure,
+ int i_garbage );
+mtime_t vpar_SynchroDate ( struct vpar_thread_s * p_vpar );
+void vpar_SynchroNewPicture( struct vpar_thread_s * p_vpar, int i_coding_type,
+ int i_repeat_field );
+
+
+/*
+ * Video parser structures
+ */
/*****************************************************************************
* vpar_thread_t: video parser thread descriptor
- *****************************************************************************
- * XXX??
*****************************************************************************/
typedef struct vpar_thread_s
{
- bit_stream_t bit_stream;
+ bit_stream_t bit_stream;
/* Thread properties and locks */
- vlc_thread_t thread_id; /* id for thread functions */
+ vlc_thread_t thread_id; /* id for thread functions */
/* Input properties */
- decoder_fifo_t * p_fifo; /* PES input fifo */
- vdec_config_t * p_config;
+ decoder_fifo_t * p_fifo; /* PES input fifo */
+ vdec_config_t * p_config;
/* Output properties */
- vout_thread_t * p_vout; /* video output thread */
+ vout_thread_t * p_vout; /* video output thread */
/* Decoder properties */
- struct vdec_thread_s * pp_vdec[NB_VDEC];
- video_fifo_t vfifo;
-#ifdef VDEC_SMP
- video_buffer_t vbuffer;
-#endif
+ vdec_pool_t pool;
/* Parser properties */
sequence_t sequence;
macroblock_parsing_t mb;
video_synchro_t synchro;
- /* Lookup tables */
- lookup_t pl_mb_addr_inc[2048]; /* for macroblock
- address increment */
+ /*
+ * Lookup tables
+ */
+ /* table for macroblock address increment */
+ lookup_t pl_mb_addr_inc[2048];
/* tables for macroblock types 0=P 1=B */
lookup_t ppl_mb_type[2][64];
/* table for coded_block_pattern */
u8 pi_default_intra_quant[64];
u8 pi_default_nonintra_quant[64];
- /* Motion compensation plugin used and shortcuts */
+ /* Motion compensation plug-in used and shortcuts */
struct module_s * p_motion_module;
void ( * pppf_motion[4][2][4] ) ( struct macroblock_s * );
void ( * ppf_motion_skipped[4][4] ) ( struct macroblock_s * );
- /* IDCT plugin used and shortcuts to access its capabilities */
+ /* IDCT plugin used and shortcuts */
struct module_s * p_idct_module;
- void ( * pf_idct_init ) ( struct vdec_thread_s * );
void ( * pf_sparse_idct ) ( void *, dctelem_t*, int );
void ( * pf_idct ) ( void *, dctelem_t*, int );
void ( * pf_norm_scan ) ( u8 ppi_scan[2][64] );
- 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 * );
* Prototypes
*****************************************************************************/
-/* Thread management functions */
+/* Thread management functions - temporary ! */
vlc_thread_t vpar_CreateThread ( vdec_config_t * );
/*****************************************************************************
* vpar_blocks.c : blocks parsing
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_blocks.c,v 1.2 2001/07/17 09:48:08 massiot Exp $
+ * $Id: vpar_blocks.c,v 1.3 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Jean-Marc Dressler <polux@via.ecp.fr>
#include "video_output.h"
#include "vdec_ext-plugins.h"
-#include "video_decoder.h"
-
-#include "vpar_blocks.h"
-#include "vpar_headers.h"
-#include "vpar_synchro.h"
+#include "vpar_pool.h"
#include "video_parser.h"
-#include "video_fifo.h"
/*
* Welcome to vpar_blocks.c ! Here's where the heavy processor-critical parsing
return;
}
- if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
- {
- /* b_die == 1 */
- return;
- }
-#ifdef VDEC_SMP
- p_vpar->picture.pp_mb[i_mb_base + i_mb] = p_mb;
-#endif
+ p_mb = p_vpar->pool.pf_new_mb( &p_vpar->pool );
InitMacroblock( p_vpar, p_mb, i_coding_type, i_structure );
UpdateContext( p_vpar, i_structure );
-#ifndef VDEC_SMP
/* Decode the macroblock NOW ! */
- vpar_DecodeMacroblock ( &p_vpar->vfifo, p_mb );
-#endif
+ p_vpar->pool.pf_decode_mb( &p_vpar->pool, p_mb );
}
/*****************************************************************************
if( p_vpar->picture.b_error ) \
{ \
/* Go to the next slice. */ \
- vpar_FreeMacroblock( &p_vpar->vfifo, p_mb ); \
+ p_vpar->pool.pf_free_mb( &p_vpar->pool, p_mb ); \
return; \
}
}
/* Get a macroblock structure. */
- if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
- {
- /* b_die == 1 */
- return;
- }
-#ifdef VDEC_SMP
- p_vpar->picture.pp_mb[i_mb_base + *pi_mb_address] = p_mb;
-#endif
+ p_mb = p_vpar->pool.pf_new_mb( &p_vpar->pool );
InitMacroblock( p_vpar, p_mb, i_coding_type, i_structure );
* Effectively decode blocks.
*/
if( b_mpeg2 )
+ {
DecodeMPEG2IntraMB( p_vpar, p_mb );
+ }
else
+ {
DecodeMPEG1IntraMB( p_vpar, p_mb );
+ }
PARSEERROR
}
if( !p_vpar->picture.b_error )
{
UpdateContext( p_vpar, i_structure );
-#ifndef VDEC_SMP
+
/* Decode the macroblock NOW ! */
- vpar_DecodeMacroblock ( &p_vpar->vfifo, p_mb );
-#endif
+ p_vpar->pool.pf_decode_mb( &p_vpar->pool, p_mb );
}
else
{
/* Go to the next slice. */
- vpar_FreeMacroblock( &p_vpar->vfifo, p_mb );
+ p_vpar->pool.pf_free_mb( &p_vpar->pool, p_mb );
}
}
}
#if 0
- /* Buggy */
+ /* BUGGY */
/* Try to recover from error. If we missed less than half the
* number of macroblocks of the picture, mark the missed ones
* as skipped. */
+++ /dev/null
-/*****************************************************************************
- * vpar_blocks.h : video parser blocks management
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_blocks.h,v 1.4 2001/07/17 09:48:08 massiot Exp $
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- * Jean-Marc Dressler <polux@via.ecp.fr>
- * Stéphane Borel <stef@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Requires:
- * "config.h"
- * "common.h"
- * "mtime.h"
- * "threads.h"
- * "input.h"
- * "video.h"
- * "video_output.h"
- * "decoder_fifo.h"
- * "video_fifo.h"
- *****************************************************************************/
-
-/*****************************************************************************
- * macroblock_parsing_t : macroblock context & predictors
- *****************************************************************************/
-typedef struct
-{
- unsigned char i_quantizer_scale; /* scale of the quantization
- * matrices */
- int pi_dc_dct_pred[3]; /* ISO/IEC 13818-2 7.2.1 */
- int pppi_pmv[2][2][2]; /* Motion vect predictors, 7.6.3 */
- int i_motion_dir;/* Used for the next skipped macroblock */
-
- /* Context used to optimize block parsing */
- int i_motion_type, i_mv_count, i_mv_format;
- boolean_t b_dmv, b_dct_type;
-
- /* Coordinates of the upper-left pixel of the macroblock, in lum and
- * chroma */
- int i_l_x, i_l_y, i_c_x, i_c_y;
-} macroblock_parsing_t;
-
-/*****************************************************************************
- * lookup_t : entry type for lookup tables *
- *****************************************************************************/
-typedef struct lookup_s
-{
- int i_value;
- int i_length;
-} lookup_t;
-
-/*****************************************************************************
- * ac_lookup_t : special entry type for lookup tables about ac coefficients
- *****************************************************************************/
-typedef struct dct_lookup_s
-{
- char i_run;
- char i_level;
- char i_length;
-} dct_lookup_t;
-
-/*****************************************************************************
- * Standard codes
- *****************************************************************************/
-
-/* Macroblock Address Increment types */
-#define MB_ADDRINC_ESCAPE 8
-#define MB_ADDRINC_STUFFING 15
-
-/* Error constant for lookup tables */
-#define MB_ERROR (-1)
-
-/* Scan */
-#define SCAN_ZIGZAG 0
-#define SCAN_ALT 1
-
-/* Constant for block decoding */
-#define DCT_EOB 64
-#define DCT_ESCAPE 65
-
-/*****************************************************************************
- * Constants
- *****************************************************************************/
-extern u8 pi_default_intra_quant[64];
-extern u8 pi_default_nonintra_quant[64];
-extern u8 pi_scan[2][64];
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-void vpar_InitCrop( struct vpar_thread_s* p_vpar );
-void vpar_InitMbAddrInc( struct vpar_thread_s * p_vpar );
-void vpar_InitPMBType( struct vpar_thread_s * p_vpar );
-void vpar_InitBMBType( struct vpar_thread_s * p_vpar );
-void vpar_InitCodedPattern( struct vpar_thread_s * p_vpar );
-void vpar_InitDCTTables( struct vpar_thread_s * p_vpar );
-void vpar_InitScanTable( struct vpar_thread_s * p_vpar );
-
-typedef void (*f_picture_data_t)( struct vpar_thread_s * p_vpar,
- int i_mb_base );
-#define PROTO_PICD( FUNCNAME ) \
-void FUNCNAME( struct vpar_thread_s * p_vpar, int i_mb_base );
-
-PROTO_PICD( vpar_PictureDataGENERIC )
-#if (VPAR_OPTIM_LEVEL > 0)
-PROTO_PICD( vpar_PictureData1I )
-PROTO_PICD( vpar_PictureData1P )
-PROTO_PICD( vpar_PictureData1B )
-PROTO_PICD( vpar_PictureData1D )
-PROTO_PICD( vpar_PictureData2IF )
-PROTO_PICD( vpar_PictureData2PF )
-PROTO_PICD( vpar_PictureData2BF )
-#endif
-#if (VPAR_OPTIM_LEVEL > 1)
-PROTO_PICD( vpar_PictureData2IT )
-PROTO_PICD( vpar_PictureData2PT )
-PROTO_PICD( vpar_PictureData2BT )
-PROTO_PICD( vpar_PictureData2IB )
-PROTO_PICD( vpar_PictureData2PB )
-PROTO_PICD( vpar_PictureData2BB )
-#endif
-
* vpar_headers.c : headers parsing
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_headers.c,v 1.2 2001/07/17 09:48:08 massiot Exp $
+ * $Id: vpar_headers.c,v 1.3 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Stéphane Borel <stef@via.ecp.fr>
#include "video_output.h"
#include "vdec_ext-plugins.h"
-#include "video_decoder.h"
-
-#include "vpar_blocks.h"
-#include "vpar_headers.h"
-#include "vpar_synchro.h"
+#include "vpar_pool.h"
#include "video_parser.h"
-#include "video_fifo.h"
/*
* Local prototypes
/* XXX: The vout request and fifo opening will eventually be here */
- /* Spawn an audio output if there is none */
+ /* Spawn a video output if there is none */
vlc_mutex_lock( &p_vout_bank->lock );
if( p_vout_bank->i_count == 0 )
ReferenceUpdate( p_vpar, I_CODING_TYPE, NULL );
if( p_vpar->picture.p_picture != NULL )
{
-#ifdef VDEC_SMP
- int i_mb;
-
- 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 );
}
p_vpar->sequence.b_expect_discontinuity = 0;
ReferenceReplace( 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 );
}
p_vpar->picture.i_c_stride = ( p_vpar->sequence.i_chroma_width
<< ( 1 - p_vpar->picture.b_frame_structure ));
- P_picture->i_deccount = p_vpar->sequence.i_mb_size;
-#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;
#endif
}
+ /* Wait for all the macroblocks to be decoded. */
+ p_vpar->pool.pf_wait_pool( &p_vpar->pool );
+
+ /* Re-spawn decoder threads if the user changed settings. */
+ vpar_SpawnPool( p_vpar );
+
if( p_vpar->p_fifo->b_die || p_vpar->p_fifo->b_error )
{
return;
if( p_vpar->picture.b_error )
{
/* Trash picture. */
-#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] );
- }
-#endif
-
#ifdef STATS
p_vpar->pc_malformed_pictures[p_vpar->picture.i_coding_type]++;
#endif
- if( P_picture->i_deccount != 1 )
- {
- vpar_SynchroEnd( p_vpar, 1 );
- vout_DestroyPicture( p_vpar->p_vout, P_picture );
- }
+ vpar_SynchroEnd( p_vpar, p_vpar->picture.i_coding_type,
+ p_vpar->picture.i_structure, 1 );
+ vout_DestroyPicture( p_vpar->p_vout, P_picture );
ReferenceReplace( p_vpar, p_vpar->picture.i_coding_type, NULL );
else if( p_vpar->picture.i_current_structure == FRAME_STRUCTURE )
{
/* 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] );
- }
-
- /* 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
+ vpar_SynchroEnd( p_vpar, p_vpar->picture.i_coding_type,
+ p_vpar->picture.i_structure, 0 );
+ vout_DisplayPicture( p_vpar->p_vout, P_picture );
/* Prepare context for the next picture. */
P_picture = NULL;
+++ /dev/null
-/*****************************************************************************
- * vpar_headers.h : video parser : headers parsing
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_headers.h,v 1.8 2001/07/17 09:48:08 massiot Exp $
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- * Stéphane Borel <stef@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Requires:
- * "config.h"
- * "common.h"
- * "mtime.h"
- * "threads.h"
- * "input.h"
- * "video.h"
- * "video_output.h"
- * "decoder_fifo.h"
- * "video_fifo.h"
- *****************************************************************************/
-
-/*****************************************************************************
- * quant_matrix_t : Quantization Matrix
- *****************************************************************************/
-typedef struct quant_matrix_s
-{
- u8 * pi_matrix;
- boolean_t b_allocated;
- /* Has the matrix been allocated by vpar_headers ? */
-} quant_matrix_t;
-
-/*****************************************************************************
- * sequence_t : sequence descriptor
- *****************************************************************************
- * This structure should only be changed when reading the sequence header,
- * or exceptionnally some extension structures (like quant_matrix).
- *****************************************************************************/
-typedef struct sequence_s
-{
- u32 i_height, i_width; /* height and width of the lum
- * comp of the picture */
- u32 i_size; /* total number of pel of the lum comp */
- u32 i_mb_height, i_mb_width, i_mb_size;
- /* the same, in macroblock units */
- unsigned int i_aspect_ratio; /* height/width display ratio */
- unsigned int i_matrix_coefficients;/* coeffs of the YUV transform */
- int i_frame_rate; /* theoritical frame rate in fps*1001 */
- boolean_t b_mpeg2; /* guess */
- boolean_t b_progressive; /* progressive (ie.
- * non-interlaced) frame */
- unsigned int i_scalable_mode; /* scalability ; unsupported, but
- * modifies the syntax of the binary
- * stream. */
- quant_matrix_t intra_quant, nonintra_quant;
- quant_matrix_t chroma_intra_quant, chroma_nonintra_quant;
- /* current quantization matrices */
-
- /* Chromatic information */
- unsigned int i_chroma_format; /* see CHROMA_* below */
- int i_chroma_nb_blocks; /* number of chroma blocks */
- u32 i_chroma_width;/* width of a line of the chroma comp */
- u32 i_chroma_mb_width, i_chroma_mb_height;
- /* size of a macroblock in the chroma buffer
- * (eg. 8x8 or 8x16 or 16x16) */
-
- /* Parser context */
- picture_t * p_forward; /* current forward reference frame */
- picture_t * p_backward; /* current backward reference frame */
- mtime_t next_pts, next_dts;
- int i_current_rate;
- boolean_t b_expect_discontinuity; /* reset the frame predictors
- * after the current frame */
-
- /* Copyright extension */
- boolean_t b_copyright_flag; /* Whether the following
- information is significant
- or not. */
- u8 i_copyright_id;
- boolean_t b_original;
- u64 i_copyright_nb;
-} sequence_t;
-
-/*****************************************************************************
- * picture_parsing_t : parser context descriptor
- *****************************************************************************
- * This structure should only be changed when reading the picture header.
- *****************************************************************************/
-typedef struct picture_parsing_s
-{
- /* ISO/CEI 11172-2 backward compatibility */
- boolean_t pb_full_pel_vector[2];
- int i_forward_f_code, i_backward_f_code;
-
- /* Values from the picture_coding_extension. Please refer to ISO/IEC
- * 13818-2. */
- int ppi_f_code[2][2];
- int i_intra_dc_precision;
- boolean_t b_frame_pred_frame_dct, b_q_scale_type;
- boolean_t b_intra_vlc_format;
- boolean_t b_alternate_scan, b_progressive;
- boolean_t b_top_field_first, b_concealment_mv;
- boolean_t b_repeat_first_field;
- /* Relative to the current field */
- int i_coding_type, i_structure;
- boolean_t b_frame_structure; /* i_structure == FRAME_STRUCTURE */
-
- picture_t * p_picture; /* picture buffer from vout */
- int i_current_structure; /* current parsed structure of
- * p_picture (second field ?) */
-#ifdef VDEC_SMP
- macroblock_t * pp_mb[MAX_MB]; /* macroblock buffer to
- * send to the vdec thread(s) */
-#endif
- boolean_t b_error; /* parsing error, try to recover */
-
- int i_l_stride, i_c_stride;
- /* number of coeffs to jump when changing
- * lines (different with field pictures) */
-} picture_parsing_t;
-
-/*****************************************************************************
- * Standard codes
- *****************************************************************************/
-#define PICTURE_START_CODE 0x100L
-#define SLICE_START_CODE_MIN 0x101L
-#define SLICE_START_CODE_MAX 0x1AFL
-#define USER_DATA_START_CODE 0x1B2L
-#define SEQUENCE_HEADER_CODE 0x1B3L
-#define SEQUENCE_ERROR_CODE 0x1B4L
-#define EXTENSION_START_CODE 0x1B5L
-#define SEQUENCE_END_CODE 0x1B7L
-#define GROUP_START_CODE 0x1B8L
-
-/* extension start code IDs */
-#define SEQUENCE_EXTENSION_ID 1
-#define SEQUENCE_DISPLAY_EXTENSION_ID 2
-#define QUANT_MATRIX_EXTENSION_ID 3
-#define COPYRIGHT_EXTENSION_ID 4
-#define SEQUENCE_SCALABLE_EXTENSION_ID 5
-#define PICTURE_DISPLAY_EXTENSION_ID 7
-#define PICTURE_CODING_EXTENSION_ID 8
-#define PICTURE_SPATIAL_SCALABLE_EXTENSION_ID 9
-#define PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID 10
-
-/* scalable modes */
-#define SC_NONE 0
-#define SC_DP 1
-#define SC_SPAT 2
-#define SC_SNR 3
-#define SC_TEMP 4
-
-/* Chroma types */
-#define CHROMA_420 1
-#define CHROMA_422 2
-#define CHROMA_444 3
-
-/* 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 */
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-int vpar_NextSequenceHeader( struct vpar_thread_s * p_vpar );
-int vpar_ParseHeader( struct vpar_thread_s * p_vpar );
--- /dev/null
+/*****************************************************************************
+ * vpar_pool.c : management of the pool of decoder threads
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: vpar_pool.c,v 1.1 2001/07/18 14:21:00 massiot Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "defs.h"
+
+#include <string.h> /* memcpy(), memset() */
+#include <stdlib.h> /* realloc() */
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h"
+
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
+#include "video.h"
+#include "video_output.h"
+
+#include "vdec_ext-plugins.h"
+#include "vpar_pool.h"
+#include "video_parser.h"
+#include "video_decoder.h"
+
+/*
+ * Local prototypes
+ */
+static void WaitDummy( vdec_pool_t * p_pool );
+static void WaitPool( vdec_pool_t * p_pool );
+static void FreeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb );
+static void FreeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb );
+static macroblock_t * NewMacroblockDummy( vdec_pool_t * p_pool );
+static macroblock_t * NewMacroblockPool( vdec_pool_t * p_pool );
+static void DecodeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb );
+static void DecodeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb );
+
+/*****************************************************************************
+ * vpar_InitPool: Initializes the pool structure
+ *****************************************************************************/
+void vpar_InitPool( vpar_thread_t * p_vpar )
+{
+ /* Initialize mutex and cond. */
+ vlc_mutex_init( &p_vpar->pool.lock );
+ vlc_cond_init( &p_vpar->pool.wait_empty );
+ vlc_cond_init( &p_vpar->pool.wait_undecoded );
+
+ /* Spawn optional video decoder threads. */
+ p_vpar->pool.i_smp = 0;
+ p_vpar->pool.pp_vdec = NULL;
+ p_vpar->pool.p_macroblocks = NULL;
+ p_vpar->pool.pp_empty_macroblocks = NULL;
+ p_vpar->pool.pp_new_macroblocks = NULL;
+ vpar_SpawnPool( p_vpar );
+
+ /* Initialize fake video decoder structure (used when
+ * decoder == parser). */
+ if ( (p_vpar->pool.p_vdec =
+ (vdec_thread_t *)malloc( sizeof(vdec_thread_t) )) == NULL )
+ {
+ intf_ErrMsg("vdec error: not enough memory for vdec_CreateThread() to create the new thread");
+ p_vpar->p_fifo->b_error = 1;
+ return;
+ }
+ p_vpar->pool.p_vdec->b_die = 0;
+ p_vpar->pool.p_vdec->p_pool = &p_vpar->pool;
+ vdec_InitThread( p_vpar->pool.p_vdec );
+}
+
+/*****************************************************************************
+ * vpar_SpawnPool: Create and cancel video decoder threads at any time
+ *****************************************************************************
+ * This function is called on startup, and everytime the user changes the
+ * number of threads to launch. Please note that *all* decoder threads must
+ * be idle during this operation, which only happens at the end of
+ * PictureHeader().
+ *****************************************************************************/
+void vpar_SpawnPool( vpar_thread_t * p_vpar )
+{
+ int i_new_smp;
+ boolean_t b_grayscale;
+ stream_ctrl_t * p_control;
+
+ p_control = p_vpar->p_config->decoder_config.p_stream_ctrl;
+ vlc_mutex_lock( &p_control->control_lock );
+ i_new_smp = p_control->i_smp;
+ b_grayscale = p_control->b_grayscale;
+ vlc_mutex_unlock( &p_control->control_lock );
+
+ /* FIXME: No error check because I'm tired. Come back later... */
+
+ /* No need to lock p_vpar->pool, since decoders MUST be idle here. */
+ if( p_vpar->pool.i_smp != i_new_smp )
+ {
+ int i;
+
+ if( p_vpar->pool.i_smp > i_new_smp )
+ {
+ /* The user reduces the number of threads. */
+
+ for( i = p_vpar->pool.i_smp - 1; i >= i_new_smp; i-- )
+ {
+ vdec_DestroyThread( p_vpar->pool.pp_vdec[i] );
+ }
+
+ p_vpar->pool.pp_vdec = realloc( p_vpar->pool.pp_vdec,
+ i_new_smp * sizeof(vdec_thread_t *) );
+ p_vpar->pool.p_macroblocks = realloc( p_vpar->pool.p_macroblocks,
+ i_new_smp * sizeof(macroblock_t) );
+ p_vpar->pool.pp_empty_macroblocks = realloc( p_vpar->pool.pp_empty_macroblocks,
+ i_new_smp * sizeof(macroblock_t *) );
+ p_vpar->pool.i_index_empty = i_new_smp;
+ p_vpar->pool.pp_new_macroblocks = realloc( p_vpar->pool.pp_new_macroblocks,
+ i_new_smp * sizeof(macroblock_t *) );
+ p_vpar->pool.i_index_new = 0;
+ }
+ else
+ {
+ /* The user raises the number of threads. */
+
+ p_vpar->pool.pp_vdec = realloc( p_vpar->pool.pp_vdec,
+ i_new_smp * sizeof(vdec_thread_t *) );
+ p_vpar->pool.p_macroblocks = realloc( p_vpar->pool.p_macroblocks,
+ i_new_smp * sizeof(macroblock_t) );
+ p_vpar->pool.pp_empty_macroblocks = realloc( p_vpar->pool.pp_empty_macroblocks,
+ i_new_smp * sizeof(macroblock_t *) );
+ p_vpar->pool.i_index_empty = i_new_smp;
+ p_vpar->pool.pp_new_macroblocks = realloc( p_vpar->pool.pp_new_macroblocks,
+ i_new_smp * sizeof(macroblock_t *) );
+ p_vpar->pool.i_index_new = 0;
+
+ for( i = p_vpar->pool.i_smp; i < i_new_smp ; i++ )
+ {
+ p_vpar->pool.pp_vdec[i] = vdec_CreateThread( &p_vpar->pool );
+ }
+
+ }
+ for( i = 0; i < i_new_smp; i++ )
+ {
+ p_vpar->pool.pp_empty_macroblocks[i] =
+ &p_vpar->pool.p_macroblocks[i];
+ }
+ p_vpar->pool.i_smp = i_new_smp;
+ }
+
+ if( i_new_smp )
+ {
+ /* We have at least one decoder thread. */
+ p_vpar->pool.pf_wait_pool = WaitPool;
+ p_vpar->pool.pf_new_mb = NewMacroblockPool;
+ p_vpar->pool.pf_free_mb = FreeMacroblockPool;
+ p_vpar->pool.pf_decode_mb = DecodeMacroblockPool;
+ }
+ else
+ {
+ /* No decoder pool. */
+ p_vpar->pool.pf_wait_pool = WaitDummy;
+ p_vpar->pool.pf_new_mb = NewMacroblockDummy;
+ p_vpar->pool.pf_free_mb = FreeMacroblockDummy;
+ p_vpar->pool.pf_decode_mb = DecodeMacroblockDummy;
+ }
+
+ if( !b_grayscale )
+ {
+ p_vpar->pool.pf_vdec_decode = p_vpar->pf_decode_mb_c;
+ }
+ else
+ {
+ p_vpar->pool.pf_vdec_decode = p_vpar->pf_decode_mb_bw;
+ }
+}
+
+/*****************************************************************************
+ * vpar_EndPool: Releases the pool structure
+ *****************************************************************************/
+void vpar_EndPool( vpar_thread_t * p_vpar )
+{
+ int i;
+
+ for( i = 0; i < p_vpar->pool.i_smp; i++ )
+ {
+ vdec_DestroyThread( p_vpar->pool.pp_vdec[i] );
+ }
+
+ if( p_vpar->pool.i_smp )
+ {
+ free( p_vpar->pool.pp_vdec );
+ free( p_vpar->pool.p_macroblocks );
+ free( p_vpar->pool.pp_new_macroblocks );
+ }
+
+ /* Free fake video decoder (used when parser == decoder). */
+ vdec_EndThread( p_vpar->pool.p_vdec );
+
+ /* Destroy lock and cond. */
+ vlc_mutex_destroy( &p_vpar->pool.lock );
+ vlc_cond_destroy( &p_vpar->pool.wait_empty );
+ vlc_cond_destroy( &p_vpar->pool.wait_undecoded );
+}
+
+/*****************************************************************************
+ * WaitPool: Wait until all decoders are idle
+ *****************************************************************************/
+static void WaitPool( vdec_pool_t * p_pool )
+{
+ vlc_mutex_lock( &p_pool->lock );
+ while( p_pool->i_index_empty != p_pool->i_smp )
+ {
+ vlc_cond_wait( &p_pool->wait_empty, &p_pool->lock );
+ }
+ vlc_mutex_unlock( &p_pool->lock );
+}
+
+/*****************************************************************************
+ * WaitDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static void WaitDummy( vdec_pool_t * p_pool )
+{
+}
+
+/*****************************************************************************
+ * NewMacroblockPool: Get an empty macroblock from the decoder pool
+ *****************************************************************************/
+static macroblock_t * NewMacroblockPool( vdec_pool_t * p_pool )
+{
+ macroblock_t * p_mb;
+
+ vlc_mutex_lock( &p_pool->lock );
+ while( p_pool->i_index_empty == 0 )
+ {
+ vlc_cond_wait( &p_pool->wait_empty, &p_pool->lock );
+ }
+ p_mb = p_pool->pp_empty_macroblocks[ --p_pool->i_index_empty ];
+ vlc_mutex_unlock( &p_pool->lock );
+ return( p_mb );
+}
+
+/*****************************************************************************
+ * NewMacroblockDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static macroblock_t * NewMacroblockDummy( vdec_pool_t * p_pool )
+{
+ return( &p_pool->mb );
+}
+
+/*****************************************************************************
+ * FreeMacroblockPool: Free a macroblock
+ *****************************************************************************/
+static void FreeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+ vlc_mutex_lock( &p_pool->lock );
+ p_pool->pp_empty_macroblocks[ p_pool->i_index_empty++ ] = p_mb;
+ vlc_cond_signal( &p_pool->wait_empty );
+ vlc_mutex_unlock( &p_pool->lock );
+}
+
+/*****************************************************************************
+ * FreeMacroblockDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static void FreeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+}
+
+/*****************************************************************************
+ * DecodeMacroblockPool: Send a macroblock to a vdec thread
+ *****************************************************************************/
+static void DecodeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+ vlc_mutex_lock( &p_pool->lock );
+ /* The undecoded macroblock LIFO cannot be full, because
+ * #macroblocks == size of the LIFO */
+ p_pool->pp_new_macroblocks[ p_pool->i_index_new++ ] = p_mb;
+ vlc_cond_signal( &p_pool->wait_undecoded );
+ vlc_mutex_unlock( &p_pool->lock );
+}
+
+/*****************************************************************************
+ * DecodeMacroblockDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static void DecodeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+ p_pool->pf_vdec_decode( p_pool->p_vdec, p_mb );
+}
+
--- /dev/null
+/*****************************************************************************
+ * vpar_pool.h : video parser/video decoders communication
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: vpar_pool.h,v 1.1 2001/07/18 14:21:00 massiot Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * vdec_pool_t
+ *****************************************************************************
+ * This structure is used for the communication between the parser and the
+ * decoders.
+ *****************************************************************************/
+typedef struct vdec_pool_s
+{
+ /* Locks */
+ vlc_mutex_t lock; /* Structure data lock */
+ vlc_cond_t wait_empty; /* The parser blocks there when all
+ * decoder threads are busy */
+ vlc_cond_t wait_undecoded; /* The decoders block there when no
+ * macroblock has been given by the
+ * parser */
+
+ /* Video decoder threads */
+ struct vdec_thread_s ** pp_vdec; /* Array of video decoder threads */
+ int i_smp; /* Number of symmetrical decoder threads,
+ * hence size of the pp_vdec, p_macroblocks
+ * and pp_new_macroblocks array */
+
+ /* Macroblocks */
+ macroblock_t * p_macroblocks;
+
+ /* Empty macroblocks */
+ macroblock_t ** pp_empty_macroblocks; /* Empty macroblocks */
+ int i_index_empty; /* Last empty macroblock */
+
+ /* Undecoded macroblocks, read by the decoders */
+ macroblock_t ** pp_new_macroblocks; /* Undecoded macroblocks */
+ int i_index_new; /* Last undecoded macroblock */
+
+ /* Undecoded macroblock, used when the parser and the decoder share the
+ * same thread */
+ macroblock_t mb;
+ struct vdec_thread_s * p_vdec; /* Fake video decoder */
+
+ /* Pointers to usual pool functions */
+ void (* pf_wait_pool) ( struct vdec_pool_s * );
+ macroblock_t * (* pf_new_mb) ( struct vdec_pool_s * );
+ void (* pf_free_mb) ( struct vdec_pool_s *,
+ struct macroblock_s * );
+ void (* pf_decode_mb) ( struct vdec_pool_s *,
+ struct macroblock_s * );
+
+ /* Pointer to the decoding function - used for B&W switching */
+ void (* pf_vdec_decode) ( struct vdec_thread_s *,
+ struct macroblock_s * );
+ boolean_t b_bw; /* Current value for B&W */
+
+ /* Access to the plug-ins needed by the video decoder thread */
+ void ( * pf_decode_init ) ( struct vdec_thread_s * );
+ void ( * pf_idct_init ) ( struct vdec_thread_s * );
+} vdec_pool_t;
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vpar_InitPool( struct vpar_thread_s * );
+void vpar_SpawnPool( struct vpar_thread_s * );
+void vpar_EndPool( struct vpar_thread_s * );
+
+/*****************************************************************************
+ * vpar_GetMacroblock: In a vdec thread, get the next available macroblock
+ *****************************************************************************/
+static __inline__ macroblock_t * vpar_GetMacroblock( vdec_pool_t * p_pool,
+ boolean_t * pb_die )
+{
+ macroblock_t * p_mb;
+
+ vlc_mutex_lock( &p_pool->lock );
+ while( p_pool->i_index_new == 0 && !*pb_die )
+ {
+ vlc_cond_wait( &p_pool->wait_undecoded, &p_pool->lock );
+ }
+
+ if( *pb_die )
+ {
+ vlc_mutex_unlock( &p_pool->lock );
+ return( NULL );
+ }
+
+ p_mb = p_pool->pp_new_macroblocks[ --p_pool->i_index_new ];
+ vlc_mutex_unlock( &p_pool->lock );
+ return( p_mb );
+}
+
* vpar_synchro.c : frame dropping routines
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_synchro.c,v 1.2 2001/07/17 09:48:08 massiot Exp $
+ * $Id: vpar_synchro.c,v 1.3 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
#include "video_output.h"
#include "vdec_ext-plugins.h"
-#include "video_decoder.h"
-
-#include "vpar_blocks.h"
-#include "vpar_headers.h"
-#include "vpar_synchro.h"
+#include "vpar_pool.h"
#include "video_parser.h"
#include "main.h"
void vpar_SynchroInit( vpar_thread_t * p_vpar )
{
p_vpar->synchro.i_type = SynchroType();
- p_vpar->synchro.i_start = p_vpar->synchro.i_end = 0;
- vlc_mutex_init( &p_vpar->synchro.fifo_lock );
/* We use a fake stream pattern, which is often right. */
p_vpar->synchro.i_n_p = p_vpar->synchro.i_eta_p = DEFAULT_NB_P;
vlc_mutex_lock( &p_vpar->p_vout->change_lock );
tau_yuv = p_vpar->p_vout->render_time;
vlc_mutex_unlock( &p_vpar->p_vout->change_lock );
-#ifdef VDEC_SMP
- vlc_mutex_lock( &p_vpar->synchro.fifo_lock );
-#endif
switch( i_coding_type )
{
}
}
-#ifdef VDEC_SMP
- vlc_mutex_unlock( &p_vpar->synchro.fifo_lock );
-#endif
#ifdef TRACE_VPAR
intf_DbgMsg("vpar synchro debug: %s picture scheduled for %s, %s (%lld)",
i_coding_type == B_CODING_TYPE ? "B" :
void vpar_SynchroDecode( vpar_thread_t * p_vpar, int i_coding_type,
int i_structure )
{
-#ifdef VDEC_SMP
- vlc_mutex_lock( &p_vpar->synchro.fifo_lock );
-#endif
-
- if( ((p_vpar->synchro.i_end + 1 - p_vpar->synchro.i_start)
- % MAX_DECODING_PIC) )
- {
- p_vpar->synchro.p_date_fifo[p_vpar->synchro.i_end] = mdate();
- p_vpar->synchro.pi_coding_types[p_vpar->synchro.i_end] = i_coding_type;
-
- FIFO_INCREMENT( i_end );
- }
- else
- {
- /* FIFO full, panic() */
- intf_ErrMsg("vpar error: synchro fifo full, estimations will be biased (%d:%d)",
- p_vpar->synchro.i_start, p_vpar->synchro.i_end);
- }
-#ifdef VDEC_SMP
- vlc_mutex_unlock( &p_vpar->synchro.fifo_lock );
-#endif
+ p_vpar->synchro.decoding_start = mdate();
}
/*****************************************************************************
* vpar_SynchroEnd : Called when the image is totally decoded
*****************************************************************************/
-void vpar_SynchroEnd( vpar_thread_t * p_vpar, int i_garbage )
+void vpar_SynchroEnd( vpar_thread_t * p_vpar, int i_coding_type,
+ int i_structure, int i_garbage )
{
mtime_t tau;
- int i_coding_type;
-
-#ifdef VDEC_SMP
- vlc_mutex_lock( &p_vpar->synchro.fifo_lock );
-#endif
-
- i_coding_type = p_vpar->synchro.pi_coding_types[p_vpar->synchro.i_start];
if( !i_garbage )
{
- tau = mdate() - p_vpar->synchro.p_date_fifo[p_vpar->synchro.i_start];
+ tau = mdate() - p_vpar->synchro.decoding_start;
/* If duration too high, something happened (pause ?), so don't
* take it into account. */
i_coding_type == B_CODING_TYPE ? "B" :
(i_coding_type == P_CODING_TYPE ? "P" : "I"));
}
-
- FIFO_INCREMENT( i_start );
-
-#ifdef VDEC_SMP
- vlc_mutex_unlock( &p_vpar->synchro.fifo_lock );
-#endif
}
/*****************************************************************************
+++ /dev/null
-/*****************************************************************************
- * vpar_synchro.h : video parser blocks management
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_synchro.h,v 1.10 2001/07/17 09:48:08 massiot Exp $
- *
- * Author: Christophe Massiot <massiot@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Requires:
- * "config.h"
- * "common.h"
- * "mtime.h"
- * "threads.h"
- * "input.h"
- * "video.h"
- * "video_output.h"
- * "decoder_fifo.h"
- * "video_fifo.h"
- *****************************************************************************/
-
-/*****************************************************************************
- * video_synchro_t and video_synchro_tab_s : timers for the video synchro
- *****************************************************************************/
-#define MAX_DECODING_PIC 16
-#define MAX_PIC_AVERAGE 8
-
-/* Read the discussion on top of vpar_synchro.c for more information. */
-typedef struct video_synchro_s
-{
- /* synchro algorithm */
- int i_type;
-
- /* fifo containing decoding dates */
- mtime_t p_date_fifo[MAX_DECODING_PIC];
- int pi_coding_types[MAX_DECODING_PIC];
- unsigned int i_start, i_end;
- vlc_mutex_t fifo_lock;
-
- /* stream properties */
- unsigned int i_n_p, i_n_b;
-
- /* decoding values */
- mtime_t p_tau[4]; /* average decoding durations */
- unsigned int pi_meaningful[4]; /* number of durations read */
- /* and p_vout->render_time (read with p_vout->change_lock) */
-
- /* stream context */
- unsigned int i_eta_p, i_eta_b;
- boolean_t b_dropped_last; /* for special synchros below */
- mtime_t backward_pts, current_pts;
- int i_current_period; /* period to add to the next picture */
- int i_backward_period; /* period to add after the next
- * reference picture
- * (backward_period * period / 2) */
-
-#ifdef STATS
- unsigned int i_trashed_pic, i_not_chosen_pic, i_pic;
-#endif
-} video_synchro_t;
-
-#define FIFO_INCREMENT( i_counter ) \
- p_vpar->synchro.i_counter = \
- (p_vpar->synchro.i_counter + 1) % MAX_DECODING_PIC;
-
-/* Synchro algorithms */
-#define VPAR_SYNCHRO_DEFAULT 0
-#define VPAR_SYNCHRO_I 1
-#define VPAR_SYNCHRO_Iplus 2
-#define VPAR_SYNCHRO_IP 3
-#define VPAR_SYNCHRO_IPplus 4
-#define VPAR_SYNCHRO_IPB 5
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-void vpar_SynchroInit ( struct vpar_thread_s * p_vpar );
-boolean_t vpar_SynchroChoose ( struct vpar_thread_s * p_vpar,
- int i_coding_type, int i_structure );
-void vpar_SynchroTrash ( struct vpar_thread_s * p_vpar,
- int i_coding_type, int i_structure );
-void vpar_SynchroDecode ( struct vpar_thread_s * p_vpar,
- int i_coding_type, int i_structure );
-void vpar_SynchroEnd ( struct vpar_thread_s * p_vpar, int i_garbage );
-mtime_t vpar_SynchroDate ( struct vpar_thread_s * p_vpar );
-void vpar_SynchroNewPicture( struct vpar_thread_s * p_vpar, int i_coding_type,
- int i_repeat_field );
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* Copyright (C) 2000 VideoLAN
- * $Id: video_output.c,v 1.134 2001/07/11 02:01:05 sam Exp $
+ * $Id: video_output.c,v 1.135 2001/07/18 14:21:00 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
#endif
vlc_mutex_unlock( &p_vout->picture_lock );
- /* Initialize mutex */
- vlc_mutex_init( &(p_free_picture->lock_deccount) );
-
return( p_free_picture );
}
intf_DbgMsg("picture %p", p_pic);
#endif
- /* destroy the lock that had been initialized in CreatePicture */
- vlc_mutex_destroy( &(p_pic->lock_deccount) );
-
vlc_mutex_unlock( &p_vout->picture_lock );
}