]> git.sesse.net Git - vlc/commitdiff
Suite du video_parser et du video_decoder.
authorChristophe Massiot <massiot@videolan.org>
Tue, 28 Dec 1999 23:35:32 +0000 (23:35 +0000)
committerChristophe Massiot <massiot@videolan.org>
Tue, 28 Dec 1999 23:35:32 +0000 (23:35 +0000)
13 files changed:
include/video_decoder.h.new [new file with mode: 0644]
include/video_fifo.h
include/video_parser.h
include/vpar_blocks.h
include/vpar_headers.h [new file with mode: 0644]
src/video_decoder/vdec_idct.c [new file with mode: 0644]
src/video_decoder/vdec_motion.c
src/video_decoder/video_decoder.c
src/video_parser/video_fifo.c
src/video_parser/video_parser.c
src/video_parser/vpar_blocks.c [new file with mode: 0644]
src/video_parser/vpar_headers.c
src/video_parser/vpar_motion.c [new file with mode: 0644]

diff --git a/include/video_decoder.h.new b/include/video_decoder.h.new
new file mode 100644 (file)
index 0000000..5dbf77e
--- /dev/null
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * video_decoder.h : video decoder thread
+ * (c)1999 VideoLAN
+ *****************************************************************************
+ *****************************************************************************
+ * Requires:
+ *  "config.h"
+ *  "common.h"
+ *  "mtime.h"
+ *  "vlc_thread.h"
+ *  "input.h"
+ *  "video.h"
+ *  "video_output.h"
+ *  "decoder_fifo.h"
+ *****************************************************************************/
+
+/*****************************************************************************
+ * vdec_thread_t: video decoder thread descriptor
+ *****************************************************************************
+ * ??
+ *****************************************************************************/
+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 */
+
+    /* Thread configuration */
+    /* ?? */
+ /*??*/
+//    int *pi_status;
+    
+
+    /* Input properties */
+    video_parser_t *   p_vpar;                       /* video_parser thread */
+        
+#ifdef STATS
+    /* Statistics */
+    count_t         c_loops;                              /* number of loops */
+    count_t         c_idle_loops;                    /* number of idle loops */
+    count_t         c_decoded_pictures;        /* number of pictures decoded */
+    count_t         c_decoded_i_pictures;    /* number of I pictures decoded */
+    count_t         c_decoded_p_pictures;    /* number of P pictures decoded */
+    count_t         c_decoded_b_pictures;    /* number of B pictures decoded */
+#endif
+} vdec_thread_t;
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+
+/* Thread management functions */
+vdec_thread_t * vdec_CreateThread       ( vpar_thread_t *p_vpar /*, int *pi_status */ );
+void            vdec_DestroyThread      ( vdec_thread_t *p_vdec /*, int *pi_status */ );
+
+/* Time management functions */
+/* ?? */
+
+/* Dynamic thread settings */
+/* ?? */
index f115ddd80dcd22bf4f690d9d79697b23e7d62476..4c1ad5e3a4dd348dcc21d549691b8cb1c2d8c756 100644 (file)
@@ -29,7 +29,7 @@
 /*****************************************************************************
  * video_fifo_t
  *****************************************************************************
- * This rotative FIFO contains undecoded pictures that are to be decoded
+ * This rotative FIFO contains undecoded macroblocks that are to be decoded
  *****************************************************************************/
 typedef struct video_fifo_s
 {
@@ -37,7 +37,7 @@ typedef struct video_fifo_s
     vlc_cond_t          wait;              /* fifo data conditional variable */
 
     /* buffer is an array of undec_picture_t pointers */
-    undec_picture_t *           buffer[VFIFO_SIZE + 1];
+    macroblock_t *              buffer[VFIFO_SIZE + 1];
     int                         i_start;
     int                         i_end;
 
@@ -48,22 +48,22 @@ typedef struct video_fifo_s
  * video_buffer_t
  *****************************************************************************
  * This structure enables the parser to maintain a list of free
- * undec_picture_t structures
+ * macroblock_t structures
  *****************************************************************************/
 typedef struct video_buffer_s
 {
     vlc_mutex_t         lock;                            /* buffer data lock */
 
-    undec_picture_t     p_undec_p[VFIFO_SIZE + 1];
-    undec_picture_t *   pp_undec_free[VFIFO_SIZE+1];       /* this is a LIFO */
+    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;
 
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
-undec_picture_t * vpar_GetPicture( video_fifo_t * p_fifo );
-undec_picture_t * vpar_NewPicture( video_fifo_t * p_fifo );
-void vpar_DecodePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p );
-void vpar_ReleasePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p );
-void vpar_DestroyPicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p );
+macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo );
+macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo );
+void vpar_DecodeMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb );
+void vpar_ReleaseMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb );
+void vpar_DestroyMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb );
index 825c3c1a4c0ed9d6f5a657bcd14e1f0b75ec8474..86b35f27974171f0d038ba06489207480a484522 100644 (file)
@@ -1,8 +1,8 @@
-/*******************************************************************************
+/*****************************************************************************
  * video_parser.h : video parser thread
  * (c)1999 VideoLAN
- *******************************************************************************
- *******************************************************************************
+ *****************************************************************************
+ *****************************************************************************
  * Requires:
  *  "config.h"
  *  "common.h"
  *  "video_output.h"
  *  "decoder_fifo.h"
  *  "video_fifo.h"
- *******************************************************************************/
+ *  "vpar_headers.h"
+ *****************************************************************************/
 
-/*******************************************************************************
- * sequence_t : sequence descriptor
- *******************************************************************************
- * ??
- *******************************************************************************/
-typedef struct sequence_s
-{
-    u16                 i_height, i_width;
-    u16                 i_mb_height, i_mb_width;
-    unsigned int        i_aspect_ratio;
-    double              d_frame_rate;
-    unsigned int        i_chroma_format;
-    boolean_t           b_mpeg2;
-    boolean_t           b_progressive;
-    
-    /* Parser context */
-    picture_t *             p_forward, p_backward;
-    pel_lookup_table_t *    p_frame_lum_lookup, p_field_lum_lookup;
-    pel_lookup_table_t *    p_frame_chroma_lookup, p_field_chroma_lookup;
-    quant_matrix_t          intra_quant, nonintra_quant;
-    quant_matrix_t          chroma_intra_quant, chroma_nonintra_quant;
-} sequence_t;
-
-/*******************************************************************************
+/*****************************************************************************
  * vpar_thread_t: video parser thread descriptor
- *******************************************************************************
+ *****************************************************************************
  * ??
- *******************************************************************************/
+ *****************************************************************************/
 typedef struct vpar_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;                                 /* `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 */
 
     /* Thread configuration */
     /* ?? */
@@ -59,67 +37,45 @@ typedef struct vpar_thread_s
     
 
     /* Input properties */
-    decoder_fifo_t      fifo;                                /* PES input fifo */
+    decoder_fifo_t      fifo;                              /* PES input fifo */
 
     /* The bit stream structure handles the PES stream at the bit level */
     bit_stream_t        bit_stream;
 
     /* Output properties */
-    vout_thread_t *     p_vout;                         /* video output thread */
-    int                 i_stream;                           /* video stream id */
+    vout_thread_t *     p_vout;                       /* video output thread */
+    int                 i_stream;                         /* video stream id */
     
     /* Decoder properties */
-    struct vdec_thread_s *      p_vdec[MAX_VDEC];
+    struct vdec_thread_s *      p_vdec[NB_VDEC];
     video_fifo_t                vfifo;
     video_buffer_t              vbuffer;
 
     /* Parser properties */
-    sequence_t          sequence;
+    sequence_t              sequence;
+    picture_parsing_t       picture;
+    slice_parsing_t         slice;
+    macroblock_parsing_t    mb;
 
 #ifdef STATS
     /* Statistics */
-    count_t         c_loops;                               /* number of loops */
-    count_t         c_idle_loops;                     /* number of idle loops */
-    count_t         c_sequences;                       /* number of sequences */
-    count_t         c_pictures;                    /* number of pictures read */
-    count_t         c_i_pictures;                /* number of I pictures read */
-    count_t         c_p_pictures;                /* number of P pictures read */
-    count_t         c_b_pictures;                /* number of B pictures read */    
-    count_t         c_decoded_pictures;         /* number of pictures decoded */
-    count_t         c_decoded_i_pictures;     /* number of I pictures decoded */
-    count_t         c_decoded_p_pictures;     /* number of P pictures decoded */
-    count_t         c_decoded_b_pictures;     /* number of B pictures decoded */
+    count_t         c_loops;                              /* number of loops */
+    count_t         c_idle_loops;                    /* number of idle loops */
+    count_t         c_sequences;                      /* number of sequences */
+    count_t         c_pictures;                   /* number of pictures read */
+    count_t         c_i_pictures;               /* number of I pictures read */
+    count_t         c_p_pictures;               /* number of P pictures read */
+    count_t         c_b_pictures;               /* number of B pictures read */
+    count_t         c_decoded_pictures;        /* number of pictures decoded */
+    count_t         c_decoded_i_pictures;    /* number of I pictures decoded */
+    count_t         c_decoded_p_pictures;    /* number of P pictures decoded */
+    count_t         c_decoded_b_pictures;    /* number of B pictures decoded */
 #endif
 } vpar_thread_t;
 
-/*******************************************************************************
- * Standard start codes
- *******************************************************************************/
-#define PICTURE_START_CODE      0x100
-#define SLICE_START_CODE_MIN    0x101
-#define SLICE_START_CODE_MAX    0x1AF
-#define USER_DATA_START_CODE    0x1B2
-#define SEQUENCE_HEADER_CODE    0x1B3
-#define SEQUENCE_ERROR_CODE     0x1B4
-#define EXTENSION_START_CODE    0x1B5
-#define SEQUENCE_END_CODE       0x1B7
-#define GROUP_START_CODE        0x1B8
-
-/* 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
-
-/*******************************************************************************
+/*****************************************************************************
  * Prototypes
- *******************************************************************************/
+ *****************************************************************************/
 
 /* Thread management functions */
 vpar_thread_t * vpar_CreateThread       ( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
index da15c9e9b43ba0c99a211554302683a0a380c490..dcbc0fc61d15bca8d4f1ebb5ca13cee32c7aca63 100644 (file)
  *****************************************************************************/
 
 /*****************************************************************************
- * quant_matrix_t : Quantization Matrix
+ * macroblock_t : information on a macroblock
+ *****************************************************************************/
+typedef struct macroblock_s
+{
+    picture_t *             p_picture;
+    int                     i_mb_x, i_mb_y;
+    int                     i_structure;
+    int                     i_l_x, i_l_y;    /* position of macroblock (lum) */
+    int                     i_c_x, i_c_y; /* position of macroblock (chroma) */
+    int                     i_structure;
+    int                     i_chroma_nb_blocks;  /* nb of bks for a chr comp */
+
+    /* IDCT information */
+    elem_t                  ppi_blocks[12][64];                    /* blocks */
+    f_idct_t                pf_idct[12];             /* sparse IDCT or not ? */
+    int                     pi_sparse_pos[12];
+
+    /* Motion compensation information */
+    f_motion_t              pf_motion;    /* function to use for motion comp */
+    f_chroma_motion_t       pf_chroma_motion;
+    picture_t *             p_backw_top, p_backw_bot;
+    picture_t *             p_forw_top, p_forw_bot;
+    int                     i_field_select_backw_top, i_field_select_backw_bot;
+    int                     i_field_select_forw_top, i_field_select_forw_bot;
+    int                     pi_motion_vectors_backw_top[2];
+    int                     pi_motion_vectors_backw_bot[2];
+    int                     pi_motion_vectors_forw_top[2];
+    int                     pi_motion_vectors_forw_bot[2];
+
+    /* AddBlock information */
+    f_addb_t                pf_addb[12];
+    data_t *                p_data[12];    /* positions of blocks in picture */
+    int                     i_lum_incr, i_chroma_incr;
+} macroblock_t;
+
+/*****************************************************************************
+ * macroblock_parsing_t : parser context descriptor #3
+ *****************************************************************************/
+typedef struct
+{
+    int                     i_mb_type, i_motion_type, i_mv_count, i_mv_format;
+    int                     i_coded_block_pattern;
+    boolean_t               b_dct_type;
+} macroblock_parsing_t;
+
+/*****************************************************************************
+ * LoadQuantizerScale
  *****************************************************************************
- * ??
+ * Quantizer scale factor (ISO/IEC 13818-2 7.4.2.2)
  *****************************************************************************/
-typedef struct quant_matrix_s
+static __inline__ void LoadQuantizerScale( vpar_thread_t * p_vpar )
 {
-    int         pi_matrix[64];
-    boolean_t   b_allocated;
-                          /* Has the matrix been allocated by vpar_headers ? */
-} quant_matrix_t;
+    /* Quantization coefficient table */
+    static unsigned char    ppi_quantizer_scale[3][32] =
+    {
+        /* MPEG-2 */
+        {
+            /* q_scale_type */
+            /* linear */
+            0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,
+            32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62
+        },
+        {
+            /* non-linear */
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 10,12,14,16,18,20, 22,
+            24,28,32,36,40,44,48,52,56,64,72,80,88,96,104,112
+        },
+        /* MPEG-1 */
+        {
+            0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
+            16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+        }
+    };
+
+    p_vpar->slice.i_quantizer_scale = ppi_quantizer_scale
+           [(!p_vpar->sequence.b_mpeg2 << 1) | p_vpar->picture.b_q_scale_type]
+           [GetBits( &p_vpar->bit_stream, 5 )];
+}
+
+/*****************************************************************************
+ * Standard codes
+ *****************************************************************************/
+/* Macroblock types */
+#define MB_INTRA                        1
+#define MB_PATTERN                      2
+#define MB_MOTION_BACKWARD              4
+#define MB_MOTION_FORWARD               8
+#define MB_QUANT                        16
 
