]> git.sesse.net Git - vlc/commitdiff
* Rewrote the video decoder to take advantage of several processors (SMP mode) ;
authorChristophe Massiot <massiot@videolan.org>
Wed, 18 Jul 2001 14:21:00 +0000 (14:21 +0000)
committerChristophe Massiot <massiot@videolan.org>
Wed, 18 Jul 2001 14:21:00 +0000 (14:21 +0000)
* 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.

30 files changed:
Makefile
include/config.h.in
include/input_ext-intf.h
include/input_ext-plugins.h
include/modules_export.h
include/stream_control.h
include/threads.h
include/vdec_ext-plugins.h
include/video.h
src/input/input.c
src/input/input_clock.c
src/input/input_dec.c
src/input/input_ext-intf.c
src/interface/interface.c
src/interface/main.c
src/video_decoder/video_decoder.c
src/video_decoder/video_decoder.h
src/video_decoder/video_fifo.c [deleted file]
src/video_decoder/video_fifo.h [deleted file]
src/video_decoder/video_parser.c
src/video_decoder/video_parser.h
src/video_decoder/vpar_blocks.c
src/video_decoder/vpar_blocks.h [deleted file]
src/video_decoder/vpar_headers.c
src/video_decoder/vpar_headers.h [deleted file]
src/video_decoder/vpar_pool.c [new file with mode: 0644]
src/video_decoder/vpar_pool.h [new file with mode: 0644]
src/video_decoder/vpar_synchro.c
src/video_decoder/vpar_synchro.h [deleted file]
src/video_output/video_output.c

index 119e07965f609929cdbe8337e195aef64ecc4203..3ff62fdaacf058298e728b9d8fa7b060df73e121 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@ AC3_SPDIF := ac3_spdif ac3_iec958
 LPCM_DECODER := lpcm_decoder_thread
 AUDIO_DECODER := audio_decoder adec_generic adec_layer1 adec_layer2 adec_math
 SPU_DECODER := spu_decoder
-VIDEO_DECODER := video_parser vpar_headers vpar_blocks vpar_synchro video_fifo video_decoder
+VIDEO_DECODER := video_parser vpar_headers vpar_blocks vpar_synchro vpar_pool video_decoder
 MISC := mtime tests modules netutils
 
 C_OBJ :=       $(INTERFACE:%=src/interface/%.o) \
index 618fbd5adaf84c236df0ef80e9bbfade0afeef71..e918f0005fda1d09b8c8ba1118a3b86c25c84a03 100644 (file)
  * that raising this level dramatically lengthens the compilation time. */
 #define VPAR_OPTIM_LEVEL                2
 
-/* The following directives only apply if you define VDEC_SMP below. */
-
-/* Number of macroblock buffers available. It should be always greater than
- * twice the number of macroblocks in a picture. VFIFO_SIZE + 1 should also
- * be a power of two. */
-#define VFIFO_SIZE                      8191
-
 /* Maximum number of macroblocks in a picture. */
 #define MAX_MB                          2048
 
  * Video decoder configuration
  *****************************************************************************/
 
-//#define VDEC_SMP
-
 #define VDEC_IDLE_SLEEP                 ((int)(0.100*CLOCK_FREQ))
 
-/* Number of video_decoder threads to launch on startup of the video_parser.
- * It should always be less than half the number of macroblocks of a
- * picture. Only available if you defined VDEC_SMP above. */
-#define NB_VDEC                         1
-
 /* Maximum range of values out of the IDCT + motion compensation. */
 #define VDEC_CROPRANGE                  2048
 
-/* Nice increments for decoders -- necessary for x11 scheduling */
-#define VDEC_NICE                       3
-
-/*****************************************************************************
- * Generic decoder configuration
- *****************************************************************************/
+/* Environment variable containing the SMP value. */
+#define VDEC_SMP_VAR                   "vlc_smp"
 
-#define GDEC_IDLE_SLEEP                 ((int)(0.100*CLOCK_FREQ))
+/* No SMP by default, since it slows down things on non-smp machines. */
+#define VDEC_SMP_DEFAULT               0
 
 /*****************************************************************************
  * Messages and console interfaces configuration
index d48282b8e9c1ec98a112a0378219d51d27ec52be..efb07513918ecc32dc53baaa3719b69ff5ef6b73 100644 (file)
@@ -4,7 +4,7 @@
  * control the pace of reading. 
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-intf.h,v 1.40 2001/06/27 09:53:56 massiot Exp $
+ * $Id: input_ext-intf.h,v 1.41 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -205,6 +205,7 @@ typedef struct stream_descriptor_s
 
     /* New status and rate requested by the interface */
     int                     i_new_status, i_new_rate;
+    int                     b_new_mute;          /* int because it can be -1 */
     vlc_cond_t              stream_wait; /* interface -> input in case of a
                                           * status change request            */
 
@@ -229,6 +230,8 @@ typedef struct stream_descriptor_s
     stream_ctrl_t           control;
 } stream_descriptor_t;
 
+#define MUTE_NO_CHANGE      -1
+
 /*****************************************************************************
  * i_p_config_t
  *****************************************************************************
@@ -360,7 +363,6 @@ struct input_thread_s * input_CreateThread ( struct playlist_item_s *,
 void input_DestroyThread( struct input_thread_s *, int *pi_status );
 
 void input_SetStatus( struct input_thread_s *, int );
-void input_SetRate  ( struct input_thread_s *, int );
 void input_Seek     ( struct input_thread_s *, off_t );
 void input_DumpStream( struct input_thread_s * );
 char * input_OffsetToTime( struct input_thread_s *, char * psz_buffer, off_t );
@@ -368,5 +370,8 @@ int  input_ChangeES ( struct input_thread_s *, struct es_descriptor_s *, u8 );
 int  input_ToggleES ( struct input_thread_s *,
                       struct es_descriptor_s *,
                       boolean_t );
-int  input_ChangeArea( input_thread_t *, input_area_t * );
+int  input_ChangeArea( struct input_thread_s *, struct input_area_s * );
+int  input_ToggleGrayscale( struct input_thread_s * );
+int  input_ToggleMute( struct input_thread_s * );
+int  input_SetSMP( struct input_thread_s *, int );
 
index 6e7f7ddc20b98637396bacc493bdb36d04d770fb..b01bd0ae44286c421b8b469012ececb6f8be011d 100644 (file)
@@ -3,7 +3,7 @@
  *                      but exported to plug-ins
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: input_ext-plugins.h,v 1.1 2001/07/17 09:48:07 massiot Exp $
+ * $Id: input_ext-plugins.h,v 1.2 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -74,8 +74,7 @@ void input_EndDecoder( struct input_thread_s *, struct es_descriptor_s * );
 void input_DecodePES ( struct decoder_fifo_s *, struct pes_packet_s * );
 void input_EscapeDiscontinuity( struct input_thread_s *,
                                 struct pgrm_descriptor_s * );
-void input_EscapeAudioDiscontinuity( struct input_thread_s *,
-                                     struct pgrm_descriptor_s * );
+void input_EscapeAudioDiscontinuity( struct input_thread_s * );
 
 /*****************************************************************************
  * Prototypes from input_clock.c
index bd785dd1589a305424c51efa13dc4fc284f4d2b5..293d700627ddf695550bba398754f2445c71584b 100644 (file)
@@ -62,7 +62,6 @@ typedef struct module_symbols_s
     int  ( * network_ChannelJoin )  ( int );
 
     void ( * input_SetStatus )      ( struct input_thread_s *, int );
-    void ( * input_SetRate )        ( struct input_thread_s *, int );
     void ( * input_Seek )           ( struct input_thread_s *, off_t );
     void ( * input_DumpStream )     ( struct input_thread_s * );
     char * ( * input_OffsetToTime ) ( struct input_thread_s *, char *, off_t );
@@ -152,7 +151,6 @@ typedef struct module_symbols_s
     (p_symbols)->network_ChannelCreate = network_ChannelCreate; \
     (p_symbols)->network_ChannelJoin = network_ChannelJoin; \
     (p_symbols)->input_SetStatus = input_SetStatus; \
-    (p_symbols)->input_SetRate = input_SetRate; \
     (p_symbols)->input_Seek = input_Seek; \
     (p_symbols)->input_DumpStream = input_DumpStream; \
     (p_symbols)->input_OffsetToTime = input_OffsetToTime; \
@@ -238,7 +236,6 @@ extern module_symbols_t* p_symbols;
 #   define network_ChannelJoin(a) p_symbols->network_ChannelJoin(a)
 
 #   define input_SetStatus(a,b) p_symbols->input_SetStatus(a,b)
-#   define input_SetRate(a,b) p_symbols->input_SetRate(a,b)
 #   define input_Seek(a,b) p_symbols->input_Seek(a,b)
 #   define input_DumpStream(a) p_symbols->input_DumpStream(a)
 #   define input_OffsetToTime(a,b,c) p_symbols->input_OffsetToTime(a,b,c)
index ab4fcdfbfa894b738bbeb57838bb3bbe48ec78cc..acaaa4b50835d1833ec6401d535a591687315cc2 100644 (file)
@@ -4,7 +4,7 @@
  * of the reading.
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: stream_control.h,v 1.5 2001/02/08 13:52:34 massiot Exp $
+ * $Id: stream_control.h,v 1.6 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -39,7 +39,9 @@ typedef struct stream_ctrl_s
     int                     i_rate;
 
     boolean_t               b_mute;
-    boolean_t               b_bw;                           /* black & white */
+    boolean_t               b_grayscale;           /* use color or grayscale */
+    int                     i_smp; /* number of symmetrical threads to launch
+                                    * to decode the video | 0 == disabled    */
 } stream_ctrl_t;
 
 /* Possible status : */
index fdbaa4f9cfabeb1268b9b61f052b1c7aa37bd453..a43129630d11f00cec17758f339c355d0f331430 100644 (file)
@@ -3,7 +3,7 @@
  * This header provides a portable threads implementation.
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: threads.h,v 1.19 2001/06/14 20:21:04 sam Exp $
+ * $Id: threads.h,v 1.20 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *          Samuel Hocevar <sam@via.ecp.fr>
@@ -491,6 +491,74 @@ static __inline__ int vlc_cond_signal( vlc_cond_t *p_condvar )
 #endif
 }
 
+/*****************************************************************************
+ * vlc_cond_broadcast: start all threads waiting on condition completion
+ *****************************************************************************/
+/*
+ * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
+ * Only works with pthreads, you need to adapt it for others
+ * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
+ */
+static __inline__ int vlc_cond_broadcast( vlc_cond_t *p_condvar )
+{
+#if defined( PTH_INIT_IN_PTH_H )
+    return pth_cond_notify( p_condvar, FALSE );
+
+#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
+    return pthread_cond_broadcast( p_condvar );
+
+#elif defined( HAVE_CTHREADS_H )
+    /* condition_signal() */
+    if ( p_condvar->queue.head || p_condvar->implications )
+    {
+        cond_signal( (condition_t)p_condvar );
+    }
+    return 0;
+
+#elif defined( HAVE_KERNEL_SCHEDULER_H )
+    if( !p_condvar )
+    {
+        return B_BAD_VALUE;
+    }
+
+    if( p_condvar->init < 2000 )
+    {
+        return B_NO_INIT;
+    }
+
+    while( p_condvar->thread != -1 )
+    {
+        thread_info info;
+        if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
+        {
+            return 0;
+        }
+
+        if( info.state != B_THREAD_SUSPENDED )
+        {
+            /* The  waiting thread is not suspended so it could
+             * have been interrupted beetwen the unlock and the
+             * suspend_thread line. That is why we sleep a little
+             * before retesting p_condver->thread. */
+            snooze( 10000 );
+        }
+        else
+        {
+            /* Ok, we have to wake up that thread */
+            resume_thread( p_condvar->thread );
+            return 0;
+        }
+    }
+    return 0;
+
+#elif defined( WIN32 )
+    /* Try to release one waiting thread. */
+    PulseEvent ( *p_condvar );
+    return 0;
+
+#endif
+}
+
 /*****************************************************************************
  * vlc_cond_wait: wait until condition completion
  *****************************************************************************/
