* 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
#include "vdec_ext-plugins.h"
#include "video_decoder.h"
#include "vpar_pool.h"
+#include "video_parser.h"
/*
* Local prototypes
* 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);
# 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) );
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);
* 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);
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
*****************************************************************************