]> git.sesse.net Git - vlc/commitdiff
* Ajout d'un flag VDEC_SMP � commenter si on n'a qu'un seul
authorChristophe Massiot <massiot@videolan.org>
Tue, 25 Jan 2000 01:51:50 +0000 (01:51 +0000)
committerChristophe Massiot <massiot@videolan.org>
Tue, 25 Jan 2000 01:51:50 +0000 (01:51 +0000)
microprocesseur.

include/config.h
include/video_decoder.h
include/video_fifo.h
include/video_parser.h
include/vpar_headers.h
src/video_decoder/video_decoder.c
src/video_parser/video_fifo.c
src/video_parser/video_parser.c
src/video_parser/vpar_blocks.c
src/video_parser/vpar_headers.c

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