index 9c8a581fbd01f5d13b3b7b0491e37c1c2bd5d99b..bcd01e50dd35f61ad40dc028226a0ddd8c66fc23 100644 (file)
@@ -2,7 +2,7 @@
  * vdec_common.h : structures from the video decoder exported to plug-ins
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vdec_ext-plugins.h,v 1.1 2001/07/17 09:48:07 massiot Exp $
+ * $Id: vdec_ext-plugins.h,v 1.2 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -98,24 +98,13 @@ typedef struct macroblock_s
  *****************************************************************************/
 typedef struct vdec_thread_s
 {
-    /* Thread properties and locks */
-    boolean_t           b_die;                                 /* `die' flag */
-    boolean_t           b_run;                                 /* `run' flag */
-    boolean_t           b_error;                             /* `error' flag */
-    boolean_t           b_active;                           /* `active' flag */
     vlc_thread_t        thread_id;                /* id for thread functions */
+    boolean_t           b_die;
 
     /* IDCT iformations */
-    void *                     p_idct_data;
-    dctelem_t              p_pre_idct[64*64];
-
-    /* Macroblock copy functions */
-    void ( * pf_decode_init ) ( struct vdec_thread_s * );
-    void ( * pf_decode_mb_c ) ( struct vdec_thread_s *, struct macroblock_s * );
-    void ( * pf_decode_mb_bw )( struct vdec_thread_s *, struct macroblock_s * );
+    void *              p_idct_data;
 
     /* Input properties */
-    struct vpar_thread_s * p_vpar;                    /* video_parser thread */
-
+    struct vdec_pool_s * p_pool;
 } vdec_thread_t;
 
index c2990ef166561d8b4c808eda8db60a234947705d..e90a0d9ecd48ad7ca86eb7093e154b788c1b0961 100644 (file)
@@ -4,7 +4,7 @@
  * includes all common video types and constants.
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video.h,v 1.30 2001/05/07 04:42:42 sam Exp $
+ * $Id: video.h,v 1.31 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *
@@ -71,11 +71,6 @@ typedef struct picture_s
     int             i_display_height;               /* useful picture height */
     int             i_aspect_ratio;                          /* aspect ratio */
 
-    /* Macroblock counter - the decoder use it to verify if it has
-     * decoded all the macroblocks of the picture */
-    int             i_deccount;
-    vlc_mutex_t     lock_deccount;
-
     /* Picture data - data can always be freely modified. p_data itself
      * (the pointer) should NEVER be modified. In YUV format, the p_y, p_u and
      * p_v data pointers refers to different areas of p_data, and should not
index 352fd39f4550174014df9fc7a2b175000a8252dc..3e532d5c423c2c0c8a8f2622af2da4d24c216025 100644 (file)
@@ -4,7 +4,7 @@
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input.c,v 1.126 2001/07/17 09:48:08 massiot Exp $
+ * $Id: input.c,v 1.127 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -138,6 +138,7 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
     p_input->stream.i_selected_es_number = 0;
     p_input->stream.i_pgrm_number = 0;
     p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
+    p_input->stream.b_new_mute = MUTE_NO_CHANGE;
     p_input->stream.i_mux_rate = 0;
 
     /* no stream, no area */
@@ -154,7 +155,10 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
     p_input->stream.control.i_status = PLAYING_S;
     p_input->stream.control.i_rate = DEFAULT_RATE;
     p_input->stream.control.b_mute = 0;
-    p_input->stream.control.b_bw = 0;
+    p_input->stream.control.b_grayscale = main_GetIntVariable(
+                            VOUT_GRAYSCALE_VAR, VOUT_GRAYSCALE_DEFAULT );
+    p_input->stream.control.i_smp = main_GetIntVariable(
+                            VDEC_SMP_VAR, VDEC_SMP_DEFAULT );
 
     /* Setup callbacks */
     p_input->pf_file_open     = FileOpen;
@@ -322,6 +326,20 @@ static void RunThread( input_thread_t *p_input )
             p_input->stream.p_newly_selected_es = NULL;
         }
 
+        if( p_input->stream.b_new_mute != MUTE_NO_CHANGE )
+        {
+            if( p_input->stream.b_new_mute )
+            {
+                input_EscapeAudioDiscontinuity( p_input );
+            }
+
+            vlc_mutex_lock( &p_input->stream.control.control_lock );
+            p_input->stream.control.b_mute = p_input->stream.b_new_mute;
+            vlc_mutex_unlock( &p_input->stream.control.control_lock );
+
+            p_input->stream.b_new_mute = MUTE_NO_CHANGE;
+        }
+
         vlc_mutex_unlock( &p_input->stream.stream_lock );
 
         i_error = p_input->pf_read( p_input, pp_packets );
index 31c1bc936c4126f70e19827c68c1b83398df0043..1b93e45138b1be4e7f9848a4f0e4ae62dd744bd2 100644 (file)
@@ -2,7 +2,7 @@
  * input_clock.c: Clock/System date convertions, stream management
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_clock.c,v 1.19 2001/07/17 09:48:08 massiot Exp $
+ * $Id: input_clock.c,v 1.20 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -197,7 +197,7 @@ int input_ClockManageControl( input_thread_t * p_input,
 
             /* Feed the audio decoders with a NULL packet to avoid
              * discontinuities. */
-            input_EscapeAudioDiscontinuity( p_input, p_pgrm );
+            input_EscapeAudioDiscontinuity( p_input );
         }
 
         p_input->stream.i_new_status = UNDEF_S;
index 2017345b5a880cc9789efb7144e37eaebf3c733e..eb53c053311c62eab0b84924ac7166b376b9c6e2 100644 (file)
@@ -2,7 +2,7 @@
  * input_dec.c: Functions for the management of decoders
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_dec.c,v 1.12 2001/07/17 09:48:08 massiot Exp $
+ * $Id: input_dec.c,v 1.13 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -147,20 +147,24 @@ void input_EscapeDiscontinuity( input_thread_t * p_input,
 /*****************************************************************************
  * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
  *****************************************************************************/
-void input_EscapeAudioDiscontinuity( input_thread_t * p_input,
-                                     pgrm_descriptor_t * p_pgrm )
+void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
 {
-    int     i_es, i;
+    int     i_pgrm, i_es, i;
 
-    for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
+    for( i_pgrm = 0; i_pgrm < p_input->stream.i_pgrm_number; i_pgrm++ )
     {
-        es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
+        pgrm_descriptor_t * p_pgrm = p_input->stream.pp_programs[i_pgrm];
 
-        if( p_es->p_decoder_fifo != NULL && p_es->b_audio )
+        for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
         {
-            for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
+            es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
+
+            if( p_es->p_decoder_fifo != NULL && p_es->b_audio )
             {
-                input_NullPacket( p_input, p_es );
+                for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
+                {
+                    input_NullPacket( p_input, p_es );
+                }
             }
         }
     }
index 753c0184385e3900564f20a57e3954640971bd38..9d1c2380cae38831518b5a70e1f58270dd52e8df 100644 (file)
@@ -2,7 +2,7 @@
  * input_ext-intf.c: services to the interface
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input_ext-intf.c,v 1.26 2001/07/17 09:48:08 massiot Exp $
+ * $Id: input_ext-intf.c,v 1.27 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -128,14 +128,6 @@ void input_SetStatus( input_thread_t * p_input, int i_mode )
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 }
 
-/*****************************************************************************
- * input_SetRate: change the reading rate
- *****************************************************************************/
-void input_SetRate( input_thread_t * p_input, int i_mode )
-{
-    ; /* FIXME: stub */
-}
 /*****************************************************************************
  * input_Seek: changes the stream postion
  *****************************************************************************/
@@ -339,3 +331,55 @@ int input_ChangeArea( input_thread_t * p_input, input_area_t * p_area )
 
     return 0;
 }
+
+/****************************************************************************
+ * input_ToggleGrayscale: change to grayscale or color output
+ ****************************************************************************/
+int input_ToggleGrayscale( input_thread_t * p_input )
+{
+    /* No need to warn the input thread since only the decoders and outputs
+     * worry about it. */
+    vlc_mutex_lock( &p_input->stream.control.control_lock );
+    p_input->stream.control.b_grayscale =
+                    !p_input->stream.control.b_grayscale;
+
+    intf_WarnMsg( 3, "input warning: changing to %s output",
+            p_input->stream.control.b_grayscale ? "grayscale" : "color" );
+
+    vlc_mutex_unlock( &p_input->stream.control.control_lock );
+
+    return 0;
+}
+
+/****************************************************************************
+ * input_ToggleMute: activate/deactivate mute mode
+ ****************************************************************************/
+int input_ToggleMute( input_thread_t * p_input )
+{
+    /* We need to feed the decoders with 0, and only input can do that, so
+     * pass the message to the input thread. */
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    p_input->stream.b_new_mute = !p_input->stream.control.b_mute;
+
+    intf_WarnMsg( 3, "input warning: %s mute mode",
+            p_input->stream.control.b_mute ? "activating" : "deactivating" );
+
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+    return 0;
+}
+
+/****************************************************************************
+ * input_SetSMP: change the number of video decoder threads
+ ****************************************************************************/
+int input_SetSMP( input_thread_t * p_input, int i_smp )
+{
+    /* No need to warn the input thread since only the decoders
+     * worry about it. */
+    vlc_mutex_lock( &p_input->stream.control.control_lock );
+    p_input->stream.control.i_smp = i_smp;
+    vlc_mutex_unlock( &p_input->stream.control.control_lock );
+
+    return 0;
+}
+
index 15687a937caa2e1f7c1757c2e02e4f9f95af1c04..3b22d42445bc6e8fd642887d6d614413deade5d0 100644 (file)
@@ -4,7 +4,7 @@
  * interface, such as command line.
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: interface.c,v 1.79 2001/05/15 14:49:48 stef Exp $
+ * $Id: interface.c,v 1.80 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *
@@ -394,6 +394,13 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
         break;
 
     case INTF_KEY_TOGGLE_VOLUME:                              /* toggle mute */
