]> git.sesse.net Git - vlc/blobdiff - src/video_decoder/video_decoder.c
* Totally rewrote the video decoder (inspired by walken's mpeg2dec), implying :
[vlc] / src / video_decoder / video_decoder.c
index 2323aaaf724c36e5661a90397a8e9cd77244f6b3..94a60c58392c8048e36698421ea1bcb480e88a54 100644 (file)
@@ -2,10 +2,10 @@
  * video_decoder.c : video decoder thread
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_decoder.c,v 1.56 2001/07/31 21:13:30 gbazin Exp $
+ * $Id: video_decoder.c,v 1.57 2001/08/22 17:21:45 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *          GaĆ«l Hendryckx <jimmy@via.ecp.fr>
+ *          Michel Lespinasse <walken@zoy.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -51,6 +51,7 @@
 #include "vdec_ext-plugins.h"
 #include "video_decoder.h"
 #include "vpar_pool.h"
+#include "video_parser.h"
 
 /*
  * Local prototypes
@@ -126,7 +127,7 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec )
  * This function is called from RunThread and performs the second step of the
  * initialization.
  *****************************************************************************/
-void vdec_InitThread( vdec_thread_t *p_vdec )
+void vdec_InitThread( vdec_thread_t * p_vdec )
 {
     intf_DbgMsg("vdec debug: initializing video decoder thread %p", p_vdec);
 
@@ -134,12 +135,12 @@ void vdec_InitThread( vdec_thread_t *p_vdec )
 #   if VDEC_NICE
     /* Re-nice ourself - otherwise we would steal CPU time from the video
      * output, which would make a poor display. */
-#if !defined(WIN32)
+#       if !defined(WIN32)
     if( nice(VDEC_NICE) == -1 )
-#else
+#       else
     if( !SetThreadPriority( GetCurrentThread(),
                             THREAD_PRIORITY_BELOW_NORMAL ) )
-#endif
+#       endif
     {
         intf_WarnMsg( 2, "vpar warning : couldn't nice() (%s)",
                       strerror(errno) );
@@ -150,7 +151,7 @@ void vdec_InitThread( vdec_thread_t *p_vdec )
     p_vdec->p_idct_data = NULL;
 
     p_vdec->p_pool->pf_decode_init( p_vdec );
-    p_vdec->p_pool->pf_idct_init( p_vdec );
+    p_vdec->p_pool->pf_idct_init( &p_vdec->p_idct_data );
 
     /* Mark thread as running and return */
     intf_DbgMsg("vdec debug: InitThread(%p) succeeded", p_vdec);
@@ -162,7 +163,7 @@ void vdec_InitThread( vdec_thread_t *p_vdec )
  * This function is called when the thread ends after a sucessful
  * initialization.
  *****************************************************************************/
-void vdec_EndThread( vdec_thread_t *p_vdec )
+void vdec_EndThread( vdec_thread_t * p_vdec )
 {
     intf_DbgMsg("vdec debug: EndThread(%p)", p_vdec);
 
@@ -174,6 +175,125 @@ void vdec_EndThread( vdec_thread_t *p_vdec )
     free( p_vdec );
 }
 
+/*****************************************************************************
+ * MotionBlock: does one component of the motion compensation
+ *****************************************************************************/
+static __inline__ void MotionBlock( vdec_pool_t * p_pool,
+                                    boolean_t b_average,
+                                    int i_x_pred, int i_y_pred,
+                                    yuv_data_t * pp_dest[3], int i_dest_offset,
+                                    yuv_data_t * pp_src[3], int i_src_offset,
+                                    int i_stride, int i_height,
+                                    boolean_t b_second_half, boolean_t b_color )
+{
+    int             i_xy_half;
+    yuv_data_t *    p_src1;
+    yuv_data_t *    p_src2;
+
+    i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
+
+    p_src1 = pp_src[0] + i_src_offset
+                + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride
+                + b_second_half * (i_stride << 3);
+
+    p_pool->ppppf_motion[b_average][0][i_xy_half]
+            ( pp_dest[0] + i_dest_offset + b_second_half * (i_stride << 3),
+              p_src1, i_stride, i_height );
+
+    if( b_color )
+    {
+        /* Expanded at compile-time. */
+        i_x_pred /= 2;
+        i_y_pred /= 2;
+
+        i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
+        i_stride >>= 1;
+        i_height >>= 1;
+        i_src_offset >>= 1;
+        i_src_offset += b_second_half * (i_stride << 2);
+        i_dest_offset >>= 1;
+        i_dest_offset += b_second_half * (i_stride << 2);
+
+        p_src1 = pp_src[1] + i_src_offset
+                    + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
+        p_src2 = pp_src[2] + i_src_offset
+                    + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
+
+        p_pool->ppppf_motion[b_average][1][i_xy_half]
+                ( pp_dest[1] + i_dest_offset, p_src1, i_stride, i_height );
+        p_pool->ppppf_motion[b_average][1][i_xy_half]
+                ( pp_dest[2] + i_dest_offset, p_src2, i_stride, i_height );
+    }
+}
+
+
+/*****************************************************************************
+ * DecodeMacroblock: decode a macroblock
+ *****************************************************************************/
+#define DECLARE_DECODEMB( PSZ_NAME, B_COLOR )                               \
+void PSZ_NAME ( vdec_thread_t *p_vdec, macroblock_t * p_mb )                \
+{                                                                           \
+    int             i;                                                      \
+    idct_inner_t *  p_idct;                                                 \
+    vdec_pool_t *   p_pool = p_vdec->p_pool;                                \
+                                                                            \
+    if( !(p_mb->i_mb_modes & MB_INTRA) )                                    \
+    {                                                                       \
+        /*                                                                  \
+         * Motion Compensation (ISO/IEC 13818-2 section 7.6)                \
+         */                                                                 \
+        for( i = 0; i < p_mb->i_nb_motions; i++ )                           \
+        {                                                                   \
+            motion_inner_t *    p_motion = &p_mb->p_motions[i];             \
+            MotionBlock( p_pool, p_motion->b_average,                       \
+                         p_motion->i_x_pred, p_motion->i_y_pred,            \
+                         p_mb->pp_dest, p_motion->i_dest_offset,            \
+                         p_motion->pp_source, p_motion->i_src_offset,       \
+                         p_motion->i_stride, p_motion->i_height,            \
+                         p_motion->b_second_half, B_COLOR );                \
+        }                                                                   \
+                                                                            \
+        for( i = 0, p_idct = p_mb->p_idcts; i < 4 + 2 * B_COLOR;            \
+             i++, p_idct++ )                                                \
+        {                                                                   \
+            if( p_mb->i_coded_block_pattern & (1 << (5 - i)) )              \
+            {                                                               \
+                /*                                                          \
+                 * Inverse DCT (ISO/IEC 13818-2 section Annex A)            \
+                 */                                                         \
+                p_idct->pf_idct( p_vdec->p_idct_data, p_idct->pi_block,     \
+                                 p_idct->i_sparse_pos );                    \
+                                                                            \
+                /*                                                          \
+                 * Adding prediction and coefficient data (ISO/IEC          \
+                 * 13818-2 section 7.6.8)                                   \
+                 */                                                         \
+                p_pool->pf_addblock( p_idct->pi_block, p_idct->p_dct_data,  \
+                                     i < 4 ? p_mb->i_lum_dct_stride :       \
+                                             p_mb->i_chrom_dct_stride );    \
+            }                                                               \
+        }                                                                   \
+    }                                                                       \
+    else                                                                    \
+    {                                                                       \
+        /* Intra macroblock */                                              \
+        for( i = 0, p_idct = p_mb->p_idcts; i < 4 + 2 * B_COLOR;            \
+             i++, p_idct++ )                                                \
+        {                                                                   \
+            p_idct->pf_idct( p_vdec->p_idct_data, p_idct->pi_block,         \
+                             p_idct->i_sparse_pos );                        \
+            p_pool->pf_copyblock( p_idct->pi_block, p_idct->p_dct_data,     \
+                                  i < 4 ? p_mb->i_lum_dct_stride :          \
+                                          p_mb->i_chrom_dct_stride );       \
+        }                                                                   \
+    }                                                                       \
+}
+
+DECLARE_DECODEMB( vdec_DecodeMacroblockC, 1 );
+DECLARE_DECODEMB( vdec_DecodeMacroblockBW, 0 );
+
+#undef DECLARE_DECODEMB
+
 /*****************************************************************************
  * RunThread: video decoder thread
  *****************************************************************************