-extern int *    pi_default_intra_quant;
-extern int *    pi_default_nonintra_quant;
+/* Motion types */
+#define MOTION_FIELD                    1
+#define MOTION_FRAME                    2
+#define MOTION_16X8                     2
+#define MOTION_DMV                      3
diff --git a/include/vpar_headers.h b/include/vpar_headers.h
new file mode 100644 (file)
index 0000000..cb992bf
--- /dev/null
@@ -0,0 +1,141 @@
+/*****************************************************************************
+ * vpar_headers.h : video parser : headers parsing
+ * (c)1999 VideoLAN
+ *****************************************************************************
+ *****************************************************************************
+ * Requires:
+ *  "config.h"
+ *  "common.h"
+ *  "mtime.h"
+ *  "vlc_thread.h"
+ *  "input.h"
+ *  "video.h"
+ *  "video_output.h"
+ *  "decoder_fifo.h"
+ *  "video_fifo.h"
+ *****************************************************************************/
+/*****************************************************************************
+ * Function pointers
+ *****************************************************************************/
+typedef (void *)    f_slice_header_t( vpar_thread_t*, int*, int, elem_t*, u32);
+
+/*****************************************************************************
+ * quant_matrix_t : Quantization Matrix
+ *****************************************************************************/
+typedef struct quant_matrix_s
+{
+    int         pi_matrix[64];
+    boolean_t   b_allocated;
+                          /* Has the matrix been allocated by vpar_headers ? */
+} quant_matrix_t;
+
+extern int *    pi_default_intra_quant;
+extern int *    pi_default_nonintra_quant;
+
+/*****************************************************************************
+ * sequence_t : sequence descriptor
+ *****************************************************************************/
+typedef struct sequence_s
+{
+    u32                 i_height, i_width, i_chroma_width, i_size;
+    u32                 i_mb_height, i_mb_width, i_mb_size;
+    unsigned int        i_aspect_ratio;
+    double              d_frame_rate;
+    unsigned int        i_chroma_format;
+    int                 i_chroma_nb_blocks;
+    boolean_t           b_mpeg2;
+    boolean_t           b_progressive;
+    unsigned int        i_scalable_mode;
+    f_slice_header_t    pf_slice_header;
+    quant_matrix_t      intra_quant, nonintra_quant;
+    quant_matrix_t      chroma_intra_quant, chroma_nonintra_quant;
+    (void *)            pf_decode_mv( vpar_thread_t *, int );
+    (void *)            pf_decode_pattern( vpar_thread_t * );
+
+    /* Parser context */
+    picture_t *         p_forward, p_backward;
+} sequence_t;
+
+/*****************************************************************************
+ * picture_parsing_t : parser context descriptor
+ *****************************************************************************/
+typedef struct picture_parsing_s
+{
+    boolean_t           b_full_pel_forward_vector, b_full_pel_backward_vector;
+    int                 i_forward_f_code, i_backward_f_code;
+
+    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_alternate_scan, b_progressive_frame;
+    boolean_t           b_top_field_first, b_concealment_mv;
+
+    int                 i_lum_incr, i_chroma_incr;
+
+    /* Used for second field management */
+    int                 i_current_structure;
+
+    picture_t *         p_picture;
+    macroblock_t *      pp_mb[MAX_MB];
+
+    /* Relative to the current field */
+    int                 i_coding_type, i_structure;
+    boolean_t           b_frame_structure;
+    (int *)             pf_macroblock_type( vpar_thread_t * );
+
+    boolean_t           b_error;
+} picture_parsing_t;
+
+/*****************************************************************************
+ * slice_parsing_t : parser context descriptor #2
+ *****************************************************************************/
+typedef struct slice_parsing_s
+{
+    unsigned char       i_quantizer_scale;
+    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 */
+} slice_parsing_t;
+
+/*****************************************************************************
+ * Standard codes
+ *****************************************************************************/
+#define PICTURE_START_CODE      0x100
+#define SLICE_START_CODE_MIN    0x101
+#define SLICE_START_CODE_MAX    0x1AF
+#define USER_DATA_START_CODE    0x1B2
+#define SEQUENCE_HEADER_CODE    0x1B3
+#define SEQUENCE_ERROR_CODE     0x1B4
+#define EXTENSION_START_CODE    0x1B5
+#define SEQUENCE_END_CODE       0x1B7
+#define GROUP_START_CODE        0x1B8
+
+/* 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
+
+/* 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 */
+
+/* Structures */
+#define TOP_FIELD               1
+#define BOTTOM_FIELD            2
+#define FRAME_STRUCTURE         3
diff --git a/src/video_decoder/vdec_idct.c b/src/video_decoder/vdec_idct.c
new file mode 100644 (file)
index 0000000..7128eb6
--- /dev/null
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * vdec_idct.c : IDCT functions
+ * (c)1999 VideoLAN
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XShm.h>
+
+#include "config.h"
+#include "common.h"
+#include "mtime.h"
+#include "vlc_thread.h"
+
+#include "intf_msg.h"
+#include "debug.h"                    /* ?? temporaire, requis par netlist.h */
+
+#include "input.h"
+#include "input_netlist.h"
+#include "decoder_fifo.h"
+#include "video.h"
+#include "video_output.h"
+#include "video_parser.h"
+
+#include "undec_picture.h"
+#include "video_fifo.h"
+#include "video_decoder.h"
+
+/*
+ * Local prototypes
+ */
+
+/* Our current implementation is a fast DCT, we might move to a fast DFT or
+ * an MMX DCT in the future. */
+
+/*****************************************************************************
+ * vdec_DummyIDCT : dummy function that does nothing
+ *****************************************************************************/
+void vdec_DummyIDCT( elem_t * p_block, int i_idontcare )
+{
+}
+
+/*****************************************************************************
+ * vdec_SparseIDCT : IDCT function for sparse matrices
+ *****************************************************************************/
+void vdec_SparseIDCT( elem_t * p_block, int i_sparse_pos )
+{
+    /* Copy from mpeg_play */
+}
+
+/*****************************************************************************
+ * vdec_IDCT : IDCT function for normal matrices
+ *****************************************************************************/
+void vdec_IDCT( elem_t * p_block, int i_idontcare )
+{
+
+}
index 310d41b6d643ac4387b365b19cb1e1ef336ada27..87f7dad82efff9fb9537bf4287faeb37d72419db 100644 (file)
@@ -3,8 +3,6 @@
  * (c)1999 VideoLAN
  *****************************************************************************/
 
-/* ?? passer en terminate/destroy avec les signaux supplémentaires */
-
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
  * Local prototypes
  */
 
+typedef (void *)        f_motion_c_t( coeff_t *, pel_lookup_table_t *,
+                                      int, coeff_t *, int, int,
+                                      int, int, int, int, int );
+
 /*****************************************************************************
- * vdec_MotionCompensation : motion compensation
+ * vdec_DummyRecon : motion compensation for an intra macroblock
  *****************************************************************************/
-void vdec_MotionFrame( vdec_thread_t * p_vdec,
-                       undec_picture_t * p_undec_p, int i_mb,
-                       f_motion_mb_t pf_mb_motion )
+void vdec_DummyRecon( macroblock_t * p_mb )
 {
-    static int      p_chroma_nb_blocks[4] = {1, 2, 4};
-    static int      p_chroma_nb_elems[4] = {0, 64, 128, 256};
+}
 
-    int i_mb_x, i_mb_y;   /* Position of our macroblock in the final picture */
-    elem_t *    p_y, p_u, p_v;             /* Pointers to our picture's data */
+/*****************************************************************************
+ * vdec_ForwardRecon : motion compensation for a forward predicted macroblock
+ *****************************************************************************/
+void vdec_ForwardRecon( macroblock_t * p_mb )
+{
+
+}
+
+/*****************************************************************************
+ * vdec_BackwardRecon : motion compensation for a backward predicted macroblock
+ *****************************************************************************/
+void vdec_BackwardRecon( macroblock_t * p_mb )
+{
 
-#define P_mb_info p_undec_p->p_mb_info[i_mb]
-    
-    i_mb_x = (i_mb << 5) % p_undec_p->p_picture->i_width;
-    i_mb_y = (i_mb << 5) / p_undec_p->p_picture->i_width;
-    p_y = &p_undec_p->p_picture->p_y[256*i_mb];
-    p_u = &p_undec_p->p_picture->p_u[p_chroma_nb_elems[p_undec_p->p_picture->i_chroma_type]*i_mb];
-    p_v = &p_undec_p->p_picture->p_v[p_chroma_nb_elems[p_undec_p->p_picture->i_chroma_type]*i_mb];
-    
-    if( (p_undec_p->i_coding_type == P_CODING_TYPE) ||
-        (P_mb_info->i_mb_type & MB_MOTION_FORWARD) )
-    {
-        if( (P_mb_info->i_motion_type == MOTION_FRAME) ||
-            !(P_mb_info->i_mb_type & MB_INTRA) )
-        {
-            MotionBlock( p_undec_p->p_forward->p_u,
-                         p_undec_p->p_forward->p_lookup_lum,
-                         p_undec_p->p_picture->i_width,
-                         p_u, i_mb_x, i_mb_y,
-                         p_undec_p->p_picture->i_width,
-                         p_undec_p->ppp_motion_vectors[0][0][0],
-                         p_undec_p->ppp_motion_vectors[0][0][1] );
-        }
-    }
 }
 
 /*****************************************************************************
- * MotionMacroblock : motion compensation for a macroblock
+ * vdec_BidirectionalRecon : motion compensation for a bidirectionally
+ *                           predicted macroblock
  *****************************************************************************/