+        /* Start/stop feeding audio data. */
+        if( p_intf->p_input != NULL )
+        {
+            input_ToggleMute( p_intf->p_input );
+        }
+
+        /* Start/stop playing sound. */
         vlc_mutex_lock( &p_aout_bank->lock );
         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
         {
index 459b880c78b09fdd94d31a0196733b56fa90e193..442955b40383024651abfbf317ad6edf41974312 100644 (file)
@@ -4,7 +4,7 @@
  * and spawn threads.
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: main.c,v 1.107 2001/07/16 22:00:45 gbazin Exp $
+ * $Id: main.c,v 1.108 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
 #define OPT_COLOR               164
 #define OPT_FULLSCREEN          165
 #define OPT_OVERLAY             166
+#define OPT_SMP                 167
 
 #define OPT_CHANNELS            170
 #define OPT_SERVER              171
@@ -183,6 +184,7 @@ static const struct option longopts[] =
     {   "yuv",              1,          0,      OPT_YUV },
     {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
     {   "overlay",          0,          0,      OPT_OVERLAY },
+    {   "smp",              1,          0,      OPT_SMP },
 
     /* DVD options */
     {   "dvdtitle",         1,          0,      't' },
@@ -693,6 +695,9 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
         case OPT_YUV:                                               /* --yuv */
             main_PutPszVariable( YUV_METHOD_VAR, optarg );
             break;
+        case OPT_SMP:                                               /* --smp */
+            main_PutIntVariable( VDEC_SMP_VAR, atoi(optarg) );
+            break;
 
         /* DVD options */
         case 't':
@@ -836,6 +841,7 @@ static void Usage( int i_fashion )
           "\n      --idct <module>            \tIDCT method"
           "\n      --yuv <module>             \tYUV method"
           "\n      --synchro <type>           \tforce synchro algorithm"
+          "\n      --smp <number of threads>  \tuse several processors"
           "\n"
           "\n  -t, --dvdtitle <num>           \tchoose DVD title"
           "\n  -T, --dvdchapter <num>         \tchoose DVD chapter"
@@ -887,7 +893,8 @@ static void Usage( int i_fashion )
         "\n  " MOTION_METHOD_VAR "=<method name>      \tmotion compensation method"
         "\n  " IDCT_METHOD_VAR "=<method name>        \tIDCT method"
         "\n  " YUV_METHOD_VAR "=<method name>         \tYUV method"
-        "\n  " VPAR_SYNCHRO_VAR "={I|I+|IP|IP+|IPB}   \tsynchro algorithm" );
+        "\n  " VPAR_SYNCHRO_VAR "={I|I+|IP|IP+|IPB}   \tsynchro algorithm"
+        "\n  " VDEC_SMP_VAR "=<number of threads>     \tuse several processors" );
 
     /* DVD parameters */
     intf_MsgImm( "\nDVD parameters:"
index 8f2a28cddaae5389314e7bc207161c49cb3243f3..8acd39680dc9543eabb7707ae1c08b2278f68b0c 100644 (file)
@@ -2,7 +2,7 @@
  * video_decoder.c : video decoder thread
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_decoder.c,v 1.53 2001/07/17 09:48:08 massiot Exp $
+ * $Id: video_decoder.c,v 1.54 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Gaël Hendryckx <jimmy@via.ecp.fr>
 
 #include "vdec_ext-plugins.h"
 #include "video_decoder.h"
-
-#include "vpar_blocks.h"
-#include "vpar_headers.h"
-#include "vpar_synchro.h"
-#include "video_parser.h"
-#include "video_fifo.h"
+#include "vpar_pool.h"
 
 /*
  * Local prototypes
  */
-#ifdef VDEC_SMP
-static int      vdec_InitThread     ( vdec_thread_t *p_vdec );
-#endif
 static void     RunThread           ( vdec_thread_t *p_vdec );
-static void     ErrorThread         ( vdec_thread_t *p_vdec );
-static void     EndThread           ( vdec_thread_t *p_vdec );
 
 /*****************************************************************************
  * vdec_CreateThread: create a video decoder thread
  *****************************************************************************
  * This function creates a new video decoder thread, and returns a pointer
  * to its description. On error, it returns NULL.
- * Following configuration properties are used:
- * XXX??
  *****************************************************************************/
-vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
+vdec_thread_t * vdec_CreateThread( vdec_pool_t * p_pool )
 {
     vdec_thread_t *     p_vdec;
 
@@ -92,12 +80,11 @@ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
      * Initialize the thread properties
      */
     p_vdec->b_die = 0;
-    p_vdec->b_error = 0;
 
     /*
      * Initialize the parser properties
      */
-    p_vdec->p_vpar = p_vpar;
+    p_vdec->p_pool = p_pool;
 
     /* Spawn the video decoder thread */
     if ( vlc_thread_create(&p_vdec->thread_id, "video decoder",
@@ -114,27 +101,20 @@ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
 
 /*****************************************************************************
  * vdec_DestroyThread: destroy a video decoder thread
- *****************************************************************************
- * Destroy and terminate thread. This function will return 0 if the thread could
- * be destroyed, and non 0 else. The last case probably means that the thread
- * was still active, and another try may succeed.
  *****************************************************************************/
-void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
+void vdec_DestroyThread( vdec_thread_t *p_vdec )
 {
     intf_DbgMsg("vdec debug: requesting termination of video decoder thread %p", p_vdec);
 
     /* Ask thread to kill itself */
     p_vdec->b_die = 1;
 
-#ifdef VDEC_SMP
     /* Make sure the decoder thread leaves the vpar_GetMacroblock() function */
-    vlc_mutex_lock( &(p_vdec->p_vpar->vfifo.lock) );
-    vlc_cond_signal( &(p_vdec->p_vpar->vfifo.wait) );
-    vlc_mutex_unlock( &(p_vdec->p_vpar->vfifo.lock) );
-#endif
+    vlc_mutex_lock( &p_vdec->p_pool->lock );
+    vlc_cond_broadcast( &p_vdec->p_pool->wait_undecoded );
+    vlc_mutex_unlock( &p_vdec->p_pool->lock );
 
     /* Waiting for the decoder thread to exit */
-    /* Remove this as soon as the "status" flag is implemented */
     vlc_thread_join( p_vdec->thread_id );
 }
 
@@ -144,65 +124,28 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
  * vdec_InitThread: initialize video decoder thread
  *****************************************************************************
  * This function is called from RunThread and performs the second step of the
- * initialization. It returns 0 on success. Note that the thread's flag are not
- * modified inside this function.
+ * initialization.
  *****************************************************************************/
-#ifdef VDEC_SMP
-static int vdec_InitThread( vdec_thread_t *p_vdec )
-#else
-int vdec_InitThread( vdec_thread_t *p_vdec )
-#endif
+void vdec_InitThread( vdec_thread_t *p_vdec )
 {
     intf_DbgMsg("vdec debug: initializing video decoder thread %p", p_vdec);
 
     p_vdec->p_idct_data = NULL;
 
-    p_vdec->pf_decode_init  = p_vdec->p_vpar->pf_decode_init;
-    p_vdec->pf_decode_mb_c  = p_vdec->p_vpar->pf_decode_mb_c;
-    p_vdec->pf_decode_mb_bw = p_vdec->p_vpar->pf_decode_mb_bw;
-
-    p_vdec->pf_decode_init( p_vdec );
-
-#ifdef VDEC_SMP
-    /* Re-nice ourself */
-    if( nice(VDEC_NICE) == -1 )
-    {
-        intf_WarnMsg( 2, "vdec warning : couldn't nice() (%s)",
-                      strerror(errno) );
-    }
-#endif
+    p_vdec->p_pool->pf_decode_init( p_vdec );
+    p_vdec->p_pool->pf_idct_init( p_vdec );
 
     /* Mark thread as running and return */
     intf_DbgMsg("vdec debug: InitThread(%p) succeeded", p_vdec);
-    return( 0 );
-}
-
-/*****************************************************************************
- * ErrorThread: RunThread() error loop
- *****************************************************************************
- * This function is called when an error occured during thread main's loop. The
- * thread can still receive feed, but must be ready to terminate as soon as
- * possible.
- *****************************************************************************/
-static void ErrorThread( vdec_thread_t *p_vdec )
-{
-    macroblock_t *       p_mb;
-
-    /* Wait until a `die' order */
-    while( !p_vdec->b_die )
-    {
-        p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo );
-        vpar_DestroyMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
-    }
 }
 
 /*****************************************************************************
- * EndThread: thread destruction
+ * vdec_EndThread: thread destruction
  *****************************************************************************
  * This function is called when the thread ends after a sucessful
  * initialization.
  *****************************************************************************/
-static void EndThread( vdec_thread_t *p_vdec )
+void vdec_EndThread( vdec_thread_t *p_vdec )
 {
     intf_DbgMsg("vdec debug: EndThread(%p)", p_vdec);
 
@@ -210,6 +153,8 @@ static void EndThread( vdec_thread_t *p_vdec )
     {
         free( p_vdec->p_idct_data );
     }
+
+    free( p_vdec );
 }
 
 /*****************************************************************************
@@ -223,44 +168,26 @@ static void RunThread( vdec_thread_t *p_vdec )
     intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)",
                 p_vdec, getpid());
 
-    /*
-     * Initialize thread and free configuration
-     */
-    p_vdec->b_error = vdec_InitThread( p_vdec );
-    if( p_vdec->b_error )
-    {
-        return;
-    }
-    p_vdec->b_run = 1;
+    vdec_InitThread( p_vdec );
 
     /*
-     * Main loop - it is not executed if an error occured during
-     * initialization
+     * Main loop
      */
-    while( (!p_vdec->b_die) && (!p_vdec->b_error) )
+    while( !p_vdec->b_die )
     {
         macroblock_t *          p_mb;
 
-        if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL )
+        if( (p_mb = vpar_GetMacroblock( p_vdec->p_pool, &p_vdec->b_die )) != NULL )
         {
-            p_vdec->pf_decode_mb_c( p_vdec, p_mb );
+            p_vdec->p_pool->pf_vdec_decode( p_vdec, p_mb );
 
             /* Decoding is finished, release the macroblock and free
              * unneeded memory. */
-            vpar_ReleaseMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
+            p_vdec->p_pool->pf_free_mb( p_vdec->p_pool, p_mb );
         }
     }
 
-    /*
-     * Error loop
-     */
-    if( p_vdec->b_error )
-    {
-        ErrorThread( p_vdec );
-    }
-
     /* End of thread */
-    EndThread( p_vdec );
-    p_vdec->b_run = 0;
+    vdec_EndThread( p_vdec );
 }
 
index c34aad415583005e2c68fde57431ab9db45f32db..b7b33e035527f471c285af83b516a602cba64a57 100644 (file)
@@ -2,7 +2,7 @@
  * video_decoder.h : video decoder thread
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_decoder.h,v 1.3 2001/07/17 09:48:08 massiot Exp $
+ * $Id: video_decoder.h,v 1.4 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
  
-/*****************************************************************************
- * Requires:
- *  "config.h"
- *  "common.h"
- *  "mtime.h"
- *  "threads.h"
- *  "input.h"
- *  "video.h"
- *  "video_output.h"
- *  "decoder_fifo.h"
- *****************************************************************************/
-
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
@@ -40,15 +28,14 @@ struct vpar_thread_s;
 struct macroblock_s;
 
 /* Thread management functions */
-#ifndef VDEC_SMP
-int             vdec_InitThread         ( struct vdec_thread_s *p_vdec );
-#endif
+void            vdec_InitThread         ( struct vdec_thread_s *p_vdec );
+void            vdec_EndThread          ( struct vdec_thread_s *p_vdec );
 void            vdec_DecodeMacroblock   ( struct vdec_thread_s *p_vdec,
                                           struct macroblock_s *p_mb );
 void            vdec_DecodeMacroblockC  ( struct vdec_thread_s *p_vdec,
                                           struct macroblock_s *p_mb );
 void            vdec_DecodeMacroblockBW ( struct vdec_thread_s *p_vdec,
                                           struct macroblock_s *p_mb );
-struct vdec_thread_s * vdec_CreateThread( struct vpar_thread_s *p_vpar );
+struct vdec_thread_s * vdec_CreateThread( struct vdec_pool_s * );
 void            vdec_DestroyThread      ( struct vdec_thread_s *p_vdec );
 
diff --git a/src/video_decoder/video_fifo.c b/src/video_decoder/video_fifo.c
deleted file mode 100644 (file)
index d9cfc5c..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*****************************************************************************
- * 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
-}
-
diff --git a/src/video_decoder/video_fifo.h b/src/video_decoder/video_fifo.h
deleted file mode 100644 (file)
index ee2f2a8..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*****************************************************************************
- * 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 );
index c970f5c571b952edd8bb09f692e1ba0cda22fd58..e74239add7f24d0d697921cbd9dc94c12422c20b 100644 (file)
@@ -2,7 +2,7 @@
  * video_parser.c : video parser thread
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_parser.c,v 1.2 2001/07/17 09:48:08 massiot Exp $
+ * $Id: video_parser.c,v 1.3 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Samuel Hocevar <sam@via.ecp.fr>
 #include "video_output.h"
 
 #include "vdec_ext-plugins.h"
-#include "video_decoder.h"
-
-#include "vpar_blocks.h"
-#include "vpar_headers.h"
-#include "vpar_synchro.h"
+#include "vpar_pool.h"
 #include "video_parser.h"
-#include "video_fifo.h"
 
 /*
  * Local prototypes
@@ -99,6 +94,34 @@ vlc_thread_t vpar_CreateThread( vdec_config_t * p_config )
     p_vpar->p_config = p_config;
     p_vpar->p_vout = NULL;
 
+    /* Spawn the video parser thread */
+    if ( vlc_thread_create( &p_vpar->thread_id, "video parser",
+                            (vlc_thread_func_t)RunThread, (void *)p_vpar ) )
+    {
+        intf_ErrMsg("vpar error: can't spawn video parser thread");
+        module_Unneed( p_vpar->p_idct_module );
+        module_Unneed( p_vpar->p_motion_module );
+        free( p_vpar );
+        return( 0 );
+    }
+
+    intf_DbgMsg("vpar debug: video parser thread (%p) created", p_vpar);
+    return( p_vpar->thread_id );
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * InitThread: initialize vpar output thread
+ *****************************************************************************
+ * This function is called from RunThread and performs the second step of the
+ * initialization. It returns 0 on success. Note that the thread's flag are not
+ * modified inside this function.
+ *****************************************************************************/
+static int InitThread( vpar_thread_t *p_vpar )
+{
+    intf_DbgMsg("vpar debug: initializing video parser thread %p", p_vpar);
+
     /*
      * Choose the best motion compensation module
      */
@@ -164,9 +187,9 @@ vlc_thread_t vpar_CreateThread( vdec_config_t * p_config )
 #undef S
 #undef M
 
-     /*
-      * Choose the best IDCT module
-      */
+    /*
+     * Choose the best IDCT module
+     */
     p_vpar->p_idct_module = module_Need( MODULE_CAPABILITY_IDCT, NULL );
 
     if( p_vpar->p_idct_module == NULL )
@@ -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
-    p_vpar->pf_idct_init    = f.pf_idct_init;
+    p_vpar->pool.pf_idct_init    = f.pf_idct_init;
     p_vpar->pf_sparse_idct  = f.pf_sparse_idct;
     p_vpar->pf_idct         = f.pf_idct;
     p_vpar->pf_norm_scan    = f.pf_norm_scan;
-    p_vpar->pf_decode_init  = f.pf_decode_init;
+    p_vpar->pool.pf_decode_init  = f.pf_decode_init;
     p_vpar->pf_decode_mb_c  = f.pf_decode_mb_c;
     p_vpar->pf_decode_mb_bw = f.pf_decode_mb_bw;
 #undef f
 
-    /* Spawn the video parser thread */
-    if ( vlc_thread_create( &p_vpar->thread_id, "video parser",
-                            (vlc_thread_func_t)RunThread, (void *)p_vpar ) )
-    {
-        intf_ErrMsg("vpar error: can't spawn video parser thread");
-        module_Unneed( p_vpar->p_idct_module );
-        module_Unneed( p_vpar->p_motion_module );
-        free( p_vpar );
-        return( 0 );
-    }
-
-    intf_DbgMsg("vpar debug: video parser thread (%p) created", p_vpar);
-    return( p_vpar->thread_id );
-}
-
-/* following functions are local */
-
-/*****************************************************************************
- * InitThread: initialize vpar output thread
- *****************************************************************************
- * This function is called from RunThread and performs the second step of the
- * initialization. It returns 0 on success. Note that the thread's flag are not
- * modified inside this function.
- *****************************************************************************/
-static int InitThread( vpar_thread_t *p_vpar )
-{
-#ifdef VDEC_SMP
-    int i_dummy;
-#endif
-
-    intf_DbgMsg("vpar debug: initializing video parser thread %p", p_vpar);
-
+    /* Initialize input bitstream */
     p_vpar->p_config->decoder_config.pf_init_bit_stream( &p_vpar->bit_stream,
         p_vpar->p_config->decoder_config.p_decoder_fifo, BitstreamCallback,
         (void *)p_vpar );
@@ -253,51 +245,6 @@ static int InitThread( vpar_thread_t *p_vpar )
            sizeof(p_vpar->pc_malformed_pictures));
 #endif
 
