diff options
Diffstat (limited to 'src')
43 files changed, 4288 insertions, 173 deletions
| diff --git a/src/dxr3/video_out_dxr3.c b/src/dxr3/video_out_dxr3.c index 2c378ad25..51e872af7 100644 --- a/src/dxr3/video_out_dxr3.c +++ b/src/dxr3/video_out_dxr3.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_dxr3.c,v 1.87 2003/09/13 15:29:33 miguelfreitas Exp $ + * $Id: video_out_dxr3.c,v 1.88 2003/10/06 21:52:43 miguelfreitas Exp $   */  /* mpeg1 encoding video out plugin for the dxr3.   @@ -91,9 +91,9 @@ static vo_info_t   vo_info_dxr3_aa = {  plugin_info_t      xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */    #ifdef HAVE_X11 -  { PLUGIN_VIDEO_OUT, 16, "dxr3", XINE_VERSION_CODE, &vo_info_dxr3_x11, &dxr3_x11_init_plugin }, +  { PLUGIN_VIDEO_OUT, 17, "dxr3", XINE_VERSION_CODE, &vo_info_dxr3_x11, &dxr3_x11_init_plugin },  #endif -  { PLUGIN_VIDEO_OUT, 16, "aadxr3", XINE_VERSION_CODE, &vo_info_dxr3_aa, &dxr3_aa_init_plugin }, +  { PLUGIN_VIDEO_OUT, 17, "aadxr3", XINE_VERSION_CODE, &vo_info_dxr3_aa, &dxr3_aa_init_plugin },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/libmpeg2/Makefile.am b/src/libmpeg2/Makefile.am index d84b43780..7e5dbeb15 100644 --- a/src/libmpeg2/Makefile.am +++ b/src/libmpeg2/Makefile.am @@ -21,10 +21,11 @@ xineplug_decode_mpeg2_la_SOURCES = \  	motion_comp_mmx.c \  	motion_comp_mlib.c \  	slice.c \ +	slice_xvmc.c \  	stats.c \  	xine_decoder.c  xineplug_decode_mpeg2_la_LIBADD = $(XINE_LIB)  xineplug_decode_mpeg2_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ -noinst_HEADERS = vlc.h mpeg2.h mpeg2_internal.h  +noinst_HEADERS = vlc.h mpeg2.h mpeg2_internal.h diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index 0f9742fe4..a55c069a8 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -50,7 +50,8 @@  static void process_userdata(mpeg2dec_t *mpeg2dec, uint8_t *buffer); -void mpeg2_init (mpeg2dec_t * mpeg2dec) +void mpeg2_init (mpeg2dec_t * mpeg2dec,  +		 xine_video_port_t * output)  {    static int do_init = 1;    uint32_t mm_accel; @@ -71,11 +72,13 @@ void mpeg2_init (mpeg2dec_t * mpeg2dec)  						(void**)&mpeg2dec->picture_base);      mpeg2dec->shift = 0xffffff00; +    mpeg2dec->new_sequence = 0;      mpeg2dec->is_sequence_needed = 1;      mpeg2dec->is_wait_for_ip_frames = 2;      mpeg2dec->frames_to_drop = 0;      mpeg2dec->drop_frame = 0;      mpeg2dec->in_slice = 0; +    mpeg2dec->output = output;      mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;      mpeg2dec->code = 0xb4;      mpeg2dec->seek_mode = 0; @@ -84,6 +87,13 @@ void mpeg2_init (mpeg2dec_t * mpeg2dec)      /* initialize substructures */      mpeg2_header_state_init (mpeg2dec->picture); + +    if( output->get_capabilities(output) & VO_CAP_XVMC_MOCOMP ) { +      printf("libmpeg2: output port has XvMC capability\n"); +      mpeg2dec->frame_format = XINE_IMGFMT_XVMC; +    } else { +      mpeg2dec->frame_format = XINE_IMGFMT_YV12; +    }  }  static inline void get_frame_duration (mpeg2dec_t * mpeg2dec, vo_frame_t *frame) @@ -400,6 +410,11 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,  	    break;  	}  	if (mpeg2dec->force_aspect) picture->aspect_ratio_information = mpeg2dec->force_aspect; + +	if (mpeg2dec->is_sequence_needed ) { +	    mpeg2dec->new_sequence = 1; +	} +  	if (mpeg2dec->is_sequence_needed   	    || (picture->frame_width != picture->coded_picture_width)  	    || (picture->frame_height != picture->coded_picture_height)) { @@ -465,7 +480,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,  	if (!(mpeg2dec->in_slice)) {  	    mpeg2dec->in_slice = 1; -      +  	    if (picture->second_field) {  	      if (picture->current_frame)  		picture->current_frame->field(picture->current_frame,  @@ -475,6 +490,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,  	    } else {  		int flags = VO_INTERLACED_FLAG | picture->picture_structure;  		if (mpeg2dec->force_pan_scan) flags |= VO_PAN_SCAN_FLAG; +		if (mpeg2dec->new_sequence) flags |= VO_NEW_SEQUENCE_FLAG;  		if ( picture->current_frame &&   		     picture->current_frame != picture->backward_reference_frame && @@ -487,7 +503,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,  						     picture->coded_picture_width,  						     picture->coded_picture_height,  						     get_aspect_ratio(mpeg2dec), -						     XINE_IMGFMT_YV12, +						     mpeg2dec->frame_format,  						     flags);  		else {  		    picture->current_frame = @@ -495,7 +511,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,  						     picture->coded_picture_width,  						     picture->coded_picture_height,  						     get_aspect_ratio(mpeg2dec), -						     XINE_IMGFMT_YV12, +						     mpeg2dec->frame_format,  						     flags);  		    if (picture->forward_reference_frame &&  		        picture->forward_reference_frame != picture->backward_reference_frame) @@ -505,6 +521,11 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,  			picture->backward_reference_frame;  		    picture->backward_reference_frame = picture->current_frame;  		} +		if(mpeg2dec->new_sequence) +		{ +		    picture->mc = picture->current_frame->macroblocks; +		    mpeg2dec->new_sequence = 0; +		}  		picture->current_frame->bad_frame          = 1;  		picture->current_frame->drawn              = 0;  		picture->current_frame->pts                = mpeg2dec->pts; @@ -512,6 +533,21 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,                  picture->current_frame->repeat_first_field = picture->repeat_first_field;                  picture->current_frame->progressive_frame  = picture->progressive_frame; +                switch( picture->picture_coding_type ) { +                  case I_TYPE: +                    picture->current_frame->picture_coding_type = XINE_PICT_I_TYPE; +                    break; +                  case P_TYPE: +                    picture->current_frame->picture_coding_type = XINE_PICT_P_TYPE; +                    break; +                  case B_TYPE: +                    picture->current_frame->picture_coding_type = XINE_PICT_B_TYPE; +                    break; +                  case D_TYPE: +                    picture->current_frame->picture_coding_type = XINE_PICT_D_TYPE; +                    break; +                } +  #ifdef LOG  		printf ("libmpeg2: decoding frame %d, type %s\n",  			picture->current_frame->id, picture->picture_coding_type == I_TYPE ? "I" : @@ -522,7 +558,17 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,  	}  	if (!mpeg2dec->drop_frame && picture->current_frame != NULL) { -	  mpeg2_slice (picture, code, buffer); +#ifdef DEBUG_LOG +	  printf("slice target %08x past %08x future %08x\n",picture->current_frame,picture->forward_reference_frame,picture->backward_reference_frame); +	  fflush(stdout); +#endif + +	  if(picture->mc && picture->mc->xvmc_accel) { +	    mpeg2_xvmc_slice (picture, code, buffer); +	     +	  } else { +	    mpeg2_slice (picture, code, buffer); +	  }  	  if( picture->v_offset > picture->limit_y ) {   	    picture->current_frame->bad_frame = 0; @@ -796,6 +842,8 @@ void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec,        if (mpeg2dec->is_sequence_needed) {          xine_event_t event;          xine_format_change_data_t data; + +	mpeg2dec->new_sequence = 1;  	mpeg2dec->is_sequence_needed = 0;  	picture->frame_width  = picture->coded_picture_width; diff --git a/src/libmpeg2/idct.c b/src/libmpeg2/idct.c index 645fc03c1..d2b3ed866 100644 --- a/src/libmpeg2/idct.c +++ b/src/libmpeg2/idct.c @@ -55,9 +55,11 @@  #define W6 1108 /* 2048*sqrt (2)*cos (6*pi/16) */  #define W7 565  /* 2048*sqrt (2)*cos (7*pi/16) */ -/* idct main entry point  */ +/* idct main entry points  */  void (* mpeg2_idct_copy) (int16_t * block, uint8_t * dest, int stride);  void (* mpeg2_idct_add) (int16_t * block, uint8_t * dest, int stride); +void (* mpeg2_idct) (int16_t * block); +void (*	mpeg2_zero_block) (int16_t * block);  static uint8_t clip_lut[1024];  #define CLIP(i) ((clip_lut+384)[ (i)]) @@ -260,8 +262,26 @@ static void mpeg2_idct_add_c (int16_t * block, uint8_t * dest, int stride)      } while (--i);  } +static void mpeg2_idct_c (int16_t * block) +{ +    int i; + +    for (i = 0; i < 8; i++) +	idct_row (block + 8 * i); + +    for (i = 0; i < 8; i++) +	idct_col (block + i); +} + +static void mpeg2_zero_block_c (int16_t * wblock) +{ +  memset( wblock, 0, sizeof(int16_t) * 64 ); +} +  void mpeg2_idct_init (uint32_t mm_accel)  { +    mpeg2_zero_block = mpeg2_zero_block_c; +  #ifdef ARCH_X86      if (mm_accel & MM_ACCEL_X86_MMXEXT) {  #ifdef LOG @@ -269,13 +289,17 @@ void mpeg2_idct_init (uint32_t mm_accel)  #endif  	mpeg2_idct_copy = mpeg2_idct_copy_mmxext;  	mpeg2_idct_add = mpeg2_idct_add_mmxext; +	mpeg2_idct     = mpeg2_idct_mmxext; +	mpeg2_zero_block = mpeg2_zero_block_mmx;  	mpeg2_idct_mmx_init ();      } else if (mm_accel & MM_ACCEL_X86_MMX) {  #ifdef LOG  	fprintf (stderr, "Using MMX for IDCT transform\n");  #endif  	mpeg2_idct_copy = mpeg2_idct_copy_mmx; -	mpeg2_idct_add = mpeg2_idct_add_mmx; +	mpeg2_idct_add  = mpeg2_idct_add_mmx; +	mpeg2_idct      = mpeg2_idct_mmx; +	mpeg2_zero_block = mpeg2_zero_block_mmx;  	mpeg2_idct_mmx_init ();      } else  #endif @@ -287,6 +311,7 @@ void mpeg2_idct_init (uint32_t mm_accel)  	mpeg2_idct_copy = mpeg2_idct_copy_altivec;  	mpeg2_idct_add = mpeg2_idct_add_altivec;  	mpeg2_idct_altivec_init (); +	mpeg2_idct       = mpeg2_idct_c;      } else  #endif  #ifdef LIBMPEG2_MLIB @@ -295,6 +320,7 @@ void mpeg2_idct_init (uint32_t mm_accel)  	env_var = getenv ("MLIB_NON_IEEE"); +	mpeg2_idct = mpeg2_idct_mlib;  	if (env_var == NULL) {  #ifdef LOG  	    fprintf (stderr, "Using mlib for IDCT transform\n"); @@ -314,7 +340,8 @@ void mpeg2_idct_init (uint32_t mm_accel)  	fprintf (stderr, "No accelerated IDCT transform found\n");  #endif  	mpeg2_idct_copy = mpeg2_idct_copy_c; -	mpeg2_idct_add = mpeg2_idct_add_c; +	mpeg2_idct_add  = mpeg2_idct_add_c; +	mpeg2_idct      = mpeg2_idct_c;  	for (i = -384; i < 640; i++)  	    clip_lut[i+384] = (i < 0) ? 0 : ((i > 255) ? 255 : i);      } diff --git a/src/libmpeg2/idct_mlib.c b/src/libmpeg2/idct_mlib.c index bfafd07b1..bb1aad9a8 100644 --- a/src/libmpeg2/idct_mlib.c +++ b/src/libmpeg2/idct_mlib.c @@ -54,4 +54,9 @@ void mpeg2_idct_add_mlib_non_ieee (int16_t * block, uint8_t * dest, int stride)      memset (block, 0, 64 * sizeof (uint16_t));  } +void mpeg2_idct_mlib (int16_t * block) +{ +    mlib_VideoIDCT_IEEE_S16_S16 (block, block); +} +  #endif diff --git a/src/libmpeg2/idct_mmx.c b/src/libmpeg2/idct_mmx.c index bee54e83b..78ab3c547 100644 --- a/src/libmpeg2/idct_mmx.c +++ b/src/libmpeg2/idct_mmx.c @@ -691,6 +691,10 @@ void mpeg2_idct_add_mmxext (int16_t * block, uint8_t * dest, int stride)      block_zero (block);  } +void mpeg2_idct_mmxext (int16_t * block) +{ +    mmxext_idct (block); +}  declare_idct (mmx_idct, mmx_table,  	      mmx_row_head, mmx_row, mmx_row_tail, mmx_row_mid) @@ -709,6 +713,16 @@ void mpeg2_idct_add_mmx (int16_t * block, uint8_t * dest, int stride)      block_zero (block);  } +void mpeg2_idct_mmx (int16_t * block) +{ +    mmx_idct (block); +} + +void mpeg2_zero_block_mmx (int16_t * block) +{ +    block_zero (block); +} +  void mpeg2_idct_mmx_init (void)  {      extern uint8_t mpeg2_scan_norm[64]; diff --git a/src/libmpeg2/mpeg2.h b/src/libmpeg2/mpeg2.h index 2fdbacdce..b6500d1ef 100644 --- a/src/libmpeg2/mpeg2.h +++ b/src/libmpeg2/mpeg2.h @@ -22,10 +22,14 @@  /* Structure for the mpeg2dec decoder */  typedef struct mpeg2dec_s { +    xine_video_port_t * output; +    uint32_t frame_format; +      /* this is where we keep the state of the decoder */      struct picture_s * picture, *picture_base;      uint32_t shift; +    int new_sequence;      int is_sequence_needed;      int is_wait_for_ip_frames;      int frames_to_drop, drop_frame; @@ -56,7 +60,8 @@ typedef struct mpeg2dec_s {  /* initialize mpegdec with a opaque user pointer */ -void mpeg2_init (mpeg2dec_t * mpeg2dec); +void mpeg2_init (mpeg2dec_t * mpeg2dec,  +		 xine_video_port_t * output);  /* destroy everything which was allocated, shutdown the output */  void mpeg2_close (mpeg2dec_t * mpeg2dec); diff --git a/src/libmpeg2/mpeg2_internal.h b/src/libmpeg2/mpeg2_internal.h index 5beea9844..069fc9dc1 100644 --- a/src/libmpeg2/mpeg2_internal.h +++ b/src/libmpeg2/mpeg2_internal.h @@ -21,13 +21,16 @@   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */ +#include "video_out.h" +  /* macroblock modes */ -#define MACROBLOCK_INTRA 1 -#define MACROBLOCK_PATTERN 2 -#define MACROBLOCK_MOTION_BACKWARD 4 -#define MACROBLOCK_MOTION_FORWARD 8 -#define MACROBLOCK_QUANT 16 -#define DCT_TYPE_INTERLACED 32 +#define MACROBLOCK_INTRA            XINE_MACROBLOCK_INTRA +#define MACROBLOCK_PATTERN          XINE_MACROBLOCK_PATTERN +#define MACROBLOCK_MOTION_BACKWARD  XINE_MACROBLOCK_MOTION_BACKWARD +#define MACROBLOCK_MOTION_FORWARD   XINE_MACROBLOCK_MOTION_FORWARD +#define MACROBLOCK_QUANT            XINE_MACROBLOCK_QUANT +#define DCT_TYPE_INTERLACED         XINE_MACROBLOCK_DCT_TYPE_INTERLACED +  /* motion_type */  #define MOTION_TYPE_MASK (3*64)  #define MOTION_TYPE_BASE 64 @@ -37,16 +40,16 @@  #define MC_DMV (3*64)  /* picture structure */ -#define TOP_FIELD 1 -#define BOTTOM_FIELD 2 -#define FRAME_PICTURE 3 +#define TOP_FIELD     VO_TOP_FIELD +#define BOTTOM_FIELD  VO_BOTTOM_FIELD +#define FRAME_PICTURE VO_BOTH_FIELDS -/* picture coding type */ +/* picture coding type (mpeg2 header) */  #define I_TYPE 1  #define P_TYPE 2  #define B_TYPE 3  #define D_TYPE 4 - +                 typedef struct motion_s {      uint8_t * ref[2][3];      uint8_t ** ref2[2]; @@ -61,6 +64,17 @@ typedef struct picture_s {      /* DCT coefficients - should be kept aligned ! */      int16_t DCTblock[64]; +    /* XvMC DCT block and macroblock data for XvMC acceleration */ +    xine_macroblocks_t *mc; +    int XvMC_mb_type; +    int XvMC_mv_field_sel[2][2]; +    int XvMC_x; +    int XvMC_y; +    int XvMC_motion_type; +    int XvMC_dmvector[2]; +    int XvMC_cbp; +    int XvMC_dct_type; +      /* bit parsing stuff */      uint32_t bitstream_buf;	/* current 32 bit working set of buffer */      int bitstream_bits;		/* used bits in working set */ @@ -198,12 +212,16 @@ void mpeg2_idct_copy_mlib_non_ieee (int16_t * block, uint8_t * dest,  				    int stride);  void mpeg2_idct_add_mlib_non_ieee (int16_t * block, uint8_t * dest,  				   int stride); +void mpeg2_idct_mlib (int16_t * block);  /* idct_mmx.c */  void mpeg2_idct_copy_mmxext (int16_t * block, uint8_t * dest, int stride);  void mpeg2_idct_add_mmxext (int16_t * block, uint8_t * dest, int stride); +void mpeg2_idct_mmxext (int16_t * block);  void mpeg2_idct_copy_mmx (int16_t * block, uint8_t * dest, int stride);  void mpeg2_idct_add_mmx (int16_t * block, uint8_t * dest, int stride); +void mpeg2_idct_mmx (int16_t * block); +void mpeg2_zero_block_mmx (int16_t * block);  void mpeg2_idct_mmx_init (void);  /* idct_altivec.c */ @@ -236,5 +254,8 @@ extern mpeg2_mc_t mpeg2_mc_mlib;  /* slice.c */  void mpeg2_slice (picture_t * picture, int code, uint8_t * buffer); +/* slice_xvmc.c */ +void mpeg2_xvmc_slice (picture_t * picture, int code, uint8_t * buffer); +  /* stats.c */  void mpeg2_stats (int code, uint8_t * buffer); diff --git a/src/libmpeg2/slice_xvmc.c b/src/libmpeg2/slice_xvmc.c new file mode 100644 index 000000000..3e63bd77b --- /dev/null +++ b/src/libmpeg2/slice_xvmc.c @@ -0,0 +1,2066 @@ +/* + * slice_xvmc.c + * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "config.h" + +#include <stdio.h> +#include <string.h>	/* memcpy/memset, try to remove */ +#include <stdlib.h> +#include <inttypes.h> + +#include "xine_internal.h" +#include "video_out.h" +#include "mpeg2_internal.h" +#include "xineutils.h" + +#include "attributes.h" + + +#define MOTION_ACCEL   XINE_VO_MOTION_ACCEL +#define IDCT_ACCEL     XINE_VO_IDCT_ACCEL +#define SIGNED_INTRA   XINE_VO_SIGNED_INTRA +#define ACCEL          (MOTION_ACCEL | IDCT_ACCEL) + + +extern mpeg2_mc_t mpeg2_mc; +extern void (* mpeg2_idct_copy) (int16_t * block, uint8_t * dest, int stride); +extern void (* mpeg2_idct_add) (int16_t * block, uint8_t * dest, int stride); +extern void (* mpeg2_idct) (int16_t * block); +extern void (* mpeg2_cpu_state_save) (cpu_state_t * state); +extern void (* mpeg2_cpu_state_restore) (cpu_state_t * state); +extern void (* mpeg2_zero_block) (int16_t * block); + +#include "vlc.h" + +extern uint8_t mpeg2_scan_norm[64]; +extern uint8_t mpeg2_scan_alt[64]; + +/* original (non-patched) scan tables */ +static uint8_t mpeg2_scan_norm_orig[64] ATTR_ALIGN(16) = +{ +    /* Zig-Zag scan pattern */ +     0, 1, 8,16, 9, 2, 3,10, +    17,24,32,25,18,11, 4, 5, +    12,19,26,33,40,48,41,34, +    27,20,13, 6, 7,14,21,28, +    35,42,49,56,57,50,43,36, +    29,22,15,23,30,37,44,51, +    58,59,52,45,38,31,39,46, +    53,60,61,54,47,55,62,63 +}; + +uint8_t mpeg2_scan_alt_orig[64] ATTR_ALIGN(16) = +{ +    /* Alternate scan pattern */ +    0,8,16,24,1,9,2,10,17,25,32,40,48,56,57,49, +    41,33,26,18,3,11,4,12,19,27,34,42,50,58,35,43, +    51,59,20,28,5,13,6,14,21,29,36,44,52,60,37,45, +    53,61,22,30,7,15,23,31,38,46,54,62,39,47,55,63 +}; + + +static int non_linear_quantizer_scale [] = { +     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 +}; + +static inline int get_xvmc_macroblock_modes (picture_t * picture) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int macroblock_modes; +    MBtab * tab; + +    switch (picture->picture_coding_type) { +    case I_TYPE: + +	tab = MB_I + UBITS (bit_buf, 1); +	DUMPBITS (bit_buf, bits, tab->len); +	macroblock_modes = tab->modes; + +	if ((! (picture->frame_pred_frame_dct)) && +	    (picture->picture_structure == FRAME_PICTURE)) { +	    macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; +	    DUMPBITS (bit_buf, bits, 1); +	} + +	return macroblock_modes; + +    case P_TYPE: + +	tab = MB_P + UBITS (bit_buf, 5); +	DUMPBITS (bit_buf, bits, tab->len); +	macroblock_modes = tab->modes; + +	if (picture->picture_structure != FRAME_PICTURE) { +	    if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { +		macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; +		DUMPBITS (bit_buf, bits, 2); +	    } +	    return macroblock_modes; +	} else if (picture->frame_pred_frame_dct) { +	    if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) +		macroblock_modes |= MC_FRAME; +	    return macroblock_modes; +	} else { +	    if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { +		macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; +		DUMPBITS (bit_buf, bits, 2); +	    } +	    if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { +		macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; +		DUMPBITS (bit_buf, bits, 1); +	    } +	    return macroblock_modes; +	} + +    case B_TYPE: + +	tab = MB_B + UBITS (bit_buf, 6); +	DUMPBITS (bit_buf, bits, tab->len); +	macroblock_modes = tab->modes; + +	if (picture->picture_structure != FRAME_PICTURE) { +	    if (! (macroblock_modes & MACROBLOCK_INTRA)) { +		macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; +		DUMPBITS (bit_buf, bits, 2); +	    } +	    return macroblock_modes; +	} else if (picture->frame_pred_frame_dct) { +	    /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ +	    macroblock_modes |= MC_FRAME; +	    return macroblock_modes; +	} else { +	    if (macroblock_modes & MACROBLOCK_INTRA) +		goto intra; +	    macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; +	    DUMPBITS (bit_buf, bits, 2); +	    if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { +	    intra: +		macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; +		DUMPBITS (bit_buf, bits, 1); +	    } +	    return macroblock_modes; +	} + +    case D_TYPE: + +	DUMPBITS (bit_buf, bits, 1); +	return MACROBLOCK_INTRA; + +    default: +	return 0; +    } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int get_xvmc_quantizer_scale (picture_t * picture) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) + +    int quantizer_scale_code; + +    quantizer_scale_code = UBITS (bit_buf, 5); +    DUMPBITS (bit_buf, bits, 5); + +    if (picture->q_scale_type) +	return non_linear_quantizer_scale [quantizer_scale_code]; +    else +	return quantizer_scale_code << 1; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int get_xvmc_motion_delta (picture_t * picture, int f_code) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) + +    int delta; +    int sign; +    MVtab * tab; + +    if (bit_buf & 0x80000000) { +	DUMPBITS (bit_buf, bits, 1); +	return 0; +    } else if (bit_buf >= 0x0c000000) { + +	tab = MV_4 + UBITS (bit_buf, 4); +	delta = (tab->delta << f_code) + 1; +	bits += tab->len + f_code + 1; +	bit_buf <<= tab->len; + +	sign = SBITS (bit_buf, 1); +	bit_buf <<= 1; + +	if (f_code) +	    delta += UBITS (bit_buf, f_code); +	bit_buf <<= f_code; + +	return (delta ^ sign) - sign; + +    } else { + +	tab = MV_10 + UBITS (bit_buf, 10); +	delta = (tab->delta << f_code) + 1; +	bits += tab->len + 1; +	bit_buf <<= tab->len; + +	sign = SBITS (bit_buf, 1); +	bit_buf <<= 1; + +	if (f_code) { +	    NEEDBITS (bit_buf, bits, bit_ptr); +	    delta += UBITS (bit_buf, f_code); +	    DUMPBITS (bit_buf, bits, f_code); +	} + +	return (delta ^ sign) - sign; + +    } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int bound_motion_vector (int vector, int f_code) +{ +#if 1 +    unsigned int limit; +    int sign; + +    limit = 16 << f_code; + +    if ((unsigned int)(vector + limit) < 2 * limit) +	return vector; +    else { +	sign = ((int32_t)vector) >> 31; +	return vector - ((2 * limit) ^ sign) + sign; +    } +#else +    return ((int32_t)vector << (27 - f_code)) >> (27 - f_code); +#endif +} + +static inline int get_xvmc_dmv (picture_t * picture) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) + +    DMVtab * tab; + +    tab = DMV_2 + UBITS (bit_buf, 2); +    DUMPBITS (bit_buf, bits, tab->len); +    return tab->dmv; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int get_xvmc_coded_block_pattern (picture_t * picture) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) + +    CBPtab * tab; + +    NEEDBITS (bit_buf, bits, bit_ptr); + +    if (bit_buf >= 0x20000000) { + +	tab = CBP_7 + (UBITS (bit_buf, 7) - 16); +	DUMPBITS (bit_buf, bits, tab->len); +	return tab->cbp; + +    } else { + +	tab = CBP_9 + UBITS (bit_buf, 9); +	DUMPBITS (bit_buf, bits, tab->len); +	return tab->cbp; +    } + +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int get_xvmc_luma_dc_dct_diff (picture_t * picture) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    DCtab * tab; +    int size; +    int dc_diff; + +    if (bit_buf < 0xf8000000) { +	tab = DC_lum_5 + UBITS (bit_buf, 5); +	size = tab->size; +	if (size) { +	    bits += tab->len + size; +	    bit_buf <<= tab->len; +	    dc_diff = +		UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); +	    bit_buf <<= size; +	    return dc_diff; +	} else { +	    DUMPBITS (bit_buf, bits, 3); +	    return 0; +	} +    } else { +	tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); +	size = tab->size; +	DUMPBITS (bit_buf, bits, tab->len); +	NEEDBITS (bit_buf, bits, bit_ptr); +	dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); +	DUMPBITS (bit_buf, bits, size); +	return dc_diff; +    } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int get_xvmc_chroma_dc_dct_diff (picture_t * picture) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    DCtab * tab; +    int size; +    int dc_diff; + +    if (bit_buf < 0xf8000000) { +	tab = DC_chrom_5 + UBITS (bit_buf, 5); +	size = tab->size; +	if (size) { +	    bits += tab->len + size; +	    bit_buf <<= tab->len; +	    dc_diff = +		UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); +	    bit_buf <<= size; +	    return dc_diff; +	} else { +	    DUMPBITS (bit_buf, bits, 2); +	    return 0; +	} +    } else { +	tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); +	size = tab->size; +	DUMPBITS (bit_buf, bits, tab->len + 1); +	NEEDBITS (bit_buf, bits, bit_ptr); +	dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); +	DUMPBITS (bit_buf, bits, size); +	return dc_diff; +    } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +#define SATURATE(val)			\ +do {					\ +    if ((uint32_t)(val + 2048) > 4095)	\ +	val = (val > 0) ? 2047 : -2048;	\ +} while (0) + +static void get_xvmc_intra_block_B14 (picture_t * picture) +{ +    int i; +    int j; +    int val; +    uint8_t * scan = picture->scan; +    uint8_t * quant_matrix = picture->intra_quantizer_matrix; +    int quantizer_scale = picture->quantizer_scale; +    int mismatch; +    DCTtab * tab; +    uint32_t bit_buf; +    int bits; +    uint8_t * bit_ptr; +    int16_t * dest; + +    dest = picture->mc->blockptr; + +    /* XvMC's IDCT must use non-patched scan tables */ +    if( picture->mc->xvmc_accel & IDCT_ACCEL ) { +      if( scan == mpeg2_scan_norm ) +        scan = mpeg2_scan_norm_orig; +      else +        scan = mpeg2_scan_alt_orig; +    } + +    i = 0; +    mismatch = ~dest[0]; + +    bit_buf = picture->bitstream_buf; +    bits = picture->bitstream_bits; +    bit_ptr = picture->bitstream_ptr; + +    NEEDBITS (bit_buf, bits, bit_ptr); + +    while (1) { +	if (bit_buf >= 0x28000000) { + +	    tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + +	    i += tab->run; +	    if (i >= 64) +		break;	/* end of block */ + +	normal_code: +	    j = scan[i]; +	    bit_buf <<= tab->len; +	    bits += tab->len + 1; +	    val = (tab->level * quantizer_scale * quant_matrix[j]) >> 4; + +	    /* if (bitstream_get (1)) val = -val; */ +	    val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + +	    SATURATE (val); +	    dest[j] = val; +	    mismatch ^= val; + +	    bit_buf <<= 1; +	    NEEDBITS (bit_buf, bits, bit_ptr); + +	    continue; + +	} else if (bit_buf >= 0x04000000) { + +	    tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + +	    i += tab->run; +	    if (i < 64) +		goto normal_code; + +	    /* escape code */ + +	    i += UBITS (bit_buf << 6, 6) - 64; +	    if (i >= 64) +		break;	/* illegal, check needed to avoid buffer overflow */ + +	    j = scan[i]; + +	    DUMPBITS (bit_buf, bits, 12); +	    NEEDBITS (bit_buf, bits, bit_ptr); +	    val = (SBITS (bit_buf, 12) * +		   quantizer_scale * quant_matrix[j]) / 16; + +	    SATURATE (val); +	    dest[j] = val; +	    mismatch ^= val; + +	    DUMPBITS (bit_buf, bits, 12); +	    NEEDBITS (bit_buf, bits, bit_ptr); + +	    continue; + +	} else if (bit_buf >= 0x02000000) { +	    tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00800000) { +	    tab = DCT_13 + (UBITS (bit_buf, 13) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00200000) { +	    tab = DCT_15 + (UBITS (bit_buf, 15) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else { +	    tab = DCT_16 + UBITS (bit_buf, 16); +	    bit_buf <<= 16; +	    GETWORD (bit_buf, bits + 16, bit_ptr); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} +	break;	/* illegal, check needed to avoid buffer overflow */ +    } + +    dest[63] ^= mismatch & 1; +    DUMPBITS (bit_buf, bits, 2);	/* dump end of block code */ +    picture->bitstream_buf = bit_buf; +    picture->bitstream_bits = bits; +    picture->bitstream_ptr = bit_ptr; +} + +static void get_xvmc_intra_block_B15 (picture_t * picture) +{ +    int i; +    int j; +    int val; +    uint8_t * scan = picture->scan; +    uint8_t * quant_matrix = picture->intra_quantizer_matrix; +    int quantizer_scale = picture->quantizer_scale; +    int mismatch; +    DCTtab * tab; +    uint32_t bit_buf; +    int bits; +    uint8_t * bit_ptr; +    int16_t * dest; + +    dest = picture->mc->blockptr; + +    /* XvMC's IDCT must use non-patched scan tables */ +    if( picture->mc->xvmc_accel & IDCT_ACCEL ) { +      if( scan == mpeg2_scan_norm ) +        scan = mpeg2_scan_norm_orig; +      else +        scan = mpeg2_scan_alt_orig; +    } + +    i = 0; +    mismatch = ~dest[0]; + +    bit_buf = picture->bitstream_buf; +    bits = picture->bitstream_bits; +    bit_ptr = picture->bitstream_ptr; + +    NEEDBITS (bit_buf, bits, bit_ptr); + +    while (1) { +	if (bit_buf >= 0x04000000) { + +	    tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); + +	    i += tab->run; +	    if (i < 64) { + +	    normal_code: +		j = scan[i]; +		bit_buf <<= tab->len; +		bits += tab->len + 1; +		val = (tab->level * quantizer_scale * quant_matrix[j]) >> 4; + +		/* if (bitstream_get (1)) val = -val; */ +		val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + +		SATURATE (val); +		dest[j] = val; +		mismatch ^= val; + +		bit_buf <<= 1; +		NEEDBITS (bit_buf, bits, bit_ptr); + +		continue; + +	    } else { + +		/* end of block. I commented out this code because if we */ +		/* dont exit here we will still exit at the later test :) */ + +		/* if (i >= 128) break;	*/	/* end of block */ + +		/* escape code */ + +		i += UBITS (bit_buf << 6, 6) - 64; +		if (i >= 64) +		    break;	/* illegal, check against buffer overflow */ + +		j = scan[i]; + +		DUMPBITS (bit_buf, bits, 12); +		NEEDBITS (bit_buf, bits, bit_ptr); +		val = (SBITS (bit_buf, 12) * +		       quantizer_scale * quant_matrix[j]) / 16; + +		SATURATE (val); + +		dest[j] = val; +		mismatch ^= val; + +		DUMPBITS (bit_buf, bits, 12); +		NEEDBITS (bit_buf, bits, bit_ptr); + +		continue; + +	    } +	} else if (bit_buf >= 0x02000000) { +	    tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00800000) { +	    tab = DCT_13 + (UBITS (bit_buf, 13) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00200000) { +	    tab = DCT_15 + (UBITS (bit_buf, 15) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else { +	    tab = DCT_16 + UBITS (bit_buf, 16); +	    bit_buf <<= 16; +	    GETWORD (bit_buf, bits + 16, bit_ptr); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} +	break;	/* illegal, check needed to avoid buffer overflow */ +    } + +    dest[63] ^= mismatch & 1; +    DUMPBITS (bit_buf, bits, 4);	/* dump end of block code */ +    picture->bitstream_buf = bit_buf; +    picture->bitstream_bits = bits; +    picture->bitstream_ptr = bit_ptr; +} + +static void get_xvmc_non_intra_block (picture_t * picture) +{ +    int i; +    int j; +    int val; +    uint8_t * scan = picture->scan; +    uint8_t * quant_matrix = picture->non_intra_quantizer_matrix; +    int quantizer_scale = picture->quantizer_scale; +    int mismatch; +    DCTtab * tab; +    uint32_t bit_buf; +    int bits; +    uint8_t * bit_ptr; +    int16_t * dest; + +    i = -1; +    mismatch = 1; + +    dest = picture->mc->blockptr; + +    /* XvMC's IDCT must use non-patched scan tables */ +    if( picture->mc->xvmc_accel & IDCT_ACCEL ) { +      if( scan == mpeg2_scan_norm ) +        scan = mpeg2_scan_norm_orig; +      else +        scan = mpeg2_scan_alt_orig; +    } + +    bit_buf = picture->bitstream_buf; +    bits = picture->bitstream_bits; +    bit_ptr = picture->bitstream_ptr; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    if (bit_buf >= 0x28000000) { +	tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); +	goto entry_1; +    } else +	goto entry_2; + +    while (1) { +	if (bit_buf >= 0x28000000) { + +	    tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + +	entry_1: +	    i += tab->run; +	    if (i >= 64) +		break;	/* end of block */ + +	normal_code: +	    j = scan[i]; +	    bit_buf <<= tab->len; +	    bits += tab->len + 1; +	    val = ((2*tab->level+1) * quantizer_scale * quant_matrix[j]) >> 5; + +	    /* if (bitstream_get (1)) val = -val; */ +	    val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + +	    SATURATE (val); +	    dest[j] = val; +	    mismatch ^= val; + +	    bit_buf <<= 1; +	    NEEDBITS (bit_buf, bits, bit_ptr); + +	    continue; + +	} + +    entry_2: +	if (bit_buf >= 0x04000000) { + +	    tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + +	    i += tab->run; +	    if (i < 64) +		goto normal_code; + +	    /* escape code */ + +	    i += UBITS (bit_buf << 6, 6) - 64; +	    if (i >= 64) +		break;	/* illegal, check needed to avoid buffer overflow */ + +	    j = scan[i]; + +	    DUMPBITS (bit_buf, bits, 12); +	    NEEDBITS (bit_buf, bits, bit_ptr); +	    val = 2 * (SBITS (bit_buf, 12) + SBITS (bit_buf, 1)) + 1; +	    val = (val * quantizer_scale * quant_matrix[j]) / 32; + +	    SATURATE (val); +	    dest[j] = val; +	    mismatch ^= val; + +	    DUMPBITS (bit_buf, bits, 12); +	    NEEDBITS (bit_buf, bits, bit_ptr); + +	    continue; + +	} else if (bit_buf >= 0x02000000) { +	    tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00800000) { +	    tab = DCT_13 + (UBITS (bit_buf, 13) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00200000) { +	    tab = DCT_15 + (UBITS (bit_buf, 15) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else { +	    tab = DCT_16 + UBITS (bit_buf, 16); +	    bit_buf <<= 16; +	    GETWORD (bit_buf, bits + 16, bit_ptr); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} +	break;	/* illegal, check needed to avoid buffer overflow */ +    } + +    dest[63] ^= mismatch & 1; +    DUMPBITS (bit_buf, bits, 2);	/* dump end of block code */ +    picture->bitstream_buf = bit_buf; +    picture->bitstream_bits = bits; +    picture->bitstream_ptr = bit_ptr; +} + +static void get_xvmc_mpeg1_intra_block (picture_t * picture) +{ +    int i; +    int j; +    int val; +    uint8_t * scan = picture->scan; +    uint8_t * quant_matrix = picture->intra_quantizer_matrix; +    int quantizer_scale = picture->quantizer_scale; +    DCTtab * tab; +    uint32_t bit_buf; +    int bits; +    uint8_t * bit_ptr; +    int16_t * dest; + +    i = 0; + +    dest = picture->mc->blockptr; + +    /* XvMC's IDCT must use non-patched scan tables */ +    if( picture->mc->xvmc_accel & IDCT_ACCEL ) { +      if( scan == mpeg2_scan_norm ) +        scan = mpeg2_scan_norm_orig; +      else +        scan = mpeg2_scan_alt_orig; +    } + +    bit_buf = picture->bitstream_buf; +    bits = picture->bitstream_bits; +    bit_ptr = picture->bitstream_ptr; + +    NEEDBITS (bit_buf, bits, bit_ptr); + +    while (1) { +	if (bit_buf >= 0x28000000) { + +	    tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + +	    i += tab->run; +	    if (i >= 64) +		break;	/* end of block */ + +	normal_code: +	    j = scan[i]; +	    bit_buf <<= tab->len; +	    bits += tab->len + 1; +	    val = (tab->level * quantizer_scale * quant_matrix[j]) >> 4; + +	    /* oddification */ +	    val = (val - 1) | 1; + +	    /* if (bitstream_get (1)) val = -val; */ +	    val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + +	    SATURATE (val); +	    dest[j] = val; + +	    bit_buf <<= 1; +	    NEEDBITS (bit_buf, bits, bit_ptr); + +	    continue; + +	} else if (bit_buf >= 0x04000000) { + +	    tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + +	    i += tab->run; +	    if (i < 64) +		goto normal_code; + +	    /* escape code */ + +	    i += UBITS (bit_buf << 6, 6) - 64; +	    if (i >= 64) +		break;	/* illegal, check needed to avoid buffer overflow */ + +	    j = scan[i]; + +	    DUMPBITS (bit_buf, bits, 12); +	    NEEDBITS (bit_buf, bits, bit_ptr); +	    val = SBITS (bit_buf, 8); +	    if (! (val & 0x7f)) { +		DUMPBITS (bit_buf, bits, 8); +		val = UBITS (bit_buf, 8) + 2 * val; +	    } +	    val = (val * quantizer_scale * quant_matrix[j]) / 16; + +	    /* oddification */ +	    val = (val + ~SBITS (val, 1)) | 1; + +	    SATURATE (val); +	    dest[j] = val; + +	    DUMPBITS (bit_buf, bits, 8); +	    NEEDBITS (bit_buf, bits, bit_ptr); + +	    continue; + +	} else if (bit_buf >= 0x02000000) { +	    tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00800000) { +	    tab = DCT_13 + (UBITS (bit_buf, 13) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00200000) { +	    tab = DCT_15 + (UBITS (bit_buf, 15) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else { +	    tab = DCT_16 + UBITS (bit_buf, 16); +	    bit_buf <<= 16; +	    GETWORD (bit_buf, bits + 16, bit_ptr); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} +	break;	/* illegal, check needed to avoid buffer overflow */ +    } +    DUMPBITS (bit_buf, bits, 2);	/* dump end of block code */ +    picture->bitstream_buf = bit_buf; +    picture->bitstream_bits = bits; +    picture->bitstream_ptr = bit_ptr; +} + +static void get_xvmc_mpeg1_non_intra_block (picture_t * picture) +{ +    int i; +    int j; +    int val; +    uint8_t * scan = picture->scan; +    uint8_t * quant_matrix = picture->non_intra_quantizer_matrix; +    int quantizer_scale = picture->quantizer_scale; +    DCTtab * tab; +    uint32_t bit_buf; +    int bits; +    uint8_t * bit_ptr; +    int16_t * dest; + +    i = -1; + +    dest = picture->mc->blockptr; + +    /* XvMC's IDCT must use non-patched scan tables */ +    if( picture->mc->xvmc_accel & IDCT_ACCEL ) { +      if( scan == mpeg2_scan_norm ) +        scan = mpeg2_scan_norm_orig; +      else +        scan = mpeg2_scan_alt_orig; +    } + +    bit_buf = picture->bitstream_buf; +    bits = picture->bitstream_bits; +    bit_ptr = picture->bitstream_ptr; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    if (bit_buf >= 0x28000000) { +	tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); +	goto entry_1; +    } else +	goto entry_2; + +    while (1) { +	if (bit_buf >= 0x28000000) { + +	    tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + +	entry_1: +	    i += tab->run; +	    if (i >= 64) +		break;	/* end of block */ + +	normal_code: +	    j = scan[i]; +	    bit_buf <<= tab->len; +	    bits += tab->len + 1; +	    val = ((2*tab->level+1) * quantizer_scale * quant_matrix[j]) >> 5; + +	    /* oddification */ +	    val = (val - 1) | 1; + +	    /* if (bitstream_get (1)) val = -val; */ +	    val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + +	    SATURATE (val); +	    dest[j] = val; + +	    bit_buf <<= 1; +	    NEEDBITS (bit_buf, bits, bit_ptr); + +	    continue; + +	} + +    entry_2: +	if (bit_buf >= 0x04000000) { + +	    tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + +	    i += tab->run; +	    if (i < 64) +		goto normal_code; + +	    /* escape code */ + +	    i += UBITS (bit_buf << 6, 6) - 64; +	    if (i >= 64) +		break;	/* illegal, check needed to avoid buffer overflow */ + +	    j = scan[i]; + +	    DUMPBITS (bit_buf, bits, 12); +	    NEEDBITS (bit_buf, bits, bit_ptr); +	    val = SBITS (bit_buf, 8); +	    if (! (val & 0x7f)) { +		DUMPBITS (bit_buf, bits, 8); +		val = UBITS (bit_buf, 8) + 2 * val; +	    } +	    val = 2 * (val + SBITS (val, 1)) + 1; +	    val = (val * quantizer_scale * quant_matrix[j]) / 32; + +	    /* oddification */ +	    val = (val + ~SBITS (val, 1)) | 1; + +	    SATURATE (val); +	    dest[j] = val; + +	    DUMPBITS (bit_buf, bits, 8); +	    NEEDBITS (bit_buf, bits, bit_ptr); + +	    continue; + +	} else if (bit_buf >= 0x02000000) { +	    tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00800000) { +	    tab = DCT_13 + (UBITS (bit_buf, 13) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else if (bit_buf >= 0x00200000) { +	    tab = DCT_15 + (UBITS (bit_buf, 15) - 16); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} else { +	    tab = DCT_16 + UBITS (bit_buf, 16); +	    bit_buf <<= 16; +	    GETWORD (bit_buf, bits + 16, bit_ptr); +	    i += tab->run; +	    if (i < 64) +		goto normal_code; +	} +	break;	/* illegal, check needed to avoid buffer overflow */ +    } +    DUMPBITS (bit_buf, bits, 2);	/* dump end of block code */ +    picture->bitstream_buf = bit_buf; +    picture->bitstream_bits = bits; +    picture->bitstream_ptr = bit_ptr; +} + +static inline void slice_xvmc_intra_DCT (picture_t * picture, int cc, +				    uint8_t * dest, int stride) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits)   +#define bit_ptr (picture->bitstream_ptr) +    NEEDBITS (bit_buf, bits, bit_ptr); +    /* Get the intra DC coefficient and inverse quantize it */ + +    //    printf("slice: slice_xvmc_intra_DCT cc=%d pred[0]=%d\n",cc,picture->dc_dct_pred[0]); +    if (cc == 0) +	picture->dc_dct_pred[0] += get_xvmc_luma_dc_dct_diff (picture); +    else +	picture->dc_dct_pred[cc] += get_xvmc_chroma_dc_dct_diff (picture); +    //TODO conversion to signed format  +    //    printf("slice:  pred[0]=%d presision=%d\n",picture->dc_dct_pred[0], +    //       picture->intra_dc_precision); + +    mpeg2_zero_block(picture->mc->blockptr); + +    picture->mc->blockptr[0] = +	picture->dc_dct_pred[cc] << (3 - picture->intra_dc_precision); +    //    memset (picture->mc->blockptr + 1, 0, 63 * sizeof (int16_t)); +    // TODO do we need to zero mem here? + +    if (picture->mpeg1) { +	if (picture->picture_coding_type != D_TYPE) +	    get_xvmc_mpeg1_intra_block (picture); +    } else if (picture->intra_vlc_format) +	get_xvmc_intra_block_B15 (picture); +    else +	get_xvmc_intra_block_B14 (picture); + +    if((picture->mc->xvmc_accel & ACCEL) == MOTION_ACCEL) { +        //motion_comp only no idct acceleration so do it in software +        mpeg2_idct (picture->mc->blockptr); +    } +    picture->mc->blockptr += 64; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline void slice_xvmc_non_intra_DCT (picture_t * picture, uint8_t * dest, +					int stride) +{ +    mpeg2_zero_block(picture->mc->blockptr); + +    if (picture->mpeg1) +	get_xvmc_mpeg1_non_intra_block (picture); +    else +	get_xvmc_non_intra_block (picture); + +    if((picture->mc->xvmc_accel & ACCEL) == MOTION_ACCEL) { +      // motion comp only no idct acceleration so do it in sw +      mpeg2_idct (picture->mc->blockptr); +    } +    picture->mc->blockptr += 64; +} + +#define MOTION(table,ref,motion_x,motion_y,size,y)			      \ +    pos_x = 2 * picture->offset + motion_x;				      \ +    pos_y = 2 * picture->v_offset + motion_y + 2 * y;			      \ +    if ((pos_x > picture->limit_x) || (pos_y > picture->limit_y_ ## size))    \ +	return;								      \ +    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);				      \ +    table[xy_half] (picture->dest[0] + y * picture->pitches[0] +	      \ +		    picture->offset, ref[0] + (pos_x >> 1) +		      \ +		    (pos_y >> 1) * picture->pitches[0], picture->pitches[0],  \ +		    size);						      \ +    motion_x /= 2;	motion_y /= 2;					      \ +    xy_half = ((motion_y & 1) << 1) | (motion_x & 1);			      \ +    table[4+xy_half] (picture->dest[1] + y/2 * picture->pitches[1] +	      \ +		      (picture->offset >> 1), ref[1] +			      \ +		      (((picture->offset + motion_x) >> 1) +		      \ +		       ((((picture->v_offset + motion_y) >> 1) + y/2) *	      \ +		        picture->pitches[1])), picture->pitches[1], size/2);  \ +    table[4+xy_half] (picture->dest[2] + y/2 * picture->pitches[2] +	      \ +		      (picture->offset >> 1), ref[2] +			      \ +		      (((picture->offset + motion_x) >> 1) +		      \ +		       ((((picture->v_offset + motion_y) >> 1) + y/2) *	      \ +		        picture->pitches[2])), picture->pitches[2], size/2)   \ + +#define MOTION_FIELD(table,ref,motion_x,motion_y,dest_field,op,src_field)     \ + +static void motion_mp1 (picture_t * picture, motion_t * motion, +			void (** table) (uint8_t *, uint8_t *, int, int)) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int motion_x, motion_y; +    unsigned int pos_x, pos_y, xy_half; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_x = (motion->pmv[0][0] + +		(get_xvmc_motion_delta (picture, +				   motion->f_code[0]) << motion->f_code[1])); +    motion_x = bound_motion_vector (motion_x, +				    motion->f_code[0] + motion->f_code[1]); +    motion->pmv[0][0] = motion_x; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_y = (motion->pmv[0][1] + +		(get_xvmc_motion_delta (picture, +				   motion->f_code[0]) << motion->f_code[1])); +    motion_y = bound_motion_vector (motion_y, +				    motion->f_code[0] + motion->f_code[1]); +    motion->pmv[0][1] = motion_y; + +    MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0); +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void motion_fr_frame (picture_t * picture, motion_t * motion, +			     void (** table) (uint8_t *, uint8_t *, int, int)) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int motion_x, motion_y; +    unsigned int pos_x, pos_y, xy_half; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_x = motion->pmv[0][0] + get_xvmc_motion_delta (picture, +						     motion->f_code[0]); +    motion_x = bound_motion_vector (motion_x, motion->f_code[0]); +    motion->pmv[1][0] = motion->pmv[0][0] = motion_x; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_y = motion->pmv[0][1] + get_xvmc_motion_delta (picture, +						     motion->f_code[1]); +    motion_y = bound_motion_vector (motion_y, motion->f_code[1]); +    motion->pmv[1][1] = motion->pmv[0][1] = motion_y; + +    MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0); +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void motion_fr_field (picture_t * picture, motion_t * motion, +			     void (** table) (uint8_t *, uint8_t *, int, int), +			     int dir) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int motion_x, motion_y, field; +    //    unsigned int pos_x, pos_y, xy_half; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    field = UBITS (bit_buf, 1); +    picture->XvMC_mv_field_sel[0][dir] = field; +    DUMPBITS (bit_buf, bits, 1); + +    motion_x = motion->pmv[0][0] + get_xvmc_motion_delta (picture, +						     motion->f_code[0]); +    motion_x = bound_motion_vector (motion_x, motion->f_code[0]); +    motion->pmv[0][0] = motion_x; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_y = (motion->pmv[0][1] >> 1) + get_xvmc_motion_delta (picture, +							    motion->f_code[1]); +    /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ +    motion->pmv[0][1] = motion_y << 1; + +    //    MOTION_FIELD (table, motion->ref[0], motion_x, motion_y, 0, & ~1, field); + +    NEEDBITS (bit_buf, bits, bit_ptr); +    field = UBITS (bit_buf, 1); +    //TODO look at field select need bob  (weave ok) +    picture->XvMC_mv_field_sel[1][dir] = field; +    DUMPBITS (bit_buf, bits, 1); + +    motion_x = motion->pmv[1][0] + get_xvmc_motion_delta (picture, +						     motion->f_code[0]); +    motion_x = bound_motion_vector (motion_x, motion->f_code[0]); +    motion->pmv[1][0] = motion_x; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_y = (motion->pmv[1][1] >> 1) + get_xvmc_motion_delta (picture, +							    motion->f_code[1]); +    /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ +    motion->pmv[1][1] = motion_y << 1; + +    //    MOTION_FIELD (table, motion->ref[0], motion_x, motion_y, 1, & ~1, field); +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void motion_fr_dmv (picture_t * picture, motion_t * motion, +			   void (** table) (uint8_t *, uint8_t *, int, int)) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int motion_x, motion_y, dmv_x, dmv_y; +    unsigned int xy_half, offset; + +    // TODO field select ?? possible need to be 0 +    picture->XvMC_mv_field_sel[0][0] = picture->XvMC_mv_field_sel[1][0] = 0; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_x = motion->pmv[0][0] + get_xvmc_motion_delta (picture, +						     motion->f_code[0]); +    motion_x = bound_motion_vector (motion_x, motion->f_code[0]); +    motion->pmv[1][0] = motion->pmv[0][0] = motion_x; +    NEEDBITS (bit_buf, bits, bit_ptr); +    dmv_x = get_xvmc_dmv (picture); + +    motion_y = (motion->pmv[0][1] >> 1) + get_xvmc_motion_delta (picture, +							    motion->f_code[1]); +    /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ +    motion->pmv[1][1] = motion->pmv[0][1] = motion_y << 1; +    dmv_y = get_xvmc_dmv (picture); + +    //    m = picture->top_field_first ? 1 : 3; +    //    other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x; +    //    other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y - 1; +    //    MOTION_FIELD (mpeg2_mc.put, motion->ref[0], other_x, other_y, 0, | 1, 0); + +    //    m = picture->top_field_first ? 3 : 1; +    //    other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x; +    //    other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y + 1; +    //    MOTION_FIELD (mpeg2_mc.put, motion->ref[0], other_x, other_y, 1, & ~1, 0); + +    xy_half = ((motion_y & 1) << 1) | (motion_x & 1); +    offset = (picture->offset + (motion_x >> 1) + +	      (picture->v_offset + (motion_y & ~1)) * picture->pitches[0]); +    mpeg2_mc.avg[xy_half] +	(picture->dest[0] + picture->offset, +	 motion->ref[0][0] + offset, 2 * picture->pitches[0], 8); +    mpeg2_mc.avg[xy_half] +	(picture->dest[0] + picture->pitches[0] + picture->offset, +	 motion->ref[0][0] + picture->pitches[0] + offset, +	 2 * picture->pitches[0], 8); +    motion_x /= 2;	motion_y /= 2; +    xy_half = ((motion_y & 1) << 1) | (motion_x & 1); +    offset = (((picture->offset + motion_x) >> 1) + +	      (((picture->v_offset >> 1) + (motion_y & ~1)) * +	       picture->pitches[1])); +    mpeg2_mc.avg[4+xy_half] +	(picture->dest[1] + (picture->offset >> 1), +	 motion->ref[0][1] + offset, 2 * picture->pitches[1], 4); +    mpeg2_mc.avg[4+xy_half] +	(picture->dest[1] + picture->pitches[1] + (picture->offset >> 1), +	 motion->ref[0][1] + picture->pitches[1] + offset, +	 2 * picture->pitches[1], 4); +    offset = (((picture->offset + motion_x) >> 1) + +	      (((picture->v_offset >> 1) + (motion_y & ~1)) * +	       picture->pitches[2])); +    mpeg2_mc.avg[4+xy_half] +	(picture->dest[2] + (picture->offset >> 1), +	 motion->ref[0][2] + offset, 2 * picture->pitches[2], 4); +    mpeg2_mc.avg[4+xy_half] +	(picture->dest[2] + picture->pitches[2] + (picture->offset >> 1), +	 motion->ref[0][2] + picture->pitches[2] + offset, +	 2 * picture->pitches[2], 4); +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void motion_reuse (picture_t * picture, motion_t * motion, +			  void (** table) (uint8_t *, uint8_t *, int, int)) +{ +    int motion_x, motion_y; +    unsigned int pos_x, pos_y, xy_half; + +    motion_x = motion->pmv[0][0]; +    motion_y = motion->pmv[0][1]; + +    MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0); +} + +// TODO don't need this routine +static void motion_zero (picture_t * picture, motion_t * motion, +			 void (** table) (uint8_t *, uint8_t *, int, int)) +{ +  if(picture->mc->xvmc_accel==0) { +    table[0] (picture->dest[0] + picture->offset, +	      (motion->ref[0][0] + picture->offset + +	       picture->v_offset * picture->pitches[0]), +	      picture->pitches[0], 16); + +    table[4] (picture->dest[1] + (picture->offset >> 1), +	      motion->ref[0][1] + (picture->offset >> 1) + +	      (picture->v_offset >> 1) * picture->pitches[1], +	      picture->pitches[1], 8); +    table[4] (picture->dest[2] + (picture->offset >> 1), +	      motion->ref[0][2] + (picture->offset >> 1) + +	      (picture->v_offset >> 1) * picture->pitches[2], +	      picture->pitches[2], 8); +  } +} + +/* like motion_frame, but parsing without actual motion compensation */ +static void motion_fr_conceal (picture_t * picture) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int tmp; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    tmp = (picture->f_motion.pmv[0][0] + +	   get_xvmc_motion_delta (picture, picture->f_motion.f_code[0])); +    tmp = bound_motion_vector (tmp, picture->f_motion.f_code[0]); +    picture->f_motion.pmv[1][0] = picture->f_motion.pmv[0][0] = tmp; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    tmp = (picture->f_motion.pmv[0][1] + +	   get_xvmc_motion_delta (picture, picture->f_motion.f_code[1])); +    tmp = bound_motion_vector (tmp, picture->f_motion.f_code[1]); +    picture->f_motion.pmv[1][1] = picture->f_motion.pmv[0][1] = tmp; + +    DUMPBITS (bit_buf, bits, 1); /* remove marker_bit */ +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void motion_fi_field (picture_t * picture, motion_t * motion, +			     void (** table) (uint8_t *, uint8_t *, int, int)) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int motion_x, motion_y; +    uint8_t ** ref_field; +    unsigned int pos_x, pos_y, xy_half; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    ref_field = motion->ref2[UBITS (bit_buf, 1)]; + +    // TODO field select may need to do something here for bob (weave ok) +    picture->XvMC_mv_field_sel[0][0] = picture->XvMC_mv_field_sel[1][0] = 0; + +    DUMPBITS (bit_buf, bits, 1); + +    motion_x = motion->pmv[0][0] + get_xvmc_motion_delta (picture, +						     motion->f_code[0]); +    motion_x = bound_motion_vector (motion_x, motion->f_code[0]); +    motion->pmv[1][0] = motion->pmv[0][0] = motion_x; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_y = motion->pmv[0][1] + get_xvmc_motion_delta (picture, +						     motion->f_code[1]); +    motion_y = bound_motion_vector (motion_y, motion->f_code[1]); +    motion->pmv[1][1] = motion->pmv[0][1] = motion_y; + +    MOTION (table, ref_field, motion_x, motion_y, 16, 0); +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void motion_fi_16x8 (picture_t * picture, motion_t * motion, +			    void (** table) (uint8_t *, uint8_t *, int, int)) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int motion_x, motion_y; +    uint8_t ** ref_field; +    unsigned int pos_x, pos_y, xy_half; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    ref_field = motion->ref2[UBITS (bit_buf, 1)]; + +    // TODO field select may need to do something here bob  (weave ok) +    picture->XvMC_mv_field_sel[0][0] = picture->XvMC_mv_field_sel[1][0] = 0; + +    DUMPBITS (bit_buf, bits, 1); + +    motion_x = motion->pmv[0][0] + get_xvmc_motion_delta (picture, +						     motion->f_code[0]); +    motion_x = bound_motion_vector (motion_x, motion->f_code[0]); +    motion->pmv[0][0] = motion_x; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_y = motion->pmv[0][1] + get_xvmc_motion_delta (picture, +						     motion->f_code[1]); +    motion_y = bound_motion_vector (motion_y, motion->f_code[1]); +    motion->pmv[0][1] = motion_y; + +    MOTION (table, ref_field, motion_x, motion_y, 8, 0); + +    NEEDBITS (bit_buf, bits, bit_ptr); +    ref_field = motion->ref2[UBITS (bit_buf, 1)]; + +    // TODO field select may need to do something here for bob (weave ok) +    picture->XvMC_mv_field_sel[0][0] = picture->XvMC_mv_field_sel[1][0] = 0; + +    DUMPBITS (bit_buf, bits, 1); + +    motion_x = motion->pmv[1][0] + get_xvmc_motion_delta (picture, +						     motion->f_code[0]); +    motion_x = bound_motion_vector (motion_x, motion->f_code[0]); +    motion->pmv[1][0] = motion_x; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_y = motion->pmv[1][1] + get_xvmc_motion_delta (picture, +						     motion->f_code[1]); +    motion_y = bound_motion_vector (motion_y, motion->f_code[1]); +    motion->pmv[1][1] = motion_y; + +    MOTION (table, ref_field, motion_x, motion_y, 8, 8); +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void motion_fi_dmv (picture_t * picture, motion_t * motion, +			   void (** table) (uint8_t *, uint8_t *, int, int)) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int motion_x, motion_y, other_x, other_y; +    unsigned int pos_x, pos_y, xy_half; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    motion_x = motion->pmv[0][0] + get_xvmc_motion_delta (picture, +						     motion->f_code[0]); +    motion_x = bound_motion_vector (motion_x, motion->f_code[0]); +    motion->pmv[1][0] = motion->pmv[0][0] = motion_x; +    NEEDBITS (bit_buf, bits, bit_ptr); +    other_x = ((motion_x + (motion_x > 0)) >> 1) + get_xvmc_dmv (picture); + +    motion_y = motion->pmv[0][1] + get_xvmc_motion_delta (picture, +						     motion->f_code[1]); +    motion_y = bound_motion_vector (motion_y, motion->f_code[1]); +    motion->pmv[1][1] = motion->pmv[0][1] = motion_y; +    other_y = (((motion_y + (motion_y > 0)) >> 1) + get_xvmc_dmv (picture) + +	       picture->dmv_offset); + +    // TODO field select may need to do something here for bob  (weave ok) +    picture->XvMC_mv_field_sel[0][0] = picture->XvMC_mv_field_sel[1][0] = 0; + +    MOTION (mpeg2_mc.put, motion->ref[0], motion_x, motion_y, 16, 0); +    MOTION (mpeg2_mc.avg, motion->ref[1], other_x, other_y, 16, 0); +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void motion_fi_conceal (picture_t * picture) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int tmp; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    DUMPBITS (bit_buf, bits, 1); /* remove field_select */ + +    tmp = (picture->f_motion.pmv[0][0] + +	   get_xvmc_motion_delta (picture, picture->f_motion.f_code[0])); +    tmp = bound_motion_vector (tmp, picture->f_motion.f_code[0]); +    picture->f_motion.pmv[1][0] = picture->f_motion.pmv[0][0] = tmp; + +    NEEDBITS (bit_buf, bits, bit_ptr); +    tmp = (picture->f_motion.pmv[0][1] + +	   get_xvmc_motion_delta (picture, picture->f_motion.f_code[1])); +    tmp = bound_motion_vector (tmp, picture->f_motion.f_code[1]); +    picture->f_motion.pmv[1][1] = picture->f_motion.pmv[0][1] = tmp; + +    DUMPBITS (bit_buf, bits, 1); /* remove marker_bit */ +#undef bit_buf +#undef bits +#undef bit_ptr +} + +#define MOTION_CALL(routine,direction)				\ +do {								\ +    if ((direction) & MACROBLOCK_MOTION_FORWARD)		\ +	routine (picture, &(picture->f_motion), mpeg2_mc.put);	\ +    if ((direction) & MACROBLOCK_MOTION_BACKWARD)		\ +	routine (picture, &(picture->b_motion),			\ +		 ((direction) & MACROBLOCK_MOTION_FORWARD ?	\ +		  mpeg2_mc.avg : mpeg2_mc.put));		\ +} while (0) + +#define NEXT_MACROBLOCK							\ +do {									\ +    picture->offset += 16;						\ +    if (picture->offset == picture->coded_picture_width) {		\ +	do { /* just so we can use the break statement */		\ +	    if (picture->current_frame->copy) {				\ +		picture->current_frame->copy (picture->current_frame,	\ +					      picture->dest);		\ +		if (picture->picture_coding_type == B_TYPE)		\ +		    break;						\ +	    }								\ +	    picture->dest[0] += 16 * picture->pitches[0];		\ +	    picture->dest[1] += 8 * picture->pitches[1];		\ +	    picture->dest[2] += 8 * picture->pitches[2];		\ +	} while (0);							\ +	picture->v_offset += 16;					\ +	if (picture->v_offset > picture->limit_y) {			\ +	    if (mpeg2_cpu_state_restore)				\ +		mpeg2_cpu_state_restore (&cpu_state);			\ +	    return;							\ +	}								\ +	picture->offset = 0;						\ +    }									\ +} while (0) + +static inline int slice_xvmc_init (picture_t * picture, int code) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    int offset, height; +    struct vo_frame_s * forward_reference_frame; +    struct vo_frame_s * backward_reference_frame; +    MBAtab * mba; + +    offset = picture->picture_structure == BOTTOM_FIELD; +    picture->pitches[0] = picture->current_frame->pitches[0]; +    picture->pitches[1] = picture->current_frame->pitches[1]; +    picture->pitches[2] = picture->current_frame->pitches[2]; + +    if( picture->forward_reference_frame ) { +        forward_reference_frame = picture->forward_reference_frame; +    } +    else { +        /* return 1; */ +        forward_reference_frame = picture->current_frame; +    } +     +    if( picture->backward_reference_frame ) { +        backward_reference_frame = picture->backward_reference_frame; +    } +    else { +        /* return 1; */ +        backward_reference_frame = picture->current_frame; +    } +     +    picture->f_motion.ref[0][0] = +        forward_reference_frame->base[0] + (offset ? picture->pitches[0] : 0); +    picture->f_motion.ref[0][1] = +        forward_reference_frame->base[1] + (offset ? picture->pitches[1] : 0); +    picture->f_motion.ref[0][2] = +        forward_reference_frame->base[2] + (offset ? picture->pitches[2] : 0); +     +    picture->b_motion.ref[0][0] = +	backward_reference_frame->base[0] + (offset ? picture->pitches[0] : 0); +    picture->b_motion.ref[0][1] = +	backward_reference_frame->base[1] + (offset ? picture->pitches[1] : 0); +    picture->b_motion.ref[0][2] = +	backward_reference_frame->base[2] + (offset ? picture->pitches[2] : 0); +     +    if (picture->picture_structure != FRAME_PICTURE) { +	uint8_t ** forward_ref; +	int bottom_field; + +	bottom_field = (picture->picture_structure == BOTTOM_FIELD); +	picture->dmv_offset = bottom_field ? 1 : -1; +	picture->f_motion.ref2[0] = picture->f_motion.ref[bottom_field]; +	picture->f_motion.ref2[1] = picture->f_motion.ref[!bottom_field]; +	picture->b_motion.ref2[0] = picture->b_motion.ref[bottom_field]; +	picture->b_motion.ref2[1] = picture->b_motion.ref[!bottom_field]; + +	forward_ref = forward_reference_frame->base; +	if (picture->second_field && (picture->picture_coding_type != B_TYPE)) +	    forward_ref = picture->current_frame->base; + +	picture->f_motion.ref[1][0] = forward_ref[0] + (bottom_field ? 0 : picture->pitches[0]); +	picture->f_motion.ref[1][1] = forward_ref[1] + (bottom_field ? 0 : picture->pitches[1]); +	picture->f_motion.ref[1][2] = forward_ref[2] + (bottom_field ? 0 : picture->pitches[2]); + +	picture->b_motion.ref[1][0] = +	    backward_reference_frame->base[0] + (bottom_field ? 0 : picture->pitches[0]); +	picture->b_motion.ref[1][1] = +	    backward_reference_frame->base[1] + (bottom_field ? 0 : picture->pitches[1]); +	picture->b_motion.ref[1][2] = +	    backward_reference_frame->base[2] + (bottom_field ? 0 : picture->pitches[2]); +    } + +    picture->f_motion.pmv[0][0] = picture->f_motion.pmv[0][1] = 0; +    picture->f_motion.pmv[1][0] = picture->f_motion.pmv[1][1] = 0; +    picture->b_motion.pmv[0][0] = picture->b_motion.pmv[0][1] = 0; +    picture->b_motion.pmv[1][0] = picture->b_motion.pmv[1][1] = 0; + +    picture->v_offset = (code - 1) * 16; +    offset = (code - 1); +    if (picture->current_frame->copy && picture->picture_coding_type == B_TYPE) +	offset = 0; +    else if (picture->picture_structure != FRAME_PICTURE) +	offset = 2 * offset; + +    picture->dest[0] = picture->current_frame->base[0] + picture->pitches[0] * offset * 16; +    picture->dest[1] = picture->current_frame->base[1] + picture->pitches[1] * offset * 8; +    picture->dest[2] = picture->current_frame->base[2] + picture->pitches[2] * offset * 8; + +    height = picture->coded_picture_height; +    switch (picture->picture_structure) { +    case BOTTOM_FIELD: +	picture->dest[0] += picture->pitches[0]; +	picture->dest[1] += picture->pitches[1]; +	picture->dest[2] += picture->pitches[2]; +	/* follow thru */ +    case TOP_FIELD: +	picture->pitches[0] <<= 1; +	picture->pitches[1] <<= 1; +	picture->pitches[2] <<= 1; +	height >>= 1; +    } +    picture->limit_x = 2 * picture->coded_picture_width - 32; +    picture->limit_y_16 = 2 * height - 32; +    picture->limit_y_8 = 2 * height - 16; +    picture->limit_y = height - 16; + +    //TODO conversion to signed format signed format +    if(picture->mc->xvmc_accel == MOTION_ACCEL) { +      //Motion Comp only unsigned intra +      // original: +      picture->dc_dct_pred[0] = picture->dc_dct_pred[1] = +	picture->dc_dct_pred[2] = 1 << (picture->intra_dc_precision + 7); +    } else { +      //Motion Comp only signed intra  MOTION_ACCEL+SIGNED_INTRA +      picture->dc_dct_pred[0] = picture->dc_dct_pred[1] = +	picture->dc_dct_pred[2] = 0; +    } + +    picture->quantizer_scale = get_xvmc_quantizer_scale (picture); + +    /* ignore intra_slice and all the extra data */ +    while (bit_buf & 0x80000000) { +	DUMPBITS (bit_buf, bits, 9); +	NEEDBITS (bit_buf, bits, bit_ptr); +    } + +    /* decode initial macroblock address increment */ +    offset = 0; +    while (1) { +	if (bit_buf >= 0x08000000) { +	    mba = MBA_5 + (UBITS (bit_buf, 6) - 2); +	    break; +	} else if (bit_buf >= 0x01800000) { +	    mba = MBA_11 + (UBITS (bit_buf, 12) - 24); +	    break; +	} else switch (UBITS (bit_buf, 12)) { +	case 8:		/* macroblock_escape */ +	    offset += 33; +	    DUMPBITS (bit_buf, bits, 11); +	    NEEDBITS (bit_buf, bits, bit_ptr); +	    continue; +	case 15:	/* macroblock_stuffing (MPEG1 only) */ +	    bit_buf &= 0xfffff; +	    DUMPBITS (bit_buf, bits, 11); +	    NEEDBITS (bit_buf, bits, bit_ptr); +	    continue; +	default:	/* error */ +	    return 1; +	} +    } +    DUMPBITS (bit_buf, bits, mba->len + 1); +    picture->offset = (offset + mba->mba) << 4; + +    while (picture->offset - picture->coded_picture_width >= 0) { +	picture->offset -= picture->coded_picture_width; +	if ((picture->current_frame->copy == NULL) || +	    (picture->picture_coding_type != B_TYPE)) { +	    picture->dest[0] += 16 * picture->pitches[0]; +	    picture->dest[1] += 8 * picture->pitches[1]; +	    picture->dest[2] += 8 * picture->pitches[2]; +	} +	picture->v_offset += 16; +    } +    if (picture->v_offset > picture->limit_y) +	return 1; + +    return 0; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +void mpeg2_xvmc_slice (picture_t * picture, int code, uint8_t * buffer) +{ +#define bit_buf (picture->bitstream_buf) +#define bits (picture->bitstream_bits) +#define bit_ptr (picture->bitstream_ptr) +    cpu_state_t cpu_state; + +    bitstream_init (picture, buffer); + +    if (slice_xvmc_init (picture, code)) +	return; + +    if (mpeg2_cpu_state_save) +	mpeg2_cpu_state_save (&cpu_state); + +    while (1) { +	int macroblock_modes; +	int mba_inc; +	MBAtab * mba; + +	NEEDBITS (bit_buf, bits, bit_ptr); + +	macroblock_modes = get_xvmc_macroblock_modes (picture); //macroblock_modes() +	picture->XvMC_mb_type = macroblock_modes & 0x1F; +	picture->XvMC_dct_type = (macroblock_modes & DCT_TYPE_INTERLACED)>>5; +	picture->XvMC_motion_type = (macroblock_modes & MOTION_TYPE_MASK)>>6; + +	picture->XvMC_x = picture->offset/16; +	picture->XvMC_y = picture->v_offset/16; + +	if((picture->XvMC_x == 0) && (picture->XvMC_y == 0)) { +	  picture->XvMC_mv_field_sel[0][0] =  +	    picture->XvMC_mv_field_sel[1][0] =  +	    picture->XvMC_mv_field_sel[0][1] =  +	    picture->XvMC_mv_field_sel[1][1] = 0; +	} + +	picture->XvMC_cbp = 0x3f;  //TODO set for intra 4:2:0 6 blocks yyyyuv all enabled + +	/* maybe integrate MACROBLOCK_QUANT test into get_xvmc_macroblock_modes ? */ +	if (macroblock_modes & MACROBLOCK_QUANT) +	    picture->quantizer_scale = get_xvmc_quantizer_scale (picture); +	if (macroblock_modes & MACROBLOCK_INTRA) { + +	    int DCT_offset, DCT_stride; +	    int offset; +	    uint8_t * dest_y; + +	    if (picture->concealment_motion_vectors) { +		if (picture->picture_structure == FRAME_PICTURE) +		    motion_fr_conceal (picture); +		else +		    motion_fi_conceal (picture); +	    } else { +		picture->f_motion.pmv[0][0] = picture->f_motion.pmv[0][1] = 0; +		picture->f_motion.pmv[1][0] = picture->f_motion.pmv[1][1] = 0; +		picture->b_motion.pmv[0][0] = picture->b_motion.pmv[0][1] = 0; +		picture->b_motion.pmv[1][0] = picture->b_motion.pmv[1][1] = 0; +	    } + +	    if (macroblock_modes & DCT_TYPE_INTERLACED) { +		DCT_offset = picture->pitches[0]; +		DCT_stride = picture->pitches[0] * 2; +	    } else { +		DCT_offset = picture->pitches[0] * 8; +		DCT_stride = picture->pitches[0]; +	    } +	    offset = picture->offset; +	    dest_y = picture->dest[0] + offset; +	    // unravaled loop of 6 block(i) calls in macroblock() +	    slice_xvmc_intra_DCT (picture, 0, dest_y, DCT_stride); +	    slice_xvmc_intra_DCT (picture, 0, dest_y + 8, DCT_stride); +	    slice_xvmc_intra_DCT (picture, 0, dest_y + DCT_offset, DCT_stride); +	    slice_xvmc_intra_DCT (picture, 0, dest_y + DCT_offset + 8, DCT_stride); +	    slice_xvmc_intra_DCT (picture, 1, picture->dest[1] + (offset >> 1), +			     picture->pitches[1]); +	    slice_xvmc_intra_DCT (picture, 2, picture->dest[2] + (offset >> 1), +			     picture->pitches[2]); + +	    if (picture->picture_coding_type == D_TYPE) { +		NEEDBITS (bit_buf, bits, bit_ptr); +		DUMPBITS (bit_buf, bits, 1); +	    } +	} else { +	    picture->XvMC_cbp = 0; + +	    if (picture->picture_structure == FRAME_PICTURE) +		switch (macroblock_modes & MOTION_TYPE_MASK) { +		case MC_FRAME: +		    if (picture->mpeg1) { +			MOTION_CALL (motion_mp1, macroblock_modes); +		    } else { +			MOTION_CALL (motion_fr_frame, macroblock_modes); +		    } +		    break; + +		case MC_FIELD: +		    //MOTION_CALL (motion_fr_field, macroblock_modes); + +		    if ((macroblock_modes) & MACROBLOCK_MOTION_FORWARD) +		      motion_fr_field(picture, &(picture->f_motion), +				       mpeg2_mc.put,0); +		    if ((macroblock_modes) & MACROBLOCK_MOTION_BACKWARD) +		      motion_fr_field(picture, &(picture->b_motion), +			     ((macroblock_modes) & MACROBLOCK_MOTION_FORWARD ? +				mpeg2_mc.avg : mpeg2_mc.put),1); + +		    break; + +		case MC_DMV: +		    MOTION_CALL (motion_fr_dmv, MACROBLOCK_MOTION_FORWARD); +		    break; + +		case 0: +		    /* non-intra mb without forward mv in a P picture */ +		    picture->f_motion.pmv[0][0] = 0; +		    picture->f_motion.pmv[0][1] = 0; +		    picture->f_motion.pmv[1][0] = 0; +		    picture->f_motion.pmv[1][1] = 0; +		    //	 MOTION_CALL (motion_zero, MACROBLOCK_MOTION_FORWARD); +		    break; +		} +	    else +		switch (macroblock_modes & MOTION_TYPE_MASK) { +		case MC_FIELD: +		    MOTION_CALL (motion_fi_field, macroblock_modes); +		    break; + +		case MC_16X8: +		    MOTION_CALL (motion_fi_16x8, macroblock_modes); +		    break; + +		case MC_DMV: +		    MOTION_CALL (motion_fi_dmv, MACROBLOCK_MOTION_FORWARD); +		    break; + +		case 0: +		    /* non-intra mb without forward mv in a P picture */ +		    picture->f_motion.pmv[0][0] = 0; +		    picture->f_motion.pmv[0][1] = 0; +		    picture->f_motion.pmv[1][0] = 0; +		    picture->f_motion.pmv[1][1] = 0; +		    //	 MOTION_CALL (motion_zero, MACROBLOCK_MOTION_FORWARD); +		    break; +		} + +	    if (macroblock_modes & MACROBLOCK_PATTERN) { +		int coded_block_pattern; +		int DCT_offset, DCT_stride; +		int offset; +		uint8_t * dest_y; + +		if (macroblock_modes & DCT_TYPE_INTERLACED) { +		    DCT_offset = picture->pitches[0]; +		    DCT_stride = picture->pitches[0] * 2; +		} else { +		    DCT_offset = picture->pitches[0] * 8; +		    DCT_stride = picture->pitches[0]; +		} + +		picture->XvMC_cbp = coded_block_pattern = get_xvmc_coded_block_pattern (picture); +		offset = picture->offset; +		dest_y = picture->dest[0] + offset; +		// TODO  optimize not fully used for idct accel only mc. +		if (coded_block_pattern & 0x20) +		    slice_xvmc_non_intra_DCT (picture, dest_y, DCT_stride); //  cc0  luma 0 +		if (coded_block_pattern & 0x10) +		    slice_xvmc_non_intra_DCT (picture, dest_y + 8, DCT_stride); // cc0 luma 1 +		if (coded_block_pattern & 0x08) +		    slice_xvmc_non_intra_DCT (picture, dest_y + DCT_offset, +					 DCT_stride); // cc0 luma 2 +		if (coded_block_pattern & 0x04) +		    slice_xvmc_non_intra_DCT (picture, dest_y + DCT_offset + 8, +					 DCT_stride); // cc0 luma 3 +		if (coded_block_pattern & 0x2) +		    slice_xvmc_non_intra_DCT (picture, +					 picture->dest[1] + (offset >> 1), +					 picture->pitches[1]); // cc1 croma  +		if (coded_block_pattern & 0x1) +		    slice_xvmc_non_intra_DCT (picture, +					 picture->dest[2] + (offset >> 1), +					 picture->pitches[2]); // cc2 croma +	    } + +	    if(picture->mc->xvmc_accel == MOTION_ACCEL) { +	        // original: +	        picture->dc_dct_pred[0] = picture->dc_dct_pred[1] = +		    picture->dc_dct_pred[2] = 128 << picture->intra_dc_precision; + +	    } else { // MOTION_ACCEL+SIGNED_INTRA +	        picture->dc_dct_pred[0] = picture->dc_dct_pred[1] = +		    picture->dc_dct_pred[2] = 0; +	    } + +	} +	picture->current_frame->proc_macro_block(picture->XvMC_x, picture->XvMC_y, +					 picture->XvMC_mb_type, +					 picture->XvMC_motion_type, +					 picture->XvMC_mv_field_sel, +					 picture->XvMC_dmvector, +					 picture->XvMC_cbp, +					 picture->XvMC_dct_type, +					 picture->current_frame, +					 picture->forward_reference_frame, +					 picture->backward_reference_frame, +					 picture->picture_structure, +					 picture->second_field, +				         picture->f_motion.pmv, +				         picture->b_motion.pmv); + + +	NEXT_MACROBLOCK; + +	NEEDBITS (bit_buf, bits, bit_ptr); +	mba_inc = 0; +	while (1) { +	    if (bit_buf >= 0x10000000) { +		mba = MBA_5 + (UBITS (bit_buf, 5) - 2); +		break; +	    } else if (bit_buf >= 0x03000000) { +		mba = MBA_11 + (UBITS (bit_buf, 11) - 24); +		break; +	    } else switch (UBITS (bit_buf, 11)) { +	    case 8:		/* macroblock_escape */ +		mba_inc += 33; +		/* pass through */ +	    case 15:	/* macroblock_stuffing (MPEG1 only) */ +		DUMPBITS (bit_buf, bits, 11); +		NEEDBITS (bit_buf, bits, bit_ptr); +		continue; +	    default:	/* end of slice, or error */ +		if (mpeg2_cpu_state_restore) +		    mpeg2_cpu_state_restore (&cpu_state); +		return; +	    } +	} +	DUMPBITS (bit_buf, bits, mba->len); +	mba_inc += mba->mba; +	if (mba_inc) { +	    //TODO  conversion to signed format signed format +	  if(picture->mc->xvmc_accel == MOTION_ACCEL) { +	    // original: +	    picture->dc_dct_pred[0] = picture->dc_dct_pred[1] = +	      picture->dc_dct_pred[2] = 128 << picture->intra_dc_precision; +	  } else { // MOTION_ACCEL+SIGNED_INTRA +	    picture->dc_dct_pred[0] = picture->dc_dct_pred[1] = +	      picture->dc_dct_pred[2] = 0; +	  } + +	    picture->XvMC_cbp = 0;  +	    if (picture->picture_coding_type == P_TYPE) { +		picture->f_motion.pmv[0][0] = picture->f_motion.pmv[0][1] = 0; +		picture->f_motion.pmv[1][0] = picture->f_motion.pmv[1][1] = 0; + +		do { +		    if(picture->mc->xvmc_accel) { + +		        /* derive motion_type */ +		        if(picture->picture_structure == FRAME_PICTURE) { +			  picture->XvMC_motion_type = XINE_MC_FRAME; +			} else { +			  picture->XvMC_motion_type = XINE_MC_FIELD; +			  /* predict from field of same parity */ +			  picture->XvMC_mv_field_sel[0][0] = +			    picture->XvMC_mv_field_sel[0][1] = +			      (picture->picture_structure==BOTTOM_FIELD); +			} +			picture->XvMC_mb_type = macroblock_modes & 0x1E; +			picture->XvMC_x = picture->offset/16; +			picture->XvMC_y = picture->v_offset/16; + +			picture->current_frame->proc_macro_block(picture->XvMC_x,picture->XvMC_y, +					 picture->XvMC_mb_type, +					 picture->XvMC_motion_type, +					 picture->XvMC_mv_field_sel, +					 picture->XvMC_dmvector, +					 picture->XvMC_cbp, +					 picture->XvMC_dct_type, +					 picture->current_frame, +					 picture->forward_reference_frame, +					 picture->backward_reference_frame, +					 picture->picture_structure, +					 picture->second_field, +				         picture->f_motion.pmv, +				         picture->b_motion.pmv); +		    } else { +		      // MOTION_CALL (motion_zero, MACROBLOCK_MOTION_FORWARD); +		    } +		    NEXT_MACROBLOCK; +		} while (--mba_inc); +	    } else { +		do { +		    if(picture->mc->xvmc_accel) { + +		        /* derive motion_type */ +		        if(picture->picture_structure == FRAME_PICTURE) { +			  picture->XvMC_motion_type = XINE_MC_FRAME; +			} else { +			  picture->XvMC_motion_type = XINE_MC_FIELD; +			  /* predict from field of same parity */ +			  picture->XvMC_mv_field_sel[0][0] = +			    picture->XvMC_mv_field_sel[0][1] = +			      (picture->picture_structure==BOTTOM_FIELD); +			} + +			picture->XvMC_mb_type = macroblock_modes & 0x1E; + +			picture->XvMC_x = picture->offset/16; +			picture->XvMC_y = picture->v_offset/16; + +			picture->current_frame->proc_macro_block(picture->XvMC_x,picture->XvMC_y, +					 picture->XvMC_mb_type, +					 picture->XvMC_motion_type, +					 picture->XvMC_mv_field_sel, +					 picture->XvMC_dmvector, +					 picture->XvMC_cbp, +					 picture->XvMC_dct_type, +					 picture->current_frame, +					 picture->forward_reference_frame, +					 picture->backward_reference_frame, +					 picture->picture_structure, +					 picture->second_field, +				         picture->f_motion.pmv, +				         picture->b_motion.pmv); +		    } else { +		        MOTION_CALL (motion_reuse, macroblock_modes); +		    } +		    NEXT_MACROBLOCK; +		} while (--mba_inc); +	    } +	} +    } +#undef bit_buf +#undef bits +#undef bit_ptr +} + diff --git a/src/libmpeg2/xine_decoder.c b/src/libmpeg2/xine_decoder.c index 7b1313e85..5d2b91df7 100644 --- a/src/libmpeg2/xine_decoder.c +++ b/src/libmpeg2/xine_decoder.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: xine_decoder.c,v 1.49 2003/08/05 15:09:23 mroi Exp $ + * $Id: xine_decoder.c,v 1.50 2003/10/06 21:52:43 miguelfreitas Exp $   *   * stuff needed to turn libmpeg2 into a xine decoder plugin   */ @@ -137,7 +137,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre    this->class                             = (mpeg2_class_t *) class_gen;    this->mpeg2.stream = stream; -  mpeg2_init (&this->mpeg2); +  mpeg2_init (&this->mpeg2, stream->video_out);    stream->video_out->open(stream->video_out, stream);    this->mpeg2.force_aspect = this->mpeg2.force_pan_scan = 0; diff --git a/src/post/deinterlace/xine_plugin.c b/src/post/deinterlace/xine_plugin.c index 5558231f7..5569039cc 100644 --- a/src/post/deinterlace/xine_plugin.c +++ b/src/post/deinterlace/xine_plugin.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: xine_plugin.c,v 1.13 2003/08/15 14:43:29 mroi Exp $ + * $Id: xine_plugin.c,v 1.14 2003/10/06 21:52:43 miguelfreitas Exp $   *   * advanced video deinterlacer plugin   * Jun/2003 by Miguel Freitas @@ -44,7 +44,7 @@ post_info_t deinterlace_special_info = { XINE_POST_TYPE_VIDEO_FILTER };  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 4, "tvtime", XINE_VERSION_CODE, &deinterlace_special_info, &deinterlace_init_plugin }, +  { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 5, "tvtime", XINE_VERSION_CODE, &deinterlace_special_info, &deinterlace_init_plugin },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/post/goom/xine_goom.c b/src/post/goom/xine_goom.c index c5b48ed73..f124ead07 100644 --- a/src/post/goom/xine_goom.c +++ b/src/post/goom/xine_goom.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: xine_goom.c,v 1.35 2003/09/14 15:45:55 tmattern Exp $ + * $Id: xine_goom.c,v 1.36 2003/10/06 21:52:43 miguelfreitas Exp $   *   * GOOM post plugin.   * @@ -122,7 +122,7 @@ post_info_t goom_special_info = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 4, "goom", XINE_VERSION_CODE, &goom_special_info, &goom_init_plugin }, +  { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 5, "goom", XINE_VERSION_CODE, &goom_special_info, &goom_init_plugin },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/post/mosaico/mosaico.c b/src/post/mosaico/mosaico.c index 7a1d5eec9..8b095769c 100644 --- a/src/post/mosaico/mosaico.c +++ b/src/post/mosaico/mosaico.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: mosaico.c,v 1.13 2003/08/12 13:56:25 mroi Exp $ + * $Id: mosaico.c,v 1.14 2003/10/06 21:52:43 miguelfreitas Exp $   */  /* @@ -47,7 +47,7 @@ post_info_t mosaico_special_info = { XINE_POST_TYPE_VIDEO_COMPOSE };  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "mosaico", MOVERSION, &mosaico_special_info, &mosaico_init_plugin }, +  { PLUGIN_POST, 5, "mosaico", MOVERSION, &mosaico_special_info, &mosaico_init_plugin },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/post/mosaico/switch.c b/src/post/mosaico/switch.c index cbe2335af..694db8697 100644 --- a/src/post/mosaico/switch.c +++ b/src/post/mosaico/switch.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: switch.c,v 1.5 2003/08/12 13:56:25 mroi Exp $ + * $Id: switch.c,v 1.6 2003/10/06 21:52:43 miguelfreitas Exp $   */  /* @@ -41,7 +41,7 @@ post_info_t switch_special_info = { XINE_POST_TYPE_VIDEO_COMPOSE };  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "switch", SWVERSION, &switch_special_info, &switch_init_plugin }, +  { PLUGIN_POST, 5, "switch", SWVERSION, &switch_special_info, &switch_init_plugin },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/post/planar/boxblur.c b/src/post/planar/boxblur.c index 5be693e33..7ec51bc55 100644 --- a/src/post/planar/boxblur.c +++ b/src/post/planar/boxblur.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: boxblur.c,v 1.6 2003/08/15 14:43:29 mroi Exp $ + * $Id: boxblur.c,v 1.7 2003/10/06 21:52:43 miguelfreitas Exp $   *   * mplayer's boxblur   * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at> @@ -31,17 +31,6 @@  /* plugin class initialization function */  void *boxblur_init_plugin(xine_t *xine, void *); -#if 0 /* moved to planar.c */ -/* plugin catalog information */ -post_info_t boxblur_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; - -plugin_info_t xine_plugin_info[] = { -  /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "boxblur", XINE_VERSION_CODE, &boxblur_special_info, &boxblur_init_plugin }, -  { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; -#endif -  typedef struct post_plugin_boxblur_s post_plugin_boxblur_t;  /* diff --git a/src/post/planar/denoise3d.c b/src/post/planar/denoise3d.c index 47570d4a9..024cba960 100644 --- a/src/post/planar/denoise3d.c +++ b/src/post/planar/denoise3d.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: denoise3d.c,v 1.6 2003/08/15 14:43:30 mroi Exp $ + * $Id: denoise3d.c,v 1.7 2003/10/06 21:52:43 miguelfreitas Exp $   *   * mplayer's denoise3d   * Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org> @@ -38,18 +38,6 @@  /* plugin class initialization function */  void *denoise3d_init_plugin(xine_t *xine, void *); - -#if 0 /* moved to planar.c */ -/* plugin catalog information */ -post_info_t denoise3d_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; - -plugin_info_t xine_plugin_info[] = { -  /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "denoise3d", XINE_VERSION_CODE, &denoise3d_special_info, &denoise3d_init_plugin }, -  { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; -#endif -  typedef struct post_plugin_denoise3d_s post_plugin_denoise3d_t; diff --git a/src/post/planar/eq.c b/src/post/planar/eq.c index e51fffe6d..e5991e7ea 100644 --- a/src/post/planar/eq.c +++ b/src/post/planar/eq.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: eq.c,v 1.5 2003/08/15 14:43:30 mroi Exp $ + * $Id: eq.c,v 1.6 2003/10/06 21:52:43 miguelfreitas Exp $   *   * mplayer's eq (soft video equalizer)   * Copyright (C) Richard Felker @@ -119,16 +119,6 @@ static void (*process)(unsigned char *dest, int dstride, unsigned char *src, int  /* plugin class initialization function */  void *eq_init_plugin(xine_t *xine, void *); -#if 0 /* moved to planar.c */ -/* plugin catalog information */ -post_info_t eq_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; - -plugin_info_t xine_plugin_info[] = { -  /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "eq", XINE_VERSION_CODE, &eq_special_info, &eq_init_plugin }, -  { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; -#endif  typedef struct post_plugin_eq_s post_plugin_eq_t; diff --git a/src/post/planar/eq2.c b/src/post/planar/eq2.c index a02303e55..866f3083b 100644 --- a/src/post/planar/eq2.c +++ b/src/post/planar/eq2.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: eq2.c,v 1.7 2003/08/19 18:33:43 mroi Exp $ + * $Id: eq2.c,v 1.8 2003/10/06 21:52:43 miguelfreitas Exp $   *   * mplayer's eq2 (soft video equalizer)   * Software equalizer (brightness, contrast, gamma, saturation) @@ -264,17 +264,6 @@ void set_saturation (vf_eq2_t *eq2, double s)  /* plugin class initialization function */  void *eq2_init_plugin(xine_t *xine, void *); -#if 0 /* moved to planar.c */ -/* plugin catalog information */ -post_info_t eq2_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; - -plugin_info_t xine_plugin_info[] = { -  /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "eq2", XINE_VERSION_CODE, &eq2_special_info, &eq2_init_plugin }, -  { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; -#endif -  typedef struct post_plugin_eq2_s post_plugin_eq2_t;  /* diff --git a/src/post/planar/expand.c b/src/post/planar/expand.c index 91b1d15c4..ea7a6ee60 100644 --- a/src/post/planar/expand.c +++ b/src/post/planar/expand.c @@ -61,17 +61,6 @@  /* plugin class initialization function */  void *expand_init_plugin(xine_t *xine, void *); -#if 0 /* moved to planar.c */ -/* plugin catalog information */ -post_info_t expand_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; - -plugin_info_t xine_plugin_info[] = { -  /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "expand", XINE_VERSION_CODE, &expand_special_info, &expand_init_plugin }, -  { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; -#endif -  /* plugin structures */  typedef struct expand_parameters_s {    int enable_automatic_shift; diff --git a/src/post/planar/invert.c b/src/post/planar/invert.c index c81d3e12a..26bc4b7b9 100644 --- a/src/post/planar/invert.c +++ b/src/post/planar/invert.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: invert.c,v 1.12 2003/08/12 13:56:26 mroi Exp $ + * $Id: invert.c,v 1.13 2003/10/06 21:52:43 miguelfreitas Exp $   */  /* @@ -31,19 +31,6 @@  /* plugin class initialization function */  void *invert_init_plugin(xine_t *xine, void *); -#if 0 /* moved to planar.c */ - -/* plugin catalog information */ -post_info_t invert_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; - -plugin_info_t xine_plugin_info[] = { -  /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "invert", XINE_VERSION_CODE, &invert_special_info, &invert_init_plugin }, -  { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; - -#endif -  /* plugin structure */  typedef struct post_invert_out_s post_invert_out_t;  struct post_invert_out_s { diff --git a/src/post/planar/planar.c b/src/post/planar/planar.c index 7ab3ad521..89f9e76bb 100644 --- a/src/post/planar/planar.c +++ b/src/post/planar/planar.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: planar.c,v 1.2 2003/08/04 03:47:11 miguelfreitas Exp $ + * $Id: planar.c,v 1.3 2003/10/06 21:52:44 miguelfreitas Exp $   *   * catalog for planar post plugins   */ @@ -49,13 +49,13 @@ post_info_t unsharp_special_info = { XINE_POST_TYPE_VIDEO_FILTER };  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "expand", XINE_VERSION_CODE+1, &expand_special_info, &expand_init_plugin }, -  { PLUGIN_POST, 4, "invert", XINE_VERSION_CODE+1, &invert_special_info, &invert_init_plugin }, -  { PLUGIN_POST, 4, "eq", XINE_VERSION_CODE, &eq_special_info, &eq_init_plugin }, -  { PLUGIN_POST, 4, "denoise3d", XINE_VERSION_CODE, &denoise3d_special_info, &denoise3d_init_plugin }, -  { PLUGIN_POST, 4, "boxblur", XINE_VERSION_CODE, &boxblur_special_info, &boxblur_init_plugin }, -  { PLUGIN_POST, 4, "eq2", XINE_VERSION_CODE, &eq2_special_info, &eq2_init_plugin }, -  { PLUGIN_POST, 4, "unsharp", XINE_VERSION_CODE, &unsharp_special_info, &unsharp_init_plugin }, +  { PLUGIN_POST, 5, "expand", XINE_VERSION_CODE+1, &expand_special_info, &expand_init_plugin }, +  { PLUGIN_POST, 5, "invert", XINE_VERSION_CODE+1, &invert_special_info, &invert_init_plugin }, +  { PLUGIN_POST, 5, "eq", XINE_VERSION_CODE, &eq_special_info, &eq_init_plugin }, +  { PLUGIN_POST, 5, "denoise3d", XINE_VERSION_CODE, &denoise3d_special_info, &denoise3d_init_plugin }, +  { PLUGIN_POST, 5, "boxblur", XINE_VERSION_CODE, &boxblur_special_info, &boxblur_init_plugin }, +  { PLUGIN_POST, 5, "eq2", XINE_VERSION_CODE, &eq2_special_info, &eq2_init_plugin }, +  { PLUGIN_POST, 5, "unsharp", XINE_VERSION_CODE, &unsharp_special_info, &unsharp_init_plugin },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/post/planar/unsharp.c b/src/post/planar/unsharp.c index 61defa672..499fba98f 100644 --- a/src/post/planar/unsharp.c +++ b/src/post/planar/unsharp.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: unsharp.c,v 1.6 2003/08/15 14:43:30 mroi Exp $ + * $Id: unsharp.c,v 1.7 2003/10/06 21:52:44 miguelfreitas Exp $   *   * mplayer's unsharp   * Copyright (C) 2002 Rémi Guyomarch <rguyom@pobox.com> @@ -130,17 +130,6 @@ static void unsharp( uint8_t *dst, uint8_t *src, int dstStride, int srcStride, i  /* plugin class initialization function */  void *unsharp_init_plugin(xine_t *xine, void *); -#if 0 /* moved to planar.c */ -/* plugin catalog information */ -post_info_t unsharp_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; - -plugin_info_t xine_plugin_info[] = { -  /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "unsharp", XINE_VERSION_CODE, &unsharp_special_info, &unsharp_init_plugin }, -  { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; -#endif -  typedef struct post_plugin_unsharp_s post_plugin_unsharp_t;  /* diff --git a/src/post/visualizations/fooviz.c b/src/post/visualizations/fooviz.c index 505a10bc6..1f0f93c33 100644 --- a/src/post/visualizations/fooviz.c +++ b/src/post/visualizations/fooviz.c @@ -23,7 +23,7 @@   * process. It simply paints the screen a solid color and rotates through   * colors on each iteration.   * - * $Id: fooviz.c,v 1.9 2003/08/04 03:47:11 miguelfreitas Exp $ + * $Id: fooviz.c,v 1.10 2003/10/06 21:52:44 miguelfreitas Exp $   *   */ @@ -373,6 +373,6 @@ post_info_t fooviz_special_info = { XINE_POST_TYPE_AUDIO_VISUALIZATION };  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_POST, 4, "fooviz", XINE_VERSION_CODE, &fooviz_special_info, &fooviz_init_plugin }, +  { PLUGIN_POST, 5, "fooviz", XINE_VERSION_CODE, &fooviz_special_info, &fooviz_init_plugin },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/post/visualizations/visualizations.c b/src/post/visualizations/visualizations.c index 447518ff3..65057cb97 100644 --- a/src/post/visualizations/visualizations.c +++ b/src/post/visualizations/visualizations.c @@ -19,7 +19,7 @@   *   * This file contains plugin entries for several visualization post plugins.   * - * $Id: visualizations.c,v 1.5 2003/09/14 12:37:30 tmattern Exp $ + * $Id: visualizations.c,v 1.6 2003/10/06 21:52:44 miguelfreitas Exp $   */  #ifdef HAVE_CONFIG_H @@ -46,8 +46,8 @@ post_info_t fftgraph_special_info = { XINE_POST_TYPE_AUDIO_VISUALIZATION };  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */ -  { PLUGIN_POST, 4, "oscope", XINE_VERSION_CODE, &oscope_special_info, &oscope_init_plugin }, -  { PLUGIN_POST, 4, "fftscope", XINE_VERSION_CODE, &fftscope_special_info, &fftscope_init_plugin }, -  { PLUGIN_POST, 4, "fftgraph", XINE_VERSION_CODE, &fftgraph_special_info, &fftgraph_init_plugin }, +  { PLUGIN_POST, 5, "oscope", XINE_VERSION_CODE, &oscope_special_info, &oscope_init_plugin }, +  { PLUGIN_POST, 5, "fftscope", XINE_VERSION_CODE, &fftscope_special_info, &fftscope_init_plugin }, +  { PLUGIN_POST, 5, "fftgraph", XINE_VERSION_CODE, &fftgraph_special_info, &fftgraph_init_plugin },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index 956c5c7fa..21afcfe51 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -20,6 +20,9 @@ syncfb_module = xineplug_vo_out_syncfb.la  if HAVE_XV  xv_module = xineplug_vo_out_xv.la  endif +if HAVE_XVMC +xvmc_module = xineplug_vo_out_xvmc.la +endif  #if HAVE_OPENGL  #opengl_module = xineplug_vo_out_opengl.la  #endif @@ -59,7 +62,7 @@ endif  #lib_LTLIBRARIES = $(xshm_module) $(xv_module) $(directfb_module)  \  #                  $(syncfb_module) $(fb_module) $(opengl_module) $(sdl_module) $(vidix_module) -lib_LTLIBRARIES = $(xshm_module) $(xv_module) $(aa_module) $(pgx64_module) \ +lib_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) $(aa_module) $(pgx64_module) \  	$(vidix_module) $(fb_module) $(sdl_module) $(syncfb_module) \  	$(stk_module) $(directfb_module) xineplug_vo_out_none.la @@ -70,8 +73,18 @@ xineplug_vo_out_xv_la_LIBADD = \  	-lXext \  	$(XINE_LIB) +xineplug_vo_out_xvmc_la_SOURCES = deinterlace.c alphablend.c video_out_xvmc.c +xineplug_vo_out_xvmc_la_LIBADD = \ +	$(XV_LIB) \ +	$(XVMC_LIB) \ +	$(X_LIBS) \ +	-lXext \ +	$(XINE_LIB) +  xineplug_vo_out_xv_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ +xineplug_vo_out_xvmc_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ +  xineplug_vo_out_xshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \  	alphablend.c video_out_xshm.c  xineplug_vo_out_xshm_la_LIBADD =  $(X_LIBS) -lXext \ diff --git a/src/video_out/video_out_aa.c b/src/video_out/video_out_aa.c index 77a28ce72..9c0e9e05a 100644 --- a/src/video_out/video_out_aa.c +++ b/src/video_out/video_out_aa.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_aa.c,v 1.36 2003/08/04 03:47:11 miguelfreitas Exp $ + * $Id: video_out_aa.c,v 1.37 2003/10/06 21:52:44 miguelfreitas Exp $   *   * video_out_aa.c, ascii-art output plugin for xine   * @@ -328,6 +328,6 @@ static vo_info_t vo_info_aa = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_VIDEO_OUT, 16, "aa", XINE_VERSION_CODE, &vo_info_aa, init_class }, +  { PLUGIN_VIDEO_OUT, 17, "aa", XINE_VERSION_CODE, &vo_info_aa, init_class },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/video_out_directfb.c b/src/video_out/video_out_directfb.c index 7f2d38291..a8282b5c5 100644 --- a/src/video_out/video_out_directfb.c +++ b/src/video_out/video_out_directfb.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_directfb.c,v 1.20 2003/08/09 22:44:09 hadess Exp $ + * $Id: video_out_directfb.c,v 1.21 2003/10/06 21:52:44 miguelfreitas Exp $   *   * DirectFB based output plugin.   * Rich Wareham <richwareham@users.sourceforge.net> @@ -591,7 +591,7 @@ static vo_info_t vo_info_directfb = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */ -  { PLUGIN_VIDEO_OUT, 16, "DirectFB", XINE_VERSION_CODE, &vo_info_directfb, init_class }, +  { PLUGIN_VIDEO_OUT, 17, "DirectFB", XINE_VERSION_CODE, &vo_info_directfb, init_class },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/video_out_directx.c b/src/video_out/video_out_directx.c index 0f8e78c71..1c514f518 100755 --- a/src/video_out/video_out_directx.c +++ b/src/video_out/video_out_directx.c @@ -1262,6 +1262,6 @@ static vo_info_t vo_info_win32 = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */ -  { PLUGIN_VIDEO_OUT, 16, "vo_directx", XINE_VERSION_CODE, &vo_info_win32, init_class }, +  { PLUGIN_VIDEO_OUT, 17, "vo_directx", XINE_VERSION_CODE, &vo_info_win32, init_class },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/video_out_fb.c b/src/video_out/video_out_fb.c index a9d4f364e..ee65f19d0 100644 --- a/src/video_out/video_out_fb.c +++ b/src/video_out/video_out_fb.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_fb.c,v 1.27 2003/08/04 03:47:11 miguelfreitas Exp $ + * $Id: video_out_fb.c,v 1.28 2003/10/06 21:52:44 miguelfreitas Exp $   *    * video_out_fb.c, frame buffer xine driver by Miguel Freitas   * @@ -1053,7 +1053,7 @@ plugin_info_t xine_plugin_info[] =    /* type, API, "name", version, special_info, init_function */      {      PLUGIN_VIDEO_OUT, -    16, +    17,      "fb",      XINE_VERSION_CODE,      &vo_info_fb, fb_init_class diff --git a/src/video_out/video_out_none.c b/src/video_out/video_out_none.c index 14dfdde57..7d99713ea 100644 --- a/src/video_out/video_out_none.c +++ b/src/video_out/video_out_none.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_none.c,v 1.15 2003/08/04 03:47:11 miguelfreitas Exp $ + * $Id: video_out_none.c,v 1.16 2003/10/06 21:52:44 miguelfreitas Exp $   *   * Was originally part of toxine frontend.   * ...but has now been adapted to xine coding style standards ;) @@ -302,6 +302,6 @@ static vo_info_t vo_info_none = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_VIDEO_OUT, 16, "none", XINE_VERSION_CODE, &vo_info_none, init_class }, +  { PLUGIN_VIDEO_OUT, 17, "none", XINE_VERSION_CODE, &vo_info_none, init_class },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/video_out_opengl.c b/src/video_out/video_out_opengl.c index 3d1ba2095..f2282eaf5 100644 --- a/src/video_out/video_out_opengl.c +++ b/src/video_out/video_out_opengl.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_opengl.c,v 1.27 2003/08/04 03:47:11 miguelfreitas Exp $ + * $Id: video_out_opengl.c,v 1.28 2003/10/06 21:52:44 miguelfreitas Exp $   *    * video_out_glut.c, glut based OpenGL rendering interface for xine   * Matthias Hopf <mat@mshopf.de> @@ -1000,7 +1000,7 @@ static vo_info_t vo_info_opengl = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */ -  { PLUGIN_VIDEO_OUT, 16, "opengl", XINE_VERSION_CODE, +  { PLUGIN_VIDEO_OUT, 17, "opengl", XINE_VERSION_CODE,      &vo_info_opengl, opengl_init_class },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/video_out_pgx64.c b/src/video_out/video_out_pgx64.c index eb0a413b8..28bde24f4 100644 --- a/src/video_out/video_out_pgx64.c +++ b/src/video_out/video_out_pgx64.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA   * - * $Id: video_out_pgx64.c,v 1.38 2003/10/05 16:22:19 komadori Exp $ + * $Id: video_out_pgx64.c,v 1.39 2003/10/06 21:52:44 miguelfreitas Exp $   *   * video_out_pgx64.c, Sun PGX64/PGX24 output plugin for xine   * @@ -1006,6 +1006,6 @@ static pgx64_driver_class_t* pgx64_init_class(xine_t *xine, void *visual_gen)  }  plugin_info_t xine_plugin_info[] = { -  {PLUGIN_VIDEO_OUT, 16, "pgx64", XINE_VERSION_CODE, &vo_info_pgx64, (void*)pgx64_init_class}, +  {PLUGIN_VIDEO_OUT, 17, "pgx64", XINE_VERSION_CODE, &vo_info_pgx64, (void*)pgx64_init_class},    {PLUGIN_NONE, 0, "", 0, NULL, NULL}  }; diff --git a/src/video_out/video_out_sdl.c b/src/video_out/video_out_sdl.c index 8d6a3e6f5..50ff3753f 100644 --- a/src/video_out/video_out_sdl.c +++ b/src/video_out/video_out_sdl.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_sdl.c,v 1.26 2003/08/04 03:47:11 miguelfreitas Exp $ + * $Id: video_out_sdl.c,v 1.27 2003/10/06 21:52:44 miguelfreitas Exp $   *   * video_out_sdl.c, Simple DirectMedia Layer   * @@ -596,6 +596,6 @@ static vo_info_t vo_info_sdl = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */ -  { PLUGIN_VIDEO_OUT, 16, "sdl", XINE_VERSION_CODE, &vo_info_sdl, init_class }, +  { PLUGIN_VIDEO_OUT, 17, "sdl", XINE_VERSION_CODE, &vo_info_sdl, init_class },    { PLUGIN_NONE, 0, "" , 0 , NULL, NULL}  }; diff --git a/src/video_out/video_out_stk.c b/src/video_out/video_out_stk.c index 96f678dd6..29894180d 100644 --- a/src/video_out/video_out_stk.c +++ b/src/video_out/video_out_stk.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_stk.c,v 1.3 2003/09/13 17:20:50 miguelfreitas Exp $ + * $Id: video_out_stk.c,v 1.4 2003/10/06 21:52:44 miguelfreitas Exp $   *   * video_out_stk.c, Libstk Surface Video Driver   * more info on Libstk at http://www.libstk.org @@ -461,7 +461,7 @@ static vo_info_t vo_info_stk = {  plugin_info_t xine_plugin_info[] = {      /* type, API, "name", version, special_info, init_function */ -    { PLUGIN_VIDEO_OUT, 16, "stk", XINE_VERSION_CODE, &vo_info_stk, init_class }, +    { PLUGIN_VIDEO_OUT, 17, "stk", XINE_VERSION_CODE, &vo_info_stk, init_class },      { PLUGIN_NONE, 0, "" , 0 , NULL, NULL}  }; diff --git a/src/video_out/video_out_syncfb.c b/src/video_out/video_out_syncfb.c index 401be3cff..32376315d 100644 --- a/src/video_out/video_out_syncfb.c +++ b/src/video_out/video_out_syncfb.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_syncfb.c,v 1.88 2003/08/25 21:51:48 f1rmb Exp $ + * $Id: video_out_syncfb.c,v 1.89 2003/10/06 21:52:44 miguelfreitas Exp $   *    * video_out_syncfb.c, SyncFB (for Matrox G200/G400 cards) interface for xine   *  @@ -1057,7 +1057,7 @@ static vo_info_t vo_info_syncfb = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */ -  { PLUGIN_VIDEO_OUT, 16, "SyncFB", XINE_VERSION_CODE, &vo_info_syncfb, init_class }, +  { PLUGIN_VIDEO_OUT, 17, "SyncFB", XINE_VERSION_CODE, &vo_info_syncfb, init_class },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/video_out_vidix.c b/src/video_out/video_out_vidix.c index 0b6a4d6b7..b7017c233 100644 --- a/src/video_out/video_out_vidix.c +++ b/src/video_out/video_out_vidix.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_vidix.c,v 1.46 2003/09/22 21:34:10 jstembridge Exp $ + * $Id: video_out_vidix.c,v 1.47 2003/10/06 21:52:44 miguelfreitas Exp $   *    * video_out_vidix.c   * @@ -1233,10 +1233,10 @@ static vo_info_t vo_info_vidixfb = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */    #ifdef HAVE_X11 -  { PLUGIN_VIDEO_OUT, 16, "vidix", XINE_VERSION_CODE, &vo_info_vidix, vidix_init_class }, +  { PLUGIN_VIDEO_OUT, 17, "vidix", XINE_VERSION_CODE, &vo_info_vidix, vidix_init_class },  #endif  #ifdef HAVE_FB -  { PLUGIN_VIDEO_OUT, 16, "vidixfb", XINE_VERSION_CODE, &vo_info_vidixfb, vidixfb_init_class }, +  { PLUGIN_VIDEO_OUT, 17, "vidixfb", XINE_VERSION_CODE, &vo_info_vidixfb, vidixfb_init_class },  #endif    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index dece34455..a7912acd5 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_xshm.c,v 1.112 2003/08/04 03:47:11 miguelfreitas Exp $ + * $Id: video_out_xshm.c,v 1.113 2003/10/06 21:52:44 miguelfreitas Exp $   *    * video_out_xshm.c, X11 shared memory extension interface for xine   * @@ -1289,6 +1289,6 @@ static vo_info_t vo_info_xshm = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */   -  { PLUGIN_VIDEO_OUT, 16, "xshm", XINE_VERSION_CODE, &vo_info_xshm, xshm_init_class }, +  { PLUGIN_VIDEO_OUT, 17, "xshm", XINE_VERSION_CODE, &vo_info_xshm, xshm_init_class },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index ad7b1b326..5fc7df389 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out_xv.c,v 1.173 2003/08/29 23:10:13 miguelfreitas Exp $ + * $Id: video_out_xv.c,v 1.174 2003/10/06 21:52:44 miguelfreitas Exp $   *   * video_out_xv.c, X11 video extension interface for xine   * @@ -1474,7 +1474,7 @@ static vo_info_t vo_info_xv = {  plugin_info_t xine_plugin_info[] = {    /* type, API, "name", version, special_info, init_function */ -  { PLUGIN_VIDEO_OUT, 16, "xv", XINE_VERSION_CODE, &vo_info_xv, init_class }, +  { PLUGIN_VIDEO_OUT, 17, "xv", XINE_VERSION_CODE, &vo_info_xv, init_class },    { PLUGIN_NONE, 0, "", 0, NULL, NULL }  }; diff --git a/src/video_out/video_out_xvmc.c b/src/video_out/video_out_xvmc.c new file mode 100644 index 000000000..2a3a642b1 --- /dev/null +++ b/src/video_out/video_out_xvmc.c @@ -0,0 +1,1908 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + *  + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA + * + * $Id: video_out_xvmc.c,v 1.2 2003/10/06 21:52:44 miguelfreitas Exp $ + *  + * video_out_xvmc.c, X11 video motion compensation extension interface for xine + * + * based on mpeg2dec code from + * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * XvMC image support by Jack Kelliher + * + * TODO: + *  - support non-XvMC output, probably falling back to Xv. + *  - support XvMC overlays for spu/osd + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_XVMC + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <assert.h> + +#if defined(__FreeBSD__) +#include <machine/param.h> +#endif +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/time.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/cursorfont.h> +#include <X11/extensions/XShm.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> + +#include <X11/extensions/XvMClib.h> +#include <X11/extensions/XvMC.h> + +#include "xine.h" +#include "video_out.h" +#include "xine_internal.h" + +// TODO - delete these? +#include "alphablend.h" +#include "deinterlace.h" + +#include "xineutils.h" +#include "vo_scale.h" + +/* +#define LOG +*/ +//#define LOG1 +//#define LOG +//#define DLOG + +//#define PRINTDATA +//#define PRINTFRAME + +#define MAX_NUM_FRAMES 8 + +typedef struct xvmc_macroblock_s { +  xine_macroblocks_t   xine_mc; +  XvMCBlockArray      *blocks;    // pointer to memory for dct block array +  int                  num_blocks; +  XvMCMacroBlock      *macroblockptr;     // pointer to current macro block +  XvMCMacroBlock      *macroblockbaseptr; // pointer to base MacroBlock in MB array +  XvMCMacroBlockArray *macro_blocks;  // pointer to memory for macroblock array +  int                  slices; +} xvmc_macroblocks_t;   + +typedef struct cxid_s cxid_t; +struct cxid_s { +  void *xid; +}; + +typedef struct xvmc_driver_s xvmc_driver_t; + +typedef struct { +  int                value; +  int                min; +  int                max; +  Atom               atom; + +  cfg_entry_t       *entry; + +  xvmc_driver_t       *this; +} xvmc_property_t; + + +typedef struct { +  vo_frame_t         vo_frame; + +  int                width, height, format; +  double             ratio; + +  XvMCSurface        surface; + +  // temporary Xv only storage +  XvImage           *image; +  XShmSegmentInfo    shminfo; + +} xvmc_frame_t; + + +struct xvmc_driver_s { + +  vo_driver_t        vo_driver; + +  config_values_t   *config; + +  /* X11 / XvMC related stuff */ +  Display           *display; +  int                screen; +  Drawable           drawable; +  unsigned int       xvmc_format_yv12; +  unsigned int       xvmc_format_yuy2; +  XVisualInfo        vinfo; +  GC                 gc; +  XvPortID           xv_port; +  XvMCContext        context; +  xvmc_frame_t      *frames[MAX_NUM_FRAMES]; + +  int                surface_type_id; +  int                max_surface_width; +  int                max_surface_height; +  int                num_frame_buffers; + +  int                surface_width;    +  int                surface_height;      +  int                surface_ratio; +  int                surface_format; +  int                surface_flags; +  short              acceleration; + +  cxid_t             context_id; +  xvmc_macroblocks_t macroblocks; + +  /* all scaling information goes here */ +  vo_scale_t         sc; + + +  XColor             black; +  int                expecting_event; /* completion event handling */ + +  /* display anatomy */ +  double             display_ratio;        /* given by visual parameter +					      from init function            */ + +  xvmc_property_t    props[VO_NUM_PROPERTIES]; +  uint32_t           capabilities; + + +  xvmc_frame_t      *recent_frames[VO_NUM_RECENT_FRAMES]; +  xvmc_frame_t      *cur_frame; +  vo_overlay_t      *overlay; + +  /* TODO CLEAN THIS UP all unused vars sizes moved to vo_scale */ + +  /* size / aspect ratio calculations */ + +  /*  +   * "delivered" size: +   * frame dimension / aspect as delivered by the decoder +   * used (among other things) to detect frame size changes +   */ + +  int                delivered_duration; + +  /*  +   * "ideal" size : +   * displayed width/height corrected by aspect ratio +   */ + +  double             ratio_factor;         /* output frame must fullfill: +					      height = width * ratio_factor  */ + +   +  xvmc_frame_t       deinterlace_frame; +  int                deinterlace_method; +  int                deinterlace_enabled; + +  void              *user_data; + +  /* gui callback */ + +  void (*frame_output_cb) (void *user_data, +			   int video_width, int video_height, +			   int *dest_x, int *dest_y,  +			   int *dest_height, int *dest_width, +			   int *win_x, int *win_y); + +  char               scratch[256]; + +  int                use_colorkey; +  uint32_t           colorkey; +}; + + +typedef struct { +  video_driver_class_t driver_class; + +  config_values_t     *config; +  XvPortID             xv_port; +  XvAdaptorInfo       *adaptor_info; +  unsigned int         adaptor_num; + +  int                  surface_type_id; +  unsigned int         max_surface_width; +  unsigned int         max_surface_height; +  short                acceleration; +} xvmc_class_t; + +int gX11Fail; + +static void xvmc_render_macro_blocks(vo_frame_t *current_image, +			      vo_frame_t *backward_ref_image, +			      vo_frame_t *forward_ref_image, +			      int picture_structure, +			      int second_field, +			      xvmc_macroblocks_t *macroblocks); + + +/*********************** XVMC specific routines *********************/ + +/**************************************************************************/ + +static void calc_DMV(DMV,dmvector,mvx,mvy,picture_structure,top_field_first) +int DMV[][2]; +int *dmvector; /* differential motion vector */ +int mvx, mvy;  /* decoded mv components (always in field format) */ +int picture_structure; +int top_field_first; +{ +  if (picture_structure==VO_BOTH_FIELDS) +  { +    if (top_field_first) +    { +      /* vector for prediction of top field from bottom field */ +      DMV[0][0] = ((mvx  +(mvx>0))>>1) + dmvector[0]; +      DMV[0][1] = ((mvy  +(mvy>0))>>1) + dmvector[1] - 1; + +      /* vector for prediction of bottom field from top field */ +      DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; +      DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1; +    } +    else +    { +      /* vector for prediction of top field from bottom field */ +      DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; +      DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1; + +      /* vector for prediction of bottom field from top field */ +      DMV[1][0] = ((mvx  +(mvx>0))>>1) + dmvector[0]; +      DMV[1][1] = ((mvy  +(mvy>0))>>1) + dmvector[1] + 1; +    } +  } +  else +  { +    /* vector for prediction from field of opposite 'parity' */ +    DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0]; +    DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1]; + +    /* correct for vertical field shift */ +    if (picture_structure==VO_TOP_FIELD) +      DMV[0][1]--; +    else +      DMV[0][1]++; +  } +} + +static void xvmc_proc_macro_block( +   int x, +   int y, +   int mb_type, +   int motion_type, +   //   int (*PMV)[2][2], +   int (*mv_field_sel)[2], +   int *dmvector, +   int cbp, +   int dct_type, +   vo_frame_t *current_frame, +   vo_frame_t *forward_ref_frame, +   vo_frame_t *backward_ref_frame, +   int picture_structure, +   int second_field, +   int (*f_mot_pmv)[2], +   int (*b_mot_pmv)[2]) +{ +  xvmc_driver_t *this = (xvmc_driver_t *) current_frame->driver; +  xvmc_macroblocks_t * mbs = &this->macroblocks; +  int top_field_first=current_frame->top_field_first; +  int picture_coding_type = current_frame->picture_coding_type; +         +  mbs->macroblockptr->x = x; +  mbs->macroblockptr->y = y; + +  if(mb_type & XINE_MACROBLOCK_INTRA) { +    mbs->macroblockptr->macroblock_type = XVMC_MB_TYPE_INTRA; +  } else { +    mbs->macroblockptr->macroblock_type = 0; +    /* XvMC doesn't support skips */ +    if(!(mb_type & (XINE_MACROBLOCK_MOTION_BACKWARD | XINE_MACROBLOCK_MOTION_FORWARD))) { +      mb_type |= XINE_MACROBLOCK_MOTION_FORWARD; +      motion_type = (picture_structure==VO_BOTH_FIELDS) ? XINE_MC_FRAME : XINE_MC_FIELD; +      mbs->macroblockptr->PMV[0][0][0] = 0; +      mbs->macroblockptr->PMV[0][0][1] = 0; +    } else { +      if(mb_type & XINE_MACROBLOCK_MOTION_BACKWARD) { +	mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD; +	mbs->macroblockptr->PMV[0][1][0] =  +	  b_mot_pmv[0][0]; +	mbs->macroblockptr->PMV[0][1][1] =  +	  b_mot_pmv[0][1]; +	mbs->macroblockptr->PMV[1][1][0] =  +	  b_mot_pmv[1][0]; +	mbs->macroblockptr->PMV[1][1][1] =  +	  b_mot_pmv[1][1]; + +      } +      if(mb_type & XINE_MACROBLOCK_MOTION_FORWARD) { +	mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_FORWARD; +	mbs->macroblockptr->PMV[0][0][0] =  +	  f_mot_pmv[0][0]; +	mbs->macroblockptr->PMV[0][0][1] =  +	  f_mot_pmv[0][1]; +	mbs->macroblockptr->PMV[1][0][0] =  +	  f_mot_pmv[1][0]; +	mbs->macroblockptr->PMV[1][0][1] =  +	  f_mot_pmv[1][1]; +      } +    } +    if((mb_type & XINE_MACROBLOCK_PATTERN) && cbp) +      mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_PATTERN; + +    mbs->macroblockptr->motion_type = motion_type; + +    if(motion_type == XINE_MC_DMV) { +      int DMV[2][2]; + +      if(picture_structure==VO_BOTH_FIELDS) { +	calc_DMV(DMV,dmvector, f_mot_pmv[0][0], +		 f_mot_pmv[0][1]>>1, picture_structure, +		 top_field_first); + +	mbs->macroblockptr->PMV[1][0][0] = DMV[0][0]; +	mbs->macroblockptr->PMV[1][0][1] = DMV[0][1]; +	mbs->macroblockptr->PMV[1][1][0] = DMV[1][0]; +	mbs->macroblockptr->PMV[1][1][1] = DMV[1][1]; +      } else { +	calc_DMV(DMV,dmvector, f_mot_pmv[0][0], +		 f_mot_pmv[0][1]>>1, picture_structure, +		 top_field_first); + +	mbs->macroblockptr->PMV[0][1][0] = DMV[0][0]; +	mbs->macroblockptr->PMV[0][1][1] = DMV[0][1]; +      } +    } + +    if((motion_type == XINE_MC_FIELD) || (motion_type == XINE_MC_16X8)) { +      mbs->macroblockptr->motion_vertical_field_select = 0; +      if(mv_field_sel[0][0]) +	mbs->macroblockptr->motion_vertical_field_select |= 1; +      if(mv_field_sel[0][1]) +	mbs->macroblockptr->motion_vertical_field_select |= 2; +      if(mv_field_sel[1][0]) +	mbs->macroblockptr->motion_vertical_field_select |= 4; +      if(mv_field_sel[1][1]) +	mbs->macroblockptr->motion_vertical_field_select |= 8; +    } +  } // else of if(mb_type & XINE_MACROBLOCK_INTRA) + +  mbs->macroblockptr->index = ((unsigned long)mbs->xine_mc.blockptr - +			     (unsigned long)mbs->xine_mc.blockbaseptr) >> 7; + +  mbs->macroblockptr->dct_type = dct_type; +  mbs->macroblockptr->coded_block_pattern = cbp; + +  cbp &= 0x3F; +  mbs->macroblockptr->coded_block_pattern = cbp; +  while(cbp) {  +    if(cbp & 1) mbs->macroblockptr->index--; +    cbp >>= 1; +  } + +#ifdef PRINTDATA +  printf("\n"); +  printf("-- %04d %04d %02x %02x %02x %02x",mbs->macroblockptr->x,mbs->macroblockptr->y,mbs->macroblockptr->macroblock_type, +	 mbs->macroblockptr->motion_type,mbs->macroblockptr->motion_vertical_field_select,mbs->macroblockptr->dct_type); +  printf(" [%04d %04d %04d %04d %04d %04d %04d %04d] ", +	 mbs->macroblockptr->PMV[0][0][0],mbs->macroblockptr->PMV[0][0][1],mbs->macroblockptr->PMV[0][1][0],mbs->macroblockptr->PMV[0][1][1], +	 mbs->macroblockptr->PMV[1][0][0],mbs->macroblockptr->PMV[1][0][1],mbs->macroblockptr->PMV[1][1][0],mbs->macroblockptr->PMV[1][1][1]); + +  printf(" %04d %04x\n",mbs->macroblockptr->index,mbs->macroblockptr->coded_block_pattern); + +#endif + +  mbs->num_blocks++; +  mbs->macroblockptr++; + +  if(mbs->num_blocks == mbs->slices) { +#ifdef PRINTDATA +    printf("macroblockptr %lx",  mbs->macroblockptr); +    printf("** RenderSurface %04d %04x\n",picture_structure, +	   second_field ? XVMC_SECOND_FIELD : 0); +    fflush(stdout); +#endif +#ifdef PRINTFRAME +    printf("  target %08x past %08x future %08x\n", +	   current_frame, +	   forward_ref_frame, +	   backward_ref_frame); +#endif +#ifdef PRINTFRAME +    if (picture_coding_type == XINE_PICT_P_TYPE) +      printf(" coding type P_TYPE\n"); +    if (picture_coding_type == XINE_PICT_I_TYPE) +      printf(" coding type I_TYPE\n"); +    if (picture_coding_type == XINE_PICT_B_TYPE) +      printf(" coding type B_TYPE\n"); +    if (picture_coding_type == XINE_PICT_D_TYPE) +      printf(" coding type D_TYPE\n"); +    fflush(stdout); +#endif + +    if (picture_coding_type == XINE_PICT_B_TYPE) +      xvmc_render_macro_blocks( +			  current_frame, +			  backward_ref_frame, +			  forward_ref_frame, +			  picture_structure, +			  second_field ? XVMC_SECOND_FIELD : 0, +			  mbs); +    if (picture_coding_type == XINE_PICT_P_TYPE) +      xvmc_render_macro_blocks( +			  current_frame, +			  NULL, +			  forward_ref_frame, +			  picture_structure, +			  second_field ? XVMC_SECOND_FIELD : 0, +			  mbs); +    if (picture_coding_type == XINE_PICT_I_TYPE) +      xvmc_render_macro_blocks( +			  current_frame, +			  NULL, +			  NULL, +			  picture_structure, +			  second_field ? XVMC_SECOND_FIELD : 0, +			  mbs); +        +    mbs->num_blocks = 0; +    mbs->macroblockptr = mbs->macroblockbaseptr; +    mbs->xine_mc.blockptr = mbs->xine_mc.blockbaseptr; +  } +} + +static uint32_t xvmc_get_capabilities (vo_driver_t *this_gen) { + +  xvmc_driver_t *this = (xvmc_driver_t *) this_gen; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_get_capabilities\n"); +#endif + +  return this->capabilities; +} + +static void xvmc_frame_field (vo_frame_t *vo_img, int which_field) { +  xvmc_driver_t *this = (xvmc_driver_t *) vo_img->driver; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_frame_field\n"); +#endif +  this->macroblocks.num_blocks = 0; +  this->macroblocks.macroblockptr = this->macroblocks.macroblockbaseptr; +  this->macroblocks.xine_mc.blockptr = this->macroblocks.xine_mc.blockbaseptr; +} + +static void xvmc_frame_dispose (vo_frame_t *vo_img) { + +  xvmc_frame_t  *frame = (xvmc_frame_t *) vo_img ; +  xvmc_driver_t *this = (xvmc_driver_t *) vo_img->driver; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_frame_dispose\n"); +#endif + +  // TODO - clean up of images/surfaces and frames +  //  Note this function is not really needed   +  // set_context does the work + +  if (frame->image) { +      XLockDisplay (this->display); +      XFree (frame->image); +      XUnlockDisplay (this->display); +  } + +  free (frame); +} + +static void xvmc_render_macro_blocks(vo_frame_t *current_image, +				     vo_frame_t *backward_ref_image, +				     vo_frame_t *forward_ref_image, +				     int picture_structure, +				     int second_field, +				     xvmc_macroblocks_t *macroblocks) { + +  xvmc_driver_t *this           = (xvmc_driver_t *) current_image->driver; +  xvmc_frame_t  *current_frame  = (xvmc_frame_t *)  current_image; +  xvmc_frame_t  *forward_frame  = (xvmc_frame_t *)  forward_ref_image; +  xvmc_frame_t  *backward_frame = (xvmc_frame_t *)  backward_ref_image; + + + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_render_macro_blocks\n"); +  printf ("                slices %d 0x%08lx 0x%08lx 0x%08lx\n", +	  macroblocks->slices, +  	  (long) current_frame, (long) backward_frame, +  	  (long) forward_frame); + +  //  printf ("                        slices %d 0x%08lx 0x%08lx 0x%08lx\n",macroblocks->slices, +  //  	  (long) current_frame->surface, (long) backward_frame->surface, +  //  	  (long) forward_frame->surface); +  fflush(stdout); +#endif + +  /* XvMCSyncSurface(this->display,¤t_frame->surface); */ +  if(forward_frame) { +    if(backward_frame) { +      XvMCRenderSurface(this->display, &this->context, picture_structure, +			¤t_frame->surface, +			&forward_frame->surface, +			&backward_frame->surface, +			second_field, +			macroblocks->slices, 0, macroblocks->macro_blocks, +			macroblocks->blocks); +    } else { +      XvMCRenderSurface(this->display, &this->context, picture_structure, +			¤t_frame->surface, +			&forward_frame->surface, +			NULL, +			second_field, +			macroblocks->slices, 0, macroblocks->macro_blocks, +			macroblocks->blocks); +    } +  } else { +    if(backward_frame) { +      XvMCRenderSurface(this->display, &this->context, picture_structure, +			¤t_frame->surface, +			NULL, +			&backward_frame->surface, +			second_field, +			macroblocks->slices, 0, macroblocks->macro_blocks, +			macroblocks->blocks); +    } else { +      XvMCRenderSurface(this->display, &this->context, picture_structure, +			¤t_frame->surface, +			NULL, +			NULL, +			second_field, +			macroblocks->slices, 0, macroblocks->macro_blocks, +			macroblocks->blocks); +    } +  } + +  //   XvMCFlushSurface(this->display, ¤t_frame->surface); + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_render_macro_blocks done\n"); +  fflush(stdout); +#endif +} + +static vo_frame_t *xvmc_alloc_frame (vo_driver_t *this_gen) { + +  xvmc_frame_t     *frame ; +  xvmc_driver_t *this = (xvmc_driver_t *) this_gen; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_alloc_frame\n"); +#endif + +  frame = (xvmc_frame_t *) malloc (sizeof (xvmc_frame_t)); +  memset (frame, 0, sizeof(xvmc_frame_t)); + +  if (frame == NULL) { +    printf ("xvmc_alloc_frame: out of memory\n"); +    return (NULL); +  } + +  // keep track of frames and how many frames alocated. +  this->frames[this->num_frame_buffers++] = frame; + +  pthread_mutex_init (&frame->vo_frame.mutex, NULL); + +  /* +   * supply required functions +   */ + +  frame->vo_frame.copy    = NULL; +  frame->vo_frame.field   = xvmc_frame_field; +  frame->vo_frame.dispose = xvmc_frame_dispose; +  frame->vo_frame.proc_macro_block = xvmc_proc_macro_block; + +  frame->vo_frame.driver  = this_gen; + +    return (vo_frame_t *) frame; +} + +static cxid_t *xvmc_set_context (xvmc_driver_t *this, +				 uint32_t width, uint32_t height, +				 double ratio, int format, int flags, +				 xine_macroblocks_t *macro_blocks) { + +  int           result = 0; +  int           i; +  int           slices = 1; +  xvmc_macroblocks_t *macroblocks = (xvmc_macroblocks_t *) macro_blocks; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_set_context %dx%d %04x\n",width,height,format); +#endif + +  //initialize block & macro block pointers first time +  if(macroblocks->blocks == NULL ||  macroblocks->macro_blocks == NULL) { +    macroblocks->blocks = malloc(sizeof(XvMCBlockArray)); +    macroblocks->macro_blocks = malloc(sizeof(XvMCMacroBlockArray)); +    memset (macroblocks->blocks, 0, sizeof(XvMCBlockArray)); +    memset (macroblocks->macro_blocks, 0, sizeof(XvMCMacroBlockArray)); +#ifdef LOG +    printf("	macroblocks->blocks %lx ->macro_blocks %lx\n",macroblocks->blocks,macroblocks->macro_blocks); +#endif +  } + +  if((this->context_id.xid != NULL)   && +     (width  == this->surface_width)  && +     (height == this->surface_height) && +     (format == this->surface_format) && +     (flags  == this->surface_flags)) { + +    // don't need to change  context +#ifdef LOG +    printf ("video_out_xvmc: didn't change context\n"); +#endif +    return(&this->context_id); + +  } else {  +    if(this->context_id.xid != NULL) { + +      // flush any drawing and wait till we are done with the old stuff +      // blow away the old stuff +#ifdef LOG +      printf ("video_out_xvmc: freeing previous context\n"); +      fflush(stdout); +#endif + +      XvMCDestroyBlocks(this->display, macroblocks->blocks); +      XvMCDestroyMacroBlocks(this->display, macroblocks->macro_blocks); + +      for(i = 0; i < this->num_frame_buffers; i++) { +	XvMCFlushSurface(this->display, &this->frames[i]->surface); +	XvMCSyncSurface(this->display, &this->frames[i]->surface); + +	XvMCDestroySurface(this->display, &this->frames[i]->surface); +      } +      XvMCDestroyContext(this->display, &this->context); +      this->context_id.xid = NULL; +    } + +#ifdef DLOG +     printf("CreateContext  w %d h %d id %x portNum %x\n",width,height,this->surface_type_id,(int)this->xv_port); +#endif + +    // now create a new context +    result = XvMCCreateContext(this->display, this->xv_port,  +			       this->surface_type_id,  +			       width, height, XVMC_DIRECT, &this->context); + +    if(result != Success) { +      fprintf(stderr, "set_context: couldn't create XvMCContext\n"); +      macroblocks->xine_mc.xvmc_accel=0; +      abort(); +    } + +    this->context_id.xid = (void *)this->context.context_id; + +    for(i = 0; i < this->num_frame_buffers; i++) { +      result = XvMCCreateSurface(this->display, &this->context, +				 &this->frames[i]->surface); +      if(result != Success) { +	XvMCDestroyContext(this->display, &this->context); +	fprintf(stderr, "set_context: couldn't create XvMCSurfaces\n"); +	this->context_id.xid = NULL; +	macroblocks->xine_mc.xvmc_accel=0; +	abort(); +      } +#ifdef LOG +      printf ("  CreatedSurface %d 0x%lx\n",i,(long)&this->frames[i]->surface); +#endif  + +    } + +    slices = (slices * width/16); + +#ifdef DLOG +   printf("CreateBlocks  slices %d\n",slices); +#endif + +    result = XvMCCreateBlocks(this->display, &this->context, slices * 6, +		     macroblocks->blocks); +    if(result != Success) { +      fprintf(stderr, "set_context: ERROR XvMCCreateBlocks failed\n"); +      macroblocks->xine_mc.xvmc_accel=0; +      abort(); +    } +    result =XvMCCreateMacroBlocks(this->display, &this->context, slices, +			  macroblocks->macro_blocks); +    if(result != Success) { +      fprintf(stderr, "set_context: ERROR XvMCCreateMacroBlocks failed\n"); +      macroblocks->xine_mc.xvmc_accel=0; +      abort(); +    } + +#ifdef LOG +      printf ("  Created bock and macro block arrays\n"); +#endif + +    macroblocks->xine_mc.blockbaseptr = macroblocks->blocks->blocks; +    macroblocks->xine_mc.blockptr = macroblocks->xine_mc.blockbaseptr; +    macroblocks->num_blocks = 0; +    macroblocks->macroblockbaseptr = macroblocks->macro_blocks->macro_blocks; +    macroblocks->macroblockptr = macroblocks->macroblockbaseptr; +    macroblocks->slices=slices; +    macroblocks->xine_mc.xvmc_accel=this->acceleration; + +    return(&this->context_id); +  } +} + +int HandleXError (Display *display, XErrorEvent *xevent) { + +  char str [1024]; + +  XGetErrorText (display, xevent->error_code, str, 1024); + +  printf ("received X error event: %s\n", str); + +  gX11Fail = 1; +  return 0; + +} + +static void x11_InstallXErrorHandler (xvmc_driver_t *this) +{ +  XSetErrorHandler (HandleXError); +  XFlush (this->display); +} + +static void x11_DeInstallXErrorHandler (xvmc_driver_t *this) +{ +  XSetErrorHandler (NULL); +  XFlush (this->display); +} + +static XvImage *create_ximage (xvmc_driver_t *this, XShmSegmentInfo *shminfo, +			       int width, int height, int format) { + +  unsigned int  xvmc_format; +  XvImage      *image=NULL; + +#ifdef LOG +  printf ("video_out_xvmc: create_ximage\n"); +#endif + +  switch (format) { +  case XINE_IMGFMT_YV12: +  case XINE_IMGFMT_XVMC: +    xvmc_format = this->xvmc_format_yv12; +    break; +  case XINE_IMGFMT_YUY2: +    xvmc_format = this->xvmc_format_yuy2; +    break; +  default: +    fprintf (stderr, "create_ximage: unknown format %08x\n",format); +    abort(); +  } + +  /* +   *  plain Xv +   */ + +  if (1) { + +    char *data; + +    switch (format) { +    case XINE_IMGFMT_YV12: +    case XINE_IMGFMT_XVMC: +      data = malloc (width * height * 3/2); +      break; +    case XINE_IMGFMT_YUY2: +      data = malloc (width * height * 2); +      break; +    default: +      fprintf (stderr, "create_ximage: unknown format %08x\n",format); +      abort(); +    } + +    image = XvCreateImage (this->display, this->xv_port, +			   xvmc_format, data, width, height); +  } +  return image; +} + +static void dispose_ximage (xvmc_driver_t *this, +			    XShmSegmentInfo *shminfo, +			    XvImage *myimage) { + +#ifdef LOG +  printf ("video_out_xvmc: dispose_ximage\n"); +#endif + +    XFree (myimage); +} + +static void xvmc_update_frame_format (vo_driver_t *this_gen, +				    vo_frame_t *frame_gen, +				    uint32_t width, uint32_t height, +				    double ratio, int format, int flags) { + +  xvmc_driver_t  *this = (xvmc_driver_t *) this_gen; +  xvmc_frame_t   *frame = (xvmc_frame_t *) frame_gen; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_update_frame_format\n"); +#endif + +  if ((frame->width != width) +      || (frame->height != height) +      || (frame->format != format)) { + +#ifdef LOG +    printf ("video_out_xvmc: updating frame to %d x %d (ratio=%f, format=%08x)\n",width,height,ratio,format); +#endif +    XLockDisplay (this->display); + +    /* +     * (re-) allocate xvimage +     */ + +    if (frame->image) { +      dispose_ximage (this, &frame->shminfo, frame->image); +      frame->image = NULL; +    } + +    frame->image = create_ximage (this, &frame->shminfo, width, height, format); + +    frame->vo_frame.pitches[0] = frame->image->pitches[0]; +    frame->vo_frame.pitches[1] = frame->image->pitches[2]; +    frame->vo_frame.pitches[2] = frame->image->pitches[1]; +    frame->vo_frame.base[0] = frame->image->data + frame->image->offsets[0]; +    frame->vo_frame.base[1] = frame->image->data + frame->image->offsets[2]; +    frame->vo_frame.base[2] = frame->image->data + frame->image->offsets[1]; +     +    frame->width  = width; +    frame->height = height; +    frame->format = format; + +    XUnlockDisplay (this->display); +  } + +  frame->ratio = ratio; + +  frame->vo_frame.macroblocks = (xine_macroblocks_t *)&this->macroblocks; +  if( flags & VO_NEW_SEQUENCE_FLAG ) { +    xvmc_set_context (this, width, height, ratio, format, flags, +                      frame->vo_frame.macroblocks); +  } +  this->macroblocks.num_blocks = 0; +  this->macroblocks.macroblockptr = this->macroblocks.macroblockbaseptr; +  this->macroblocks.xine_mc.blockptr = this->macroblocks.xine_mc.blockbaseptr; +} + +static void xvmc_clean_output_area (xvmc_driver_t *this) { + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_clean_output_area\n"); +#endif + +  XLockDisplay (this->display); + +  XSetForeground (this->display, this->gc, this->black.pixel); + +  XFillRectangle(this->display, this->drawable, this->gc, +		 this->sc.gui_x, this->sc.gui_y, this->sc.gui_width, this->sc.gui_height); + +  if (this->use_colorkey) { +    XSetForeground (this->display, this->gc, this->colorkey); +    XFillRectangle (this->display, this->drawable, this->gc, +		    this->sc.output_xoffset, this->sc.output_yoffset,  +		    this->sc.output_width, this->sc.output_height); +  } +   +  XUnlockDisplay (this->display); +} + +/* + * convert delivered height/width to ideal width/height + * taking into account aspect ratio and zoom factor + */ + +static void xvmc_compute_ideal_size (xvmc_driver_t *this) { + +  vo_scale_compute_ideal_size( &this->sc ); +} + + +/* + * make ideal width/height "fit" into the gui + */ + +static void xvmc_compute_output_size (xvmc_driver_t *this) { + + vo_scale_compute_output_size( &this->sc ); + +} + +static void xvmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { + +  xvmc_frame_t   *frame = (xvmc_frame_t *) frame_gen; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_overlay_blend\n"); +#endif + +  /* Alpha Blend here +   * As XV drivers improve to support Hardware overlay, we will change this function. +   */ +   +  if (overlay->rle) { +    if (frame->format == XINE_IMGFMT_YV12) +      blend_yuv(frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches); +    else +      blend_yuy2(frame->vo_frame.base[0], overlay, frame->width, frame->height, frame->vo_frame.pitches[0]); +  } + +} + +static void xvmc_add_recent_frame (xvmc_driver_t *this, xvmc_frame_t *frame) { +  int i; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_add_recent_frame\n"); +#endif + +  i = VO_NUM_RECENT_FRAMES-1; +  if( this->recent_frames[i] ) +    this->recent_frames[i]->vo_frame.free +       (&this->recent_frames[i]->vo_frame); + +  for( ; i ; i-- ) +    this->recent_frames[i] = this->recent_frames[i-1]; + +  this->recent_frames[0] = frame; +} + +/* currently not used - we could have a method to call this from video loop */ +#if 0 +static void xvmc_flush_recent_frames (xvmc_driver_t *this) { + +  int i; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_flush_recent_frames\n"); +#endif + +  for( i=0; i < VO_NUM_RECENT_FRAMES; i++ ) +  { +    if( this->recent_frames[i] ) +      this->recent_frames[i]->vo_frame.free +         (&this->recent_frames[i]->vo_frame); +    this->recent_frames[i] = NULL; +  } +} +#endif + +static int xvmc_redraw_needed (vo_driver_t *this_gen) { +  xvmc_driver_t  *this = (xvmc_driver_t *) this_gen; +  int ret = 0; + +  if( this->cur_frame ) { + +    this->sc.delivered_height   = this->cur_frame->height; +    this->sc.delivered_width    = this->cur_frame->width; +    this->sc.delivered_ratio    = this->cur_frame->ratio; + +    xvmc_compute_ideal_size(this); + +    if( vo_scale_redraw_needed( &this->sc ) ) { + +      xvmc_compute_output_size (this); + +      xvmc_clean_output_area (this); + +      ret = 1; +    } +  } +  else +    ret = 1; + +  return ret; +} + +static void xvmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { + +  xvmc_driver_t  *this = (xvmc_driver_t *) this_gen; +  xvmc_frame_t   *frame = (xvmc_frame_t *) frame_gen; +  int            status; + +#ifdef LOG1 +  printf ("video_out_xvmc: xvmc_display_frame %d %x\n",frame_gen->id,frame_gen); +#endif + +  if (this->expecting_event) { + +    frame->vo_frame.free (&frame->vo_frame); +    this->expecting_event--; +#ifdef LOG +    printf ("video_out_xvmc: xvmc_display_frame... not displayed, waiting for completion event\n"); +#endif +  } else { + +    /*  +     * queue frames (deinterlacing) +     * free old frames +     */ + +    xvmc_add_recent_frame (this, frame); /* deinterlacing */ + +    this->cur_frame = frame; + +    /* +     * let's see if this frame is different in size / aspect +     * ratio from the previous one +     */ + +    if ( (frame->width != this->sc.delivered_width) +	 || (frame->height != this->sc.delivered_height) +	 || (frame->ratio != this->sc.delivered_ratio) ) { +#ifdef LOG +      printf("video_out_xvmc: frame format changed\n"); +#endif + +      //      this->delivered_width      = frame->width; +      //      this->delivered_height     = frame->height; +      //      this->delivered_ratio      = frame->ratio; +      //      this->delivered_duration   = frame->vo_frame.duration; + +      //xvmc_compute_ideal_size (this); +       +      //this->gui_width = 0; /* trigger re-calc of output size */ +      this->sc.force_redraw = 1;    /* trigger re-calc of output size */ +    } + +    /*  +     * tell gui that we are about to display a frame, +     * ask for offset and output size +     */ +    xvmc_redraw_needed (this_gen); + +    XLockDisplay (this->display); + +    XvMCGetSurfaceStatus(this->display, &this->cur_frame->surface, &status); + +    if(status & XVMC_RENDERING) { +      printf("--------- current frame is still being rendered %x --------\n",status); +      fflush(stdout); +      XvMCSyncSurface(this->display, &this->cur_frame->surface); +    } + +    if (this->deinterlace_enabled && +	(this->deinterlace_method == DEINTERLACE_ONEFIELD)) { +      XvMCPutSurface(this->display, &this->cur_frame->surface, +		     this->drawable, +		     this->sc.displayed_xoffset, this->sc.displayed_yoffset, +		     this->sc.displayed_width, this->sc.displayed_height, +		     this->sc.output_xoffset, this->sc.output_yoffset, +		     this->sc.output_width, this->sc.output_height, +		     XVMC_TOP_FIELD); +    } else { // WEAVE +      XvMCPutSurface(this->display, &this->cur_frame->surface, +		     this->drawable, +		     this->sc.displayed_xoffset, this->sc.displayed_yoffset, +		     this->sc.displayed_width, this->sc.displayed_height, +		     this->sc.output_xoffset, this->sc.output_yoffset, +		     this->sc.output_width, this->sc.output_height, +		     XVMC_FRAME_PICTURE); +    } + +    //    XFlush(this->display); + +    XUnlockDisplay (this->display); +     +  } +  /* +  printf ("video_out_xvmc: xvmc_display_frame... done\n"); +  */ +} + +static int xvmc_get_property (vo_driver_t *this_gen, int property) { + +  xvmc_driver_t *this = (xvmc_driver_t *) this_gen; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_get_property\n"); +#endif +   +  return this->props[property].value; +} + +static void xvmc_property_callback (void *property_gen, xine_cfg_entry_t *entry) { + +  xvmc_property_t *property = (xvmc_property_t *) property_gen; +  xvmc_driver_t   *this = property->this; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_property_callback\n"); +#endif +   +  XvSetPortAttribute (this->display, this->xv_port, +		      property->atom, entry->num_value); + +} + +static int xvmc_set_property (vo_driver_t *this_gen, +			    int property, int value) { + +  xvmc_driver_t *this = (xvmc_driver_t *) this_gen; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_set_property %d value %d\n",property,value); +#endif +   +  if (this->props[property].atom != None) { +    /* value is out of bound */ +    if((value < this->props[property].min) || (value > this->props[property].max)) +      value = (this->props[property].min + this->props[property].max) >> 1; + +    XvSetPortAttribute (this->display, this->xv_port, +			this->props[property].atom, value); +    XvGetPortAttribute (this->display, this->xv_port, +			this->props[property].atom, +			&this->props[property].value); + +    if (this->props[property].entry) +      this->props[property].entry->num_value = this->props[property].value; + +    return this->props[property].value; +  } else { +    switch (property) { +    case VO_PROP_INTERLACED: + +      this->props[property].value = value; +      printf("video_out_xvmc: VO_PROP_INTERLACED(%d)\n", +	     this->props[property].value); +      this->deinterlace_enabled = value; +      if (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) { +         xvmc_compute_ideal_size (this); +      } +      break; +    case VO_PROP_ASPECT_RATIO: + +      if (value>=XINE_VO_ASPECT_NUM_RATIOS) +	value = XINE_VO_ASPECT_AUTO; + +      this->props[property].value = value; +      printf("video_out_xvmc: VO_PROP_ASPECT_RATIO(%d)\n", +	     this->props[property].value); + +      xvmc_compute_ideal_size (this); +      xvmc_compute_output_size (this); +      xvmc_clean_output_area (this); + +      break; +    case VO_PROP_ZOOM_X: + +      if ((value >= VO_ZOOM_MIN) && (value <= VO_ZOOM_MAX)) { +        this->props[property].value = value; +        printf ("video_out_xv: VO_PROP_ZOOM_X = %d\n", +		this->props[property].value); + +	this->sc.zoom_factor_x = (double)value / (double)VO_ZOOM_STEP; + +	xvmc_compute_ideal_size (this); + +	this->sc.force_redraw = 1;    /* trigger re-calc of output size */ +      } +      break; +    case VO_PROP_ZOOM_Y: + +      if ((value >= VO_ZOOM_MIN) && (value <= VO_ZOOM_MAX)) { +        this->props[property].value = value; +        printf ("video_out_xv: VO_PROP_ZOOM_Y = %d\n", +		this->props[property].value); + +	this->sc.zoom_factor_y = (double)value / (double)VO_ZOOM_STEP; + +	xvmc_compute_ideal_size (this); + +	this->sc.force_redraw = 1;    /* trigger re-calc of output size */ +      } +      break; +    }  +  } + +  return value; +} + +static void xvmc_get_property_min_max (vo_driver_t *this_gen, +				     int property, int *min, int *max) { + +  xvmc_driver_t *this = (xvmc_driver_t *) this_gen; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_get_property_min_max\n"); +#endif + +  *min = this->props[property].min; +  *max = this->props[property].max; +} + +static int xvmc_gui_data_exchange (vo_driver_t *this_gen, +				 int data_type, void *data) { + +  xvmc_driver_t     *this = (xvmc_driver_t *) this_gen; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_gui_data_exchange\n"); +#endif +   +  switch (data_type) { +  case XINE_GUI_SEND_COMPLETION_EVENT: { +    +    XShmCompletionEvent *cev = (XShmCompletionEvent *) data; + +    if (cev->drawable == this->drawable) { +      this->expecting_event = 0; + +    } + +  } +  break; + +  case XINE_GUI_SEND_EXPOSE_EVENT: { + +    /* XExposeEvent * xev = (XExposeEvent *) data; */ +     +    /* FIXME : take care of completion events */ + +    //    printf ("video_out_xvmc: XINE_GUI_SEND_EXPOSE_EVENT\n"); +     +    if (this->cur_frame) { +      int i; + +      XLockDisplay (this->display); + +      //      XvPutImage(this->display, this->xv_port, +      //		 this->drawable, this->gc, this->cur_frame->image, +      //		 this->sc.displayed_xoffset, this->sc.displayed_yoffset, +      //		 this->sc.displayed_width, this->sc.displayed_height, +      //		 this->sc.output_xoffset, this->sc.output_yoffset, +      //		 this->sc.output_width, this->sc.output_height); + +      XSetForeground (this->display, this->gc, this->black.pixel); + +      for( i = 0; i < 4; i++ ) { +        if( this->sc.border[i].w && this->sc.border[i].h ) +          XFillRectangle(this->display, this->drawable, this->gc, +                         this->sc.border[i].x, this->sc.border[i].y, +                         this->sc.border[i].w, this->sc.border[i].h); +      } +       +      if (this->use_colorkey) { +	XSetForeground (this->display, this->gc, this->colorkey); +	XFillRectangle (this->display, this->drawable, this->gc, +			this->sc.output_xoffset, this->sc.output_yoffset,  +			this->sc.output_width, this->sc.output_height); +      } + +      XvMCPutSurface(this->display, &this->cur_frame->surface, +		   this->drawable, +		   this->sc.displayed_xoffset, this->sc.displayed_yoffset, +		   this->sc.displayed_width, this->sc.displayed_height, +		   this->sc.output_xoffset, this->sc.output_yoffset, +		   this->sc.output_width, this->sc.output_height, +		   XVMC_FRAME_PICTURE); +       +      XFlush(this->display); +       +      XUnlockDisplay (this->display); +    } +  } +  break; + +  case XINE_GUI_SEND_DRAWABLE_CHANGED: +    this->drawable = (Drawable) data; +    this->gc       = XCreateGC (this->display, this->drawable, 0, NULL); +    break; + +  case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: +    { +      int x1, y1, x2, y2; +      x11_rectangle_t *rect = data; + +//      xvmc_translate_gui2video(this, rect->x, rect->y, +//			     &x1, &y1); +//      xvmc_translate_gui2video(this, rect->x + rect->w, rect->y + rect->h, +//			     &x2, &y2); + +      vo_scale_translate_gui2video(&this->sc, rect->x, rect->y, +			     &x1, &y1); +      vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h, +			     &x2, &y2); + +      rect->x = x1; +      rect->y = y1; +      rect->w = x2-x1; +      rect->h = y2-y1; +    } +    break; + +  default: +    return -1; +  } + +  return 0; +} + +static void xvmc_dispose (vo_driver_t *this_gen) { + +  xvmc_driver_t *this = (xvmc_driver_t *) this_gen; +  int i; + +#ifdef LOG +  printf ("video_out_xvmc: xvmc_dispose\n"); +#endif + +  if (this->deinterlace_frame.image) { +    dispose_ximage (this, &this->deinterlace_frame.shminfo, +		    this->deinterlace_frame.image); +    this->deinterlace_frame.image = NULL; +  } + +  if(this->context_id.xid) { +    for(i = 0; i < this->num_frame_buffers; i++) { +      //      if(useOverlay) /* only one is displaying but I don't want to keep track*/ +      XvMCHideSurface(this->display, &this->frames[i]->surface); +      XvMCDestroySurface(this->display, &this->frames[i]->surface); +    } +    //    XvMCDestroyBlocks(this->display, ¯oblocks->blocks); +    //    XvMCDestroyMacroBlocks(this->display, ¯oblocks->macro_blocks); +    XvMCDestroyContext(this->display, &this->context);     +  } + +  XLockDisplay (this->display); +  if(XvUngrabPort (this->display, this->xv_port, CurrentTime) != Success) { +    printf ("video_out_xvmc: xvmc_dispose: XvUngrabPort() failed.\n"); +  } +  XUnlockDisplay (this->display); + +  for( i=0; i < VO_NUM_RECENT_FRAMES; i++ ) +  { +    if( this->recent_frames[i] ) +      this->recent_frames[i]->vo_frame.dispose +         (&this->recent_frames[i]->vo_frame); +    this->recent_frames[i] = NULL; +  } + +  free (this); +} + +static void xvmc_check_capability (xvmc_driver_t *this, +				 uint32_t capability, +				 int property, XvAttribute attr, +				 int base_id, char *str_prop, +				 char *config_name, +				 char *config_desc) { + +  int         int_default; +  cfg_entry_t *entry; + +  this->capabilities |= capability; + +  /* +   * some Xv drivers (Gatos ATI) report some ~0 as max values, this is confusing. +   */ +  if (VO_CAP_COLORKEY && (attr.max_value == ~0)) +    attr.max_value = 2147483615; + +  this->props[property].min  = attr.min_value; +  this->props[property].max  = attr.max_value; +  this->props[property].atom = XInternAtom (this->display, str_prop, False); + +  XvGetPortAttribute (this->display, this->xv_port, +		      this->props[property].atom, &int_default); + +  printf ("video_out_xvmc: port attribute %s (%d) value is %d\n", +	  str_prop, property, int_default); + +  if (config_name) { +    /* is this a boolean property ? */ +    if ((attr.min_value == 0) && (attr.max_value == 1)) { +      this->config->register_bool (this->config, config_name, int_default, +				   config_desc, +				   NULL, 10, xvmc_property_callback, &this->props[property]); + +    } else { +      this->config->register_range (this->config, config_name, int_default, +				    this->props[property].min, this->props[property].max, +				    config_desc, +				    NULL, 10, xvmc_property_callback, &this->props[property]); +    } + +    entry = this->config->lookup_entry (this->config, config_name); + +    this->props[property].entry = entry; + +    xvmc_set_property (&this->vo_driver, property, entry->num_value); + +    if (capability == VO_CAP_COLORKEY) { +      this->use_colorkey = 1; +      this->colorkey = entry->num_value; +    } +  } else +    this->props[property].value  = int_default; +} + +static void xvmc_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) +{ +  xvmc_driver_t *this = (xvmc_driver_t *) this_gen; + +  //#ifdef LOG +  printf ("video_out_xvmc: xvmc_update_deinterlace method = %d\n",entry->num_value); +  //#endif +   +  this->deinterlace_method = entry->num_value; +} + +static void xvmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) +{ +  xvmc_driver_t *this = (xvmc_driver_t *) this_gen; +  Atom atom; +  int xvmc_double_buffer; +   +  xvmc_double_buffer = entry->num_value; +   +  atom = XInternAtom (this->display, "XV_DOUBLE_BUFFER", False); + +  XvSetPortAttribute (this->display, this->xv_port, atom, xvmc_double_buffer); +  printf("video_out_xvmc: double buffering mode = %d\n",xvmc_double_buffer); +} + +static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { + +  xvmc_class_t         *class = (xvmc_class_t *) class_gen; +  config_values_t      *config = class->config; +  xvmc_driver_t        *this = NULL; +  Display              *display = NULL; +  unsigned int          i, formats; +  XvPortID              xv_port = class->xv_port; +  XvAttribute          *attr; +  XvImageFormatValues  *fo; +  int                   nattr; +  x11_visual_t         *visual = (x11_visual_t *) visual_gen; +  XColor                dummy; +  //  XvImage              *myimage; + +#ifdef LOG +  printf ("video_out_xvmc: open_plugin\n"); +#endif + +  display = visual->display; + +  // TODO ???  +  this = malloc (sizeof (xvmc_driver_t)); + +  if (!this) { +    printf ("video_out_xvmc: malloc failed\n"); +    return NULL; +  } +  +  memset (this, 0, sizeof(xvmc_driver_t)); + +  this->display            = visual->display; +  this->overlay            = NULL; +  this->screen             = visual->screen; +  this->xv_port            = class->xv_port; +  this->config             = config; + +  vo_scale_init (&this->sc, 1, 0, config ); + +  this->sc.frame_output_cb   = visual->frame_output_cb; +  this->sc.user_data         = visual->user_data; + +  this->drawable           = visual->d; +  this->gc                 = XCreateGC(this->display, this->drawable, 0, NULL); +  this->capabilities       = VO_CAP_XVMC_MOCOMP; +  this->expecting_event    = 0; + +  this->surface_type_id    = class->surface_type_id; +  this->max_surface_width  = class->max_surface_width; +  this->max_surface_height = class->max_surface_height; +  this->context_id.xid     = NULL; +  this->num_frame_buffers  = 0; +  this->acceleration       = class->acceleration; + +  // TODO CLEAN UP THIS +  this->user_data          = visual->user_data; + +  this->deinterlace_method = 0; +  this->deinterlace_frame.image = NULL; +  this->use_colorkey       = 0; +  this->colorkey           = 0; + +  XAllocNamedColor(this->display, +		   DefaultColormap(this->display, this->screen), +		   "black", &this->black, &dummy); + +  this->vo_driver.get_capabilities     = xvmc_get_capabilities; +  this->vo_driver.alloc_frame          = xvmc_alloc_frame; +  this->vo_driver.update_frame_format  = xvmc_update_frame_format; +  this->vo_driver.overlay_blend        = xvmc_overlay_blend; +  this->vo_driver.display_frame        = xvmc_display_frame; +  this->vo_driver.get_property         = xvmc_get_property; +  this->vo_driver.set_property         = xvmc_set_property; +  this->vo_driver.get_property_min_max = xvmc_get_property_min_max; +  this->vo_driver.gui_data_exchange    = xvmc_gui_data_exchange; +  this->vo_driver.dispose              = xvmc_dispose; +  this->vo_driver.redraw_needed        = xvmc_redraw_needed; + +  /* +   * init properties +   */ + +  for (i=0; i<VO_NUM_PROPERTIES; i++) { +    this->props[i].value = 0; +    this->props[i].min   = 0; +    this->props[i].max   = 0; +    this->props[i].atom  = None; +    this->props[i].entry = NULL; +    this->props[i].this  = this; +  } + +  this->props[VO_PROP_INTERLACED].value     = 0; +  this->props[VO_PROP_ASPECT_RATIO].value   = XINE_VO_ASPECT_AUTO; +  this->props[VO_PROP_ZOOM_X].value    = 100; +  this->props[VO_PROP_ZOOM_Y].value    = 100; +  this->props[VO_PROP_MAX_NUM_FRAMES].value = MAX_NUM_FRAMES; + +  /* +   * check this adaptor's capabilities +   */ + +  if(this->acceleration&XINE_VO_IDCT_ACCEL)  +    this->capabilities |= VO_CAP_XVMC_IDCT; + +  attr = XvQueryPortAttributes(display, xv_port, &nattr); +  if(attr && nattr) { +    int k; + +    for(k = 0; k < nattr; k++) { +      if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) { +	if(!strcmp(attr[k].name, "XV_HUE")) { +	  xvmc_check_capability (this, VO_CAP_HUE, +				 VO_PROP_HUE, attr[k], +				 class->adaptor_info[class->adaptor_num].base_id, "XV_HUE", +				 NULL, NULL); + +	} else if(!strcmp(attr[k].name, "XV_SATURATION")) { +	  xvmc_check_capability (this, VO_CAP_SATURATION, +				 VO_PROP_SATURATION, attr[k], +				 class->adaptor_info[class->adaptor_num].base_id, "XV_SATURATION", +				 NULL, NULL); + +	} else if(!strcmp(attr[k].name, "XV_BRIGHTNESS")) { +	  xvmc_check_capability (this, VO_CAP_BRIGHTNESS, +				 VO_PROP_BRIGHTNESS, attr[k], +				 class->adaptor_info[class->adaptor_num].base_id, "XV_BRIGHTNESS", +				 NULL, NULL); + +	} else if(!strcmp(attr[k].name, "XV_CONTRAST")) { +	  xvmc_check_capability (this, VO_CAP_CONTRAST, +				 VO_PROP_CONTRAST, attr[k], +				 class->adaptor_info[class->adaptor_num].base_id, "XV_CONTRAST", +				 NULL, NULL); + +	} else if(!strcmp(attr[k].name, "XV_COLORKEY")) { +	  xvmc_check_capability (this, VO_CAP_COLORKEY, +				 VO_PROP_COLORKEY, attr[k], +				 class->adaptor_info[class->adaptor_num].base_id, "XV_COLORKEY", +				 "video.xv_colorkey", +				 _("Colorkey used for Xv video overlay")); + +	} else if(!strcmp(attr[k].name, "XV_AUTOPAINT_COLORKEY")) { +	  xvmc_check_capability (this, VO_CAP_AUTOPAINT_COLORKEY, +				 VO_PROP_AUTOPAINT_COLORKEY, attr[k], +				 class->adaptor_info[class->adaptor_num].base_id, "XV_AUTOPAINT_COLORKEY", +				 NULL, NULL); + +	} else if(!strcmp(attr[k].name, "XV_DOUBLE_BUFFER")) { +	  int xvmc_double_buffer; +	  xvmc_double_buffer = config->register_bool (config, "video.XV_DOUBLE_BUFFER", 1, +						      _("double buffer to sync video to the retrace"), +						      NULL, 10, xvmc_update_XV_DOUBLE_BUFFER, this); +	  config->update_num(config,"video.XV_DOUBLE_BUFFER",xvmc_double_buffer); +	} +      } +    } +    XFree(attr); +  } else { +    printf("video_out_xvmc: no port attributes defined.\n"); +  } + + +  /* +   * check supported image formats +   */ + +  fo = XvListImageFormats(display, this->xv_port, (int*)&formats); + +  this->xvmc_format_yv12 = 0; +  this->xvmc_format_yuy2 = 0; +   +  for(i = 0; i < formats; i++) { +#ifdef LOG +    printf ("video_out_xvmc: XvMC image format: 0x%x (%4.4s) %s\n", +	    fo[i].id, (char*)&fo[i].id, +	    (fo[i].format == XvPacked) ? "packed" : "planar"); +#endif +    if (fo[i].id == XINE_IMGFMT_YV12)  { +      this->xvmc_format_yv12 = fo[i].id; +      this->capabilities |= VO_CAP_YV12; +      printf("video_out_xvmc: this adaptor supports the yv12 format.\n"); +    } else if (fo[i].id == XINE_IMGFMT_YUY2) { +      this->xvmc_format_yuy2 = fo[i].id; +      this->capabilities |= VO_CAP_YUY2; +      printf("video_out_xvmc: this adaptor supports the yuy2 format.\n"); +    } +  } + +  /* +   * try to create a shared image +   * to find out if MIT shm really works, using supported format +   */ +  //  myimage = create_ximage (this, &myshminfo, 100, 100,  +  //			   (this->xvmc_format_yv12 != 0) ? XINE_IMGFMT_YV12 : IMGFMT_YUY2); +  //  dispose_ximage (this, &myshminfo, myimage); + +  this->deinterlace_method = config->register_enum (config, "video.deinterlace_method", 4, +						    deinterlace_methods,  +						    _("Software deinterlace method (Key I toggles deinterlacer on/off)"), +						    NULL, 10, xvmc_update_deinterlace, this); +  this->deinterlace_enabled = 1;  // default is enabled +  printf("video_out_xvmc: deinterlace_methods %d ",this->deinterlace_method); +  switch(this->deinterlace_method) { +  case DEINTERLACE_NONE: printf("NONE\n"); break; +  case DEINTERLACE_BOB: printf("BOB\n"); break; +  case DEINTERLACE_WEAVE: printf("WEAVE\n"); break; +  case DEINTERLACE_GREEDY: printf("GREEDY\n"); break; +  case DEINTERLACE_ONEFIELD: printf("ONEFIELD\n"); break; +  case DEINTERLACE_ONEFIELDXV: printf("ONEFIELDXV\n"); break; +  case DEINTERLACE_LINEARBLEND: printf("LINEARBLEND\n"); break; +  } +  printf("video_out_xvmc: initialization of plugin successful\n"); + +  return &this->vo_driver; +} + +/* + * class functions + */ + +static char* get_identifier (video_driver_class_t *this_gen) { +  return "XvMC"; +} + +static char* get_description (video_driver_class_t *this_gen) { +  return _("xine video output plugin using the XvMC X video extension"); +} + +static void dispose_class (video_driver_class_t *this_gen) { + +  xvmc_class_t        *this = (xvmc_class_t *) this_gen; + +  XvFreeAdaptorInfo (this->adaptor_info); + +  free (this); +} + +static void *init_class (xine_t *xine, void *visual_gen) { + +  x11_visual_t      *visual = (x11_visual_t *) visual_gen; +  xvmc_class_t      *this; +  Display           *display = NULL; +  unsigned int       adaptors, j = 0; +  unsigned int       ver,rel,req,ev,err; +  XvPortID           xv_port; +  XvAdaptorInfo     *adaptor_info; +  unsigned int       adaptor_num; + +  /* XvMC */ +  int                IDCTaccel = 0; +  int                useOverlay = 0; +  int                unsignedIntra = 0; +  unsigned int       surface_num, types; +  unsigned int       max_width=0, max_height=0; +  XvMCSurfaceInfo   *surfaceInfo; +  int                surface_type = 0; + + +  display = visual->display; + +  /* +   * check for Xv and  XvMC video support +   */ + +  printf ("video_out_xvmc: XvMC init_class\n"); + +  if (Success != XvQueryExtension(display,&ver,&rel,&req,&ev,&err)) { +    printf ("video_out_xvmc: Xv extension not present.\n"); +    return NULL; +  } + +  if(!XvMCQueryExtension(display, &ev, &err)) { +    printf ("video_out_xvmc: XvMC extension not present.\n"); +    return 0; +  } + +  /* +   * check adaptors, search for one that supports (at least) yuv12 +   */ + +  if(Success != XvQueryAdaptors(display,DefaultRootWindow(display), +				&adaptors,&adaptor_info))  { +    printf ("video_out_xvmc: XvQueryAdaptors failed.\n"); +    return 0; +  } + +  xv_port = 0; + +  for ( adaptor_num = 0; (adaptor_num < adaptors) && !xv_port; adaptor_num++ ) { +    printf ("video_out_xvmc: checking adaptor %d\n",adaptor_num); +    if (adaptor_info[adaptor_num].type & XvImageMask) { +      surfaceInfo = XvMCListSurfaceTypes(display, adaptor_info[adaptor_num].base_id, +					 &types); +      if(surfaceInfo) { +	for(surface_num  = 0; surface_num < types; surface_num++) { +	  if((surfaceInfo[surface_num].chroma_format == XVMC_CHROMA_FORMAT_420) && +	      (surfaceInfo[surface_num].mc_type == (XVMC_IDCT | XVMC_MPEG_2))) { +	    max_width = surfaceInfo[surface_num].max_width; +	    max_height = surfaceInfo[surface_num].max_height; +	    for(j = 0; j < adaptor_info[adaptor_num].num_ports; j++) { +	      /* try to grab a port */ +	      if(Success == XvGrabPort(display, adaptor_info[adaptor_num].base_id + j, +				       CurrentTime)) +		{    +		  xv_port = adaptor_info[adaptor_num].base_id + j; +		  surface_type = surfaceInfo[j].surface_type_id; +		  break; +		} +	    } +	    if(xv_port) break; +	  } +	} +	if(!xv_port) { // try for just XVMC_MOCOMP  +	  printf ("video_out_xvmc: didn't find XVMC_IDCT acceleration trying for MC\n"); +	  for(surface_num  = 0; surface_num < types; surface_num++) { +	    if((surfaceInfo[surface_num].chroma_format == XVMC_CHROMA_FORMAT_420) && +	       ((surfaceInfo[surface_num].mc_type == (XVMC_MOCOMP | XVMC_MPEG_2)))) { +	      printf ("video_out_xvmc: Found XVMC_MOCOMP\n"); +	      max_width = surfaceInfo[surface_num].max_width; +	      max_height = surfaceInfo[surface_num].max_height; +	      for(j = 0; j < adaptor_info[adaptor_num].num_ports; j++) { +		/* try to grab a port */ +		if(Success == XvGrabPort(display, adaptor_info[adaptor_num].base_id + j, +					 CurrentTime)) +		  {    +		    xv_port = adaptor_info[adaptor_num].base_id + j; +		    surface_type = surfaceInfo[j].surface_type_id; +		    break; +		  } +	      } +	      if(xv_port) break; +	    } +	  } +	} +	if(xv_port) { +	  printf ("video_out_xvmc: port %ld surface %d\n",xv_port,j); +	  if(surfaceInfo[j].flags & XVMC_OVERLAID_SURFACE) +	    useOverlay = 1; +	  if(surfaceInfo[j].flags & XVMC_INTRA_UNSIGNED) +	    unsignedIntra = 1; +	  if(surfaceInfo[j].mc_type == (XVMC_IDCT | XVMC_MPEG_2)) +	    IDCTaccel = XINE_VO_IDCT_ACCEL + XINE_VO_MOTION_ACCEL; +	  else if(surfaceInfo[j].mc_type == (XVMC_MOCOMP | XVMC_MPEG_2)) { +	    IDCTaccel = XINE_VO_MOTION_ACCEL; +	    if(!unsignedIntra) +	      IDCTaccel |= XINE_VO_SIGNED_INTRA; +	  } +	  else  +	    IDCTaccel = 0; +	  printf ("video_out_xvmc: IDCTaccel %02x\n",IDCTaccel); +	  break; +	} +	XFree(surfaceInfo); +      } +    } +  } // outer for adaptor_num loop +  if (!xv_port) { +    printf ("video_out_xvmc: Xv extension is present but " +	    "I couldn't find a usable yuv12 port.\n"); +    printf ("              Looks like your graphics hardware " +	    "driver doesn't support Xv?!\n"); +    /* XvFreeAdaptorInfo (adaptor_info); this crashed on me (gb)*/ +    return NULL; +  } else { +    printf ("video_out_xvmc: using Xv port %ld from adaptor %s\n" +	    "                for hardware colorspace conversion and scaling\n", xv_port, +            adaptor_info[adaptor_num].name); + +    if(IDCTaccel&XINE_VO_IDCT_ACCEL) +      printf ("                idct and motion compensation acceleration \n"); +    else if (IDCTaccel&XINE_VO_MOTION_ACCEL) +      printf ("                motion compensation acceleration only\n"); +    else +      printf ("                no XvMC support \n"); +    printf ("                With Overlay = %d; UnsignedIntra = %d.\n", useOverlay, +	    unsignedIntra); +  } + +  this = (xvmc_class_t *) malloc (sizeof (xvmc_class_t)); + +  if (!this) { +    printf ("video_out_xvmc: malloc failed\n"); +    return NULL; +  } + +  this->driver_class.open_plugin     = open_plugin; +  this->driver_class.get_identifier  = get_identifier; +  this->driver_class.get_description = get_description; +  this->driver_class.dispose         = dispose_class; + +  this->config            = xine->config; +  this->xv_port           = xv_port; +  this->adaptor_info      = adaptor_info; +  this->adaptor_num       = adaptor_num; +  this->surface_type_id   = surface_type; +  this->max_surface_width  = max_width; +  this->max_surface_height = max_height; +  this->acceleration      = IDCTaccel; + +  printf("video_out_xvmc: init_class done\n"); +  return this; +} + +static vo_info_t vo_info_xvmc = { +  /* priority must be low until it supports displaying non-accelerated stuff */ +  0,                    /* priority    */ +  XINE_VISUAL_TYPE_X11  /* visual type */ +}; + +/* + * exported plugin catalog entry + */ + +plugin_info_t xine_plugin_info[] = { +  /* type, API, "name", version, special_info, init_function */ +  { PLUGIN_VIDEO_OUT, 17, "xvmc", XINE_VERSION_CODE, &vo_info_xvmc, init_class }, +  { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; + +#endif diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c index a57f9748f..1b1f70308 100644 --- a/src/xine-engine/post.c +++ b/src/xine-engine/post.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: post.c,v 1.14 2003/08/15 14:38:04 mroi Exp $ + * $Id: post.c,v 1.15 2003/10/06 21:52:44 miguelfreitas Exp $   */  /* @@ -91,7 +91,6 @@ static int post_video_set_property(xine_video_port_t *port_gen, int property, in    return port->original_port->set_property(port->original_port, property, value);  } -  post_video_port_t *post_intercept_video_port(post_plugin_t *post, xine_video_port_t *original) {    post_video_port_t *post_port = (post_video_port_t *)malloc(sizeof(post_video_port_t)); @@ -158,6 +157,33 @@ static void post_frame_dispose(vo_frame_t *vo_img) {    vo_img->dispose(vo_img);  } +static void post_frame_proc_macro_block(int x, +			   int y, +			   int mb_type, +			   int motion_type, +			   int (*mv_field_sel)[2], +			   int *dmvector, +			   int cbp, +			   int dct_type, +			   vo_frame_t *current_frame, +			   vo_frame_t *forward_ref_frame, +			   vo_frame_t *backward_ref_frame, +			   int picture_structure, +			   int second_field, +			   int (*f_mot_pmv)[2], +			   int (*b_mot_pmv)[2]) { +  post_video_port_t *port = (post_video_port_t *)current_frame->port; +  post_restore_video_frame(current_frame, port); +  post_restore_video_frame(forward_ref_frame, port); +  post_restore_video_frame(backward_ref_frame, port); +  current_frame->proc_macro_block(x, y, mb_type, motion_type, mv_field_sel, +                                  dmvector, cbp, dct_type, current_frame, +                                  forward_ref_frame, backward_ref_frame, +                                  picture_structure, second_field,  +                                  f_mot_pmv, b_mot_pmv); +} + +  void post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) {    port->original_frame.port       = frame->port; @@ -167,6 +193,7 @@ void post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) {    port->original_frame.draw       = frame->draw;    port->original_frame.lock       = frame->lock;    port->original_frame.dispose    = frame->dispose; +  port->original_frame.proc_macro_block = frame->proc_macro_block;    frame->port                     = &port->port;    frame->free                     = post_frame_free; @@ -175,6 +202,7 @@ void post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) {    frame->draw                     = post_frame_draw;    frame->lock                     = post_frame_lock;    frame->dispose                  = post_frame_dispose; +  frame->proc_macro_block         = post_frame_proc_macro_block;  }  void post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port) { @@ -185,6 +213,7 @@ void post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port) {    frame->draw                     = port->original_frame.draw;    frame->lock                     = port->original_frame.lock;    frame->dispose                  = port->original_frame.dispose; +  frame->proc_macro_block         = port->original_frame.proc_macro_block;  } diff --git a/src/xine-engine/post.h b/src/xine-engine/post.h index e29f12cdd..8cd658e7a 100644 --- a/src/xine-engine/post.h +++ b/src/xine-engine/post.h @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: post.h,v 1.11 2003/08/15 14:38:04 mroi Exp $ + * $Id: post.h,v 1.12 2003/10/06 21:52:45 miguelfreitas Exp $   *   * post plugin definitions   * @@ -38,7 +38,7 @@  #  include <xine/xineutils.h>  #endif -#define POST_PLUGIN_IFACE_VERSION 4 +#define POST_PLUGIN_IFACE_VERSION 5  typedef struct post_class_s post_class_t; diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 62dda64be..5c8b12c82 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out.c,v 1.171 2003/09/13 16:15:38 miguelfreitas Exp $ + * $Id: video_out.c,v 1.172 2003/10/06 21:52:45 miguelfreitas Exp $   *   * frame allocation / queuing / scheduling / output functions   */ @@ -298,6 +298,7 @@ static vo_frame_t *vo_get_frame (xine_video_port_t *this_gen,    img->progressive_frame  = 0;    img->repeat_first_field = 0;    img->top_field_first    = 1; +  img->macroblocks        = NULL;    extra_info_reset ( img->extra_info );    /* let driver ensure this image has the right format */ diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 957b8aef7..c4cdb2d03 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA   * - * $Id: video_out.h,v 1.96 2003/08/15 14:35:09 mroi Exp $ + * $Id: video_out.h,v 1.97 2003/10/06 21:52:45 miguelfreitas Exp $   *   *   * xine version of video_out.h  @@ -70,6 +70,13 @@ typedef struct extra_info_s extra_info_t;   * adaption of the post plugin decoration layer. Be sure to look into   * src/xine-engine/post.[ch].   */ + +typedef struct xine_macroblock_s { +  short  *blockptr;          // pointer to current dct block +  short  *blockbaseptr;      // pointer to base of dct block array in blocks +  short  xvmc_accel;         // type of acceleration supported +} xine_macroblocks_t; +  struct vo_frame_s {    /*     * member functions @@ -97,6 +104,23 @@ struct vo_frame_s {    /* free memory/resources for this frame */    void (*dispose) (vo_frame_t *vo_img); + +  /* XvMC routine for rendering  macroblocks */ +  void (*proc_macro_block)(int x, +			   int y, +			   int mb_type, +			   int motion_type, +			   int (*mv_field_sel)[2], +			   int *dmvector, +			   int cbp, +			   int dct_type, +			   vo_frame_t *current_frame, +			   vo_frame_t *forward_ref_frame, +			   vo_frame_t *backward_ref_frame, +			   int picture_structure, +			   int second_field, +			   int (*f_mot_pmv)[2], +			   int (*b_mot_pmv)[2]);    /*     * public variables to decoders and vo drivers @@ -119,6 +143,7 @@ struct vo_frame_s {     * that reason, this flag should be interpreted as a "hint".     */    int                        progressive_frame; +  int                        picture_coding_type;    /* pan/scan offset */    int                        pan_scan_x; @@ -136,6 +161,9 @@ struct vo_frame_s {    int                        flags;         /* remember the frame flags */    int                        copy_called;   /* track use of copy() method */ +  /* used to carry macroblocks information for XvMC acceleration */ +  xine_macroblocks_t        *macroblocks; +    /* "backward" references to where this frame originates from */    xine_video_port_t         *port;    vo_driver_t               *driver; @@ -151,7 +179,6 @@ struct vo_frame_s {    int                        id; /* debugging - track this frame */    int                        is_first; -  };  /* @@ -248,11 +275,12 @@ struct xine_video_port_s {  /* get_frame flags */ -#define VO_TOP_FIELD       1 -#define VO_BOTTOM_FIELD    2 -#define VO_BOTH_FIELDS     (VO_TOP_FIELD | VO_BOTTOM_FIELD) -#define VO_PAN_SCAN_FLAG   4 -#define VO_INTERLACED_FLAG 8 +#define VO_TOP_FIELD         1 +#define VO_BOTTOM_FIELD      2 +#define VO_BOTH_FIELDS       (VO_TOP_FIELD | VO_BOTTOM_FIELD) +#define VO_PAN_SCAN_FLAG     4 +#define VO_INTERLACED_FLAG   8 +#define VO_NEW_SEQUENCE_FLAG 16 /* set after MPEG2 Sequence Header Code (used by XvMC) */  /* video driver capabilities */ @@ -269,6 +297,34 @@ struct xine_video_port_s {  #define VO_CAP_CONTRAST               0x00000080 /* driver can set CONTRAST value           */  #define VO_CAP_COLORKEY               0x00000100 /* driver can set COLORKEY value           */  #define VO_CAP_AUTOPAINT_COLORKEY     0x00000200 /* driver can set AUTOPAINT_COLORKEY value */ +#define VO_CAP_XVMC_MOCOMP            0x00000400 /* driver can set XvMC motion compensation */ +#define VO_CAP_XVMC_IDCT              0x00000800 /* driver can use XvMC idct acceleration   */ + +/* macroblock modes */ +#define XINE_MACROBLOCK_INTRA 1 +#define XINE_MACROBLOCK_PATTERN 2 +#define XINE_MACROBLOCK_MOTION_BACKWARD 4 +#define XINE_MACROBLOCK_MOTION_FORWARD 8 +#define XINE_MACROBLOCK_QUANT 16 +#define XINE_MACROBLOCK_DCT_TYPE_INTERLACED 32 + +/* motion types */ +#define XINE_MC_FIELD 1 +#define XINE_MC_FRAME 2 +#define XINE_MC_16X8  2 +#define XINE_MC_DMV   3 + +/* picture coding type */ +#define XINE_PICT_I_TYPE 1 +#define XINE_PICT_P_TYPE 2 +#define XINE_PICT_B_TYPE 3 +#define XINE_PICT_D_TYPE 4 + +/* xvmc acceleration types */ +#define XINE_VO_MOTION_ACCEL   1 +#define XINE_VO_IDCT_ACCEL     2 +#define XINE_VO_SIGNED_INTRA   4 +  /*   * vo_driver_s contains the functions every display driver @@ -279,7 +335,7 @@ struct xine_video_port_s {   * from generic vo functions.   */ -#define VIDEO_OUT_DRIVER_IFACE_VERSION  16 +#define VIDEO_OUT_DRIVER_IFACE_VERSION  17  struct vo_driver_s { | 