-void vdec_MotionMacroblock420( coeff_t * p_src, pel_lookup_table_t * p_lookup,
-                               int i_width_line,
-                               coeff_t * p_dest, int i_dest_x, i_dest_y,
-                               int i_stride_line,
-                               i_mv1_x, i_mv1_y, i_mv2_x, i_mv2_y )
+void vdec_BidirectionalRecon( macroblock_t * p_mb )
+{
+
+}
+
+/*****************************************************************************
+ * vdec_MotionMacroblock420 : motion compensation for a 4:2:0 macroblock
+ *****************************************************************************/
+void vdec_MotionMacroblock420( macroblock_t * p_mb )
 {
     /* Luminance */
     MotionBlock( p_undec_p->p_forward->p_u, p_undec_p->p_forward->p_lookup_lum,
@@ -105,12 +97,9 @@ void __inline__ MotionBlock( coeff_t * p_src, pel_lookup_table_t * p_lookup,
                              int i_stride_line,
                              i_mv1_x, i_mv1_y, i_mv2_x, i_mv2_y )
 {
-    static (void *)     ComponentMode( coeff_t * p_src,
-                             pel_lookup_table_t * p_lookup,
-                             coeff_t * p_dest, int i_dest_x, i_dest_y,
-                             int i_stride_line, i_mv_x, i_mv_y )[4]
-                                = { ComponentNN, ComponentNH, ComponentHN,
-                                    ComponentHH };
+    static f_motion_c_t     ComponentMode[4]
+                                = { &ComponentNN, &ComponentNH, &ComponentHN,
+                                    &ComponentHH };
 
     int i_mode;
 
@@ -118,7 +107,8 @@ void __inline__ MotionBlock( coeff_t * p_src, pel_lookup_table_t * p_lookup,
 
     ComponentMode[i_mode]( p_src, p_lookup, i_width_line,
                            p_dest, i_dest_x, i_dest_y,
-                           i_stride_line, i_mv_x >> 1, i_mv_y >> 1 );
+                           i_stride_line, i_mv1_x >> 1, i_mv1_y >> 1,
+                           i_mv2_x >> 1, i_mv2_y >> 1 );
 }
 
 /*****************************************************************************
@@ -132,9 +122,22 @@ void ComponentNN( coeff_t * p_src, pel_lookup_table_t * p_lookup,
     int             i_vpos;
     register int    i_hpos, i_src_loc;
     
-    i_src_loc = (i_dest_y + i_mv_y)*i_width_line + i_dest_x + i_mv_x;
+    i_src_loc = (i_dest_y + i_mv1_y)*i_width_line + i_dest_x + i_mv1_x;
     
-    for( i_vpos = 0; i_vpos < 8; i_vpos++ )
+    for( i_vpos = 0; i_vpos < 4; i_vpos++ )
+    {
+        for( i_hpos = 0; i_hpos < 8; i_hpos++ )
+        {
+            p_dest[i_hpos] += p_src[p_lookup->pi_pel[i_src_loc + i_hpos]];
+        }
+        
+        p_dest += 8;
+        i_src_loc += i_stride_line;
+    }
+
+    i_src_loc = (i_dest_y + i_mv2_y)*i_width_line + i_dest_x + i_mv2_x;
+
+    for( i_vpos = 4; i_vpos < 8; i_vpos++ )
     {
         for( i_hpos = 0; i_hpos < 8; i_hpos++ )
         {
index 00df1e880a4d1843ca8e2e6ce9b1cf2ac2c80ec5..ff0328e0ad32402adf443f838a23a485f0088ddb 100644 (file)
@@ -43,8 +43,8 @@ static int      InitThread          ( vdec_thread_t *p_vdec );
 static void     RunThread           ( vdec_thread_t *p_vdec );
 static void     ErrorThread         ( vdec_thread_t *p_vdec );
 static void     EndThread           ( vdec_thread_t *p_vdec );
-static void     DecodePicture       ( vdec_thread_t *p_vdec,
-                                      undec_picture_t * p_undec_p );
+static void     DecodeMacroblock    ( vdec_thread_t *p_vdec,
+                                      macroblock_t * p_mb );
 
 /*******************************************************************************
  * vdec_CreateThread: create a video decoder thread
@@ -165,11 +165,11 @@ static void RunThread( vdec_thread_t *p_vdec )
      */
     while( (!p_vdec->b_die) && (!p_vdec->b_error) )
     {
-        undec_picture_t *       p_undec_p;
+        macroblock_t *          p_mb;
         
-        if( (p_undec_p = GetPicture( p_vdec->p_vpar->p_fifo )) != NULL )
+        if( (p_mb = GetMacroblock( &p_vdec->p_vpar.vfifo )) != NULL )
         {
-            DecodePicture( p_vdec, p_undec_p );
+            DecodeMacroblock( p_vdec, p_mb );
         }
     } 
 
@@ -220,92 +220,101 @@ static void EndThread( vdec_thread_t *p_vdec )
 }
 
 /*******************************************************************************
- * DecodePicture : decode a picture
+ * DecodeMacroblock : decode a macroblock of a picture
  *******************************************************************************/
-static void DecodePicture( vdec_thread_t *p_vdec, undec_picture_t * p_undec_p )
+static void DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb )
 {
-    static int              pi_chroma_nb_blocks[4] = {0, 1, 2, 4};
-    static int              pi_chroma_nb_coeffs[4] = {0, 64, 128, 256};
-    static f_motion_mb_t    ppf_chroma_motion[4] = { NULL,
-                                                     &vdec_MotionMacroBlock420,
-                                                     &vdec_MotionMacroBlock422,
-                                                     &vdec_MotionMacroBlock444 };
-    static f_motion_t       pppf_motion_forward[4][2] = {
-                                {NULL, NULL} /* I picture */
-                                {&vdec_MotionForward, &vdec_MotionForward} /* P */
-                                {NULL, &vdec_MotionForward} /* B */
-                                {NULL, NULL} /* D */ };
-    static f_motion_t       pppf_motion_backward[4][2] = {
-                                {NULL, NULL} /* I picture */
-                                {NULL, NULL} /* P */
-                                {NULL, &vdec_MotionBackward} /* B */
-                                {NULL, NULL} /* D */ };
-    static f_motion_t       ppf_motion[4] = { NULL,
-                                              &vdec_MotionTopFirst,
-                                              &vdec_MotionBottomFirst,
-                                              &vdec_MotionFrame };
-
-    int             i_mb, i_b, i_totb;
-    coeff_t *       p_y, p_u, p_v;
-    f_motion_mb_t   pf_chroma_motion;
-    f_motion_t      pf_motion_forward, pf_motion_backward;
-    int             i_chroma_nb_blocks, i_chroma_nb_coeffs;
-    
-    p_y = (coeff_t *)p_undec_p->p_picture->p_y;
-    p_u = (coeff_t *)p_undec_p->p_picture->p_u;
-    p_v = (coeff_t *)p_undec_p->p_picture->p_v;
-
-#define I_chroma_format     p_undec_p->p_picture->i_chroma_format
-    pf_chroma_motion = ppf_chroma_motion[I_chroma_format];
-    pf_motion_forward
-    pf_motion = ppf_motion[p_undec_p->i_structure];
+    int             i_b;
 
-    i_chroma_nb_blocks = pi_chroma_nb_blocks[I_chroma_format];
-    i_chroma_nb_coeffs = pi_chroma_nb_coeffs[I_chroma_format];
-#undef I_chroma_format
+    /*
+     * Motion Compensation (ISO/IEC 13818-2 section 7.6)
+     */
+    (*p_mb->pf_motion)( p_mb );
 
-    for( i_mb = 0; i_mb < p_undec_p->i_mb_height*p_undec_p->i_mb_width; i_mb++ )
+    /* luminance */
+    for( i_b = 0; i_b < 4; i_b++ )
     {
-#define P_mb_info           p_undec_p->p_mb_info[i_ref]
-
         /*
          * Inverse DCT (ISO/IEC 13818-2 section Annex A)
          */
-        
-        /* Luminance : always 4 blocks */
-        for( i_b = 0; i_b < 4; i_b++ )
-        {
-            (*P_mb_info.p_idct_function[i_b])( p_y + i_b*64 );
-        }
-        i_totb = 4;
-        
-        /* Chrominance Cr */
-        for( i_b = 0; i_b < i_chroma_nb_blocks\ 5; i_b++ )
-        {
-            (*P_mb_info.p_idct_function[i_totb + i_b])( p_u + i_b*64 );
-        }
-        i_totb += i_chroma_nb_blocks;
-        
-        /* Chrominance Cb */
-        for( i_b = 0; i_b < i_chroma_nb_blocks; i_b++ )
-        {
-            (*P_mb_info.p_idct_function[i_totb + i_b])( p_v + i_b*64 );
-        }
+        (*p_mb->pf_idct[i_b])( p_mb, p_mb->ppi_blocks[i_b], p_mb->pi_sparse_pos[i_b] );
+
+        /*
+         * Adding prediction and coefficient data (ISO/IEC 13818-2 section 7.6.8)
+         */
+        (*p_mb->pf_addb[i_b])( p_mb->ppi_blocks[i_b],
+                               p_mb->p_data[i_b], p_mb->i_lum_incr );
+    }
 
+    /* chrominance */
+    for( i_b = 4; i_b < 4 + 2*p_mb->i_chroma_nb_blocks; i_b++ )
+    {
         /*
-         * Motion Compensation (ISO/IEC 13818-2 section 7.6)
+         * Inverse DCT (ISO/IEC 13818-2 section Annex A)
          */
-        (*pf_motion)( p_vdec, p_undec_p, i_mb, pf_chroma_motion );
+        (*p_mb->pf_idct[i_b])( p_mb, p_mb->ppi_blocks[i_b], p_mb->pi_sparse_pos[i_b] );
 
-        p_y += 256;
-        p_u += i_chroma_nb_coeffs;
-        p_v += i_chroma_nb_coeffs;
-#undef P_mb_info
+        /*
+         * Adding prediction and coefficient data (ISO/IEC 13818-2 section 7.6.8)
+         */
+        (*p_mb->pf_addb[i_b])( p_mb->ppi_blocks[i_b],
+                               p_mb->p_data[i_b], p_mb->i_chroma_incr );
     }
 
     /*
-     * Decoding is finished, mark the picture ready for displaying and free
-     * unneeded memory
+     * Decoding is finished, release the macroblock and free
+     * unneeded memory.
      */
-    vpar_ReleasePicture( p_vdec->p_vpar->p_fifo, p_undec_p );
+    vpar_ReleaseMacroblock( &p_vdec->p_vpar.vfifo, p_mb );
+}
+
+/*******************************************************************************
+ * vdec_AddBlock : add a block
+ *******************************************************************************/
+void vdec_AddBlock( elem_t * p_block, data_t * p_data, int i_incr )
+{
+    int i_x, i_y;
+    
+    for( i_y = 0; i_y < 8; i_y++ )
+    {
+        for( i_x = 0; i_x < 8; i_x++ )
+        {
+            /* ??? Need clip to be MPEG-2 compliant */
+            *p_data++ += *p_block++;
+        }
+        p_data += i_incr;
+    }
+}
+
+/*******************************************************************************
+ * vdec_CopyBlock : copy a block
+ *******************************************************************************/
+void vdec_CopyBlock( elem_t * p_block, data_t * p_data, int i_incr )
+{
+    int i_x, i_y;
+    
+    for( i_y = 0; i_y < 8; i_y++ )
+    {
+#ifndef VDEC_DFT
+        /* elem_t and data_t are the same */
+        memcopy( p_data, p_block, 8*sizeof(data_t) );
+        p_data += i_incr+8;
+        p_block += 8;
+#else
+        for( i_x = 0; i_x < 8; i_x++ )
+        {
+            /* ??? Need clip to be MPEG-2 compliant */
+            /* ??? Why does the reference decoder add 128 ??? */
+            *p_data++ = *p_block++;
+        }
+        p_data += i_incr;
+#endif
+    }
+}
+
+/*******************************************************************************
+ * vdec_DummyBlock : dummy function that does nothing
+ *******************************************************************************/
+void vdec_DummyBlock( elem_t * p_block, data_t * p_data, int i_incr )
+{
 }
index 8242894a84ec0a2852102a24441b8ad5983bd828..0831aa46234734f7879858add2dd80eeb045f833 100644 (file)
@@ -30,7 +30,7 @@
 #include "video_output.h"
 #include "video_parser.h"
 
-#include "undec_picture.h"
+#include "macroblock.h"
 #include "video_fifo.h"
 #include "video_decoder.h"
 
@@ -39,7 +39,7 @@
  *****************************************************************************/
 void vpar_InitFIFO( vpar_thread_t * p_vpar )
 {
-    int i_dummy;
+    int                 i_dummy;
     
     /* Initialize mutex and cond */
     vlc_mutex_init( p_vpar->vfifo.lock );
@@ -54,17 +54,16 @@ void vpar_InitFIFO( vpar_thread_t * p_vpar )
     i_index = VFIFO_SIZE; /* all structures are available */
     for( i_dummy = 0; i_dummy < VFIFO_SIZE + 1; i_dummy++ )
     {
-        p_vpar->vfifo.pp_undec_free[i_dummy] = p_vpar->vfifo.p_undec_p + i;
-        p_vpar->vfifo.p_undec_p[i].p_mb_info = NULL;
+        p_vpar->vfifo.pp_mb_free[i_dummy] = p_vpar->vfifo.p_macroblocks + i;
     }
 }
 
 /*****************************************************************************
- * vpar_GetPicture : return a picture to be decoded
+ * vpar_GetMacroblock : return a macroblock to be decoded
  *****************************************************************************/
-undec_picture_t * vpar_GetPicture( video_fifo_t * p_fifo )
+macroblock_t * vpar_GetMacroblock( video_fifo_t * p_fifo )
 {
-    undec_picture_t *   p_undec_p;
+    macroblock_t *      p_mb;
 
     vlc_mutex_lock( &p_fifo->lock );
     while( VIDEO_FIFO_ISEMPTY( *p_fifo ) )
@@ -77,20 +76,20 @@ undec_picture_t * vpar_GetPicture( video_fifo_t * p_fifo )
         }
     }
     
-    p_undec_p = VIDEO_FIFO_START( *p_fifo );
+    p_mb = VIDEO_FIFO_START( *p_fifo );
     VIDEO_FIFO_INCSTART( *p_fifo );
     
     vlc_mutex_unlock( &p_fifo->lock );
     
-    return( p_undec_p );
+    return( p_mb );
 }
 
 /*****************************************************************************
- * vpar_NewPicture : return a buffer for the parser
+ * vpar_NewMacroblock : return a buffer for the parser
  *****************************************************************************/