-    /* Initialize video FIFO */
-    vpar_InitFIFO( p_vpar );
-
-    memset( p_vpar->pp_vdec, 0, NB_VDEC*sizeof(vdec_thread_t *) );
-
-#ifdef VDEC_SMP
-    /* Spawn video_decoder threads */
-    /* FIXME: modify the number of vdecs at runtime ?? */
-    for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
-    {
-        if( (p_vpar->pp_vdec[i_dummy] = vdec_CreateThread( p_vpar )) == NULL )
-        {
-            return( 1 );
-        }
-    }
-#else
-    /* Fake a video_decoder thread */
-    p_vpar->pp_vdec[0] = (vdec_thread_t *)malloc(sizeof( vdec_thread_t ));
-
-    if( p_vpar->pp_vdec[0] == NULL )
-    {
-        return( 1 );
-    }
-
-    p_vpar->pp_vdec[0]->b_die = 0;
-    p_vpar->pp_vdec[0]->b_error = 0;
-    p_vpar->pp_vdec[0]->p_vpar = p_vpar;
-
-    if( vdec_InitThread( p_vpar->pp_vdec[0] ) )
-    {
-        return( 1 );
-    }
-
-#   if !defined(SYS_BEOS) && !defined(WIN32)
-#       if VDEC_NICE
-    /* Re-nice ourself */
-    if( nice(VDEC_NICE) == -1 )
-    {
-        intf_WarnMsg( 2, "vpar warning : couldn't nice() (%s)",
-                      strerror(errno) );
-    }
-#       endif
-#   endif
-#endif
-
     /* Initialize lookup tables */
     vpar_InitMbAddrInc( p_vpar );
     vpar_InitDCTTables( p_vpar );
@@ -311,6 +258,9 @@ static int InitThread( vpar_thread_t *p_vpar )
      */
     vpar_SynchroInit( p_vpar );
 
+    /* Spawn optional video decoder threads */
+    vpar_InitPool( p_vpar );
+
     /* Mark thread as running and return */
     intf_DbgMsg("vpar debug: InitThread(%p) succeeded", p_vpar);
     return( 0 );
@@ -350,7 +300,7 @@ static void RunThread( vpar_thread_t *p_vpar )
             {
                 /* End of sequence */
                 break;
-            };
+            }
         }
     }
 
@@ -406,10 +356,6 @@ static void ErrorThread( vpar_thread_t *p_vpar )
  *****************************************************************************/
 static void EndThread( vpar_thread_t *p_vpar )
 {
-#ifdef VDEC_SMP
-    int i_dummy;
-#endif
-
     intf_DbgMsg("vpar debug: destroying video parser thread %p", p_vpar);
 
     /* Release used video buffers. */
@@ -489,30 +435,10 @@ static void EndThread( vpar_thread_t *p_vpar )
         free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
     }
 
-#ifdef VDEC_SMP
-    /* Destroy vdec threads */
-    for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
-    {
-        if( p_vpar->pp_vdec[i_dummy] != NULL )
-            vdec_DestroyThread( p_vpar->pp_vdec[i_dummy] );
-        else
-            break;
-    }
-#else
-    free( p_vpar->pp_vdec[0] );
-#endif
+    vpar_EndPool( p_vpar );
 
     free( p_vpar->p_config );
 
-#ifdef VDEC_SMP
-    /* Destroy lock and cond */
-    vlc_mutex_destroy( &(p_vpar->vbuffer.lock) );
-    vlc_cond_destroy( &(p_vpar->vfifo.wait) );
-    vlc_mutex_destroy( &(p_vpar->vfifo.lock) );
-#endif
-    
-    vlc_mutex_destroy( &(p_vpar->synchro.fifo_lock) );
-    
     module_Unneed( p_vpar->p_idct_module );
     module_Unneed( p_vpar->p_motion_module );
 
index 410d7a019acc071336e3864ea813635c7ea59892..1def8f68dfbf397f30348ebf4edb15979b7b8843 100644 (file)
@@ -2,9 +2,11 @@
  * video_parser.h : video parser thread
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_parser.h,v 1.10 2001/07/17 09:48:08 massiot Exp $
+ * $Id: video_parser.h,v 1.11 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *          Jean-Marc Dressler <polux@via.ecp.fr>
+ *          Stéphane Borel <stef@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
+/*
+ * Block parsing structures
+ */
+
 /*****************************************************************************
- * Requires:
- *  "config.h"
- *  "common.h"
- *  "mtime.h"
- *  "threads.h"
- *  "input.h"
- *  "video.h"
- *  "video_output.h"
- *  "decoder_fifo.h"
- *  "video_fifo.h"
- *  "vpar_headers.h"
+ * macroblock_parsing_t : macroblock context & predictors
  *****************************************************************************/
+typedef struct
+{
+    unsigned char       i_quantizer_scale;        /* scale of the quantization
+                                                   * matrices                */
+    int                 pi_dc_dct_pred[3];          /* ISO/IEC 13818-2 7.2.1 */
+    int                 pppi_pmv[2][2][2];  /* Motion vect predictors, 7.6.3 */
+    int                 i_motion_dir;/* Used for the next skipped macroblock */
+
+    /* Context used to optimize block parsing */
+    int                 i_motion_type, i_mv_count, i_mv_format;
+    boolean_t           b_dmv, b_dct_type;
+
+    /* Coordinates of the upper-left pixel of the macroblock, in lum and
+     * chroma */
+    int                 i_l_x, i_l_y, i_c_x, i_c_y;
+} macroblock_parsing_t;
 
 /*****************************************************************************
- * video_fifo_t
- *****************************************************************************
- * This rotative FIFO contains undecoded macroblocks that are to be decoded
+ * lookup_t : entry type for lookup tables                                   *
  *****************************************************************************/
-struct vpar_thread_s;
+typedef struct lookup_s
+{
+    int    i_value;
+    int    i_length;
+} lookup_t;
 
-typedef struct video_fifo_s
+/*****************************************************************************
+ * ac_lookup_t : special entry type for lookup tables about ac coefficients
+ *****************************************************************************/
+typedef struct dct_lookup_s
 {
-#ifdef VDEC_SMP
-    vlc_mutex_t         lock;                              /* fifo data lock */
-    vlc_cond_t          wait;              /* fifo data conditional variable */
-
-    /* buffer is an array of undec_picture_t pointers */
-    macroblock_t *      buffer[VFIFO_SIZE + 1];
-    int                 i_start;
-    int                 i_end;
-#else
-    macroblock_t        buffer;
+    char   i_run;
+    char   i_level;
+    char   i_length;
+} dct_lookup_t;
+
+/*****************************************************************************
+ * Standard codes
+ *****************************************************************************/
+
+/* Macroblock Address Increment types */
+#define MB_ADDRINC_ESCAPE               8
+#define MB_ADDRINC_STUFFING             15
+
+/* Error constant for lookup tables */
+#define MB_ERROR                        (-1)
+
+/* Scan */
+#define SCAN_ZIGZAG                     0
+#define SCAN_ALT                        1
+
+/* Constant for block decoding */
+#define DCT_EOB                         64
+#define DCT_ESCAPE                      65
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+extern u8       pi_default_intra_quant[64];
+extern u8       pi_default_nonintra_quant[64];
+extern u8       pi_scan[2][64];
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vpar_InitCrop( struct vpar_thread_s* p_vpar );
+void vpar_InitMbAddrInc( struct vpar_thread_s * p_vpar );
+void vpar_InitPMBType( struct vpar_thread_s * p_vpar );
+void vpar_InitBMBType( struct vpar_thread_s * p_vpar );
+void vpar_InitCodedPattern( struct vpar_thread_s * p_vpar );
+void vpar_InitDCTTables( struct vpar_thread_s * p_vpar );
+void vpar_InitScanTable( struct vpar_thread_s * p_vpar );
+
+typedef void (*f_picture_data_t)( struct vpar_thread_s * p_vpar,
+                                  int i_mb_base );
+#define PROTO_PICD( FUNCNAME )                                              \
+void FUNCNAME( struct vpar_thread_s * p_vpar, int i_mb_base );
+
+PROTO_PICD( vpar_PictureDataGENERIC )
+#if (VPAR_OPTIM_LEVEL > 0)
+PROTO_PICD( vpar_PictureData1I )
+PROTO_PICD( vpar_PictureData1P )
+PROTO_PICD( vpar_PictureData1B )
+PROTO_PICD( vpar_PictureData1D )
+PROTO_PICD( vpar_PictureData2IF )
+PROTO_PICD( vpar_PictureData2PF )
+PROTO_PICD( vpar_PictureData2BF )
 #endif
+#if (VPAR_OPTIM_LEVEL > 1)
+PROTO_PICD( vpar_PictureData2IT )
+PROTO_PICD( vpar_PictureData2PT )
+PROTO_PICD( vpar_PictureData2BT )
+PROTO_PICD( vpar_PictureData2IB )
+PROTO_PICD( vpar_PictureData2PB )
+PROTO_PICD( vpar_PictureData2BB )
+#endif
+
 
-    struct vpar_thread_s *      p_vpar;
-} video_fifo_t;
+/*
+ * Headers parsing structures
+ */
+
+/*****************************************************************************
+ * quant_matrix_t : Quantization Matrix
+ *****************************************************************************/
+typedef struct quant_matrix_s
+{
+    u8 *        pi_matrix;
+    boolean_t   b_allocated;
+                          /* Has the matrix been allocated by vpar_headers ? */
+} quant_matrix_t;
 
 /*****************************************************************************
- * video_buffer_t
+ * sequence_t : sequence descriptor
  *****************************************************************************
- * This structure enables the parser to maintain a list of free
- * macroblock_t structures
+ * This structure should only be changed when reading the sequence header,
+ * or exceptionnally some extension structures (like quant_matrix).
  *****************************************************************************/
-#ifdef VDEC_SMP
-typedef struct video_buffer_s
+typedef struct sequence_s
 {
-    vlc_mutex_t         lock;                            /* buffer data lock */
+    u32                 i_height, i_width;      /* height and width of the lum
+                                                 * comp of the picture       */
+    u32                 i_size;       /* total number of pel of the lum comp */
+    u32                 i_mb_height, i_mb_width, i_mb_size;
+                                            /* the same, in macroblock units */
+    unsigned int        i_aspect_ratio;        /* height/width display ratio */
+    unsigned int        i_matrix_coefficients;/* coeffs of the YUV transform */
+    int                 i_frame_rate;  /* theoritical frame rate in fps*1001 */
+    boolean_t           b_mpeg2;                                    /* guess */
+    boolean_t           b_progressive;              /* progressive (ie.
+                                                     * non-interlaced) frame */
+    unsigned int        i_scalable_mode; /* scalability ; unsupported, but
+                                          * modifies the syntax of the binary
+                                          * stream.                          */
+    quant_matrix_t      intra_quant, nonintra_quant;
+    quant_matrix_t      chroma_intra_quant, chroma_nonintra_quant;
+                                            /* current quantization matrices */
+
+    /* Chromatic information */
+    unsigned int        i_chroma_format;               /* see CHROMA_* below */
+    int                 i_chroma_nb_blocks;       /* number of chroma blocks */
+    u32                 i_chroma_width;/* width of a line of the chroma comp */
+    u32                 i_chroma_mb_width, i_chroma_mb_height;
+                                 /* size of a macroblock in the chroma buffer
+                                  * (eg. 8x8 or 8x16 or 16x16)               */
+
+    /* Parser context */
+    picture_t *         p_forward;        /* current forward reference frame */
+    picture_t *         p_backward;      /* current backward reference frame */
+    mtime_t             next_pts, next_dts;
+    int                 i_current_rate;
+    boolean_t           b_expect_discontinuity; /* reset the frame predictors
+                                                 * after the current frame   */
+
+    /* Copyright extension */
+    boolean_t           b_copyright_flag;     /* Whether the following
+                                                 information is significant
+                                                 or not. */
+    u8                  i_copyright_id;
+    boolean_t           b_original;
+    u64                 i_copyright_nb;
+} sequence_t;
 
