Commit d0c9b479 authored by Christophe Massiot's avatar Christophe Massiot

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

* Fixed a bug in the video decoder initialization :-p ;
* Added --smp option and several hooks in src/input/input_ext-intf.c ;
* Grayscale mode now turns off chroma IDCT.
parent 18f5cd99
...@@ -30,7 +30,7 @@ AC3_SPDIF := ac3_spdif ac3_iec958 ...@@ -30,7 +30,7 @@ AC3_SPDIF := ac3_spdif ac3_iec958
LPCM_DECODER := lpcm_decoder_thread LPCM_DECODER := lpcm_decoder_thread
AUDIO_DECODER := audio_decoder adec_generic adec_layer1 adec_layer2 adec_math AUDIO_DECODER := audio_decoder adec_generic adec_layer1 adec_layer2 adec_math
SPU_DECODER := spu_decoder 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 MISC := mtime tests modules netutils
C_OBJ := $(INTERFACE:%=src/interface/%.o) \ C_OBJ := $(INTERFACE:%=src/interface/%.o) \
......
...@@ -439,13 +439,6 @@ ...@@ -439,13 +439,6 @@
* that raising this level dramatically lengthens the compilation time. */ * that raising this level dramatically lengthens the compilation time. */
#define VPAR_OPTIM_LEVEL 2 #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. */ /* Maximum number of macroblocks in a picture. */
#define MAX_MB 2048 #define MAX_MB 2048
...@@ -456,26 +449,16 @@ ...@@ -456,26 +449,16 @@
* Video decoder configuration * Video decoder configuration
*****************************************************************************/ *****************************************************************************/
//#define VDEC_SMP
#define VDEC_IDLE_SLEEP ((int)(0.100*CLOCK_FREQ)) #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. */ /* Maximum range of values out of the IDCT + motion compensation. */
#define VDEC_CROPRANGE 2048 #define VDEC_CROPRANGE 2048
/* Nice increments for decoders -- necessary for x11 scheduling */ /* Environment variable containing the SMP value. */
#define VDEC_NICE 3 #define VDEC_SMP_VAR "vlc_smp"
/*****************************************************************************
* Generic decoder configuration
*****************************************************************************/
#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 * Messages and console interfaces configuration
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* control the pace of reading. * control the pace of reading.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -205,6 +205,7 @@ typedef struct stream_descriptor_s ...@@ -205,6 +205,7 @@ typedef struct stream_descriptor_s
/* New status and rate requested by the interface */ /* New status and rate requested by the interface */
int i_new_status, i_new_rate; 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 vlc_cond_t stream_wait; /* interface -> input in case of a
* status change request */ * status change request */
...@@ -229,6 +230,8 @@ typedef struct stream_descriptor_s ...@@ -229,6 +230,8 @@ typedef struct stream_descriptor_s
stream_ctrl_t control; stream_ctrl_t control;
} stream_descriptor_t; } stream_descriptor_t;
#define MUTE_NO_CHANGE -1
/***************************************************************************** /*****************************************************************************
* i_p_config_t * i_p_config_t
***************************************************************************** *****************************************************************************
...@@ -360,7 +363,6 @@ struct input_thread_s * input_CreateThread ( struct playlist_item_s *, ...@@ -360,7 +363,6 @@ struct input_thread_s * input_CreateThread ( struct playlist_item_s *,
void input_DestroyThread( struct input_thread_s *, int *pi_status ); void input_DestroyThread( struct input_thread_s *, int *pi_status );
void input_SetStatus( struct input_thread_s *, 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_Seek ( struct input_thread_s *, off_t );
void input_DumpStream( struct input_thread_s * ); void input_DumpStream( struct input_thread_s * );
char * input_OffsetToTime( struct input_thread_s *, char * psz_buffer, off_t ); char * input_OffsetToTime( struct input_thread_s *, char * psz_buffer, off_t );
...@@ -368,5 +370,8 @@ int input_ChangeES ( struct input_thread_s *, struct es_descriptor_s *, u8 ); ...@@ -368,5 +370,8 @@ int input_ChangeES ( struct input_thread_s *, struct es_descriptor_s *, u8 );
int input_ToggleES ( struct input_thread_s *, int input_ToggleES ( struct input_thread_s *,
struct es_descriptor_s *, struct es_descriptor_s *,
boolean_t ); boolean_t );
int input_ChangeArea( input_thread_t *, input_area_t * ); int input_ChangeArea( struct input_thread_s *, struct input_area_s * );
int input_ToggleGrayscale( struct input_thread_s * );
int input_ToggleMute( struct input_thread_s * );
int input_SetSMP( struct input_thread_s *, int );
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* but exported to plug-ins * but exported to plug-ins
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -74,8 +74,7 @@ void input_EndDecoder( struct input_thread_s *, struct es_descriptor_s * ); ...@@ -74,8 +74,7 @@ void input_EndDecoder( struct input_thread_s *, struct es_descriptor_s * );
void input_DecodePES ( struct decoder_fifo_s *, struct pes_packet_s * ); void input_DecodePES ( struct decoder_fifo_s *, struct pes_packet_s * );
void input_EscapeDiscontinuity( struct input_thread_s *, void input_EscapeDiscontinuity( struct input_thread_s *,
struct pgrm_descriptor_s * ); struct pgrm_descriptor_s * );
void input_EscapeAudioDiscontinuity( struct input_thread_s *, void input_EscapeAudioDiscontinuity( struct input_thread_s * );
struct pgrm_descriptor_s * );
/***************************************************************************** /*****************************************************************************
* Prototypes from input_clock.c * Prototypes from input_clock.c
......
...@@ -62,7 +62,6 @@ typedef struct module_symbols_s ...@@ -62,7 +62,6 @@ typedef struct module_symbols_s
int ( * network_ChannelJoin ) ( int ); int ( * network_ChannelJoin ) ( int );
void ( * input_SetStatus ) ( struct input_thread_s *, 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_Seek ) ( struct input_thread_s *, off_t );
void ( * input_DumpStream ) ( struct input_thread_s * ); void ( * input_DumpStream ) ( struct input_thread_s * );
char * ( * input_OffsetToTime ) ( struct input_thread_s *, char *, off_t ); char * ( * input_OffsetToTime ) ( struct input_thread_s *, char *, off_t );
...@@ -152,7 +151,6 @@ typedef struct module_symbols_s ...@@ -152,7 +151,6 @@ typedef struct module_symbols_s
(p_symbols)->network_ChannelCreate = network_ChannelCreate; \ (p_symbols)->network_ChannelCreate = network_ChannelCreate; \
(p_symbols)->network_ChannelJoin = network_ChannelJoin; \ (p_symbols)->network_ChannelJoin = network_ChannelJoin; \
(p_symbols)->input_SetStatus = input_SetStatus; \ (p_symbols)->input_SetStatus = input_SetStatus; \
(p_symbols)->input_SetRate = input_SetRate; \
(p_symbols)->input_Seek = input_Seek; \ (p_symbols)->input_Seek = input_Seek; \
(p_symbols)->input_DumpStream = input_DumpStream; \ (p_symbols)->input_DumpStream = input_DumpStream; \
(p_symbols)->input_OffsetToTime = input_OffsetToTime; \ (p_symbols)->input_OffsetToTime = input_OffsetToTime; \
...@@ -238,7 +236,6 @@ extern module_symbols_t* p_symbols; ...@@ -238,7 +236,6 @@ extern module_symbols_t* p_symbols;
# define network_ChannelJoin(a) p_symbols->network_ChannelJoin(a) # define network_ChannelJoin(a) p_symbols->network_ChannelJoin(a)
# define input_SetStatus(a,b) p_symbols->input_SetStatus(a,b) # 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_Seek(a,b) p_symbols->input_Seek(a,b)
# define input_DumpStream(a) p_symbols->input_DumpStream(a) # define input_DumpStream(a) p_symbols->input_DumpStream(a)
# define input_OffsetToTime(a,b,c) p_symbols->input_OffsetToTime(a,b,c) # define input_OffsetToTime(a,b,c) p_symbols->input_OffsetToTime(a,b,c)
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* of the reading. * of the reading.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -39,7 +39,9 @@ typedef struct stream_ctrl_s ...@@ -39,7 +39,9 @@ typedef struct stream_ctrl_s
int i_rate; int i_rate;
boolean_t b_mute; 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; } stream_ctrl_t;
/* Possible status : */ /* Possible status : */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* This header provides a portable threads implementation. * This header provides a portable threads implementation.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr> * Samuel Hocevar <sam@via.ecp.fr>
...@@ -491,6 +491,74 @@ static __inline__ int vlc_cond_signal( vlc_cond_t *p_condvar ) ...@@ -491,6 +491,74 @@ static __inline__ int vlc_cond_signal( vlc_cond_t *p_condvar )
#endif #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 * vlc_cond_wait: wait until condition completion
*****************************************************************************/ *****************************************************************************/
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vdec_common.h : structures from the video decoder exported to plug-ins * vdec_common.h : structures from the video decoder exported to plug-ins
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -98,24 +98,13 @@ typedef struct macroblock_s ...@@ -98,24 +98,13 @@ typedef struct macroblock_s
*****************************************************************************/ *****************************************************************************/
typedef struct vdec_thread_s typedef struct vdec_thread_s
{ {
/* Thread properties and locks */
boolean_t b_die; /* `die' flag */
boolean_t b_run; /* `run' flag */
boolean_t b_error; /* `error' flag */
boolean_t b_active; /* `active' flag */
vlc_thread_t thread_id; /* id for thread functions */ vlc_thread_t thread_id; /* id for thread functions */
boolean_t b_die;
/* IDCT iformations */ /* IDCT iformations */
void * p_idct_data; 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 * );
/* Input properties */ /* Input properties */
struct vpar_thread_s * p_vpar; /* video_parser thread */ struct vdec_pool_s * p_pool;
} vdec_thread_t; } vdec_thread_t;
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* includes all common video types and constants. * includes all common video types and constants.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* *
...@@ -71,11 +71,6 @@ typedef struct picture_s ...@@ -71,11 +71,6 @@ typedef struct picture_s
int i_display_height; /* useful picture height */ int i_display_height; /* useful picture height */
int i_aspect_ratio; /* aspect ratio */ 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 /* 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 * (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 * p_v data pointers refers to different areas of p_data, and should not
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* decoders. * decoders.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -138,6 +138,7 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) ...@@ -138,6 +138,7 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
p_input->stream.i_selected_es_number = 0; p_input->stream.i_selected_es_number = 0;
p_input->stream.i_pgrm_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.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; p_input->stream.i_mux_rate = 0;
/* no stream, no area */ /* no stream, no area */
...@@ -154,7 +155,10 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) ...@@ -154,7 +155,10 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
p_input->stream.control.i_status = PLAYING_S; p_input->stream.control.i_status = PLAYING_S;
p_input->stream.control.i_rate = DEFAULT_RATE; p_input->stream.control.i_rate = DEFAULT_RATE;
p_input->stream.control.b_mute = 0; 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 */ /* Setup callbacks */
p_input->pf_file_open = FileOpen; p_input->pf_file_open = FileOpen;
...@@ -322,6 +326,20 @@ static void RunThread( input_thread_t *p_input ) ...@@ -322,6 +326,20 @@ static void RunThread( input_thread_t *p_input )
p_input->stream.p_newly_selected_es = NULL; 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 ); vlc_mutex_unlock( &p_input->stream.stream_lock );
i_error = p_input->pf_read( p_input, pp_packets ); i_error = p_input->pf_read( p_input, pp_packets );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_clock.c: Clock/System date convertions, stream management * input_clock.c: Clock/System date convertions, stream management
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -197,7 +197,7 @@ int input_ClockManageControl( input_thread_t * p_input, ...@@ -197,7 +197,7 @@ int input_ClockManageControl( input_thread_t * p_input,
/* Feed the audio decoders with a NULL packet to avoid /* Feed the audio decoders with a NULL packet to avoid
* discontinuities. */ * discontinuities. */
input_EscapeAudioDiscontinuity( p_input, p_pgrm ); input_EscapeAudioDiscontinuity( p_input );
} }
p_input->stream.i_new_status = UNDEF_S; p_input->stream.i_new_status = UNDEF_S;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_dec.c: Functions for the management of decoders * input_dec.c: Functions for the management of decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -147,20 +147,24 @@ void input_EscapeDiscontinuity( input_thread_t * p_input, ...@@ -147,20 +147,24 @@ void input_EscapeDiscontinuity( input_thread_t * p_input,
/***************************************************************************** /*****************************************************************************
* input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
*****************************************************************************/ *****************************************************************************/
void input_EscapeAudioDiscontinuity( input_thread_t * p_input, void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
pgrm_descriptor_t * p_pgrm )
{ {
int i_es, i; int i_pgrm, i_es, i;
for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ ) for( i_pgrm = 0; i_pgrm < p_input->stream.i_pgrm_number; i_pgrm++ )
{ {
es_descriptor_t * p_es = p_pgrm->pp_es[i_es]; pgrm_descriptor_t * p_pgrm = p_input->stream.pp_programs[i_pgrm];
if( p_es->p_decoder_fifo != NULL && p_es->b_audio ) for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
{ {
for( i = 0; i < PADDING_PACKET_NUMBER; i++ ) es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
if( p_es->p_decoder_fifo != NULL && p_es->b_audio )
{ {
input_NullPacket( p_input, p_es ); for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
{
input_NullPacket( p_input, p_es );
}
} }
} }
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ext-intf.c: services to the interface * input_ext-intf.c: services to the interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -128,14 +128,6 @@ void input_SetStatus( input_thread_t * p_input, int i_mode ) ...@@ -128,14 +128,6 @@ void input_SetStatus( input_thread_t * p_input, int i_mode )
vlc_mutex_unlock( &p_input->stream.stream_lock ); 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 * input_Seek: changes the stream postion
*****************************************************************************/ *****************************************************************************/
...@@ -339,3 +331,55 @@ int input_ChangeArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -339,3 +331,55 @@ int input_ChangeArea( input_thread_t * p_input, input_area_t * p_area )
return 0; return 0;
} }
/****************************************************************************
* input_ToggleGrayscale: change to grayscale or color output
****************************************************************************/
int input_ToggleGrayscale( input_thread_t * p_input )
{
/* No need to warn the input thread since only the decoders and outputs
* worry about it. */
vlc_mutex_lock( &p_input->stream.control.control_lock );
p_input->stream.control.b_grayscale =
!p_input->stream.control.b_grayscale;
intf_WarnMsg( 3, "input warning: changing to %s output",
p_input->stream.control.b_grayscale ? "grayscale" : "color" );
vlc_mutex_unlock( &p_input->stream.control.control_lock );
return 0;
}
/****************************************************************************
* input_ToggleMute: activate/deactivate mute mode
****************************************************************************/
int input_ToggleMute( input_thread_t * p_input )
{
/* We need to feed the decoders with 0, and only input can do that, so
* pass the message to the input thread. */
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.b_new_mute = !p_input->stream.control.b_mute;
intf_WarnMsg( 3, "input warning: %s mute mode",
p_input->stream.control.b_mute ? "activating" : "deactivating" );
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0;
}
/****************************************************************************
* input_SetSMP: change the number of video decoder threads
****************************************************************************/
int input_SetSMP( input_thread_t * p_input, int i_smp )
{
/* No need to warn the input thread since only the decoders
* worry about it. */
vlc_mutex_lock( &p_input->stream.control.control_lock );
p_input->stream.control.i_smp = i_smp;
vlc_mutex_unlock( &p_input->stream.control.control_lock );
return 0;
}
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* interface, such as command line. * interface, such as command line.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * 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> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* *
...@@ -394,6 +394,13 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key ) ...@@ -394,6 +394,13 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
break; break;
case INTF_KEY_TOGGLE_VOLUME: /* toggle mute */ 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 ); vlc_mutex_lock( &p_aout_bank->lock );
for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ ) for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
{ {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* and spawn threads. * and spawn threads.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * 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> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -113,6 +113,7 @@ ...@@ -113,6 +113,7 @@
#define OPT_COLOR 164 #define OPT_COLOR 164
#define OPT_FULLSCREEN 165 #define OPT_FULLSCREEN 165
#define OPT_OVERLAY 166 #define OPT_OVERLAY 166
#define OPT_SMP 167
#define OPT_CHANNELS 170 #define OPT_CHANNELS 170
#define OPT_SERVER 171 #define OPT_SERVER 171
...@@ -183,6 +184,7 @@ static const struct option longopts[] = ...@@ -183,6 +184,7 @@ static const struct option longopts[] =
{ "yuv", 1, 0, OPT_YUV }, { "yuv", 1, 0, OPT_YUV },
{ "fullscreen", 0, 0, OPT_FULLSCREEN }, { "fullscreen", 0, 0, OPT_FULLSCREEN },
{ "overlay", 0, 0, OPT_OVERLAY }, { "overlay", 0, 0, OPT_OVERLAY },
{ "smp", 1, 0, OPT_SMP },
/* DVD options */ /* DVD options */
{ "dvdtitle", 1, 0, 't' }, { "dvdtitle", 1, 0, 't' },
...@@ -693,6 +695,9 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] ) ...@@ -693,6 +695,9 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
case OPT_YUV: /* --yuv */ case OPT_YUV: /* --yuv */
main_PutPszVariable( YUV_METHOD_VAR, optarg ); main_PutPszVariable( YUV_METHOD_VAR, optarg );
break; break;
case OPT_SMP: /* --smp */
main_PutIntVariable( VDEC_SMP_VAR, atoi(optarg) );
break;
/* DVD options */ /* DVD options */
case 't': case 't':
...@@ -836,6 +841,7 @@ static void Usage( int i_fashion ) ...@@ -836,6 +841,7 @@ static void Usage( int i_fashion )
"\n --idct <module> \tIDCT method" "\n --idct <module> \tIDCT method"
"\n --yuv <module> \tYUV method" "\n --yuv <module> \tYUV method"
"\n --synchro <type> \tforce synchro algorithm" "\n --synchro <type> \tforce synchro algorithm"
"\n --smp <number of threads> \tuse several processors"
"\n" "\n"
"\n -t, --dvdtitle <num> \tchoose DVD title" "\n -t, --dvdtitle <num> \tchoose DVD title"
"\n -T, --dvdchapter <num> \tchoose DVD chapter" "\n -T, --dvdchapter <num> \tchoose DVD chapter"
...@@ -887,7 +893,8 @@ static void Usage( int i_fashion ) ...@@ -887,7 +893,8 @@ static void Usage( int i_fashion )
"\n " MOTION_METHOD_VAR "=<method name> \tmotion compensation method" "\n " MOTION_METHOD_VAR "=<method name> \tmotion compensation method"
"\n " IDCT_METHOD_VAR "=<method name> \tIDCT method" "\n " IDCT_METHOD_VAR "=<method name> \tIDCT method"
"\n " YUV_METHOD_VAR "=<method name> \tYUV 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 */ /* DVD parameters */
intf_MsgImm( "\nDVD parameters:" intf_MsgImm( "\nDVD parameters:"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* video_decoder.c : video decoder thread * video_decoder.c : video decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Gal Hendryckx <jimmy@via.ecp.fr> * Gal Hendryckx <jimmy@via.ecp.fr>
...@@ -50,32 +50,20 @@ ...@@ -50,32 +50,20 @@
#include "vdec_ext-plugins.h" #include "vdec_ext-plugins.h"
#include "video_decoder.h" #include "video_decoder.h"
#include "vpar_pool.h"
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "vpar_synchro.h"
#include "video_parser.h"
#include "video_fifo.h"
/* /*
* Local prototypes * 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 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 * vdec_CreateThread: create a video decoder thread
***************************************************************************** *****************************************************************************
* This function creates a new video decoder thread, and returns a pointer * This function creates a new video decoder thread, and returns a pointer
* to its description. On error, it returns NULL. * 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; vdec_thread_t * p_vdec;
...@@ -92,12 +80,11 @@ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ ) ...@@ -92,12 +80,11 @@ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
* Initialize the thread properties * Initialize the thread properties
*/ */
p_vdec->b_die = 0; p_vdec->b_die = 0;
p_vdec->b_error = 0;
/* /*
* Initialize the parser properties * Initialize the parser properties
*/ */
p_vdec->p_vpar = p_vpar; p_vdec->p_pool = p_pool;
/* Spawn the video decoder thread */ /* Spawn the video decoder thread */
if ( vlc_thread_create(&p_vdec->thread_id, "video decoder", if ( vlc_thread_create(&p_vdec->thread_id, "video decoder",
...@@ -114,27 +101,20 @@ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ ) ...@@ -114,27 +101,20 @@ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
/***************************************************************************** /*****************************************************************************
* vdec_DestroyThread: destroy a video decoder thread * 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); intf_DbgMsg("vdec debug: requesting termination of video decoder thread %p", p_vdec);
/* Ask thread to kill itself */ /* Ask thread to kill itself */
p_vdec->b_die = 1; p_vdec->b_die = 1;
#ifdef VDEC_SMP
/* Make sure the decoder thread leaves the vpar_GetMacroblock() function */ /* Make sure the decoder thread leaves the vpar_GetMacroblock() function */
vlc_mutex_lock( &(p_vdec->p_vpar->vfifo.lock) ); vlc_mutex_lock( &p_vdec->p_pool->lock );
vlc_cond_signal( &(p_vdec->p_vpar->vfifo.wait) ); vlc_cond_broadcast( &p_vdec->p_pool->wait_undecoded );
vlc_mutex_unlock( &(p_vdec->p_vpar->vfifo.lock) ); vlc_mutex_unlock( &p_vdec->p_pool->lock );
#endif
/* Waiting for the decoder thread to exit */ /* Waiting for the decoder thread to exit */
/* Remove this as soon as the "status" flag is implemented */
vlc_thread_join( p_vdec->thread_id ); vlc_thread_join( p_vdec->thread_id );
} }
...@@ -144,65 +124,28 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ ) ...@@ -144,65 +124,28 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
* vdec_InitThread: initialize video decoder thread * vdec_InitThread: initialize video decoder thread
***************************************************************************** *****************************************************************************
* This function is called from RunThread and performs the second step of the * 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 * initialization.
* modified inside this function.
*****************************************************************************/ *****************************************************************************/
#ifdef VDEC_SMP void vdec_InitThread( vdec_thread_t *p_vdec )
static int vdec_InitThread( vdec_thread_t *p_vdec )
#else
int vdec_InitThread( vdec_thread_t *p_vdec )
#endif
{ {
intf_DbgMsg("vdec debug: initializing video decoder thread %p", p_vdec); intf_DbgMsg("vdec debug: initializing video decoder thread %p", p_vdec);
p_vdec->p_idct_data = NULL; p_vdec->p_idct_data = NULL;
p_vdec->pf_decode_init = p_vdec->p_vpar->pf_decode_init; p_vdec->p_pool->pf_decode_init( p_vdec );
p_vdec->pf_decode_mb_c = p_vdec->p_vpar->pf_decode_mb_c; p_vdec->p_pool->pf_idct_init( p_vdec );
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
/* Mark thread as running and return */ /* Mark thread as running and return */
intf_DbgMsg("vdec debug: InitThread(%p) succeeded", p_vdec); 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 * This function is called when the thread ends after a sucessful
* initialization. * 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); intf_DbgMsg("vdec debug: EndThread(%p)", p_vdec);
...@@ -210,6 +153,8 @@ static void EndThread( vdec_thread_t *p_vdec ) ...@@ -210,6 +153,8 @@ static void EndThread( vdec_thread_t *p_vdec )
{ {
free( p_vdec->p_idct_data ); free( p_vdec->p_idct_data );
} }
free( p_vdec );
} }
/***************************************************************************** /*****************************************************************************
...@@ -223,44 +168,26 @@ static void RunThread( vdec_thread_t *p_vdec ) ...@@ -223,44 +168,26 @@ static void RunThread( vdec_thread_t *p_vdec )
intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)", intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)",
p_vdec, getpid()); p_vdec, getpid());
/* vdec_InitThread( p_vdec );
* Initialize thread and free configuration
*/
p_vdec->b_error = vdec_InitThread( p_vdec );
if( p_vdec->b_error )
{
return;
}
p_vdec->b_run = 1;
/* /*
* Main loop - it is not executed if an error occured during * Main loop
* initialization
*/ */
while( (!p_vdec->b_die) && (!p_vdec->b_error) ) while( !p_vdec->b_die )
{ {
macroblock_t * p_mb; 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 /* Decoding is finished, release the macroblock and free
* unneeded memory. */ * 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 */ /* End of thread */
EndThread( p_vdec ); vdec_EndThread( p_vdec );
p_vdec->b_run = 0;
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* video_decoder.h : video decoder thread * video_decoder.h : video decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -21,18 +21,6 @@ ...@@ -21,18 +21,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * 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 * Prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -40,15 +28,14 @@ struct vpar_thread_s; ...@@ -40,15 +28,14 @@ struct vpar_thread_s;
struct macroblock_s; struct macroblock_s;
/* Thread management functions */ /* Thread management functions */
#ifndef VDEC_SMP void vdec_InitThread ( struct vdec_thread_s *p_vdec );
int vdec_InitThread ( struct vdec_thread_s *p_vdec ); void vdec_EndThread ( struct vdec_thread_s *p_vdec );
#endif
void vdec_DecodeMacroblock ( struct vdec_thread_s *p_vdec, void vdec_DecodeMacroblock ( struct vdec_thread_s *p_vdec,
struct macroblock_s *p_mb ); struct macroblock_s *p_mb );
void vdec_DecodeMacroblockC ( struct vdec_thread_s *p_vdec, void vdec_DecodeMacroblockC ( struct vdec_thread_s *p_vdec,
struct macroblock_s *p_mb ); struct macroblock_s *p_mb );
void vdec_DecodeMacroblockBW ( struct vdec_thread_s *p_vdec, void vdec_DecodeMacroblockBW ( struct vdec_thread_s *p_vdec,
struct macroblock_s *p_mb ); 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 ); void vdec_DestroyThread ( struct vdec_thread_s *p_vdec );
/*****************************************************************************
* 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
}
/*****************************************************************************
* 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 );
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* video_parser.c : video parser thread * video_parser.c : video parser thread
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr> * Samuel Hocevar <sam@via.ecp.fr>
...@@ -55,13 +55,8 @@ ...@@ -55,13 +55,8 @@
#include "video_output.h" #include "video_output.h"
#include "vdec_ext-plugins.h" #include "vdec_ext-plugins.h"
#include "video_decoder.h" #include "vpar_pool.h"
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "vpar_synchro.h"
#include "video_parser.h" #include "video_parser.h"
#include "video_fifo.h"
/* /*
* Local prototypes * Local prototypes
...@@ -99,6 +94,34 @@ vlc_thread_t vpar_CreateThread( vdec_config_t * p_config ) ...@@ -99,6 +94,34 @@ vlc_thread_t vpar_CreateThread( vdec_config_t * p_config )
p_vpar->p_config = p_config; p_vpar->p_config = p_config;
p_vpar->p_vout = NULL; 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 * Choose the best motion compensation module
*/ */
...@@ -164,9 +187,9 @@ vlc_thread_t vpar_CreateThread( vdec_config_t * p_config ) ...@@ -164,9 +187,9 @@ vlc_thread_t vpar_CreateThread( vdec_config_t * p_config )
#undef S #undef S
#undef M #undef M
/* /*
* Choose the best IDCT module * Choose the best IDCT module
*/ */
p_vpar->p_idct_module = module_Need( MODULE_CAPABILITY_IDCT, NULL ); p_vpar->p_idct_module = module_Need( MODULE_CAPABILITY_IDCT, NULL );
if( p_vpar->p_idct_module == NULL ) if( p_vpar->p_idct_module == NULL )
...@@ -178,47 +201,16 @@ vlc_thread_t vpar_CreateThread( vdec_config_t * p_config ) ...@@ -178,47 +201,16 @@ vlc_thread_t vpar_CreateThread( vdec_config_t * p_config )
} }
#define f p_vpar->p_idct_module->p_functions->idct.functions.idct #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_sparse_idct = f.pf_sparse_idct;
p_vpar->pf_idct = f.pf_idct; p_vpar->pf_idct = f.pf_idct;
p_vpar->pf_norm_scan = f.pf_norm_scan; 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_c = f.pf_decode_mb_c;
p_vpar->pf_decode_mb_bw = f.pf_decode_mb_bw; p_vpar->pf_decode_mb_bw = f.pf_decode_mb_bw;
#undef f #undef f
/* Spawn the video parser thread */ /* Initialize input bitstream */
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);
p_vpar->p_config->decoder_config.pf_init_bit_stream( &p_vpar->bit_stream, p_vpar->p_config->decoder_config.pf_init_bit_stream( &p_vpar->bit_stream,
p_vpar->p_config->decoder_config.p_decoder_fifo, BitstreamCallback, p_vpar->p_config->decoder_config.p_decoder_fifo, BitstreamCallback,
(void *)p_vpar ); (void *)p_vpar );
...@@ -253,51 +245,6 @@ static int InitThread( vpar_thread_t *p_vpar ) ...@@ -253,51 +245,6 @@ static int InitThread( vpar_thread_t *p_vpar )
sizeof(p_vpar->pc_malformed_pictures)); sizeof(p_vpar->pc_malformed_pictures));
#endif #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 */ /* Initialize lookup tables */
vpar_InitMbAddrInc( p_vpar ); vpar_InitMbAddrInc( p_vpar );
vpar_InitDCTTables( p_vpar ); vpar_InitDCTTables( p_vpar );
...@@ -311,6 +258,9 @@ static int InitThread( vpar_thread_t *p_vpar ) ...@@ -311,6 +258,9 @@ static int InitThread( vpar_thread_t *p_vpar )
*/ */
vpar_SynchroInit( p_vpar ); vpar_SynchroInit( p_vpar );
/* Spawn optional video decoder threads */
vpar_InitPool( p_vpar );
/* Mark thread as running and return */ /* Mark thread as running and return */
intf_DbgMsg("vpar debug: InitThread(%p) succeeded", p_vpar); intf_DbgMsg("vpar debug: InitThread(%p) succeeded", p_vpar);
return( 0 ); return( 0 );
...@@ -350,7 +300,7 @@ static void RunThread( vpar_thread_t *p_vpar ) ...@@ -350,7 +300,7 @@ static void RunThread( vpar_thread_t *p_vpar )
{ {
/* End of sequence */ /* End of sequence */
break; break;
}; }
} }
} }
...@@ -406,10 +356,6 @@ static void ErrorThread( vpar_thread_t *p_vpar ) ...@@ -406,10 +356,6 @@ static void ErrorThread( vpar_thread_t *p_vpar )
*****************************************************************************/ *****************************************************************************/
static void EndThread( vpar_thread_t *p_vpar ) static void EndThread( vpar_thread_t *p_vpar )
{ {
#ifdef VDEC_SMP
int i_dummy;
#endif
intf_DbgMsg("vpar debug: destroying video parser thread %p", p_vpar); intf_DbgMsg("vpar debug: destroying video parser thread %p", p_vpar);
/* Release used video buffers. */ /* Release used video buffers. */
...@@ -489,30 +435,10 @@ static void EndThread( vpar_thread_t *p_vpar ) ...@@ -489,30 +435,10 @@ static void EndThread( vpar_thread_t *p_vpar )
free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix ); free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
} }
#ifdef VDEC_SMP vpar_EndPool( p_vpar );
/* 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
free( p_vpar->p_config ); 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_idct_module );
module_Unneed( p_vpar->p_motion_module ); module_Unneed( p_vpar->p_motion_module );
......
This diff is collapsed.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vpar_blocks.c : blocks parsing * vpar_blocks.c : blocks parsing
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Jean-Marc Dressler <polux@via.ecp.fr> * Jean-Marc Dressler <polux@via.ecp.fr>
...@@ -44,13 +44,8 @@ ...@@ -44,13 +44,8 @@
#include "video_output.h" #include "video_output.h"
#include "vdec_ext-plugins.h" #include "vdec_ext-plugins.h"
#include "video_decoder.h" #include "vpar_pool.h"
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "vpar_synchro.h"
#include "video_parser.h" #include "video_parser.h"
#include "video_fifo.h"
/* /*
* Welcome to vpar_blocks.c ! Here's where the heavy processor-critical parsing * Welcome to vpar_blocks.c ! Here's where the heavy processor-critical parsing
...@@ -1644,14 +1639,7 @@ static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb, ...@@ -1644,14 +1639,7 @@ static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb,
return; return;
} }
if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL ) p_mb = p_vpar->pool.pf_new_mb( &p_vpar->pool );
{
/* b_die == 1 */
return;
}
#ifdef VDEC_SMP
p_vpar->picture.pp_mb[i_mb_base + i_mb] = p_mb;
#endif
InitMacroblock( p_vpar, p_mb, i_coding_type, i_structure ); InitMacroblock( p_vpar, p_mb, i_coding_type, i_structure );
...@@ -1679,10 +1667,8 @@ static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb, ...@@ -1679,10 +1667,8 @@ static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb,
UpdateContext( p_vpar, i_structure ); UpdateContext( p_vpar, i_structure );
#ifndef VDEC_SMP
/* Decode the macroblock NOW ! */ /* Decode the macroblock NOW ! */
vpar_DecodeMacroblock ( &p_vpar->vfifo, p_mb ); p_vpar->pool.pf_decode_mb( &p_vpar->pool, p_mb );
#endif
} }
/***************************************************************************** /*****************************************************************************
...@@ -1776,7 +1762,7 @@ static __inline__ void MacroblockModes( vpar_thread_t * p_vpar, ...@@ -1776,7 +1762,7 @@ static __inline__ void MacroblockModes( vpar_thread_t * p_vpar,
if( p_vpar->picture.b_error ) \ if( p_vpar->picture.b_error ) \
{ \ { \
/* Go to the next slice. */ \ /* Go to the next slice. */ \
vpar_FreeMacroblock( &p_vpar->vfifo, p_mb ); \ p_vpar->pool.pf_free_mb( &p_vpar->pool, p_mb ); \
return; \ return; \
} }
...@@ -1830,14 +1816,7 @@ static __inline__ void ParseMacroblock( ...@@ -1830,14 +1816,7 @@ static __inline__ void ParseMacroblock(
} }
/* Get a macroblock structure. */ /* Get a macroblock structure. */
if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL ) p_mb = p_vpar->pool.pf_new_mb( &p_vpar->pool );
{
/* b_die == 1 */
return;
}
#ifdef VDEC_SMP
p_vpar->picture.pp_mb[i_mb_base + *pi_mb_address] = p_mb;
#endif
InitMacroblock( p_vpar, p_mb, i_coding_type, i_structure ); InitMacroblock( p_vpar, p_mb, i_coding_type, i_structure );
...@@ -1960,24 +1939,27 @@ static __inline__ void ParseMacroblock( ...@@ -1960,24 +1939,27 @@ static __inline__ void ParseMacroblock(
* Effectively decode blocks. * Effectively decode blocks.
*/ */
if( b_mpeg2 ) if( b_mpeg2 )
{
DecodeMPEG2IntraMB( p_vpar, p_mb ); DecodeMPEG2IntraMB( p_vpar, p_mb );
}
else else
{
DecodeMPEG1IntraMB( p_vpar, p_mb ); DecodeMPEG1IntraMB( p_vpar, p_mb );
}
PARSEERROR PARSEERROR
} }
if( !p_vpar->picture.b_error ) if( !p_vpar->picture.b_error )
{ {
UpdateContext( p_vpar, i_structure ); UpdateContext( p_vpar, i_structure );
#ifndef VDEC_SMP
/* Decode the macroblock NOW ! */ /* Decode the macroblock NOW ! */
vpar_DecodeMacroblock ( &p_vpar->vfifo, p_mb ); p_vpar->pool.pf_decode_mb( &p_vpar->pool, p_mb );
#endif
} }
else else
{ {
/* Go to the next slice. */ /* Go to the next slice. */
vpar_FreeMacroblock( &p_vpar->vfifo, p_mb ); p_vpar->pool.pf_free_mb( &p_vpar->pool, p_mb );
} }
} }
...@@ -2090,7 +2072,7 @@ static __inline__ void vpar_PictureData( vpar_thread_t * p_vpar, ...@@ -2090,7 +2072,7 @@ static __inline__ void vpar_PictureData( vpar_thread_t * p_vpar,
} }
#if 0 #if 0
/* Buggy */ /* BUGGY */
/* Try to recover from error. If we missed less than half the /* Try to recover from error. If we missed less than half the
* number of macroblocks of the picture, mark the missed ones * number of macroblocks of the picture, mark the missed ones
* as skipped. */ * as skipped. */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vpar_headers.c : headers parsing * vpar_headers.c : headers parsing
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Stphane Borel <stef@via.ecp.fr> * Stphane Borel <stef@via.ecp.fr>
...@@ -44,13 +44,8 @@ ...@@ -44,13 +44,8 @@
#include "video_output.h" #include "video_output.h"
#include "vdec_ext-plugins.h" #include "vdec_ext-plugins.h"
#include "video_decoder.h" #include "vpar_pool.h"
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "vpar_synchro.h"
#include "video_parser.h" #include "video_parser.h"
#include "video_fifo.h"
/* /*
* Local prototypes * Local prototypes
...@@ -450,7 +445,7 @@ static void SequenceHeader( vpar_thread_t * p_vpar ) ...@@ -450,7 +445,7 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
/* XXX: The vout request and fifo opening will eventually be here */ /* 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 ); vlc_mutex_lock( &p_vout_bank->lock );
if( p_vout_bank->i_count == 0 ) if( p_vout_bank->i_count == 0 )
...@@ -510,15 +505,6 @@ static void PictureHeader( vpar_thread_t * p_vpar ) ...@@ -510,15 +505,6 @@ static void PictureHeader( vpar_thread_t * p_vpar )
ReferenceUpdate( p_vpar, I_CODING_TYPE, NULL ); ReferenceUpdate( p_vpar, I_CODING_TYPE, NULL );
if( p_vpar->picture.p_picture != 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 ); vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
} }
p_vpar->sequence.b_expect_discontinuity = 0; p_vpar->sequence.b_expect_discontinuity = 0;
...@@ -613,14 +599,6 @@ static void PictureHeader( vpar_thread_t * p_vpar ) ...@@ -613,14 +599,6 @@ static void PictureHeader( vpar_thread_t * p_vpar )
ReferenceReplace( p_vpar, ReferenceReplace( p_vpar,
p_vpar->picture.i_coding_type, p_vpar->picture.i_coding_type,
NULL ); 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 ); vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
} }
...@@ -747,30 +725,11 @@ static void PictureHeader( vpar_thread_t * p_vpar ) ...@@ -747,30 +725,11 @@ static void PictureHeader( vpar_thread_t * p_vpar )
p_vpar->picture.i_c_stride = ( p_vpar->sequence.i_chroma_width p_vpar->picture.i_c_stride = ( p_vpar->sequence.i_chroma_width
<< ( 1 - p_vpar->picture.b_frame_structure )); << ( 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 ?? */ /* FIXME ! remove asap ?? */
//memset( P_picture->p_data, 0, (p_vpar->sequence.i_mb_size*384)); //memset( P_picture->p_data, 0, (p_vpar->sequence.i_mb_size*384));
/* Update the reference pointers. */ /* Update the reference pointers. */
ReferenceUpdate( p_vpar, p_vpar->picture.i_coding_type, P_picture ); 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_current_structure |= i_structure;
p_vpar->picture.i_structure = i_structure; p_vpar->picture.i_structure = i_structure;
...@@ -855,6 +814,12 @@ static void PictureHeader( vpar_thread_t * p_vpar ) ...@@ -855,6 +814,12 @@ static void PictureHeader( vpar_thread_t * p_vpar )
#endif #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 ) if( p_vpar->p_fifo->b_die || p_vpar->p_fifo->b_error )
{ {
return; return;
...@@ -863,22 +828,13 @@ static void PictureHeader( vpar_thread_t * p_vpar ) ...@@ -863,22 +828,13 @@ static void PictureHeader( vpar_thread_t * p_vpar )
if( p_vpar->picture.b_error ) if( p_vpar->picture.b_error )
{ {
/* Trash picture. */ /* 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 #ifdef STATS
p_vpar->pc_malformed_pictures[p_vpar->picture.i_coding_type]++; p_vpar->pc_malformed_pictures[p_vpar->picture.i_coding_type]++;
#endif #endif
if( P_picture->i_deccount != 1 ) vpar_SynchroEnd( p_vpar, p_vpar->picture.i_coding_type,
{ p_vpar->picture.i_structure, 1 );
vpar_SynchroEnd( p_vpar, 1 ); vout_DestroyPicture( p_vpar->p_vout, P_picture );
vout_DestroyPicture( p_vpar->p_vout, P_picture );
}
ReferenceReplace( p_vpar, p_vpar->picture.i_coding_type, NULL ); ReferenceReplace( p_vpar, p_vpar->picture.i_coding_type, NULL );
...@@ -890,17 +846,9 @@ static void PictureHeader( vpar_thread_t * p_vpar ) ...@@ -890,17 +846,9 @@ static void PictureHeader( vpar_thread_t * p_vpar )
else if( p_vpar->picture.i_current_structure == FRAME_STRUCTURE ) else if( p_vpar->picture.i_current_structure == FRAME_STRUCTURE )
{ {
/* Frame completely parsed. */ /* Frame completely parsed. */
#ifdef VDEC_SMP vpar_SynchroEnd( p_vpar, p_vpar->picture.i_coding_type,
for( i_mb = 1; p_vpar->picture.pp_mb[i_mb] != NULL; i_mb++ ) p_vpar->picture.i_structure, 0 );
{ vout_DisplayPicture( p_vpar->p_vout, P_picture );
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
/* Prepare context for the next picture. */ /* Prepare context for the next picture. */
P_picture = NULL; P_picture = 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>
* Stphane 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 );
This diff is collapsed.
/***************************************************************************** /*****************************************************************************
* vpar_blocks.h : video parser blocks management * vpar_pool.h : video parser/video decoders communication
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: vpar_blocks.h,v 1.4 2001/07/17 09:48:08 massiot Exp $ * $Id: vpar_pool.h,v 1.1 2001/07/18 14:21:00 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Jean-Marc Dressler <polux@via.ecp.fr>
* Stphane Borel <stef@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -24,115 +22,90 @@ ...@@ -24,115 +22,90 @@
*****************************************************************************/ *****************************************************************************/
/***************************************************************************** /*****************************************************************************
* Requires: * vdec_pool_t
* "config.h" *****************************************************************************
* "common.h" * This structure is used for the communication between the parser and the
* "mtime.h" * decoders.
* "threads.h"
* "input.h"
* "video.h"
* "video_output.h"
* "decoder_fifo.h"
* "video_fifo.h"
*****************************************************************************/
/*****************************************************************************
* macroblock_parsing_t : macroblock context & predictors
*****************************************************************************/ *****************************************************************************/
typedef struct typedef struct vdec_pool_s
{ {
unsigned char i_quantizer_scale; /* scale of the quantization /* Locks */
* matrices */ vlc_mutex_t lock; /* Structure data lock */
int pi_dc_dct_pred[3]; /* ISO/IEC 13818-2 7.2.1 */ vlc_cond_t wait_empty; /* The parser blocks there when all
int pppi_pmv[2][2][2]; /* Motion vect predictors, 7.6.3 */ * decoder threads are busy */
int i_motion_dir;/* Used for the next skipped macroblock */ vlc_cond_t wait_undecoded; /* The decoders block there when no
* macroblock has been given by the
/* Context used to optimize block parsing */ * parser */
int i_motion_type, i_mv_count, i_mv_format;
boolean_t b_dmv, b_dct_type; /* Video decoder threads */
struct vdec_thread_s ** pp_vdec; /* Array of video decoder threads */
/* Coordinates of the upper-left pixel of the macroblock, in lum and int i_smp; /* Number of symmetrical decoder threads,
* chroma */ * hence size of the pp_vdec, p_macroblocks
int i_l_x, i_l_y, i_c_x, i_c_y; * and pp_new_macroblocks array */
} macroblock_parsing_t;
/* 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;
/***************************************************************************** /*****************************************************************************
* lookup_t : entry type for lookup tables * * Prototypes
*****************************************************************************/ *****************************************************************************/
typedef struct lookup_s void vpar_InitPool( struct vpar_thread_s * );
{ void vpar_SpawnPool( struct vpar_thread_s * );
int i_value; void vpar_EndPool( struct vpar_thread_s * );
int i_length;
} lookup_t;
/***************************************************************************** /*****************************************************************************
* ac_lookup_t : special entry type for lookup tables about ac coefficients * vpar_GetMacroblock: In a vdec thread, get the next available macroblock
*****************************************************************************/ *****************************************************************************/
typedef struct dct_lookup_s static __inline__ macroblock_t * vpar_GetMacroblock( vdec_pool_t * p_pool,
boolean_t * pb_die )
{ {
char i_run; macroblock_t * p_mb;
char i_level;
char i_length; vlc_mutex_lock( &p_pool->lock );
} dct_lookup_t; while( p_pool->i_index_new == 0 && !*pb_die )
{
/***************************************************************************** vlc_cond_wait( &p_pool->wait_undecoded, &p_pool->lock );
* Standard codes }
*****************************************************************************/
if( *pb_die )
/* Macroblock Address Increment types */ {
#define MB_ADDRINC_ESCAPE 8 vlc_mutex_unlock( &p_pool->lock );
#define MB_ADDRINC_STUFFING 15 return( NULL );
}
/* Error constant for lookup tables */
#define MB_ERROR (-1) p_mb = p_pool->pp_new_macroblocks[ --p_pool->i_index_new ];
vlc_mutex_unlock( &p_pool->lock );
/* Scan */ return( p_mb );
#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
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vpar_synchro.c : frame dropping routines * vpar_synchro.c : frame dropping routines
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr> * Samuel Hocevar <sam@via.ecp.fr>
...@@ -112,11 +112,7 @@ ...@@ -112,11 +112,7 @@
#include "video_output.h" #include "video_output.h"
#include "vdec_ext-plugins.h" #include "vdec_ext-plugins.h"
#include "video_decoder.h" #include "vpar_pool.h"
#include "vpar_blocks.h"
#include "vpar_headers.h"
#include "vpar_synchro.h"
#include "video_parser.h" #include "video_parser.h"
#include "main.h" #include "main.h"
...@@ -138,8 +134,6 @@ static int SynchroType( void ); ...@@ -138,8 +134,6 @@ static int SynchroType( void );
void vpar_SynchroInit( vpar_thread_t * p_vpar ) void vpar_SynchroInit( vpar_thread_t * p_vpar )
{ {
p_vpar->synchro.i_type = SynchroType(); 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. */ /* 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; p_vpar->synchro.i_n_p = p_vpar->synchro.i_eta_p = DEFAULT_NB_P;
...@@ -234,9 +228,6 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type, ...@@ -234,9 +228,6 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
vlc_mutex_lock( &p_vpar->p_vout->change_lock ); vlc_mutex_lock( &p_vpar->p_vout->change_lock );
tau_yuv = p_vpar->p_vout->render_time; tau_yuv = p_vpar->p_vout->render_time;
vlc_mutex_unlock( &p_vpar->p_vout->change_lock ); 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 ) switch( i_coding_type )
{ {
...@@ -317,9 +308,6 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type, ...@@ -317,9 +308,6 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
} }
} }
#ifdef VDEC_SMP
vlc_mutex_unlock( &p_vpar->synchro.fifo_lock );
#endif
#ifdef TRACE_VPAR #ifdef TRACE_VPAR
intf_DbgMsg("vpar synchro debug: %s picture scheduled for %s, %s (%lld)", intf_DbgMsg("vpar synchro debug: %s picture scheduled for %s, %s (%lld)",
i_coding_type == B_CODING_TYPE ? "B" : i_coding_type == B_CODING_TYPE ? "B" :
...@@ -356,46 +344,20 @@ void vpar_SynchroTrash( vpar_thread_t * p_vpar, int i_coding_type, ...@@ -356,46 +344,20 @@ void vpar_SynchroTrash( vpar_thread_t * p_vpar, int i_coding_type,
void vpar_SynchroDecode( vpar_thread_t * p_vpar, int i_coding_type, void vpar_SynchroDecode( vpar_thread_t * p_vpar, int i_coding_type,
int i_structure ) int i_structure )
{ {
#ifdef VDEC_SMP p_vpar->synchro.decoding_start = mdate();
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
} }
/***************************************************************************** /*****************************************************************************
* vpar_SynchroEnd : Called when the image is totally decoded * 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; 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 ) 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 /* If duration too high, something happened (pause ?), so don't
* take it into account. */ * take it into account. */
...@@ -425,12 +387,6 @@ void vpar_SynchroEnd( vpar_thread_t * p_vpar, int i_garbage ) ...@@ -425,12 +387,6 @@ void vpar_SynchroEnd( vpar_thread_t * p_vpar, int i_garbage )
i_coding_type == B_CODING_TYPE ? "B" : i_coding_type == B_CODING_TYPE ? "B" :
(i_coding_type == P_CODING_TYPE ? "P" : "I")); (i_coding_type == P_CODING_TYPE ? "P" : "I"));
} }
FIFO_INCREMENT( i_start );
#ifdef VDEC_SMP
vlc_mutex_unlock( &p_vpar->synchro.fifo_lock );
#endif
} }
/***************************************************************************** /*****************************************************************************
......
/*****************************************************************************
* 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 );
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* thread, and destroy a previously oppened video output thread. * thread, and destroy a previously oppened video output thread.
***************************************************************************** *****************************************************************************
* Copyright (C) 2000 VideoLAN * 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> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* *
...@@ -685,9 +685,6 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type, ...@@ -685,9 +685,6 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
#endif #endif
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
/* Initialize mutex */
vlc_mutex_init( &(p_free_picture->lock_deccount) );
return( p_free_picture ); return( p_free_picture );
} }
...@@ -725,9 +722,6 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -725,9 +722,6 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
intf_DbgMsg("picture %p", p_pic); intf_DbgMsg("picture %p", p_pic);
#endif #endif
/* destroy the lock that had been initialized in CreatePicture */
vlc_mutex_destroy( &(p_pic->lock_deccount) );
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment