]> git.sesse.net Git - vlc/commitdiff
Support for X11 Unichrome and XvMC extensions. The patch includes hw codec and video_...
authorJean-Paul Saman <jpsaman@videolan.org>
Mon, 23 Oct 2006 21:16:55 +0000 (21:16 +0000)
committerJean-Paul Saman <jpsaman@videolan.org>
Mon, 23 Oct 2006 21:16:55 +0000 (21:16 +0000)
This patch is not tested yet and is disabled by default.

23 files changed:
THANKS
modules/codec/xvmc/Modules.am [new file with mode: 0644]
modules/codec/xvmc/accel_xvmc.h [new file with mode: 0644]
modules/codec/xvmc/alloc.c [new file with mode: 0644]
modules/codec/xvmc/attributes.h [new file with mode: 0644]
modules/codec/xvmc/cpu_accel.c [new file with mode: 0644]
modules/codec/xvmc/cpu_state.c [new file with mode: 0644]
modules/codec/xvmc/decode.c [new file with mode: 0644]
modules/codec/xvmc/header.c [new file with mode: 0644]
modules/codec/xvmc/motion_comp.c [new file with mode: 0644]
modules/codec/xvmc/motion_comp_mmx.c [new file with mode: 0644]
modules/codec/xvmc/mpeg2.h [new file with mode: 0644]
modules/codec/xvmc/mpeg2_internal.h [new file with mode: 0644]
modules/codec/xvmc/slice.c [new file with mode: 0644]
modules/codec/xvmc/slice_xvmc_vld.c [new file with mode: 0644]
modules/codec/xvmc/vlc.h [new file with mode: 0644]
modules/codec/xvmc/xvmc_vld.h [new file with mode: 0644]
modules/codec/xvmc/xxmc-config.h [new file with mode: 0644]
modules/codec/xvmc/xxmc.c [new file with mode: 0644]
modules/video_output/x11/Modules.am
modules/video_output/x11/xcommon.c
modules/video_output/x11/xcommon.h
modules/video_output/x11/xvmc.c [new file with mode: 0644]

diff --git a/THANKS b/THANKS
index da9519ffdb839d285c118b05bb60b13e436c4e79..4c70da31512e3000144aec24a7d7c46465e26550 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -39,6 +39,7 @@ Cédric Cocquebert - Misc opengl effects for the OpenGL Video Output. "Panoramix
 Chris Clepper - OpenGL fix
 Christian Henz - libupnp service discovery plugin, CyberLink UPnP fixes
 Christof Baumgaertner - dbox web intf
+Christophe Burgalat <c.burgalat _at_ broadcastavenue _dot_ com> - XVMC (cle266) patch for VIA boards
 Christophe Mutricy <xtophe at nxtelevision dot com> - many fixes (preferences, M3U, ...)
 Christopher Johnson <cjohnson at mint.net> - Qt fix in vlc.spec
 Colin Simmonds <colin_simmonds at Mac.lover.org> - compile fix for Mac OS X