-    macroblock_t        p_macroblocks[VFIFO_SIZE + 1];
-    macroblock_t *      pp_mb_free[VFIFO_SIZE+1];          /* this is a LIFO */
-    int                 i_index;
-} video_buffer_t;
+/*****************************************************************************
+ * picture_parsing_t : parser context descriptor
+ *****************************************************************************
+ * This structure should only be changed when reading the picture header.
+ *****************************************************************************/
+typedef struct picture_parsing_s
+{
+    /* ISO/CEI 11172-2 backward compatibility */
+    boolean_t           pb_full_pel_vector[2];
+    int                 i_forward_f_code, i_backward_f_code;
+
+    /* Values from the picture_coding_extension. Please refer to ISO/IEC
+     * 13818-2. */
+    int                 ppi_f_code[2][2];
+    int                 i_intra_dc_precision;
+    boolean_t           b_frame_pred_frame_dct, b_q_scale_type;
+    boolean_t           b_intra_vlc_format;
+    boolean_t           b_alternate_scan, b_progressive;
+    boolean_t           b_top_field_first, b_concealment_mv;
+    boolean_t           b_repeat_first_field;
+    /* Relative to the current field */
+    int                 i_coding_type, i_structure;
+    boolean_t           b_frame_structure; /* i_structure == FRAME_STRUCTURE */
+
+    picture_t *         p_picture;               /* picture buffer from vout */
+    int                 i_current_structure;   /* current parsed structure of
+                                                * p_picture (second field ?) */
+    boolean_t           b_error;            /* parsing error, try to recover */
+
+    int                 i_l_stride, i_c_stride;
+                                    /* number of coeffs to jump when changing
+                                     * lines (different with field pictures) */
+} picture_parsing_t;
+
+/*****************************************************************************
+ * Standard codes
+ *****************************************************************************/
+#define PICTURE_START_CODE      0x100L
+#define SLICE_START_CODE_MIN    0x101L
+#define SLICE_START_CODE_MAX    0x1AFL
+#define USER_DATA_START_CODE    0x1B2L
+#define SEQUENCE_HEADER_CODE    0x1B3L
+#define SEQUENCE_ERROR_CODE     0x1B4L
+#define EXTENSION_START_CODE    0x1B5L
+#define SEQUENCE_END_CODE       0x1B7L
+#define GROUP_START_CODE        0x1B8L
+
+/* extension start code IDs */
+#define SEQUENCE_EXTENSION_ID                    1
+#define SEQUENCE_DISPLAY_EXTENSION_ID            2
+#define QUANT_MATRIX_EXTENSION_ID                3
+#define COPYRIGHT_EXTENSION_ID                   4
+#define SEQUENCE_SCALABLE_EXTENSION_ID           5
+#define PICTURE_DISPLAY_EXTENSION_ID             7
+#define PICTURE_CODING_EXTENSION_ID              8
+#define PICTURE_SPATIAL_SCALABLE_EXTENSION_ID    9
+#define PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID  10
+
+/* scalable modes */
+#define SC_NONE     0
+#define SC_DP       1
+#define SC_SPAT     2
+#define SC_SNR      3
+#define SC_TEMP     4
+
+/* Chroma types */
+#define CHROMA_420 1
+#define CHROMA_422 2
+#define CHROMA_444 3
+
+/* Pictures types */
+#define I_CODING_TYPE           1
+#define P_CODING_TYPE           2
+#define B_CODING_TYPE           3
+#define D_CODING_TYPE           4 /* MPEG-1 ONLY */
+/* other values are reserved */
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+int vpar_NextSequenceHeader( struct vpar_thread_s * p_vpar );
+int vpar_ParseHeader( struct vpar_thread_s * p_vpar );
+
+
+/*
+ * Synchronization management
+ */
+
+/*****************************************************************************
+ * video_synchro_t : timers for the video synchro
+ *****************************************************************************/
+#define MAX_PIC_AVERAGE         8
+
+/* Read the discussion on top of vpar_synchro.c for more information. */
+typedef struct video_synchro_s
+{
+    /* synchro algorithm */
+    int             i_type;
+
+    /* date of the beginning of the decoding of the current picture */
+    mtime_t         decoding_start;
+
+    /* stream properties */
+    unsigned int    i_n_p, i_n_b;
+
+    /* decoding values */
+    mtime_t         p_tau[4];                  /* average decoding durations */
+    unsigned int    pi_meaningful[4];            /* number of durations read */
+    /* and p_vout->render_time (read with p_vout->change_lock) */
+
+    /* stream context */
+    unsigned int    i_eta_p, i_eta_b;
+    boolean_t       b_dropped_last;            /* for special synchros below */
+    mtime_t         backward_pts, current_pts;
+    int             i_current_period;   /* period to add to the next picture */
+    int             i_backward_period;  /* period to add after the next
+                                         * reference picture
+                                         * (backward_period * period / 2) */
+
+#ifdef STATS
+    unsigned int    i_trashed_pic, i_not_chosen_pic, i_pic;
 #endif
+} video_synchro_t;
+
+/* Synchro algorithms */
+#define VPAR_SYNCHRO_DEFAULT    0
+#define VPAR_SYNCHRO_I          1
+#define VPAR_SYNCHRO_Iplus      2
+#define VPAR_SYNCHRO_IP         3
+#define VPAR_SYNCHRO_IPplus     4
+#define VPAR_SYNCHRO_IPB        5
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vpar_SynchroInit           ( struct vpar_thread_s * p_vpar );
+boolean_t vpar_SynchroChoose    ( struct vpar_thread_s * p_vpar,
+                                  int i_coding_type, int i_structure );
+void vpar_SynchroTrash          ( struct vpar_thread_s * p_vpar,
+                                  int i_coding_type, int i_structure );
+void vpar_SynchroDecode         ( struct vpar_thread_s * p_vpar,
+                                  int i_coding_type, int i_structure );
+void vpar_SynchroEnd            ( struct vpar_thread_s * p_vpar,
+                                  int i_coding_type, int i_structure,
+                                  int i_garbage );
+mtime_t vpar_SynchroDate        ( struct vpar_thread_s * p_vpar );
+void vpar_SynchroNewPicture( struct vpar_thread_s * p_vpar, int i_coding_type,
+                             int i_repeat_field );
+
+
+/*
+ * Video parser structures
+ */
 
 /*****************************************************************************
  * vpar_thread_t: video parser thread descriptor
- *****************************************************************************
- * XXX??
  *****************************************************************************/
 typedef struct vpar_thread_s
 {
-    bit_stream_t        bit_stream;
+    bit_stream_t            bit_stream;
 
     /* Thread properties and locks */
-    vlc_thread_t        thread_id;                /* id for thread functions */
+    vlc_thread_t            thread_id;            /* id for thread functions */
 
     /* Input properties */
-    decoder_fifo_t *    p_fifo;                            /* PES input fifo */
-    vdec_config_t *     p_config;
+    decoder_fifo_t *        p_fifo;                        /* PES input fifo */
+    vdec_config_t *         p_config;
 
     /* Output properties */
-    vout_thread_t *     p_vout;                       /* video output thread */
+    vout_thread_t *         p_vout;                   /* video output thread */
 
     /* Decoder properties */
-    struct vdec_thread_s *      pp_vdec[NB_VDEC];
-    video_fifo_t                vfifo;
-#ifdef VDEC_SMP
-    video_buffer_t              vbuffer;
-#endif
+    vdec_pool_t             pool;
 
     /* Parser properties */
     sequence_t              sequence;
@@ -108,9 +373,11 @@ typedef struct vpar_thread_s
     macroblock_parsing_t    mb;
     video_synchro_t         synchro;
 
-    /* Lookup tables */
-    lookup_t                pl_mb_addr_inc[2048];    /* for macroblock
-                                                        address increment */
+    /*
+     * Lookup tables
+     */
+    /* table for macroblock address increment */
+    lookup_t                pl_mb_addr_inc[2048];
     /* tables for macroblock types 0=P 1=B */
     lookup_t                ppl_mb_type[2][64];
     /* table for coded_block_pattern */
@@ -125,18 +392,16 @@ typedef struct vpar_thread_s
     u8                      pi_default_intra_quant[64];
     u8                      pi_default_nonintra_quant[64];
 
-    /* Motion compensation plugin used and shortcuts */
+    /* Motion compensation plug-in used and shortcuts */
     struct module_s *       p_motion_module;
     void ( * pppf_motion[4][2][4] )     ( struct macroblock_s * );
     void ( * ppf_motion_skipped[4][4] ) ( struct macroblock_s * );
 
-    /* IDCT plugin used and shortcuts to access its capabilities */
+    /* IDCT plugin used and shortcuts */
     struct module_s *           p_idct_module;
-    void ( * pf_idct_init )   ( struct vdec_thread_s * );
     void ( * pf_sparse_idct ) ( void *, dctelem_t*, int );
     void ( * pf_idct )        ( void *, dctelem_t*, int );
     void ( * pf_norm_scan )   ( u8 ppi_scan[2][64] );
-    void ( * pf_decode_init ) ( struct vdec_thread_s * );
     void ( * pf_decode_mb_c ) ( struct vdec_thread_s *, struct macroblock_s * );
     void ( * pf_decode_mb_bw )( struct vdec_thread_s *, struct macroblock_s * );
 
@@ -156,7 +421,7 @@ typedef struct vpar_thread_s
  * Prototypes
  *****************************************************************************/
 
-/* Thread management functions */
+/* Thread management functions - temporary ! */
 vlc_thread_t vpar_CreateThread       ( vdec_config_t * );
 
 /*****************************************************************************
index c143d606ad08b873057e96c4276536089d683251..6af8a573f9c0527a75cb79ea226d5b56627cf067 100644 (file)
@@ -2,7 +2,7 @@
  * vpar_blocks.c : blocks parsing
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_blocks.c,v 1.2 2001/07/17 09:48:08 massiot Exp $
+ * $Id: vpar_blocks.c,v 1.3 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Jean-Marc Dressler <polux@via.ecp.fr>
 #include "video_output.h"
 
 #include "vdec_ext-plugins.h"
-#include "video_decoder.h"
-
-#include "vpar_blocks.h"
-#include "vpar_headers.h"
-#include "vpar_synchro.h"
+#include "vpar_pool.h"
 #include "video_parser.h"
-#include "video_fifo.h"
 
 /*
  * Welcome to vpar_blocks.c ! Here's where the heavy processor-critical parsing
@@ -1644,14 +1639,7 @@ static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb,
         return;
     }
 
-    if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
-    {
-        /* b_die == 1 */
-        return;
-    }
-#ifdef VDEC_SMP
-    p_vpar->picture.pp_mb[i_mb_base + i_mb] = p_mb;
-#endif
+    p_mb = p_vpar->pool.pf_new_mb( &p_vpar->pool );
 
     InitMacroblock( p_vpar, p_mb, i_coding_type, i_structure );
 
@@ -1679,10 +1667,8 @@ static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb,
 
     UpdateContext( p_vpar, i_structure );
 
-#ifndef VDEC_SMP
     /* Decode the macroblock NOW ! */
-    vpar_DecodeMacroblock ( &p_vpar->vfifo, p_mb );
-#endif
+    p_vpar->pool.pf_decode_mb( &p_vpar->pool, p_mb );
 }
 
 /*****************************************************************************
@@ -1776,7 +1762,7 @@ static __inline__ void MacroblockModes( vpar_thread_t * p_vpar,
 if( p_vpar->picture.b_error )                                           \
 {                                                                       \
     /* Go to the next slice. */                                         \
-    vpar_FreeMacroblock( &p_vpar->vfifo, p_mb );                        \
+    p_vpar->pool.pf_free_mb( &p_vpar->pool, p_mb );                     \
     return;                                                             \
 }
 
@@ -1830,14 +1816,7 @@ static __inline__ void ParseMacroblock(
     }
 
     /* Get a macroblock structure. */
-    if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
-    {
-        /* b_die == 1 */
-        return;
-    }
-#ifdef VDEC_SMP
-    p_vpar->picture.pp_mb[i_mb_base + *pi_mb_address] = p_mb;
-#endif
+    p_mb = p_vpar->pool.pf_new_mb( &p_vpar->pool );
 
     InitMacroblock( p_vpar, p_mb, i_coding_type, i_structure );
 
@@ -1960,24 +1939,27 @@ static __inline__ void ParseMacroblock(
          * Effectively decode blocks.
          */
         if( b_mpeg2 )
+        {
             DecodeMPEG2IntraMB( p_vpar, p_mb );
+        }
         else
+        {
             DecodeMPEG1IntraMB( p_vpar, p_mb );
+        }
         PARSEERROR
     }
 
     if( !p_vpar->picture.b_error )
     {
         UpdateContext( p_vpar, i_structure );
-#ifndef VDEC_SMP
+
         /* Decode the macroblock NOW ! */
-        vpar_DecodeMacroblock ( &p_vpar->vfifo, p_mb );
-#endif
+        p_vpar->pool.pf_decode_mb( &p_vpar->pool, p_mb );
     }
     else
     {
         /* Go to the next slice. */
-        vpar_FreeMacroblock( &p_vpar->vfifo, p_mb );
+        p_vpar->pool.pf_free_mb( &p_vpar->pool, p_mb );
     }
 }
 