-undec_picture_t * vpar_NewPicture( video_fifo_t * p_fifo )
+macroblock_t * vpar_NewMacroblock( video_fifo_t * p_fifo )
 {
-    undec_picture_t *   p_undec_p;
+    macroblock_t *      p_mb;
 
 #define P_buffer p_fifo->p_vpar.vbuffer
     vlc_mutex_lock( &P_buffer->lock );
@@ -100,128 +99,100 @@ undec_picture_t * vpar_NewPicture( video_fifo_t * p_fifo )
         return NULL;
     }
 
-    p_undec_p = P_buffer->pp_undec_free[ P_buffer->i_index-- ];
+    p_mb = P_buffer->pp_undec_free[ P_buffer->i_index-- ];
 #undef P_buffer
 
     vlc_mutex_unlock( &P_buffer->lock );
-    return( p_undec_p );
+    return( p_mb );
 }
 
 /*****************************************************************************
- * vpar_DecodePicture : put a picture in the video fifo, if it is decodable
+ * vpar_DecodeMacroblock : put a macroblock in the video fifo
  *****************************************************************************/
-void vpar_DecodePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p )
+void vpar_DecodeMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb )
 {
-    boolean_t           b_decodable;
-    
-    switch( p_undec_p )
-    {
-    case B_CODING_TYPE:
-        b_decodable = ((p_undec_p->p_backward_p != NULL) &&
-                       (p_undec_p->p_forward_p != NULL));
-        break;
-    case P_CODING_TYPE:
-        b_decodable = (p_undec_p->p_backward_p != NULL);
-        break;
-    case I_CODING_TYPE:
-    case D_CODING_TYPE:
-        b_decodable = TRUE;
-        break;
-    default:
-        /* That should not happen */
-    }
-
-    if( b_decodable )
-    {
-        /* Place picture in the video FIFO */
-        vlc_mutex_lock( &p_fifo->lock );
+    /* 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_undec_p;
-        VIDEO_FIFO_INCEND( *p_fifo );
+    /* 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 );
-    }
+    vlc_mutex_unlock( &p_fifo->lock );
 }
 
 /*****************************************************************************
- * vpar_ReleasePicture : put a picture in the video_output fifo, and update
- *                  links and buffers
+ * vpar_ReleaseMacroblock : release a macroblock and put the picture in the
+ *                          video output heap, if it is finished
  *****************************************************************************/
-void vpar_ReleasePicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p )
+void vpar_ReleaseMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb )
 {
-    int         i_ref;
-    
-    /* Tell referencing pictures so that they can be decoded */
-    for( i_ref = 0; p_undec_p->pp_referencing_undec[i_ref].p_undec != NULL
-                    && i_ref < MAX_REFERENCING_UNDEC; i_ref++ )
+    /* Unlink referenced pictures */
+    if( p_mb->p_forw_top != NULL )
     {
-        *p_undec_p->pp_referencing_undec[i_ref].pp_frame = p_undec_p->p_picture;
-        vout_LinkPicture( p_fifo->p_vpar.p_vout, p_picture );
-        
-        /* Try to put the referencing picture in the video FIFO */
-        vpar_DecodePicture( p_fifo, p_undec_p->pp_referencing_undec[i_ref].p_undec );
+        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_forw_top );
+    }
+    if( p_mb->p_backw_top != NULL )
+    {
+        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_backw_top );
+    }
+    if( p_mb->p_forw_bot != NULL )
+    {
+        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_forw_bot );
+    }
+    if( p_mb->p_backw_bot != NULL )
+    {
+        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_backw_bot );
     }
 
-    /* Unlink referenced pictures */
-    if( p_undec_p->p_forward_ref != NULL )
+    /* Unlink picture buffer */
+    vlc_mutex_lock( &p_mb->p_picture->lock_deccount );
+    p_mb->p_picture->i_deccount--;
+    if( p_mb->p_picture->i_deccount == 0 )
     {
-        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_forward_ref );
-        if( p_undec_p->p_backward_ref != NULL )
-        {
-            vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_backward_ref );
-        }
+        /* 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 );
     }
-    
-    /* Mark the picture to be displayed */
-    vout_DisplayPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_picture );
+    vlc_mutex_unlock( & p_mb->p_picture->lock_deccount );
 
-    /* Release the undec_picture_t structure */
+    /* Release the macroblock_t structure */
 #define P_buffer p_fifo->p_vpar.vbuffer
     vlc_mutex_lock( &P_buffer->lock );
-
-    P_buffer->pp_undec_free[ ++P_buffer->i_index ] = p_undec_p;
-    
+    P_buffer->pp_mb_free[ ++P_buffer->i_index ] = p_mb;
     vlc_mutex_unlock( &P_buffer->lock );
 #undef P_buffer
-    }
 }
 
 /*****************************************************************************
- * vpar_DestroyPicture : destroy a picture in case of error
+ * vpar_DestroyMacroblock : destroy a macroblock in case of error
  *****************************************************************************/
-void vpar_DestroyPicture( video_fifo_t * p_fifo, undec_picture_t * p_undec_p )
+void vpar_DestroyMacroblock( video_fifo_t * p_fifo, macroblock_t * p_mb )
 {
-    int         i_ref;
-    
-    /* Destroy referencing pictures */
-    for( i_ref = 0; p_undec_p->pp_referencing_undec[i_ref].p_undec != NULL
-                    && i_ref < MAX_REFERENCING_UNDEC; i_ref++ )
+    /* Unlink referenced pictures */
+    if( p_mb->p_forw_top != NULL )
     {
-        /* Try to put the referencing picture in the video FIFO */
-        vpar_DestroyPicture( p_fifo, p_undec_p->pp_referencing_undec[i_ref].p_undec );
+        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_forw_top );
     }
-
-    /* Unlink referenced pictures */
-    if( p_undec_p->p_forward_ref != NULL )
+    if( p_mb->p_backw_top != NULL )
     {
-        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_forward_ref );
-        if( p_undec_p->p_backward_ref != NULL )
-        {
-            vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_backward_ref );
-        }
+        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_backw_top );
     }
-    
-    /* Release the picture buffer */
-    vout_DestroyPicture( p_fifo->p_vpar.p_vout, p_undec_p->p_picture );
-    
-    /* Release the undec_picture_t structure */
+    if( p_mb->p_forw_bot != NULL )
+    {
+        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_forw_bot );
+    }
+    if( p_mb->p_backw_bot != NULL )
+    {
+        vout_UnlinkPicture( p_fifo->p_vpar.p_vout, p_mb->p_backw_bot );
+    }
+
+    /* Release the macroblock_t structure */
 #define P_buffer p_fifo->p_vpar.vbuffer
     vlc_mutex_lock( &P_buffer->lock );
-
-    P_buffer->pp_undec_free[ ++P_buffer->i_index ] = p_undec_p;
-    
+    P_buffer->pp_mb_free[ ++P_buffer->i_index ] = p_mb;
     vlc_mutex_unlock( &P_buffer->lock );
 #undef P_buffer
-    }
 }
index b4c0e6398876b78c696d034492e9731b6a6fe74f..de98f7fb34f2599e7a30566e3364832b3edeb944 100644 (file)
@@ -146,6 +146,7 @@ static int CheckConfiguration( video_cfg_t *p_cfg )
  *******************************************************************************/
 static int InitThread( vpar_thread_t *p_vpar )
 {
+    int     i_dummy;
 
     intf_DbgMsg("vpar debug: initializing video parser thread %p\n", p_vpar);
 
@@ -181,6 +182,7 @@ static int InitThread( vpar_thread_t *p_vpar )
     p_vpar->sequence.nonintra_quant.b_allocated = FALSE;
     p_vpar->sequence.chroma_intra_quant.b_allocated = FALSE;
     p_vpar->sequence.chroma_nonintra_quant.b_allocated = FALSE;
+    p_vpar->sequence.i_frame_number = 0;
 
     /* Initialize other properties */
 #ifdef STATS
@@ -201,16 +203,19 @@ static int InitThread( vpar_thread_t *p_vpar )
     
     bzero( p_vpar->p_vdec, MAX_VDEC*sizeof(vdec_thread_t *) );
     
-    /* Spawn a video_decoder thread */
-    /* ??? add the possibility to launch multiple vdec threads */
-    if( (p_vpar->p_vdec[0] = vdec_CreateThread( p_vpar )) == NULL )
+    /* Spawn video_decoder threads */
+    /* ??? modify the number of vdecs at runtime ? */
+    for( i_dummy = 0; i_dummy < NB_VDEC; i_dummy++ )
     {
-        return( 1 );
+        if( (p_vpar->p_vdec[i_dummy] = vdec_CreateThread( p_vpar )) == NULL )
+        {
+            return( 1 );
+        }
     }
 
     /* Mark thread as running and return */
     intf_DbgMsg("vpar debug: InitThread(%p) succeeded\n", p_vpar);
-    return( 0 );    
+    return( 0 );
 }
 
 /*******************************************************************************
@@ -289,15 +294,16 @@ static void ErrorThread( vpar_thread_t *p_vpar )
         vlc_mutex_lock( &p_vpar->fifo.data_lock );
 
         /* ?? trash all trashable PES packets */
-        while( !PARSER_FIFO_ISEMPTY(p_vpar->fifo) )
+        while( !DECODER_FIFO_ISEMPTY(p_vpar->fifo) )
         {
-            input_NetlistFreePES( p_vpar->bit_stream.p_input, PARSER_FIFO_START(p_vpar->fifo) );
-            PARSER_FIFO_INCSTART( p_vpar->fifo );
+            input_NetlistFreePES( p_vpar->bit_stream.p_input,
+                                  DECODER_FIFO_START(p_vpar->fifo) );
+            DECODER_FIFO_INCSTART( p_vpar->fifo );
         }
 
         vlc_mutex_unlock( &p_vpar->fifo.data_lock );
         /* Sleep a while */
-        msleep( VPAR_IDLE_SLEEP );                
+        msleep( VPAR_IDLE_SLEEP );
     }
 }
 
@@ -323,7 +329,7 @@ static void EndThread( vpar_thread_t *p_vpar )
     /* ?? */
 
     /* Destroy vdec threads */