diff --git a/modules/codec/xvmc/Modules.am b/modules/codec/xvmc/Modules.am
new file mode 100644 (file)
index 0000000..c869287
--- /dev/null
@@ -0,0 +1,19 @@
+SOURCES_xvmc = \
+       xxmc.c \
+       alloc.c \
+       cpu_accel.c \
+       cpu_state.c \
+       decode.c \
+       header.c \
+        motion_comp.c \
+        motion_comp_mmx.c \
+       slice.c \
+       slice_xvmc_vld.c \
+        accel_xvmc.h \
+        attributes.h \
+        xxmc-config.h \
+        mpeg2.h \
+        mpeg2_internal.h \
+        vlc.h \
+        xvmc_vld.h \
+       $(NULL)
diff --git a/modules/codec/xvmc/accel_xvmc.h b/modules/codec/xvmc/accel_xvmc.h
new file mode 100644 (file)
index 0000000..47245f0
--- /dev/null
@@ -0,0 +1,156 @@
+/*****************************************************************************
+ * xvmc.c : Common acceleration definitions for XvMC
+ *****************************************************************************
+ * Copyright (C) 2006 VideoLAN
+ * $Id$
+ *
+ * Authors: Christophe Burgalat <c _dot_ burgalat _at_ broadcastavenue _dot_ com>
+ *          Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+/*
+ * Common acceleration definitions for XvMC
+ *
+ *
+ */
+
+#ifndef HAVE_VLC_ACCEL_H
+#define HAVE_VLC_ACCEL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct vlc_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 */
+} vlc_macroblocks_t;
+
+typedef struct vlc_vld_frame_s
+{
+    int version;              /* Backward compatibility */
+    int mv_ranges[2][2];
+    int picture_structure;
+    int picture_coding_type;
+    int intra_dc_precision;
+    int mpeg_coding;
+    int progressive_sequence;
+    int scan;
+    int pred_dct_frame;
+    int concealment_motion_vectors;
+    int q_scale_type;
+    int intra_vlc_format;
+    int second_field;
+    int load_intra_quantizer_matrix;
+    int load_non_intra_quantizer_matrix;
+    uint8_t intra_quantizer_matrix[64];
+    uint8_t non_intra_quantizer_matrix[64];
+    picture_t *backward_reference_picture;
+    picture_t *forward_reference_picture;
+} vlc_vld_frame_t;
+
+
+typedef struct vlc_xvmc_s
+{
+    vlc_macroblocks_t *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,
+    picture_t *current_picture,picture_t *forward_ref_picture,
+    picture_t *backward_ref_picture,int picture_structure,
+    int second_field,int (*f_mot_pmv)[2],int (*b_mot_pmv)[2]);
+} vlc_xvmc_t ;
+
+typedef struct vlc_xxmc_s
+{
+    /*
+    * We inherit the xine_xvmc_t properties.
+    */
+    vlc_xvmc_t xvmc;
+
+    unsigned mpeg;
+    unsigned acceleration;
+    vlc_fourcc_t fallback_format;
+    vlc_vld_frame_t vld_frame;
+    uint8_t *slice_data;
+    unsigned slice_data_size;
+    unsigned slice_code;
+    int result;
+    int decoded;
+    float sleep;
+    void (*proc_xxmc_update_frame) (picture_t *picture_gen,
+                uint32_t width, uint32_t height, double ratio,
+                int format, int flags);
+    void (*proc_xxmc_begin) (picture_t *vo_img);
+    void (*proc_xxmc_slice) (picture_t *vo_img);
+    void (*proc_xxmc_flush) (picture_t *vo_img);
+    void (*proc_xxmc_flushsync) (picture_t *vo_img);
+} vlc_xxmc_t;
+
+#define VLC_IMGFMT_XXMC VLC_FOURCC('X','x','M','C')
+
+  /*
+   * Register XvMC stream types here.
+   */
+#define VLC_XVMC_MPEG_1 0x00000001
+#define VLC_XVMC_MPEG_2 0x00000002
+#define VLC_XVMC_MPEG_4 0x00000004
+
+  /*
+   * Register XvMC acceleration levels here.
+   */
+#define VLC_XVMC_ACCEL_MOCOMP 0x00000001
+#define VLC_XVMC_ACCEL_IDCT   0x00000002
+#define VLC_XVMC_ACCEL_VLD    0x00000004
+
+/* xvmc acceleration types */
+#define VLC_VO_MOTION_ACCEL   1
+#define VLC_VO_IDCT_ACCEL     2
+#define VLC_VO_SIGNED_INTRA   4
+
+/* motion types */
+#define VLC_MC_FIELD 1
+#define VLC_MC_FRAME 2
+#define VLC_MC_16X8  2
+#define VLC_MC_DMV   3
+
+/* picture coding type */
+#define VLC_PICT_I_TYPE 1
+#define VLC_PICT_P_TYPE 2
+#define VLC_PICT_B_TYPE 3
+#define VLC_PICT_D_TYPE 4
+
+/* macroblock modes */
+#define VLC_MACROBLOCK_INTRA 1
+#define VLC_MACROBLOCK_PATTERN 2
+#define VLC_MACROBLOCK_MOTION_BACKWARD 4
+#define VLC_MACROBLOCK_MOTION_FORWARD 8
+#define VLC_MACROBLOCK_QUANT 16
+#define VLC_MACROBLOCK_DCT_TYPE_INTERLACED 32
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/modules/codec/xvmc/alloc.c b/modules/codec/xvmc/alloc.c
new file mode 100644 (file)
index 0000000..184e9be
--- /dev/null
@@ -0,0 +1,73 @@
+/* $Id:$
+ * alloc.c
+ * Copyright (C) 2000-2003 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 <stdlib.h>
+#include <inttypes.h>
+
+#include "mpeg2.h"
+
+static void * (* malloc_hook) (unsigned size, mpeg2_alloc_t reason) = NULL;
+static int (* free_hook) (void * buf) = NULL;
+
+void * mpeg2_malloc( unsigned size, mpeg2_alloc_t reason )
+{
+    char *buf = NULL;
+
+    if (malloc_hook)
+    {
+        buf = (char *) malloc_hook (size, reason);
+        if (buf)
+            return buf;
+    }
+
+    if (size)
+    {
+        buf = (char *) malloc (size + 63 + sizeof (void **));
+        if (buf)
+        {
+            char * align_buf = NULL;
+
+            align_buf = buf + 63 + sizeof (void **);
+            align_buf -= (long)align_buf & 63;
+            *(((void **)align_buf) - 1) = buf;
+            return align_buf;
+        }
+    }
+    return NULL;
+}
+
+void mpeg2_free( void * buf )
+{
+    if (free_hook && free_hook (buf))
+        return;
+
+    if (buf)
+        free (*(((void **)buf) - 1));
+}
+
+void mpeg2_malloc_hooks( void * malloc (unsigned, mpeg2_alloc_t),
+                         int free (void *) )
+{
+    malloc_hook = malloc;
+    free_hook = free;
+}
diff --git a/modules/codec/xvmc/attributes.h b/modules/codec/xvmc/attributes.h
new file mode 100644 (file)
index 0000000..fe2a2b6
--- /dev/null
@@ -0,0 +1,37 @@
+/* $Id:$
+ * attributes.h
+ * Copyright (C) 2000-2003 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
+ */
+
+/* use gcc attribs to align critical data structures */
+#ifdef ATTRIBUTE_ALIGNED_MAX
+# define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align)))
+#else
+# define ATTR_ALIGN(align)
+#endif
+
+#ifdef HAVE_BUILTIN_EXPECT
+# define likely(x) __builtin_expect ((x) != 0, 1)
+# define unlikely(x) __builtin_expect ((x) != 0, 0)
+#else
+# define likely(x) (x)
+# define unlikely(x) (x)
+#endif
diff --git a/modules/codec/xvmc/cpu_accel.c b/modules/codec/xvmc/cpu_accel.c
new file mode 100644 (file)
index 0000000..d390a92
--- /dev/null
@@ -0,0 +1,114 @@
+/* $Id:$
+ * cpu_accel.c
+ * Copyright (C) 2000-2003 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 <inttypes.h>
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+static inline uint32_t arch_accel( void )
+{
+    uint32_t eax, ebx, ecx, edx;
+    int AMD;
+    uint32_t caps;
+
+#if !defined(PIC) && !defined(__PIC__)
+#define cpuid(op,eax,ebx,ecx,edx) \
+    __asm__ ("cpuid"        \
+         : "=a" (eax),      \
+           "=b" (ebx),      \
+           "=c" (ecx),      \
+           "=d" (edx)       \
+         : "a" (op)         \
+         : "cc")
+#else /* PIC version : save ebx */
+#define cpuid(op,eax,ebx,ecx,edx) \
+    __asm__ ("push %%ebx\n\t"   \
+         "cpuid\n\t"            \
+         "movl %%ebx,%1\n\t"    \
+         "pop %%ebx"        \
+         : "=a" (eax),      \
+           "=r" (ebx),      \
+           "=c" (ecx),      \
+           "=d" (edx)       \
+         : "a" (op)         \
+         : "cc")
+#endif
+
+    __asm__ ("pushf\n\t"
+        "pushf\n\t"
+        "pop %0\n\t"
+        "movl %0,%1\n\t"
+        "xorl $0x200000,%0\n\t"
+        "push %0\n\t"
+        "popf\n\t"
+        "pushf\n\t"
+        "pop %0\n\t"
+        "popf"
+        : "=r" (eax),
+          "=r" (ebx)
+        :
+        : "cc");
+
+    if (eax == ebx) /* no cpuid */
+        return 0;
+
+    cpuid (0x00000000, eax, ebx, ecx, edx);
+    if (!eax) /* vendor string only */
+        return 0;
+
+    AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
+
+    cpuid (0x00000001, eax, ebx, ecx, edx);
+    if (! (edx & 0x00800000))  /* no MMX */
+        return 0;
+
+    caps = MPEG2_ACCEL_X86_MMX;
+    if (edx & 0x02000000)      /* SSE - identical to AMD MMX extensions */
+        caps = MPEG2_ACCEL_X86_MMX | MPEG2_ACCEL_X86_MMXEXT;
+
+    cpuid (0x80000000, eax, ebx, ecx, edx);
+    if (eax < 0x80000001)      /* no extended capabilities */
+        return caps;
+
+    cpuid (0x80000001, eax, ebx, ecx, edx);
+
+    if (edx & 0x80000000)
+        caps |= MPEG2_ACCEL_X86_3DNOW;
+
+    if (AMD && (edx & 0x00400000))     /* AMD MMX extensions */
+        caps |= MPEG2_ACCEL_X86_MMXEXT;
+
+    return caps;
+}
+
+uint32_t mpeg2_detect_accel (void)
+{
+    uint32_t accel;
+
+    accel = 0;
+    accel = arch_accel ();
+
+    return accel;
+}
diff --git a/modules/codec/xvmc/cpu_state.c b/modules/codec/xvmc/cpu_state.c
new file mode 100644 (file)
index 0000000..e2c3acf
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id:$
+ * cpu_state.c
+ * Copyright (C) 2000-2003 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 "xxmc-config.h"
+
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+#ifdef ARCH_X86
+# include "mmx.h"
+#endif
+
+void (* mpeg2_cpu_state_save) (cpu_state_t * state) = NULL;
+void (* mpeg2_cpu_state_restore) (cpu_state_t * state) = NULL;
+
+static void state_restore_mmx (cpu_state_t * state)
+{
+    emms ();
+}
+
+void mpeg2_cpu_state_init (uint32_t accel)
+{
+    if (accel & MPEG2_ACCEL_X86_MMX)
+    {
+        mpeg2_cpu_state_restore = state_restore_mmx;
+    }
+
+}
diff --git a/modules/codec/xvmc/decode.c b/modules/codec/xvmc/decode.c
new file mode 100644 (file)
index 0000000..4ac08dc
--- /dev/null
@@ -0,0 +1,490 @@
+/* $Id:$
+ * decode.c
+ * Copyright (C) 2000-2003 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 "xxmc-config.h"
+
+#include <string.h>    /* memcmp/memset, try to remove */
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+static int mpeg2_accels = 0;
+
+#define BUFFER_SIZE (1194 * 1024)
+
+const mpeg2_info_t *mpeg2_info( mpeg2dec_t * mpeg2dec )
+{
+    return &(mpeg2dec->info);
+}
+
+static inline int skip_chunk( mpeg2dec_t * mpeg2dec, int bytes )
+{
+    uint8_t *current = NULL;
+    uint32_t shift;
+    uint8_t *limit = NULL;
+    uint8_t byte;
+
+    if (!bytes)
+        return 0;
+
+    current = mpeg2dec->buf_start;
+    shift = mpeg2dec->shift;
+    limit = current + bytes;
+
+    do {
+        byte = *current++;
+        if (shift == 0x00000100)
+        {
+            int skipped;
+
+            mpeg2dec->shift = 0xffffff00;
+            skipped = current - mpeg2dec->buf_start;
+            mpeg2dec->buf_start = current;
+            return skipped;
+        }
+        shift = (shift | byte) << 8;
+    } while (current < limit);
+
+    mpeg2dec->shift = shift;
+    mpeg2dec->buf_start = current;
+    return 0;
+}
+
+static inline int copy_chunk( mpeg2dec_t * mpeg2dec, int bytes )
+{
+    uint8_t *current = NULL;
+    uint32_t shift;
+    uint8_t *chunk_ptr = NULL;
+    uint8_t *limit = NULL;
+    uint8_t byte;
+
+    if (!bytes)
+        return 0;
+
+    current = mpeg2dec->buf_start;
+    shift = mpeg2dec->shift;
+    chunk_ptr = mpeg2dec->chunk_ptr;
+    limit = current + bytes;
+
+    do {
+        byte = *current++;
+        if (shift == 0x00000100)
+        {
+            int copied;
+
+            mpeg2dec->shift = 0xffffff00;
+            mpeg2dec->chunk_size = chunk_ptr - mpeg2dec->chunk_start - 3;
+            mpeg2dec->chunk_ptr = chunk_ptr + 1;   
+            copied = current - mpeg2dec->buf_start;
+            mpeg2dec->buf_start = current;
+            return copied;
+        }
+        shift = (shift | byte) << 8;
+        *chunk_ptr++ = byte;
+    } while (current < limit);
+
+    mpeg2dec->shift = shift;
+    mpeg2dec->buf_start = current;
+    return 0;
+}
+
+void mpeg2_buffer( mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end )
+{
+    mpeg2dec->buf_start = start;
+    mpeg2dec->buf_end = end;
+}
+
+int mpeg2_getpos( mpeg2dec_t * mpeg2dec )
+{
+    return mpeg2dec->buf_end - mpeg2dec->buf_start;
+}
+
+static inline mpeg2_state_t seek_chunk( mpeg2dec_t * mpeg2dec )
+{
+    int size, skipped;
+
+    size = mpeg2dec->buf_end - mpeg2dec->buf_start;
+    skipped = skip_chunk (mpeg2dec, size);
+    if (!skipped)
+    {
+        mpeg2dec->bytes_since_tag += size;
+        return STATE_BUFFER;
+    }
+    mpeg2dec->bytes_since_tag += skipped;
+    mpeg2dec->code = mpeg2dec->buf_start[-1];
+    return (mpeg2_state_t)-1;
+}
+
+mpeg2_state_t mpeg2_seek_header( mpeg2dec_t * mpeg2dec )
+{
+    while( (mpeg2dec->code != 0xb3) &&
+           (((mpeg2dec->code != 0xb7) &&
+             (mpeg2dec->code != 0xb8) &&
+             mpeg2dec->code ) ||
+             (mpeg2dec->sequence.width == (unsigned)-1)) )
+    {
+        if (seek_chunk (mpeg2dec) == STATE_BUFFER)
+            return STATE_BUFFER;
+    }
+
+    mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+    mpeg2dec->user_data_len = 0;
+    return (mpeg2dec->code ? mpeg2_parse_header (mpeg2dec) :
+                             mpeg2_header_picture_start (mpeg2dec));
+}
+
+#define RECEIVED(code,state) (((state) << 8) + (code))
+
+mpeg2_state_t mpeg2_parse( mpeg2dec_t * mpeg2dec )
+{
+    int size_buffer, size_chunk, copied;
+
+    if (mpeg2dec->action)
+    {
+        mpeg2_state_t state;
+
+        state = mpeg2dec->action (mpeg2dec);
+        if ((int)state >= 0)
+            return state;
+    }
+
+    while(1)
+    {
+        while( (unsignedint) (mpeg2dec->code - mpeg2dec->first_decode_slice)
+                 < mpeg2dec->nb_decode_slices )
+        {
+            size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
+            size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
+                          mpeg2dec->chunk_ptr);
+
+            if (size_buffer <= size_chunk)
+            {
+                copied = copy_chunk (mpeg2dec, size_buffer);
+                if (!copied)
+                {
+                    mpeg2dec->bytes_since_tag += size_buffer;
+                    mpeg2dec->chunk_ptr += size_buffer;
+                    return STATE_BUFFER;
+                }
+            }
+            else
+            {
+                copied = copy_chunk (mpeg2dec, size_chunk);
+
+                if( !copied )
+                {
+                    /* filled the chunk buffer without finding a start code */
+                    mpeg2dec->bytes_since_tag += size_chunk;
+                    mpeg2dec->action = seek_chunk;
+                    return STATE_INVALID;
+                }
+            }
+            mpeg2dec->bytes_since_tag += copied;
+            mpeg2_xxmc_slice( &(mpeg2dec->decoder), NULL,
+                              mpeg2dec->code,mpeg2dec->chunk_start,
+                              mpeg2dec->chunk_size);
+            mpeg2dec->prev_code = mpeg2dec->code;
+            mpeg2dec->code = mpeg2dec->buf_start[-1];
+            mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
+        }
+
+        if( (unsigned int) (mpeg2dec->code - 1) >= (0xb0 - 1) )
+              break;
+        if( seek_chunk (mpeg2dec) == STATE_BUFFER )
+            return STATE_BUFFER;
+    }
+
+    switch( mpeg2dec->code )
+    {
+        case 0x00:
+            mpeg2dec->action = mpeg2_header_picture_start;
+            return mpeg2dec->state;
+        case 0xb7:
+            mpeg2dec->action = mpeg2_header_end;
+            break;
+        case 0xb3:
+        case 0xb8:
+            mpeg2dec->action = mpeg2_parse_header;
+            break;
+        default:
+            mpeg2dec->action = seek_chunk;
+            return STATE_INVALID;
+    }
+    return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID;
+}
+
+mpeg2_state_t mpeg2_parse_header( mpeg2dec_t * mpeg2dec )
+{
+    static int (* process_header[]) (mpeg2dec_t * mpeg2dec) =
+    {
+        mpeg2_header_picture,
+        mpeg2_header_extension,
+        mpeg2_header_user_data,
+        mpeg2_header_sequence,
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        mpeg2_header_gop
+    };
+    int size_buffer, size_chunk, copied;
+
+    mpeg2dec->action = mpeg2_parse_header;
+    mpeg2dec->info.user_data = NULL;
+    mpeg2dec->info.user_data_len = 0;
+
+    while( 1 )
+    {
+        size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
+        size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
+                      mpeg2dec->chunk_ptr);
+        if( size_buffer <= size_chunk )
+        {
+            copied = copy_chunk (mpeg2dec, size_buffer);
+            if( !copied )
+            {
+                mpeg2dec->bytes_since_tag += size_buffer;
+                mpeg2dec->chunk_ptr += size_buffer;
+                return STATE_BUFFER;
+            }
+        }
+        else
+        {
+            copied = copy_chunk (mpeg2dec, size_chunk);
+            if( !copied )
+            {
+                /* filled the chunk buffer without finding a start code */
+                mpeg2dec->bytes_since_tag += size_chunk;
+                mpeg2dec->code = 0xb4;
+                mpeg2dec->action = mpeg2_seek_header;
+                return STATE_INVALID;
+            }
+        }
+        mpeg2dec->bytes_since_tag += copied;
+
+        if( process_header[mpeg2dec->code & 0x0b](mpeg2dec) )
+        {
+            mpeg2dec->code = mpeg2dec->buf_start[-1];
+            mpeg2dec->action = mpeg2_seek_header;
+            return STATE_INVALID;
+        }
+        mpeg2dec->code = mpeg2dec->buf_start[-1];
+
+        switch( RECEIVED(mpeg2dec->code, mpeg2dec->state) )
+        {
+            /* state transition after a sequence header */
+            case RECEIVED (0x00, STATE_SEQUENCE):
+                mpeg2dec->action = mpeg2_header_picture_start;
+            case RECEIVED (0xb8, STATE_SEQUENCE):
+                mpeg2_header_sequence_finalize( mpeg2dec );
+                break;
+            /* other legal state transitions */
+            case RECEIVED (0x00, STATE_GOP):
+                mpeg2_header_gop_finalize( mpeg2dec );
+                mpeg2dec->action = mpeg2_header_picture_start;
+                break;
+            case RECEIVED (0x01, STATE_PICTURE):
+            case RECEIVED (0x01, STATE_PICTURE_2ND):
+                mpeg2_header_picture_finalize( mpeg2dec, mpeg2_accels );
+                mpeg2dec->action = mpeg2_header_slice_start;
+                break;
+            /* legal headers within a given state */
+            case RECEIVED (0xb2, STATE_SEQUENCE):
+            case RECEIVED (0xb2, STATE_GOP):
+            case RECEIVED (0xb2, STATE_PICTURE):
+            case RECEIVED (0xb2, STATE_PICTURE_2ND):
+            case RECEIVED (0xb5, STATE_SEQUENCE):
+            case RECEIVED (0xb5, STATE_PICTURE):
+            case RECEIVED (0xb5, STATE_PICTURE_2ND):
+                mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
+                continue;
+            default:
+                mpeg2dec->action = mpeg2_seek_header;
+                return STATE_INVALID;
+        }
+        mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+        mpeg2dec->user_data_len = 0;
+        return mpeg2dec->state;
+    }
+}
+
+int mpeg2_convert( mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg )
+{
+    mpeg2_convert_init_t convert_init;
+    int error;
+
+    error = convert( MPEG2_CONVERT_SET, NULL, &(mpeg2dec->sequence), 0,
+                mpeg2_accels, arg, &convert_init );
+    if (!error)
+    {
+        mpeg2dec->convert = convert;
+        mpeg2dec->convert_arg = arg;
+        mpeg2dec->convert_id_size = convert_init.id_size;
+        mpeg2dec->convert_stride = 0;
+    }
+    return error;
+}
+
+int mpeg2_stride( mpeg2dec_t * mpeg2dec, int stride )
+{
+    if (!mpeg2dec->convert)
+    {
+        if (stride < (int) mpeg2dec->sequence.width)
+            stride = mpeg2dec->sequence.width;
+        mpeg2dec->decoder.stride_frame = stride;
+    }
+    else
+    {
+        mpeg2_convert_init_t convert_init;
+
+        stride = mpeg2dec->convert( MPEG2_CONVERT_STRIDE, NULL,
+                                    &(mpeg2dec->sequence), stride,
+                                    mpeg2_accels, mpeg2dec->convert_arg,
+                                    &convert_init );
+        mpeg2dec->convert_id_size = convert_init.id_size;
+        mpeg2dec->convert_stride = stride;
+    }
+    return stride;
+}
+
+void mpeg2_set_buf( mpeg2dec_t * mpeg2dec, uint8_t * buf[3], void * id )
+{
+    mpeg2_fbuf_t * fbuf;
+
+    if (mpeg2dec->custom_fbuf)
+    {
+        if (mpeg2dec->state == STATE_SEQUENCE)
+        {
+            mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1];
+            mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0];
+        }
+        mpeg2_set_fbuf( mpeg2dec,
+                (mpeg2dec->decoder.coding_type == PIC_FLAG_CODING_TYPE_B) );
+        fbuf = mpeg2dec->fbuf[0];
+    }
+    else
+    {
+        fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf);
+        mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index;
+    }
+    fbuf->buf[0] = buf[0];
+    fbuf->buf[1] = buf[1];
+    fbuf->buf[2] = buf[2];
+    fbuf->id = id;
+}
+
+void mpeg2_custom_fbuf( mpeg2dec_t * mpeg2dec, int custom_fbuf )
+{
+    mpeg2dec->custom_fbuf = custom_fbuf;
+}
+
+void mpeg2_skip( mpeg2dec_t * mpeg2dec, int skip )
+{
+    mpeg2dec->first_decode_slice = 1;
+    mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1);
+}
+
+void mpeg2_slice_region( mpeg2dec_t * mpeg2dec, int start, int end )
+{
+    start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start;
+    end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end;
+    mpeg2dec->first_decode_slice = start;
+    mpeg2dec->nb_decode_slices = end - start;
+}
+
+void mpeg2_tag_picture( mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2 )
+{
+    mpeg2dec->tag_previous = mpeg2dec->tag_current;
+    mpeg2dec->tag2_previous = mpeg2dec->tag2_current;
+    mpeg2dec->tag_current = tag;
+    mpeg2dec->tag2_current = tag2;
+    mpeg2dec->num_tags++;
+    mpeg2dec->bytes_since_tag = 0;
+}
+
+uint32_t mpeg2_accel( uint32_t accel )
+{
+    if( !mpeg2_accels )
+    {
+        if( accel & MPEG2_ACCEL_DETECT )
+            accel |= mpeg2_detect_accel ();
+        mpeg2_accels = accel |= MPEG2_ACCEL_DETECT;
+        mpeg2_cpu_state_init (accel);
+        /* mpeg2_idct_init (accel); */
+        mpeg2_mc_init (accel);
+    }
+    return mpeg2_accels & ~MPEG2_ACCEL_DETECT;
+}
+
+void mpeg2_reset( mpeg2dec_t * mpeg2dec, int full_reset )
+{
+    mpeg2dec->buf_start = mpeg2dec->buf_end = NULL;
+    mpeg2dec->num_tags = 0;
+    mpeg2dec->shift = 0xffffff00;
+    mpeg2dec->code = 0xb4;
+    mpeg2dec->action = mpeg2_seek_header;
+    mpeg2dec->state = STATE_INVALID;
+    mpeg2dec->first = 1;
+    mpeg2dec->ptr_forward_ref_picture = NULL;
+    mpeg2dec->ptr_backward_ref_picture = NULL;
+
+    mpeg2_reset_info(&(mpeg2dec->info));
+    mpeg2dec->info.gop = NULL;
+    mpeg2dec->info.user_data = NULL;
+    mpeg2dec->info.user_data_len = 0;
+    if( full_reset )
+    {
+        mpeg2dec->info.sequence = NULL;
+        mpeg2_header_state_init (mpeg2dec);
+    }
+}
+
+mpeg2dec_t *mpeg2_init( void )
+{
+    mpeg2dec_t *mpeg2dec = NULL;
+
+    mpeg2_accel( MPEG2_ACCEL_DETECT );
+    mpeg2dec = (mpeg2dec_t *) mpeg2_malloc( sizeof (mpeg2dec_t),
+                                            MPEG2_ALLOC_MPEG2DEC );
+    if( mpeg2dec == NULL )
+        return NULL;
+
+    memset( mpeg2dec->decoder.DCTblock, 0, 64 * sizeof (int16_t) );
+    memset( mpeg2dec->quantizer_matrix, 0, 4 * 64 * sizeof (uint8_t) );
+
+    mpeg2dec->chunk_buffer = (uint8_t *) mpeg2_malloc( BUFFER_SIZE + 4,
+                                                       MPEG2_ALLOC_CHUNK );
+    mpeg2dec->sequence.width = (unsigned int)-1;
+    mpeg2_reset (mpeg2dec, 1);
+    return mpeg2dec;
+}
+
+void mpeg2_close( mpeg2dec_t * mpeg2dec )
+{
+    mpeg2_header_state_init( mpeg2dec );
+    mpeg2_free( mpeg2dec->chunk_buffer );
+    mpeg2_free( mpeg2dec );
+}
diff --git a/modules/codec/xvmc/header.c b/modules/codec/xvmc/header.c
new file mode 100644 (file)
index 0000000..3428424
--- /dev/null
@@ -0,0 +1,991 @@
+/* $Id:$
+ * header.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 2003      Regis Duchesne <hpreg@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 "xxmc-config.h"
+
+#include <inttypes.h>
+#include <stdlib.h>    /* defines NULL */
+#include <string.h>    /* memcmp */
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+#define SEQ_EXT 2
+#define SEQ_DISPLAY_EXT 4
+#define QUANT_MATRIX_EXT 8
+#define COPYRIGHT_EXT 0x10
+#define PIC_DISPLAY_EXT 0x80
+#define PIC_CODING_EXT 0x100
+
+/* default intra quant matrix, in zig-zag order */
+static const uint8_t default_intra_quantizer_matrix[64] ATTR_ALIGN(16) =
+{
+    8,
+    16, 16,
+    19, 16, 19,
+    22, 22, 22, 22,
+    22, 22, 26, 24, 26,
+    27, 27, 27, 26, 26, 26,
+    26, 27, 27, 27, 29, 29, 29,
+    34, 34, 34, 29, 29, 29, 27, 27,
+    29, 29, 32, 32, 34, 34, 37,
+    38, 37, 35, 35, 34, 35,
+    38, 38, 40, 40, 40,
+    48, 48, 46, 46,
+    56, 56, 58,
+    69, 69,
+    83
+};
+
+uint8_t mpeg2_scan_norm[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[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
+};
+
+void mpeg2_header_state_init( mpeg2dec_t *mpeg2dec )
+{
+    if( mpeg2dec->sequence.width != (unsigned int)-1 )
+    {
+        int i;
+
+        mpeg2dec->sequence.width = (unsigned int)-1;
+        if( !mpeg2dec->custom_fbuf )
+        {
+            for( i = mpeg2dec->alloc_index_user;
+                 i < mpeg2dec->alloc_index; i++ )
+            {
+                mpeg2_free( mpeg2dec->fbuf_alloc[i].fbuf.buf[0] );
+                mpeg2_free( mpeg2dec->fbuf_alloc[i].fbuf.buf[1] );
+                mpeg2_free( mpeg2dec->fbuf_alloc[i].fbuf.buf[2] );
+            }
+        }
+        if( mpeg2dec->convert_start )
+        {
+            for( i = 0; i < 3; i++ )
+            {
+                mpeg2_free( mpeg2dec->yuv_buf[i][0] );
+                mpeg2_free( mpeg2dec->yuv_buf[i][1] );
+                mpeg2_free( mpeg2dec->yuv_buf[i][2] );
+            }
+        }
+        if( mpeg2dec->decoder.convert_id )
+            mpeg2_free( mpeg2dec->decoder.convert_id );
+    }
+    mpeg2dec->decoder.coding_type = I_TYPE;
+    mpeg2dec->decoder.convert = NULL;
+    mpeg2dec->decoder.convert_id = NULL; 
+    mpeg2dec->decoder.load_intra_quantizer_matrix = 1;
+    mpeg2dec->decoder.load_non_intra_quantizer_matrix = 1;
+    mpeg2dec->picture = mpeg2dec->pictures;
+    mpeg2dec->fbuf[0] = &mpeg2dec->fbuf_alloc[0].fbuf;
+    mpeg2dec->fbuf[1] = &mpeg2dec->fbuf_alloc[1].fbuf;
+    mpeg2dec->fbuf[2] = &mpeg2dec->fbuf_alloc[2].fbuf;
+    mpeg2dec->first = 1;
+    mpeg2dec->alloc_index = 0;
+    mpeg2dec->alloc_index_user = 0;
+    mpeg2dec->first_decode_slice = 1;
+    mpeg2dec->nb_decode_slices = 0xb0 - 1;
+    mpeg2dec->convert = NULL;
+    mpeg2dec->convert_start = NULL;
+    mpeg2dec->custom_fbuf = 0;
+    mpeg2dec->yuv_index = 0;
+}
+
+void mpeg2_reset_info( mpeg2_info_t * info )
+{
+    info->current_picture = info->current_picture_2nd = NULL;
+    info->display_picture = info->display_picture_2nd = NULL;
+    info->current_fbuf = info->display_fbuf = info->discard_fbuf = NULL;
+}
+
+static void info_user_data( mpeg2dec_t * mpeg2dec )
+{
+    if( mpeg2dec->user_data_len )
+    {
+        mpeg2dec->info.user_data = mpeg2dec->chunk_buffer;
+        mpeg2dec->info.user_data_len = mpeg2dec->user_data_len - 3;
+    }
+}
+
+int mpeg2_header_sequence( mpeg2dec_t * mpeg2dec )
+{
+    uint8_t * buffer = mpeg2dec->chunk_start;
+    mpeg2_sequence_t * sequence = &(mpeg2dec->new_sequence);
+    static unsigned int frame_period[16] =
+    {
+        0, 1126125, 1125000, 1080000, 900900, 900000, 540000, 450450, 450000,
+        /* unofficial: xing 15 fps */
+        1800000,
+        /* unofficial: libmpeg3 "Unofficial economy rates" 5/10/12/15 fps */
+        5400000, 2700000, 2250000, 1800000, 0, 0
+    };
+    int i;
+
+    if( (buffer[6] & 0x20) != 0x20 )/* missing marker_bit */
+        return 1;
+
+    i = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
+    if( !(sequence->display_width = sequence->picture_width = i >> 12) )
+        return 1;
+    if( !(sequence->display_height = sequence->picture_height = i & 0xfff) )
+        return 1;
+    sequence->width = (sequence->picture_width + 15) & ~15;
+    sequence->height = (sequence->picture_height + 15) & ~15;
+    sequence->chroma_width = sequence->width >> 1;
+    sequence->chroma_height = sequence->height >> 1;
+    sequence->flags = (SEQ_FLAG_PROGRESSIVE_SEQUENCE |
+                       SEQ_VIDEO_FORMAT_UNSPECIFIED);
+    sequence->aspect_ratio_information = buffer[3] >> 4;
+    sequence->pixel_width = sequence->aspect_ratio_information; /* aspect ratio */
+    sequence->frame_period = frame_period[buffer[3] & 15];
+    sequence->byte_rate = (buffer[4]<<10) | (buffer[5]<<2) | (buffer[6]>>6);
+    sequence->vbv_buffer_size = ((buffer[6]<<16)|(buffer[7]<<8))&0x1ff800;
+
+    if( buffer[7] & 4 )
+        sequence->flags |= SEQ_FLAG_CONSTRAINED_PARAMETERS;
+
+    mpeg2dec->copy_matrix = 3;
+    if( buffer[7] & 2 )
+    {
+        for( i = 0; i < 64; i++ )
+            mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] =
+                            (buffer[i+7] << 7) | (buffer[i+8] >> 1);
+        buffer += 64;
+    }
+    else
+    {
+        for( i = 0; i < 64; i++ )
+                mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] =
+                                    default_intra_quantizer_matrix[i];
+    }
+
+    if( buffer[7] & 1 )
+    {
+        for( i = 0; i < 64; i++ )
+            mpeg2dec->new_quantizer_matrix[1][mpeg2_scan_norm[i]] =
+                                                         buffer[i+8];
+    }
+    else
+        memset( mpeg2dec->new_quantizer_matrix[1], 16, 64 );
+
+    mpeg2dec->decoder.load_intra_quantizer_matrix = 1;
+    mpeg2dec->decoder.load_non_intra_quantizer_matrix = 1;
+    sequence->profile_level_id = 0x80;
+    sequence->colour_primaries = 0;
+    sequence->transfer_characteristics = 0;
+    sequence->matrix_coefficients = 0;
+
+    mpeg2dec->ext_state = SEQ_EXT;
+    mpeg2dec->state = STATE_SEQUENCE;
+    mpeg2dec->display_offset_x = mpeg2dec->display_offset_y = 0;
+    mpeg2dec->ptr_forward_ref_picture = NULL;
+    mpeg2dec->ptr_backward_ref_picture = NULL;
+
+    return 0;
+}
+
+static int sequence_ext( mpeg2dec_t * mpeg2dec )
+{
+    uint8_t * buffer = mpeg2dec->chunk_start;
+    mpeg2_sequence_t * sequence = &(mpeg2dec->new_sequence);
+    uint32_t flags;
+
+    if( !(buffer[3] & 1) )
+        return 1;
+
+    sequence->profile_level_id = (buffer[0] << 4) | (buffer[1] >> 4);
+    sequence->display_width = sequence->picture_width +=
+                              ((buffer[1] << 13) | (buffer[2] << 5)) & 0x3000;
+    sequence->display_height = sequence->picture_height +=
+                               (buffer[2] << 7) & 0x3000;
+    sequence->width = (sequence->picture_width + 15) & ~15;
+    sequence->height = (sequence->picture_height + 15) & ~15;
+    flags = sequence->flags | SEQ_FLAG_MPEG2;
+    if( !(buffer[1] & 8) )
+    {
+        flags &= ~SEQ_FLAG_PROGRESSIVE_SEQUENCE;
+        sequence->height = (sequence->height + 31) & ~31;
+    }
+    if( buffer[5] & 0x80 )
+        flags |= SEQ_FLAG_LOW_DELAY;
+    sequence->flags = flags;
+    sequence->chroma_width = sequence->width;
+    sequence->chroma_height = sequence->height;
+
+    switch( buffer[1] & 6 )
+    {
+        case 0:        /* invalid */
+            return 1;
+        case 2:        /* 4:2:0 */
+            sequence->chroma_height >>= 1;
+        case 4:        /* 4:2:2 */
+            sequence->chroma_width >>= 1;
+    }
+
+    sequence->byte_rate += ((buffer[2]<<25) | (buffer[3]<<17)) & 0x3ffc0000;
+    sequence->vbv_buffer_size |= buffer[4] << 21;
+    sequence->frame_period = sequence->frame_period *
+                            ((buffer[5]&31)+1) / (((buffer[5]>>2)&3)+1);
+    mpeg2dec->ext_state = SEQ_DISPLAY_EXT;
+    return 0;
+}
+
+static int sequence_display_ext( mpeg2dec_t * mpeg2dec )
+{
+    uint8_t * buffer = mpeg2dec->chunk_start;
+    mpeg2_sequence_t * sequence = &(mpeg2dec->new_sequence);
+    uint32_t flags;
+
+    flags = ((sequence->flags & ~SEQ_MASK_VIDEO_FORMAT) |
+            ((buffer[0]<<4) & SEQ_MASK_VIDEO_FORMAT));
+    if( buffer[0] & 1 )
+    {
+        flags |= SEQ_FLAG_COLOUR_DESCRIPTION;
+        sequence->colour_primaries = buffer[1];
+        sequence->transfer_characteristics = buffer[2];
+        sequence->matrix_coefficients = buffer[3];
+        buffer += 3;
+    }
+
+    if( !(buffer[2] & 2) )/* missing marker_bit */
+        return 1;
+
+    sequence->display_width = (buffer[1] << 6) | (buffer[2] >> 2);
+    sequence->display_height =
+            ((buffer[2]& 1 ) << 13) | (buffer[3] << 5) | (buffer[4] >> 3);
+
+    return 0;
+}
+
+static inline void finalize_sequence( mpeg2_sequence_t * sequence )
+{
+    int width;
+    int height;
+
+    sequence->byte_rate *= 50;
+
+    if( sequence->flags & SEQ_FLAG_MPEG2 )
+    {
+        switch( sequence->pixel_width )
+        {
+            case 1: /* square pixels */
+                sequence->pixel_width = sequence->pixel_height = 1;
+                return;
+            case 2: /* 4:3 aspect ratio */
+                width = 4; height = 3;
+                break;
+            case 3: /* 16:9 aspect ratio */
+                width = 16; height = 9;
+                break;
+            case 4: /* 2.21:1 aspect ratio */
+                width = 221; height = 100;
+                break;
+            default: /* illegal */
+                sequence->pixel_width = sequence->pixel_height = 0;
+                return;
+        }
+        width *= sequence->display_height;
+        height *= sequence->display_width;
+    }
+    else
+    {
+        if( sequence->byte_rate == 50 * 0x3ffff )
+            sequence->byte_rate = 0; /* mpeg-1 VBR */
+
+        switch( sequence->pixel_width )
+        {
+            case 0:
+            case 15: /* illegal */
+                sequence->pixel_width = sequence->pixel_height = 0;
+                return;
+            case 1: /* square pixels */
+                sequence->pixel_width = sequence->pixel_height = 1;
+                return;
+            case 3: /* 720x576 16:9 */
+                sequence->pixel_width = 64;    sequence->pixel_height = 45;
+                return;
+            case 6: /* 720x480 16:9 */
+                sequence->pixel_width = 32;    sequence->pixel_height = 27;
+                return;
+            case 12: /* 720*480 4:3 */
+                sequence->pixel_width = 8;     sequence->pixel_height = 9;
+                return;
+            default:
+                height = 88 * sequence->pixel_width + 1171;
+                width = 2000;
+        }
+   }
+
+    sequence->pixel_width = width;
+    sequence->pixel_height = height;
+    while (width)
+    { /* find greatest common divisor */
+        int tmp = width;
+        width = height % tmp;
+        height = tmp;
+    }
+    sequence->pixel_width /= height;
+    sequence->pixel_height /= height;
+}
+
+static void copy_matrix( mpeg2dec_t * mpeg2dec, int index )
+{
+    if( memcmp( mpeg2dec->quantizer_matrix[index],
+                mpeg2dec->new_quantizer_matrix[index], 64) )
+    {
+        memcpy( mpeg2dec->quantizer_matrix[index],
+                mpeg2dec->new_quantizer_matrix[index], 64);
+        mpeg2dec->scaled[index] = -1;
+    }
+}
+
+static void finalize_matrix( mpeg2dec_t * mpeg2dec )
+{
+    mpeg2_decoder_t * decoder = &(mpeg2dec->decoder);
+    int i;
+
+    for( i = 0; i < 2; i++ )
+    {
+        if( mpeg2dec->copy_matrix & (1 << i) )
+            copy_matrix (mpeg2dec, i);
+        if( (mpeg2dec->copy_matrix & (4 << i)) &&
+            memcmp( mpeg2dec->quantizer_matrix[i],
+                    mpeg2dec->new_quantizer_matrix[i+2], 64) )
+        {
+            copy_matrix (mpeg2dec, i + 2);
+            decoder->chroma_quantizer[i] = decoder->quantizer_prescale[i+2];
+        }
+        else if( mpeg2dec->copy_matrix & (5 << i) )
+        decoder->chroma_quantizer[i] = decoder->quantizer_prescale[i];
+    }
+#if 0
+    decoder->load_intra_quantizer_matrix = 1;
+    decoder->load_non_intra_quantizer_matrix = 1;
+#endif
+}
+
+static mpeg2_state_t invalid_end_action( mpeg2dec_t * mpeg2dec )
+{
+    mpeg2_reset_info( &(mpeg2dec->info) );
+    mpeg2dec->info.gop = NULL;
+    info_user_data( mpeg2dec );
+    mpeg2_header_state_init( mpeg2dec );
+    mpeg2dec->sequence = mpeg2dec->new_sequence;
+    mpeg2dec->action = mpeg2_seek_header;
+    mpeg2dec->state = STATE_SEQUENCE;
+    return STATE_SEQUENCE;
+}
+
+void mpeg2_header_sequence_finalize (mpeg2dec_t * mpeg2dec)
+{
+    mpeg2_sequence_t * sequence = &(mpeg2dec->new_sequence);
+    mpeg2_decoder_t * decoder = &(mpeg2dec->decoder);
+
+    finalize_sequence (sequence);
+    finalize_matrix (mpeg2dec);
+
+    decoder->mpeg1 = !(sequence->flags & SEQ_FLAG_MPEG2);
+    decoder->progressive_sequence = (sequence->flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE);
+    decoder->aspect_ratio_information = sequence->aspect_ratio_information;
+    decoder->width = sequence->width;
+    decoder->height = sequence->height;
+    decoder->vertical_position_extension = (sequence->picture_height > 2800);
+    decoder->chroma_format = ((sequence->chroma_width == sequence->width) +
+                              (sequence->chroma_height == sequence->height));
+
+    if( mpeg2dec->sequence.width != (unsigned int)-1 )
+    {
+        unsigned int new_byte_rate;
+
+        /*
+         * According to 6.1.1.6, repeat sequence headers should be
+         * identical to the original. However some DVDs dont respect
+         * that and have different bitrates in the repeat sequence
+         * headers. So we'll ignore that in the comparison and still
+         * consider these as repeat sequence headers.
+         *
+         * However, be careful not to alter the current sequence when
+         * returning STATE_INVALID_END.
+         */
+        new_byte_rate = sequence->byte_rate;
+        sequence->byte_rate = mpeg2dec->sequence.byte_rate;
+        if( memcmp( &(mpeg2dec->sequence), sequence,
+                    sizeof (mpeg2_sequence_t)) )
+        {
+            decoder->stride_frame = sequence->width;
+            sequence->byte_rate = new_byte_rate;
+            mpeg2_header_end( mpeg2dec );
+            mpeg2dec->action = invalid_end_action;
+            mpeg2dec->state = STATE_INVALID_END;
+            return;
+        }
+        sequence->byte_rate = new_byte_rate;
+        mpeg2dec->state = STATE_SEQUENCE_REPEATED;
+    }
+    else
+        decoder->stride_frame = sequence->width;
+    mpeg2dec->sequence = *sequence;
+    mpeg2_reset_info( &(mpeg2dec->info) );
+    mpeg2dec->info.sequence = &(mpeg2dec->sequence);
+    mpeg2dec->info.gop = NULL;
+    info_user_data( mpeg2dec );
+}
+
+int mpeg2_header_gop( mpeg2dec_t * mpeg2dec )
+{
+    uint8_t * buffer = mpeg2dec->chunk_start;
+    mpeg2_gop_t * gop = &(mpeg2dec->new_gop);
+
+    if( ! (buffer[1] & 8) )
+        return 1;
+    gop->hours = (buffer[0] >> 2) & 31;
+    gop->minutes = ((buffer[0] << 4) | (buffer[1] >> 4)) & 63;
+    gop->seconds = ((buffer[1] << 3) | (buffer[2] >> 5)) & 63;
+    gop->pictures = ((buffer[2] << 1) | (buffer[3] >> 7)) & 63;
+    gop->flags = (buffer[0] >> 7) | ((buffer[3] >> 4) & 6);
+    mpeg2dec->state = STATE_GOP;
+    return 0;
+}
+
+void mpeg2_header_gop_finalize( mpeg2dec_t * mpeg2dec )
+{
+    mpeg2dec->gop = mpeg2dec->new_gop;
+    mpeg2_reset_info( &(mpeg2dec->info) );
+    mpeg2dec->info.gop = &(mpeg2dec->gop);
+    info_user_data (mpeg2dec);
+}
+
+void mpeg2_set_fbuf( mpeg2dec_t * mpeg2dec, int b_type )
+{
+    int i;
+
+    for( i = 0; i < 3; i++ )
+    {
+        if( (mpeg2dec->fbuf[1] != &mpeg2dec->fbuf_alloc[i].fbuf) &&
+            (mpeg2dec->fbuf[2] != &mpeg2dec->fbuf_alloc[i].fbuf) )
+        {
+            mpeg2dec->fbuf[0] = &mpeg2dec->fbuf_alloc[i].fbuf;
+            mpeg2dec->info.current_fbuf = mpeg2dec->fbuf[0];
+            if( b_type || (mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY) )
+            {
+                if( b_type || mpeg2dec->convert )
+                    mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[0];
+                mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[0];
+            }
+        }
+        break;
+    }
+}
+
+mpeg2_state_t mpeg2_header_picture_start( mpeg2dec_t * mpeg2dec )
+{
+    mpeg2_picture_t * picture = &(mpeg2dec->new_picture);
+
+    mpeg2dec->state = ((mpeg2dec->state != STATE_SLICE_1ST) ?
+                        STATE_PICTURE : STATE_PICTURE_2ND);
+    picture->flags = 0;
+    picture->tag = picture->tag2 = 0;
+    if( mpeg2dec->num_tags )
+    {
+        if( mpeg2dec->bytes_since_tag >= 4 )
+        {
+            mpeg2dec->num_tags = 0;
+            picture->tag = mpeg2dec->tag_current;
+            picture->tag2 = mpeg2dec->tag2_current;
+            picture->flags = PIC_FLAG_TAGS;
+        }
+        else if( mpeg2dec->num_tags > 1 )
+        {
+            mpeg2dec->num_tags = 1;
+            picture->tag = mpeg2dec->tag_previous;
+            picture->tag2 = mpeg2dec->tag2_previous;
+            picture->flags = PIC_FLAG_TAGS;
+        }
+    }
+    picture->display_offset[0].x = picture->display_offset[1].x =
+    picture->display_offset[2].x = mpeg2dec->display_offset_x;
+    picture->display_offset[0].y = picture->display_offset[1].y =
+    picture->display_offset[2].y = mpeg2dec->display_offset_y;
+    return mpeg2_parse_header (mpeg2dec);
+}
+
+int mpeg2_header_picture( mpeg2dec_t * mpeg2dec )
+{
+    uint8_t * buffer = mpeg2dec->chunk_start;
+    mpeg2_picture_t * picture = &(mpeg2dec->new_picture);
+    mpeg2_decoder_t * decoder = &(mpeg2dec->decoder);
+    int type;
+
+    type = (buffer [1] >> 3) & 7;
+    mpeg2dec->ext_state = PIC_CODING_EXT;
+
+    picture->temporal_reference = (buffer[0] << 2) | (buffer[1] >> 6);
+
+    picture->flags |= type;
+
+    if( (type == PIC_FLAG_CODING_TYPE_P) || (type == PIC_FLAG_CODING_TYPE_B) )
+    {
+        /* forward_f_code and backward_f_code - used in mpeg1 only */
+        decoder->f_motion.f_code[1] = (buffer[3] >> 2) & 1;
+        decoder->f_motion.f_code[0] =
+                            (((buffer[3] << 1) | (buffer[4] >> 7)) & 7) - 1;
+        decoder->b_motion.f_code[1] = (buffer[4] >> 6) & 1;
+        decoder->b_motion.f_code[0] = ((buffer[4] >> 3) & 7) - 1;
+    }
+
+    /* XXXXXX decode extra_information_picture as well */
+    picture->nb_fields = 2;
+
+    mpeg2dec->q_scale_type = 0;
+    decoder->intra_dc_precision = 7;
+    decoder->frame_pred_frame_dct = 1;
+    decoder->concealment_motion_vectors = 0;
+    decoder->scan = mpeg2_scan_norm;
+    decoder->picture_structure = FRAME_PICTURE;
+    mpeg2dec->copy_matrix = 0;  
+    return 0;
+}
+
+static int picture_coding_ext( mpeg2dec_t * mpeg2dec )
+{
+    uint8_t * buffer = mpeg2dec->chunk_start;
+    mpeg2_picture_t * picture = &(mpeg2dec->new_picture);
+    mpeg2_decoder_t * decoder = &(mpeg2dec->decoder);
+    uint32_t flags;
+
+    /* pre subtract 1 for use later in compute_motion_vector */
+    decoder->f_motion.f_code[0] = (buffer[0] & 15) - 1;
+    decoder->f_motion.f_code[1] = (buffer[1] >> 4) - 1;
+    decoder->b_motion.f_code[0] = (buffer[1] & 15) - 1;
+    decoder->b_motion.f_code[1] = (buffer[2] >> 4) - 1;
+
+    flags = picture->flags;
+    decoder->intra_dc_precision = 7 - ((buffer[2] >> 2) & 3);
+    decoder->picture_structure = buffer[2] & 3;
+
+    switch (decoder->picture_structure)
+    {
+        case TOP_FIELD:
+            //flags |= PIC_FLAG_TOP_FIELD_FIRST;
+        case BOTTOM_FIELD:
+            picture->nb_fields = 1;
+            break;
+        case FRAME_PICTURE:
+            if( !(mpeg2dec->sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE) )
+            {
+                picture->nb_fields = (buffer[3] & 2) ? 3 : 2;
+                flags |= (buffer[3] & 128) ? PIC_FLAG_TOP_FIELD_FIRST : 0;
+            }
+            else
+                picture->nb_fields = (buffer[3]&2) ? ((buffer[3]&128) ? 6 : 4) : 2;
+            break;
+        default:
+            return 1;
+    }
+    decoder->top_field_first = buffer[3] >> 7;
+
+    if( decoder->top_field_first )
+        flags |= PIC_FLAG_TOP_FIELD_FIRST;
+    decoder->frame_pred_frame_dct = (buffer[3] >> 6) & 1;
+    decoder->concealment_motion_vectors = (buffer[3] >> 5) & 1;
+    decoder->q_scale_type = (buffer[3] >> 4) & 1;
+    mpeg2dec->q_scale_type = buffer[3] & 16;
+    decoder->intra_vlc_format = (buffer[3] >> 3) & 1;
+    decoder->scan = (buffer[3] & 4) ? mpeg2_scan_alt : mpeg2_scan_norm;
+    flags |= (buffer[4] & 0x80) ? PIC_FLAG_PROGRESSIVE_FRAME : 0;
+
+    if( buffer[4] & 0x40 )
+        flags |= (((buffer[4]<<26) | (buffer[5]<<18) | (buffer[6]<<10)) &
+                  PIC_MASK_COMPOSITE_DISPLAY) | PIC_FLAG_COMPOSITE_DISPLAY;
+    picture->flags = flags;
+
+    mpeg2dec->ext_state = PIC_DISPLAY_EXT | COPYRIGHT_EXT | QUANT_MATRIX_EXT;
+    return 0;
+}
+
+static int picture_display_ext( mpeg2dec_t * mpeg2dec )
+{
+    uint8_t * buffer = mpeg2dec->chunk_start;
+    mpeg2_picture_t * picture = &(mpeg2dec->new_picture);
+    int i, nb_pos;
+
+    nb_pos = picture->nb_fields;
+    if( mpeg2dec->sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE )
+        nb_pos >>= 1;
+
+    for( i = 0; i < nb_pos; i++ )
+    {
+        int x, y;
+
+        x = ((buffer[4*i] << 24) | (buffer[4*i+1] << 16) |
+            (buffer[4*i+2] << 8) | buffer[4*i+3]) >> (11-2*i);
+        y = ((buffer[4*i+2] << 24) | (buffer[4*i+3] << 16) |
+            (buffer[4*i+4] << 8) | buffer[4*i+5]) >> (10-2*i);
+        if( !(x & y & 1) )
+            return 1;
+        picture->display_offset[i].x = mpeg2dec->display_offset_x = x >> 1;
+        picture->display_offset[i].y = mpeg2dec->display_offset_y = y >> 1;
+        }
+    }
+    for( ; i < 3; i++ )
+    {
+        picture->display_offset[i].x = mpeg2dec->display_offset_x;
+        picture->display_offset[i].y = mpeg2dec->display_offset_y;
+    }
+    return 0;
+}
+
+void mpeg2_header_picture_finalize( mpeg2dec_t * mpeg2dec, uint32_t accels )
+{
+    mpeg2_decoder_t * decoder = &(mpeg2dec->decoder);
+    int old_type_b = (decoder->coding_type == B_TYPE);
+    int low_delay = mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY;
+
+    finalize_matrix( mpeg2dec );
+    decoder->coding_type = mpeg2dec->new_picture.flags & PIC_MASK_CODING_TYPE;
+
+    /* move in header_process_picture_header */
+    decoder->second_field = (decoder->picture_structure != FRAME_PICTURE) &&
+            !(decoder->second_field);
+
+    if( mpeg2dec->state == STATE_PICTURE )
+    {
+        mpeg2_picture_t * picture;
+        mpeg2_picture_t * other;
+
+        /* decoder->second_field = 0; */
+
+        picture = other = mpeg2dec->pictures;
+        if( old_type_b ^ (mpeg2dec->picture < mpeg2dec->pictures + 2) )
+            picture += 2;
+        else
+            other += 2;
+        mpeg2dec->picture = picture;
+        *picture = mpeg2dec->new_picture;
+
+        if( !old_type_b )
+        {
+            mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1];
+            mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0];
+        }
+        mpeg2dec->fbuf[0] = NULL;
+        mpeg2_reset_info (&(mpeg2dec->info));
+        mpeg2dec->info.current_picture = picture;
+        mpeg2dec->info.display_picture = picture;
+
+        if( decoder->coding_type != B_TYPE )
+        {
+            if (!low_delay)
+            {
+                if (mpeg2dec->first)
+                {
+                    mpeg2dec->info.display_picture = NULL;
+                    mpeg2dec->first = 0;
+                }
+                else
+                {
+                    mpeg2dec->info.display_picture = other;
+                    if (other->nb_fields == 1)
+                        mpeg2dec->info.display_picture_2nd = other + 1;
+                    mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[1];
+                }
+            }
+            if( !low_delay + !mpeg2dec->convert )
+                mpeg2dec->info.discard_fbuf =
+                    mpeg2dec->fbuf[!low_delay + !mpeg2dec->convert];
+        }
+        if (mpeg2dec->convert)
+        {
+            mpeg2_convert_init_t convert_init;
+            if (!mpeg2dec->convert_start)
+            {
+                int y_size, uv_size;
+
+                mpeg2dec->decoder.convert_id =
+                    mpeg2_malloc( mpeg2dec->convert_id_size,
+                                  MPEG2_ALLOC_CONVERT_ID );
+                mpeg2dec->convert( MPEG2_CONVERT_START,
+                                   mpeg2dec->decoder.convert_id,
+                                   &(mpeg2dec->sequence),
+                                   mpeg2dec->convert_stride, accels,
+                                   mpeg2dec->convert_arg, &convert_init );
+                mpeg2dec->convert_start = convert_init.start;
+                mpeg2dec->decoder.convert = convert_init.copy;
+
+                y_size = decoder->stride_frame * mpeg2dec->sequence.height;
+                uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format);
+                mpeg2dec->yuv_buf[0][0] =
+                        (uint8_t *) mpeg2_malloc (y_size, MPEG2_ALLOC_YUV);
+                mpeg2dec->yuv_buf[0][1] =
+                        (uint8_t *) mpeg2_malloc (uv_size, MPEG2_ALLOC_YUV);
+                mpeg2dec->yuv_buf[0][2] =
+                        (uint8_t *) mpeg2_malloc (uv_size, MPEG2_ALLOC_YUV);
+                mpeg2dec->yuv_buf[1][0] =
+                        (uint8_t *) mpeg2_malloc (y_size, MPEG2_ALLOC_YUV);
+                mpeg2dec->yuv_buf[1][1] =
+                        (uint8_t *) mpeg2_malloc (uv_size, MPEG2_ALLOC_YUV);
+                mpeg2dec->yuv_buf[1][2] =
+                        (uint8_t *) mpeg2_malloc (uv_size, MPEG2_ALLOC_YUV);
+                y_size = decoder->stride_frame * 32;
+                uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format);
+                mpeg2dec->yuv_buf[2][0] =
+                        (uint8_t *) mpeg2_malloc (y_size, MPEG2_ALLOC_YUV);
+                mpeg2dec->yuv_buf[2][1] =
+                        (uint8_t *) mpeg2_malloc (uv_size, MPEG2_ALLOC_YUV);
+                mpeg2dec->yuv_buf[2][2] =
+                        (uint8_t *) mpeg2_malloc (uv_size, MPEG2_ALLOC_YUV);
+            }
+            if (!mpeg2dec->custom_fbuf)
+            {
+                while( mpeg2dec->alloc_index < 3 )
+                {
+                    mpeg2_fbuf_t * fbuf;
+
+                    fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index++].fbuf;
+                    fbuf->id = NULL;
+                    fbuf->buf[0] =
+                            (uint8_t *) mpeg2_malloc( convert_init.buf_size[0],
+                                                      MPEG2_ALLOC_CONVERTED );
+                    fbuf->buf[1] =
+                            (uint8_t *) mpeg2_malloc( convert_init.buf_size[1],
+                                                      MPEG2_ALLOC_CONVERTED );
+                    fbuf->buf[2] =
+                            (uint8_t *) mpeg2_malloc( convert_init.buf_size[2],
+                                                      MPEG2_ALLOC_CONVERTED );
+                }
+                mpeg2_set_fbuf( mpeg2dec, (decoder->coding_type == B_TYPE) );
+            }
+        }
+        else if( !mpeg2dec->custom_fbuf )
+        {
+            while (mpeg2dec->alloc_index < 3)
+            {
+                mpeg2_fbuf_t * fbuf;
+                int y_size, uv_size;
+
+                fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index++].fbuf);
+                fbuf->id = NULL;
+                y_size = decoder->stride_frame * mpeg2dec->sequence.height;
+                         uv_size = y_size >> (2 - decoder->chroma_format);
+                fbuf->buf[0] = (uint8_t *) mpeg2_malloc( y_size,
+                                                         MPEG2_ALLOC_YUV );
+                fbuf->buf[1] = (uint8_t *) mpeg2_malloc( uv_size,
+                                                         MPEG2_ALLOC_YUV );
+                fbuf->buf[2] = (uint8_t *) mpeg2_malloc( uv_size,
+                                                         MPEG2_ALLOC_YUV );
+            }
+            mpeg2_set_fbuf (mpeg2dec, (decoder->coding_type == B_TYPE));
+        }
+    }
+    else
+    {
+        /* decoder->second_field = 1; */
+        mpeg2dec->picture++;   /* second field picture */
+        *(mpeg2dec->picture) = mpeg2dec->new_picture;
+        mpeg2dec->info.current_picture_2nd = mpeg2dec->picture;
+        if (low_delay || decoder->coding_type == B_TYPE)
+            mpeg2dec->info.display_picture_2nd = mpeg2dec->picture;
+    }
+    info_user_data( mpeg2dec );
+}
+
+static int copyright_ext( mpeg2dec_t * mpeg2dec )
+{
+    return 0;
+}
+
+static int quant_matrix_ext( mpeg2dec_t * mpeg2dec )
+{
+    uint8_t * buffer = mpeg2dec->chunk_start;
+    int i, j;
+
+    for (i = 0; i < 4; i++)
+    {
+        if (buffer[0] & (8 >> i))
+        {
+            for (j = 0; j < 64; j++)
+                mpeg2dec->new_quantizer_matrix[i][mpeg2_scan_norm[j]] =
+                            (buffer[j] << (i+5)) | (buffer[j+1] >> (3-i));
+            mpeg2dec->copy_matrix |= 1 << i;
+            buffer += 64;
+        }
+    }
+    return 0;
+}
+
+int mpeg2_header_extension( mpeg2dec_t * mpeg2dec )
+{
+    static int (* parser[]) (mpeg2dec_t *) = {
+                    0, sequence_ext, sequence_display_ext, quant_matrix_ext,
+                    copyright_ext, 0, 0, picture_display_ext, picture_coding_ext
+                };
+    int ext, ext_bit;
+
+    ext = mpeg2dec->chunk_start[0] >> 4;
+    ext_bit = 1 << ext;
+
+    if( !(mpeg2dec->ext_state & ext_bit) )
+        return 0; /* ignore illegal extensions */
+    mpeg2dec->ext_state &= ~ext_bit;
+    return parser[ext] (mpeg2dec);
+}
+
+int mpeg2_header_user_data( mpeg2dec_t * mpeg2dec )
+{
+    mpeg2dec->user_data_len += mpeg2dec->chunk_ptr - 1 - mpeg2dec->chunk_start;
+    mpeg2dec->chunk_start = mpeg2dec->chunk_ptr - 1;
+    return 0;
+}
+
+static void prescale( mpeg2dec_t * mpeg2dec, int index )
+{
+    static int non_linear_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
+    };
+    int i, j, k;
+    mpeg2_decoder_t * decoder = &(mpeg2dec->decoder);
+
+    if( mpeg2dec->scaled[index] != mpeg2dec->q_scale_type )
+    {
+        mpeg2dec->scaled[index] = mpeg2dec->q_scale_type;
+        for( i = 0; i < 32; i++ )
+        {
+            k = mpeg2dec->q_scale_type ? non_linear_scale[i] : (i << 1);
+            for( j = 0; j < 64; j++ )
+                decoder->quantizer_prescale[index][i][j] =
+                            k * mpeg2dec->quantizer_matrix[index][j];
+        }
+    }
+}
+
+mpeg2_state_t mpeg2_header_slice_start( mpeg2dec_t * mpeg2dec )
+{
+    mpeg2_decoder_t * decoder = &(mpeg2dec->decoder);
+
+    mpeg2dec->info.user_data = NULL;
+    mpeg2dec->info.user_data_len = 0;
+    mpeg2dec->state = ((mpeg2dec->picture->nb_fields > 1 ||
+                        mpeg2dec->state == STATE_PICTURE_2ND) ?
+                        STATE_SLICE : STATE_SLICE_1ST);
+
+    if (mpeg2dec->decoder.coding_type != D_TYPE)
+    {
+        prescale (mpeg2dec, 0);
+        if( decoder->chroma_quantizer[0] == decoder->quantizer_prescale[2] )
+            prescale (mpeg2dec, 2);
+        if( mpeg2dec->decoder.coding_type != I_TYPE )
+        {
+            prescale (mpeg2dec, 1);
+            if( decoder->chroma_quantizer[1] == decoder->quantizer_prescale[3] )
+                prescale (mpeg2dec, 3);
+        }
+    }
+
+    if( !(mpeg2dec->nb_decode_slices) )
+        mpeg2dec->picture->flags |= PIC_FLAG_SKIP;
+    else if( mpeg2dec->convert_start )
+    {
+        mpeg2dec->convert_start( decoder->convert_id, mpeg2dec->fbuf[0],
+                                 mpeg2dec->picture, mpeg2dec->info.gop );
+
+        if( mpeg2dec->decoder.coding_type == B_TYPE )
+            mpeg2_init_fbuf( &(mpeg2dec->decoder), mpeg2dec->yuv_buf[2],
+                               mpeg2dec->yuv_buf[mpeg2dec->yuv_index ^ 1],
+                               mpeg2dec->yuv_buf[mpeg2dec->yuv_index] );
+        else
+        {
+            mpeg2_init_fbuf( &(mpeg2dec->decoder),
+                             mpeg2dec->yuv_buf[mpeg2dec->yuv_index ^ 1],
+                             mpeg2dec->yuv_buf[mpeg2dec->yuv_index],
+                             mpeg2dec->yuv_buf[mpeg2dec->yuv_index] );
+            if( mpeg2dec->state == STATE_SLICE )
+                mpeg2dec->yuv_index ^= 1;
+        }
+    }
+    else
+    {
+        int b_type;
+
+        b_type = (mpeg2dec->decoder.coding_type == B_TYPE);
+        mpeg2_init_fbuf( &(mpeg2dec->decoder), mpeg2dec->fbuf[0]->buf,
+                         mpeg2dec->fbuf[b_type + 1]->buf,
+                        mpeg2dec->fbuf[b_type]->buf );
+    }
+    mpeg2dec->action = NULL;
+    return (mpeg2_state_t)-1;
+}
+
+static mpeg2_state_t seek_sequence (mpeg2dec_t * mpeg2dec)
+{
+    mpeg2_reset_info (&(mpeg2dec->info));
+    mpeg2dec->info.sequence = NULL;
+    mpeg2dec->info.gop = NULL;
+    mpeg2_header_state_init (mpeg2dec);
+    mpeg2dec->action = mpeg2_seek_header;
+    return mpeg2_seek_header (mpeg2dec);
+}
+
+mpeg2_state_t mpeg2_header_end (mpeg2dec_t * mpeg2dec)
+{
+    mpeg2_picture_t * picture;
+    int b_type;
+
+    b_type = (mpeg2dec->decoder.coding_type == B_TYPE);
+    picture = mpeg2dec->pictures;
+    if( (mpeg2dec->picture >= picture + 2) ^ b_type )
+        picture = mpeg2dec->pictures + 2;
+
+    mpeg2_reset_info (&(mpeg2dec->info));
+    if( !(mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY) )
+    {
+        mpeg2dec->info.display_picture = picture;
+        if( picture->nb_fields == 1 )
+            mpeg2dec->info.display_picture_2nd = picture + 1;
+        mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[b_type];
+        if( !mpeg2dec->convert )
+            mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[b_type + 1];
+    }
+    else if( !mpeg2dec->convert )
+        mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[b_type];
+    mpeg2dec->action = seek_sequence;
+    return STATE_END;
+}
diff --git a/modules/codec/xvmc/motion_comp.c b/modules/codec/xvmc/motion_comp.c
new file mode 100644 (file)
index 0000000..37247aa
--- /dev/null
@@ -0,0 +1,113 @@
+/* $Id:$
+ * motion_comp.c
+ * Copyright (C) 2000-2003 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 <inttypes.h>
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+mpeg2_mc_t mpeg2_mc;
+
+void mpeg2_mc_init (uint32_t accel)
+{
+    if (accel & MPEG2_ACCEL_X86_MMXEXT)
+        mpeg2_mc = mpeg2_mc_mmxext;
+    else if (accel & MPEG2_ACCEL_X86_3DNOW)
+        mpeg2_mc = mpeg2_mc_3dnow;
+    else if (accel & MPEG2_ACCEL_X86_MMX)
+        mpeg2_mc = mpeg2_mc_mmx;
+    else
+        mpeg2_mc = mpeg2_mc_c;
+}
+
+#define avg2(a,b) ((a+b+1)>>1)
+#define avg4(a,b,c,d) ((a+b+c+d+2)>>2)
+
+#define predict_o(i) (ref[i])
+#define predict_x(i) (avg2 (ref[i], ref[i+1]))
+#define predict_y(i) (avg2 (ref[i], (ref+stride)[i]))
+#define predict_xy(i) (avg4 (ref[i], ref[i+1], \
+                            (ref+stride)[i], (ref+stride)[i+1]))
+
+#define put(predictor,i) dest[i] = predictor (i)
+#define avg(predictor,i) dest[i] = avg2 (predictor (i), dest[i])
+
+/* mc function template */
+
+#define MC_FUNC(op,xy)                                                 \
+static void MC_##op##_##xy##_16_c (uint8_t * dest, const uint8_t * ref,        \
+                                  const int stride, int height)        \
+{                                                                      \
+    do {                                                               \
+       op (predict_##xy, 0);                                           \
+       op (predict_##xy, 1);                                           \
+       op (predict_##xy, 2);                                           \
+       op (predict_##xy, 3);                                           \
+       op (predict_##xy, 4);                                           \
+       op (predict_##xy, 5);                                           \
+       op (predict_##xy, 6);                                           \
+       op (predict_##xy, 7);                                           \
+       op (predict_##xy, 8);                                           \
+       op (predict_##xy, 9);                                           \
+       op (predict_##xy, 10);                                          \
+       op (predict_##xy, 11);                                          \
+       op (predict_##xy, 12);                                          \
+       op (predict_##xy, 13);                                          \
+       op (predict_##xy, 14);                                          \
+       op (predict_##xy, 15);                                          \
+       ref += stride;                                                  \
+       dest += stride;                                                 \
+    } while (--height);                                                        \
+}                                                                      \
+static void MC_##op##_##xy##_8_c (uint8_t * dest, const uint8_t * ref, \
+                                 const int stride, int height)         \
+{                                                                      \
+    do {                                                               \
+       op (predict_##xy, 0);                                           \
+       op (predict_##xy, 1);                                           \
+       op (predict_##xy, 2);                                           \
+       op (predict_##xy, 3);                                           \
+       op (predict_##xy, 4);                                           \
+       op (predict_##xy, 5);                                           \
+       op (predict_##xy, 6);                                           \
+       op (predict_##xy, 7);                                           \
+       ref += stride;                                                  \
+       dest += stride;                                                 \
+    } while (--height);                                                        \
+}
+
+/* definitions of the actual mc functions */
+
+MC_FUNC (put,o)
+MC_FUNC (avg,o)
+MC_FUNC (put,x)
+MC_FUNC (avg,x)
+MC_FUNC (put,y)
+MC_FUNC (avg,y)
+MC_FUNC (put,xy)
+MC_FUNC (avg,xy)
+
+MPEG2_MC_EXTERN (c)
diff --git a/modules/codec/xvmc/motion_comp_mmx.c b/modules/codec/xvmc/motion_comp_mmx.c
new file mode 100644 (file)
index 0000000..0eda018
--- /dev/null
@@ -0,0 +1,998 @@
+/* $Id:$
+ * motion_comp_mmx.c
+ * Copyright (C) 2000-2003 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 <inttypes.h>
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+#include "mmx.h"
+
+#define CPU_MMXEXT 0
+#define CPU_3DNOW 1
+
+/* MMX code - needs a rewrite */
+
+/*
+ * Motion Compensation frequently needs to average values using the
+ * formula (x+y+1)>>1. Both MMXEXT and 3Dnow include one instruction
+ * to compute this, but it's been left out of classic MMX.
+ *
+ * We need to be careful of overflows when doing this computation.
+ * Rather than unpacking data to 16-bits, which reduces parallelism,
+ * we use the following formulas:
+ *
+ * (x+y)>>1 == (x&y)+((x^y)>>1)
+ * (x+y+1)>>1 == (x|y)-((x^y)>>1)
+ */
+
+/* some rounding constants */
+static mmx_t mask1 = {0xfefefefefefefefeLL};
+static mmx_t round4 = {0x0002000200020002LL};
+
+/*
+ * This code should probably be compiled with loop unrolling
+ * (ie, -funroll-loops in gcc)becuase some of the loops
+ * use a small static number of iterations. This was written
+ * with the assumption the compiler knows best about when
+ * unrolling will help
+ */
+
+static inline void mmx_zero_reg ()
+{
+    /* load 0 into mm0 */
+    pxor_r2r (mm0, mm0);
+}
+
+static inline void mmx_average_2_U8 (uint8_t * dest, const uint8_t * src1,
+                                    const uint8_t * src2)
+{
+    /* *dest = (*src1 + *src2 + 1)/ 2; */
+
+    movq_m2r (*src1, mm1);     /* load 8 src1 bytes */
+    movq_r2r (mm1, mm2);       /* copy 8 src1 bytes */
+
+    movq_m2r (*src2, mm3);     /* load 8 src2 bytes */
+    movq_r2r (mm3, mm4);       /* copy 8 src2 bytes */
+
+    pxor_r2r (mm1, mm3);       /* xor src1 and src2 */
+    pand_m2r (mask1, mm3);     /* mask lower bits */
+    psrlq_i2r (1, mm3);                /* /2 */
+    por_r2r (mm2, mm4);                /* or src1 and src2 */
+    psubb_r2r (mm3, mm4);      /* subtract subresults */
+    movq_r2m (mm4, *dest);     /* store result in dest */
+}
+
+static inline void mmx_interp_average_2_U8 (uint8_t * dest,
+                                           const uint8_t * src1,
+                                           const uint8_t * src2)
+{
+    /* *dest = (*dest + (*src1 + *src2 + 1)/ 2 + 1)/ 2; */
+
+    movq_m2r (*dest, mm1);     /* load 8 dest bytes */
+    movq_r2r (mm1, mm2);       /* copy 8 dest bytes */
+
+    movq_m2r (*src1, mm3);     /* load 8 src1 bytes */
+    movq_r2r (mm3, mm4);       /* copy 8 src1 bytes */
+
+    movq_m2r (*src2, mm5);     /* load 8 src2 bytes */
+    movq_r2r (mm5, mm6);       /* copy 8 src2 bytes */
+
+    pxor_r2r (mm3, mm5);       /* xor src1 and src2 */
+    pand_m2r (mask1, mm5);     /* mask lower bits */
+    psrlq_i2r (1, mm5);                /* /2 */
+    por_r2r (mm4, mm6);                /* or src1 and src2 */
+    psubb_r2r (mm5, mm6);      /* subtract subresults */
+    movq_r2r (mm6, mm5);       /* copy subresult */
+
+    pxor_r2r (mm1, mm5);       /* xor srcavg and dest */
+    pand_m2r (mask1, mm5);     /* mask lower bits */
+    psrlq_i2r (1, mm5);                /* /2 */
+    por_r2r (mm2, mm6);                /* or srcavg and dest */
+    psubb_r2r (mm5, mm6);      /* subtract subresults */
+    movq_r2m (mm6, *dest);     /* store result in dest */
+}
+
+static inline void mmx_average_4_U8 (uint8_t * dest, const uint8_t * src1,
+                                    const uint8_t * src2,
+                                    const uint8_t * src3,
+                                    const uint8_t * src4)
+{
+    /* *dest = (*src1 + *src2 + *src3 + *src4 + 2)/ 4; */
+
+    movq_m2r (*src1, mm1);     /* load 8 src1 bytes */
+    movq_r2r (mm1, mm2);       /* copy 8 src1 bytes */
+
+    punpcklbw_r2r (mm0, mm1);  /* unpack low src1 bytes */
+    punpckhbw_r2r (mm0, mm2);  /* unpack high src1 bytes */
+
+    movq_m2r (*src2, mm3);     /* load 8 src2 bytes */
+    movq_r2r (mm3, mm4);       /* copy 8 src2 bytes */
+
+    punpcklbw_r2r (mm0, mm3);  /* unpack low src2 bytes */
+    punpckhbw_r2r (mm0, mm4);  /* unpack high src2 bytes */
+
+    paddw_r2r (mm3, mm1);      /* add lows */
+    paddw_r2r (mm4, mm2);      /* add highs */
+
+    /* now have partials in mm1 and mm2 */
+
+    movq_m2r (*src3, mm3);     /* load 8 src3 bytes */
+    movq_r2r (mm3, mm4);       /* copy 8 src3 bytes */
+
+    punpcklbw_r2r (mm0, mm3);  /* unpack low src3 bytes */
+    punpckhbw_r2r (mm0, mm4);  /* unpack high src3 bytes */
+
+    paddw_r2r (mm3, mm1);      /* add lows */
+    paddw_r2r (mm4, mm2);      /* add highs */
+
+    movq_m2r (*src4, mm5);     /* load 8 src4 bytes */
+    movq_r2r (mm5, mm6);       /* copy 8 src4 bytes */
+
+    punpcklbw_r2r (mm0, mm5);  /* unpack low src4 bytes */
+    punpckhbw_r2r (mm0, mm6);  /* unpack high src4 bytes */
+
+    paddw_r2r (mm5, mm1);      /* add lows */
+    paddw_r2r (mm6, mm2);      /* add highs */
+
+    /* now have subtotal in mm1 and mm2 */
+
+    paddw_m2r (round4, mm1);
+    psraw_i2r (2, mm1);                /* /4 */
+    paddw_m2r (round4, mm2);
+    psraw_i2r (2, mm2);                /* /4 */
+
+    packuswb_r2r (mm2, mm1);   /* pack (w/ saturation) */
+    movq_r2m (mm1, *dest);     /* store result in dest */
+}
+
+static inline void mmx_interp_average_4_U8 (uint8_t * dest,
+                                           const uint8_t * src1,
+                                           const uint8_t * src2,
+                                           const uint8_t * src3,
+                                           const uint8_t * src4)
+{
+    /* *dest = (*dest + (*src1 + *src2 + *src3 + *src4 + 2)/ 4 + 1)/ 2; */
+
+    movq_m2r (*src1, mm1);     /* load 8 src1 bytes */
+    movq_r2r (mm1, mm2);       /* copy 8 src1 bytes */
+
+    punpcklbw_r2r (mm0, mm1);  /* unpack low src1 bytes */
+    punpckhbw_r2r (mm0, mm2);  /* unpack high src1 bytes */
+
+    movq_m2r (*src2, mm3);     /* load 8 src2 bytes */
+    movq_r2r (mm3, mm4);       /* copy 8 src2 bytes */
+
+    punpcklbw_r2r (mm0, mm3);  /* unpack low src2 bytes */
+    punpckhbw_r2r (mm0, mm4);  /* unpack high src2 bytes */
+
+    paddw_r2r (mm3, mm1);      /* add lows */
+    paddw_r2r (mm4, mm2);      /* add highs */
+
+    /* now have partials in mm1 and mm2 */
+
+    movq_m2r (*src3, mm3);     /* load 8 src3 bytes */
+    movq_r2r (mm3, mm4);       /* copy 8 src3 bytes */
+
+    punpcklbw_r2r (mm0, mm3);  /* unpack low src3 bytes */
+    punpckhbw_r2r (mm0, mm4);  /* unpack high src3 bytes */
+
+    paddw_r2r (mm3, mm1);      /* add lows */
+    paddw_r2r (mm4, mm2);      /* add highs */
+
+    movq_m2r (*src4, mm5);     /* load 8 src4 bytes */
+    movq_r2r (mm5, mm6);       /* copy 8 src4 bytes */
+
+    punpcklbw_r2r (mm0, mm5);  /* unpack low src4 bytes */
+    punpckhbw_r2r (mm0, mm6);  /* unpack high src4 bytes */
+
+    paddw_r2r (mm5, mm1);      /* add lows */
+    paddw_r2r (mm6, mm2);      /* add highs */
+
+    paddw_m2r (round4, mm1);
+    psraw_i2r (2, mm1);                /* /4 */
+    paddw_m2r (round4, mm2);
+    psraw_i2r (2, mm2);                /* /4 */
+
+    /* now have subtotal/4 in mm1 and mm2 */
+
+    movq_m2r (*dest, mm3);     /* load 8 dest bytes */
+    movq_r2r (mm3, mm4);       /* copy 8 dest bytes */
+
+    packuswb_r2r (mm2, mm1);   /* pack (w/ saturation) */
+    movq_r2r (mm1,mm2);                /* copy subresult */
+
+    pxor_r2r (mm1, mm3);       /* xor srcavg and dest */
+    pand_m2r (mask1, mm3);     /* mask lower bits */
+    psrlq_i2r (1, mm3);                /* /2 */
+    por_r2r (mm2, mm4);                /* or srcavg and dest */
+    psubb_r2r (mm3, mm4);      /* subtract subresults */
+    movq_r2m (mm4, *dest);     /* store result in dest */
+}
+
+/*-----------------------------------------------------------------------*/
+
+static inline void MC_avg_mmx (const int width, int height, uint8_t * dest,
+                              const uint8_t * ref, const int stride)
+{
+    mmx_zero_reg ();
+
+    do
+    {
+        mmx_average_2_U8 (dest, dest, ref);
+
+        if (width == 16)
+            mmx_average_2_U8 (dest+8, dest+8, ref+8);
+
+        dest += stride;
+        ref += stride;
+    } while( --height );
+}
+
+static void MC_avg_o_16_mmx (uint8_t * dest, const uint8_t * ref,
+                            int stride, int height)
+{
+    MC_avg_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_avg_o_8_mmx (uint8_t * dest, const uint8_t * ref,
+                           int stride, int height)
+{
+    MC_avg_mmx (8, height, dest, ref, stride);
+}
+
+/*-----------------------------------------------------------------------*/
+
+static inline void MC_put_mmx (const int width, int height, uint8_t * dest,
+                              const uint8_t * ref, const int stride)
+{
+    mmx_zero_reg ();
+
+    do
+    {
+        movq_m2r (* ref, mm1); /* load 8 ref bytes */
+        movq_r2m (mm1,* dest); /* store 8 bytes at curr */
+
+        if( width == 16 )
+        {
+            movq_m2r (* (ref+8), mm1); /* load 8 ref bytes */
+            movq_r2m (mm1,* (dest+8)); /* store 8 bytes at curr */
+        }
+        dest += stride;
+        ref += stride;
+    } while( --height );
+}
+
+static void MC_put_o_16_mmx (uint8_t * dest, const uint8_t * ref,
+                            int stride, int height)
+{
+    MC_put_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_put_o_8_mmx (uint8_t * dest, const uint8_t * ref,
+                           int stride, int height)
+{
+    MC_put_mmx (8, height, dest, ref, stride);
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* Half pixel interpolation in the x direction */
+static inline void MC_avg_x_mmx (const int width, int height, uint8_t * dest,
+                                const uint8_t * ref, const int stride)
+{
+    mmx_zero_reg ();
+
+    do
+    {
+        mmx_interp_average_2_U8 (dest, ref, ref+1);
+
+        if (width == 16)
+            mmx_interp_average_2_U8 (dest+8, ref+8, ref+9);
+
+        dest += stride;
+        ref += stride;
+    } while( --height );
+}
+
+static void MC_avg_x_16_mmx (uint8_t * dest, const uint8_t * ref,
+                            int stride, int height)
+{
+    MC_avg_x_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_avg_x_8_mmx (uint8_t * dest, const uint8_t * ref,
+                           int stride, int height)
+{
+    MC_avg_x_mmx (8, height, dest, ref, stride);
+}
+
+/*-----------------------------------------------------------------------*/
+
+static inline void MC_put_x_mmx (const int width, int height, uint8_t * dest,
+                                const uint8_t * ref, const int stride)
+{
+    mmx_zero_reg ();
+
+    do
+    {
+        mmx_average_2_U8 (dest, ref, ref+1);
+
+        if (width == 16)
+            mmx_average_2_U8 (dest+8, ref+8, ref+9);
+
+        dest += stride;
+        ref += stride;
+    } while (--height);
+}
+
+static void MC_put_x_16_mmx (uint8_t * dest, const uint8_t * ref,
+                            int stride, int height)
+{
+    MC_put_x_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_put_x_8_mmx (uint8_t * dest, const uint8_t * ref,
+                           int stride, int height)
+{
+    MC_put_x_mmx (8, height, dest, ref, stride);
+}
+
+/*-----------------------------------------------------------------------*/
+
+static inline void MC_avg_xy_mmx (const int width, int height, uint8_t * dest,
+                                 const uint8_t * ref, const int stride)
+{
+    const uint8_t * ref_next = ref + stride;
+
+    mmx_zero_reg ();
+
+    do
+    {
+        mmx_interp_average_4_U8 (dest, ref, ref+1, ref_next, ref_next+1);
+
+        if (width == 16)
+            mmx_interp_average_4_U8( dest+8, ref+8, ref+9,
+                                     ref_next+8, ref_next+9 );
+
+        dest += stride;
+        ref += stride;
+        ref_next += stride;
+    } while( --height );
+}
+
+static void MC_avg_xy_16_mmx (uint8_t * dest, const uint8_t * ref,
+                             int stride, int height)
+{
+    MC_avg_xy_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_avg_xy_8_mmx (uint8_t * dest, const uint8_t * ref,
+                            int stride, int height)
+{
+    MC_avg_xy_mmx (8, height, dest, ref, stride);
+}
+
+/*-----------------------------------------------------------------------*/
+
+static inline void MC_put_xy_mmx (const int width, int height, uint8_t * dest,
+                                 const uint8_t * ref, const int stride)
+{
+    const uint8_t * ref_next = ref + stride;
+
+    mmx_zero_reg ();
+
+    do
+    {
+        mmx_average_4_U8 (dest, ref, ref+1, ref_next, ref_next+1);
+
+        if (width == 16)
+            mmx_average_4_U8( dest+8, ref+8, ref+9, ref_next+8, ref_next+9 );
+
+        dest += stride;
+        ref += stride;
+        ref_next += stride;
+    } while (--height);
+}
+
+static void MC_put_xy_16_mmx (uint8_t * dest, const uint8_t * ref,
+                             int stride, int height)
+{
+    MC_put_xy_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_put_xy_8_mmx (uint8_t * dest, const uint8_t * ref,
+                            int stride, int height)
+{
+    MC_put_xy_mmx (8, height, dest, ref, stride);
+}
+
+/*-----------------------------------------------------------------------*/
+
+static inline void MC_avg_y_mmx (const int width, int height, uint8_t * dest,
+                                const uint8_t * ref, const int stride)
+{
+    const uint8_t * ref_next = ref + stride;
+
+    mmx_zero_reg ();
+
+    do
+    {
+        mmx_interp_average_2_U8 (dest, ref, ref_next);
+
+        if (width == 16)
+            mmx_interp_average_2_U8( dest+8, ref+8, ref_next+8 );
+
+        dest += stride;
+        ref += stride;
+        ref_next += stride;
+    } while (--height);
+}
+
+static void MC_avg_y_16_mmx (uint8_t * dest, const uint8_t * ref,
+                            int stride, int height)
+{
+    MC_avg_y_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_avg_y_8_mmx (uint8_t * dest, const uint8_t * ref,
+                           int stride, int height)
+{
+    MC_avg_y_mmx (8, height, dest, ref, stride);
+}
+
+/*-----------------------------------------------------------------------*/
+
+static inline void MC_put_y_mmx (const int width, int height, uint8_t * dest,
+                                const uint8_t * ref, const int stride)
+{
+    const uint8_t * ref_next = ref + stride;
+
+    mmx_zero_reg ();
+
+    do
+    {
+        mmx_average_2_U8 (dest, ref, ref_next);
+
+        if (width == 16)
+            mmx_average_2_U8( dest+8, ref+8, ref_next+8 );
+
+        dest += stride;
+        ref += stride;
+        ref_next += stride;
+    } while (--height);
+}
+
+static void MC_put_y_16_mmx (uint8_t * dest, const uint8_t * ref,
+                            int stride, int height)
+{
+    MC_put_y_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_put_y_8_mmx (uint8_t * dest, const uint8_t * ref,
+                           int stride, int height)
+{
+    MC_put_y_mmx (8, height, dest, ref, stride);
+}
+
+
+MPEG2_MC_EXTERN (mmx)
+
+/* CPU_MMXEXT/CPU_3DNOW adaptation layer */
+
+#define pavg_r2r(src,dest)             \
+do {                                   \
+    if (cpu == CPU_MMXEXT)             \
+       pavgb_r2r (src, dest);          \
+    else                               \
+       pavgusb_r2r (src, dest);        \
+} while (0)
+
+#define pavg_m2r(src,dest)             \
+do {                                   \
+    if (cpu == CPU_MMXEXT)             \
+       pavgb_m2r (src, dest);          \
+    else                               \
+       pavgusb_m2r (src, dest);        \
+} while (0)
+
+
+/* CPU_MMXEXT code */
+
+
+static inline void MC_put1_8 (int height, uint8_t * dest, const uint8_t * ref,
+                             const int stride)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        movq_r2m (mm0, *dest);
+        ref += stride;
+        dest += stride;
+    } while (--height);
+}
+
+static inline void MC_put1_16 (int height, uint8_t * dest, const uint8_t * ref,
+                              const int stride)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        movq_m2r (*(ref+8), mm1);
+        ref += stride;
+        movq_r2m (mm0, *dest);
+        movq_r2m (mm1, *(dest+8));
+        dest += stride;
+    } while (--height);
+}
+
+static inline void MC_avg1_8 (int height, uint8_t * dest, const uint8_t * ref,
+                             const int stride, const int cpu)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        pavg_m2r (*dest, mm0);
+        ref += stride;
+        movq_r2m (mm0, *dest);
+        dest += stride;
+    } while (--height);
+}
+
+static inline void MC_avg1_16 (int height, uint8_t * dest, const uint8_t * ref,
+                              const int stride, const int cpu)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        movq_m2r (*(ref+8), mm1);
+        pavg_m2r (*dest, mm0);
+        pavg_m2r (*(dest+8), mm1);
+        movq_r2m (mm0, *dest);
+        ref += stride;
+        movq_r2m (mm1, *(dest+8));
+        dest += stride;
+    } while (--height);
+}
+
+static inline void MC_put2_8 (int height, uint8_t * dest, const uint8_t * ref,
+                             const int stride, const int offset,
+                             const int cpu)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        pavg_m2r (*(ref+offset), mm0);
+        ref += stride;
+        movq_r2m (mm0, *dest);
+        dest += stride;
+    } while (--height);
+}
+
+static inline void MC_put2_16 (int height, uint8_t * dest, const uint8_t * ref,
+                              const int stride, const int offset,
+                              const int cpu)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        movq_m2r (*(ref+8), mm1);
+        pavg_m2r (*(ref+offset), mm0);
+        pavg_m2r (*(ref+offset+8), mm1);
+        movq_r2m (mm0, *dest);
+        ref += stride;
+        movq_r2m (mm1, *(dest+8));
+        dest += stride;
+    } while (--height);
+}
+
+static inline void MC_avg2_8 (int height, uint8_t * dest, const uint8_t * ref,
+                             const int stride, const int offset,
+                             const int cpu)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        pavg_m2r (*(ref+offset), mm0);
+        pavg_m2r (*dest, mm0);
+        ref += stride;
+        movq_r2m (mm0, *dest);
+        dest += stride;
+    } while (--height);
+}
+
+static inline void MC_avg2_16 (int height, uint8_t * dest, const uint8_t * ref,
+                              const int stride, const int offset,
+                              const int cpu)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        movq_m2r (*(ref+8), mm1);
+        pavg_m2r (*(ref+offset), mm0);
+        pavg_m2r (*(ref+offset+8), mm1);
+        pavg_m2r (*dest, mm0);
+        pavg_m2r (*(dest+8), mm1);
+        ref += stride;
+        movq_r2m (mm0, *dest);
+        movq_r2m (mm1, *(dest+8));
+        dest += stride;
+    } while (--height);
+}
+
+static mmx_t mask_one = {0x0101010101010101LL};
+
+static inline void MC_put4_8 (int height, uint8_t * dest, const uint8_t * ref,
+                             const int stride, const int cpu)
+{
+    movq_m2r (*ref, mm0);
+    movq_m2r (*(ref+1), mm1);
+    movq_r2r (mm0, mm7);
+    pxor_r2r (mm1, mm7);
+    pavg_r2r (mm1, mm0);
+    ref += stride;
+
+    do {
+        movq_m2r (*ref, mm2);
+        movq_r2r (mm0, mm5);
+
+        movq_m2r (*(ref+1), mm3);
+        movq_r2r (mm2, mm6);
+
+        pxor_r2r (mm3, mm6);
+        pavg_r2r (mm3, mm2);
+
+        por_r2r (mm6, mm7);
+        pxor_r2r (mm2, mm5);
+
+        pand_r2r (mm5, mm7);
+        pavg_r2r (mm2, mm0);
+
+        pand_m2r (mask_one, mm7);
+
+        psubusb_r2r (mm7, mm0);
+
+        ref += stride;
+        movq_r2m (mm0, *dest);
+        dest += stride;
+
+        movq_r2r (mm6, mm7);   /* unroll ! */
+        movq_r2r (mm2, mm0);   /* unroll ! */
+    } while (--height);
+}
+
+static inline void MC_put4_16 (int height, uint8_t * dest, const uint8_t * ref,
+                              const int stride, const int cpu)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        movq_m2r (*(ref+stride+1), mm1);
+        movq_r2r (mm0, mm7);
+        movq_m2r (*(ref+1), mm2);
+        pxor_r2r (mm1, mm7);
+        movq_m2r (*(ref+stride), mm3);
+        movq_r2r (mm2, mm6);
+        pxor_r2r (mm3, mm6);
+        pavg_r2r (mm1, mm0);
+        pavg_r2r (mm3, mm2);
+        por_r2r (mm6, mm7);
+        movq_r2r (mm0, mm6);
+        pxor_r2r (mm2, mm6);
+        pand_r2r (mm6, mm7);
+        pand_m2r (mask_one, mm7);
+        pavg_r2r (mm2, mm0);
+        psubusb_r2r (mm7, mm0);
+        movq_r2m (mm0, *dest);
+
+        movq_m2r (*(ref+8), mm0);
+        movq_m2r (*(ref+stride+9), mm1);
+        movq_r2r (mm0, mm7);
+        movq_m2r (*(ref+9), mm2);
+        pxor_r2r (mm1, mm7);
+        movq_m2r (*(ref+stride+8), mm3);
+        movq_r2r (mm2, mm6);
+        pxor_r2r (mm3, mm6);
+        pavg_r2r (mm1, mm0);
+        pavg_r2r (mm3, mm2);
+        por_r2r (mm6, mm7);
+        movq_r2r (mm0, mm6);
+        pxor_r2r (mm2, mm6);
+        pand_r2r (mm6, mm7);
+        pand_m2r (mask_one, mm7);
+        pavg_r2r (mm2, mm0);
+        psubusb_r2r (mm7, mm0);
+        ref += stride;
+        movq_r2m (mm0, *(dest+8));
+        dest += stride;
+    } while (--height);
+}
+
+static inline void MC_avg4_8 (int height, uint8_t * dest, const uint8_t * ref,
+                             const int stride, const int cpu)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        movq_m2r (*(ref+stride+1), mm1);
+        movq_r2r (mm0, mm7);
+        movq_m2r (*(ref+1), mm2);
+        pxor_r2r (mm1, mm7);
+        movq_m2r (*(ref+stride), mm3);
+        movq_r2r (mm2, mm6);
+        pxor_r2r (mm3, mm6);
+        pavg_r2r (mm1, mm0);
+        pavg_r2r (mm3, mm2);
+        por_r2r (mm6, mm7);
+        movq_r2r (mm0, mm6);
+        pxor_r2r (mm2, mm6);
+        pand_r2r (mm6, mm7);
+        pand_m2r (mask_one, mm7);
+        pavg_r2r (mm2, mm0);
+        psubusb_r2r (mm7, mm0);
+        movq_m2r (*dest, mm1);
+        pavg_r2r (mm1, mm0);
+        ref += stride;
+        movq_r2m (mm0, *dest);
+        dest += stride;
+    } while (--height);
+}
+
+static inline void MC_avg4_16 (int height, uint8_t * dest, const uint8_t * ref,
+                              const int stride, const int cpu)
+{
+    do {
+        movq_m2r (*ref, mm0);
+        movq_m2r (*(ref+stride+1), mm1);
+        movq_r2r (mm0, mm7);
+        movq_m2r (*(ref+1), mm2);
+        pxor_r2r (mm1, mm7);
+        movq_m2r (*(ref+stride), mm3);
+        movq_r2r (mm2, mm6);
+        pxor_r2r (mm3, mm6);
+        pavg_r2r (mm1, mm0);
+        pavg_r2r (mm3, mm2);
+        por_r2r (mm6, mm7);
+        movq_r2r (mm0, mm6);
+        pxor_r2r (mm2, mm6);
+        pand_r2r (mm6, mm7);
+        pand_m2r (mask_one, mm7);
+        pavg_r2r (mm2, mm0);
+        psubusb_r2r (mm7, mm0);
+        movq_m2r (*dest, mm1);
+        pavg_r2r (mm1, mm0);
+        movq_r2m (mm0, *dest);
+
+        movq_m2r (*(ref+8), mm0);
+        movq_m2r (*(ref+stride+9), mm1);
+        movq_r2r (mm0, mm7);
+        movq_m2r (*(ref+9), mm2);
+        pxor_r2r (mm1, mm7);
+        movq_m2r (*(ref+stride+8), mm3);
+        movq_r2r (mm2, mm6);
+        pxor_r2r (mm3, mm6);
+        pavg_r2r (mm1, mm0);
+        pavg_r2r (mm3, mm2);
+        por_r2r (mm6, mm7);
+        movq_r2r (mm0, mm6);
+        pxor_r2r (mm2, mm6);
+        pand_r2r (mm6, mm7);
+        pand_m2r (mask_one, mm7);
+        pavg_r2r (mm2, mm0);
+        psubusb_r2r (mm7, mm0);
+        movq_m2r (*(dest+8), mm1);
+        pavg_r2r (mm1, mm0);
+        ref += stride;
+        movq_r2m (mm0, *(dest+8));
+        dest += stride;
+    } while (--height);
+}
+
+static void MC_avg_o_16_mmxext (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_avg1_16 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_o_8_mmxext (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_avg1_8 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_put_o_16_mmxext (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_put1_16 (height, dest, ref, stride);
+}
+
+static void MC_put_o_8_mmxext (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_put1_8 (height, dest, ref, stride);
+}
+
+static void MC_avg_x_16_mmxext (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_avg2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_avg_x_8_mmxext (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_avg2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_put_x_16_mmxext (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_put2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_put_x_8_mmxext (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_put2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_avg_y_16_mmxext (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_avg2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_y_8_mmxext (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_avg2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_put_y_16_mmxext (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_put2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_put_y_8_mmxext (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_put2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_xy_16_mmxext (uint8_t * dest, const uint8_t * ref,
+                                int stride, int height)
+{
+    MC_avg4_16 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_xy_8_mmxext (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_avg4_8 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_put_xy_16_mmxext (uint8_t * dest, const uint8_t * ref,
+                                int stride, int height)
+{
+    MC_put4_16 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_put_xy_8_mmxext (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_put4_8 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+MPEG2_MC_EXTERN (mmxext)
+
+static void MC_avg_o_16_3dnow (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_avg1_16 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_avg_o_8_3dnow (uint8_t * dest, const uint8_t * ref,
+                             int stride, int height)
+{
+    MC_avg1_8 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_put_o_16_3dnow (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_put1_16 (height, dest, ref, stride);
+}
+
+static void MC_put_o_8_3dnow (uint8_t * dest, const uint8_t * ref,
+                             int stride, int height)
+{
+    MC_put1_8 (height, dest, ref, stride);
+}
+
+static void MC_avg_x_16_3dnow (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_avg2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_avg_x_8_3dnow (uint8_t * dest, const uint8_t * ref,
+                             int stride, int height)
+{
+    MC_avg2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_put_x_16_3dnow (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_put2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_put_x_8_3dnow (uint8_t * dest, const uint8_t * ref,
+                             int stride, int height)
+{
+    MC_put2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_avg_y_16_3dnow (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_avg2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_avg_y_8_3dnow (uint8_t * dest, const uint8_t * ref,
+                             int stride, int height)
+{
+    MC_avg2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_put_y_16_3dnow (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_put2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_put_y_8_3dnow (uint8_t * dest, const uint8_t * ref,
+                             int stride, int height)
+{
+    MC_put2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_avg_xy_16_3dnow (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_avg4_16 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_avg_xy_8_3dnow (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_avg4_8 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_put_xy_16_3dnow (uint8_t * dest, const uint8_t * ref,
+                               int stride, int height)
+{
+    MC_put4_16 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_put_xy_8_3dnow (uint8_t * dest, const uint8_t * ref,
+                              int stride, int height)
+{
+    MC_put4_8 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+MPEG2_MC_EXTERN (3dnow)
+
diff --git a/modules/codec/xvmc/mpeg2.h b/modules/codec/xvmc/mpeg2.h
new file mode 100644 (file)
index 0000000..fad180f
--- /dev/null
@@ -0,0 +1,207 @@
+/* $Id:$
+ * mpeg2.h
+ * Copyright (C) 2000-2003 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
+ */
+
+#ifndef MPEG2_H
+#define MPEG2_H
+
+#define MPEG2_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c))
+#define MPEG2_RELEASE MPEG2_VERSION (0, 4, 0)  /* 0.4.0 */
+
+#define SEQ_FLAG_MPEG2 1
+#define SEQ_FLAG_CONSTRAINED_PARAMETERS 2
+#define SEQ_FLAG_PROGRESSIVE_SEQUENCE 4
+#define SEQ_FLAG_LOW_DELAY 8
+#define SEQ_FLAG_COLOUR_DESCRIPTION 16
+
+#define SEQ_MASK_VIDEO_FORMAT 0xe0
+#define SEQ_VIDEO_FORMAT_COMPONENT 0
+#define SEQ_VIDEO_FORMAT_PAL 0x20
+#define SEQ_VIDEO_FORMAT_NTSC 0x40
+#define SEQ_VIDEO_FORMAT_SECAM 0x60
+#define SEQ_VIDEO_FORMAT_MAC 0x80
+#define SEQ_VIDEO_FORMAT_UNSPECIFIED 0xa0
+
+typedef struct mpeg2_sequence_s
+{
+    unsigned int width, height;
+    unsigned int chroma_width, chroma_height;
+    unsigned int byte_rate;
+    unsigned int vbv_buffer_size;
+    uint32_t flags;
+
+    unsigned int picture_width, picture_height;
+    unsigned int display_width, display_height;
+    unsigned int pixel_width, pixel_height;
+    unsigned int frame_period;
+
+    uint8_t profile_level_id;
+    uint8_t colour_primaries;
+    uint8_t transfer_characteristics;
+    uint8_t matrix_coefficients;
+    int aspect_ratio_information;    
+} mpeg2_sequence_t;
+
+#define GOP_FLAG_DROP_FRAME 1
+#define GOP_FLAG_BROKEN_LINK 2
+#define GOP_FLAG_CLOSED_GOP 4
+
+typedef struct mpeg2_gop_s
+{
+    uint8_t hours;
+    uint8_t minutes;
+    uint8_t seconds;
+    uint8_t pictures;
+    uint32_t flags;
+} mpeg2_gop_t;
+
+#define PIC_MASK_CODING_TYPE 7
+#define PIC_FLAG_CODING_TYPE_I 1
+#define PIC_FLAG_CODING_TYPE_P 2
+#define PIC_FLAG_CODING_TYPE_B 3
+#define PIC_FLAG_CODING_TYPE_D 4
+
+#define PIC_FLAG_TOP_FIELD_FIRST 8
+#define PIC_FLAG_PROGRESSIVE_FRAME 16
+#define PIC_FLAG_COMPOSITE_DISPLAY 32
+#define PIC_FLAG_SKIP 64
+#define PIC_FLAG_TAGS 128
+#define PIC_MASK_COMPOSITE_DISPLAY 0xfffff000
+
+typedef struct mpeg2_picture_s
+{
+    unsigned int temporal_reference;
+    unsigned int nb_fields;
+    uint32_t tag, tag2;
+    uint32_t flags;
+    struct {
+        int x, y;
+    } display_offset[3];
+} mpeg2_picture_t;
+
+typedef struct mpeg2_fbuf_s
+{
+    uint8_t * buf[3];
+    void * id;
+} mpeg2_fbuf_t;
+
+typedef struct mpeg2_info_s
+{
+    const mpeg2_sequence_t * sequence;
+    const mpeg2_gop_t * gop;
+    const mpeg2_picture_t * current_picture;
+    const mpeg2_picture_t * current_picture_2nd;
+    const mpeg2_fbuf_t * current_fbuf;
+    const mpeg2_picture_t * display_picture;
+    const mpeg2_picture_t * display_picture_2nd;
+    const mpeg2_fbuf_t * display_fbuf;
+    const mpeg2_fbuf_t * discard_fbuf;
+    const uint8_t * user_data;
+    unsigned int user_data_len;
+} mpeg2_info_t;
+
+typedef struct mpeg2dec_s mpeg2dec_t;
+typedef struct mpeg2_decoder_s mpeg2_decoder_t;
+
+typedef enum
+{
+    STATE_BUFFER = 0,
+    STATE_SEQUENCE = 1,
+    STATE_SEQUENCE_REPEATED = 2,
+    STATE_GOP = 3,
+    STATE_PICTURE = 4,
+    STATE_SLICE_1ST = 5,
+    STATE_PICTURE_2ND = 6,
+    STATE_SLICE = 7,
+    STATE_END = 8,
+    STATE_INVALID = 9,
+    STATE_INVALID_END = 10
+} mpeg2_state_t;
+
+typedef struct mpeg2_convert_init_s
+{
+    unsigned int id_size;
+    unsigned int buf_size[3];
+    void (* start) (void * id, const mpeg2_fbuf_t * fbuf,
+                    const mpeg2_picture_t * picture, const mpeg2_gop_t * gop);
+    void (* copy) (void * id, uint8_t * const * src, unsigned int v_offset);
+} mpeg2_convert_init_t;
+
+typedef enum
+{
+    MPEG2_CONVERT_SET = 0,
+    MPEG2_CONVERT_STRIDE = 1,
+    MPEG2_CONVERT_START = 2
+} mpeg2_convert_stage_t;
+
+typedef int mpeg2_convert_t (int stage, void * id,
+                            const mpeg2_sequence_t * sequence, int stride,
+                            uint32_t accel, void * arg,
+                            mpeg2_convert_init_t * result);
+int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg);
+int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride);
+void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[3], void * id);
+void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf);
+
+#define MPEG2_ACCEL_X86_MMX 1
+#define MPEG2_ACCEL_X86_3DNOW 2
+#define MPEG2_ACCEL_X86_MMXEXT 4
+#define MPEG2_ACCEL_PPC_ALTIVEC 1
+#define MPEG2_ACCEL_ALPHA 1
+#define MPEG2_ACCEL_ALPHA_MVI 2
+#define MPEG2_ACCEL_SPARC_VIS 1
+#define MPEG2_ACCEL_SPARC_VIS2 2
+#define MPEG2_ACCEL_DETECT 0x80000000
+
+uint32_t mpeg2_accel (uint32_t accel);
+mpeg2dec_t * mpeg2_init (void);
+const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec);
+void mpeg2_close (mpeg2dec_t * mpeg2dec);
+
+void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end);
+int mpeg2_getpos (mpeg2dec_t * mpeg2dec);
+mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec);
+
+void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset);
+void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip);
+void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end);
+
+void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2);
+
+void mpeg2_init_fbuf (mpeg2_decoder_t * decoder, uint8_t * current_fbuf[3],
+                     uint8_t * forward_fbuf[3], uint8_t * backward_fbuf[3]);
+
+typedef enum
+{
+    MPEG2_ALLOC_MPEG2DEC = 0,
+    MPEG2_ALLOC_CHUNK = 1,
+    MPEG2_ALLOC_YUV = 2,
+    MPEG2_ALLOC_CONVERT_ID = 3,
+    MPEG2_ALLOC_CONVERTED = 4
+} mpeg2_alloc_t;
+
+void * mpeg2_malloc (unsigned size, mpeg2_alloc_t reason);
+void mpeg2_free (void * buf);
+void mpeg2_malloc_hooks (void * malloc (unsigned, mpeg2_alloc_t),
+                        int free (void *));
+
+#endif /* MPEG2_H */
diff --git a/modules/codec/xvmc/mpeg2_internal.h b/modules/codec/xvmc/mpeg2_internal.h
new file mode 100644 (file)
index 0000000..8003825
--- /dev/null
@@ -0,0 +1,297 @@
+/* $Id:$
+ * mpeg2_internal.h
+ * Copyright (C) 2000-2003 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
+ */
+
+/* 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
+/* motion_type */
+#define MOTION_TYPE_SHIFT 6
+#define MC_FIELD 1
+#define MC_FRAME 2
+#define MC_16X8 2
+#define MC_DMV 3
+
+/* picture structure */
+#define TOP_FIELD 1
+#define BOTTOM_FIELD 2
+#define FRAME_PICTURE 3
+
+/* picture coding type */
+#define I_TYPE 1
+#define P_TYPE 2
+#define B_TYPE 3
+#define D_TYPE 4
+
+typedef void mpeg2_mc_fct (uint8_t *, const uint8_t *, int, int);
+
+typedef struct
+{
+    uint8_t * ref[2][3];
+    uint8_t ** ref2[2];
+    int pmv[2][2];
+    int f_code[2];
+} motion_t;
+
+typedef void motion_parser_t( mpeg2_decoder_t * decoder,
+                              motion_t * motion,
+                             mpeg2_mc_fct * const * table );
+
+struct mpeg2_decoder_s
+{
+    /* first, state that carries information from one macroblock to the */
+    /* next inside a slice, and is never used outside of mpeg2_slice() */
+
+    /* bit parsing stuff */
+    uint32_t bitstream_buf;            /* current 32 bit working set */
+    int bitstream_bits;                        /* used bits in working set */
+    const uint8_t * bitstream_ptr;     /* buffer with stream data */
+
+    uint8_t * dest[3];
+
+    int offset;
+    int stride;
+    int uv_stride;
+    int slice_stride;
+    int slice_uv_stride;
+    int stride_frame;
+    unsigned int limit_x;
+    unsigned int limit_y_16;
+    unsigned int limit_y_8;
+    unsigned int limit_y;
+
+    /* Motion vectors */
+    /* The f_ and b_ correspond to the forward and backward motion */
+    /* predictors */
+    motion_t b_motion;
+    motion_t f_motion;
+    motion_parser_t * motion_parser[5];
+
+    /* predictor for DC coefficients in intra blocks */
+    int16_t dc_dct_pred[3];
+
+    /* DCT coefficients */
+    int16_t DCTblock[64] ATTR_ALIGN(64);
+
+    uint8_t * picture_dest[3];
+    void (* convert) (void * convert_id, uint8_t * const * src,
+                      unsigned int v_offset);
+    void * convert_id;
+
+    int dmv_offset;
+    unsigned int v_offset;
+
+    /* now non-slice-specific information */
+
+    /* sequence header stuff */
+    uint16_t * quantizer_matrix[4];
+    uint16_t (* chroma_quantizer[2])[64];
+    uint16_t quantizer_prescale[4][32][64];
+    int load_intra_quantizer_matrix;
+    int load_non_intra_quantizer_matrix;
+
+    /* The width and height of the picture snapped to macroblock units */
+    int width;
+    int height;
+    int vertical_position_extension;
+    int chroma_format;
+
+    /* picture header stuff */
+
+    /* what type of picture this is (I, P, B, D) */
+    int coding_type;
+
+    /* picture coding extension stuff */
+
+    /* quantization factor for intra dc coefficients */
+    int intra_dc_precision;
+    /* top/bottom/both fields */
+    int picture_structure;
+    /* bool to indicate all predictions are frame based */
+    int frame_pred_frame_dct;
+    /* bool to indicate whether intra blocks have motion vectors */
+    /* (for concealment) */
+    int concealment_motion_vectors;
+    /* bit to indicate which quantization table to use */
+    int q_scale_type;
+    /* bool to use different vlc tables */
+    int intra_vlc_format;
+    /* used for DMV MC */
+    int top_field_first;
+
+    /* stuff derived from bitstream */
+
+    /* pointer to the zigzag scan we're supposed to be using */
+    const uint8_t * scan;
+
+    int second_field;
+
+    int mpeg1;
+
+    int aspect_ratio_information;
+    int progressive_sequence;
+};
+
+typedef struct
+{
+    mpeg2_fbuf_t fbuf;
+} fbuf_alloc_t;
+
+struct mpeg2dec_s
+{
+    mpeg2_decoder_t decoder;
+
+    mpeg2_info_t info;
+
+    uint32_t shift;
+    int is_display_initialized;
+    mpeg2_state_t (* action) (struct mpeg2dec_s * mpeg2dec);
+    mpeg2_state_t state;
+    uint32_t ext_state;
+
+    /* allocated in init - gcc has problems allocating such big structures */
+    uint8_t * chunk_buffer;
+    /* pointer to start of the current chunk */
+    uint8_t * chunk_start;
+    /* pointer to current position in chunk_buffer */
+    uint8_t * chunk_ptr;
+    uint32_t chunk_size;
+    /* last start code ? */
+    uint8_t code;
+    uint8_t prev_code;
+
+    /* picture tags */
+    uint32_t tag_current, tag2_current, tag_previous, tag2_previous;
+    int num_tags;
+    int bytes_since_tag;
+
+    int first;
+    int alloc_index_user;
+    int alloc_index;
+    uint8_t first_decode_slice;
+    uint8_t nb_decode_slices;
+
+    unsigned int user_data_len;
+
+    mpeg2_sequence_t new_sequence;
+    mpeg2_sequence_t sequence;
+    mpeg2_gop_t new_gop;
+    mpeg2_gop_t gop;
+    mpeg2_picture_t new_picture;
+    mpeg2_picture_t pictures[4];
+    mpeg2_picture_t * picture;
+    /*const*/ mpeg2_fbuf_t * fbuf[3];  /* 0: current fbuf, 1-2: prediction fbufs */
+
+    fbuf_alloc_t fbuf_alloc[3];
+    int custom_fbuf;
+
+    uint8_t * yuv_buf[3][3];
+    int yuv_index;
+    mpeg2_convert_t * convert;
+    void * convert_arg;
+    unsigned int convert_id_size;
+    int convert_stride;
+    void (* convert_start) (void * id, const mpeg2_fbuf_t * fbuf,
+                            const mpeg2_picture_t * picture,
+                            const mpeg2_gop_t * gop);
+
+    uint8_t * buf_start;
+    uint8_t * buf_end;
+
+    int16_t display_offset_x, display_offset_y;
+
+    int copy_matrix;
+    int8_t q_scale_type, scaled[4];
+    uint8_t quantizer_matrix[4][64];
+    uint8_t new_quantizer_matrix[4][64];
+
+    /* a spu decoder for possible closed captions */
+    //spu_decoder_t *cc_dec;
+    int xvmc_last_slice_code;
+    unsigned xxmc_mb_pic_height;
+
+    void *ptr_forward_ref_picture;
+    void *ptr_backward_ref_picture;
+};
+
+typedef struct
+{
+#ifdef ARCH_PPC
+    uint8_t regv[12*16];
+#endif
+    int dummy;
+} cpu_state_t;
+
+/* cpu_accel.c */
+uint32_t mpeg2_detect_accel (void);
+
+/* cpu_state.c */
+void mpeg2_cpu_state_init (uint32_t accel);
+
+/* decode.c */
+mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec);
+mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec);
+
+/* header.c */
+extern uint8_t mpeg2_scan_norm[64];
+extern uint8_t mpeg2_scan_alt[64];
+void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec);
+void mpeg2_reset_info (mpeg2_info_t * info);
+int mpeg2_header_sequence (mpeg2dec_t * mpeg2dec);
+int mpeg2_header_gop (mpeg2dec_t * mpeg2dec);
+mpeg2_state_t mpeg2_header_picture_start (mpeg2dec_t * mpeg2dec);
+int mpeg2_header_picture (mpeg2dec_t * mpeg2dec);
+int mpeg2_header_extension (mpeg2dec_t * mpeg2dec);
+int mpeg2_header_user_data (mpeg2dec_t * mpeg2dec);
+void mpeg2_header_sequence_finalize (mpeg2dec_t * mpeg2dec);
+void mpeg2_header_gop_finalize (mpeg2dec_t * mpeg2dec);
+void mpeg2_header_picture_finalize (mpeg2dec_t * mpeg2dec, uint32_t accels);
+mpeg2_state_t mpeg2_header_slice_start (mpeg2dec_t * mpeg2dec);
+mpeg2_state_t mpeg2_header_end (mpeg2dec_t * mpeg2dec);
+void mpeg2_set_fbuf (mpeg2dec_t * mpeg2dec, int b_type);
+
+/* motion_comp.c */
+void mpeg2_mc_init (uint32_t accel);
+
+typedef struct {
+    mpeg2_mc_fct * put [8];
+    mpeg2_mc_fct * avg [8];
+} mpeg2_mc_t;
+
+#define MPEG2_MC_EXTERN(x) mpeg2_mc_t mpeg2_mc_##x = {                   \
+    {MC_put_o_16_##x, MC_put_x_16_##x, MC_put_y_16_##x, MC_put_xy_16_##x, \
+     MC_put_o_8_##x,  MC_put_x_8_##x,  MC_put_y_8_##x,  MC_put_xy_8_##x}, \
+    {MC_avg_o_16_##x, MC_avg_x_16_##x, MC_avg_y_16_##x, MC_avg_xy_16_##x, \
+     MC_avg_o_8_##x,  MC_avg_x_8_##x,  MC_avg_y_8_##x,  MC_avg_xy_8_##x}  \
+};
+
+extern mpeg2_mc_t mpeg2_mc_c;
+extern mpeg2_mc_t mpeg2_mc_mmx;
+extern mpeg2_mc_t mpeg2_mc_mmxext;
+extern mpeg2_mc_t mpeg2_mc_3dnow;
+extern mpeg2_mc_t mpeg2_mc_altivec;
+extern mpeg2_mc_t mpeg2_mc_alpha;
+extern mpeg2_mc_t mpeg2_mc_vis;
diff --git a/modules/codec/xvmc/slice.c b/modules/codec/xvmc/slice.c
new file mode 100644 (file)
index 0000000..7f37001
--- /dev/null
@@ -0,0 +1,845 @@
+/* $Id:$
+ * slice.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 2003      Peter Gubanov <peter@elecard.net.ru>
+ * 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 "xxmc-config.h"
+
+#include <inttypes.h>
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+extern mpeg2_mc_t mpeg2_mc;
+extern void (* mpeg2_cpu_state_save) (cpu_state_t * state);
+extern void (* mpeg2_cpu_state_restore) (cpu_state_t * state);
+
+#include "vlc.h"
+
+static inline int get_motion_delta( mpeg2_decoder_t * const decoder,
+                                   const int f_code )
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+    int delta;
+    int sign;
+    const 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 (const int vector, const int f_code)
+{
+    return ((int32_t)vector << (27 - f_code)) >> (27 - f_code);
+}
+
+static inline int get_dmv (mpeg2_decoder_t * const decoder)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+    const 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
+}
+
+#define MOTION_420(table,ref,motion_x,motion_y,size,y)                       \
+    pos_x = 2 * decoder->offset + motion_x;                                  \
+    pos_y = 2 * decoder->v_offset + motion_y + 2 * y;                        \
+    if (unlikely (pos_x > decoder->limit_x)) {                               \
+       pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x;                      \
+       motion_x = pos_x - 2 * decoder->offset;                               \
+    }                                                                        \
+    if (unlikely (pos_y > decoder->limit_y_ ## size)) {                              \
+       pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size;             \
+       motion_y = pos_y - 2 * decoder->v_offset - 2 * y;                     \
+    }                                                                        \
+    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);                                      \
+    table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \
+                   ref[0] + (pos_x >> 1) + (pos_y >> 1) * decoder->stride,   \
+                   decoder->stride, size);                                   \
+    motion_x /= 2;     motion_y /= 2;                                        \
+    xy_half = ((motion_y & 1) << 1) | (motion_x & 1);                        \
+    offset = (((decoder->offset + motion_x) >> 1) +                          \
+             ((((decoder->v_offset + motion_y) >> 1) + y/2) *                \
+              decoder->uv_stride));                                          \
+    table[4+xy_half] (decoder->dest[1] + y/2 * decoder->uv_stride +          \
+                     (decoder->offset >> 1), ref[1] + offset,                \
+                     decoder->uv_stride, size/2);                            \
+    table[4+xy_half] (decoder->dest[2] + y/2 * decoder->uv_stride +          \
+                     (decoder->offset >> 1), ref[2] + offset,                \
+                     decoder->uv_stride, size/2)
+
+#define MOTION_FIELD_420(table,ref,motion_x,motion_y,dest_field,op,src_field) \
+    pos_x = 2 * decoder->offset + motion_x;                                  \
+    pos_y = decoder->v_offset + motion_y;                                    \
+    if (unlikely (pos_x > decoder->limit_x)) {                               \
+       pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x;                      \
+       motion_x = pos_x - 2 * decoder->offset;                               \
+    }                                                                        \
+    if (unlikely (pos_y > decoder->limit_y)) {                               \
+       pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y;                      \
+       motion_y = pos_y - decoder->v_offset;                                 \
+    }                                                                        \
+    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);                                      \
+    table[xy_half] (decoder->dest[0] + dest_field * decoder->stride +        \
+                   decoder->offset,                                          \
+                   (ref[0] + (pos_x >> 1) +                                  \
+                    ((pos_y op) + src_field) * decoder->stride),             \
+                   2 * decoder->stride, 8);                                  \
+    motion_x /= 2;     motion_y /= 2;                                        \
+    xy_half = ((motion_y & 1) << 1) | (motion_x & 1);                        \
+    offset = (((decoder->offset + motion_x) >> 1) +                          \
+             (((decoder->v_offset >> 1) + (motion_y op) + src_field) *       \
+              decoder->uv_stride));                                          \
+    table[4+xy_half] (decoder->dest[1] + dest_field * decoder->uv_stride +    \
+                     (decoder->offset >> 1), ref[1] + offset,                \
+                     2 * decoder->uv_stride, 4);                             \
+    table[4+xy_half] (decoder->dest[2] + dest_field * decoder->uv_stride +    \
+                     (decoder->offset >> 1), ref[2] + offset,                \
+                     2 * decoder->uv_stride, 4)
+
+#define MOTION_DMV_420(table,ref,motion_x,motion_y)                          \
+    pos_x = 2 * decoder->offset + motion_x;                                  \
+    pos_y = decoder->v_offset + motion_y;                                    \
+    if (unlikely (pos_x > decoder->limit_x)) {                               \
+       pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x;                      \
+       motion_x = pos_x - 2 * decoder->offset;                               \
+    }                                                                        \
+    if (unlikely (pos_y > decoder->limit_y)) {                               \
+       pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y;                      \
+       motion_y = pos_y - decoder->v_offset;                                 \
+    }                                                                        \
+    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);                                      \
+    offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride;                  \
+    table[xy_half] (decoder->dest[0] + decoder->offset,                              \
+                   ref[0] + offset, 2 * decoder->stride, 8);                 \
+    table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset,     \
+                   ref[0] + decoder->stride + offset,                        \
+                   2 * decoder->stride, 8);                                  \
+    motion_x /= 2;     motion_y /= 2;                                        \
+    xy_half = ((motion_y & 1) << 1) | (motion_x & 1);                        \
+    offset = (((decoder->offset + motion_x) >> 1) +                          \
+             (((decoder->v_offset >> 1) + (motion_y & ~1)) *                 \
+              decoder->uv_stride));                                          \
+    table[4+xy_half] (decoder->dest[1] + (decoder->offset >> 1),             \
+                     ref[1] + offset, 2 * decoder->uv_stride, 4);            \
+    table[4+xy_half] (decoder->dest[1] + decoder->uv_stride +                \
+                     (decoder->offset >> 1),                                 \
+                     ref[1] + decoder->uv_stride + offset,                   \
+                     2 * decoder->uv_stride, 4);                             \
+    table[4+xy_half] (decoder->dest[2] + (decoder->offset >> 1),             \
+                     ref[2] + offset, 2 * decoder->uv_stride, 4);            \
+    table[4+xy_half] (decoder->dest[2] + decoder->uv_stride +                \
+                     (decoder->offset >> 1),                                 \
+                     ref[2] + decoder->uv_stride + offset,                   \
+                     2 * decoder->uv_stride, 4)
+
+#define MOTION_ZERO_420(table,ref)                                           \
+    table[0] (decoder->dest[0] + decoder->offset,                            \
+             (ref[0] + decoder->offset +                                     \
+              decoder->v_offset * decoder->stride), decoder->stride, 16);    \
+    offset = ((decoder->offset >> 1) +                                       \
+             (decoder->v_offset >> 1) * decoder->uv_stride);                 \
+    table[4] (decoder->dest[1] + (decoder->offset >> 1),                     \
+             ref[1] + offset, decoder->uv_stride, 8);                        \
+    table[4] (decoder->dest[2] + (decoder->offset >> 1),                     \
+             ref[2] + offset, decoder->uv_stride, 8)
+
+#define MOTION_422(table,ref,motion_x,motion_y,size,y)                       \
+    pos_x = 2 * decoder->offset + motion_x;                                  \
+    pos_y = 2 * decoder->v_offset + motion_y + 2 * y;                        \
+    if (unlikely (pos_x > decoder->limit_x)) {                               \
+       pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x;                      \
+       motion_x = pos_x - 2 * decoder->offset;                               \
+    }                                                                        \
+    if (unlikely (pos_y > decoder->limit_y_ ## size)) {                              \
+       pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size;             \
+       motion_y = pos_y - 2 * decoder->v_offset - 2 * y;                     \
+    }                                                                        \
+    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);                                      \
+    offset = (pos_x >> 1) + (pos_y >> 1) * decoder->stride;                  \
+    table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \
+                   ref[0] + offset, decoder->stride, size);                  \
+    offset = (offset + (motion_x & (motion_x < 0))) >> 1;                    \
+    motion_x /= 2;                                                           \
+    xy_half = ((pos_y & 1) << 1) | (motion_x & 1);                           \
+    table[4+xy_half] (decoder->dest[1] + y * decoder->uv_stride +            \
+                     (decoder->offset >> 1), ref[1] + offset,                \
+                     decoder->uv_stride, size);                              \
+    table[4+xy_half] (decoder->dest[2] + y * decoder->uv_stride +            \
+                     (decoder->offset >> 1), ref[2] + offset,                \
+                     decoder->uv_stride, size)
+
+#define MOTION_FIELD_422(table,ref,motion_x,motion_y,dest_field,op,src_field) \
+    pos_x = 2 * decoder->offset + motion_x;                                  \
+    pos_y = decoder->v_offset + motion_y;                                    \
+    if (unlikely (pos_x > decoder->limit_x)) {                               \
+       pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x;                      \
+       motion_x = pos_x - 2 * decoder->offset;                               \
+    }                                                                        \
+    if (unlikely (pos_y > decoder->limit_y)) {                               \
+       pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y;                      \
+       motion_y = pos_y - decoder->v_offset;                                 \
+    }                                                                        \
+    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);                                      \
+    offset = (pos_x >> 1) + ((pos_y op) + src_field) * decoder->stride;              \
+    table[xy_half] (decoder->dest[0] + dest_field * decoder->stride +        \
+                   decoder->offset, ref[0] + offset,                         \
+                   2 * decoder->stride, 8);                                  \
+    offset = (offset + (motion_x & (motion_x < 0))) >> 1;                    \
+    motion_x /= 2;                                                           \
+    xy_half = ((pos_y & 1) << 1) | (motion_x & 1);                           \
+    table[4+xy_half] (decoder->dest[1] + dest_field * decoder->uv_stride +    \
+                     (decoder->offset >> 1), ref[1] + offset,                \
+                     2 * decoder->uv_stride, 8);                             \
+    table[4+xy_half] (decoder->dest[2] + dest_field * decoder->uv_stride +    \
+                     (decoder->offset >> 1), ref[2] + offset,                \
+                     2 * decoder->uv_stride, 8)
+
+#define MOTION_DMV_422(table,ref,motion_x,motion_y)                          \
+    pos_x = 2 * decoder->offset + motion_x;                                  \
+    pos_y = decoder->v_offset + motion_y;                                    \
+    if (unlikely (pos_x > decoder->limit_x)) {                               \
+       pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x;                      \
+       motion_x = pos_x - 2 * decoder->offset;                               \
+    }                                                                        \
+    if (unlikely (pos_y > decoder->limit_y)) {                               \
+       pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y;                      \
+       motion_y = pos_y - decoder->v_offset;                                 \
+    }                                                                        \
+    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);                                      \
+    offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride;                  \
+    table[xy_half] (decoder->dest[0] + decoder->offset,                              \
+                   ref[0] + offset, 2 * decoder->stride, 8);                 \
+    table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset,     \
+                   ref[0] + decoder->stride + offset,                        \
+                   2 * decoder->stride, 8);                                  \
+    offset = (offset + (motion_x & (motion_x < 0))) >> 1;                    \
+    motion_x /= 2;                                                           \
+    xy_half = ((pos_y & 1) << 1) | (motion_x & 1);                           \
+    table[4+xy_half] (decoder->dest[1] + (decoder->offset >> 1),             \
+                     ref[1] + offset, 2 * decoder->uv_stride, 8);            \
+    table[4+xy_half] (decoder->dest[1] + decoder->uv_stride +                \
+                     (decoder->offset >> 1),                                 \
+                     ref[1] + decoder->uv_stride + offset,                   \
+                     2 * decoder->uv_stride, 8);                             \
+    table[4+xy_half] (decoder->dest[2] + (decoder->offset >> 1),             \
+                     ref[2] + offset, 2 * decoder->uv_stride, 8);            \
+    table[4+xy_half] (decoder->dest[2] + decoder->uv_stride +                \
+                     (decoder->offset >> 1),                                 \
+                     ref[2] + decoder->uv_stride + offset,                   \
+                     2 * decoder->uv_stride, 8)
+
+#define MOTION_ZERO_422(table,ref)                                           \
+    offset = decoder->offset + decoder->v_offset * decoder->stride;          \
+    table[0] (decoder->dest[0] + decoder->offset,                            \
+             ref[0] + offset, decoder->stride, 16);                          \
+    offset >>= 1;                                                            \
+    table[4] (decoder->dest[1] + (decoder->offset >> 1),                     \
+             ref[1] + offset, decoder->uv_stride, 16);                       \
+    table[4] (decoder->dest[2] + (decoder->offset >> 1),                     \
+             ref[2] + offset, decoder->uv_stride, 16)
+
+#define MOTION_444(table,ref,motion_x,motion_y,size,y)                       \
+    pos_x = 2 * decoder->offset + motion_x;                                  \
+    pos_y = 2 * decoder->v_offset + motion_y + 2 * y;                        \
+    if (unlikely (pos_x > decoder->limit_x)) {                               \
+       pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x;                      \
+       motion_x = pos_x - 2 * decoder->offset;                               \
+    }                                                                        \
+    if (unlikely (pos_y > decoder->limit_y_ ## size)) {                              \
+       pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size;             \
+       motion_y = pos_y - 2 * decoder->v_offset - 2 * y;                     \
+    }                                                                        \
+    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);                                      \
+    offset = (pos_x >> 1) + (pos_y >> 1) * decoder->stride;                  \
+    table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \
+                   ref[0] + offset, decoder->stride, size);                  \
+    table[xy_half] (decoder->dest[1] + y * decoder->stride + decoder->offset, \
+                   ref[1] + offset, decoder->stride, size);                  \
+    table[xy_half] (decoder->dest[2] + y * decoder->stride + decoder->offset, \
+                   ref[2] + offset, decoder->stride, size)
+
+#define MOTION_FIELD_444(table,ref,motion_x,motion_y,dest_field,op,src_field) \
+    pos_x = 2 * decoder->offset + motion_x;                                  \
+    pos_y = decoder->v_offset + motion_y;                                    \
+    if (unlikely (pos_x > decoder->limit_x)) {                               \
+       pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x;                      \
+       motion_x = pos_x - 2 * decoder->offset;                               \
+    }                                                                        \
+    if (unlikely (pos_y > decoder->limit_y)) {                               \
+       pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y;                      \
+       motion_y = pos_y - decoder->v_offset;                                 \
+    }                                                                        \
+    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);                                      \
+    offset = (pos_x >> 1) + ((pos_y op) + src_field) * decoder->stride;              \
+    table[xy_half] (decoder->dest[0] + dest_field * decoder->stride +        \
+                   decoder->offset, ref[0] + offset,                         \
+                   2 * decoder->stride, 8);                                  \
+    table[xy_half] (decoder->dest[1] + dest_field * decoder->stride +        \
+                   decoder->offset, ref[1] + offset,                         \
+                   2 * decoder->stride, 8);                                  \
+    table[xy_half] (decoder->dest[2] + dest_field * decoder->stride +        \
+                   decoder->offset, ref[2] + offset,                         \
+                   2 * decoder->stride, 8)
+
+#define MOTION_DMV_444(table,ref,motion_x,motion_y)                          \
+    pos_x = 2 * decoder->offset + motion_x;                                  \
+    pos_y = decoder->v_offset + motion_y;                                    \
+    if (unlikely (pos_x > decoder->limit_x)) {                               \
+       pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x;                      \
+       motion_x = pos_x - 2 * decoder->offset;                               \
+    }                                                                        \
+    if (unlikely (pos_y > decoder->limit_y)) {                               \
+       pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y;                      \
+       motion_y = pos_y - decoder->v_offset;                                 \
+    }                                                                        \
+    xy_half = ((pos_y & 1) << 1) | (pos_x & 1);                                      \
+    offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride;                  \
+    table[xy_half] (decoder->dest[0] + decoder->offset,                              \
+                   ref[0] + offset, 2 * decoder->stride, 8);                 \
+    table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset,     \
+                   ref[0] + decoder->stride + offset,                        \
+                   2 * decoder->stride, 8);                                  \
+    table[xy_half] (decoder->dest[1] + decoder->offset,                              \
+                   ref[1] + offset, 2 * decoder->stride, 8);                 \
+    table[xy_half] (decoder->dest[1] + decoder->stride + decoder->offset,     \
+                   ref[1] + decoder->stride + offset,                        \
+                   2 * decoder->stride, 8);                                  \
+    table[xy_half] (decoder->dest[2] + decoder->offset,                              \
+                   ref[2] + offset, 2 * decoder->stride, 8);                 \
+    table[xy_half] (decoder->dest[2] + decoder->stride + decoder->offset,     \
+                   ref[2] + decoder->stride + offset,                        \
+                   2 * decoder->stride, 8)
+
+#define MOTION_ZERO_444(table,ref)                                           \
+    offset = decoder->offset + decoder->v_offset * decoder->stride;          \
+    table[0] (decoder->dest[0] + decoder->offset,                            \
+             ref[0] + offset, decoder->stride, 16);                          \
+    table[4] (decoder->dest[1] + decoder->offset,                            \
+             ref[1] + offset, decoder->stride, 16);                          \
+    table[4] (decoder->dest[2] + (decoder->offset >> 1),                     \
+             ref[2] + offset, decoder->stride, 16)
+
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+static void motion_mp1 (mpeg2_decoder_t * const decoder,
+                       motion_t * const motion,
+                       mpeg2_mc_fct * const * const table)
+{
+    int motion_x, motion_y;
+    unsigned int pos_x, pos_y, xy_half, offset;
+
+    NEEDBITS (bit_buf, bits, bit_ptr);
+    motion_x = (motion->pmv[0][0] +
+               (get_motion_delta( decoder,
+                                  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_motion_delta( decoder,
+                                  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_420 (table, motion->ref[0], motion_x, motion_y, 16, 0);
+}
+
+#define MOTION_FUNCTIONS(FORMAT,MOTION,MOTION_FIELD,MOTION_DMV,MOTION_ZERO)   \
+                                                                             \
+static void motion_fr_frame_##FORMAT (mpeg2_decoder_t * const decoder,       \
+                                     motion_t * const motion,                \
+                                     mpeg2_mc_fct * const * const table)     \
+{                                                                            \
+    int motion_x, motion_y;                                                  \
+    unsigned int pos_x, pos_y, xy_half, offset;                                      \
+                                                                             \
+    NEEDBITS (bit_buf, bits, bit_ptr);                                       \
+    motion_x = motion->pmv[0][0] + get_motion_delta (decoder,                \
+                                                    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_motion_delta (decoder,                \
+                                                    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);               \
+}                                                                            \
+                                                                             \
+static void motion_fr_field_##FORMAT (mpeg2_decoder_t * const decoder,       \
+                                     motion_t * const motion,                \
+                                     mpeg2_mc_fct * const * const table)     \
+{                                                                            \
+    int motion_x, motion_y, field;                                           \
+    unsigned int pos_x, pos_y, xy_half, offset;                                      \
+                                                                             \
+    NEEDBITS (bit_buf, bits, bit_ptr);                                       \
+    field = UBITS (bit_buf, 1);                                                      \
+    DUMPBITS (bit_buf, bits, 1);                                             \
+                                                                             \
+    motion_x = motion->pmv[0][0] + get_motion_delta (decoder,                \
+                                                    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_motion_delta (decoder, 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);                                                      \
+    DUMPBITS (bit_buf, bits, 1);                                             \
+                                                                             \
+    motion_x = motion->pmv[1][0] + get_motion_delta (decoder,                \
+                                                    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_motion_delta (decoder, 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); \
+}                                                                            \
+                                                                             \
+static void motion_fr_dmv_##FORMAT (mpeg2_decoder_t * const decoder,         \
+                                   motion_t * const motion,                  \
+                                   mpeg2_mc_fct * const * const table)       \
+{                                                                            \
+    int motion_x, motion_y, dmv_x, dmv_y, m, other_x, other_y;               \
+    unsigned int pos_x, pos_y, xy_half, offset;                                      \
+                                                                             \
+    NEEDBITS (bit_buf, bits, bit_ptr);                                       \
+    motion_x = motion->pmv[0][0] + get_motion_delta (decoder,                \
+                                                    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_dmv (decoder);                                               \
+                                                                             \
+    motion_y = ((motion->pmv[0][1] >> 1) +                                   \
+               get_motion_delta (decoder, 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_dmv (decoder);                                               \
+                                                                             \
+    m = decoder->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 = decoder->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);\
+                                                                             \
+    MOTION_DMV (mpeg2_mc.avg, motion->ref[0], motion_x, motion_y);           \
+}                                                                            \
+                                                                             \
+static void motion_reuse_##FORMAT (mpeg2_decoder_t * const decoder,          \
+                                  motion_t * const motion,                   \
+                                  mpeg2_mc_fct * const * const table)        \
+{                                                                            \
+    int motion_x, motion_y;                                                  \
+    unsigned int pos_x, pos_y, xy_half, offset;                                      \
+                                                                             \
+    motion_x = motion->pmv[0][0];                                            \
+    motion_y = motion->pmv[0][1];                                            \
+                                                                             \
+    MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0);               \
+}                                                                            \
+                                                                             \
+static void motion_zero_##FORMAT (mpeg2_decoder_t * const decoder,           \
+                                 motion_t * const motion,                    \
+                                 mpeg2_mc_fct * const * const table)         \
+{                                                                            \
+    unsigned int offset;                                                     \
+                                                                             \
+    motion->pmv[0][0] = motion->pmv[0][1] = 0;                               \
+    motion->pmv[1][0] = motion->pmv[1][1] = 0;                               \
+                                                                             \
+    MOTION_ZERO (table, motion->ref[0]);                                     \
+}                                                                            \
+                                                                             \
+static void motion_fi_field_##FORMAT (mpeg2_decoder_t * const decoder,       \
+                                     motion_t * const motion,                \
+                                     mpeg2_mc_fct * const * const table)     \
+{                                                                            \
+    int motion_x, motion_y;                                                  \
+    uint8_t ** ref_field;                                                    \
+    unsigned int pos_x, pos_y, xy_half, offset;                                      \
+                                                                             \
+    NEEDBITS (bit_buf, bits, bit_ptr);                                       \
+    ref_field = motion->ref2[UBITS (bit_buf, 1)];                            \
+    DUMPBITS (bit_buf, bits, 1);                                             \
+                                                                             \
+    motion_x = motion->pmv[0][0] + get_motion_delta (decoder,                \
+                                                    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_motion_delta (decoder,                \
+                                                    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);                    \
+}                                                                            \
+                                                                             \
+static void motion_fi_16x8_##FORMAT (mpeg2_decoder_t * const decoder,        \
+                                    motion_t * const motion,                 \
+                                    mpeg2_mc_fct * const * const table)      \
+{                                                                            \
+    int motion_x, motion_y;                                                  \
+    uint8_t ** ref_field;                                                    \
+    unsigned int pos_x, pos_y, xy_half, offset;                                      \
+                                                                             \
+    NEEDBITS (bit_buf, bits, bit_ptr);                                       \
+    ref_field = motion->ref2[UBITS (bit_buf, 1)];                            \
+    DUMPBITS (bit_buf, bits, 1);                                             \
+                                                                             \
+    motion_x = motion->pmv[0][0] + get_motion_delta (decoder,                \
+                                                    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_motion_delta (decoder,                \
+                                                    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)];                            \
+    DUMPBITS (bit_buf, bits, 1);                                             \
+                                                                             \
+    motion_x = motion->pmv[1][0] + get_motion_delta (decoder,                \
+                                                    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_motion_delta (decoder,                \
+                                                    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);                     \
+}                                                                            \
+                                                                             \
+static void motion_fi_dmv_##FORMAT (mpeg2_decoder_t * const decoder,         \
+                                   motion_t * const motion,                  \
+                                   mpeg2_mc_fct * const * const table)       \
+{                                                                            \
+    int motion_x, motion_y, other_x, other_y;                                \
+    unsigned int pos_x, pos_y, xy_half, offset;                                      \
+                                                                             \
+    NEEDBITS (bit_buf, bits, bit_ptr);                                       \
+    motion_x = motion->pmv[0][0] + get_motion_delta (decoder,                \
+                                                    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_dmv (decoder);        \
+                                                                             \
+    motion_y = motion->pmv[0][1] + get_motion_delta (decoder,                \
+                                                    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_dmv (decoder) +              \
+              decoder->dmv_offset);                                          \
+                                                                             \
+    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);          \
+}                                                                            \
+
+MOTION_FUNCTIONS (420, MOTION_420, MOTION_FIELD_420, MOTION_DMV_420,
+                 MOTION_ZERO_420)
+MOTION_FUNCTIONS (422, MOTION_422, MOTION_FIELD_422, MOTION_DMV_422,
+                 MOTION_ZERO_422)
+MOTION_FUNCTIONS (444, MOTION_444, MOTION_FIELD_444, MOTION_DMV_444,
+                 MOTION_ZERO_444)
+
+/* like motion_frame, but parsing without actual motion compensation */
+static void motion_fr_conceal (mpeg2_decoder_t * const decoder)
+{
+    int tmp;
+
+    NEEDBITS (bit_buf, bits, bit_ptr);
+    tmp = (decoder->f_motion.pmv[0][0] +
+           get_motion_delta (decoder, decoder->f_motion.f_code[0]));
+    tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[0]);
+    decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[0][0] = tmp;
+
+    NEEDBITS (bit_buf, bits, bit_ptr);
+    tmp = (decoder->f_motion.pmv[0][1] +
+           get_motion_delta (decoder, decoder->f_motion.f_code[1]));
+    tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[1]);
+    decoder->f_motion.pmv[1][1] = decoder->f_motion.pmv[0][1] = tmp;
+
+    DUMPBITS (bit_buf, bits, 1); /* remove marker_bit */
+}
+
+static void motion_fi_conceal (mpeg2_decoder_t * const decoder)
+{
+    int tmp;
+
+    NEEDBITS (bit_buf, bits, bit_ptr);
+    DUMPBITS (bit_buf, bits, 1); /* remove field_select */
+
+    tmp = (decoder->f_motion.pmv[0][0] +
+           get_motion_delta (decoder, decoder->f_motion.f_code[0]));
+    tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[0]);
+    decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[0][0] = tmp;
+
+    NEEDBITS (bit_buf, bits, bit_ptr);
+    tmp = (decoder->f_motion.pmv[0][1] +
+           get_motion_delta (decoder, decoder->f_motion.f_code[1]));
+    tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[1]);
+    decoder->f_motion.pmv[1][1] = decoder->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 (decoder, &(decoder->f_motion), mpeg2_mc.put);  \
+    if ((direction) & MACROBLOCK_MOTION_BACKWARD)              \
+       routine (decoder, &(decoder->b_motion),                 \
+                ((direction) & MACROBLOCK_MOTION_FORWARD ?     \
+                 mpeg2_mc.avg : mpeg2_mc.put));                \
+} while (0)
+
+#define NEXT_MACROBLOCK                                                        \
+do {                                                                   \
+    decoder->offset += 16;                                             \
+    if (decoder->offset == decoder->width) {                           \
+       do { /* just so we can use the break statement */               \
+           if (decoder->convert) {                                     \
+               decoder->convert (decoder->convert_id, decoder->dest,   \
+                                 decoder->v_offset);                   \
+               if (decoder->coding_type == B_TYPE)                     \
+                   break;                                              \
+           }                                                           \
+           decoder->dest[0] += decoder->slice_stride;                  \
+           decoder->dest[1] += decoder->slice_uv_stride;               \
+           decoder->dest[2] += decoder->slice_uv_stride;               \
+       } while (0);                                                    \
+       decoder->v_offset += 16;                                        \
+       if (decoder->v_offset > decoder->limit_y) {                     \
+           if (mpeg2_cpu_state_restore)                                \
+               mpeg2_cpu_state_restore (&cpu_state);                   \
+           return;                                                     \
+       }                                                               \
+       decoder->offset = 0;                                            \
+    }                                                                  \
+} while (0)
+
+void mpeg2_init_fbuf (mpeg2_decoder_t * decoder, uint8_t * current_fbuf[3],
+                     uint8_t * forward_fbuf[3], uint8_t * backward_fbuf[3])
+{
+    int offset, stride, height, bottom_field;
+
+    stride = decoder->stride_frame;
+    bottom_field = (decoder->picture_structure == BOTTOM_FIELD);
+    offset = bottom_field ? stride : 0;
+    height = decoder->height;
+
+    decoder->picture_dest[0] = current_fbuf[0] + offset;
+    decoder->picture_dest[1] = current_fbuf[1] + (offset >> 1);
+    decoder->picture_dest[2] = current_fbuf[2] + (offset >> 1);
+
+    decoder->f_motion.ref[0][0] = forward_fbuf[0] + offset;
+    decoder->f_motion.ref[0][1] = forward_fbuf[1] + (offset >> 1);
+    decoder->f_motion.ref[0][2] = forward_fbuf[2] + (offset >> 1);
+
+    decoder->b_motion.ref[0][0] = backward_fbuf[0] + offset;
+    decoder->b_motion.ref[0][1] = backward_fbuf[1] + (offset >> 1);
+    decoder->b_motion.ref[0][2] = backward_fbuf[2] + (offset >> 1);
+
+    if( decoder->picture_structure != FRAME_PICTURE )
+    {
+        decoder->dmv_offset = bottom_field ? 1 : -1;
+        decoder->f_motion.ref2[0] = decoder->f_motion.ref[bottom_field];
+        decoder->f_motion.ref2[1] = decoder->f_motion.ref[!bottom_field];
+        decoder->b_motion.ref2[0] = decoder->b_motion.ref[bottom_field];
+        decoder->b_motion.ref2[1] = decoder->b_motion.ref[!bottom_field];
+        offset = stride - offset;
+
+        if( decoder->second_field && (decoder->coding_type != B_TYPE) )
+            forward_fbuf = current_fbuf;
+
+        decoder->f_motion.ref[1][0] = forward_fbuf[0] + offset;
+        decoder->f_motion.ref[1][1] = forward_fbuf[1] + (offset >> 1);
+        decoder->f_motion.ref[1][2] = forward_fbuf[2] + (offset >> 1);
+
+        decoder->b_motion.ref[1][0] = backward_fbuf[0] + offset;
+        decoder->b_motion.ref[1][1] = backward_fbuf[1] + (offset >> 1);
+        decoder->b_motion.ref[1][2] = backward_fbuf[2] + (offset >> 1);
+
+        stride <<= 1;
+        height >>= 1;
+    }
+
+    decoder->stride = stride;
+    decoder->uv_stride = stride >> 1;
+    decoder->slice_stride = 16 * stride;
+    decoder->slice_uv_stride =
+    decoder->slice_stride >> (2 - decoder->chroma_format);
+    decoder->limit_x = 2 * decoder->width - 32;
+    decoder->limit_y_16 = 2 * height - 32;
+    decoder->limit_y_8 = 2 * height - 16;
+    decoder->limit_y = height - 16;
+
+    if( decoder->mpeg1 )
+    {
+        decoder->motion_parser[0] = motion_zero_420;
+        decoder->motion_parser[MC_FRAME] = motion_mp1;
+        decoder->motion_parser[4] = motion_reuse_420;
+    }
+    else if( decoder->picture_structure == FRAME_PICTURE )
+    {
+        if (decoder->chroma_format == 0)
+        {
+            decoder->motion_parser[0] = motion_zero_420;
+            decoder->motion_parser[MC_FIELD] = motion_fr_field_420;
+            decoder->motion_parser[MC_FRAME] = motion_fr_frame_420;
+            decoder->motion_parser[MC_DMV] = motion_fr_dmv_420;
+            decoder->motion_parser[4] = motion_reuse_420;
+        }
+        else if (decoder->chroma_format == 1)
+        {
+            decoder->motion_parser[0] = motion_zero_422;
+            decoder->motion_parser[MC_FIELD] = motion_fr_field_422;
+            decoder->motion_parser[MC_FRAME] = motion_fr_frame_422;
+            decoder->motion_parser[MC_DMV] = motion_fr_dmv_422;
+            decoder->motion_parser[4] = motion_reuse_422;
+        } else
+        {
+            decoder->motion_parser[0] = motion_zero_444;
+            decoder->motion_parser[MC_FIELD] = motion_fr_field_444;
+            decoder->motion_parser[MC_FRAME] = motion_fr_frame_444;
+            decoder->motion_parser[MC_DMV] = motion_fr_dmv_444;
+            decoder->motion_parser[4] = motion_reuse_444;
+        }
+    }
+    else
+    {
+        if (decoder->chroma_format == 0)
+        {
+            decoder->motion_parser[0] = motion_zero_420;
+            decoder->motion_parser[MC_FIELD] = motion_fi_field_420;
+            decoder->motion_parser[MC_16X8] = motion_fi_16x8_420;
+            decoder->motion_parser[MC_DMV] = motion_fi_dmv_420;
+            decoder->motion_parser[4] = motion_reuse_420;
+        }
+        else if (decoder->chroma_format == 1)
+        {
+            decoder->motion_parser[0] = motion_zero_422;
+            decoder->motion_parser[MC_FIELD] = motion_fi_field_422;
+            decoder->motion_parser[MC_16X8] = motion_fi_16x8_422;
+            decoder->motion_parser[MC_DMV] = motion_fi_dmv_422;
+            decoder->motion_parser[4] = motion_reuse_422;
+        }
+        else
+        {
+            decoder->motion_parser[0] = motion_zero_444;
+            decoder->motion_parser[MC_FIELD] = motion_fi_field_444;
+            decoder->motion_parser[MC_16X8] = motion_fi_16x8_444;
+            decoder->motion_parser[MC_DMV] = motion_fi_dmv_444;
+            decoder->motion_parser[4] = motion_reuse_444;
+        }
+    }
+}
diff --git a/modules/codec/xvmc/slice_xvmc_vld.c b/modules/codec/xvmc/slice_xvmc_vld.c
new file mode 100644 (file)
index 0000000..93bdba9
--- /dev/null
@@ -0,0 +1,307 @@
+/* $Id:$
+ * Copyright (c) 2004 The Unichrome project. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTIES OR REPRESENTATIONS; 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 <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#include "mpeg2.h"
+#include "mpeg2_internal.h"
+#include "xvmc_vld.h"
+
+static uint8_t zig_zag_scan[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
+};
+
+static uint8_t alternate_scan [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
+};
+
+
+
+
+void mpeg2_xxmc_choose_coding(decoder_t *p_dec, mpeg2_decoder_t * const decoder, picture_t *picture,
+                             double aspect_ratio, int flags) 
+{
+    if (picture)
+    {
+        //vlc_fourcc_t decoder_format = picture->format.i_chroma;
+        //if (decoder_format == VLC_FOURCC('X','x','M','C')) {
+        vlc_xxmc_t *xxmc = (vlc_xxmc_t *) picture->p_accel_data;
+
+        /*
+         * Make a request for acceleration type and mpeg coding from
+         * the output plugin.
+         */
+
+        xxmc->fallback_format = VLC_FOURCC('Y','V','1','2');
+        xxmc->acceleration = VLC_XVMC_ACCEL_VLD;//| VLC_XVMC_ACCEL_IDCT| VLC_XVMC_ACCEL_MOCOMP ;
+
+        //msg_Dbg(p_dec, "mpeg2_xxmc_choose_coding 2");
+        /*
+         * Standard MOCOMP / IDCT XvMC implementation for interlaced streams
+         * is buggy. The bug is inherited from the old XvMC driver. Don't use it until
+         * it has been fixed. (A volunteer ?)
+         */
+
+        //if ( decoder->picture_structure != 3 ) {
+        //xxmc->acceleration &= ~( VLC_XVMC_ACCEL_IDCT | VLC_XVMC_ACCEL_MOCOMP );
+        //}
+
+        xxmc->mpeg = (decoder->mpeg1) ? VLC_XVMC_MPEG_1:VLC_XVMC_MPEG_2;
+        xxmc->proc_xxmc_update_frame( picture,
+                                      decoder->width,
+                                      decoder->height,
+                                      aspect_ratio,
+                                      VLC_IMGFMT_XXMC, flags );
+        //}
+  }
+}
+
+void mpeg2_xxmc_slice( mpeg2dec_t *mpeg2dec, picture_t *picture, int code,
+                      uint8_t *buffer, int size) 
+{
+    mpeg2_decoder_t * const decoder = &(mpeg2dec->decoder);
+    picture = (picture_t *)mpeg2dec->fbuf[0]->id;
+    vlc_xxmc_t *xxmc = (vlc_xxmc_t *) picture->p_accel_data;
+    vlc_vld_frame_t *vft = &xxmc->vld_frame;
+    unsigned mb_frame_height;
+    int i;
+    const uint8_t *scan_pattern;
+
+    if (1 == code)
+    {
+        //mpeg2_skip(mpeg2dec, 1);
+        //frame->bad_frame = 1;
+
+        /*
+         * Check that first field went through OK. Otherwise,
+         * indicate bad frame.
+         */ 
+        if (decoder->second_field)
+        {
+            mpeg2dec->xvmc_last_slice_code = (xxmc->decoded) ? 0 : -1;
+            xxmc->decoded = 0;
+        }
+        else
+        {
+            mpeg2dec->xvmc_last_slice_code = 0;
+        }
+
+        mb_frame_height =
+                //(!(decoder->mpeg1) && (decoder->progressive_sequence)) ?
+                //2*((decoder->height+31) >> 5) :
+                (decoder->height+15) >> 4;
+        mpeg2dec->xxmc_mb_pic_height = (decoder->picture_structure == FRAME_PICTURE ) ?
+                                        mb_frame_height : mb_frame_height >> 1;
+
+        if (decoder->mpeg1)
+        {
+            vft->mv_ranges[0][0] = decoder->b_motion.f_code[0];
+            vft->mv_ranges[0][1] = decoder->b_motion.f_code[0];
+            vft->mv_ranges[1][0] = decoder->f_motion.f_code[0];
+            vft->mv_ranges[1][1] = decoder->f_motion.f_code[0];
+        }
+        else
+        {
+            vft->mv_ranges[0][0] = decoder->b_motion.f_code[0];
+            vft->mv_ranges[0][1] = decoder->b_motion.f_code[1];
+            vft->mv_ranges[1][0] = decoder->f_motion.f_code[0];
+            vft->mv_ranges[1][1] = decoder->f_motion.f_code[1];
+        }
+
+        vft->picture_structure = decoder->picture_structure;
+        vft->picture_coding_type = decoder->coding_type;
+        vft->mpeg_coding = (decoder->mpeg1) ? 0 : 1;
+        vft->progressive_sequence = decoder->progressive_sequence;
+        vft->scan = (decoder->scan == mpeg2_scan_alt);
+        vft->pred_dct_frame = decoder->frame_pred_frame_dct;
+        vft->concealment_motion_vectors =
+        decoder->concealment_motion_vectors;
+        vft->q_scale_type = decoder->q_scale_type;
+        vft->intra_vlc_format = decoder->intra_vlc_format;
+        vft->intra_dc_precision = 7 - decoder->intra_dc_precision;
+        vft->second_field = decoder->second_field;
+
+        /*
+         * Translation of libmpeg2's Q-matrix layout to VLD XvMC's.
+         * Errors here will give
+         * blocky artifacts and sometimes wrong colors.
+         */
+
+        scan_pattern = (vft->scan) ? alternate_scan : zig_zag_scan;
+        if( (vft->load_intra_quantizer_matrix = decoder->load_intra_quantizer_matrix) )
+        {
+            for (i=0; i<64; ++i)
+            {
+                vft->intra_quantizer_matrix[scan_pattern[i]] =
+                mpeg2dec->quantizer_matrix[0][decoder->scan[i]];
+            }
+        }
+
+        if( (vft->load_non_intra_quantizer_matrix = decoder->load_non_intra_quantizer_matrix) )
+        {
+            for (i=0; i<64; ++i)
+            {
+                vft->non_intra_quantizer_matrix[scan_pattern[i]] =
+                                        mpeg2dec->quantizer_matrix[1][decoder->scan[i]];
+            }
+        }
+        decoder->load_intra_quantizer_matrix = 0;
+        decoder->load_non_intra_quantizer_matrix = 0;
+
+        vft->forward_reference_picture = (picture_t *)mpeg2dec->ptr_forward_ref_picture;
+        vft->backward_reference_picture = (picture_t *)mpeg2dec->ptr_backward_ref_picture;
+
+#if 0
+    printf("\nSLICE DATA !!!! size=%d", size-4);
+    int i=0;
+    if ( vft->forward_reference_picture != NULL && ((vlc_xxmc_t *)
+         vft->forward_reference_picture->p_accel_data)->slice_data_size > 10)
+    {
+        printf("\nFORWARD SLICE DATA !!!! size=%d\n", ((vlc_xxmc_t *)
+               vft->forward_reference_picture->p_accel_data)->slice_data_size);
+        for (i=0;i<10;i++)
+        {
+            printf("%d ", *(((vlc_xxmc_t *) vft->forward_reference_picture->p_accel_data)->slice_data+i));
+        }
+        printf("\nFORWARD SLICE DATA END!!!!\n");
+    }
+    if ( vft->backward_reference_picture != NULL && ((vlc_xxmc_t *)
+         vft->backward_reference_picture->p_accel_data)->slice_data_size > 10)
+    {
+        printf("\nBACKWARD SLICE DATA !!!! size=%d\n", ((vlc_xxmc_t *)
+               vft->backward_reference_picture->p_accel_data)->slice_data_size);
+        for (i=0;i<10;i++)
+        {
+            printf("%d ", *(((vlc_xxmc_t *) vft->backward_reference_picture->p_accel_data)->slice_data+i));
+        }
+        printf("\nBACKWARD SLICE DATA END!!!!\n");
+    }
+#endif
+
+        xxmc->proc_xxmc_begin( picture );
+        if (xxmc->result != 0)
+        {
+            /* "mpeg2_xxmc_slice begin failed" */
+            /* xmc->proc_xxmc_flushsync( picture ); */
+            xxmc->proc_xxmc_flush( picture );
+            mpeg2dec->xvmc_last_slice_code=-1;
+        }
+    }
+
+    if( ((code == mpeg2dec->xvmc_last_slice_code + 1 ||
+        code == mpeg2dec->xvmc_last_slice_code)) &&
+        code <= mpeg2dec->xxmc_mb_pic_height )
+    {
+        /*
+         * Send this slice to the output plugin. May stall for a long
+         * time in proc_slice;
+         */
+        //mpeg2_skip(mpeg2dec, 1);
+
+        //frame->bad_frame = 1;
+        //size = mpeg2dec->chunk_ptr-mpeg2dec->chunk_start;
+        xxmc->slice_data_size = size;//mpeg2dec->buf_end - mpeg2dec->buf_start;
+        xxmc->slice_data = mpeg2dec->chunk_start;//buffer;
+        xxmc->slice_code = code;
+        xxmc->proc_xxmc_slice( picture );
+
+        if (xxmc->result != 0)
+        {
+            //xxmc->proc_xxmc_flushsync( picture );
+            xxmc->proc_xxmc_flush( picture );  
+            mpeg2dec->xvmc_last_slice_code=-1;
+            return;
+        }
+        if (code == mpeg2dec->xxmc_mb_pic_height)
+        {
+            /*
+             * We've encountered the last slice of this frame.
+             * Release the decoder for a new frame and, if all
+             * went well, tell libmpeg2 that we are ready.
+             */
+
+            mpeg2_xxmc_vld_frame_complete(mpeg2dec,picture,code);
+            return;
+        }
+        else if (code == mpeg2dec->xvmc_last_slice_code + 1)
+        {
+            //xxmc->proc_xxmc_flush( picture );
+
+            /*
+             * Keep track of slices.
+             */
+            mpeg2dec->xvmc_last_slice_code++;
+        }
+    }
+    else
+    {
+        /*
+         * An error has occured.
+         */
+
+        //printf("VLD XvMC: Slice error: code=%d\tlast slice code=%d\tmb_pic_height=%d\n", code, mpeg2dec->xvmc_last_slice_code,mpeg2dec->xxmc_mb_pic_height);
+        mpeg2dec->xvmc_last_slice_code = -1;
+        xxmc->proc_xxmc_flush( picture );
+        return;
+    }
+}
+
+void mpeg2_xxmc_vld_frame_complete(mpeg2dec_t *mpeg2dec, picture_t *picture, int code) 
+{
+    vlc_xxmc_t *xxmc = (vlc_xxmc_t *) picture->p_accel_data;
+    vlc_vld_frame_t *vft = &xxmc->vld_frame;
+
+    if (xxmc->decoded)
+        return;
+
+    if (mpeg2dec->xvmc_last_slice_code >= 1)
+    {
+        xxmc->proc_xxmc_flush( picture );
+        if (xxmc->result)
+        {
+            mpeg2dec->xvmc_last_slice_code=-1;
+            return;
+        }
+        xxmc->decoded = 1;
+        mpeg2dec->xvmc_last_slice_code++;
+        if (vft->picture_structure == 3 || vft->second_field)
+        {
+            if (xxmc->result == 0)
+                mpeg2_skip(mpeg2dec, 0);
+            //frame->bad_frame = 0;
+        }
+    }
+}
+
diff --git a/modules/codec/xvmc/vlc.h b/modules/codec/xvmc/vlc.h
new file mode 100644 (file)
index 0000000..47d0ea7
--- /dev/null
@@ -0,0 +1,453 @@
+/* $Id:$
+ * vlc.h
+ * Copyright (C) 2000-2003 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
+ */
+
+#define GETWORD(bit_buf,shift,bit_ptr)                         \
+do {                                                           \
+    bit_buf |= ((bit_ptr[0] << 8) | bit_ptr[1]) << (shift);    \
+    bit_ptr += 2;                                              \
+} while (0)
+
+static inline void bitstream_init (mpeg2_decoder_t * decoder,
+                                  const uint8_t * start)
+{
+    decoder->bitstream_buf =
+       (start[0] << 24) | (start[1] << 16) | (start[2] << 8) | start[3];
+    decoder->bitstream_ptr = start + 4;
+    decoder->bitstream_bits = -16;
+}
+
+/* make sure that there are at least 16 valid bits in bit_buf */
+#define NEEDBITS(bit_buf,bits,bit_ptr)         \
+do {                                           \
+    if (unlikely (bits > 0)) {                 \
+       GETWORD (bit_buf, bits, bit_ptr);       \
+       bits -= 16;                             \
+    }                                          \
+} while (0)
+
+/* remove num valid bits from bit_buf */
+#define DUMPBITS(bit_buf,bits,num)     \
+do {                                   \
+    bit_buf <<= (num);                 \
+    bits += (num);                     \
+} while (0)
+
+/* take num bits from the high part of bit_buf and zero extend them */
+#define UBITS(bit_buf,num) (((uint32_t)(bit_buf)) >> (32 - (num)))
+
+/* take num bits from the high part of bit_buf and sign extend them */
+#define SBITS(bit_buf,num) (((int32_t)(bit_buf)) >> (32 - (num)))
+
+typedef struct
+{
+    uint8_t modes;
+    uint8_t len;
+} MBtab;
+
+typedef struct
+{
+    uint8_t delta;
+    uint8_t len;
+} MVtab;
+
+typedef struct
+{
+    int8_t dmv;
+    uint8_t len;
+} DMVtab;
+
+typedef struct
+{
+    uint8_t cbp;
+    uint8_t len;
+} CBPtab;
+
+typedef struct
+{
+    uint8_t size;
+    uint8_t len;
+} DCtab;
+
+typedef struct
+{
+    uint8_t run;
+    uint8_t level;
+    uint8_t len;
+} DCTtab;
+
+typedef struct
+{
+    uint8_t mba;
+    uint8_t len;
+} MBAtab;
+
+#define INTRA MACROBLOCK_INTRA
+#define QUANT MACROBLOCK_QUANT
+
+static const MBtab MB_I [] =
+{
+    {INTRA|QUANT, 2}, {INTRA, 1}
+};
+
+#define MC MACROBLOCK_MOTION_FORWARD
+#define CODED MACROBLOCK_PATTERN
+
+static const MBtab MB_P [] =
+{
+    {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA,    5},
+    {MC,          3}, {MC,          3}, {MC,             3}, {MC,       3},
+    {CODED,       2}, {CODED,       2}, {CODED,          2}, {CODED,    2},
+    {CODED,       2}, {CODED,       2}, {CODED,          2}, {CODED,    2},
+    {MC|CODED,    1}, {MC|CODED,    1}, {MC|CODED,       1}, {MC|CODED, 1},
+    {MC|CODED,    1}, {MC|CODED,    1}, {MC|CODED,       1}, {MC|CODED, 1},
+    {MC|CODED,    1}, {MC|CODED,    1}, {MC|CODED,       1}, {MC|CODED, 1},
+    {MC|CODED,    1}, {MC|CODED,    1}, {MC|CODED,       1}, {MC|CODED, 1}
+};
+
+#define FWD MACROBLOCK_MOTION_FORWARD
+#define BWD MACROBLOCK_MOTION_BACKWARD
+#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD
+
+static const MBtab MB_B [] =
+{
+    {0,                 0}, {INTRA|QUANT,       6},
+    {BWD|CODED|QUANT,   6}, {FWD|CODED|QUANT,   6},
+    {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5},
+    {INTRA,       5}, {INTRA,       5},
+    {FWD,         4}, {FWD,         4}, {FWD,         4}, {FWD,         4},
+    {FWD|CODED,   4}, {FWD|CODED,   4}, {FWD|CODED,   4}, {FWD|CODED,   4},
+    {BWD,         3}, {BWD,         3}, {BWD,         3}, {BWD,         3},
+    {BWD,         3}, {BWD,         3}, {BWD,         3}, {BWD,         3},
+    {BWD|CODED,   3}, {BWD|CODED,   3}, {BWD|CODED,   3}, {BWD|CODED,   3},
+    {BWD|CODED,   3}, {BWD|CODED,   3}, {BWD|CODED,   3}, {BWD|CODED,   3},
+    {INTER,       2}, {INTER,       2}, {INTER,       2}, {INTER,       2},
+    {INTER,       2}, {INTER,       2}, {INTER,       2}, {INTER,       2},
+    {INTER,       2}, {INTER,       2}, {INTER,       2}, {INTER,       2},
+    {INTER,       2}, {INTER,       2}, {INTER,       2}, {INTER,       2},
+    {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
+    {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
+    {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
+    {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}
+};
+
+#undef INTRA
+#undef QUANT
+#undef MC
+#undef CODED
+#undef FWD
+#undef BWD
+#undef INTER
+
+static const MVtab MV_4 [] =
+{
+    { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2}
+};
+
+static const MVtab MV_10 [] =
+{
+    { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10},
+    { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10},
+    {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9},
+    { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7},
+    { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7},
+    { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}
+};
+
+static const DMVtab DMV_2 [] =
+{
+    { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2}
+};
+
+static const CBPtab CBP_7 [] =
+{
+    {0x11, 7}, {0x12, 7}, {0x14, 7}, {0x18, 7},
+    {0x21, 7}, {0x22, 7}, {0x24, 7}, {0x28, 7},
+    {0x3f, 6}, {0x3f, 6}, {0x30, 6}, {0x30, 6},
+    {0x09, 6}, {0x09, 6}, {0x06, 6}, {0x06, 6},
+    {0x1f, 5}, {0x1f, 5}, {0x1f, 5}, {0x1f, 5},
+    {0x10, 5}, {0x10, 5}, {0x10, 5}, {0x10, 5},
+    {0x2f, 5}, {0x2f, 5}, {0x2f, 5}, {0x2f, 5},
+    {0x20, 5}, {0x20, 5}, {0x20, 5}, {0x20, 5},
+    {0x07, 5}, {0x07, 5}, {0x07, 5}, {0x07, 5},
+    {0x0b, 5}, {0x0b, 5}, {0x0b, 5}, {0x0b, 5},
+    {0x0d, 5}, {0x0d, 5}, {0x0d, 5}, {0x0d, 5},
+    {0x0e, 5}, {0x0e, 5}, {0x0e, 5}, {0x0e, 5},
+    {0x05, 5}, {0x05, 5}, {0x05, 5}, {0x05, 5},
+    {0x0a, 5}, {0x0a, 5}, {0x0a, 5}, {0x0a, 5},
+    {0x03, 5}, {0x03, 5}, {0x03, 5}, {0x03, 5},
+    {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5},
+    {0x01, 4}, {0x01, 4}, {0x01, 4}, {0x01, 4},
+    {0x01, 4}, {0x01, 4}, {0x01, 4}, {0x01, 4},
+    {0x02, 4}, {0x02, 4}, {0x02, 4}, {0x02, 4},
+    {0x02, 4}, {0x02, 4}, {0x02, 4}, {0x02, 4},
+    {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
+    {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
+    {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
+    {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
+    {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3},
+    {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3},
+    {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3},
+    {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3}
+};
+
+static const CBPtab CBP_9 [] =
+{
+    {0,    0}, {0x00, 9}, {0x39, 9}, {0x36, 9},
+    {0x37, 9}, {0x3b, 9}, {0x3d, 9}, {0x3e, 9},
+    {0x17, 8}, {0x17, 8}, {0x1b, 8}, {0x1b, 8},
+    {0x1d, 8}, {0x1d, 8}, {0x1e, 8}, {0x1e, 8},
+    {0x27, 8}, {0x27, 8}, {0x2b, 8}, {0x2b, 8},
+    {0x2d, 8}, {0x2d, 8}, {0x2e, 8}, {0x2e, 8},
+    {0x19, 8}, {0x19, 8}, {0x16, 8}, {0x16, 8},
+    {0x29, 8}, {0x29, 8}, {0x26, 8}, {0x26, 8},
+    {0x35, 8}, {0x35, 8}, {0x3a, 8}, {0x3a, 8},
+    {0x33, 8}, {0x33, 8}, {0x3c, 8}, {0x3c, 8},
+    {0x15, 8}, {0x15, 8}, {0x1a, 8}, {0x1a, 8},
+    {0x13, 8}, {0x13, 8}, {0x1c, 8}, {0x1c, 8},
+    {0x25, 8}, {0x25, 8}, {0x2a, 8}, {0x2a, 8},
+    {0x23, 8}, {0x23, 8}, {0x2c, 8}, {0x2c, 8},
+    {0x31, 8}, {0x31, 8}, {0x32, 8}, {0x32, 8},
+    {0x34, 8}, {0x34, 8}, {0x38, 8}, {0x38, 8}
+};
+
+
+static const DCtab DC_lum_5 [] =
+{
+    {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
+    {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
+    {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3},
+    {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}
+};
+
+static const DCtab DC_chrom_5 [] =
+{
+    {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2},
+    {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
+    {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
+    {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}
+};
+
+static const DCtab DC_long [] =
+{
+    {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
+    {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
+    {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6},
+    {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9}
+};
+
+static const DCTtab DCT_16 [] =
+{
+    {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
+    {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
+    {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
+    {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
+    {  2,18, 0}, {  2,17, 0}, {  2,16, 0}, {  2,15, 0},
+    {  7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0},
+    { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0},
+    { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0}
+};
+
+static const DCTtab DCT_15 [] =
+{
+    {  1,40,15}, {  1,39,15}, {  1,38,15}, {  1,37,15},
+    {  1,36,15}, {  1,35,15}, {  1,34,15}, {  1,33,15},
+    {  1,32,15}, {  2,14,15}, {  2,13,15}, {  2,12,15},
+    {  2,11,15}, {  2,10,15}, {  2, 9,15}, {  2, 8,15},
+    {  1,31,14}, {  1,31,14}, {  1,30,14}, {  1,30,14},
+    {  1,29,14}, {  1,29,14}, {  1,28,14}, {  1,28,14},
+    {  1,27,14}, {  1,27,14}, {  1,26,14}, {  1,26,14},
+    {  1,25,14}, {  1,25,14}, {  1,24,14}, {  1,24,14},
+    {  1,23,14}, {  1,23,14}, {  1,22,14}, {  1,22,14},
+    {  1,21,14}, {  1,21,14}, {  1,20,14}, {  1,20,14},
+    {  1,19,14}, {  1,19,14}, {  1,18,14}, {  1,18,14},
+    {  1,17,14}, {  1,17,14}, {  1,16,14}, {  1,16,14}
+};
+
+static const DCTtab DCT_13 [] =
+{
+    { 11, 2,13}, { 10, 2,13}, {  6, 3,13}, {  4, 4,13},
+    {  3, 5,13}, {  2, 7,13}, {  2, 6,13}, {  1,15,13},
+    {  1,14,13}, {  1,13,13}, {  1,12,13}, { 27, 1,13},
+    { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13},
+    {  1,11,12}, {  1,11,12}, {  9, 2,12}, {  9, 2,12},
+    {  5, 3,12}, {  5, 3,12}, {  1,10,12}, {  1,10,12},
+    {  3, 4,12}, {  3, 4,12}, {  8, 2,12}, {  8, 2,12},
+    { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12},
+    {  1, 9,12}, {  1, 9,12}, { 20, 1,12}, { 20, 1,12},
+    { 19, 1,12}, { 19, 1,12}, {  2, 5,12}, {  2, 5,12},
+    {  4, 3,12}, {  4, 3,12}, {  1, 8,12}, {  1, 8,12},
+    {  7, 2,12}, {  7, 2,12}, { 18, 1,12}, { 18, 1,12}
+};
+
+static const DCTtab DCT_B14_10 [] =
+{
+    { 17, 1,10}, {  6, 2,10}, {  1, 7,10}, {  3, 3,10},
+    {  2, 4,10}, { 16, 1,10}, { 15, 1,10}, {  5, 2,10}
+};
+
+static const DCTtab DCT_B14_8 [] =
+{
+    { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
+    {  3, 2, 7}, {  3, 2, 7}, { 10, 1, 7}, { 10, 1, 7},
+    {  1, 4, 7}, {  1, 4, 7}, {  9, 1, 7}, {  9, 1, 7},
+    {  8, 1, 6}, {  8, 1, 6}, {  8, 1, 6}, {  8, 1, 6},
+    {  7, 1, 6}, {  7, 1, 6}, {  7, 1, 6}, {  7, 1, 6},
+    {  2, 2, 6}, {  2, 2, 6}, {  2, 2, 6}, {  2, 2, 6},
+    {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6},
+    { 14, 1, 8}, {  1, 6, 8}, { 13, 1, 8}, { 12, 1, 8},
+    {  4, 2, 8}, {  2, 3, 8}, {  1, 5, 8}, { 11, 1, 8}
+};
+
+static const DCTtab DCT_B14AC_5 [] =
+{
+                 {  1, 3, 5}, {  5, 1, 5}, {  4, 1, 5},
+    {  1, 2, 4}, {  1, 2, 4}, {  3, 1, 4}, {  3, 1, 4},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
+    {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}
+};
+
+static const DCTtab DCT_B14DC_5 [] =
+{
+                 {  1, 3, 5}, {  5, 1, 5}, {  4, 1, 5},
+    {  1, 2, 4}, {  1, 2, 4}, {  3, 1, 4}, {  3, 1, 4},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1},
+    {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1},
+    {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1},
+    {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}
+};
+
+static const DCTtab DCT_B15_10 [] =
+{
+    {  6, 2, 9}, {  6, 2, 9}, { 15, 1, 9}, { 15, 1, 9},
+    {  3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9}
+};
+
+static const DCTtab DCT_B15_8 [] =
+{
+    { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
+    {  8, 1, 7}, {  8, 1, 7}, {  9, 1, 7}, {  9, 1, 7},
+    {  7, 1, 7}, {  7, 1, 7}, {  3, 2, 7}, {  3, 2, 7},
+    {  1, 7, 6}, {  1, 7, 6}, {  1, 7, 6}, {  1, 7, 6},
+    {  1, 6, 6}, {  1, 6, 6}, {  1, 6, 6}, {  1, 6, 6},
+    {  5, 1, 6}, {  5, 1, 6}, {  5, 1, 6}, {  5, 1, 6},
+    {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6},
+    {  2, 5, 8}, { 12, 1, 8}, {  1,11, 8}, {  1,10, 8},
+    { 14, 1, 8}, { 13, 1, 8}, {  4, 2, 8}, {  2, 4, 8},
+    {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5},
+    {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5},
+    {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5},
+    {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5},
+    {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5},
+    {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
+    {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+    {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+    {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+    {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+    {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
+    {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
+    {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
+    {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
+    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
+    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
+    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
+    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
+    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
+    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
+    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
+    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
+    {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5},
+    {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5},
+    {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5},
+    {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5},
+    { 10, 1, 7}, { 10, 1, 7}, {  2, 3, 7}, {  2, 3, 7},
+    { 11, 1, 7}, { 11, 1, 7}, {  1, 8, 7}, {  1, 8, 7},
+    {  1, 9, 7}, {  1, 9, 7}, {  1,12, 8}, {  1,13, 8},
+    {  3, 3, 8}, {  5, 2, 8}, {  1,14, 8}, {  1,15, 8}
+};
+
+
+static const MBAtab MBA_5 [] =
+{
+            {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4},
+    {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+    {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1},
+    {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}
+};
+
+static const MBAtab MBA_11 [] =
+{
+    {32, 11}, {31, 11}, {30, 11}, {29, 11},
+    {28, 11}, {27, 11}, {26, 11}, {25, 11},
+    {24, 11}, {23, 11}, {22, 11}, {21, 11},
+    {20, 10}, {20, 10}, {19, 10}, {19, 10},
+    {18, 10}, {18, 10}, {17, 10}, {17, 10},
+    {16, 10}, {16, 10}, {15, 10}, {15, 10},
+    {14,  8}, {14,  8}, {14,  8}, {14,  8},
+    {14,  8}, {14,  8}, {14,  8}, {14,  8},
+    {13,  8}, {13,  8}, {13,  8}, {13,  8},
+    {13,  8}, {13,  8}, {13,  8}, {13,  8},
+    {12,  8}, {12,  8}, {12,  8}, {12,  8},
+    {12,  8}, {12,  8}, {12,  8}, {12,  8},
+    {11,  8}, {11,  8}, {11,  8}, {11,  8},
+    {11,  8}, {11,  8}, {11,  8}, {11,  8},
+    {10,  8}, {10,  8}, {10,  8}, {10,  8},
+    {10,  8}, {10,  8}, {10,  8}, {10,  8},
+    { 9,  8}, { 9,  8}, { 9,  8}, { 9,  8},
+    { 9,  8}, { 9,  8}, { 9,  8}, { 9,  8},
+    { 8,  7}, { 8,  7}, { 8,  7}, { 8,  7},
+    { 8,  7}, { 8,  7}, { 8,  7}, { 8,  7},
+    { 8,  7}, { 8,  7}, { 8,  7}, { 8,  7},
+    { 8,  7}, { 8,  7}, { 8,  7}, { 8,  7},
+    { 7,  7}, { 7,  7}, { 7,  7}, { 7,  7},
+    { 7,  7}, { 7,  7}, { 7,  7}, { 7,  7},
+    { 7,  7}, { 7,  7}, { 7,  7}, { 7,  7},
+    { 7,  7}, { 7,  7}, { 7,  7}, { 7,  7}
+};
diff --git a/modules/codec/xvmc/xvmc_vld.h b/modules/codec/xvmc/xvmc_vld.h
new file mode 100644 (file)
index 0000000..86bc95c
--- /dev/null
@@ -0,0 +1,34 @@
+/* $Id:$
+ * Copyright (c) 2004 The Unichrome project. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTIES OR REPRESENTATIONS; 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.
+ *
+ *
+ */
+
+#ifndef _XVMC_VLD_H
+#define _XVMC_VLD_H
+
+#include "accel_xvmc.h"
+//#include "xvmc.h"
+
+extern void mpeg2_xxmc_slice( mpeg2dec_t *mpeg2dec, picture_t *picture,
+                              int code, uint8_t *buffer, int size );
+extern void mpeg2_xxmc_choose_coding( decoder_t *p_dec,
+                mpeg2_decoder_t * const decoder, picture_t *picture,
+                double aspect_ratio, int flags );
+extern void mpeg2_xxmc_vld_frame_complete( mpeg2dec_t *mpeg2dec,
+                picture_t *picture, int code );
+
+#endif
diff --git a/modules/codec/xvmc/xxmc-config.h b/modules/codec/xvmc/xxmc-config.h
new file mode 100644 (file)
index 0000000..e9e3cc7
--- /dev/null
@@ -0,0 +1,173 @@
+/* include/config.h.  Generated by configure.  */
+/* include/config.h.in.  Generated from configure.in by autoheader.  */
+
+/* autodetect accelerations */
+#define ACCEL_DETECT 
+
+/* alpha architecture */
+/* #undef ARCH_ALPHA */
+
+/* ppc architecture */
+/* #undef ARCH_PPC */
+
+/* sparc architecture */
+/* #undef ARCH_SPARC */
+
+/* x86 architecture */
+#define ARCH_X86 
+
+/* maximum supported data alignment */
+#define ATTRIBUTE_ALIGNED_MAX 64
+
+/* debug mode configuration */
+/* #undef DEBUG */
+
+/* Define to 1 if you have the <altivec.h> header file. */
+/* #undef HAVE_ALTIVEC_H */
+
+/* Define if you have the `__builtin_expect' function. */
+#define HAVE_BUILTIN_EXPECT 
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ftime' function. */
+#define HAVE_FTIME 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct timeval'. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* libvo DirectX support */
+/* #undef LIBVO_DX */
+
+/* libvo SDL support */
+/* #undef LIBVO_SDL */
+
+/* libvo X11 support */
+#define LIBVO_X11 
+
+/* libvo Xv support */
+#define LIBVO_XV 
+
+/* mpeg2dec profiling */
+/* #undef MPEG2DEC_GPROF */
+
+/* Name of package */
+#define PACKAGE "mpeg2dec"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* The size of a `char', as computed by sizeof. */
+/* #undef SIZEOF_CHAR */
+
+/* The size of a `int', as computed by sizeof. */
+/* #undef SIZEOF_INT */
+
+/* The size of a `long', as computed by sizeof. */
+/* #undef SIZEOF_LONG */
+
+/* The size of a `short', as computed by sizeof. */
+/* #undef SIZEOF_SHORT */
+
+/* The size of a `void*', as computed by sizeof. */
+/* #undef SIZEOF_VOIDP */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Version number of package */
+#define VERSION "0.4.0"
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to 1 if the X Window System is missing or not being used. */
+/* #undef X_DISPLAY_MISSING */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#define inline __attribute__ ((__always_inline__))
+#endif
+
+/* Define as `__restrict' if that's what the C compiler calls it, or to
+   nothing if it is not supported. */
+#define restrict __restrict__
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+   code using `volatile' can become incorrect without. Disable with care. */
+/* #undef volatile */
diff --git a/modules/codec/xvmc/xxmc.c b/modules/codec/xvmc/xxmc.c
new file mode 100644 (file)
index 0000000..aa7e4c2
--- /dev/null
@@ -0,0 +1,729 @@
+/*****************************************************************************
+ * xxmc.c : HW MPEG decoder thread
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id$
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *          Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#include <mcheck.h>
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+#include "xvmc_vld.h"
+
+#include "vout_synchro.h"
+
+/* Aspect ratio (ISO/IEC 13818-2 section 6.3.3, table 6-3) */
+#define AR_SQUARE_PICTURE       1                           /* square pixels */
+#define AR_3_4_PICTURE          2                        /* 3:4 picture (TV) */
+#define AR_16_9_PICTURE         3              /* 16:9 picture (wide screen) */
+#define AR_221_1_PICTURE        4                  /* 2.21:1 picture (movie) */
+
+#include <unistd.h>
+/*****************************************************************************
+ * decoder_sys_t : libmpeg2 decoder descriptor
+ *****************************************************************************/
+struct decoder_sys_t
+{
+    /*
+     * libmpeg2 properties
+     */
+    mpeg2dec_t          *p_mpeg2dec;
+    const mpeg2_info_t  *p_info;
+    vlc_bool_t          b_skip;
+
+    /*
+     * Input properties
+     */
+    pes_packet_t     *p_pes;                  /* current PES we are decoding */
+    mtime_t          i_pts;
+    mtime_t          i_previous_pts;
+    mtime_t          i_current_pts;
+    mtime_t          i_previous_dts;
+    mtime_t          i_current_dts;    
+    int              i_current_rate;
+    picture_t *      p_picture_to_destroy;
+    vlc_bool_t       b_garbage_pic;
+    vlc_bool_t       b_after_sequence_header; /* is it the next frame after
+                                               * the sequence header ?    */
+    vlc_bool_t       b_slice_i;             /* intra-slice refresh stream */
+
+    /*
+     * Output properties
+     */
+    vout_synchro_t *p_synchro;
+    int i_aspect;
+    mtime_t        i_last_frame_pts;   
+
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+
+static int  OpenDecoder( vlc_object_t * );
+static void CloseDecoder( vlc_object_t * );
+
+static picture_t *DecodeBlock( decoder_t *, block_t ** );
+
+static picture_t *GetNewPicture( decoder_t *, uint8_t ** );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+    set_description( _("MPEG I/II hw video decoder (using libmpeg2)") );
+    set_capability( "decoder", 160 );
+    set_callbacks( OpenDecoder, CloseDecoder );
+    add_shortcut( "xxmc" );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+
+    decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
+    uint32_t i_accel = 0;
+    FILE *f_wd_dec; 
+
+    msg_Dbg(p_dec, "OpenDecoder Entering");
+    mtrace();
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','v') &&
+        p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','1') &&
+        /* Pinnacle hardware-mpeg1 */
+        p_dec->fmt_in.i_codec != VLC_FOURCC('P','I','M','1') &&
+        /* VIA hardware-mpeg2 */
+        p_dec->fmt_in.i_codec != VLC_FOURCC('X','x','M','C') &&
+        /* ATI Video */
+        p_dec->fmt_in.i_codec != VLC_FOURCC('V','C','R','2') &&
+        p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','2') )
+    {
+        return VLC_EGENERIC;
+    }
+
+    /* Allocate the memory needed to store the decoder's structure */
+    if( ( p_dec->p_sys = p_sys =
+          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
+    {
+        msg_Err( p_dec, "out of memory" );
+        return VLC_EGENERIC;
+    }
+
+    /* Initialize the thread properties */
+    memset( p_sys, 0, sizeof(decoder_sys_t) );
+    p_sys->p_pes      = NULL;
+    p_sys->p_mpeg2dec = NULL;
+    p_sys->p_synchro  = NULL;
+    p_sys->p_info     = NULL;
+    p_sys->i_pts      = mdate() + DEFAULT_PTS_DELAY;
+    p_sys->i_current_pts  = 0;
+    p_sys->i_previous_pts = 0;
+    p_sys->i_current_dts  = 0;
+    p_sys->i_previous_dts = 0;
+    p_sys->p_picture_to_destroy = NULL;
+    p_sys->b_garbage_pic = 0;
+    p_sys->b_slice_i  = 0;
+    p_sys->b_skip     = 0;
+
+#if defined( __i386__ )
+    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_MMX )
+    {
+        i_accel |= MPEG2_ACCEL_X86_MMX;
+    }
+
+    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_3DNOW )
+    {
+        i_accel |= MPEG2_ACCEL_X86_3DNOW;
+    }
+
+    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT )
+    {
+        i_accel |= MPEG2_ACCEL_X86_MMXEXT;
+    }
+
+#elif defined( __powerpc__ ) || defined( SYS_DARWIN )
+    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_ALTIVEC )
+    {
+        i_accel |= MPEG2_ACCEL_PPC_ALTIVEC;
+    }
+
+#else
+    /* If we do not know this CPU, trust libmpeg2's feature detection */
+    i_accel = MPEG2_ACCEL_DETECT;
+
+#endif
+
+    /* Set CPU acceleration features */
+    mpeg2_accel( i_accel );
+
+    /* Initialize decoder */
+    p_sys->p_mpeg2dec = mpeg2_init();
+    if( p_sys->p_mpeg2dec == NULL)
+    {
+        msg_Err( p_dec, "mpeg2_init() failed" );
+        free( p_sys );
+        return VLC_EGENERIC;
+    }
+
+    p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec );
+
+    p_dec->pf_decode_video = DecodeBlock;
+
+    f_wd_dec = fopen("/vlc/dec_pid", "w");
+
+    if (f_wd_dec != NULL)
+    {
+        fprintf(f_wd_dec, "%d\n", getpid());
+        fflush(f_wd_dec);
+        fclose(f_wd_dec);
+    }
+
+    msg_Dbg(p_dec, "OpenDecoder Leaving");
+    return VLC_SUCCESS;
+}
+
+static void WriteDecodeFile(int value)
+{
+    FILE *f_wd_ok;
+
+    f_wd_ok = fopen("/vlc/dec_ok", "w");
+    if (f_wd_ok != NULL)
+    {
+        fprintf(f_wd_ok, "%d", value);
+        fflush(f_wd_ok);
+        fclose(f_wd_ok);
+    }
+}
+
+/*****************************************************************************
+ * RunDecoder: the libmpeg2 decoder
+ *****************************************************************************/
+static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
+{
+    decoder_sys_t   *p_sys = p_dec->p_sys;
+    mpeg2_state_t   state;
+    picture_t       *p_pic;
+
+    block_t *p_block;
+
+    if( !pp_block || !*pp_block )
+        return NULL;
+
+    p_block = *pp_block;
+    while( 1 )
+    {
+        state = mpeg2_parse( p_sys->p_mpeg2dec );
+        switch( state )
+        {
+            case STATE_BUFFER:
+                if( !p_block->i_buffer )
+                {
+                    block_Release( p_block );
+                    return NULL;
+                }
+                if( (p_block->i_flags&BLOCK_FLAG_DISCONTINUITY) &&
+                    p_sys->p_synchro &&
+                    p_sys->p_info->sequence &&
+                    p_sys->p_info->sequence->width != (unsigned int)-1 )
+                {
+                    vout_SynchroReset( p_sys->p_synchro );
+                    if( p_sys->p_info->current_fbuf != NULL
+                        && p_sys->p_info->current_fbuf->id != NULL )
+                    {
+                        p_sys->b_garbage_pic = 1;
+                        p_pic = p_sys->p_info->current_fbuf->id;
+                    }
+                    else
+                    {
+                        uint8_t *buf[3];
+                        buf[0] = buf[1] = buf[2] = NULL;
+                        if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
+                            break;
+                        mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
+                    }
+                    p_sys->p_picture_to_destroy = p_pic;
+
+                    if ( p_sys->b_slice_i )
+                    {
+                        vout_SynchroNewPicture( p_sys->p_synchro,
+                            I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
+                        vout_SynchroDecode( p_sys->p_synchro );
+                        vout_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
+                    }
+                }
+
+#ifdef PIC_FLAG_PTS
+                if( p_block->i_pts )
+                {
+                    mpeg2_pts( p_sys->p_mpeg2dec, (uint32_t)p_block->i_pts );
+
+#else /* New interface */
+                if( p_block->i_pts || p_block->i_dts )
+                {
+                    mpeg2_tag_picture( p_sys->p_mpeg2dec,
+                                        (uint32_t)p_block->i_pts,
+                                        (uint32_t)p_block->i_dts );
+#endif
+                    p_sys->i_previous_pts = p_sys->i_current_pts;
+                    p_sys->i_current_pts = p_block->i_pts;
+                    p_sys->i_previous_dts = p_sys->i_current_dts;
+                    p_sys->i_current_dts = p_block->i_dts;
+                }
+                p_sys->i_current_rate = p_block->i_rate;
+
+                mpeg2_buffer( p_sys->p_mpeg2dec, p_block->p_buffer,
+                                p_block->p_buffer + p_block->i_buffer );
+                p_block->i_buffer = 0;
+                break;
+
+            case STATE_SEQUENCE:
+            {
+                /* Initialize video output */
+                uint8_t *buf[3];
+                buf[0] = buf[1] = buf[2] = NULL;
+
+                /* Check whether the input gave a particular aspect ratio */
+                if( p_dec->fmt_in.video.i_aspect )
+                {
+                    p_sys->i_aspect = p_dec->fmt_in.video.i_aspect;
+                    if( p_sys->i_aspect <= AR_221_1_PICTURE )
+                    switch( p_sys->i_aspect )
+                    {
+                    case AR_3_4_PICTURE:
+                        p_sys->i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
+                        break;
+                    case AR_16_9_PICTURE:
+                        p_sys->i_aspect = VOUT_ASPECT_FACTOR * 16 / 9;
+                        break;
+                    case AR_221_1_PICTURE:
+                        p_sys->i_aspect = VOUT_ASPECT_FACTOR * 221 / 100;
+                        break;
+                    case AR_SQUARE_PICTURE:
+                        p_sys->i_aspect = VOUT_ASPECT_FACTOR *
+                                    p_sys->p_info->sequence->width /
+                                    p_sys->p_info->sequence->height;
+                        break;
+                    }
+                }
+                else
+                {
+                    /* Use the value provided in the MPEG sequence header */
+                    if( p_sys->p_info->sequence->pixel_height > 0 )
+                    {
+                        p_sys->i_aspect =
+                            ((uint64_t)p_sys->p_info->sequence->display_width) *
+                            p_sys->p_info->sequence->pixel_width *
+                            VOUT_ASPECT_FACTOR /
+                            p_sys->p_info->sequence->display_height /
+                            p_sys->p_info->sequence->pixel_height;
+                    }
+                    else
+                    {
+                        /* Invalid aspect, assume 4:3.
+                        * This shouldn't happen and if it does it is a bug
+                        * in libmpeg2 (likely triggered by an invalid stream) */
+                        p_sys->i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
+                    }
+                }
+
+                msg_Dbg( p_dec, "%dx%d, aspect %d, %u.%03u fps",
+                        p_sys->p_info->sequence->width,
+                        p_sys->p_info->sequence->height, p_sys->i_aspect,
+                        (uint32_t)((uint64_t)1001000000 * 27 /
+                            p_sys->p_info->sequence->frame_period / 1001),
+                        (uint32_t)((uint64_t)1001000000 * 27 /
+                            p_sys->p_info->sequence->frame_period % 1001) );
+
+                mpeg2_custom_fbuf( p_sys->p_mpeg2dec, 1 );
+
+                /* Set the first 2 reference frames */
+                mpeg2_set_buf( p_sys->p_mpeg2dec, buf, NULL );
+
+                if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
+                {
+                    block_Release( p_block );
+                    return NULL;
+                }
+                mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
+
+                p_pic->date = 0;
+                p_dec->pf_picture_link( p_dec, p_pic );
+
+                if( p_sys->p_synchro )
+                {
+                    vout_SynchroRelease( p_sys->p_synchro );
+                }
+                p_sys->p_synchro = vout_SynchroInit( p_dec,
+                    (uint32_t)((uint64_t)1001000000 * 27 /
+                    p_sys->p_info->sequence->frame_period) );
+                p_sys->b_after_sequence_header = 1;
+            }
+            break;
+
+            case STATE_PICTURE_2ND:
+                vout_SynchroNewPicture( p_sys->p_synchro,
+                        p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
+                        p_sys->p_info->current_picture->nb_fields,
+                        0, 0, p_sys->i_current_rate );
+
+                if( p_sys->b_skip )
+                {
+                    vout_SynchroTrash( p_sys->p_synchro );
+                }
+                else
+                {
+                    vout_SynchroDecode( p_sys->p_synchro );
+                }
+                break;
+
+            case STATE_PICTURE:
+            {
+                uint8_t *buf[3];
+                mtime_t i_pts;
+                buf[0] = buf[1] = buf[2] = NULL;
+
+                if ( p_sys->b_after_sequence_header &&
+                    ((p_sys->p_info->current_picture->flags &
+                        PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P) )
+                {
+                    /* Intra-slice refresh. Simulate a blank I picture. */
+                    msg_Dbg( p_dec, "intra-slice refresh stream" );
+                    vout_SynchroNewPicture( p_sys->p_synchro,
+                        I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
+                    vout_SynchroDecode( p_sys->p_synchro );
+                    vout_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
+                    p_sys->b_slice_i = 1;
+                }
+                p_sys->b_after_sequence_header = 0;
+
+#ifdef PIC_FLAG_PTS
+                i_pts = p_sys->p_info->current_picture->flags & PIC_FLAG_PTS ?
+                    ( ( p_sys->p_info->current_picture->pts ==
+                        (uint32_t)p_sys->i_current_pts ) ?
+                    p_sys->i_current_pts : p_sys->i_previous_pts ) : 0;
+#else /* New interface */
+                i_pts = p_sys->p_info->current_picture->flags & PIC_FLAG_TAGS ?
+                    ( ( p_sys->p_info->current_picture->tag ==
+                        (uint32_t)p_sys->i_current_pts ) ?
+                    p_sys->i_current_pts : p_sys->i_previous_pts ) : 0;
+#endif
+                /* Hack to handle demuxers which only have DTS timestamps */
+                if( !i_pts && !p_block->i_pts && p_block->i_dts > 0 )
+                {
+                    if( p_sys->p_info->sequence->flags & SEQ_FLAG_LOW_DELAY ||
+                        (p_sys->p_info->current_picture->flags &
+                        PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_B )
+                    {
+                        i_pts = p_block->i_dts;
+                    }
+                }
+                p_block->i_pts = p_block->i_dts = 0;
+                /* End hack */
+
+                vout_SynchroNewPicture( p_sys->p_synchro,
+                    p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
+                    p_sys->p_info->current_picture->nb_fields, i_pts,
+                    0, p_sys->i_current_rate );
+
+                if ( !(p_sys->b_slice_i
+                    && ((p_sys->p_info->current_picture->flags
+                            & PIC_MASK_CODING_TYPE) == P_CODING_TYPE))
+                    && !vout_SynchroChoose( p_sys->p_synchro,
+                                p_sys->p_info->current_picture->flags
+                                    & PIC_MASK_CODING_TYPE,
+                                /*FindVout(p_dec)->render_time*/ 0 /*FIXME*/ ) )
+                {
+                    mpeg2_skip( p_sys->p_mpeg2dec, 1 );
+                    p_sys->b_skip = 1;
+                    vout_SynchroTrash( p_sys->p_synchro );
+                    mpeg2_set_buf( p_sys->p_mpeg2dec, buf, NULL );
+                }
+                else
+                {
+                    mpeg2_skip( p_sys->p_mpeg2dec, 0 );
+                    p_sys->b_skip = 0;
+                    vout_SynchroDecode( p_sys->p_synchro );
+
+                    if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
+                    {
+                        block_Release( p_block );
+                        return NULL;
+                    }
+
+                    p_sys->p_mpeg2dec->ptr_forward_ref_picture = p_sys->p_mpeg2dec->fbuf[2]->id;
+                    p_sys->p_mpeg2dec->ptr_backward_ref_picture = p_sys->p_mpeg2dec->fbuf[1]->id;
+
+                    if ((p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE) != B_CODING_TYPE)
+                    {
+                        //if (p_sys->p_mpeg2dec->ptr_forward_ref_picture &&
+                        //    p_sys->p_mpeg2dec->ptr_forward_ref_picture != picture->backward_reference_frame)
+                        //    p_pic->forward_reference_frame->free (p_pic->forward_reference_frame);
+
+                        p_sys->p_mpeg2dec->ptr_forward_ref_picture =
+                                    p_sys->p_mpeg2dec->ptr_backward_ref_picture;
+                        p_sys->p_mpeg2dec->ptr_backward_ref_picture = (void *)p_pic;
+                    }
+                    mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
+                }
+            }
+            break;
+
+            case STATE_END:
+            case STATE_SLICE:
+                p_pic = NULL;
+                if( p_sys->p_info->display_fbuf
+                    && p_sys->p_info->display_fbuf->id )
+                {
+                    p_pic = (picture_t *)p_sys->p_info->display_fbuf->id;
+
+                    vout_SynchroEnd( p_sys->p_synchro,
+                                p_sys->p_info->display_picture->flags
+                                & PIC_MASK_CODING_TYPE,
+                                p_sys->b_garbage_pic );
+                    p_sys->b_garbage_pic = 0;
+
+                    if ( p_sys->p_picture_to_destroy != p_pic )
+                    {
+                        p_pic->date = vout_SynchroDate( p_sys->p_synchro );
+                    }
+                    else
+                    {
+                        p_sys->p_picture_to_destroy = NULL;
+                        p_pic->date = 0;
+                    }
+                }
+
+                if( p_sys->p_info->discard_fbuf &&
+                    p_sys->p_info->discard_fbuf->id )
+                {
+                    p_dec->pf_picture_unlink( p_dec, p_sys->p_info->discard_fbuf->id );
+                }
+                /* For still frames */
+                //if( state == STATE_END && p_pic ) p_pic->b_force = VLC_TRUE;
+
+                if( p_pic )
+                {
+#if 0
+                    /* Avoid frames with identical timestamps.
+                     * Especially needed for still frames in DVD menus. */
+                     if( p_sys->i_last_frame_pts == p_pic->date ) p_pic->date++;
+                        p_sys->i_last_frame_pts = p_pic->date;
+#endif
+                    return p_pic;
+                }
+                break;
+
+            case STATE_INVALID:
+            {
+                uint8_t *buf[3];
+                buf[0] = buf[1] = buf[2] = NULL;
+
+                msg_Warn( p_dec, "invalid picture encountered" );
+                if ( ( p_sys->p_info->current_picture == NULL ) ||
+                ( ( p_sys->p_info->current_picture->flags &
+                    PIC_MASK_CODING_TYPE) != B_CODING_TYPE ) )
+                {
+                    if( p_sys->p_synchro ) vout_SynchroReset( p_sys->p_synchro );
+                }
+                mpeg2_skip( p_sys->p_mpeg2dec, 1 );
+                p_sys->b_skip = 1;
+
+                if( p_sys->p_info->current_fbuf &&
+                    p_sys->p_info->current_fbuf->id )
+                {
+                    p_sys->b_garbage_pic = 1;
+                    p_pic = p_sys->p_info->current_fbuf->id;
+                }
+                else if( !p_sys->p_info->sequence )
+                {
+                    break;
+                }
+                else
+                {
+                    if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
+                        break;
+                    mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
+                }
+                p_sys->p_picture_to_destroy = p_pic;
+
+                memset( p_pic->p[0].p_pixels, 0,
+                        p_sys->p_info->sequence->width
+                        * p_sys->p_info->sequence->height );
+                memset( p_pic->p[1].p_pixels, 0x80,
+                        p_sys->p_info->sequence->width
+                        * p_sys->p_info->sequence->height / 4 );
+                memset( p_pic->p[2].p_pixels, 0x80,
+                        p_sys->p_info->sequence->width
+                        * p_sys->p_info->sequence->height / 4 );
+
+                if( p_sys->b_slice_i )
+                {
+                    vout_SynchroNewPicture( p_sys->p_synchro,
+                                I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
+                    vout_SynchroDecode( p_sys->p_synchro );
+                    vout_SynchroEnd( p_sys->p_synchro, I_CODING_TYPE, 0 );
+                }
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+    return NULL;
+}
+
+/*****************************************************************************
+ * CloseDecoder: libmpeg2 decoder destruction
+ *****************************************************************************/
+static void CloseDecoder( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t *)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    FILE *f_wd_dec;
+
+    if( p_sys->p_synchro ) vout_SynchroRelease( p_sys->p_synchro );
+    if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec );
+
+    f_wd_dec = fopen("/vlc/dec_pid", "w");
+    if (f_wd_dec != NULL)
+    {
+        fprintf(f_wd_dec, "0\n");
+        fflush(f_wd_dec);
+        fclose(f_wd_dec);
+    }
+    free( p_sys );
+}
+
+static double get_aspect_ratio( decoder_t *p_dec )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    double ratio;
+    double mpeg1_pel_ratio[16] = {1.0 /* forbidden */,
+        1.0, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157,
+        0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 1.0 /*reserved*/ };
+
+    if( !p_sys->p_mpeg2dec->decoder.mpeg1 )
+    {
+        /* these hardcoded values are defined on mpeg2 standard for
+        * aspect ratio. other values are reserved or forbidden.  */
+        switch( p_sys->p_mpeg2dec->decoder.aspect_ratio_information )
+        {
+            case 2:
+                ratio = 4.0/3.0;
+                break;
+            case 3:
+                ratio = 16.0/9.0;
+                break;
+            case 4:
+                ratio = 2.11/1.0;
+                break;
+            case 1:
+                default:
+                ratio = (double)p_sys->p_mpeg2dec->decoder.width/(double)p_sys->p_mpeg2dec->decoder.height;
+            break;
+        }
+    }
+    else
+    {
+        /* mpeg1 constants refer to pixel aspect ratio */
+        ratio = (double)p_sys->p_mpeg2dec->decoder.width/(double)p_sys->p_mpeg2dec->decoder.height;
+        ratio /= mpeg1_pel_ratio[p_sys->p_mpeg2dec->decoder.aspect_ratio_information];
+    }
+    return ratio;
+}
+/*****************************************************************************
+ * GetNewPicture: Get a new picture from the vout and set the buf struct
+ *****************************************************************************/
+static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
+{
+    //msg_Dbg(p_dec, "GetNewPicture Entering");
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    picture_t *p_pic;
+    static int nbpic = 0;
+
+    p_dec->fmt_out.video.i_width = p_sys->p_info->sequence->width;
+    p_dec->fmt_out.video.i_height = p_sys->p_info->sequence->height;
+    p_dec->fmt_out.video.i_aspect = p_sys->i_aspect;
+
+    if( p_sys->p_info->sequence->frame_period > 0 )
+    {
+        p_dec->fmt_out.video.i_frame_rate =
+            (uint32_t)( (uint64_t)1001000000 * 27 /
+                        p_sys->p_info->sequence->frame_period );
+        p_dec->fmt_out.video.i_frame_rate_base = 1001;
+    }
+
+    p_dec->fmt_out.i_codec =
+        ( p_sys->p_info->sequence->chroma_height <
+          p_sys->p_info->sequence->height ) ?
+        VLC_FOURCC('I','4','2','0') : VLC_FOURCC('I','4','2','2');
+
+#if 0
+    p_sys->f_wd_nb = fopen("/vlc/dec_nb", "w");
+    if (p_sys->f_wd_nb != NULL)
+    {
+//         fprintf(p_sys->f_wd_nb, "%d\n", mdate());
+        fprintf(p_sys->f_wd_nb, "%s\n", mdate());
+       fflush(p_sys->f_wd_nb); 
+    }
+#endif
+    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+
+    if( p_pic == NULL ) return NULL;
+
+    p_pic->b_progressive = p_sys->p_info->current_picture != NULL ?
+        p_sys->p_info->current_picture->flags & PIC_FLAG_PROGRESSIVE_FRAME : 1;
+    p_pic->b_top_field_first = p_sys->p_info->current_picture != NULL ?
+        p_sys->p_info->current_picture->flags & PIC_FLAG_TOP_FIELD_FIRST : 1;
+    p_pic->i_nb_fields = p_sys->p_info->current_picture != NULL ?
+        p_sys->p_info->current_picture->nb_fields : 2;
+    p_pic->format.i_frame_rate = p_dec->fmt_out.video.i_frame_rate;
+    p_pic->format.i_frame_rate_base = p_dec->fmt_out.video.i_frame_rate_base;
+
+    p_dec->pf_picture_link( p_dec, p_pic );
+
+    pp_buf[0] = p_pic->p[0].p_pixels;
+    pp_buf[1] = p_pic->p[1].p_pixels;
+    pp_buf[2] = p_pic->p[2].p_pixels;
+
+    /* let driver ensure this image has the right format */
+#if 0
+    this->driver->update_frame_format( p_pic->p_sys->p_vout, p_pic,
+                                       p_dec->fmt_out.video.i_width,
+                                       p_dec->fmt_out.video.i_height,
+                                       p_dec->fmt_out.video.i_aspect,
+                                       format, flags);
+#endif
+    mpeg2_xxmc_choose_coding( p_dec, &p_sys->p_mpeg2dec->decoder, p_pic,
+                              get_aspect_ratio(p_dec), 0 );
+    return p_pic;
+}
index 9b5c70f00e6e40fb92458b1e2e401cfd251bb1ee..d00f375a755c4cd3526f041284dd208c98e93fcf 100644 (file)
@@ -15,3 +15,10 @@ SOURCES_glx = \
        xcommon.c \
        xcommon.h \
        $(NULL)
+
+SOURCES_xvmc = \
+        xvmc.c \
+        xcommon.c \
+        xcommon.h \
+        $(NULL)
+
index 1db49ddf90de166b7ff1ec99bdda1e384277288c..1d9878b589373caa205f3934ca075a08a6b6a9a4 100644 (file)
@@ -63,7 +63,7 @@
 #   include <X11/extensions/dpms.h>
 #endif
 
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
 #   include <X11/extensions/Xv.h>
 #   include <X11/extensions/Xvlib.h>
 #endif
 #   include <X11/extensions/xf86vmode.h>
 #endif
 
+#ifdef MODULE_NAME_IS_xvmc
+#   include <X11/extensions/vldXvMC.h>
+#   include "../../codec/xvmc/accel_xvmc.h"
+#endif
+
 #include "xcommon.h"
 
 /*****************************************************************************
@@ -119,7 +124,7 @@ static void CreateCursor   ( vout_thread_t * );
 static void DestroyCursor  ( vout_thread_t * );
 static void ToggleCursor   ( vout_thread_t * );
 
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
 static int  XVideoGetPort    ( vout_thread_t *, vlc_fourcc_t, vlc_fourcc_t * );
 static void XVideoReleasePort( vout_thread_t *, int );
 #endif
@@ -129,6 +134,12 @@ static void SetPalette     ( vout_thread_t *,
                              uint16_t *, uint16_t *, uint16_t * );
 #endif
 
+#ifdef MODULE_NAME_IS_xvmc
+static void RenderVideo    ( vout_thread_t *, picture_t * );
+static int  xvmc_check_yv12( Display *display, XvPortID port );
+static void xvmc_update_XV_DOUBLE_BUFFER( vout_thread_t *p_vout );
+#endif
+
 static void TestNetWMSupport( vout_thread_t * );
 static int ConvertKey( int );
 
@@ -148,8 +159,10 @@ int E_(Activate) ( vlc_object_t *p_this )
     vout_thread_t *p_vout = (vout_thread_t *)p_this;
     char *        psz_display;
     vlc_value_t   val;
-
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvmc)
+    char *psz_value;
+#endif
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
     char *       psz_chroma;
     vlc_fourcc_t i_chroma = 0;
     vlc_bool_t   b_chroma = 0;
@@ -158,7 +171,11 @@ int E_(Activate) ( vlc_object_t *p_this )
     p_vout->pf_init = InitVideo;
     p_vout->pf_end = EndVideo;
     p_vout->pf_manage = ManageVideo;
+#ifdef MODULE_NAME_IS_xvmc
+    p_vout->pf_render = RenderVideo;
+#else
     p_vout->pf_render = NULL;
+#endif
     p_vout->pf_display = DisplayVideo;
     p_vout->pf_control = Control;
 
@@ -194,7 +211,7 @@ int E_(Activate) ( vlc_object_t *p_this )
     /* Get a screen ID matching the XOpenDisplay return value */
     p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
 
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
     psz_chroma = config_GetPsz( p_vout, "xvideo-chroma" );
     if( psz_chroma )
     {
@@ -298,6 +315,60 @@ int E_(Activate) ( vlc_object_t *p_this )
 
     TestNetWMSupport( p_vout );
 
+#ifdef MODULE_NAME_IS_xvmc
+    p_vout->p_sys->p_last_subtitle_save = NULL;
+    psz_value = config_GetPsz( p_vout, "xvmc-deinterlace-mode" );
+
+    /* Look what method was requested */
+    //var_Create( p_vout, "xvmc-deinterlace-mode", VLC_VAR_STRING );
+    //var_Change( p_vout, "xvmc-deinterlace-mode", VLC_VAR_INHERITVALUE, &val, NULL );
+    if( psz_value )
+    {
+        if( (strcmp(psz_value, "bob") == 0) ||
+            (strcmp(psz_value, "blend") == 0) )
+           p_vout->p_sys->xvmc_deinterlace_method = 2;
+        else if (strcmp(psz_value, "discard") == 0)
+           p_vout->p_sys->xvmc_deinterlace_method = 1;
+        else
+           p_vout->p_sys->xvmc_deinterlace_method = 0;
+        free(psz_value );
+    }
+    else
+        p_vout->p_sys->xvmc_deinterlace_method = 0;
+
+    /* Look what method was requested */
+    //var_Create( p_vout, "xvmc-crop-style", VLC_VAR_STRING );
+    //var_Change( p_vout, "xvmc-crop-style", VLC_VAR_INHERITVALUE, &val, NULL );
+    psz_value = config_GetPsz( p_vout, "xvmc-crop-style" );
+
+    if( psz_value )
+    {
+        if( strncmp( psz_value, "eq", 2 ) == 0 )
+           p_vout->p_sys->xvmc_crop_style = 1;
+        else if( strncmp( psz_value, "4-16", 4 ) == 0)
+           p_vout->p_sys->xvmc_crop_style = 2;
+        else if( strncmp( psz_value, "16-4", 4 ) == 0)
+           p_vout->p_sys->xvmc_crop_style = 3;
+        else
+           p_vout->p_sys->xvmc_crop_style = 0;
+        free( psz_value );
+    }
+    else
+        p_vout->p_sys->xvmc_crop_style = 0;
+
+    msg_Dbg(p_vout, "Deinterlace = %d", p_vout->p_sys->xvmc_deinterlace_method);
+    msg_Dbg(p_vout, "Crop = %d", p_vout->p_sys->xvmc_crop_style);
+
+    if( !checkXvMCCap( p_vout ) )
+    {
+        msg_Err( p_vout, "no XVMC capability found" );
+        E_(Deactivate)( p_vout );
+        return VLC_EGENERIC;
+    }
+    sub_pic.p_sys = NULL;
+    p_vout->p_sys->last_date = 0;
+#endif
+
     /* Variable to indicate if the window should be on top of others */
     /* Trigger a callback right now */
     var_Get( p_vout, "video-on-top", &val );
@@ -335,19 +406,271 @@ void E_(Deactivate) ( vlc_object_t *p_this )
     }
 #elif defined(MODULE_NAME_IS_xvideo)
     XVideoReleasePort( p_vout, p_vout->p_sys->i_xvport );
+#elif defined(MODULE_NAME_IS_xvmc)
+    if( p_vout->p_sys->xvmc_cap )
+    {
+        xvmc_context_writer_lock( &p_vout->p_sys->xvmc_lock );
+        xxmc_dispose_context( p_vout );
+        if( p_vout->p_sys->old_subpic )
+        {
+            xxmc_xvmc_free_subpicture( p_vout, p_vout->p_sys->old_subpic );
+            p_vout->p_sys->old_subpic = NULL;
+        }
+        if( p_vout->p_sys->new_subpic )
+        {
+            xxmc_xvmc_free_subpicture( p_vout, p_vout->p_sys->new_subpic );
+            p_vout->p_sys->new_subpic = NULL;
+        }
+        free( p_vout->p_sys->xvmc_cap );
+        xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
+    }
 #endif
 
     DestroyCursor( p_vout );
     EnableXScreenSaver( p_vout );
     DestroyWindow( p_vout, &p_vout->p_sys->original_window );
-
     XCloseDisplay( p_vout->p_sys->p_display );
 
     /* Destroy structure */
     vlc_mutex_destroy( &p_vout->p_sys->lock );
+#ifdef MODULE_NAME_IS_xvmc
+    free_context_lock( &p_vout->p_sys->xvmc_lock );
+#endif
+
     free( p_vout->p_sys );
 }
 
+#ifdef MODULE_NAME_IS_xvmc
+
+#define XINE_IMGFMT_YV12 (('2'<<24)|('1'<<16)|('V'<<8)|'Y')
+
+/* called xlocked */
+static int xvmc_check_yv12( Display *display, XvPortID port )
+{
+    XvImageFormatValues *formatValues;
+    int                  formats;
+    int                  i;
+
+    formatValues = XvListImageFormats( display, port, &formats );
+
+    for( i = 0; i < formats; i++ )
+    {
+        if( ( formatValues[i].id == XINE_IMGFMT_YV12 ) &&
+            ( !( strncmp( formatValues[i].guid, "YV12", 4 ) ) ) )
+        {
+            XFree (formatValues);
+            return 0;
+        }
+    }
+
+    XFree (formatValues);
+    return 1;
+}
+
+static void xvmc_sync_surface( vout_thread_t *p_vout, XvMCSurface * srf )
+{
+    XvMCSyncSurface( p_vout->p_sys->p_display, srf );
+}
+
+static void xvmc_update_XV_DOUBLE_BUFFER( vout_thread_t *p_vout )
+{
+    Atom         atom;
+    int          xv_double_buffer;
+
+    xv_double_buffer = 1;
+
+    XLockDisplay( p_vout->p_sys->p_display );
+    atom = XInternAtom( p_vout->p_sys->p_display, "XV_DOUBLE_BUFFER", False );
+#if 0
+    XvSetPortAttribute (p_vout->p_sys->p_display, p_vout->p_sys->i_xvport, atom, xv_double_buffer);
+#endif
+    XvMCSetAttribute( p_vout->p_sys->p_display, &p_vout->p_sys->context, atom, xv_double_buffer );
+    XUnlockDisplay( p_vout->p_sys->p_display );
+
+    //xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+    //    "video_out_xxmc: double buffering mode = %d\n", xv_double_buffer);
+}
+
+static void RenderVideo( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    vlc_xxmc_t *xxmc = NULL;
+
+    vlc_mutex_lock( &p_vout->p_sys->lock );
+    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+
+    xxmc = &p_pic->p_sys->xxmc_data;
+    if( (!xxmc->decoded ||
+        !xxmc_xvmc_surface_valid( p_vout, p_pic->p_sys->xvmc_surf )) )
+    {
+        vlc_mutex_unlock( &p_vout->p_sys->lock );
+        xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+        return;
+    }
+
+    vlc_mutex_lock( &p_vout->lastsubtitle_lock );
+
+    if (p_vout->p_last_subtitle != NULL)
+    {
+        if( p_vout->p_sys->p_last_subtitle_save != p_vout->p_last_subtitle )
+        {
+            p_vout->p_sys->new_subpic =
+                xxmc_xvmc_alloc_subpicture( p_vout, &p_vout->p_sys->context,
+                    p_vout->p_sys->xvmc_width,
+                    p_vout->p_sys->xvmc_height,
+                    p_vout->p_sys->xvmc_cap[p_vout->p_sys->xvmc_cur_cap].subPicType.id );
+
+            if (p_vout->p_sys->new_subpic)
+            {
+                XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+                XvMCClearSubpicture( p_vout->p_sys->p_display,
+                        p_vout->p_sys->new_subpic,
+                        0,
+                        0,
+                        p_vout->p_sys->xvmc_width,
+                        p_vout->p_sys->xvmc_height,
+                        0x00 );
+                XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+                clear_xx44_palette( &p_vout->p_sys->palette );
+
+                if( sub_pic.p_sys == NULL )
+                {
+                    sub_pic.p_sys = malloc( sizeof( picture_sys_t ) );
+                    if( sub_pic.p_sys != NULL )
+                    {
+                        sub_pic.p_sys->p_vout = p_vout;
+                        sub_pic.p_sys->xvmc_surf = NULL;
+                        sub_pic.p_sys->p_image = p_vout->p_sys->subImage;
+                    }
+                }
+                sub_pic.p_sys->p_image = p_vout->p_sys->subImage;
+                sub_pic.p->p_pixels = sub_pic.p_sys->p_image->data;
+                sub_pic.p->i_pitch = p_vout->output.i_width;
+
+                memset( p_vout->p_sys->subImage->data, 0,
+                        (p_vout->p_sys->subImage->width * p_vout->p_sys->subImage->height) );
+
+                if (p_vout->p_last_subtitle != NULL)
+                {
+                    blend_xx44( p_vout->p_sys->subImage->data,
+                                p_vout->p_last_subtitle,
+                                p_vout->p_sys->subImage->width,
+                                p_vout->p_sys->subImage->height,
+                                p_vout->p_sys->subImage->width,
+                                &p_vout->p_sys->palette,
+                                (p_vout->p_sys->subImage->id == FOURCC_IA44) );
+                }
+
+                XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+                XvMCCompositeSubpicture( p_vout->p_sys->p_display,
+                                         p_vout->p_sys->new_subpic,
+                                         p_vout->p_sys->subImage,
+                                         0, /* overlay->x */
+                                         0, /* overlay->y */
+                                         p_vout->output.i_width, /* overlay->width, */
+                                         p_vout->output.i_height, /* overlay->height */
+                                         0, /* overlay->x */
+                                         0 ); /*overlay->y */
+                XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+                if (p_vout->p_sys->old_subpic)
+                {
+                    xxmc_xvmc_free_subpicture( p_vout,
+                                               p_vout->p_sys->old_subpic);
+                    p_vout->p_sys->old_subpic = NULL;
+                }
+                if (p_vout->p_sys->new_subpic)
+                {
+                    p_vout->p_sys->old_subpic = p_vout->p_sys->new_subpic;
+                    p_vout->p_sys->new_subpic = NULL;
+                    xx44_to_xvmc_palette( &p_vout->p_sys->palette,
+                            p_vout->p_sys->xvmc_palette,
+                            0,
+                            p_vout->p_sys->old_subpic->num_palette_entries,
+                            p_vout->p_sys->old_subpic->entry_bytes,
+                            p_vout->p_sys->old_subpic->component_order );
+                    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+                    XvMCSetSubpicturePalette( p_vout->p_sys->p_display,
+                                              p_vout->p_sys->old_subpic,
+                                              p_vout->p_sys->xvmc_palette );
+                    XvMCFlushSubpicture( p_vout->p_sys->p_display,
+                                         p_vout->p_sys->old_subpic);
+                    XvMCSyncSubpicture( p_vout->p_sys->p_display,
+                                        p_vout->p_sys->old_subpic );
+                    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+                }
+
+                XVMCLOCKDISPLAY( p_vout->p_sys->p_display);
+                if (p_vout->p_sys->xvmc_backend_subpic )
+                {
+                    XvMCBlendSubpicture( p_vout->p_sys->p_display,
+                                         p_pic->p_sys->xvmc_surf,
+                                         p_vout->p_sys->old_subpic,
+                                         0,
+                                         0,
+                                         p_vout->p_sys->xvmc_width,
+                                         p_vout->p_sys->xvmc_height,
+                                         0,
+                                         0,
+                                         p_vout->p_sys->xvmc_width,
+                                         p_vout->p_sys->xvmc_height );
+                }
+                else
+                {
+                    XvMCBlendSubpicture2( p_vout->p_sys->p_display,
+                                          p_pic->p_sys->xvmc_surf,
+                                          p_pic->p_sys->xvmc_surf,
+                                          p_vout->p_sys->old_subpic,
+                                          0,
+                                          0,
+                                          p_vout->p_sys->xvmc_width,
+                                          p_vout->p_sys->xvmc_height,
+                                          0,
+                                          0,
+                                          p_vout->p_sys->xvmc_width,
+                                          p_vout->p_sys->xvmc_height );
+               }
+               XVMCUNLOCKDISPLAY(p_vout->p_sys->p_display);
+            }
+        }
+        else
+        {
+            XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+            if( p_vout->p_sys->xvmc_backend_subpic )
+            {
+                XvMCBlendSubpicture( p_vout->p_sys->p_display,
+                                     p_pic->p_sys->xvmc_surf,
+                                     p_vout->p_sys->old_subpic,
+                                     0, 0,
+                                     p_vout->p_sys->xvmc_width,
+                                     p_vout->p_sys->xvmc_height,
+                                     0, 0,
+                                     p_vout->p_sys->xvmc_width,
+                                     p_vout->p_sys->xvmc_height );
+            }
+            else
+            {
+                XvMCBlendSubpicture2( p_vout->p_sys->p_display,
+                                      p_pic->p_sys->xvmc_surf,
+                                      p_pic->p_sys->xvmc_surf,
+                                      p_vout->p_sys->old_subpic,
+                                      0, 0,
+                                      p_vout->p_sys->xvmc_width,
+                                      p_vout->p_sys->xvmc_height,
+                                      0, 0,
+                                      p_vout->p_sys->xvmc_width,
+                                      p_vout->p_sys->xvmc_height );
+            }
+            XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+        }
+    }
+    p_vout->p_sys->p_last_subtitle_save = p_vout->p_last_subtitle;
+
+    vlc_mutex_unlock( &p_vout->lastsubtitle_lock );
+    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+
+    vlc_mutex_unlock( &p_vout->p_sys->lock );
+}
+#endif
+
 /*****************************************************************************
  * InitVideo: initialize X11 video thread output method
  *****************************************************************************
@@ -361,7 +684,7 @@ static int InitVideo( vout_thread_t *p_vout )
 
     I_OUTPUTPICTURES = 0;
 
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
     /* Initialize the output structure; we already found an XVideo port,
      * and the corresponding chroma we will be using. Since we can
      * arbitrary scale, stick to the coordinates and aspect. */
@@ -506,11 +829,122 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
 
     vlc_mutex_lock( &p_vout->p_sys->lock );
 
+#ifdef MODULE_NAME_IS_xvmc
+    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+
+    vlc_xxmc_t *xxmc = &p_picture->p_sys->xxmc_data;
+    if( !xxmc->decoded ||
+        !xxmc_xvmc_surface_valid( p_vout, p_picture->p_sys->xvmc_surf ) )
+    {
+      msg_Dbg( p_vout, "DisplayVideo decoded=%d\tsurfacevalid=%d",
+               xxmc->decoded,
+               xxmc_xvmc_surface_valid( p_vout, p_picture->p_sys->xvmc_surf ) );
+      vlc_mutex_unlock( &p_vout->p_sys->lock );
+      xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+      return;
+    }
+
+    src_width = p_vout->output.i_width;
+    src_height = p_vout->output.i_height;
+
+    if( p_vout->p_sys->xvmc_crop_style == 1 )
+    {
+        src_x = 20;
+        src_y = 20;
+        src_width -= 40;
+        src_height -= 40;
+    }
+    else if( p_vout->p_sys->xvmc_crop_style == 2 )
+    {
+        src_x = 20;
+        src_y = 40;
+        src_width -= 40;
+        src_height -= 80;
+    }
+    else if( p_vout->p_sys->xvmc_crop_style == 3 )
+    {
+        src_x = 40;
+        src_y = 20;
+        src_width -= 80;
+        src_height -= 40;
+    }
+    else
+    {
+        src_x = 0;
+        src_y = 0;
+    }
+
+    if( p_vout->p_sys->xvmc_deinterlace_method > 0 )
+    {   /* BOB DEINTERLACE */
+        if( (p_picture->p_sys->nb_display == 0) ||
+            (p_vout->p_sys->xvmc_deinterlace_method == 1) )
+        {
+            first_field = (p_picture->b_top_field_first) ?
+                                XVMC_BOTTOM_FIELD : XVMC_TOP_FIELD;
+        }
+        else
+        {
+            first_field = (p_picture->b_top_field_first) ?
+                                XVMC_TOP_FIELD : XVMC_BOTTOM_FIELD;
+        }
+    }
+    else
+    {
+        first_field = XVMC_FRAME_PICTURE;
+     }
+
+    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+    XvMCFlushSurface( p_vout->p_sys->p_display, p_picture->p_sys->xvmc_surf );
+    /* XvMCSyncSurface(p_vout->p_sys->p_display, p_picture->p_sys->xvmc_surf); */
+    XvMCPutSurface( p_vout->p_sys->p_display,
+                    p_picture->p_sys->xvmc_surf,
+                    p_vout->p_sys->p_win->video_window,
+                    src_x,
+                    src_y,
+                    src_width,
+                    src_height,
+                    0 /*dest_x*/,
+                    0 /*dest_y*/,
+                    i_width,
+                    i_height,
+                    first_field);
+
+    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+    if( p_vout->p_sys->xvmc_deinterlace_method == 2 ) 
+    {   /* BOB DEINTERLACE */
+        if( p_picture->p_sys->nb_display == 0 )/* && ((t2-t1) < 15000)) */
+        {
+            mtime_t last_date = p_picture->date;
+
+            vlc_mutex_lock( &p_vout->picture_lock );
+            if( !p_vout->p_sys->last_date )
+            {
+                p_picture->date += 20000;
+            }
+            else
+            {
+                p_picture->date = ((3 * p_picture->date -
+                                    p_vout->p_sys->last_date) / 2 );
+            }
+            p_vout->p_sys->last_date = last_date;
+            p_picture->b_force = 1;
+            p_picture->p_sys->nb_display = 1;
+            vlc_mutex_unlock( &p_vout->picture_lock );
+        }
+        else
+        {
+            p_picture->p_sys->nb_display = 0;
+            p_picture->b_force = 0;
+        }
+    }
+    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+#endif
+
 #ifdef HAVE_SYS_SHM_H
     if( p_vout->p_sys->b_shm )
     {
         /* Display rendered image using shared memory extension */
-#   ifdef MODULE_NAME_IS_xvideo
+#   if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
         XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport,
                        p_vout->p_sys->p_win->video_window,
                        p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
@@ -536,7 +970,7 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
 #endif /* HAVE_SYS_SHM_H */
     {
         /* Use standard XPutImage -- this is gonna be slow ! */
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
         XvPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport,
                     p_vout->p_sys->p_win->video_window,
                     p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
@@ -577,6 +1011,10 @@ static int ManageVideo( vout_thread_t *p_vout )
 
     vlc_mutex_lock( &p_vout->p_sys->lock );
 
+#ifdef MODULE_NAME_IS_xvmc
+    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+#endif
+
     /* Handle events from the owner window */
     if( p_vout->p_sys->p_win->owner_window )
     {
@@ -948,8 +1386,11 @@ static int ManageVideo( vout_thread_t *p_vout )
         }
     }
 
-    vlc_mutex_unlock( &p_vout->p_sys->lock );
+#ifdef MODULE_NAME_IS_xvmc
+    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+#endif
 
+    vlc_mutex_unlock( &p_vout->p_sys->lock );
     return 0;
 }
 
@@ -1273,7 +1714,7 @@ static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
 {
 #ifndef MODULE_NAME_IS_glx
 
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
     int i_plane;
 #endif
 
@@ -1286,6 +1727,15 @@ static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
         return -1;
     }
 
+#ifdef MODULE_NAME_IS_xvmc
+    p_pic->p_sys->p_vout = p_vout;
+    p_pic->p_sys->xvmc_surf = NULL;
+    p_pic->p_sys->xxmc_data.decoded = 0;
+    p_pic->p_sys->xxmc_data.proc_xxmc_update_frame = xxmc_do_update_frame;
+    p_pic->p_accel_data = &p_pic->p_sys->xxmc_data;
+    p_pic->p_sys->nb_display = 0;
+#endif
+
     /* Fill in picture_t fields */
     vout_InitPicture( VLC_OBJECT(p_vout), p_pic, p_vout->output.i_chroma,
                       p_vout->output.i_width, p_vout->output.i_height,
@@ -1297,8 +1747,8 @@ static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
         /* Create image using XShm extension */
         p_pic->p_sys->p_image =
             CreateShmImage( p_vout, p_vout->p_sys->p_display,
-#   ifdef MODULE_NAME_IS_xvideo
-                            p_vout->p_sys->i_xvport, 
+#   if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
+                            p_vout->p_sys->i_xvport,
                             VLC2X11_FOURCC(p_vout->output.i_chroma),
 #   else
                             p_vout->p_sys->p_visual,
@@ -1314,7 +1764,7 @@ static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
         /* Create image without XShm extension */
         p_pic->p_sys->p_image =
             CreateImage( p_vout, p_vout->p_sys->p_display,
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
                          p_vout->p_sys->i_xvport, 
                          VLC2X11_FOURCC(p_vout->output.i_chroma),
                          p_pic->format.i_bits_per_pixel,
@@ -1342,7 +1792,7 @@ static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
 
     switch( p_vout->output.i_chroma )
     {
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
         case VLC_FOURCC('I','4','2','0'):
         case VLC_FOURCC('Y','V','1','2'):
         case VLC_FOURCC('Y','2','1','1'):
@@ -1437,6 +1887,14 @@ static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
         IMAGE_FREE( p_pic->p_sys->p_image );
     }
 
+#ifdef MODULE_NAME_IS_xvmc
+    if( p_pic->p_sys->xvmc_surf != NULL )
+    {
+        xxmc_xvmc_free_surface(p_vout , p_pic->p_sys->xvmc_surf);
+        p_pic->p_sys->xvmc_surf = NULL;
+    }
+#endif
+
     /* Do NOT use XFlush here ! */
     XSync( p_vout->p_sys->p_display, False );
 
@@ -1799,7 +2257,7 @@ static void ToggleCursor( vout_thread_t *p_vout )
     }
 }
 
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
 /*****************************************************************************
  * XVideoGetPort: get YUV12 port
  *****************************************************************************/
@@ -1851,8 +2309,11 @@ static int XVideoGetPort( vout_thread_t *p_vout,
     }
 
     i_selected_port = -1;
+#ifdef MODULE_NAME_IS_xvmc
+    i_requested_adaptor = config_GetInt( p_vout, "xvmc-adaptor" );
+#else
     i_requested_adaptor = config_GetInt( p_vout, "xvideo-adaptor" );
-
+#endif
     for( i_adaptor = 0; i_adaptor < i_num_adaptors; ++i_adaptor )
     {
         XvImageFormatValues *p_formats;
@@ -2151,6 +2612,9 @@ static IMAGE_TYPE * CreateShmImage( vout_thread_t *p_vout,
     i_height = ( i_height + 15 ) >> 4 << 4;
     i_width = ( i_width + 15 ) >> 4 << 4;
 
+    p_image = XvShmCreateImage( p_display, i_xvport, i_chroma, 0,
+                                i_width, i_height, p_shm );
+#elif defined(MODULE_NAME_IS_xvmc)
     p_image = XvShmCreateImage( p_display, i_xvport, i_chroma, 0,
                                 i_width, i_height, p_shm );
 #else
@@ -2352,7 +2816,7 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args )
     unsigned int i_width, i_height;
     unsigned int *pi_width, *pi_height;
     Drawable d = 0;
-    
+
     switch( i_query )
     {
         case VOUT_GET_SIZE:
@@ -2381,11 +2845,16 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args )
             if( !i_width ) i_width = p_vout->i_window_width;
             if( !i_height ) i_height = p_vout->i_window_height;
 
+#ifdef MODULE_NAME_IS_xvmc
+            xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+#endif
             /* Update dimensions */
             XResizeWindow( p_vout->p_sys->p_display,
                            p_vout->p_sys->p_win->base_window,
                            i_width, i_height );
-
+#ifdef MODULE_NAME_IS_xvmc
+            xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+#endif
             vlc_mutex_unlock( &p_vout->p_sys->lock );
             return VLC_SUCCESS;
 
@@ -2400,6 +2869,9 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args )
             vlc_mutex_lock( &p_vout->p_sys->lock );
             if( i_query == VOUT_REPARENT ) d = (Drawable)va_arg( args, int );
             if( !d )
+#ifdef MODULE_NAME_IS_xvmc
+            xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+#endif
             XReparentWindow( p_vout->p_sys->p_display,
                              p_vout->p_sys->original_window.base_window,
                              DefaultRootWindow( p_vout->p_sys->p_display ),
@@ -2410,6 +2882,9 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args )
                              d, 0, 0);
             XSync( p_vout->p_sys->p_display, False );
             p_vout->p_sys->original_window.owner_window = 0;
+#ifdef MODULE_NAME_IS_xvmc
+            xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+#endif
             vlc_mutex_unlock( &p_vout->p_sys->lock );
             return vout_vaControlDefault( p_vout, i_query, args );
 
@@ -2420,7 +2895,13 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args )
 
             b_arg = va_arg( args, vlc_bool_t );
             vlc_mutex_lock( &p_vout->p_sys->lock );
+#ifdef MODULE_NAME_IS_xvmc
+            xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+#endif
             WindowOnTop( p_vout, b_arg );
+#ifdef MODULE_NAME_IS_xvmc
+            xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+#endif
             vlc_mutex_unlock( &p_vout->p_sys->lock );
             return VLC_SUCCESS;
 
index 3964715a7f0557be275eb1261c95fff9a543776c..749ac7cfbef4452ef247ab9bce644323e3d13afa 100644 (file)
@@ -27,7 +27,7 @@
 /*****************************************************************************
  * Defines
  *****************************************************************************/
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
 #   define IMAGE_TYPE     XvImage
 #   define EXTRA_ARGS     int i_xvport, int i_chroma, int i_bits_per_pixel
 #   define EXTRA_ARGS_SHM int i_xvport, int i_chroma, XShmSegmentInfo *p_shm
@@ -51,6 +51,7 @@
         VLC_FOURCC( i & 0xff, (i >> 8) & 0xff, (i >> 16) & 0xff, \
                     (i >> 24) & 0xff )
 
+
 /*****************************************************************************
  * x11_window_t: X11 window descriptor
  *****************************************************************************
@@ -106,7 +107,7 @@ struct vout_sys_t
     vlc_bool_t          b_shm;               /* shared memory extension flag */
 #endif
 
-#ifdef MODULE_NAME_IS_xvideo
+#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
     int                 i_xvport;
 #else
     Colormap            colormap;               /* colormap used (8bpp only) */
@@ -149,6 +150,62 @@ struct vout_sys_t
     GLXContext          gwctx;
     GLXWindow           gwnd;
 #endif
+
+#ifdef MODULE_NAME_IS_xvmc
+    /* XvMC related stuff here */
+    xvmc_macroblocks_t  macroblocks;
+    xvmc_capabilities_t *xvmc_cap;
+    unsigned int        xvmc_num_cap;
+    unsigned int        xvmc_max_subpic_x;
+    unsigned int        xvmc_max_subpic_y;
+    int                 xvmc_eventbase;
+    int                 xvmc_errbase;
+    int                 hwSubpictures;
+    XvMCSubpicture      *old_subpic;
+    XvMCSubpicture      *new_subpic;
+    xx44_palette_t      palette;
+    int                 first_overlay;
+    float               cpu_saver;
+    int                 cpu_save_enabled;
+    int                 reverse_nvidia_palette;
+    int                 context_flags;
+
+    /*
+     * These variables are protected by the context lock:
+     */
+    unsigned            xvmc_cur_cap;
+    int                 xvmc_backend_subpic;
+    XvMCContext         context;
+    int                 contextActive;
+    xvmc_surface_handler_t xvmc_surf_handler;
+    unsigned            xvmc_mpeg;
+    unsigned            xvmc_accel;
+    unsigned            last_accel_request;
+    unsigned            xvmc_width;
+    unsigned            xvmc_height;
+    int                 have_xvmc_autopaint;
+    int                 xvmc_xoverlay_type;
+    int                 unsigned_intra;
+
+    /*
+     * Only creation and destruction of the below.
+     */
+    char                *xvmc_palette;
+    XvImage             *subImage;
+    XShmSegmentInfo     subShmInfo;
+
+    /*
+     * The mutex below is needed since XlockDisplay wasn't really enough
+     * to protect the XvMC Calls.
+     */
+    context_lock_t      xvmc_lock;
+    subpicture_t *      p_last_subtitle_save;
+    int                 xvmc_deinterlace_method;
+    int                 xvmc_crop_style;
+    mtime_t             last_date;
+
+    //alphablend_t       alphablend_extra_data;
+#endif
 };
 
 /*****************************************************************************
@@ -164,6 +221,14 @@ struct picture_sys_t
 #ifdef HAVE_SYS_SHM_H
     XShmSegmentInfo     shminfo;       /* shared memory zone information */
 #endif
+
+#ifdef MODULE_NAME_IS_xvmc
+    XvMCSurface         *xvmc_surf;
+    vlc_xxmc_t           xxmc_data;
+    int                  last_sw_format;
+    vout_thread_t        *p_vout;
+    int                  nb_display;
+#endif
 };
 
 /*****************************************************************************
@@ -174,6 +239,7 @@ struct picture_sys_t
  *****************************************************************************/
 #define MWM_HINTS_DECORATIONS   (1L << 1)
 #define PROP_MWM_HINTS_ELEMENTS 5
+
 typedef struct mwmhints_t
 {
     uint32_t flags;
@@ -181,7 +247,6 @@ typedef struct mwmhints_t
     uint32_t decorations;
     int32_t  input_mode;
     uint32_t status;
-
 } mwmhints_t;
 
 /*****************************************************************************
@@ -189,7 +254,125 @@ typedef struct mwmhints_t
  *****************************************************************************/
 #ifdef MODULE_NAME_IS_xvideo
 #   define MAX_DIRECTBUFFERS 10
+#elif defined(MODULE_NAME_IS_xvmc)
+#   define MAX_DIRECTBUFFERS 12
 #else
 #   define MAX_DIRECTBUFFERS 2
 #endif
 
+/*****************************************************************************
+ * Xxmc defines
+ *****************************************************************************/
+
+#ifdef MODULE_NAME_IS_xvmc
+
+typedef struct
+{         /* CLUT == Color LookUp Table */
+    uint8_t cb;
+    uint8_t cr;
+    uint8_t y;
+    uint8_t foo;
+} clut_t;
+
+#define XX44_PALETTE_SIZE 32
+#define OVL_PALETTE_SIZE 256
+#define XVMC_MAX_SURFACES 16
+#define XVMC_MAX_SUBPICTURES 4
+#define FOURCC_IA44 0x34344149
+#define FOURCC_AI44 0x34344941
+
+typedef struct
+{
+    unsigned size;
+    unsigned max_used;
+    uint32_t cluts[XX44_PALETTE_SIZE];
+    /* cache palette entries for both colors and clip_colors */
+    int lookup_cache[OVL_PALETTE_SIZE*2];
+} xx44_palette_t;
+
+/*
+ * Functions to handle the vlc-specific palette.
+ */
+
+void clear_xx44_palette( xx44_palette_t *p );
+
+/*
+ * Convert the xine-specific palette to something useful.
+ */
+
+void xx44_to_xvmc_palette( const xx44_palette_t *p,unsigned char *xvmc_palette,
+             unsigned first_xx44_entry, unsigned num_xx44_entries,
+             unsigned num_xvmc_components, char *xvmc_components );
+
+typedef struct
+{
+    vlc_macroblocks_t   vlc_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
+{
+    unsigned int        mpeg_flags;
+    unsigned int        accel_flags;
+    unsigned int        max_width;
+    unsigned int        max_height;
+    unsigned int        sub_max_width;
+    unsigned int        sub_max_height;
+    int                 type_id;
+    XvImageFormatValues subPicType;
+    int                 flags;
+} xvmc_capabilities_t;
+
+typedef struct xvmc_surface_handler_s
+{
+    XvMCSurface         surfaces[XVMC_MAX_SURFACES];
+    int                 surfInUse[XVMC_MAX_SURFACES];
+    int                 surfValid[XVMC_MAX_SURFACES];
+    XvMCSubpicture      subpictures[XVMC_MAX_SUBPICTURES];
+    int                 subInUse[XVMC_MAX_SUBPICTURES];
+    int                 subValid[XVMC_MAX_SUBPICTURES];
+    pthread_mutex_t     mutex;
+} xvmc_surface_handler_t;
+
+typedef struct context_lock_s
+{
+    pthread_mutex_t     mutex;
+    pthread_cond_t      cond;
+    int                 num_readers;
+} context_lock_t;
+
+#define XVMCLOCKDISPLAY(display) XLockDisplay(display);
+#define XVMCUNLOCKDISPLAY(display) XUnlockDisplay(display);
+
+void xvmc_context_reader_unlock( context_lock_t *c );
+void xvmc_context_reader_lock( context_lock_t *c );
+void xvmc_context_writer_lock( context_lock_t *c );
+void xvmc_context_writer_unlock( context_lock_t *c );
+void free_context_lock( context_lock_t *c );
+void xxmc_dispose_context( vout_thread_t *p_vout );
+
+int xxmc_xvmc_surface_valid( vout_thread_t *p_vout, XvMCSurface *surf );
+void xxmc_xvmc_free_surface( vout_thread_t *p_vout, XvMCSurface *surf );
+
+void xvmc_vld_slice( picture_t *picture );
+void xvmc_vld_frame( picture_t *picture );
+
+void xxmc_do_update_frame( picture_t *picture, uint32_t width, uint32_t height,
+        double ratio, int format, int flags);
+
+int checkXvMCCap( vout_thread_t *p_vout);
+
+XvMCSubpicture *xxmc_xvmc_alloc_subpicture( vout_thread_t *p_vout,
+        XvMCContext *context, unsigned short width, unsigned short height,
+        int xvimage_id );
+
+void xxmc_xvmc_free_subpicture( vout_thread_t *p_vout, XvMCSubpicture *sub );
+void blend_xx44( uint8_t *dst_img, subpicture_t *sub_img, int dst_width,
+        int dst_height, int dst_pitch, xx44_palette_t *palette,int ia44);
+
+#endif
diff --git a/modules/video_output/x11/xvmc.c b/modules/video_output/x11/xvmc.c
new file mode 100644 (file)
index 0000000..eed65e2
--- /dev/null
@@ -0,0 +1,1461 @@
+/*****************************************************************************
+ * xvmc.c : XVMC plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id$
+ *
+ * Authors: Shane Harper <shanegh@optusnet.com.au>
+ *          Vincent Seguin <seguin@via.ecp.fr>
+ *          Samuel Hocevar <sam@zoy.org>
+ *          David Kennedy <dkennedy@tinytoad.com>
+ *          Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>                                            /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+#include <vlc_keys.h>
+
+#ifdef HAVE_MACHINE_PARAM_H
+    /* BSD */
+#   include <machine/param.h>
+#   include <sys/types.h>                                  /* typedef ushort */
+#   include <sys/ipc.h>
+#endif
+
+#ifndef WIN32
+#   include <netinet/in.h>                            /* BSD: struct in_addr */
+#endif
+
+#ifdef HAVE_SYS_SHM_H
+#   include <sys/shm.h>                                /* shmget(), shmctl() */
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xmd.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#ifdef HAVE_SYS_SHM_H
+#   include <X11/extensions/XShm.h>
+#endif
+#ifdef DPMSINFO_IN_DPMS_H
+#   include <X11/extensions/dpms.h>
+#endif
+
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/vldXvMC.h>
+
+#include "../../codec/xxmc/accel_xvmc.h"
+#include "xcommon.h"
+#include "../../codec/spudec/spudec.h"
+#include <unistd.h>
+
+/* picture structure */
+#define TOP_FIELD 1
+#define BOTTOM_FIELD 2
+#define FRAME_PICTURE 3
+
+/* picture coding type */
+#define I_TYPE 1
+#define P_TYPE 2
+#define B_TYPE 3
+#define D_TYPE 4
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+extern int  E_(Activate)   ( vlc_object_t * );
+extern void E_(Deactivate) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define ADAPTOR_TEXT N_("XVMC adaptor number")
+#define ADAPTOR_LONGTEXT N_( \
+    "If you graphics card provides several adaptors, this option allows you " \
+    "to choose which one will be used (you shouldn't have to change this).")
+
+#define ALT_FS_TEXT N_("Alternate fullscreen method")
+#define ALT_FS_LONGTEXT N_( \
+    "There are two ways to make a fullscreen window, unfortunately each one " \
+    "has its drawbacks.\n" \
+    "1) Let the window manager handle your fullscreen window (default), but " \
+    "things like taskbars will likely show on top of the video.\n" \
+    "2) Completely bypass the window manager, but then nothing will be able " \
+    "to show on top of the video.")
+
+#define DISPLAY_TEXT N_("X11 display name")
+#define DISPLAY_LONGTEXT N_( \
+    "Specify the X11 hardware display you want to use. By default VLC will " \
+    "use the value of the DISPLAY environment variable.")
+
+#define CHROMA_TEXT N_("XVimage chroma format")
+#define CHROMA_LONGTEXT N_( \
+    "Force the XVideo renderer to use a specific chroma format instead of " \
+    "trying to improve performances by using the most efficient one.")
+
+#define SHM_TEXT N_("Use shared memory")
+#define SHM_LONGTEXT N_( \
+    "Use shared memory to communicate between VLC and the X server.")
+
+#define SCREEN_TEXT N_("Screen to be used for fullscreen mode.")
+#define SCREEN_LONGTEXT N_( \
+    "Choose the screen you want to use in fullscreen mode. For instance " \
+    "set it to 0 for first screen, 1 for the second.")
+
+#define MODE_TEXT N_("Deinterlace mode")
+#define MODE_LONGTEXT N_("You can choose the default deinterlace mode")
+
+#define CROP_TEXT N_("Crop")
+#define CROP_LONGTEXT N_("You can choose the crop style to apply.")
+
+vlc_module_begin();
+    set_shortname( "XVMC" );
+    add_string( "xvmc-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, VLC_TRUE );
+    add_integer( "xvmc-adaptor", -1, NULL, ADAPTOR_TEXT, ADAPTOR_LONGTEXT, VLC_TRUE );
+    add_bool( "xvmc-altfullscreen", 0, NULL, ALT_FS_TEXT, ALT_FS_LONGTEXT, VLC_TRUE );
+    add_string( "xvmc-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, VLC_TRUE );
+#ifdef HAVE_SYS_SHM_H
+    add_bool( "xvmc-shm", 1, NULL, SHM_TEXT, SHM_LONGTEXT, VLC_TRUE );
+#endif
+#ifdef HAVE_XINERAMA
+    add_integer ( "xvmc-xineramascreen", 0, NULL, SCREEN_TEXT, SCREEN_LONGTEXT, VLC_TRUE );
+#endif
+    add_string( "xvmc-deinterlace-mode", "bob", NULL, MODE_TEXT, MODE_LONGTEXT, VLC_FALSE );
+    add_string( "xvmc-crop-style", "eq", NULL, CROP_TEXT, CROP_LONGTEXT, VLC_FALSE );
+
+    set_description( _("XVMC extension video output") );
+    set_capability( "video output", 160 );
+    set_callbacks( E_(Activate), E_(Deactivate) );
+vlc_module_end();
+
+/* following functions are local */
+
+static unsigned accel_priority[] = {
+    VLC_XVMC_ACCEL_VLD,
+};
+
+#define NUM_ACCEL_PRIORITY (sizeof(accel_priority)/sizeof(accel_priority[0]))
+
+/*
+ * Additional thread safety, since the plugin may decide to destroy a context
+ * while it's surfaces are still active in the video-out loop.
+ * When / If XvMC libs are reasonably thread-safe, the locks can be made
+ * more efficient by allowing multiple threads in that do not destroy
+ * the context or surfaces that may be active in other threads.
+ */
+
+static void init_context_lock( context_lock_t *c )
+{
+    pthread_cond_init(&c->cond,NULL);
+    pthread_mutex_init(&c->mutex,NULL);
+    c->num_readers = 0;
+}
+
+void free_context_lock( context_lock_t *c )
+{
+    pthread_mutex_destroy(&c->mutex);
+    pthread_cond_destroy(&c->cond);
+}
+
+void xvmc_context_reader_lock( context_lock_t *c )
+{
+    pthread_mutex_lock(&c->mutex);
+    c->num_readers++;
+    pthread_mutex_unlock(&c->mutex);
+}
+
+void xvmc_context_reader_unlock( context_lock_t *c )
+{
+    pthread_mutex_lock(&c->mutex);
+    if (c->num_readers > 0) {
+        if (--(c->num_readers) == 0) {
+        pthread_cond_broadcast(&c->cond);
+        }
+    }
+    pthread_mutex_unlock(&c->mutex);
+}
+
+void xvmc_context_writer_lock( context_lock_t *c )
+{
+    pthread_mutex_lock(&c->mutex);
+    while(c->num_readers) {
+        pthread_cond_wait( &c->cond, &c->mutex );
+    }
+}
+
+void xvmc_context_writer_unlock( context_lock_t *c )
+{
+    pthread_mutex_unlock( &c->mutex );
+}
+
+void clear_xx44_palette( xx44_palette_t *p )
+{
+    register int i;
+    register uint32_t *cluts = p->cluts;
+    register int *ids = p->lookup_cache;
+
+    i= p->size;
+    while(i--)
+        *cluts++ = 0;
+    i = 2*OVL_PALETTE_SIZE;
+    while(i--)
+        *ids++ = -1;
+    p->max_used=1;
+}
+
+static void init_xx44_palette( xx44_palette_t *p, unsigned num_entries )
+{
+    p->size = (num_entries > XX44_PALETTE_SIZE) ?
+                    XX44_PALETTE_SIZE : num_entries;
+}
+
+static void dispose_xx44_palette(xx44_palette_t *p)
+{
+    /* Nothing to do */
+}
+
+static void colorToPalette( const uint32_t *icolor, unsigned char *palette_p,
+                            unsigned num_xvmc_components, char *xvmc_components )
+{
+    const clut_t *color = (const clut_t *) icolor;
+    int i;
+
+    for (i=0; i<num_xvmc_components; ++i)
+    {
+        switch(xvmc_components[i])
+        {
+            case 'V': *palette_p = color->cr; break;
+            case 'U': *palette_p = color->cb; break;
+            case 'Y':
+            default:  *palette_p = color->y; break;
+        }
+        *palette_p++;
+    }
+}
+
+
+void xx44_to_xvmc_palette( const xx44_palette_t *p,unsigned char *xvmc_palette,
+                           unsigned first_xx44_entry, unsigned num_xx44_entries,
+                           unsigned num_xvmc_components, char *xvmc_components )
+{
+    int i;
+    const uint32_t *cluts = p->cluts + first_xx44_entry;
+
+    for( i=0; i<num_xx44_entries; ++i )
+    {
+        if( (cluts - p->cluts) < p->size )
+        {
+            colorToPalette( cluts++, xvmc_palette,
+                            num_xvmc_components, xvmc_components );
+            xvmc_palette += num_xvmc_components;
+        }
+    }
+}
+
+static int xx44_paletteIndex( xx44_palette_t *p, int color, uint32_t clut )
+{
+    int i;
+    uint32_t *cluts = p->cluts;
+    int tmp;
+
+    if( (tmp = p->lookup_cache[color]) >= 0 )
+    {
+        if (cluts[tmp] == clut)
+            return tmp;
+    }
+    for (i=0; i<p->max_used; ++i)
+    {
+        if (*cluts++ == clut) {
+            p->lookup_cache[color] = i;
+            return p->lookup_cache[color];
+        }
+    }
+
+    if( p->max_used == (p->size -1) )
+    {
+        //printf("video_out: Warning! Out of xx44 palette colors!\n");
+        return 1;
+    }
+    p->cluts[p->max_used] = clut;
+    p->lookup_cache[color] = p->max_used++;
+    return p->lookup_cache[color];
+}
+
+static void memblend_xx44( uint8_t *mem, uint8_t val,
+                           size_t size, uint8_t mask )
+{
+    uint8_t masked_val = val & mask;
+
+    if (size < 0)
+        return;
+
+    while(size--)
+    {
+        if( (*mem & mask) <= masked_val )
+            *mem = val;
+        mem++;
+    }
+}
+
+void blend_xx44( uint8_t *dst_img, subpicture_t *sub_img,
+                 int dst_width, int dst_height, int dst_pitch,
+                 xx44_palette_t *palette, int ia44 )
+{
+    int src_width;
+    int src_height;
+    int mask;
+    int x_off;
+    int y_off;
+    int x, y;
+    uint8_t norm_pixel,clip_pixel;
+    uint8_t *dst_y;
+    uint8_t *dst;
+    uint8_t alphamask;
+    int clip_right;
+    int i_len, i_color;
+    uint16_t *p_source = NULL;
+    uint16_t i_colprecomp, i_destalpha;
+
+    if (!sub_img)
+        return;
+
+    src_width  = sub_img->i_width;
+    src_height = sub_img->i_height;
+    x_off = sub_img->i_x;
+    y_off = sub_img->i_y;
+    alphamask = (ia44) ? 0x0F : 0xF0;
+    p_source = (uint16_t *)sub_img->p_sys->p_data;
+    i_colprecomp, i_destalpha;
+
+    dst_y = dst_img + dst_pitch*y_off + x_off;
+
+    if( (x_off + sub_img->i_width) <= dst_width )
+        clip_right = sub_img->i_width;
+    else
+        clip_right = dst_width - x_off;
+
+    if ((src_height + y_off) > dst_height)
+        src_height = dst_height - y_off;
+
+    for (y = 0; y < src_height; y++)
+    {
+        mask = !( (y < sub_img->p_sys->i_y_start) ||
+                  (y >= sub_img->p_sys->i_y_end) );
+        dst = dst_y;
+
+        for (x = 0; x < src_width;)
+        {
+            i_color = *p_source & 0x3;
+            i_len = *p_source++ >> 2;
+
+            if( (i_len > 0) && ((x+i_len) <= src_width) )
+            {
+                /* Get the RLE part, then draw the line */
+                uint32_t color = (sub_img->p_sys->pi_yuv[i_color][0] << 16) |
+                                 (sub_img->p_sys->pi_yuv[i_color][1] << 0) |
+                                 (sub_img->p_sys->pi_yuv[i_color][2] << 8);
+
+                norm_pixel = (uint8_t)(
+                            (xx44_paletteIndex( palette,i_color, color ) << 4) |
+                            (sub_img->p_sys->pi_alpha[i_color] & 0x0F) );
+                clip_pixel = (uint8_t)(
+                            (xx44_paletteIndex( palette,i_color + OVL_PALETTE_SIZE,
+                                                sub_img->p_sys->pi_yuv[i_color][0] ) << 4) |
+                            (sub_img->p_sys->pi_alpha[i_color] & 0x0F));
+
+                if( !ia44 )
+                {
+                    norm_pixel = ((norm_pixel & 0x0F) << 4) | ((norm_pixel & 0xF0) >> 4);
+                    clip_pixel = ((clip_pixel & 0x0F) << 4) | ((clip_pixel & 0xF0) >> 4);
+                }
+                if( mask )
+                {
+                    if( x < sub_img->p_sys->i_x_start )
+                    {
+                        if( (x + i_len) <= sub_img->p_sys->i_x_start )
+                        {
+                            memblend_xx44( dst, norm_pixel, i_len, alphamask );
+                            dst += i_len;
+                        }
+                        else
+                        {
+                            memblend_xx44( dst, norm_pixel,
+                                           sub_img->p_sys->i_x_start - x,
+                                           alphamask );
+                            dst += sub_img->p_sys->i_x_start - x;
+                            i_len -= sub_img->p_sys->i_x_start - x;
+                            if( i_len <= (sub_img->p_sys->i_x_end -
+                                          sub_img->p_sys->i_x_start) )
+                            {
+                                memblend_xx44( dst, clip_pixel,
+                                               i_len, alphamask);
+                                dst += i_len;
+                            }
+                            else
+                            {
+                                memblend_xx44( dst, clip_pixel,
+                                               sub_img->p_sys->i_x_end -
+                                                    sub_img->p_sys->i_x_start,
+                                               alphamask );
+                                dst += (sub_img->p_sys->i_x_end -
+                                        sub_img->p_sys->i_x_start);
+                                i_len -= (sub_img->p_sys->i_x_end -
+                                          sub_img->p_sys->i_x_start);
+                                memblend_xx44( dst, norm_pixel,
+                                               i_len, alphamask );
+                                dst += i_len;
+                            }
+                        }
+                    }
+                    else if( x < sub_img->p_sys->i_x_end )
+                    {
+                        if( i_len <= (sub_img->p_sys->i_x_end - x) )
+                        {
+                            memblend_xx44( dst, clip_pixel, i_len, alphamask);
+                            dst += i_len;
+                        }
+                        else
+                        {
+                            memblend_xx44( dst, clip_pixel,
+                                           sub_img->p_sys->i_x_end - x,
+                                           alphamask);
+                            dst += (sub_img->p_sys->i_x_end - x);
+                            i_len -= (sub_img->p_sys->i_x_end - x);
+                            memblend_xx44( dst, norm_pixel, i_len, alphamask);
+                            dst += i_len;
+                        }
+                    }
+                    else
+                    {
+                        memblend_xx44( dst, norm_pixel, i_len, alphamask );
+                        dst += i_len;
+                    }
+                }
+                else
+                {
+                    memblend_xx44( dst, norm_pixel, i_len, alphamask );
+                    dst += i_len;
+                }
+            }
+            else
+            {
+                return;
+            }
+            x += i_len;
+        }
+        dst_y += dst_pitch;
+    }
+}
+
+int xxmc_xvmc_surface_valid( vout_thread_t *p_vout, XvMCSurface *surf )
+{
+    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
+    unsigned int index = surf - handler->surfaces;
+    int ret;
+
+    if (index >= XVMC_MAX_SURFACES)
+        return 0;
+    pthread_mutex_lock(&handler->mutex);
+    ret = handler->surfValid[index];
+    pthread_mutex_unlock(&handler->mutex);
+    return ret;
+}
+
+static void xxmc_xvmc_dump_subpictures( vout_thread_t *p_vout )
+{
+    int i;
+    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
+
+    for( i=0; i < XVMC_MAX_SUBPICTURES; ++i )
+    {
+        msg_Dbg( p_vout, "handler in use %d, valid %d",
+                         handler->subInUse[i],
+                         handler->subValid[i]);
+    }
+}
+
+XvMCSubpicture *xxmc_xvmc_alloc_subpicture( vout_thread_t *p_vout,
+                    XvMCContext *context, unsigned short width,
+                    unsigned short height, int xvimage_id )
+{
+    int i;
+    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
+    int status;
+
+    pthread_mutex_lock(&handler->mutex);
+    /* xxmc_xvmc_dump_subpictures(p_vout); */
+    for( i=0; i<XVMC_MAX_SUBPICTURES; ++i )
+    {
+        if( handler->subValid[i] && !handler->subInUse[i] )
+        {
+            XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+            if( XvMCGetSubpictureStatus( p_vout->p_sys->p_display,
+                                         handler->subpictures + i,
+                                         &status ) )
+            {
+                XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+                continue;
+            }
+            XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+            if( status & XVMC_DISPLAYING )
+                continue;
+            handler->subInUse[i] = 1;
+            /* xxmc_xvmc_dump_subpictures(p_vout); */
+            pthread_mutex_unlock(&handler->mutex);
+            return (handler->subpictures + i);
+        }
+    }
+    for (i=0; i<XVMC_MAX_SUBPICTURES; ++i)
+    {
+        if( !handler->subInUse[i] )
+        {
+            XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+            if( Success != XvMCCreateSubpicture( p_vout->p_sys->p_display,
+                                                 context,
+                                                 handler->subpictures + i,
+                                                 width, height, xvimage_id ) )
+            {
+                XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+                pthread_mutex_unlock( &handler->mutex );
+                return NULL;
+            }
+            XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+            msg_Dbg( p_vout, "video_out_xxmc: created subpicture %d\n", i );
+            handler->subInUse[i] = 1;
+            handler->subValid[i] = 1;
+            pthread_mutex_unlock( &handler->mutex );
+            return (handler->subpictures + i);
+        }
+    }
+    pthread_mutex_unlock( &handler->mutex );
+    return NULL;
+}
+
+void xxmc_xvmc_free_subpicture( vout_thread_t *p_vout, XvMCSubpicture *sub )
+{
+    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
+    unsigned int index = sub - handler->subpictures;
+
+    if( index >= XVMC_MAX_SUBPICTURES )
+        return;
+
+    pthread_mutex_lock( &handler->mutex );
+    handler->subInUse[index] = 0;
+    /* xxmc_xvmc_dump_subpictures(p_vout); */
+    pthread_mutex_unlock( &handler->mutex );
+}
+
+static void xxmc_xvmc_surface_handler_construct( vout_thread_t *p_vout )
+{
+    int i;
+    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
+    
+    pthread_mutex_init( &handler->mutex, NULL );
+    for( i=0; i<XVMC_MAX_SURFACES; ++i )
+    {
+        handler->surfInUse[i] = 0;
+        handler->surfValid[i] = 0;
+    }
+    for( i=0; i<XVMC_MAX_SUBPICTURES; ++i )
+    {
+        handler->subInUse[i] = 0;
+        handler->subValid[i] = 0;
+    }
+}
+
+static void xxmc_xvmc_dump_surfaces( vout_thread_t *p_vout )
+{
+    int i;
+    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
+
+    for (i=0; i<XVMC_MAX_SURFACES; ++i)
+    {
+        msg_Dbg(p_vout, "surfaces in use %d, valid %d;",
+                        handler->surfInUse[i],
+                        handler->surfValid[i]);
+    }
+}
+
+void xxmc_xvmc_free_surface( vout_thread_t *p_vout, XvMCSurface *surf )
+{
+    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
+    unsigned int index = 0;
+
+    index = (surf - handler->surfaces);
+
+    if (index < XVMC_MAX_SURFACES)
+    {
+        pthread_mutex_lock(&handler->mutex);
+        msg_Dbg( p_vout,"free surface %d",index );
+        handler->surfInUse[index]--;
+        xxmc_xvmc_dump_surfaces(p_vout);
+        pthread_mutex_unlock(&handler->mutex);
+    }
+}
+
+int checkXvMCCap( vout_thread_t *p_vout )
+{
+    int i_xvport = 0;
+    int numSurf = 0;
+    int numSub = 0;
+    int i,j;
+    XvMCSurfaceInfo     *surfaceInfo =NULL;
+    XvMCSurfaceInfo     *curInfo = NULL;
+    XvMCContext         c;
+    xvmc_capabilities_t *curCap = NULL;
+    XvImageFormatValues *formatValues = NULL;
+
+    i_xvport = p_vout->p_sys->i_xvport;
+    p_vout->p_sys->xvmc_cap = 0;
+
+    init_context_lock( &p_vout->p_sys->xvmc_lock );
+    xvmc_context_writer_lock( &p_vout->p_sys->xvmc_lock );
+
+    p_vout->p_sys->old_subpic = NULL;
+    p_vout->p_sys->new_subpic = NULL;
+    p_vout->p_sys->contextActive = 0;
+    p_vout->p_sys->subImage = NULL;
+    p_vout->p_sys->hwSubpictures = 0;
+    p_vout->p_sys->xvmc_palette = NULL;
+
+    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+
+    if( !XvMCQueryExtension( p_vout->p_sys->p_display,
+                             &p_vout->p_sys->xvmc_eventbase,
+                             &p_vout->p_sys->xvmc_errbase ) )
+    {
+        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+        xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
+        return VLC_EGENERIC;
+    }
+    msg_Dbg( p_vout,"XvMC extension found" );
+
+    surfaceInfo = XvMCListSurfaceTypes(p_vout->p_sys->p_display, i_xvport, &numSurf);
+    if( !surfaceInfo )
+    {
+        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+        xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
+        return VLC_EGENERIC;
+    }
+
+    p_vout->p_sys->xvmc_cap =
+            (xvmc_capabilities_t *) malloc( numSurf *
+                                            sizeof(xvmc_capabilities_t) );
+    if( !p_vout->p_sys->xvmc_cap )
+    {
+        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+        xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
+        return VLC_EGENERIC;
+    }
+
+    p_vout->p_sys->xvmc_num_cap = numSurf;
+    curInfo = surfaceInfo;
+    curCap = p_vout->p_sys->xvmc_cap;
+
+    msg_Dbg( p_vout,"found %d XvMC surface types", numSurf );
+
+    for( i=0; i< numSurf; ++i )
+    {
+        curCap->mpeg_flags = 0;
+        curCap->accel_flags = 0;
+        if( curInfo->chroma_format == XVMC_CHROMA_FORMAT_420 )
+        {
+            curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_1) ?
+                                                VLC_XVMC_MPEG_1 : 0);
+            curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_2) ?
+                                                VLC_XVMC_MPEG_2 : 0);
+            curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_4) ?
+                                                VLC_XVMC_MPEG_4 : 0);
+            curCap->accel_flags |= ((curInfo->mc_type & XVMC_VLD) ?
+                                              VLC_XVMC_ACCEL_VLD : 0);
+            curCap->accel_flags |= ((curInfo->mc_type & XVMC_IDCT) ?
+                                             VLC_XVMC_ACCEL_IDCT : 0);
+            curCap->accel_flags |= ((curInfo->mc_type & (XVMC_VLD | XVMC_IDCT)) ?
+                                            0 : VLC_XVMC_ACCEL_MOCOMP);
+            curCap->max_width = curInfo->max_width;
+            curCap->max_height = curInfo->max_height;
+            curCap->sub_max_width = curInfo->subpicture_max_width;
+            curCap->sub_max_height = curInfo->subpicture_max_height;
+            curCap->flags = curInfo->flags;
+
+            msg_Dbg (p_vout, "surface type %d: Max size: %d %d.",
+                            i, curCap->max_width, curCap->max_height);
+            msg_Dbg (p_vout, "surface subtype %d: Max subpic size: %d %d.",
+                            i, curCap->sub_max_width, curCap->sub_max_height);
+
+            curCap->type_id = curInfo->surface_type_id;
+            formatValues = XvMCListSubpictureTypes( p_vout->p_sys->p_display,
+                                                    i_xvport,
+                                                    curCap->type_id,
+                                                    &numSub );
+            curCap->subPicType.id = 0;
+            if( formatValues )
+            {
+                msg_Dbg( p_vout, "surface type %d: found %d XvMC subpicture types",
+                                i, numSub);
+                for( j = 0; j<numSub; ++j )
+                {
+                    if( formatValues[j].id == FOURCC_IA44 )
+                    {
+                        curCap->subPicType = formatValues[j];
+                        msg_Dbg( p_vout,
+                                    "surface type %d: detected and using "
+                                    "IA44 subpicture type.", i );
+                        /* Prefer IA44 */
+                        break;
+                    }
+                    else if( formatValues[j].id == FOURCC_AI44 )
+                    {
+                        curCap->subPicType = formatValues[j];
+                        msg_Dbg( p_vout,
+                                 "surface type %d: detected AI44 "
+                                 "subpicture type.", i );
+                    }
+                }
+            }
+            XFree(formatValues);
+            curInfo++;
+            curCap++;
+        }
+    }
+    XFree(surfaceInfo);
+
+    /*
+    * Try to create a direct rendering context. This will fail if we are not
+    * on the displaying computer or an indirect context is not available.
+    */
+    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+    curCap = p_vout->p_sys->xvmc_cap;
+    if( Success == XvMCCreateContext( p_vout->p_sys->p_display, i_xvport,
+                                      curCap->type_id,
+                                      curCap->max_width,
+                                      curCap->max_height,
+                                      XVMC_DIRECT, &c) )
+    {
+            p_vout->p_sys->context_flags = XVMC_DIRECT;
+    }
+    else if( Success == XvMCCreateContext( p_vout->p_sys->p_display, i_xvport,
+                                           curCap->type_id,
+                                           curCap->max_width,
+                                           curCap->max_height,
+                                           0, &c) )
+    {
+        p_vout->p_sys->context_flags = 0;
+    }
+    else
+    {
+        if( p_vout->p_sys->xvmc_cap )
+            free( p_vout->p_sys->xvmc_cap );
+        p_vout->p_sys->xvmc_cap = NULL;
+        msg_Err( p_vout, "use of direct XvMC context on a remote display failed"
+                         " falling back to XV." );
+        xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
+        return VLC_SUCCESS;
+    }
+    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );  
+    XvMCDestroyContext( p_vout->p_sys->p_display, &c );
+    xxmc_xvmc_surface_handler_construct(p_vout );
+    /*  p_vout->p_sys->capabilities |= VO_CAP_XXMC; */
+    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+    init_xx44_palette( &p_vout->p_sys->palette , 0 );
+    p_vout->p_sys->last_accel_request = 0xFFFFFFFF;
+    xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
+    return VLC_SUCCESS;
+}
+
+static int xxmc_setup_subpictures( vout_thread_t *p_vout,
+        unsigned int width, unsigned int height )
+{
+    xvmc_capabilities_t *curCap = NULL;
+    XvMCSubpicture *sp = NULL;
+
+    if( p_vout->p_sys->contextActive )
+    {
+        curCap = p_vout->p_sys->xvmc_cap + p_vout->p_sys->xvmc_cur_cap;
+
+        if( (width > curCap->sub_max_width) ||
+            (height > curCap->sub_max_height) )
+            return VLC_EGENERIC;
+
+        if( (p_vout->p_sys->xvmc_backend_subpic =
+                (curCap->flags & XVMC_BACKEND_SUBPICTURE)) )
+            msg_Dbg( p_vout, "using backend subpictures." );
+
+        if (!p_vout->p_sys->subImage)
+        {
+            XLockDisplay( p_vout->p_sys->p_display );
+            msg_Dbg(p_vout, "xxmc_setup_subpictures");
+#ifdef HAVE_SYS_SHM_H
+            if( p_vout->p_sys->b_shm )
+            {
+                /* Create image using XShm extension */
+                p_vout->p_sys->subImage = CreateShmImage( p_vout,
+                                            p_vout->p_sys->p_display,
+                                            p_vout->p_sys->i_xvport,
+                                            curCap->subPicType.id,
+                                            /* VLC2X11_FOURCC( p_vout->output. i_chroma ), */
+                                            &p_vout->p_sys->subShmInfo,
+                                            p_vout->output.i_width,
+                                            p_vout->output.i_height );
+            }
+#endif /* HAVE_SYS_SHM_H */
+            XUnlockDisplay( p_vout->p_sys->p_display );
+            if( !p_vout->p_sys->subImage )
+            {
+                msg_Dbg(p_vout, "failed allocating XvImage for supbictures" );
+                return VLC_EGENERIC;
+            }
+        }
+
+        sp = xxmc_xvmc_alloc_subpicture( p_vout, &p_vout->p_sys->context,
+                                         width, height,
+                                         curCap->subPicType.id );
+        if( !sp == NULL )
+            return VLC_EGENERIC;
+
+        init_xx44_palette( &p_vout->p_sys->palette, sp->num_palette_entries );
+        p_vout->p_sys->xvmc_palette = (char *) malloc( sp->num_palette_entries
+                                                       * sp->entry_bytes );
+        xxmc_xvmc_free_subpicture( p_vout, sp);
+        if( !p_vout->p_sys->xvmc_pallette )
+            return VLC_EGENERIC;
+        p_vout->p_sys->hwSubpictures = 1;
+    }
+    return VLC_SUCCESS;
+}
+
+static void xvmc_check_colorkey_properties( vout_thread_t *p_vout )
+{
+    int num,i;
+    XvAttribute *xvmc_attributes = NULL;
+    Atom ap;
+
+    /*
+    * Determine if the context is of "Overlay" type. If so,
+    * check whether we can autopaint.
+    */
+    p_vout->p_sys->have_xvmc_autopaint = 0;
+    if( p_vout->p_sys->context_flags & XVMC_OVERLAID_SURFACE )
+    {
+        msg_Dbg( p_vout, "check colorkey properties" );
+        XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+        xvmc_attributes = XvMCQueryAttributes( p_vout->p_sys->p_display,
+                                               &p_vout->p_sys->context,
+                                               &num );
+        if( xvmc_attributes )
+        {
+            for( i = 0; i < num; ++i )
+            {
+                if( strncmp( "XV_AUTOPAINT_COLORKEY",
+                             xvmc_attributes[i].name,
+                             21) == 0)
+                {
+                    ap = XInternAtom( p_vout->p_sys->p_display,
+                                      "XV_AUTOPAINT_COLORKEY",
+                                       False );
+                    XvMCSetAttribute( p_vout->p_sys->p_display,
+                                      &p_vout->p_sys->context,
+                                      ap,
+                                      1 ); /* p_vout->p_sys->props[VO_PROP_AUTOPAINT_COLORKEY].value */
+                    p_vout->p_sys->have_xvmc_autopaint = 1;
+                    msg_Dbg( p_vout, "has xvmc autopaint" );
+                }
+            }
+        }
+        XFree( xvmc_attributes );
+        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+        /* p_vout->p_sys->xvmc_xoverlay_type = X11OSD_COLORKEY; */
+    }
+#if 0
+    else
+    {
+        p_vout->p_sys->xvmc_xoverlay_type = X11OSD_SHAPED;
+    }
+#endif
+}
+
+static void xxmc_xvmc_destroy_surfaces( vout_thread_t *p_vout )
+{
+    int i;
+    xvmc_surface_handler_t *handler = NULL;
+
+    handler = &p_vout->p_sys->xvmc_surf_handler;
+
+    pthread_mutex_lock( &handler->mutex );
+    for( i = 0; i < XVMC_MAX_SURFACES; ++i )
+    {
+        XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+        if( handler->surfValid[i] )
+        {
+            XvMCFlushSurface( p_vout->p_sys->p_display , handler->surfaces+i);
+            XvMCSyncSurface( p_vout->p_sys->p_display, handler->surfaces+i );
+            XvMCHideSurface( p_vout->p_sys->p_display, handler->surfaces+i );
+            XvMCDestroySurface( p_vout->p_sys->p_display, handler->surfaces+i );
+        }
+        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+        handler->surfValid[i] = 0;
+    }
+    pthread_mutex_unlock( &handler->mutex );
+}
+
+static void xxmc_xvmc_destroy_subpictures( vout_thread_t *p_vout )
+{
+    int i;
+    xvmc_surface_handler_t *handler = NULL;
+
+    handler = &p_vout->p_sys->xvmc_surf_handler;
+
+    pthread_mutex_lock( &handler->mutex );
+    for( i = 0; i < XVMC_MAX_SUBPICTURES; ++i )
+    {
+        XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+        if( handler->subValid[i] )
+        {
+            XvMCFlushSubpicture( p_vout->p_sys->p_display , handler->subpictures+i);
+            XvMCSyncSubpicture( p_vout->p_sys->p_display, handler->subpictures+i );
+            XvMCDestroySubpicture( p_vout->p_sys->p_display, handler->subpictures+i );
+        }
+        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+        handler->subValid[i] = 0;
+    }
+    pthread_mutex_unlock( &handler->mutex );
+}
+
+static XvMCSurface *xxmc_xvmc_alloc_surface( vout_thread_t *p_vout,
+        XvMCContext *context )
+{
+    xvmc_surface_handler_t *handler = NULL;
+    int i;
+
+    handler = &p_vout->p_sys->xvmc_surf_handler;
+
+    pthread_mutex_lock( &handler->mutex );
+    xxmc_xvmc_dump_surfaces( p_vout );
+    for( i = 0; i < XVMC_MAX_SURFACES; ++i )
+    {
+        if( handler->surfValid[i] && !handler->surfInUse[i] )
+        {
+            handler->surfInUse[i] = 1;
+            xxmc_xvmc_dump_surfaces( p_vout );
+            pthread_mutex_unlock( &handler->mutex );
+            return (handler->surfaces + i);
+        }
+    }
+    for( i = 0; i < XVMC_MAX_SURFACES; ++i )
+    {
+        if( !handler->surfInUse[i] )
+        {
+            XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+            if( Success != XvMCCreateSurface( p_vout->p_sys->p_display
+                                              context,
+                                              handler->surfaces + i) )
+            {
+                XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+                pthread_mutex_unlock( &handler->mutex );
+                return NULL;
+            }
+            XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+
+            msg_Dbg( p_vout, "created surface %d", i );
+            handler->surfInUse[i] = 1;
+            handler->surfValid[i] = 1;
+            pthread_mutex_unlock( &handler->mutex );
+            return (handler->surfaces + i);
+        }
+    }
+    pthread_mutex_unlock( &handler->mutex );
+    return NULL;
+}
+
+void xxmc_dispose_context( vout_thread_t *p_vout )
+{
+    if( p_vout->p_sys->contextActive )
+    {
+        if( p_vout->p_sys->xvmc_accel &
+            (VLC_XVMC_ACCEL_MOCOMP | VLC_XVMC_ACCEL_IDCT) )
+        {
+            xvmc_macroblocks_t *macroblocks = NULL;
+
+            macroblocks = &p_vout->p_sys->macroblocks;
+            XvMCDestroyMacroBlocks( p_vout->p_sys->p_display,
+                                    &macroblocks->macro_blocks );
+            XvMCDestroyBlocks( p_vout->p_sys->p_display,
+                               &macroblocks->blocks );
+        }
+
+        msg_Dbg( p_vout, "freeing up XvMC surfaces and subpictures" );
+        if( p_vout->p_sys->xvmc_palette )
+            free( p_vout->p_sys->xvmc_palette );
+        dispose_xx44_palette( &p_vout->p_sys->palette );
+        xxmc_xvmc_destroy_subpictures( p_vout );
+        xxmc_xvmc_destroy_surfaces( p_vout );
+
+        msg_Dbg(p_vout, "freeing up XvMC Context.");
+        XLockDisplay( p_vout->p_sys->p_display );
+        if( p_vout->p_sys->subImage )
+        {
+            XFree( p_vout->p_sys->subImage );
+            p_vout->p_sys->subImage = NULL;
+        }
+        p_vout->p_sys->subImage = NULL;
+        XUnlockDisplay( p_vout->p_sys->p_display );
+        XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+        XvMCDestroyContext( p_vout->p_sys->p_display,
+                            &p_vout->p_sys->context );
+        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+        p_vout->p_sys->contextActive = 0;
+        p_vout->p_sys->hwSubpictures = 0;
+        p_vout->p_sys->xvmc_accel = 0;
+    }
+}
+
+static int xxmc_find_context( vout_thread_t *p_vout, vlc_xxmc_t *xxmc,
+        unsigned int width, unsigned int height )
+{
+    int i, k;
+    vlc_bool_t found = VLC_FALSE;
+    xvmc_capabilities_t *curCap = NULL;
+    unsigned int request_mpeg_flags, request_accel_flags;
+
+    request_mpeg_flags = xxmc->mpeg;
+    for( k = 0; k < NUM_ACCEL_PRIORITY; ++k )
+    {
+        request_accel_flags = xxmc->acceleration & accel_priority[k];
+        if( !request_accel_flags )
+            continue;
+
+        curCap = p_vout->p_sys->xvmc_cap;
+        for( i =0; i < p_vout->p_sys->xvmc_num_cap; ++i )
+        {
+            msg_Dbg( p_vout, "surface type %d, capabilities 0x%8x 0x%8x",
+                             i,
+                             curCap->mpeg_flags,
+                             curCap->accel_flags );
+            msg_Dbg( p_vout, "fequests: 0x%8x 0x%8x",
+                             request_mpeg_flags,
+                             request_accel_flags );
+            if( ( (curCap->mpeg_flags & request_mpeg_flags) == request_mpeg_flags) &&
+                  (curCap->accel_flags & request_accel_flags) &&
+                  (width <= curCap->max_width) &&
+                  (height <= curCap->max_height) )
+            {
+                found = VLC_TRUE;
+                break;
+            }
+            curCap++;
+        }
+        if( found )
+        {
+            p_vout->p_sys->xvmc_cur_cap = i;
+            break;
+        }
+    }
+    if( found )
+    {
+        p_vout->p_sys->xvmc_accel = request_accel_flags;
+        p_vout->p_sys->unsigned_intra = (curCap->flags & XVMC_INTRA_UNSIGNED);
+        return 1;
+    }
+    p_vout->p_sys->xvmc_accel = 0;
+    return 0;
+}
+
+static int xxmc_create_context( vout_thread_t *p_vout,
+        unsigned int width, unsigned int height )
+{
+    xvmc_capabilities_t *curCap = NULL;
+
+    curCap = p_vout->p_sys->xvmc_cap + p_vout->p_sys->xvmc_cur_cap;
+
+    msg_Dbg( p_vout, "creating new XvMC context %d", curCap->type_id );
+
+    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+    if( Success == XvMCCreateContext( p_vout->p_sys->p_display,
+                                      p_vout->p_sys->i_xvport,
+                                      curCap->type_id,
+                                      width,
+                                      height,
+                                      p_vout->p_sys->context_flags,
+                                      &p_vout->p_sys->context ) )
+    {
+        p_vout->p_sys->xvmc_mpeg = curCap->mpeg_flags;
+        p_vout->p_sys->xvmc_width = width;
+        p_vout->p_sys->xvmc_height = height;
+        p_vout->p_sys->contextActive = 1;
+    }
+    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+    return p_vout->p_sys->contextActive;
+}
+
+static void xvmc_flushsync(picture_t *picture)
+{
+    vout_thread_t *p_vout = picture->p_sys->p_vout;
+
+    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+
+    if( ! xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf)) {
+        msg_Dbg(p_vout, "xvmc_flushsync 1 : %d", picture->p_sys->xxmc_data.result );
+        picture->p_sys->xxmc_data.result = 128;
+        xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+        return;
+    }
+
+    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+    picture->p_sys->xxmc_data.result =
+            XvMCFlushSurface( p_vout->p_sys->p_display,
+                              picture->p_sys->xvmc_surf );
+    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+}
+
+static void xvmc_flush(picture_t *picture)
+{
+    vout_thread_t *p_vout = picture->p_sys->p_vout;
+
+    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+
+    if ( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
+    {
+        msg_Dbg(p_vout, "xvmc flush 1 : %d", picture->p_sys->xxmc_data.result );
+        picture->p_sys->xxmc_data.result = 128;
+        xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+        return;
+    }
+
+    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+    picture->p_sys->xxmc_data.result =
+            XvMCFlushSurface( p_vout->p_sys->p_display,
+                              picture->p_sys->xvmc_surf );
+    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+}
+
+static int xxmc_frame_updates( vout_thread_t *p_vout, picture_t *picture )
+{
+    vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
+
+    /*
+     * If we have changed context since the surface was updated, xvmc_surf
+     * is either NULL or invalid. If it is invalid. Set it to NULL.
+     * Also if there are other users of this surface, deregister our use of
+     * it and later try to allocate a new, fresh one.
+     */
+
+    if( picture->p_sys->xvmc_surf )
+    {
+        if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
+        {
+            xxmc_xvmc_free_surface( p_vout , picture->p_sys->xvmc_surf );
+            picture->p_sys->xvmc_surf = NULL;
+        }
+    }
+#if 0
+    if( picture->p_sys->p_image )
+    {
+        memset( picture->p_sys->p_image->data, 0,
+                picture->p_sys->p_image->width
+                    * picture->p_sys->p_image->height );
+    }
+#endif
+    /*
+     * If it is NULL create a new surface.
+     */
+    if( !picture->p_sys->xvmc_surf )
+    {
+        picture->p_sys->xvmc_surf = xxmc_xvmc_alloc_surface( p_vout,
+                                                    &p_vout->p_sys->context );
+        if( !picture->p_sys->xvmc_surf )
+        {
+            msg_Err( p_vout, "accelerated surface allocation failed.\n"
+                            " You are probably out of framebuffer memory.\n"
+                            " Falling back to software decoding." );
+            p_vout->p_sys->xvmc_accel = 0;
+            xxmc_dispose_context( p_vout );
+            return VLC_EGENERIC;
+        }
+    }
+    xxmc->acceleration = p_vout->p_sys->xvmc_accel;
+
+    xxmc->proc_xxmc_flush = xvmc_flush;
+    xxmc->proc_xxmc_flushsync = xvmc_flushsync;
+    xxmc->xvmc.proc_macro_block = NULL;
+#if 0
+    frame->vo_frame.proc_duplicate_frame_data = xxmc_duplicate_frame_data;
+#endif
+    xxmc->proc_xxmc_begin = xvmc_vld_frame;
+    xxmc->proc_xxmc_slice = xvmc_vld_slice;
+    return VLC_SUCCESS;
+}
+
+static int xxmc_xvmc_update_context( vout_thread_t *p_vout,
+    picture_t *picture, uint32_t width, uint32_t height )
+{
+    vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
+
+    /*
+     * Are we at all capable of doing XvMC ?
+     */
+    if( p_vout->p_sys->xvmc_cap == 0 )
+        return VLC_EGENERIC;
+
+    msg_Dbg( p_vout, "new format: need to change XvMC context. "
+                     "width: %d height: %d mpeg: %d acceleration: %d",
+                     width, height,
+                     xxmc->mpeg, xxmc->acceleration );
+
+    if( picture->p_sys->xvmc_surf )
+        xxmc_xvmc_free_surface( p_vout , picture->p_sys->xvmc_surf );
+    picture->p_sys->xvmc_surf = NULL;
+
+    xxmc_dispose_context( p_vout );
+
+    if( xxmc_find_context( p_vout, xxmc, width, height ) )
+    {
+        xxmc_create_context( p_vout, width, height);
+        xvmc_check_colorkey_properties( p_vout );
+        xxmc_setup_subpictures(p_vout, width, height);
+    }
+
+    if( !p_vout->p_sys->contextActive )
+    {
+        msg_Dbg( p_vout, "using software decoding for this stream" );
+        p_vout->p_sys->xvmc_accel = 0;
+    }
+    else
+    {
+        msg_Dbg(p_vout, "using hardware decoding for this stream." );
+    }
+
+    p_vout->p_sys->xvmc_mpeg = xxmc->mpeg;
+    p_vout->p_sys->xvmc_width = width;
+    p_vout->p_sys->xvmc_height = height;
+    return p_vout->p_sys->contextActive;
+}
+
+
+void xxmc_do_update_frame( picture_t *picture, uint32_t width, uint32_t height,
+        double ratio, int format, int flags)
+{
+    vout_thread_t *p_vout = picture->p_sys->p_vout;
+    int indextime = 0;
+    int status = 0;
+
+    picture->p_sys->xxmc_data.decoded = 0;
+    picture->p_sys->nb_display = 0;
+    picture->b_force = 0;
+    vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
+
+    xvmc_context_writer_lock( &p_vout->p_sys->xvmc_lock);
+    if( (p_vout->p_sys->last_accel_request != xxmc->acceleration) ||
+        (p_vout->p_sys->xvmc_mpeg != xxmc->mpeg) ||
+        (p_vout->p_sys->xvmc_width != width) ||
+        (p_vout->p_sys->xvmc_height != height))
+    {
+        p_vout->p_sys->last_accel_request = xxmc->acceleration;
+        xxmc_xvmc_update_context( p_vout, picture, width, height );
+    }
+
+    if( p_vout->p_sys->contextActive )
+        xxmc_frame_updates( p_vout, picture );
+
+    if( !p_vout->p_sys->contextActive )
+    {
+        xxmc->acceleration = 0;
+        xxmc->xvmc.macroblocks = 0;
+    }
+    else
+    {
+        picture->format.i_chroma = format;
+    }
+    xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock);
+
+    XvMCGetSurfaceStatus( p_vout->p_sys->p_display,
+                          picture->p_sys->xvmc_surf,
+                          &status );
+    /* Wait a little till frame is being displayed */
+    while( status & XVMC_DISPLAYING )
+    {
+        msleep(1);
+
+        XvMCGetSurfaceStatus( p_vout->p_sys->p_display,
+                              picture->p_sys->xvmc_surf,
+                              &status );
+
+        indextime++;
+        if( indextime > 4 )
+            break;
+    }
+}
+
+#if 0
+/* called xlocked */
+static void dispose_ximage( vout_thread_t *p_vout, XShmSegmentInfo *shminfo,
+                XvImage *myimage )
+{
+# ifdef HAVE_SYS_SHM_H
+    if( p_vout->p_sys->b_shm )
+    {
+        XShmDetach( p_vout->p_sys->p_display, shminfo );
+        XFree( myimage );
+        shmdt( shminfo->shmaddr );
+        if( shminfo->shmid >= 0 )
+        {
+            shmctl( shminfo->shmid, IPC_RMID, 0 );
+            shminfo->shmid = -1;
+        }
+    }
+    else
+#endif
+    {
+        if( myimage->data )
+            free(myimage->data);
+        XFree (myimage);
+    }
+}
+#endif
+
+void xvmc_vld_frame( picture_t *picture )
+{
+    vout_sys_t *p_sys = picture->p_sys;
+    vout_thread_t *p_vout = p_sys->p_vout;
+    vlc_vld_frame_t *vft = &(p_sys->xxmc_data.vld_frame);
+    picture_t *ff = (picture_t *) vft->forward_reference_picture;
+    picture_t *bf = (picture_t *) vft->backward_reference_picture;
+    XvMCMpegControl ctl;
+    XvMCSurface *fs=0, *bs=0;
+    XvMCQMatrix qmx;
+
+    ctl.BHMV_range = vft->mv_ranges[0][0];
+    ctl.BVMV_range = vft->mv_ranges[0][1];
+    ctl.FHMV_range = vft->mv_ranges[1][0];
+    ctl.FVMV_range = vft->mv_ranges[1][1];
+    ctl.picture_structure = vft->picture_structure;
+    ctl.intra_dc_precision = vft->intra_dc_precision;
+    ctl.picture_coding_type = vft->picture_coding_type;
+    ctl.mpeg_coding = (vft->mpeg_coding == 0) ? XVMC_MPEG_1 : XVMC_MPEG_2;
+    ctl.flags = 0;
+    ctl.flags |= (vft->progressive_sequence) ? XVMC_PROGRESSIVE_SEQUENCE : 0;
+    ctl.flags |= (vft->scan) ? XVMC_ALTERNATE_SCAN : XVMC_ZIG_ZAG_SCAN;
+    ctl.flags |= (vft->pred_dct_frame) ?
+                    XVMC_PRED_DCT_FRAME : XVMC_PRED_DCT_FIELD;
+    ctl.flags |= (picture->b_top_field_first) ?
+                    XVMC_TOP_FIELD_FIRST : XVMC_BOTTOM_FIELD_FIRST;
+    ctl.flags |= (vft->concealment_motion_vectors) ?
+                    XVMC_CONCEALMENT_MOTION_VECTORS : 0;
+    ctl.flags |= (vft->q_scale_type) ? XVMC_Q_SCALE_TYPE : 0;
+    ctl.flags |= (vft->intra_vlc_format) ? XVMC_INTRA_VLC_FORMAT : 0;
+    ctl.flags |= (vft->second_field) ? XVMC_SECOND_FIELD : 0;
+
+    if( ff )
+        fs = ff->p_sys->xvmc_surf;
+    if( bf )
+        bs = bf->p_sys->xvmc_surf;
+
+    /*
+     * Below is for interlaced streams and second_field.
+     */
+    if( ctl.picture_coding_type == P_TYPE ) /* XVMC_P_PICTURE) */
+        bs = picture->p_sys->xvmc_surf;
+
+    if( (qmx.load_intra_quantiser_matrix = vft->load_intra_quantizer_matrix) )
+    {
+        memcpy( qmx.intra_quantiser_matrix, vft->intra_quantizer_matrix,
+                sizeof(qmx.intra_quantiser_matrix) );
+    }
+    if( (qmx.load_non_intra_quantiser_matrix =
+                vft->load_non_intra_quantizer_matrix) )
+    {
+        memcpy( qmx.non_intra_quantiser_matrix, vft->non_intra_quantizer_matrix,
+               sizeof(qmx.non_intra_quantiser_matrix) );
+    }
+    qmx.load_chroma_intra_quantiser_matrix = 0;
+    qmx.load_chroma_non_intra_quantiser_matrix = 0;
+    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+
+    if( ! xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf) )
+    {
+        picture->p_sys->xxmc_data.result = 128;
+        xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+        return;
+    }
+
+    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+    XvMCLoadQMatrix( p_vout->p_sys->p_display, &p_vout->p_sys->context, &qmx );
+    do {
+        picture->p_sys->xxmc_data.result =
+                XvMCBeginSurface( p_vout->p_sys->p_display,
+                                  &p_vout->p_sys->context,
+                                  picture->p_sys->xvmc_surf,
+                                  fs, bs, &ctl );
+    } while( !picture->p_sys->xxmc_data.result );
+    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+}
+
+void xvmc_vld_slice( picture_t *picture )
+{
+    vout_sys_t *p_sys     = picture->p_sys;
+    vout_thread_t *p_vout = p_sys->p_vout;
+
+    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
+    if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
+    {
+        picture->p_sys->xxmc_data.result = 128;
+        xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+        msg_Err(p_vout, "vld slice error" );
+        return;
+    }
+
+    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
+    picture->p_sys->xxmc_data.result =
+            XvMCPutSlice2( p_vout->p_sys->p_display,
+                           &p_vout->p_sys->context,
+                            picture->p_sys->xxmc_data.slice_data,
+                            picture->p_sys->xxmc_data.slice_data_size,
+                            picture->p_sys->xxmc_data.slice_code );
+
+    if( picture->p_sys->xxmc_data.result != 0 )
+        msg_Err( p_vout, "vlc slice error %d",
+                 picture->p_sys->xxmc_data.result );
+    /*
+     * If CPU-saving mode is enabled, sleep after every xxmc->sleep slice. This will free
+     * up the cpu while the decoder is working on the slice. The value of xxmc->sleep is calculated
+     * so that the decoder thread sleeps at most 50% of the frame delay,
+     * assuming a 2.6 kernel clock of 1000 Hz.
+     */
+    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
+    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
+#if 0
+    if( p_vout->p_sys->cpu_save_enabled )
+    {
+        p_vout->p_sys->cpu_saver += 1.;
+        if( p_vout->p_sys->cpu_saver >= picture->p_sys->xxmc_data.sleep )
+        {
+            usleep(1);
+            p_vout->p_sys->cpu_saver -= picture->p_sys->xxmc_data.sleep;
+        }
+    }
+#endif
+}