@@ -2090,7 +2072,7 @@ static __inline__ void vpar_PictureData( vpar_thread_t * p_vpar,
     }
 
 #if 0
-    /* Buggy */
+    /* BUGGY */
     /* Try to recover from error. If we missed less than half the
      * number of macroblocks of the picture, mark the missed ones
      * as skipped. */
diff --git a/src/video_decoder/vpar_blocks.h b/src/video_decoder/vpar_blocks.h
deleted file mode 100644 (file)
index abb1d51..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*****************************************************************************
- * vpar_blocks.h : video parser blocks management
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_blocks.h,v 1.4 2001/07/17 09:48:08 massiot Exp $
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *          Jean-Marc Dressler <polux@via.ecp.fr>
- *          Stéphane Borel <stef@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Requires:
- *  "config.h"
- *  "common.h"
- *  "mtime.h"
- *  "threads.h"
- *  "input.h"
- *  "video.h"
- *  "video_output.h"
- *  "decoder_fifo.h"
- *  "video_fifo.h"
- *****************************************************************************/
-
-/*****************************************************************************
- * macroblock_parsing_t : macroblock context & predictors
- *****************************************************************************/
-typedef struct
-{
-    unsigned char       i_quantizer_scale;        /* scale of the quantization
-                                                   * matrices                */
-    int                 pi_dc_dct_pred[3];          /* ISO/IEC 13818-2 7.2.1 */
-    int                 pppi_pmv[2][2][2];  /* Motion vect predictors, 7.6.3 */
-    int                 i_motion_dir;/* Used for the next skipped macroblock */
-
-    /* Context used to optimize block parsing */
-    int                 i_motion_type, i_mv_count, i_mv_format;
-    boolean_t           b_dmv, b_dct_type;
-
-    /* Coordinates of the upper-left pixel of the macroblock, in lum and
-     * chroma */
-    int                 i_l_x, i_l_y, i_c_x, i_c_y;
-} macroblock_parsing_t;
-
-/*****************************************************************************
- * lookup_t : entry type for lookup tables                                   *
- *****************************************************************************/
-typedef struct lookup_s
-{
-    int    i_value;
-    int    i_length;
-} lookup_t;
-
-/*****************************************************************************
- * ac_lookup_t : special entry type for lookup tables about ac coefficients
- *****************************************************************************/
-typedef struct dct_lookup_s
-{
-    char   i_run;
-    char   i_level;
-    char   i_length;
-} dct_lookup_t;
-
-/*****************************************************************************
- * Standard codes
- *****************************************************************************/
-
-/* Macroblock Address Increment types */
-#define MB_ADDRINC_ESCAPE               8
-#define MB_ADDRINC_STUFFING             15
-
-/* Error constant for lookup tables */
-#define MB_ERROR                        (-1)
-
-/* Scan */
-#define SCAN_ZIGZAG                     0
-#define SCAN_ALT                        1
-
-/* Constant for block decoding */
-#define DCT_EOB                         64
-#define DCT_ESCAPE                      65
-
-/*****************************************************************************
- * Constants
- *****************************************************************************/
-extern u8       pi_default_intra_quant[64];
-extern u8       pi_default_nonintra_quant[64];
-extern u8       pi_scan[2][64];
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-void vpar_InitCrop( struct vpar_thread_s* p_vpar );
-void vpar_InitMbAddrInc( struct vpar_thread_s * p_vpar );
-void vpar_InitPMBType( struct vpar_thread_s * p_vpar );
-void vpar_InitBMBType( struct vpar_thread_s * p_vpar );
-void vpar_InitCodedPattern( struct vpar_thread_s * p_vpar );
-void vpar_InitDCTTables( struct vpar_thread_s * p_vpar );
-void vpar_InitScanTable( struct vpar_thread_s * p_vpar );
-
-typedef void (*f_picture_data_t)( struct vpar_thread_s * p_vpar,
-                                  int i_mb_base );
-#define PROTO_PICD( FUNCNAME )                                              \
-void FUNCNAME( struct vpar_thread_s * p_vpar, int i_mb_base );
-
-PROTO_PICD( vpar_PictureDataGENERIC )
-#if (VPAR_OPTIM_LEVEL > 0)
-PROTO_PICD( vpar_PictureData1I )
-PROTO_PICD( vpar_PictureData1P )
-PROTO_PICD( vpar_PictureData1B )
-PROTO_PICD( vpar_PictureData1D )
-PROTO_PICD( vpar_PictureData2IF )
-PROTO_PICD( vpar_PictureData2PF )
-PROTO_PICD( vpar_PictureData2BF )
-#endif
-#if (VPAR_OPTIM_LEVEL > 1)
-PROTO_PICD( vpar_PictureData2IT )
-PROTO_PICD( vpar_PictureData2PT )
-PROTO_PICD( vpar_PictureData2BT )
-PROTO_PICD( vpar_PictureData2IB )
-PROTO_PICD( vpar_PictureData2PB )
-PROTO_PICD( vpar_PictureData2BB )
-#endif
-
index 0bc6c52a01a2853dbd13bd65d56901600e795612..2430af885f26c0ca64d0eb82ad21a4d2037702d0 100644 (file)
@@ -2,7 +2,7 @@
  * vpar_headers.c : headers parsing
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_headers.c,v 1.2 2001/07/17 09:48:08 massiot Exp $
+ * $Id: vpar_headers.c,v 1.3 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Stéphane Borel <stef@via.ecp.fr>
 #include "video_output.h"
 
 #include "vdec_ext-plugins.h"
-#include "video_decoder.h"
-
-#include "vpar_blocks.h"
-#include "vpar_headers.h"
-#include "vpar_synchro.h"
+#include "vpar_pool.h"
 #include "video_parser.h"
-#include "video_fifo.h"
 
 /*
  * Local prototypes
@@ -450,7 +445,7 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
 
     /* XXX: The vout request and fifo opening will eventually be here */
 
-    /* Spawn an audio output if there is none */
+    /* Spawn a video output if there is none */
     vlc_mutex_lock( &p_vout_bank->lock );
     
     if( p_vout_bank->i_count == 0 )
@@ -510,15 +505,6 @@ static void PictureHeader( vpar_thread_t * p_vpar )
         ReferenceUpdate( p_vpar, I_CODING_TYPE, NULL );
         if( p_vpar->picture.p_picture != NULL )
         {
-#ifdef VDEC_SMP
-            int     i_mb;
-
-            for( i_mb = 0; p_vpar->picture.pp_mb[i_mb] != NULL; i_mb++ )
-            {
-                vpar_DestroyMacroblock( &p_vpar->vfifo,
-                                        p_vpar->picture.pp_mb[i_mb] );
-            }
-#endif
             vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
         }
         p_vpar->sequence.b_expect_discontinuity = 0;
@@ -613,14 +599,6 @@ static void PictureHeader( vpar_thread_t * p_vpar )
             ReferenceReplace( p_vpar,
                       p_vpar->picture.i_coding_type,
                       NULL );
-
-#ifdef VDEC_SMP
-            for( i_mb = 0; p_vpar->picture.pp_mb[i_mb] != NULL; i_mb++ )
-            {
-                vpar_DestroyMacroblock( &p_vpar->vfifo,
-                                        p_vpar->picture.pp_mb[i_mb] );
-            }
-#endif
             vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
         }
 
@@ -747,30 +725,11 @@ static void PictureHeader( vpar_thread_t * p_vpar )
         p_vpar->picture.i_c_stride = ( p_vpar->sequence.i_chroma_width
                     << ( 1 - p_vpar->picture.b_frame_structure ));
 
-        P_picture->i_deccount = p_vpar->sequence.i_mb_size;
-#ifdef VDEC_SMP
-        memset( p_vpar->picture.pp_mb, 0, MAX_MB*sizeof(macroblock_t *) );
-#endif
 /* FIXME ! remove asap ?? */
 //memset( P_picture->p_data, 0, (p_vpar->sequence.i_mb_size*384));
 
         /* Update the reference pointers. */
         ReferenceUpdate( p_vpar, p_vpar->picture.i_coding_type, P_picture );
-
-#ifdef VDEC_SMP
-        /* Link referenced pictures for the decoder
-         * They are unlinked in vpar_ReleaseMacroblock() &
-         * vpar_DestroyMacroblock() */
-        if( p_vpar->picture.i_coding_type == P_CODING_TYPE ||
-            p_vpar->picture.i_coding_type == B_CODING_TYPE )
-        {
-            vout_LinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
-        }
-        if( p_vpar->picture.i_coding_type == B_CODING_TYPE )
-        {
-            vout_LinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
-        }
-#endif
     }
     p_vpar->picture.i_current_structure |= i_structure;
     p_vpar->picture.i_structure = i_structure;
@@ -855,6 +814,12 @@ static void PictureHeader( vpar_thread_t * p_vpar )
 #endif
     }
 