-    for( i_dummy = 0; i_dummy < MAX_VDEC; i_dummy++ )
+    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] );
diff --git a/src/video_parser/vpar_blocks.c b/src/video_parser/vpar_blocks.c
new file mode 100644 (file)
index 0000000..1a2ebbd
--- /dev/null
@@ -0,0 +1,417 @@
+/*****************************************************************************
+ * vpar_blocks.c : blocks parsing
+ * (c)1999 VideoLAN
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XShm.h>
+
+#include "config.h"
+#include "common.h"
+#include "mtime.h"
+#include "vlc_thread.h"
+
+#include "intf_msg.h"
+#include "debug.h"                    /* ?? temporaire, requis par netlist.h */
+
+#include "input.h"
+#include "input_netlist.h"
+#include "decoder_fifo.h"
+#include "video.h"
+#include "video_output.h"
+#include "video_parser.h"
+
+#include "video_fifo.h"
+#include "video_decoder.h"
+
+/*
+ * Local prototypes
+ */
+static __inline__ void InitMacroblock( vpar_thread_t * p_vpar,
+                                       macroblock_t * p_mb, int i_mb_address );
+static __inline__ int MacroblockAddressIncrement( vpar_thread_t * p_vpar );
+static __inline__ void MacroblockModes( vpar_thread_t * p_vpar,
+                                        macroblock_t * p_mb );
+
+typedef (void *)    f_decode_block_t( vpar_thread_t *, macroblock_t *, int );
+
+/*****************************************************************************
+ * vpar_ParseMacroblock : Parse the next macroblock
+ *****************************************************************************/
+void vpar_ParseMacroblock( vpar_thread_t * p_vpar, int * pi_mb_address,
+                           int i_mb_previous, int i_mb_base )
+{
+    static f_addb_t ppf_addb_intra[2] = {vdec_AddBlock, vdec_CopyBlock};
+
+    int             i_mb, i_b, i_mask, i_x, i_y, pi_pos[3], pi_width[3];
+    macroblock_t *  p_mb;
+    f_addb_t        pf_addb;
+
+    *pi_mb_address += MacroblockAddressIncrement( p_vpar );
+
+    for( i_mb = i_mb_previous; i_mb < *pi_mb_address; i_mb++ )
+    {
+        /* Skipped macroblock (ISO/IEC 13818-2 7.6.6). */
+        static int          pi_dc_dct_reinit[4] = {128,256,512,1024};
+        static f_motion_t   pf_motion_skipped[4] = {NULL, vdec_MotionField,
+                                vdec_MotionField, vdec_MotionFrame};
+
+        /* Reset DC predictors (7.2.1). */
+        p_vpar->slice.pi_dct_pred[0] = p_vpar->slice.pi_dct_pred[1]
+            = p_vpar->slice.pi_dct_pred[2]
+            = pi_dc_dct_reinit[p_vpar->picture.i_intra_dc_precision];
+
+        if( p_vpar->picture.i_coding_type == P_CODING_TYPE )
+        {
+            /* Reset motion vector predictors (ISO/IEC 13818-2 7.6.3.4). */
+            bzero( p_vpar->slice.pppi_pmv, 8*sizeof(int) );
+        }
+
+        if( (p_mb = p_vpar->picture.pp_mb[i_mb_base + i_mb] =
+             vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
+        {
+            p_vpar->picture.b_error = TRUE;
+            intf_ErrMsg("vpar error: macroblock list is empty !");
+            return;
+        }
+
+        InitMacroblock( p_vpar, p_mb, i_mb );
+
+        /* No IDCT nor AddBlock. */
+        for( i_b = 0; i_b < 12; i_b++ )
+        {
+            p_mb->pf_idct[i_b] = vdec_DummyIDCT;
+            p_mb->pf_addb[i_b] = vdec_DummyBlock;
+        }
+
+        /* Motion type is picture structure. */
+        p_mb->pf_motion = pf_motion_skipped[p_vpar->picture.i_structure];
+
+        /* Predict from field of same parity. */
+        /* ??? */
+    }
+
+    /* Get a macroblock structure. */
+    if( (p_mb = p_vpar->picture.pp_mb[i_mb_base + *pi_mb_address] =
+         vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
+    {
+        p_vpar->picture.b_error = TRUE;
+        intf_ErrMsg("vpar error: macroblock list is empty !");
+        return;
+    }
+
+    InitMacroblock( p_vpar, p_mb, *pi_mb_address );
+
+    /* Parse off macroblock_modes structure. */
+    MacroblockModes( p_vpar, p_mb );
+
+    if( p_vpar->mb.i_mb_type & MB_QUANT )
+    {
+        LoadQuantizerScale( p_vpar );
+    }
+
+    if( p_vpar->mb.i_mb_type & MB_MOTION_FORWARD )
+    {
+        (*p_vpar->sequence.pf_decode_mv)( p_vpar, 0 );
+    }
+
+    if( p_vpar->mb.i_mb_type & MB_MOTION_BACKWARD )
+    {
+        (*p_vpar->sequence.pf_decode_mv)( p_vpar, 1 );
+    }
+
+    if( p_vpar->picture.b_concealment_mv && (p_vpar->mb.i_mb_type & MB_INTRA) )
+    {
+        DumpBits( &p_vpar->bit_stream, 1 );
+    }
+
+    if( p_vpar->mb.i_mb_type & MB_PATTERN )
+    {
+        (*p_vpar->sequence.pf_decode_pattern)( p_vpar );
+    }
+    else
+    {
+        int     pi_coded_block_pattern[2] = {0,
+                    (1 << 4+2*p_vpar->sequence.i_chroma_nb_blocks) - 1};
+        p_vpar->mb.i_coded_block_pattern = pi_coded_block_pattern
+                                    [p_vpar->mb.i_mb_type & MB_INTRA];
+    }
+
+    pf_addb = ppf_addb_intra[p_vpar->mb.i_mb_type & MB_INTRA];
+
+    /* C'est de la merde, il faut recommencer */
+
+    i_x = p_mb->i_mb_x << 4;
+    i_y = p_mb->i_mb_y << 4;
+
+    pi_pos[0] = i_y*(p_vpar->sequence.i_width
+                        << (!p_vpar->picture.b_frame_structure))
+                + (p_mb->i_structure == BOTTOM_FIELD)*p_vpar->sequence.i_width
+                + i_x;
+    pi_pos[1] = pi_pos[2] = i_y*(p_vpar->sequence.i_chroma_width
+                        << (!p_vpar->picture.b_frame_structure))
+                + (p_mb->i_structure == BOTTOM_FIELD)*p_vpar->sequence.i_chroma_width
+                + (i_x >> (3-p_vpar->sequence.i_chroma_format));
+    pi_width[0] = p_vpar->sequence.i_width << (!p_vpar->picture.b_frame_structure
+                                               || p_vpar->mb.b_dct_type);
+    pi_width[1] = pi_width[2] = p_vpar->sequence.i_chroma_width
+                << (!p_vpar->picture.b_frame_structure || p_vpar->mb.b_dct_type);
+
+    /* Effectively decode blocks. */
+    for( i_b = 0, i_mask = 1 << (3 + 2*p_vpar->sequence.i_chroma_nb_blocks);
+         i_b < 4 + 2*p_vpar->sequence.i_chroma_nb_blocks; i_b++, i_mask >>= 1 )
+    {
+        if( p_vpar->mb.i_coded_block_pattern & i_mask )
+        {
+            static f_decode_block_t pppf_decode_block[2][2] =
+                { {vpar_DecodeMPEG1Non, vpar_DecodeMPEG1Intra},
+                  {vpar_DecodeMPEG2Non, vpar_DecodeMPEG2Intra} };
+            static int              pi_x[12] = {0,8,0,8,0,0,0,0,8,8,8,8};
+            static int              pi_y[12] = {0,0,8,8,0,0,8,8,0,0,8,8};
+            data_t                  pi_data[12] =
+                {p_mb->p_picture->p_y, p_mb->p_picture->p_y,
+                 p_mb->p_picture->p_y, p_mb->p_picture->p_y,
+                 p_mb->p_picture->p_u, p_mb->p_picture->p_v,
+                 p_mb->p_picture->p_u, p_mb->p_picture->p_v,
+                 p_mb->p_picture->p_u, p_mb->p_picture->p_v,
+                 p_mb->p_picture->p_u, p_mb->p_picture->p_v};
+
+            bzero( p_mb->ppi_blocks[i_b], 64*sizeof(elem_t) );
+            (*pppf_decode_block[p_vpar->sequence.b_mpeg2]
+                               [p_vpar->mb.i_mb_type & MB_INTRA])
+                ( p_vpar, p_mb, i_b );
+
+            /* decode_block has already set pf_idct and pi_sparse_pos. */
+            p_mb->pf_addb[i_b] = pf_addb;
+
+            /* Calculate block coordinates. */
+            p_mb->p_data[i_b] = pi_data[i_b] + pi_pos[i_b >> 2]
+                    + pi_y[i_b]*pi_width[i_b >> 2]
+                    + (p_vpar->mb.b_dct_type & ((i_b & 2) >> 1))
+                    /* INACHEVÉ parce que trop pourri ! */
+        }
+        else
+        {
+            /* Block not coded, so no IDCT, nor AddBlock */
+            p_mb->pf_addb[i_b] = vdec_DummyBlock;
+            p_mb->pf_idct[i_b] = vdec_DummyIDCT;
+        }
+    }
+
+    if( !( p_vpar->mb.i_mb_type & MB_INTRA ) )
+    {
+        static int          pi_dc_dct_reinit[4] = {128,256,512,1024};
+
+        /* Reset DC predictors (7.2.1). */
+        p_vpar->slice.pi_dct_pred[0] = p_vpar->slice.pi_dct_pred[1]
+            = p_vpar->slice.pi_dct_pred[2]
+            = pi_dc_dct_reinit[p_vpar->picture.i_intra_dc_precision];
+    }
+    else if( !p_vpar->picture.b_concealment_mv )
+    {
+        /* Reset MV predictors. */
+        bzero( p_vpar->slice.pppi_pmv, 8*sizeof(int) );
+    }
+
+    if( (p_vpar->picture.i_coding_type == P_CODING_TYPE) &&
+        !(p_vpar->mb.i_mb_type & (MB_MOTION_FORWARD|MB_INTRA)) )
+    {
+        /* Special No-MC macroblock in P pictures (7.6.3.5). */
+        p_vpar->slice.pppi_pmv[0][0][0] = p_vpar->slice.pppi_pmv[0][0][1] =
+        p_vpar->slice.pppi_pmv[1][0][0] = p_vpar->slice.pppi_pmv[1][0][1] = 0;
+        
+        /* motion type ?????? */
+        /* predict from field of same parity ????? */
+    }
+}
+
+/*****************************************************************************
+ * InitMacroblock : Initialize macroblock values
+ *****************************************************************************/
+static __inline__ void InitMacroblock( vpar_thread_t * p_vpar,
+                                       macroblock_t * p_mb, int i_mb_address )
+{
+    p_mb->p_picture = p_vpar->picture.p_picture;
+    p_mb->i_structure = p_vpar->picture.i_structure;
+    p_mb->i_mb_x = i_mb_address % p_vpar->sequence.i_mb_width;
+    p_mb->i_mb_y = i_mb_address / p_vpar->sequence.i_mb_width;
+    p_mb->i_chroma_nb_blocks = p_vpar->sequence.i_chroma_nb_blocks;
+
+    p_mb->i_lum_incr = p_vpar->picture.i_lum_incr;
+    p_mb->i_chroma_incr = p_vpar->picture.i_chroma_incr;
+}
+
+/*****************************************************************************
+ * MacroblockAddressIncrement : Get the macroblock_address_increment field
+ *****************************************************************************/
+static __inline__ int MacroblockAddressIncrement( vpar_thread_t * p_vpar )
+{
+    /* Ã€ pomper dans Berkeley */
+}
+
+/*****************************************************************************
+ * MacroblockModes : Get the macroblock_modes structure
+ *****************************************************************************/
+static __inline__ void MacroblockModes( vpar_thread_t * p_vpar,
+                                        macroblock_t * p_mb )
+{
+    static f_motion_t   pf_motion[2][4] =
+        { {NULL, vdec_FieldRecon, vdec_16x8Recon, vdec_DMVRecon},
+          {NULL, vdec_FieldRecon, vdec_FrameRecon, vdec_DMVRecon} };
+    static int          ppi_mv_count[2][4] = { {0, 1, 2, 1}, {0, 2, 1, 1} };
+    static int          ppi_mv_format[2][4] = { {0, 1, 1, 1}, {0, 1, 2, 1} };
+
+    /* Get macroblock_type. */
+    p_vpar->mb.i_mb_type = (*p_vpar->picture.pf_macroblock_type)
+                                  ( vpar_thread_t * p_vpar );
+
+    /* SCALABILITY : warning, we don't know if spatial_temporal_weight_code
+     * has to be dropped, take care if you use scalable streams. */
+    /* DumpBits( &p_vpar->bit_stream, 2 ); */
+    
+    if( !(p_vpar->mb.i_mb_type & (MB_MOTION_FORWARD | MB_MOTION_BACKWARD))
+        || p_vpar->picture.b_frame_pred_frame_dct )
+    {
+        /* If mb_type has neither MOTION_FORWARD nor MOTION_BACKWARD, this
+         * is useless, but also harmless. */
+        p_vpar->mb.i_motion_type = MOTION_FRAME;
+    }
+    else
+    {
+        p_vpar->mb.i_motion_type = GetBits( &p_vpar->bit_stream, 2 );
+    }
+
+    p_mb->f_motion = pf_motion[p_vpar->picture.b_frame_structure]
+                              [p_vpar->mb.i_motion_type];
+    p_vpar->mb.i_mv_count = ppi_mv_count[p_vpar->picture.b_frame_structure]
+                                        [p_vpar->mb.i_motion_type];
+    p_vpar->mb.i_mv_format = ppi_mv_format[p_vpar->picture.b_frame_structure]
+                                          [p_vpar->mb.i_motion_type];
+
+    if( (p_vpar->picture.i_structure == FRAME_STRUCTURE) &&
+        (!p_vpar->picture.b_frame_pred_frame_dct) &&
+        (p_var->mb.i_mb_type & (MB_PATTERN|MB_INTRA)) )
+    {
+        p_vpar->mb.b_dct_type = GetBits( &p_vpar->bit_stream, 1 );
+    }
+    else
+    {
+        p_vpar->mb.b_dct_type = 0;
+    }
+}
+
+/*****************************************************************************
+ * vpar_IMBType : macroblock_type in I pictures
+ *****************************************************************************/
+int vpar_IMBType( vpar_thread_t * p_vpar )
+{
+    /* Ã€ pomper dans Berkeley */
+}
+
+/*****************************************************************************
+ * vpar_PMBType : macroblock_type in P pictures
+ *****************************************************************************/
+int vpar_PMBType( vpar_thread_t * p_vpar )
+{
+    /* Ã€ pomper dans Berkeley */
+}
+
+/*****************************************************************************
+ * vpar_BMBType : macroblock_type in B pictures
+ *****************************************************************************/
+int vpar_BMBType( vpar_thread_t * p_vpar )
+{
+    /* Ã€ pomper dans Berkeley */
+}
+
+/*****************************************************************************
+ * vpar_DMBType : macroblock_type in D pictures
+ *****************************************************************************/
+int vpar_DMBType( vpar_thread_t * p_vpar )
+{
+    /* Ã€ pomper dans Berkeley */
+}
+
+/*****************************************************************************
+ * vpar_CodedPattern420 : coded_block_pattern with 420 chroma
+ *****************************************************************************/
+int vpar_CodedPattern420( vpar_thread_t * p_vpar )
+{
+    /* Ã€ pomper dans Berkeley */
+}
+
+/*****************************************************************************
+ * vpar_CodedPattern422 : coded_block_pattern with 422 chroma
+ *****************************************************************************/
+int vpar_CodedPattern422( vpar_thread_t * p_vpar )
+{
+    /* Ã€ pomper dans Berkeley + attention ! y'a 2 bits en plus en MPEG2 */
+}
+
+/*****************************************************************************
+ * vpar_CodedPattern444 : coded_block_pattern with 444 chroma
+ *****************************************************************************/
+int vpar_CodedPattern444( vpar_thread_t * p_vpar )
+{
+    /* Ã€ pomper dans Berkeley + attention ! y'a 4 bits en plus en MPEG2 */
+}
+
+/*****************************************************************************
+ * vpar_DecodeMPEG1Non : decode MPEG-1 non-intra blocks
+ *****************************************************************************/
+void vpar_DecodeMPEG1Non( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b )
+{
+    /* Ã€ pomper dans Berkeley. Pour toutes ces fonctions, il faut mettre
+       p_mb->pf_idct[i_b] Ã  :
+        - vdec_IDCT ou
+        - vdec_SparseIDCT si la matrice n'a qu'un coefficient non nul.
+       Dans le deuxième cas, p_mb->pi_sparse_pos[i_b] contient le numéro
+       de ce coefficient. */
+
+    if( p_vpar->picture.i_coding_type == D_CODING_TYPE )
+    {
+        /* Remove end_of_macroblock (always 1, prevents startcode emulation)
+         * ISO/IEC 11172-2 section 2.4.2.7 and 2.4.3.6 */
+        DumpBits( &p_vpar->fifo, 1 );
+    }
+}
+
+/*****************************************************************************
+ * vpar_DecodeMPEG1Intra : decode MPEG-1 intra blocks
+ *****************************************************************************/
+void vpar_DecodeMPEG1Intra( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b )
+{
+    /* Ã€ pomper dans Berkeley. */
+
+    if( p_vpar->picture.i_coding_type == D_CODING_TYPE )
+    {
+        /* Remove end_of_macroblock (always 1, prevents startcode emulation)
+         * ISO/IEC 11172-2 section 2.4.2.7 and 2.4.3.6 */
+        DumpBits( &p_vpar->fifo, 1 );
+    }
+}
+
+/*****************************************************************************
+ * vpar_DecodeMPEG2Non : decode MPEG-2 non-intra blocks
+ *****************************************************************************/
+void vpar_DecodeMPEG2Non( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b )
+{
+    /* Ã€ pomper dans Berkeley. Bien sûr les matrices seront différentes... */
+}
+
+/*****************************************************************************
+ * vpar_DecodeMPEG2Intra : decode MPEG-2 intra blocks
+ *****************************************************************************/
+void vpar_DecodeMPEG2Intra( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b )
+{
+    /* Ã€ pomper dans Berkeley. */
+}
index 7c022ad4a5a2d530b10721b22b7b12b7788b1dc3..7af83a8a1671de202cfe5277183c37431abdc238 100644 (file)
@@ -3,8 +3,6 @@
  * (c)1999 VideoLAN
  *****************************************************************************/
 
-/* ?? passer en terminate/destroy avec les signaux supplémentaires */
-
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
 #include "decoder_fifo.h"
 #include "video.h"
 #include "video_output.h"
+#include "vpar_blocks.h"
 #include "video_parser.h"
 
-#include "undec_picture.h"
+#include "macroblock.h"
 #include "video_fifo.h"
 #include "video_decoder.h"
 
 /*
  * Local prototypes
  */
+static __inline__ void NextStartCode( vpar_thread_t * p_vpar );
+static void GroupHeader( vpar_thread_t * p_vpar )
+static void PictureHeader( vpar_thread_t * p_vpar )
+static void __inline__ ReferenceUpdate( vpar_thread_t * p_vpar,
+                                        int i_coding_type,
+                                        picture_t * p_newref )
+static void __inline__ ReferenceReplace( vpar_thread_t * p_vpar,
+                                         int i_coding_type,
+                                         picture_t * p_newref )
+static void SliceHeader00( vpar_thread_t * p_vpar,
+                           int * pi_mb_address, int i_mb_base,
+                           elem_t * p_y, p_u, p_v, u32 i_vert_code )
+static void SliceHeader01( vpar_thread_t * p_vpar,
+                           int * pi_mb_address, int i_mb_base,
+                           elem_t * p_y, p_u, p_v, u32 i_vert_code )
+static void SliceHeader10( vpar_thread_t * p_vpar,
+                           int * pi_mb_address, int i_mb_base,
+                           elem_t * p_y, p_u, p_v, u32 i_vert_code )
+static void SliceHeader11( vpar_thread_t * p_vpar,
+                           int * pi_mb_address, int i_mb_base,
+                           elem_t * p_y, p_u, p_v, u32 i_vert_code )
+static __inline__ void SliceHeader( vpar_thread_t * p_vpar,
+                                    int * pi_mb_address, int i_mb_base,
+                                    elem_t * p_y, p_u, p_v, u32 i_vert_code )
+static void ExtensionAndUserData( vpar_thread_t * p_vpar )
 
 /*****************************************************************************
  * vpar_NextSequenceHeader : Find the next sequence header
@@ -98,7 +122,7 @@ int vpar_ParseHeader( vpar_thread_t * p_vpar )
  *****************************************************************************/
 static __inline__ void NextStartCode( vpar_thread_t * p_vpar )
 {
-    /* Re-align the buffer to an 8-bit boundary */
+    /* Re-align the buffer on an 8-bit boundary */
     DumpBits( &p_vpar->bit_stream, p_vpar->bit_stream.fifo.i_available & 7 );
 
     while( ShowBits( &p_vpar->bit_stream, 24 ) != 0x01L && !p_vpar->b_die )
@@ -110,37 +134,31 @@ static __inline__ void NextStartCode( vpar_thread_t * p_vpar )
 /*****************************************************************************
  * SequenceHeader : Parse the next sequence header
  *****************************************************************************/
-#define RESERVED    -1 
-static double d_frame_rate_table[16] =
-{
-  0.0,
-  ((23.0*1000.0)/1001.0),
-  24.0,
-  25.0,
-  ((30.0*1000.0)/1001.0),
-  30.0,
-  50.0,
-  ((60.0*1000.0)/1001.0),
-  60.0,
-  RESERVED,
-  RESERVED,
-  RESERVED,
-  RESERVED,
-  RESERVED,
-  RESERVED,
-  RESERVED
-};
-
 static void SequenceHeader( vpar_thread_t * p_vpar )
 {
+#define RESERVED    -1 
+    static double d_frame_rate_table[16] =
+    {
+        0.0,
+        ((23.0*1000.0)/1001.0),
+        24.0,
+        25.0,
+        ((30.0*1000.0)/1001.0),
+        30.0,
+        50.0,
+        ((60.0*1000.0)/1001.0),
+        60.0,
+        RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED
+    };
+#undef RESERVED
+
     int i_height_save, i_width_save;
     
     i_height_save = p_vpar->sequence.i_height;
     i_width_save = p_vpar->sequence.i_width;
 
-    p_vpar->sequence.i_height = ntohl( GetBits( p_vpar->bit_stream, 12 ) );
-    p_vpar->sequence.i_width = ntohl( GetBits( p_vpar->bit_stream, 12 ) );
+    p_vpar->sequence.i_height = GetBits( p_vpar->bit_stream, 12 );
+    p_vpar->sequence.i_width = GetBits( p_vpar->bit_stream, 12 );
     p_vpar->sequence.i_ratio = GetBits( p_vpar->bit_stream, 4 );
     p_vpar->sequence.d_frame_rate =
             d_frame_rate_table( GetBits( p_vpar->bit_stream, 4 ) );
@@ -182,9 +200,14 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
     /*
      * Sequence Extension
      */
-    if( ShowBits( p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
+    NextStartCode( p_vpar );
+    if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
     {
         int             i_dummy;
+        static int      pi_chroma_nb_blocks[4] = {0, 1, 2, 4};
+        static (void *) ppf_chroma_pattern[4]( vpar_thread_t * ) =
+                            {NULL, vpar_CodedPattern420,
+                             vpar_CodedPattern422, vpar_CodedPattern444};
     
         /* Parse sequence_extension */
         DumpBits32( &p_vpar->bit_stream );
@@ -192,6 +215,12 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
         DumpBits( &p_vpar->bit_stream, 12 );
         p_vpar->sequence.b_progressive = GetBits( &p_vpar->bit_stream, 1 );
         p_vpar->sequence.i_chroma_format = GetBits( &p_vpar->bit_stream, 2 );
+        p_vpar->sequence.i_chroma_width = p_vpar->sequence.i_width
+                    >> (3-p_vpar->sequence.i_chroma_format);
+        p_vpar->sequence.i_chroma_nb_blocks = pi_chroma_nb_blocks
+                                    [p_vpar->sequence.i_chroma_format];
+        p_vpar->sequence.pf_decode_pattern = ppf_chroma_pattern
+                                    [p_vpar->sequence.i_chroma_format];
         p_vpar->sequence.i_width |= GetBits( &p_vpar->bit_stream, 2 ) << 12;
         p_vpar->sequence.i_height |= GetBits( &p_vpar->bit_stream, 2 ) << 12;
         /* bit_rate_extension, marker_bit, vbv_buffer_size_extension, low_delay */
@@ -202,180 +231,64 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
         p_vpar->sequence.d_frame_rate *= (i_dummy + 1)
                                   / (GetBits( &p_vpar->bit_stream, 5 ) + 1);
 
-        /* Extension and User data */
-        ExtensionAndUserData( p_vpar );
+        p_vpar->sequence.pf_decode_mv = vpar_MPEG2MotionVector;
     }
     else
     {
         /* It's an MPEG-1 stream. Put adequate parameters. */
         p_vpar->sequence.b_progressive = 1;
-        p_vpar->i_chroma_format = CHROMA_420;
+        p_vpar->sequence.i_chroma_format = CHROMA_420;
+        p_vpar->sequence.i_chroma_width = p_vpar->sequence.i->width >> 2;
+        p_vpar->sequence.i_chroma_nb_blocks = 2;
+        p_vpar->sequence.pf_decode_pattern = vpar_CodedPattern420;
+
+        p_vpar->sequence.pf_decode_mv = vpar_MPEG1MotionVector;
     }
 
     p_vpar->sequence.i_mb_width = (p_vpar->sequence.i_width + 15) / 16;
     p_vpar->sequence.i_mb_height = (p_vpar->sequence.b_progressive) ?
                                    (p_vpar->sequence.i_height + 15) / 16 :
                                    2 * (p_vpar->sequence.i_height + 31) / 32;
+    p_vpar->sequence.i_mb_size = p_vpar->sequence.i_mb_width
+                                        * p_vpar->sequence.i_mb_height;
     p_vpar->sequence.i_width = (p_vpar->sequence.i_mb_width * 16);
     p_vpar->sequence.i_height = (p_vpar->sequence.i_mb_height * 16);
+    p_vpar->sequence.i_size = p_vpar->sequence.i_width
+                                        * p_vpar->sequence.i_height;
 
-    if(    p_vpar->sequence.i_width != i_width_save
-        || p_vpar->sequence.i_height != i_height_save
-        || p_vpar->sequence.p_frame_lum_lookup == NULL )
+    /* Slice Header functions */
+    if( p_vpar->sequence.i_height <= 2800 )
     {
-        int                 i_x, i_y;
-        pel_lookup_table *  p_fr, p_fl;
-        int                 i_fr, i_fl;
-        static int          pi_chroma_size[4] = {0, 2, 1, 0}
-#define Sequence p_vpar->sequence
-
-        /* The size of the pictures has changed. Probably a new sequence.
-         * We must recalculate the lookup matrices. */
-
-        /* First unlink the previous lookup matrices so that they can
-         * be freed in the future. */
-        if( Sequence.p_frame_lum_lookup != NULL )
+        if( p_vpar->sequence.i_scalable_mode != SC_DP )
         {
-            UNLINK_LOOKUP( Sequence.p_frame_lum_lookup );
-            UNLINK_LOOKUP( Sequence.p_field_lum_lookup );
-            UNLINK_LOOKUP( Sequence.p_frame_chroma_lookup );
-            UNLINK_LOOKUP( Sequence.p_field_chroma_lookup );
+            p_vpar->sequence.pf_slice_header = SliceHeader00;
         }
-
-        /* Allocate the new lookup tables. */
-        Sequence.p_frame_lum_lookup
-            = (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) *
-                        Sequence.i_width * Sequence.i_height );
-        Sequence.p_field_lum_lookup
-            = (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) *
-                        Sequence.i_width * Sequence.i_height );
-        Sequence.p_frame_chroma_lookup
-            = (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) *
-                        Sequence.i_width * Sequence.i_height
-                         >> pi_chroma_size[Sequence.i_chroma_format] );
-        Sequence.p_field_chroma_lookup
-            = (pel_lookup_table_t *)malloc( sizeof( pel_lookup_table_t ) *
-                        Sequence.i_width * Sequence.i_height
-                         >> pi_chroma_size[Sequence.i_chroma_format] );
-
-        if( !Sequence.p_frame_lum_lookup || !Sequence.p_field_lum_lookup
-            || !Sequence.p_frame_chroma_lookup
-            || !Sequence.p_field_chroma_lookup )
+        else
         {
-            intf_DbgMsg("vpar error: not enough memory for lookup tables");
-            p_vpar->b_error = 1;
-            return;
+            p_vpar->sequence.pf_slice_header = SliceHeader01;
         }
-
-        /* Fill in the luminance lookup tables */
-        p_fr = &Sequence.p_frame_lum_lookup->pi_pel;
-        p_fl = &Sequence.p_field_lum_lookup->pi_pel;
-        i_fr = i_fl = 0;
-
-        for( i_y = 0; i_y < Sequence.i_height; i_y++ )
+    }
+    else
+    {
+        if( p_vpar->sequence.i_scalable_mode != SC_DP )
         {
-            int i_mb_y, i_b_y, i_pos_y;
-            i_mb_y = i_y >> 4;
-            i_b_y = (i_y & 15) >> 3;
-            i_pos_y = (i_y & 7);
-
-            for( i_x = 0; i_x < Sequence.i_width; i_x++ )
-            {
-                int i_mb_x, i_b_x, i_pos_x;
-                i_mb_x = i_x >> 4;
-                i_b_x = (i_x & 15) >> 3;
-                i_pos_x = (i_x & 7);
-
-                p_fl[i_fr + i_x] = p_fr[i_fr + i_x]
-                                 = (i_mb_y*Sequence.i_mb_width + i_mb_y)*256
-                                        + ((i_b_y << 1) + i_b_x)*64
-                                        + i_pos_y*8 + i_pos_x;
-            }
-            i_fr += Sequence.i_width;
-            i_fl += Sequence.i_width << 1;
-            if( i_fl == Sequence.i_width*Sequence.i_height )
-            {
-                i_fl = Sequence.i_width;
-            }
+            p_vpar->sequence.pf_slice_header = SliceHeader10;
         }
-        
-        /* Fill in the chrominance lookup tables */
-        p_fr = &Sequence.p_frame_chroma_lookup->pi_pel;
-        p_fl = &Sequence.p_field_chroma_lookup->pi_pel;
-        i_fr = i_fl = 0;
-
-        switch( p_vpar->i_chroma_format )
+        else
         {
-        case CHROMA_444:
-            /* That's the same as luminance */
-            memcopy( &Sequence.p_frame_croma_lookup->pi_pel,
-                     &Sequence.p_frame_lum_lookup->pi_pel,
-                     sizeof(PEL_P)*Sequence.i_height*Sequence.i_width );
-            memcopy( &Sequence.p_field_croma_lookup->pi_pel,
-                     &Sequence.p_field_lum_lookup->pi_pel,
-                     sizeof(PEL_P)*Sequence.i_height*Sequence.i_width );
-
-        case CHROMA_422:
-            for( i_y = 0; i_y < Sequence.i_height; i_y++ )
-            {
-                int i_mb_y, i_b_y, i_pos_y;
-                i_mb_y = i_y >> 4;
-                i_b_y = (i_y & 15) >> 3;
-                i_pos_y = (i_y & 7);
-    
-                for( i_x = 0; i_x < (Sequence.i_width >> 1); i_x++ )
-                {
-                    int i_mb_x, i_pos_x;
-                    i_mb_x = i_x >> 3;
-                    i_pos_x = (i_x & 7);
-    
-                    p_fl[i_fr + i_x] = p_fr[i_fr + i_x]
-                                     = (i_mb_y*Sequence.i_mb_width + i_mb_y)*128
-                                            + i_b_y*64
-                                            + i_pos_y*8 + i_pos_x;
-                }
-                i_fr += Sequence.i_width >> 1;
-                i_fl += Sequence.i_width;
-                if( i_fl == (Sequence.i_width*Sequence.i_height >> 1) )
-                {
-                    i_fl = (Sequence.i_width >> 1);
-                }
-            }
+            p_vpar->sequence.pf_slice_header = SliceHeader11;
+        }
+    }
+
+    if(    p_vpar->sequence.i_width != i_width_save
+        || p_vpar->sequence.i_height != i_height_save
+        || p_vpar->sequence.p_frame_lum_lookup == NULL )
+    {
 
-        case CHROMA_420:
-            for( i_y = 0; i_y < (Sequence.i_height >> 1); i_y++ )
-            {
-                int i_mb_y, i_pos_y;
-                i_mb_y = i_y >> 3;
-                i_pos_y = (i_y & 7);
-    
-                for( i_x = 0; i_x < (Sequence.i_width >> 1); i_x++ )
-                {
-                    int i_mb_x, i_pos_x;
-                    i_mb_x = i_x >> 3;
-                    i_pos_x = (i_x & 7);
-    
-                    p_fl[i_fr + i_x] = p_fr[i_fr + i_x]
-                                     = (i_mb_y*Sequence.i_mb_width + i_mb_y)*64
-                                            + i_pos_y*8 + i_pos_x;
-                }
-                i_fr += Sequence.i_width >> 1;
-                i_fl += Sequence.i_width;
-                if( i_fl == (Sequence.i_width*Sequence.i_height >> 2) )
-                {
-                    i_fl = Sequence.i_width >> 1;
-                }
-            }
-        } /* switch */
-        
-        /* Link the new lookup tables so that they don't get freed all
-         * the time. */
-        LINK_LOOKUP( Sequence.p_frame_lum_lookup );
-        LINK_LOOKUP( Sequence.p_field_lum_lookup );
-        LINK_LOOKUP( Sequence.p_frame_chroma_lookup );
-        LINK_LOOKUP( Sequence.p_field_chroma_lookup );
-#undef Sequence
     }
+
+    /* Extension and User data */
+    ExtensionAndUserData( p_vpar );
 }
 
 /*****************************************************************************
@@ -393,57 +306,233 @@ static void GroupHeader( vpar_thread_t * p_vpar )
  *****************************************************************************/
 static void PictureHeader( vpar_thread_t * p_vpar )
 {
-    int                 i_coding_type;
-    mtime_t             i_pts;
-    undec_picture_t *   p_undec_p;
+    static (int *)      ppf_macroblock_type[4] = {vpar_IMBType, vpar_PMBType,
+                                                  vpar_BMBType, vpar_DMBType};
+
+    int                 i_structure;
+    int                 i_mb_address, i_mb_base, i_mb;
+    elem_t *            p_y, p_u, p_v;
+    boolean_t           b_parsable;
+    u32                 i_dummy;
     
     DumpBits( &p_vpar->bit_stream, 10 ); /* temporal_reference */
-    i_coding_type = GetBits( &p_vpar->bit_stream, 3 );
+    p_vpar->picture.i_coding_type = GetBits( &p_vpar->bit_stream, 3 );
+    p_vpar->picture.pf_macroblock_type = ppf_macroblock_type
+                                         [p_vpar->picture.i_coding_type];
+    
+    DumpBits( &p_vpar->bit_stream, 16 ); /* vbv_delay */
     
-    if( ((i_coding_type == P_CODING_TYPE) &&
-         (p_vpar->sequence.p_forward == NULL)) ||
-        ((i_coding_type == B_CODING_TYPE) &&
-         (p_vpar->sequence.p_forward == NULL ||
-          p_vpar->sequence.p_backward == NULL)) )
-    {
-        /* The picture cannot be decoded because we lack one of the
-         * reference frames */
+    p_vpar->picture.b_full_pel_forward_vector = GetBits( &p_vpar->bit_stream, 1 );
+    p_vpar->picture.i_forward_f_code = GetBits( &p_vpar->bit_stream, 3 );
+    p_vpar->picture.b_full_pel_backward_vector = GetBits( &p_vpar->bit_stream, 1 );
+    p_vpar->picture.i_backward_f_code = GetBits( &p_vpar->bit_stream, 3 );
+
+    /* extra_information_picture */
+    while( GetBits( &p_vpar->bit_stream, 1 ) )
+    {
+        DumpBits( &p_vpar->bit_stream, 8 );
+    }
+
+    /* 
+     * Picture Coding Extension
+     */
+    NextStartCode( p_vpar );
+    if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
+    {
+        /* Parse picture_coding_extension */
+        DumpBits32( &p_vpar->bit_stream );
+        /* extension_start_code_identifier */
+        DumpBits( &p_vpar->bit_stream, 4 );
         
-        /* Update the reference pointers */
-        ReferenceUpdate( p_vpar, i_coding_type, NULL );
+        p_vpar->picture.ppi_f_code[0][0] = GetBits( &p_vpar->bit_stream, 4 );
+        p_vpar->picture.ppi_f_code[0][1] = GetBits( &p_vpar->bit_stream, 4 );
+        p_vpar->picture.ppi_f_code[1][0] = GetBits( &p_vpar->bit_stream, 4 );
+        p_vpar->picture.ppi_f_code[1][1] = GetBits( &p_vpar->bit_stream, 4 );
+        p_vpar->picture.i_intra_dc_precision = GetBits( &p_vpar->bit_stream, 2 );
+        i_structure = GetBits( &p_vpar->bit_stream, 2 );
+        p_vpar->picture.b_top_field_first = GetBits( &p_vpar->bit_stream, 1 );
+        p_vpar->picture.b_frame_pred_frame_dct
+             = GetBits( &p_vpar->bit_stream, 1 );
+        p_vpar->picture.b_concealment_mv = GetBits( &p_vpar->bit_stream, 1 );
+        p_vpar->picture.b_q_scale_type = GetBits( &p_vpar->bit_stream, 1 );
+        p_vpar->picture.b_intra_vlc_format = GetBits( &p_vpar->bit_stream, 1 );
+        p_vpar->picture.b_alternate_scan = GetBits( &p_vpar->bit_stream, 1 );
+        /* repeat_first_field (ISO/IEC 13818-2 6.3.10 is cryptic and
+         * apparently the reference decoder doesn't use it, so trash it),
+         * chroma_420_type (obsolete) */
+        DumpBits( &p_vpar->bit_stream, 2 );
+        p_vpar->picture.b_progressive_frame = GetBits( &p_vpar->bit_stream, 1 );
         
-        /* Warn Synchro we have trashed a picture */
-        vpar_SynchroTrash( p_vpar, i_coding_type );
-
-        return;
+        /* composite_display_flag */
+        if( GetBits( &p_vpar->bit_stream, 1 ) )
+        {
+            /* v_axis, field_sequence, sub_carrier, burst_amplitude,
+             * sub_carrier_phase */
+            DumpBits( &p_vpar->bit_stream, 20 );
+        }
+    }
+    else
+    {
+        /* MPEG-1 compatibility flags */
+        p_vpar->i_intra_dc_precision = 0; /* 8 bits */
+        i_structure = FRAME_STRUCTURE;
+        p_vpar->b_frame_pred_frame_dct = TRUE;
+        p_vpar->picture.b_concealment_mv = 0;
+        p_vpar->picture.b_q_scale_type = 0;
+        p_vpar->picture.b_intra_vlc_format = 0;
+        p_vpar->picture.b_alternate_scan = 0; /* zigzag */
+        b_repeat_first_field = FALSE;
+        p_vpar->picture.b_progressive_frame = TRUE;
     }
 
-    if( !(i_pts = vpar_SynchroChoose( p_vpar, i_coding_type )) )
+    if( p_vpar->picture.i_current_structure &&
+        (i_structure == FRAME_STRUCTURE ||
+         i_structure == p_vpar->picture.i_current_structure) )
     {
-        /* Synchro has decided not to decode the picture */
+        /* We don't have the second field of the buffered frame. */
+        if( p_pvar->picture.p_picture != NULL )
+        {
+            ReferenceReplace( p_vpar,
+                      p_vpar->picture.p_second_field_buffer->i_coding_type,
+                      NULL );
+
+            for( i_mb = 0; i_mb < p_vpar->sequence.i_mb_size >> 1; 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 );
+        }
         
-        /* Update the reference pointers */
+        p_pvar->picture.i_current_structure = 0;
+
+        intf_DbgMsg("vpar debug: odd number of field picture.");
+    }
+
+    if( p_vpar->picture.i_current_structure )
+    {
+        /* Second field of a frame. We will decode it if, and only if we
+         * have decoded the first frame. */
+        b_parsable = (p_vpar->picture.p_second_field_buffer != NULL);
+    }
+    else
+    {
+        /* Do we have the reference pictures ? */
+        b_parsable = !((i_coding_type == P_CODING_TYPE) &&
+                       (p_vpar->sequence.p_forward == NULL)) ||
+                      ((i_coding_type == B_CODING_TYPE) &&
+                       (p_vpar->sequence.p_forward == NULL ||
+                        p_vpar->sequence.p_backward == NULL));
+
+        /* Does synchro say we have enough time to decode it ? */
+        b_parsable &&= vpar_SynchroChoose( p_vpar, i_coding_type, i_structure );
+    }
+
+    if( !b_parsable )
+    {
+        /* Update the reference pointers. */
         ReferenceUpdate( p_vpar, i_coding_type, NULL );
         
+        /* Warn Synchro we have trashed a picture. */
+        vpar_SynchroTrash( p_vpar, i_coding_type, i_structure );
+
+        /* Update context. */
+        if( i_structure != FRAME_STRUCTURE )
+            p_vpar->picture.i_current_structure = i_structure;
+        p_vpar->picture.p_picture = NULL;
+
         return;
     }
 
-    /* OK, now we are sure we will decode the picture. Get a structure. */
-    p_undec_p = vpar_NewPicture( &p_vpar->vfifo );
-    
-    /* Request a buffer from the video_output. */
-    p_undec_p->p_picture = vout_CreatePicture( p_vpar->p_vout,
-                                               SPLITTED_YUV_PICTURE,
-                                               p_vpar->sequence.i_width,
-                                               p_vpar->sequence.i_height,
-                                               p_vpar->sequence.i_chroma_format );
-
-    /* Initialize values */
-    p_undec_p->i_coding_type = i_conding_type;
-    p_undec_p->b_mpeg2 = p_vpar->sequence.b_mpeg2;
-    p_undec_p->i_mb_height = p_vpar->sequence.i_mb_height;
-    p_undec_p->i_mb_width = p_vpar->sequence.i_mb_width;
-    p_undec_p->i_pts = i_pts;
+    /* OK, now we are sure we will decode the picture. */
+#define P_picture p_vpar->picture.p_picture
+    p_vpar->picture.b_error = FALSE;
+
+    if( !p_vpar->picture.i_current_structure )
+    {
+        /* This is a new frame. Get a structure from the video_output. */
+        P_picture = vout_CreatePicture( p_vpar->p_vout,
+                                        SPLITTED_YUV_PICTURE,
+                                        p_vpar->sequence.i_width,
+                                        p_vpar->sequence.i_height,
+                                        p_vpar->sequence.i_chroma_format );
+
+        /* Initialize values. */
+        P_picture->date = vpar_SynchroDecode( p_vpar, i_coding_type,
+                                              i_structure );
+        bzero( p_vpar->picture.pp_mb, MAX_MB*sizeof( macroblock_t * ) );
+        p_vpar->picture.i_lum_incr = - 8 + ( p_vpar->sequence.i_width
+                    << ( i_structure != FRAME_STRUCTURE ) );
+        p_vpar->picture.i_chroma_incr = -8 + ( p_vpar->sequence.i_width
+                    << (( i_structure != FRAME_STRUCTURE ) +
+                        ( 3 - p_vpar->sequence.i_chroma_format )) );
+
+        /* Update the reference pointers. */
+        ReferenceUpdate( p_vpar, i_coding_type, p_undec_p );
+    }
+    p_vpar->picture.i_current_structure |= i_structure;
+    p_vpar->picture.i_structure = i_structure;
+    p_vpar->picture.b_frame_structure = (i_structure == FRAME_STRUCTURE);
+
+    /* Initialize picture data for decoding. */
+    if( i_structure == BOTTOM_FIELD )
+    {
+        i_mb_base = p_vpar->sequence.i_mb_size >> 1;
+    }
+    else
+    {
+        i_mb_base = 0;
+    }
+    i_mb_address = 0;
+
+    /* Extension and User data. */
+    ExtensionAndUserData( p_vpar );
+
+    /* Picture data (ISO/IEC 13818-2 6.2.3.7). */
+    NextStartCode( p_vpar );
+    while( i_mb_address+i_mb_base < p_vpar->sequence.i_mb_size
+           && !p_vpar->picture.b_error)
+    {
+        if( ((i_dummy = ShowBits( &p_vpar->bit_stream, 32 ))
+                 < SLICE_START_CODE_MIN) ||
+            (i_dummy > SLICE_START_CODE_MAX) )
+        {
+            intf_DbgMsg("vpar debug: premature end of picture");
+            p_vpar->picture.b_error = TRUE;
+            break;
+        }
+        DumpBits32( &p_vpar->bit_stream );
+        
+        /* Decode slice data. */
+        SliceHeader( p_vpar, &i_mb_address, i_mb_base, i_dummy & 255 );
+    }
+
+    if( p_vpar->picture.b_error )
+    {
+        /* Trash picture. */
+        for( i_mb = 0; p_vpar->picture.pp_mb[i_mb]; i_mb++ )
+        {
+            vpar_DestroyMacroblock( &p_vpar->vfifo, p_vpar->picture.pp_mb[i_mb] );
+        }
+
+        ReferenceReplace( p_vpar, p_vpar->picture.i_coding_type, NULL );
+        vout_DestroyPicture( p_vpar->p_vout, P_picture );
+
+        /* Prepare context for the next picture. */
+        P_picture = NULL:
+    }
+    else if( p_vpar->picture.i_current_structure == FRAME_STRUCTURE )
+    {
+        /* Frame completely parsed. */
+        for( i_mb = 0; i_mb < p_vpar->sequence.i_mb_size; i_mb++ )
+        {
+            vpar_DecodeMacroblock( &p_vpar->vfifo, p_vpar->picture.pp_mb[i_mb] );
+        }
+
+        /* Prepare context for the next picture. */
+        P_picture = NULL;
+    }
+#undef P_picture
 }
 
 /*****************************************************************************
@@ -455,11 +544,115 @@ static void __inline__ ReferenceUpdate( vpar_thread_t * p_vpar,
 {
     if( i_coding_type != B_CODING_TYPE )
     {
-        /* The P picture would have become the new p_backward reference. */
-        vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
+        if( p_vpar->sequence.p_forward != NULL )
+            vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
         p_vpar->sequence.p_forward = p_vpar->sequence.p_backward;
         p_vpar->sequence.p_backward = p_newref;
+        if( p_newref != NULL )
+            vout_LinkPicture( p_vpar->p_vout, p_newref );
+    }
+}
+
+/*****************************************************************************
+ * ReferenceReplace : Replace the last reference pointer when we destroy
+ * a picture
+ *****************************************************************************/
+static void __inline__ ReferenceReplace( vpar_thread_t * p_vpar,
+                                         int i_coding_type,
+                                         picture_t * p_newref )
+{
+    if( i_coding_type != B_CODING_TYPE )
+    {
+        if( p_vpar->sequence.p_backward != NULL )
+            vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
+        p_vpar->sequence.p_backward = p_newref;
+        if( p_newref != NULL )
+            vout_LinkPicture( p_vpar->p_vout, p_newref );
+    }
+}
+
+/*****************************************************************************
+ * SliceHeaderXY : Parse the next slice structure
+ *****************************************************************************
+ * X = i_height > 2800 ?
+ * Y = scalable_mode == SC_DP ?
+ *****************************************************************************/
+static void SliceHeader00( vpar_thread_t * p_vpar,
+                           int * pi_mb_address, int i_mb_base,
+                           u32 i_vert_code )
+{
+    SliceHeader( p_vpar, pi_mb_address, i_mb_base, i_vert_code );
+}
+
+static void SliceHeader01( vpar_thread_t * p_vpar,
+                           int * pi_mb_address, int i_mb_base,
+                           u32 i_vert_code )
+{
+    DumpBits( &p_vpar->bit_stream, 7 ); /* priority_breakpoint */
+    SliceHeader( p_vpar, pi_mb_address, i_mb_base, i_vert_code );
+}
+
+static void SliceHeader10( vpar_thread_t * p_vpar,
+                           int * pi_mb_address, int i_mb_base,
+                           u32 i_vert_code )
+{
+    i_vert_code += GetBits( &p_vpar->bit_stream, 3 ) << 7;
+    SliceHeader( p_vpar, pi_mb_address, i_mb_base, i_vert_code );
+}
+
+static void SliceHeader11( vpar_thread_t * p_vpar,
+                           int * pi_mb_address, int i_mb_base,
+                           u32 i_vert_code )
+{
+    i_vert_code += GetBits( &p_vpar->bit_stream, 3 ) << 7;
+    DumpBits( &p_vpar->bit_stream, 7 ); /* priority_breakpoint */
+    SliceHeader( p_vpar, pi_mb_address, i_mb_base, i_vert_code );
+}
+
+/*****************************************************************************
+ * SliceHeader : Parse the next slice structure
+ *****************************************************************************/
+static __inline__ void SliceHeader( vpar_thread_t * p_vpar,
+                                    int * pi_mb_address, int i_mb_base,
+                                    u32 i_vert_code )
+{
+    /* DC predictors initialization table */
+    static int              pi_dc_dct_reinit[4] = {128,256,512,1024};
+
+    int                     i_mb_address_save = *pi_mb_address;
+
+    /* slice_vertical_position_extension and priority_breakpoint already done */
+    LoadQuantizerScale( p_vpar );
+
+    if( GetBits( &p_vpar->bit_stream, 1 ) )
+    {
+        /* intra_slice, slice_id */
+        DumpBits( &p_vpar->bit_stream, 8 );
+        /* extra_information_slice */
+        while( GetBits( &p_vpar->bit_stream, 1 ) )
+        {
+            DumpBits( &p_vpar->bit_stream, 8 );
+        }
+    }
+
+    *pi_mb_address = (i_vert_code - 1)*p_vpar->sequence.i_mb_width;
+
+    /* Reset DC coefficients predictors (ISO/IEC 13818-2 7.2.1). Why
+     * does the reference decoder put 0 instead of the normative values ? */
+    p_vpar->slice.pi_dct_pred[0] = p_vpar->slice.pi_dct_pred[1]
+        = p_vpar->slice.pi_dct_pred[2]
+        = pi_dc_dct_reinit[p_vpar->picture.i_intra_dc_precision];
+
+    /* Reset motion vector predictors (ISO/IEC 13818-2 7.6.3.4). */
+    bzero( p_vpar->slice.pppi_pmv, 8*sizeof(int) );
+
+    do
+    {
+        vpar_ParseMacroblock( p_vpar, pi_mb_address, i_mb_address_save,
+                              i_mb_base );
+        i_mb_address_save = *pi_mb_address;
     }
+    while( !ShowBits( &p_vpar->bit_stream, 23 ) );
 }
 
 /*****************************************************************************
@@ -563,4 +756,3 @@ static void LinkMatrix( quant_matrix_t * p_matrix, int * pi_array )
     
     p_matrix->pi_matrix = pi_array;
 }
-
diff --git a/src/video_parser/vpar_motion.c b/src/video_parser/vpar_motion.c
new file mode 100644 (file)
index 0000000..7f9443d
--- /dev/null
@@ -0,0 +1,54 @@
+/*****************************************************************************
+ * vpar_motion.c : motion vectors parsing
+ * (c)1999 VideoLAN
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XShm.h>
+
+#include "config.h"
+#include "common.h"
+#include "mtime.h"
+#include "vlc_thread.h"
+
+#include "intf_msg.h"
+#include "debug.h"                    /* ?? temporaire, requis par netlist.h */
+
+#include "input.h"
+#include "input_netlist.h"
+#include "decoder_fifo.h"
+#include "video.h"
+#include "video_output.h"
+#include "video_parser.h"
+
+#include "video_fifo.h"
+#include "video_decoder.h"
+
+/*
+ * Local prototypes
+ */
+
+/*****************************************************************************
+ * vpar_MPEG1MotionVector : Parse the next MPEG-1 motion vector
+ *****************************************************************************/
+void vpar_MPEG1MotionVector( vpar_thread_t * p_vpar, int i_mv )
+{
+
+}
+
+/*****************************************************************************
+ * vpar_MPEG2MotionVector : Parse the next MPEG-2 motion vector
+ *****************************************************************************/
+void vpar_MPEG2MotionVector( vpar_thread_t * p_vpar, int i_mv )
+{
+
+}