+    /* Wait for all the macroblocks to be decoded. */
+    p_vpar->pool.pf_wait_pool( &p_vpar->pool );
+
+    /* Re-spawn decoder threads if the user changed settings. */
+    vpar_SpawnPool( p_vpar );
+
     if( p_vpar->p_fifo->b_die || p_vpar->p_fifo->b_error )
     {
         return;
@@ -863,22 +828,13 @@ static void PictureHeader( vpar_thread_t * p_vpar )
     if( p_vpar->picture.b_error )
     {
         /* Trash picture. */
-#ifdef VDEC_SMP
-        for( i_mb = 1; p_vpar->picture.pp_mb[i_mb] != NULL; i_mb++ )
-        {
-            vpar_DestroyMacroblock( &p_vpar->vfifo, p_vpar->picture.pp_mb[i_mb] );
-        }
-#endif
-
 #ifdef STATS
         p_vpar->pc_malformed_pictures[p_vpar->picture.i_coding_type]++;
 #endif
 
-        if( P_picture->i_deccount != 1 )
-        {
-            vpar_SynchroEnd( p_vpar, 1 );
-            vout_DestroyPicture( p_vpar->p_vout, P_picture );
-        }
+        vpar_SynchroEnd( p_vpar, p_vpar->picture.i_coding_type,
+                         p_vpar->picture.i_structure, 1 );
+        vout_DestroyPicture( p_vpar->p_vout, P_picture );
 
         ReferenceReplace( p_vpar, p_vpar->picture.i_coding_type, NULL );
 
@@ -890,17 +846,9 @@ static void PictureHeader( vpar_thread_t * p_vpar )
     else if( p_vpar->picture.i_current_structure == FRAME_STRUCTURE )
     {
         /* Frame completely parsed. */
-#ifdef VDEC_SMP
-        for( i_mb = 1; p_vpar->picture.pp_mb[i_mb] != NULL; i_mb++ )
-        {
-            vpar_DecodeMacroblock( &p_vpar->vfifo, p_vpar->picture.pp_mb[i_mb] );
-        }
-
-        /* Send signal to the video_decoder. */
-        vlc_mutex_lock( &p_vpar->vfifo.lock );
-        vlc_cond_signal( &p_vpar->vfifo.wait );
-        vlc_mutex_unlock( &p_vpar->vfifo.lock );
-#endif
+        vpar_SynchroEnd( p_vpar, p_vpar->picture.i_coding_type,
+                         p_vpar->picture.i_structure, 0 );
+        vout_DisplayPicture( p_vpar->p_vout, P_picture );
 
         /* Prepare context for the next picture. */
         P_picture = NULL;
diff --git a/src/video_decoder/vpar_headers.h b/src/video_decoder/vpar_headers.h
deleted file mode 100644 (file)
index 8dcaffd..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*****************************************************************************
- * vpar_headers.h : video parser : headers parsing
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_headers.h,v 1.8 2001/07/17 09:48:08 massiot Exp $
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *          Stéphane Borel <stef@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Requires:
- *  "config.h"
- *  "common.h"
- *  "mtime.h"
- *  "threads.h"
- *  "input.h"
- *  "video.h"
- *  "video_output.h"
- *  "decoder_fifo.h"
- *  "video_fifo.h"
- *****************************************************************************/
-
-/*****************************************************************************
- * quant_matrix_t : Quantization Matrix
- *****************************************************************************/
-typedef struct quant_matrix_s
-{
-    u8 *        pi_matrix;
-    boolean_t   b_allocated;
-                          /* Has the matrix been allocated by vpar_headers ? */
-} quant_matrix_t;
-
-/*****************************************************************************
- * sequence_t : sequence descriptor
- *****************************************************************************
- * This structure should only be changed when reading the sequence header,
- * or exceptionnally some extension structures (like quant_matrix).
- *****************************************************************************/
-typedef struct sequence_s
-{
-    u32                 i_height, i_width;      /* height and width of the lum
-                                                 * comp of the picture       */
-    u32                 i_size;       /* total number of pel of the lum comp */
-    u32                 i_mb_height, i_mb_width, i_mb_size;
-                                            /* the same, in macroblock units */
-    unsigned int        i_aspect_ratio;        /* height/width display ratio */
-    unsigned int        i_matrix_coefficients;/* coeffs of the YUV transform */
-    int                 i_frame_rate;  /* theoritical frame rate in fps*1001 */
-    boolean_t           b_mpeg2;                                    /* guess */
-    boolean_t           b_progressive;              /* progressive (ie.
-                                                     * non-interlaced) frame */
-    unsigned int        i_scalable_mode; /* scalability ; unsupported, but
-                                          * modifies the syntax of the binary
-                                          * stream.                          */
-    quant_matrix_t      intra_quant, nonintra_quant;
-    quant_matrix_t      chroma_intra_quant, chroma_nonintra_quant;
-                                            /* current quantization matrices */
-
-    /* Chromatic information */
-    unsigned int        i_chroma_format;               /* see CHROMA_* below */
-    int                 i_chroma_nb_blocks;       /* number of chroma blocks */
-    u32                 i_chroma_width;/* width of a line of the chroma comp */
-    u32                 i_chroma_mb_width, i_chroma_mb_height;
-                                 /* size of a macroblock in the chroma buffer
-                                  * (eg. 8x8 or 8x16 or 16x16)               */
-
-    /* Parser context */
-    picture_t *         p_forward;        /* current forward reference frame */
-    picture_t *         p_backward;      /* current backward reference frame */
-    mtime_t             next_pts, next_dts;
-    int                 i_current_rate;
-    boolean_t           b_expect_discontinuity; /* reset the frame predictors
-                                                 * after the current frame   */
-
-    /* Copyright extension */
-    boolean_t           b_copyright_flag;     /* Whether the following
-                                                 information is significant
-                                                 or not. */
-    u8                  i_copyright_id;
-    boolean_t           b_original;
-    u64                 i_copyright_nb;
-} sequence_t;
-
-/*****************************************************************************
- * picture_parsing_t : parser context descriptor
- *****************************************************************************
- * This structure should only be changed when reading the picture header.
- *****************************************************************************/
-typedef struct picture_parsing_s
-{
-    /* ISO/CEI 11172-2 backward compatibility */
-    boolean_t           pb_full_pel_vector[2];
-    int                 i_forward_f_code, i_backward_f_code;
-
-    /* Values from the picture_coding_extension. Please refer to ISO/IEC
-     * 13818-2. */
-    int                 ppi_f_code[2][2];
-    int                 i_intra_dc_precision;
-    boolean_t           b_frame_pred_frame_dct, b_q_scale_type;
-    boolean_t           b_intra_vlc_format;
-    boolean_t           b_alternate_scan, b_progressive;
-    boolean_t           b_top_field_first, b_concealment_mv;
-    boolean_t           b_repeat_first_field;
-    /* Relative to the current field */
-    int                 i_coding_type, i_structure;
-    boolean_t           b_frame_structure; /* i_structure == FRAME_STRUCTURE */
-
-    picture_t *         p_picture;               /* picture buffer from vout */
-    int                 i_current_structure;   /* current parsed structure of
-                                                * p_picture (second field ?) */
-#ifdef VDEC_SMP
-    macroblock_t *      pp_mb[MAX_MB];         /* macroblock buffer to
-                                                * send to the vdec thread(s) */
-#endif
-    boolean_t           b_error;            /* parsing error, try to recover */
-
-    int                 i_l_stride, i_c_stride;
-                                    /* number of coeffs to jump when changing
-                                     * lines (different with field pictures) */
-} picture_parsing_t;
-
-/*****************************************************************************
- * Standard codes
- *****************************************************************************/
-#define PICTURE_START_CODE      0x100L
-#define SLICE_START_CODE_MIN    0x101L
-#define SLICE_START_CODE_MAX    0x1AFL
-#define USER_DATA_START_CODE    0x1B2L
-#define SEQUENCE_HEADER_CODE    0x1B3L
-#define SEQUENCE_ERROR_CODE     0x1B4L
-#define EXTENSION_START_CODE    0x1B5L
-#define SEQUENCE_END_CODE       0x1B7L
-#define GROUP_START_CODE        0x1B8L
-
-/* extension start code IDs */
-#define SEQUENCE_EXTENSION_ID                    1
-#define SEQUENCE_DISPLAY_EXTENSION_ID            2
-#define QUANT_MATRIX_EXTENSION_ID                3
-#define COPYRIGHT_EXTENSION_ID                   4
-#define SEQUENCE_SCALABLE_EXTENSION_ID           5
-#define PICTURE_DISPLAY_EXTENSION_ID             7
-#define PICTURE_CODING_EXTENSION_ID              8
-#define PICTURE_SPATIAL_SCALABLE_EXTENSION_ID    9
-#define PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID  10
-
-/* scalable modes */
-#define SC_NONE     0
-#define SC_DP       1
-#define SC_SPAT     2
-#define SC_SNR      3
-#define SC_TEMP     4
-
-/* Chroma types */
-#define CHROMA_420 1
-#define CHROMA_422 2
-#define CHROMA_444 3
-
-/* Pictures types */
-#define I_CODING_TYPE           1
-#define P_CODING_TYPE           2
-#define B_CODING_TYPE           3
-#define D_CODING_TYPE           4 /* MPEG-1 ONLY */
-/* other values are reserved */
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-int vpar_NextSequenceHeader( struct vpar_thread_s * p_vpar );
-int vpar_ParseHeader( struct vpar_thread_s * p_vpar );
diff --git a/src/video_decoder/vpar_pool.c b/src/video_decoder/vpar_pool.c
new file mode 100644 (file)
index 0000000..d1ecf65
--- /dev/null
@@ -0,0 +1,308 @@
+/*****************************************************************************
+ * vpar_pool.c : management of the pool of decoder threads
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: vpar_pool.c,v 1.1 2001/07/18 14:21:00 massiot Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "defs.h"
+
+#include <string.h>                                    /* memcpy(), memset() */
+#include <stdlib.h>                                             /* realloc() */
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h"
+
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
+#include "video.h"
+#include "video_output.h"
+
+#include "vdec_ext-plugins.h"
+#include "vpar_pool.h"
+#include "video_parser.h"
+#include "video_decoder.h"
+
+/*
+ * Local prototypes
+ */
+static void WaitDummy( vdec_pool_t * p_pool );
+static void WaitPool( vdec_pool_t * p_pool );
+static void FreeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb );
+static void FreeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb );
+static macroblock_t * NewMacroblockDummy( vdec_pool_t * p_pool );
+static macroblock_t * NewMacroblockPool( vdec_pool_t * p_pool );
+static void DecodeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb );
+static void DecodeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb );
+
+/*****************************************************************************
+ * vpar_InitPool: Initializes the pool structure
+ *****************************************************************************/
+void vpar_InitPool( vpar_thread_t * p_vpar )
+{
+    /* Initialize mutex and cond. */
+    vlc_mutex_init( &p_vpar->pool.lock );
+    vlc_cond_init( &p_vpar->pool.wait_empty );
+    vlc_cond_init( &p_vpar->pool.wait_undecoded );
+
+    /* Spawn optional video decoder threads. */
+    p_vpar->pool.i_smp = 0;
+    p_vpar->pool.pp_vdec = NULL;
+    p_vpar->pool.p_macroblocks = NULL;
+    p_vpar->pool.pp_empty_macroblocks = NULL;
+    p_vpar->pool.pp_new_macroblocks = NULL;
+    vpar_SpawnPool( p_vpar );
+
+    /* Initialize fake video decoder structure (used when
+     * decoder == parser). */
+    if ( (p_vpar->pool.p_vdec =
+                (vdec_thread_t *)malloc( sizeof(vdec_thread_t) )) == NULL )
+    {
+        intf_ErrMsg("vdec error: not enough memory for vdec_CreateThread() to create the new thread");
+        p_vpar->p_fifo->b_error = 1;
+        return;
+    }
+    p_vpar->pool.p_vdec->b_die = 0;
+    p_vpar->pool.p_vdec->p_pool = &p_vpar->pool;
+    vdec_InitThread( p_vpar->pool.p_vdec );
+}
+
+/*****************************************************************************
+ * vpar_SpawnPool: Create and cancel video decoder threads at any time
+ *****************************************************************************
+ * This function is called on startup, and everytime the user changes the
+ * number of threads to launch. Please note that *all* decoder threads must
+ * be idle during this operation, which only happens at the end of
+ * PictureHeader().
+ *****************************************************************************/
+void vpar_SpawnPool( vpar_thread_t * p_vpar )
+{
+    int                 i_new_smp;
+    boolean_t           b_grayscale;
+    stream_ctrl_t *     p_control;
+
+    p_control = p_vpar->p_config->decoder_config.p_stream_ctrl;
+    vlc_mutex_lock( &p_control->control_lock );
+    i_new_smp = p_control->i_smp;
+    b_grayscale = p_control->b_grayscale;
+    vlc_mutex_unlock( &p_control->control_lock );
+
+    /* FIXME: No error check because I'm tired. Come back later... */
+
+    /* No need to lock p_vpar->pool, since decoders MUST be idle here. */
+    if( p_vpar->pool.i_smp != i_new_smp )
+    {
+        int i;
+
+        if( p_vpar->pool.i_smp > i_new_smp )
+        {
+            /* The user reduces the number of threads. */
+
+            for( i = p_vpar->pool.i_smp - 1; i >= i_new_smp; i-- )
+            {
+                vdec_DestroyThread( p_vpar->pool.pp_vdec[i] );
+            }
+
+            p_vpar->pool.pp_vdec = realloc( p_vpar->pool.pp_vdec,
+                                            i_new_smp * sizeof(vdec_thread_t *) );
+            p_vpar->pool.p_macroblocks = realloc( p_vpar->pool.p_macroblocks,
+                                            i_new_smp * sizeof(macroblock_t) );
+            p_vpar->pool.pp_empty_macroblocks = realloc( p_vpar->pool.pp_empty_macroblocks,
+                                            i_new_smp * sizeof(macroblock_t *) );
+            p_vpar->pool.i_index_empty = i_new_smp;
+            p_vpar->pool.pp_new_macroblocks = realloc( p_vpar->pool.pp_new_macroblocks,
+                                            i_new_smp * sizeof(macroblock_t *) );
+            p_vpar->pool.i_index_new = 0;
+        }
+        else
+        {
+            /* The user raises the number of threads. */
+
+            p_vpar->pool.pp_vdec = realloc( p_vpar->pool.pp_vdec,
+                                            i_new_smp * sizeof(vdec_thread_t *) );
+            p_vpar->pool.p_macroblocks = realloc( p_vpar->pool.p_macroblocks,
+                                            i_new_smp * sizeof(macroblock_t) );
+            p_vpar->pool.pp_empty_macroblocks = realloc( p_vpar->pool.pp_empty_macroblocks,
+                                            i_new_smp * sizeof(macroblock_t *) );
+            p_vpar->pool.i_index_empty = i_new_smp;
+            p_vpar->pool.pp_new_macroblocks = realloc( p_vpar->pool.pp_new_macroblocks,
+                                            i_new_smp * sizeof(macroblock_t *) );
+            p_vpar->pool.i_index_new = 0;
+
+            for( i = p_vpar->pool.i_smp; i < i_new_smp ; i++ )
+            {
+                p_vpar->pool.pp_vdec[i] = vdec_CreateThread( &p_vpar->pool );
+            }
+
+        }
+        for( i = 0; i < i_new_smp; i++ )
+        {
+            p_vpar->pool.pp_empty_macroblocks[i] =
+                                    &p_vpar->pool.p_macroblocks[i];
+        }
+        p_vpar->pool.i_smp = i_new_smp;
+    }
+
+    if( i_new_smp )
+    {
+        /* We have at least one decoder thread. */
+        p_vpar->pool.pf_wait_pool = WaitPool;
+        p_vpar->pool.pf_new_mb = NewMacroblockPool;
+        p_vpar->pool.pf_free_mb = FreeMacroblockPool;
+        p_vpar->pool.pf_decode_mb = DecodeMacroblockPool;
+    }
+    else
+    {
+        /* No decoder pool. */
+        p_vpar->pool.pf_wait_pool = WaitDummy;
+        p_vpar->pool.pf_new_mb = NewMacroblockDummy;
+        p_vpar->pool.pf_free_mb = FreeMacroblockDummy;
+        p_vpar->pool.pf_decode_mb = DecodeMacroblockDummy;
+    }
+
+    if( !b_grayscale )
+    {
+        p_vpar->pool.pf_vdec_decode = p_vpar->pf_decode_mb_c;
+    }
+    else
+    {
+        p_vpar->pool.pf_vdec_decode = p_vpar->pf_decode_mb_bw;
+    }
+}
+
+/*****************************************************************************
+ * vpar_EndPool: Releases the pool structure
+ *****************************************************************************/
+void vpar_EndPool( vpar_thread_t * p_vpar )
+{
+    int i;
+
+    for( i = 0; i < p_vpar->pool.i_smp; i++ )
+    {
+        vdec_DestroyThread( p_vpar->pool.pp_vdec[i] );
+    }
+
+    if( p_vpar->pool.i_smp )
+    {
+        free( p_vpar->pool.pp_vdec );
+        free( p_vpar->pool.p_macroblocks );
+        free( p_vpar->pool.pp_new_macroblocks );
+    }
+
+    /* Free fake video decoder (used when parser == decoder). */
+    vdec_EndThread( p_vpar->pool.p_vdec );
+
+    /* Destroy lock and cond. */
+    vlc_mutex_destroy( &p_vpar->pool.lock );
+    vlc_cond_destroy( &p_vpar->pool.wait_empty );
+    vlc_cond_destroy( &p_vpar->pool.wait_undecoded );
+}
+
+/*****************************************************************************
+ * WaitPool: Wait until all decoders are idle
+ *****************************************************************************/
+static void WaitPool( vdec_pool_t * p_pool )
+{
+    vlc_mutex_lock( &p_pool->lock );
+    while( p_pool->i_index_empty != p_pool->i_smp )
+    {
+        vlc_cond_wait( &p_pool->wait_empty, &p_pool->lock );
+    }
+    vlc_mutex_unlock( &p_pool->lock );
+}
+
+/*****************************************************************************
+ * WaitDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static void WaitDummy( vdec_pool_t * p_pool )
+{
+}
+
+/*****************************************************************************
+ * NewMacroblockPool: Get an empty macroblock from the decoder pool
+ *****************************************************************************/
+static macroblock_t * NewMacroblockPool( vdec_pool_t * p_pool )
+{
+    macroblock_t *  p_mb;
+
+    vlc_mutex_lock( &p_pool->lock );
+    while( p_pool->i_index_empty == 0 )
+    {
+        vlc_cond_wait( &p_pool->wait_empty, &p_pool->lock );
+    }
+    p_mb = p_pool->pp_empty_macroblocks[ --p_pool->i_index_empty ];
+    vlc_mutex_unlock( &p_pool->lock );
+    return( p_mb );
+}
+
+/*****************************************************************************
+ * NewMacroblockDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static macroblock_t * NewMacroblockDummy( vdec_pool_t * p_pool )
+{
+    return( &p_pool->mb );
+}
+
+/*****************************************************************************
+ * FreeMacroblockPool: Free a macroblock
+ *****************************************************************************/
+static void FreeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+    vlc_mutex_lock( &p_pool->lock );
+    p_pool->pp_empty_macroblocks[ p_pool->i_index_empty++ ] = p_mb;
+    vlc_cond_signal( &p_pool->wait_empty );
+    vlc_mutex_unlock( &p_pool->lock );
+}
+
+/*****************************************************************************
+ * FreeMacroblockDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static void FreeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+}
+
+/*****************************************************************************
+ * DecodeMacroblockPool: Send a macroblock to a vdec thread
+ *****************************************************************************/
+static void DecodeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+    vlc_mutex_lock( &p_pool->lock );
+    /* The undecoded macroblock LIFO cannot be full, because
+     * #macroblocks == size of the LIFO */
+    p_pool->pp_new_macroblocks[ p_pool->i_index_new++ ] = p_mb;
+    vlc_cond_signal( &p_pool->wait_undecoded );
+    vlc_mutex_unlock( &p_pool->lock );
+}
+
+/*****************************************************************************
+ * DecodeMacroblockDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static void DecodeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+    p_pool->pf_vdec_decode( p_pool->p_vdec, p_mb );
+}
+
diff --git a/src/video_decoder/vpar_pool.h b/src/video_decoder/vpar_pool.h
new file mode 100644 (file)
index 0000000..76cb96b
--- /dev/null
@@ -0,0 +1,111 @@
+/*****************************************************************************
+ * vpar_pool.h : video parser/video decoders communication
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: vpar_pool.h,v 1.1 2001/07/18 14:21:00 massiot Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * vdec_pool_t
+ *****************************************************************************
+ * This structure is used for the communication between the parser and the
+ * decoders.
+ *****************************************************************************/
+typedef struct vdec_pool_s
+{
+    /* Locks */
+    vlc_mutex_t         lock;                         /* Structure data lock */
+    vlc_cond_t          wait_empty;      /* The parser blocks there when all
+                                          * decoder threads are busy         */
+    vlc_cond_t          wait_undecoded; /* The decoders block there when no
+                                         * macroblock has been given by the
+                                         * parser */
+
+    /* Video decoder threads */
+    struct vdec_thread_s ** pp_vdec;       /* Array of video decoder threads */
+    int                 i_smp;     /* Number of symmetrical decoder threads,
+                                    * hence size of the pp_vdec, p_macroblocks
+                                    * and pp_new_macroblocks array */
+
+    /* Macroblocks */
+    macroblock_t *      p_macroblocks;
+
+    /* Empty macroblocks */
+    macroblock_t **     pp_empty_macroblocks;           /* Empty macroblocks */
+    int                 i_index_empty;              /* Last empty macroblock */
+
+    /* Undecoded macroblocks, read by the decoders */
+    macroblock_t **     pp_new_macroblocks;         /* Undecoded macroblocks */
+    int                 i_index_new;            /* Last undecoded macroblock */
+
+    /* Undecoded macroblock, used when the parser and the decoder share the
+     * same thread */
+    macroblock_t        mb;
+    struct vdec_thread_s * p_vdec;                     /* Fake video decoder */
+
+    /* Pointers to usual pool functions */
+    void             (* pf_wait_pool) ( struct vdec_pool_s * );
+    macroblock_t *   (* pf_new_mb) ( struct vdec_pool_s * );
+    void             (* pf_free_mb) ( struct vdec_pool_s *,
+                                      struct macroblock_s * );
+    void             (* pf_decode_mb) ( struct vdec_pool_s *,
+                                        struct macroblock_s * );
+
+    /* Pointer to the decoding function - used for B&W switching */
+    void             (* pf_vdec_decode) ( struct vdec_thread_s *,
+                                          struct macroblock_s * );
+    boolean_t           b_bw;                      /* Current value for B&W */
+
+    /* Access to the plug-ins needed by the video decoder thread */
+    void ( * pf_decode_init ) ( struct vdec_thread_s * );
+    void ( * pf_idct_init )   ( struct vdec_thread_s * );
+} vdec_pool_t;
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vpar_InitPool( struct vpar_thread_s * );
+void vpar_SpawnPool( struct vpar_thread_s * );
+void vpar_EndPool( struct vpar_thread_s * );
+
+/*****************************************************************************
+ * vpar_GetMacroblock: In a vdec thread, get the next available macroblock
+ *****************************************************************************/
+static __inline__ macroblock_t * vpar_GetMacroblock( vdec_pool_t * p_pool,
+                                                     boolean_t * pb_die )
+{
+    macroblock_t *  p_mb;
+
+    vlc_mutex_lock( &p_pool->lock );
+    while( p_pool->i_index_new == 0 && !*pb_die )
+    {
+        vlc_cond_wait( &p_pool->wait_undecoded, &p_pool->lock );
+    }
+
+    if( *pb_die )
+    {
+        vlc_mutex_unlock( &p_pool->lock );
+        return( NULL );
+    }
+
+    p_mb = p_pool->pp_new_macroblocks[ --p_pool->i_index_new ];
+    vlc_mutex_unlock( &p_pool->lock );
+    return( p_mb );
+}
+
index eb6d58ac8bfcc1ea92cf0805fbea2271b143e633..997a88f08949cf69f66589f47005ddf4882de03d 100644 (file)
@@ -2,7 +2,7 @@
  * vpar_synchro.c : frame dropping routines
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_synchro.c,v 1.2 2001/07/17 09:48:08 massiot Exp $
+ * $Id: vpar_synchro.c,v 1.3 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Samuel Hocevar <sam@via.ecp.fr>
 #include "video_output.h"
 
 #include "vdec_ext-plugins.h"
-#include "video_decoder.h"
-
-#include "vpar_blocks.h"
-#include "vpar_headers.h"
-#include "vpar_synchro.h"
+#include "vpar_pool.h"
 #include "video_parser.h"
 
 #include "main.h"
@@ -138,8 +134,6 @@ static int  SynchroType( void );
 void vpar_SynchroInit( vpar_thread_t * p_vpar )
 {
     p_vpar->synchro.i_type = SynchroType();
-    p_vpar->synchro.i_start = p_vpar->synchro.i_end = 0;
-    vlc_mutex_init( &p_vpar->synchro.fifo_lock );
 
     /* We use a fake stream pattern, which is often right. */
     p_vpar->synchro.i_n_p = p_vpar->synchro.i_eta_p = DEFAULT_NB_P;
@@ -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 );
         tau_yuv = p_vpar->p_vout->render_time;
         vlc_mutex_unlock( &p_vpar->p_vout->change_lock );
-#ifdef VDEC_SMP
-        vlc_mutex_lock( &p_vpar->synchro.fifo_lock );
-#endif
 
         switch( i_coding_type )
         {
@@ -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
         intf_DbgMsg("vpar synchro debug: %s picture scheduled for %s, %s (%lld)",
                     i_coding_type == B_CODING_TYPE ? "B" :
@@ -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,
                          int i_structure )
 {
-#ifdef VDEC_SMP
-    vlc_mutex_lock( &p_vpar->synchro.fifo_lock );
-#endif
-
-    if( ((p_vpar->synchro.i_end + 1 - p_vpar->synchro.i_start)
-            % MAX_DECODING_PIC) )
-    {
-        p_vpar->synchro.p_date_fifo[p_vpar->synchro.i_end] = mdate();
-        p_vpar->synchro.pi_coding_types[p_vpar->synchro.i_end] = i_coding_type;
-
-        FIFO_INCREMENT( i_end );
-    }
-    else
-    {
-        /* FIFO full, panic() */
-        intf_ErrMsg("vpar error: synchro fifo full, estimations will be biased (%d:%d)",
-                    p_vpar->synchro.i_start, p_vpar->synchro.i_end);
-    }
-#ifdef VDEC_SMP
-    vlc_mutex_unlock( &p_vpar->synchro.fifo_lock );
-#endif
+    p_vpar->synchro.decoding_start = mdate();
 }
 
 /*****************************************************************************
  * vpar_SynchroEnd : Called when the image is totally decoded
  *****************************************************************************/
-void vpar_SynchroEnd( vpar_thread_t * p_vpar, int i_garbage )
+void vpar_SynchroEnd( vpar_thread_t * p_vpar, int i_coding_type,
+                      int i_structure, int i_garbage )
 {
     mtime_t     tau;
-    int         i_coding_type;
-
-#ifdef VDEC_SMP
-    vlc_mutex_lock( &p_vpar->synchro.fifo_lock );
-#endif
-
-    i_coding_type = p_vpar->synchro.pi_coding_types[p_vpar->synchro.i_start];
 
     if( !i_garbage )
     {
-        tau = mdate() - p_vpar->synchro.p_date_fifo[p_vpar->synchro.i_start];
+        tau = mdate() - p_vpar->synchro.decoding_start;
 
         /* If duration too high, something happened (pause ?), so don't
          * take it into account. */
@@ -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 == P_CODING_TYPE ? "P" : "I"));
     }
-
-    FIFO_INCREMENT( i_start );
-
-#ifdef VDEC_SMP
-    vlc_mutex_unlock( &p_vpar->synchro.fifo_lock );
-#endif
 }
 
 /*****************************************************************************
diff --git a/src/video_decoder/vpar_synchro.h b/src/video_decoder/vpar_synchro.h
deleted file mode 100644 (file)
index b2c7537..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*****************************************************************************
- * 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 );
index f78ae4c0444a9653f16056d0feb78dad52a4c476..a6e84e3b51b538edc66528de0a8f40e510e1fb87 100644 (file)
@@ -5,7 +5,7 @@
  * thread, and destroy a previously oppened video output thread.
  *****************************************************************************
  * Copyright (C) 2000 VideoLAN
- * $Id: video_output.c,v 1.134 2001/07/11 02:01:05 sam Exp $
+ * $Id: video_output.c,v 1.135 2001/07/18 14:21:00 massiot Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *
@@ -685,9 +685,6 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
 #endif
         vlc_mutex_unlock( &p_vout->picture_lock );
 
-        /* Initialize mutex */
-        vlc_mutex_init( &(p_free_picture->lock_deccount) );
-
         return( p_free_picture );
     }
 
@@ -725,9 +722,6 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
     intf_DbgMsg("picture %p", p_pic);
 #endif
 
-    /* destroy the lock that had been initialized in CreatePicture */
-    vlc_mutex_destroy( &(p_pic->lock_deccount) );
-
     vlc_mutex_unlock( &p_vout->picture_lock );
 }