summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2004-09-28 18:49:38 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2004-09-28 18:49:38 +0000
commitfe2a390351727cb5ae264588293f8bd7d6d5198e (patch)
tree20c91e59d361585dd0d8d45440a96c807ea7dddb
parentf42eccd3e7c5a717f668f0b832ace09f161dbfbc (diff)
downloadxine-lib-fe2a390351727cb5ae264588293f8bd7d6d5198e.tar.gz
xine-lib-fe2a390351727cb5ae264588293f8bd7d6d5198e.tar.bz2
xxmc patch by Thomas Hellstrom (with some changes)
there is still some work to do, please report any breakages. note: new xxmc driver tested with both nvidia and via libraries. CVS patchset: 7007 CVS date: 2004/09/28 18:49:38
-rw-r--r--AUTHORS6
-rw-r--r--ChangeLog8
-rw-r--r--configure.ac187
-rw-r--r--include/xine.h.in3
-rw-r--r--src/libmpeg2/Makefile.am3
-rw-r--r--src/libmpeg2/decode.c146
-rw-r--r--src/libmpeg2/header.c5
-rw-r--r--src/libmpeg2/mpeg2.h9
-rw-r--r--src/libmpeg2/mpeg2_internal.h3
-rw-r--r--src/libmpeg2/slice_xvmc.c9
-rw-r--r--src/libmpeg2/slice_xvmc_vld.c248
-rw-r--r--src/libmpeg2/xxmc.h12
-rw-r--r--src/video_out/Makefile.am11
-rw-r--r--src/video_out/alphablend.c188
-rw-r--r--src/video_out/alphablend.h40
-rw-r--r--src/video_out/video_out_xvmc.c17
-rw-r--r--src/video_out/video_out_xxmc.c2652
-rw-r--r--src/video_out/xvmc_mocomp.c274
-rw-r--r--src/video_out/xvmc_vld.c171
-rw-r--r--src/video_out/xxmc.h293
-rw-r--r--src/xine-engine/Makefile.am3
-rw-r--r--src/xine-engine/accel_xvmc.h152
-rw-r--r--src/xine-engine/post.c36
-rw-r--r--src/xine-engine/video_out.c60
-rw-r--r--src/xine-engine/video_out.h61
25 files changed, 4396 insertions, 201 deletions
diff --git a/AUTHORS b/AUTHORS
index 85f2f36e2..e024c6460 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -503,5 +503,9 @@ Ryan Tadlock <pholan-xine-users@midnight.postino.com>
Casper Boemann <cbr@boemann.dk>
reuse stubs for unresolved exports of win32 dlls
-
+
+Thomas Hellström <unichrome@shipmail.org>
+ XxMC driver with reworked XvMC support, including VIA CLE266 vld
+ extensions.
+
(let us know if we've forgotten anyone)
diff --git a/ChangeLog b/ChangeLog
index 19a4196c5..3dc83ee53 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,7 +7,13 @@
(these files required cropping after decoding)
* Fix crashes with some input plugins when no audio output was available
* Windows ports updates and cleanups
-
+ * new xxmc driver supporting XvMC with extended vld (for VIA CLE266),
+ idct and mocomp accelerations. includes automatic Xv fallback for
+ non-mpeg streams. supports overlays and OSD.
+ * suggested using the libXvMCW so xine won't depend on any vendor
+ specific library. you can get the old behaviour (not recommended)
+ using ./configure --with-xvmc-lib=XvMCNVIDIA
+
xine-lib (1-rc6)
* Moved win32 frontend into separate module.
* Fixed Xv initialization to enable multiple instances of the Xv plugin
diff --git a/configure.ac b/configure.ac
index 8071d2a7c..35f1f683b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -472,8 +472,6 @@ dnl static linking is preferred!
dnl but only dynamic linking is possible when using libtool < 1.4.0
AC_PREREQ_LIBTOOL(1.4.0, xv_lib="libXv.a", xv_lib="libXv.so")
-AC_PREREQ_LIBTOOL(1.4.0, xvmc_lib="libXvMC.a", xvmc_lib="libXvMC.so")
-AC_PREREQ_LIBTOOL(1.4.0, xvmc_lib_nv="libXvMCNVIDIA.a", xv_lib_nv="libXvMCNVIDIA_dynamic.so.1")
host_or_hostalias="$host"
if test "$host_or_hostalias" = ""; then
@@ -492,14 +490,6 @@ case "$host_or_hostalias" in
echo "warning: hppa linker - disabling static libXv"
xv_lib="libXv.so"
fi
- if test "$xvmc_lib" = "libXvMC.a"; then
- echo "warning: hppa linker - disabling static libXvMC"
- xvmc_lib="libXvMC.so"
- fi
- if test "$xvmc_lib_nv" = "libXvMCNVIDIA.a"; then
- echo "warning: hppa linker - disabling static libXvMCNVIDIA"
- xvmc_lib_nv="libXvMCNVIDIA_dynamic.so.1"
- fi
;;
i386-*-freebsd*)
@@ -566,45 +556,138 @@ AC_SUBST(XV_LIB)
AC_SUBST(EXTRA_X_LIBS)
AC_SUBST(EXTRA_X_CFLAGS)
-AC_ARG_WITH(xvmc-path, AC_HELP_STRING([--with-xvmc-path=path], [where libXvMC is installed]),
- xvmc_path="$withval", xvmc_path="/usr/X11R6/lib")
-
-AC_CHECK_LIB(XvMC, XvMCQueryExtension,
- [ AC_MSG_CHECKING(for $xvmc_lib location)
- if test -f "$xvmc_path/$xvmc_lib_nv"; then
- if test -f "$xvmc_path/$xvmc_lib"; then
- AC_MSG_RESULT(found in $xvmc_path)
- XVMC_LIB="-L$xvmc_path -lXvMC -lXvMCNVIDIA"
- AC_DEFINE(HAVE_XVMC,1,[Define this if you have libXvMC installed])
- ac_have_xvmc="yes"
- if test x$xvmc_lib = "xlibXvMC.a" ; then
- AC_DEFINE(HAVE_XVMC_STATIC,1,[Define this if you have libXvMC.a])
- fi
- else
- AC_MSG_RESULT(not found in $xvmc_path)
- echo
- echo "****************************************************************"
- echo "* if you don't have a libXvMC.so on your system, use: *"
- echo "* ld --whole-archive -shared -o libXvMC.so.1 libXvMC.a *"
- echo "* then: ln -s libXvMC.so.1 libXvMC.so *"
- echo "* to create it or try to use --with-xvmc-path to set the *"
- echo "* location of libXvMC.so *"
- echo "****************************************************************"
- echo
- fi
- fi ],, [$X_LIBS $X_PRE_LIBS -lXext $X_EXTRA_LIBS])
+dnl
+dnl Check if we can enable the xxmc plugin.
+dnl
+if test x$no_x = "x"; then
+
+AC_ARG_WITH(xxmc-path, AC_HELP_STRING([--with-xxmc-path=path], [where libXvMC libraries for the
+ xxmc plugin are installed. Defalts to the default X library path.]),
+ xxmc_path="$withval", xxmc_path="$x_libraries")
+AC_ARG_WITH(xxmc-lib, AC_HELP_STRING([--with-xxmc-lib=XXXX], [The name of the XvMC library
+ libXXXX.so for the xxmc plugin.]),xxmc_stub="$withval",
+ xxmc_stub="XvMCW")
+saved_libs="$LIBS"
+XXMC_LIB="-L$xxmc_path -l$xxmc_stub"
+AC_MSG_CHECKING(whether to enable the xxmc plugin with vld extensions)
+AC_MSG_RESULT()
+dnl Check if vld "extended" XvMC is available
+if test x$xxmc_stub == "xXvMCW"; then
+ AC_CHECK_LIB($xxmc_stub, XvMCPutSlice,
+ ac_have_xxmc="yes",
+ [ac_have_xxmc="no"
+ AC_MSG_RESULT([*** Could not link with -l$xxmc_stub for vld extensions.])],
+ [-L$xxmc_path $X_LIBS $X_PRE_LIBS $XV_LIB -lXext $X_EXTRA_LIBS])
+else
+ if test x$ac_have_xv = "xyes"; then
+ AC_CHECK_LIB($xxmc_stub, XvMCPutSlice,
+ [ac_have_xxmc="yes"
+ XXMC_LIB="$XXMC_LIB -lXvMC"],
+ [ac_have_xxmc="no"
+ AC_MSG_RESULT([*** Could not link with -l$xxmc_stub -lXvMC for vld extensions.])],
+ [-L$xxmc_path -lXvMC $X_LIBS $X_PRE_LIBS $XV_LIB -lXext $X_EXTRA_LIBS])
+ else
+ ac_have_xxmc="no",
+ fi
+fi
+if test x$ac_have_xxmc = "xyes"; then
+ AC_CHECK_HEADERS($x_includes/X11/extensions/vldXvMC.h,
+ [ac_have_vldxvmc_h="yes"],
+ ac_have_xxmc="no",)
+ if test "x$ac_have_vldxvmc_h" = "xyes"; then
+ AC_DEFINE([HAVE_VLDXVMC], [1],
+ [Define 1 if you have vldXvMC.h])
+ fi
+fi
+AM_CONDITIONAL(HAVE_VLDXVMC, test x$ac_have_vldxvmc_h = "xyes")
+dnl Try fallback to standard XvMC if vld failed
+if test x$ac_have_xxmc = "xno"; then
+ if test x$xxmc_stub == "xXvMCW"; then
+ AC_CHECK_LIB($xxmc_stub, XvMCCreateContext,
+ ac_have_xxmc="yes",
+ [ac_have_xxmc="no"
+ AC_MSG_RESULT([*** Could not link with -l$xxmc_stub for standard XvMC.])],
+ [-L$xxmc_path $X_LIBS $X_PRE_LIBS $XV_LIB -lXext $X_EXTRA_LIBS])
+ else
+ if test x$ac_have_xv = "xyes"; then
+ AC_CHECK_LIB($xxmc_stub, XvMCCreateContext,
+ [ac_have_xxmc="yes"
+ XXMC_LIB="$XXMC_LIB -lXvMC"],
+ [ac_have_xxmc="no"
+ AC_MSG_RESULT([*** Could not link with -lXvMC for standard XvMC.])],
+ [-L$xxmc_path -lXvMC $X_LIBS $X_PRE_LIBS $XV_LIB -lXext $X_EXTRA_LIBS])
+ else
+ ac_have_xxmc="no",
+ fi
+ fi
+fi
+if test x$ac_have_xxmc = "xyes"; then
+ AC_CHECK_HEADERS($x_includes/X11/extensions/XvMC.h,,
+ ac_have_xxmc="no",)
+fi
+if test x$ac_have_xxmc = "xyes"; then
+ AC_DEFINE(HAVE_XXMC,1,[Define this to compile the xxmc plugin.])
+ if test "x$ac_have_vldxvmc_h" = "xyes"; then
+ AC_MSG_RESULT([*** Enabling xxmc plugin with vld extensions.])
+ else
+ AC_MSG_RESULT([*** Enabling xxmc plugin for standard XvMC *only*.])
+ fi
+else
+ AC_MSG_RESULT([*** Disabling xxmc plugin due to above errors.])
+fi
+LIBS="$saved_libs"
+fi
+AM_CONDITIONAL(HAVE_XXMC, test x$ac_have_xxmc = "xyes")
+AC_SUBST(XXMC_LIB)
-AM_CONDITIONAL(HAVE_XVMC, test x$ac_have_xvmc = "xyes")
-dnl AM_CONDITIONAL(HAVE_XVMC_STATIC, test x$ac_have_xvmc = "xyes" -a x$xvmc_lib = "xlibXvMC.a")
dnl
-dnl xine_check use XvMC functions API.
+dnl Check if we can enable the xvmc plugin.
dnl
+if test x$no_x = "x"; then
+
+AC_ARG_WITH(xvmc-path, AC_HELP_STRING([--with-xvmc-path=path], [where libXvMC libraries for the
+ xvmc plugin are installed. Defalts to the default X library path.]),
+ xvmc_path="$withval", xvmc_path="$x_libraries")
+AC_ARG_WITH(xvmc-lib, AC_HELP_STRING([--with-xvmc-lib=XXXX], [The name of the XvMC library
+ libXXXX.so for the xvmc plugin.]),xvmc_stub="$withval",
+ xvmc_stub="XvMCW")
+saved_libs="$LIBS"
+XVMC_LIB="-L$xvmc_path -l$xvmc_stub"
+AC_MSG_CHECKING(whether to enable the xvmc plugin)
+AC_MSG_RESULT()
+if test x$xvmc_stub == "xXvMCW"; then
+ AC_CHECK_LIB($xvmc_stub, XvMCCreateContext,
+ ac_have_xvmc="yes",
+ [ac_have_xvmc="no"
+ AC_MSG_RESULT([*** Could not link with -l$xvmc_stub.])],
+ [-L$xvmc_path $X_LIBS $X_PRE_LIBS $XV_LIB -lXext $X_EXTRA_LIBS])
+else
+ if test x$ac_have_xv = "xyes"; then
+ AC_CHECK_LIB($xvmc_stub, XvMCCreateContext,
+ [ac_have_xvmc="yes"
+ XVMC_LIB="$XVMC_LIB -lXvMC"],
+ [ac_have_xvmc="no"
+ AC_MSG_RESULT([*** Could not link with -lXvMC.])],
+ [-L$xvmc_path -lXvMC $X_LIBS $X_PRE_LIBS $XV_LIB -lXext $X_EXTRA_LIBS])
+ else
+ ac_have_xvmc="no",
+ fi
+fi
if test x$ac_have_xvmc = "xyes"; then
- EXTRA_X_LIBS="-L$xvmc_path $XVMC_LIBS -lXext"
- EXTRA_X_CFLAGS=""
+ AC_CHECK_HEADERS($x_includes/X11/extensions/XvMC.h,,
+ ac_have_xvmc="no",)
+fi
+if test x$ac_have_xvmc = "xyes"; then
+ AC_DEFINE(HAVE_XVMC,1,[Define this if you have an XvMC library and XvMC.h installed.])
+ AC_MSG_RESULT([*** Enabling old xvmc plugin.])
+else
+ AC_MSG_RESULT([*** Disabling old xvmc plugin due to above errors.])
fi
-AC_SUBST(XVMC_LIB)
+LIBS="$saved_libs"
+fi
+AM_CONDITIONAL(HAVE_XVMC, test x$ac_have_xvmc = "xyes")
+AC_SUBST(XVMC_LIB)
dnl ---------------------------------------------
dnl Checks for Xinerama extension
@@ -2330,21 +2413,17 @@ if test x"$no_x" != "xyes"; then
echo " - Xv (XVideo *shared*)"
fi
fi
- dnl XvMC
- if test x$ac_have_xvmc = "xyes"; then
- if test x$xvmc_lib="xlibXvMC.a"; then
- echo " - XvMC (XVideo *static*)"
+ dnl XxMC
+ if test x$ac_have_xxmc = "xyes"; then
+ if test "x$ac_have_vldxvmc_h" = "xyes"; then
+ echo " - XxMC (XVideo extended motion compensation)"
else
- echo " - XvMC (XVideo *shared*)"
+ echo " - XxMC (XVideo motion compensation - vld extensions DISABLED)"
fi
fi
- dnl XvMCNVIDIA
+ dnl XvMC
if test x$ac_have_xvmc = "xyes"; then
- if test x$xvmc_lib="xlibXvMCNVIDIA.a"; then
- echo " - XvMCNVIDIA (XVideo *static*)"
- else
- echo " - XvMCNVIDIA (XVideo *shared*)"
- fi
+ echo " - XvMC (XVideo motion compensation)"
fi
if test x$ac_have_opengl = "xyes" -a x$ac_have_glut="xyes" -o \
x$ac_have_opengl = "xyes" -a x$ac_have_glu="xyes"; then
diff --git a/include/xine.h.in b/include/xine.h.in
index f03e9fa1d..a4633c78e 100644
--- a/include/xine.h.in
+++ b/include/xine.h.in
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine.h.in,v 1.130 2004/09/22 20:18:50 miguelfreitas Exp $
+ * $Id: xine.h.in,v 1.131 2004/09/28 18:49:39 miguelfreitas Exp $
*
* public xine-lib (libxine) interface and documentation
*
@@ -417,6 +417,7 @@ int xine_get_current_frame (xine_stream_t *stream,
#define XINE_IMGFMT_YV12 (('2'<<24)|('1'<<16)|('V'<<8)|'Y')
#define XINE_IMGFMT_YUY2 (('2'<<24)|('Y'<<16)|('U'<<8)|'Y')
#define XINE_IMGFMT_XVMC (('C'<<24)|('M'<<16)|('v'<<8)|'X')
+#define XINE_IMGFMT_XXMC (('C'<<24)|('M'<<16)|('x'<<8)|'X')
/* get current xine's virtual presentation timestamp (1/90000 sec)
* note: this is mostly internal data.
diff --git a/src/libmpeg2/Makefile.am b/src/libmpeg2/Makefile.am
index c0d06d978..78351525d 100644
--- a/src/libmpeg2/Makefile.am
+++ b/src/libmpeg2/Makefile.am
@@ -21,10 +21,11 @@ xineplug_decode_mpeg2_la_SOURCES = \
motion_comp_vis.c \
slice.c \
slice_xvmc.c \
+ slice_xvmc_vld.c \
stats.c \
xine_decoder.c
xineplug_decode_mpeg2_la_LIBADD = $(MLIB_LIBS) $(XINE_LIB)
xineplug_decode_mpeg2_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
-noinst_HEADERS = vlc.h mpeg2.h mpeg2_internal.h idct_mlib.h vis.h
+noinst_HEADERS = vlc.h mpeg2.h xxmc.h mpeg2_internal.h idct_mlib.h vis.h
diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c
index bb5076489..114e8bc11 100644
--- a/src/libmpeg2/decode.c
+++ b/src/libmpeg2/decode.c
@@ -1,4 +1,4 @@
-/*
+ /*
* decode.c
* Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
@@ -25,7 +25,6 @@
*/
#include "config.h"
-
#include <stdio.h>
#include <string.h> /* memcpy/memset, try to remove */
#include <stdlib.h>
@@ -42,6 +41,7 @@
#include "mpeg2.h"
#include "mpeg2_internal.h"
#include "xineutils.h"
+#include "xxmc.h"
/*
#define LOG_PAN_SCAN
@@ -90,7 +90,10 @@ void mpeg2_init (mpeg2dec_t * mpeg2dec,
/* initialize substructures */
mpeg2_header_state_init (mpeg2dec->picture);
- if( output->get_capabilities(output) & VO_CAP_XVMC_MOCOMP ) {
+ if ( output->get_capabilities(output) & VO_CAP_XXMC) {
+ printf("libmpeg2: output port has XxMC capability\n");
+ mpeg2dec->frame_format = XINE_IMGFMT_XXMC;
+ } else if( output->get_capabilities(output) & VO_CAP_XVMC_MOCOMP) {
printf("libmpeg2: output port has XvMC capability\n");
mpeg2dec->frame_format = XINE_IMGFMT_XVMC;
} else {
@@ -274,6 +277,38 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
if (is_frame_done && picture->current_frame != NULL) {
+ /*
+ * This frame completion code will move to a separate libmpeg2_accel.c file?
+ * int libmpeg2_accel_frame_completion(mpeg2dec_t *, picture_t *, int);
+ */
+
+ if (mpeg2dec->frame_format == XINE_IMGFMT_XXMC) {
+ xine_xxmc_t *xxmc = (xine_xxmc_t *)
+ picture->current_frame->accel_data;
+ switch(xxmc->format) {
+ case XINE_IMGFMT_XXMC:
+ switch(xxmc->acceleration) {
+ case XINE_XVMC_ACCEL_VLD:
+ mpeg2_xxmc_vld_frame_complete(mpeg2dec, picture, code);
+ break;
+ case XINE_XVMC_ACCEL_IDCT:
+ case XINE_XVMC_ACCEL_MOCOMP:
+ xxmc->decoded = !picture->current_frame->bad_frame;
+ xxmc->proc_xxmc_flush( picture->current_frame );
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ /*
+ * End of frame completion code.
+ */
+
+
if (((picture->picture_structure == FRAME_PICTURE) ||
(picture->second_field)) ) {
@@ -486,7 +521,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
picture->current_frame != picture->forward_reference_frame ) {
picture->current_frame->free (picture->current_frame);
}
- if (picture->picture_coding_type == B_TYPE)
+ if (picture->picture_coding_type == B_TYPE) {
picture->current_frame =
mpeg2dec->stream->video_out->get_frame (mpeg2dec->stream->video_out,
picture->coded_picture_width,
@@ -494,7 +529,15 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
get_aspect_ratio(mpeg2dec),
mpeg2dec->frame_format,
flags);
- else {
+ /*
+ * Move to libmpeg2_accel.c
+ * int libmpeg2_accel_new_frame(mpeg2dec_t *, picture_t *)
+ */
+ mpeg2_xxmc_choose_coding(mpeg2dec->frame_format, picture);
+ /*
+ * End of new frame accel code.
+ */
+ } else {
picture->current_frame =
mpeg2dec->stream->video_out->get_frame (mpeg2dec->stream->video_out,
picture->coded_picture_width,
@@ -502,6 +545,14 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
get_aspect_ratio(mpeg2dec),
mpeg2dec->frame_format,
flags);
+ /*
+ * Move to libmpeg2_accel.c
+ * int libmpeg2_accel_new_frame(mpeg2dec_t *, picture_t *)
+ */
+ mpeg2_xxmc_choose_coding(mpeg2dec->frame_format, picture);
+ /*
+ * End of new frame accel code.
+ */
if (picture->forward_reference_frame &&
picture->forward_reference_frame != picture->backward_reference_frame)
picture->forward_reference_frame->free (picture->forward_reference_frame);
@@ -510,11 +561,30 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
picture->backward_reference_frame;
picture->backward_reference_frame = picture->current_frame;
}
- if(mpeg2dec->new_sequence)
- {
- picture->mc = picture->current_frame->macroblocks;
- mpeg2dec->new_sequence = 0;
+
+ /*
+ * Move to libmpeg2_accel.c
+ * int libmpeg2_accel_new_sequence(mpeg2dec_t *, picture_t *)
+ */
+
+ if(mpeg2dec->new_sequence) {
+ switch(mpeg2dec->frame_format) {
+ case XINE_IMGFMT_XXMC:
+ case XINE_IMGFMT_XVMC: {
+ xine_xvmc_t *xvmc = (xine_xvmc_t *)
+ picture->current_frame->accel_data;
+ picture->mc = xvmc->macroblocks;
+ mpeg2dec->new_sequence = 0;
+ break;
+ }
+ default:
+ break;
+ }
}
+ /*
+ * End of new sequence accel code.
+ */
+
picture->current_frame->bad_frame = 1;
picture->current_frame->drawn = 0;
picture->current_frame->pts = mpeg2dec->pts;
@@ -543,6 +613,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
picture->current_frame->id, picture->picture_coding_type == I_TYPE ? "I" :
picture->picture_coding_type == P_TYPE ? "P" : "B");
mpeg2dec->pts = 0;
+ /*printf("Starting to decode frame %d\n",picture->current_frame->id);*/
}
}
@@ -551,17 +622,50 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
printf("slice target %08x past %08x future %08x\n",picture->current_frame,picture->forward_reference_frame,picture->backward_reference_frame);
fflush(stdout);
#endif
-
- if(picture->mc && picture->mc->xvmc_accel) {
- mpeg2_xvmc_slice (picture, code, buffer);
-
- } else {
- mpeg2_slice (picture, code, buffer);
+ /*
+ * The below accelerated slice function choice will move to libmpeg2_accel.c ?
+ * int libmpeg2_accel_slice(mpeg2dec_t *, picture_t *, int , char *)
+ */
+
+ switch( mpeg2dec->frame_format ) {
+ case XINE_IMGFMT_XXMC:
+ {
+ xine_xxmc_t *xxmc = (xine_xxmc_t *)
+ picture->current_frame->accel_data;
+ switch(xxmc->format) {
+ case XINE_IMGFMT_XXMC:
+ switch(xxmc->acceleration) {
+ case XINE_XVMC_ACCEL_VLD:
+ mpeg2_xxmc_slice(mpeg2dec, picture, code, buffer);
+ break;
+ case XINE_XVMC_ACCEL_IDCT:
+ case XINE_XVMC_ACCEL_MOCOMP:
+ mpeg2_xvmc_slice (picture, code, buffer);
+ break;
+ default:
+ mpeg2_slice (picture, code, buffer);
+ break;
+ }
+ break;
+ default:
+ mpeg2_slice (picture, code, buffer);
+ break;
+ }
+ break;
+ }
+ case XINE_IMGFMT_XVMC:
+ mpeg2_xvmc_slice (picture, code, buffer);
+ break;
+ default:
+ mpeg2_slice (picture, code, buffer);
+ break;
}
+ /*
+ * End of acceleration code.
+ */
if( picture->v_offset > picture->limit_y ) {
picture->current_frame->bad_frame = 0;
- lprintf("frame %d successfuly decoded\n",picture->current_frame->id);
}
}
}
@@ -604,6 +708,7 @@ static inline uint8_t * copy_chunk (mpeg2dec_t * mpeg2dec,
}
}
mpeg2dec->code = byte;
+ mpeg2dec->chunk_size = chunk_ptr - mpeg2dec->chunk_buffer - 3;
mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
mpeg2dec->shift = 0xffffff00;
return current;
@@ -652,6 +757,15 @@ void mpeg2_discontinuity (mpeg2dec_t * mpeg2dec) {
picture->forward_reference_frame->pts = 0;
if ( picture->backward_reference_frame )
picture->backward_reference_frame->pts = 0;
+
+ /*
+ * Move to libmpeg2_accel.c
+ * int libmpeg2_accel_discontinuity(mpeg2dec_t *);
+ */
+ mpeg2dec->xxmc_last_slice_code=-1;
+ /*
+ * End of discontinuity accel code.
+ */
}
void mpeg2_reset (mpeg2dec_t * mpeg2dec) {
diff --git a/src/libmpeg2/header.c b/src/libmpeg2/header.c
index 0f10588b0..e435fb405 100644
--- a/src/libmpeg2/header.c
+++ b/src/libmpeg2/header.c
@@ -104,6 +104,8 @@ static uint32_t get_bits(uint8_t *buffer, uint32_t count, uint32_t *bit_position
void mpeg2_header_state_init (picture_t * picture)
{
picture->scan = mpeg2_scan_norm;
+ picture->load_intra_quantizer_matrix = 1;
+ picture->load_non_intra_quantizer_matrix = 1;
}
int mpeg2_header_sequence (picture_t * picture, uint8_t * buffer)
@@ -150,7 +152,8 @@ int mpeg2_header_sequence (picture_t * picture, uint8_t * buffer)
else
for (i = 0; i < 64; i++)
picture->non_intra_quantizer_matrix[i] = 16;
-
+ picture->load_intra_quantizer_matrix = 1;
+ picture->load_non_intra_quantizer_matrix = 1;
/* MPEG1 - for testing only */
picture->mpeg1 = 1;
picture->intra_dc_precision = 0;
diff --git a/src/libmpeg2/mpeg2.h b/src/libmpeg2/mpeg2.h
index b6500d1ef..b2ecf669e 100644
--- a/src/libmpeg2/mpeg2.h
+++ b/src/libmpeg2/mpeg2.h
@@ -21,6 +21,9 @@
/* Structure for the mpeg2dec decoder */
+#ifndef MPEG2_H
+#define MPEG2_H
+
typedef struct mpeg2dec_s {
xine_video_port_t * output;
uint32_t frame_format;
@@ -45,6 +48,7 @@ typedef struct mpeg2dec_s {
uint8_t * chunk_ptr;
/* last start code ? */
uint8_t code;
+ uint32_t chunk_size;
int64_t pts;
uint32_t rff_pattern;
@@ -55,7 +59,8 @@ typedef struct mpeg2dec_s {
/* a spu decoder for possible closed captions */
spu_decoder_t *cc_dec;
-
+ int xxmc_last_slice_code;
+ unsigned xxmc_mb_pic_height;
} mpeg2dec_t ;
@@ -81,3 +86,5 @@ void mpeg2_discontinuity (mpeg2dec_t * mpeg2dec);
* currently
*/
/* void process_userdata(mpeg2dec_t *mpeg2dec, uint8_t *buffer); */
+
+#endif
diff --git a/src/libmpeg2/mpeg2_internal.h b/src/libmpeg2/mpeg2_internal.h
index 6ec414789..27611e132 100644
--- a/src/libmpeg2/mpeg2_internal.h
+++ b/src/libmpeg2/mpeg2_internal.h
@@ -22,6 +22,7 @@
*/
#include "video_out.h"
+#include "accel_xvmc.h"
/* macroblock modes */
#define MACROBLOCK_INTRA XINE_MACROBLOCK_INTRA
@@ -108,6 +109,8 @@ typedef struct picture_s {
/* sequence header stuff */
uint8_t intra_quantizer_matrix [64];
uint8_t non_intra_quantizer_matrix [64];
+ int load_intra_quantizer_matrix;
+ int load_non_intra_quantizer_matrix;
/* The width and height of the picture snapped to macroblock units */
int coded_picture_width;
diff --git a/src/libmpeg2/slice_xvmc.c b/src/libmpeg2/slice_xvmc.c
index ec23e25ad..1f6176e78 100644
--- a/src/libmpeg2/slice_xvmc.c
+++ b/src/libmpeg2/slice_xvmc.c
@@ -34,7 +34,7 @@
#include "xineutils.h"
#include "attributes.h"
-
+#include "accel_xvmc.h"
#define MOTION_ACCEL XINE_VO_MOTION_ACCEL
#define IDCT_ACCEL XINE_VO_IDCT_ACCEL
@@ -1700,6 +1700,7 @@ void mpeg2_xvmc_slice (picture_t * picture, int code, uint8_t * buffer)
#define bits (picture->bitstream_bits)
#define bit_ptr (picture->bitstream_ptr)
cpu_state_t cpu_state;
+ xine_xvmc_t *xvmc = (xine_xvmc_t *) picture->current_frame->accel_data;
bitstream_init (picture, buffer);
@@ -1889,7 +1890,7 @@ void mpeg2_xvmc_slice (picture_t * picture, int code, uint8_t * buffer)
}
}
- picture->current_frame->proc_macro_block(picture->XvMC_x, picture->XvMC_y,
+ xvmc->proc_macro_block(picture->XvMC_x, picture->XvMC_y,
picture->XvMC_mb_type,
picture->XvMC_motion_type,
picture->XvMC_mv_field_sel,
@@ -1965,7 +1966,7 @@ void mpeg2_xvmc_slice (picture_t * picture, int code, uint8_t * buffer)
picture->XvMC_x = picture->offset/16;
picture->XvMC_y = picture->v_offset/16;
- picture->current_frame->proc_macro_block(picture->XvMC_x,picture->XvMC_y,
+ xvmc->proc_macro_block(picture->XvMC_x,picture->XvMC_y,
picture->XvMC_mb_type,
picture->XvMC_motion_type,
picture->XvMC_mv_field_sel,
@@ -2004,7 +2005,7 @@ void mpeg2_xvmc_slice (picture_t * picture, int code, uint8_t * buffer)
picture->XvMC_x = picture->offset/16;
picture->XvMC_y = picture->v_offset/16;
- picture->current_frame->proc_macro_block(picture->XvMC_x,picture->XvMC_y,
+ xvmc->proc_macro_block(picture->XvMC_x,picture->XvMC_y,
picture->XvMC_mb_type,
picture->XvMC_motion_type,
picture->XvMC_mv_field_sel,
diff --git a/src/libmpeg2/slice_xvmc_vld.c b/src/libmpeg2/slice_xvmc_vld.c
new file mode 100644
index 000000000..950ec1f63
--- /dev/null
+++ b/src/libmpeg2/slice_xvmc_vld.c
@@ -0,0 +1,248 @@
+/*
+ * 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 "xine_internal.h"
+#include "video_out.h"
+#include "mpeg2.h"
+#include "mpeg2_internal.h"
+#include "xxmc.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(int decoder_format, picture_t *picture)
+{
+ if (picture->current_frame) {
+ if (XINE_IMGFMT_XXMC == decoder_format) {
+ xine_xxmc_t *xxmc = (xine_xxmc_t *)
+ picture->current_frame->accel_data;
+
+ /*
+ * Make a request for acceleration type and mpeg coding from
+ * the output plugin.
+ */
+
+ xxmc->format = XINE_IMGFMT_XXMC;
+ xxmc->acceleration = XINE_XVMC_ACCEL_VLD| XINE_XVMC_ACCEL_IDCT
+ | XINE_XVMC_ACCEL_MOCOMP ;
+ xxmc->mpeg = (picture->mpeg1) ? XINE_XVMC_MPEG_1:XINE_XVMC_MPEG_2;
+ xxmc->proc_xxmc_frame(picture->current_frame);
+ }
+ }
+}
+
+
+void mpeg2_xxmc_slice( mpeg2dec_t *mpeg2dec, picture_t *picture, int code,
+ uint8_t *buffer)
+{
+ vo_frame_t
+ *frame = picture->current_frame;
+ xine_xxmc_t
+ *xxmc = (xine_xxmc_t *) frame->accel_data;
+ xine_vld_frame_t
+ *vft = &xxmc->vld_frame;
+ unsigned
+ mb_frame_height;
+ int
+ i;
+ const uint8_t *
+ scan_pattern;
+ float
+ ms_per_slice;
+
+ if (1 == code) {
+ frame->bad_frame = 1;
+
+ /*
+ * Check that first field went through OK. Otherwise,
+ * indicate bad frame.
+ */
+
+ if (picture->second_field) {
+ mpeg2dec->xxmc_last_slice_code = (xxmc->decoded) ? 0 : -1;
+ xxmc->decoded = 0;
+ } else {
+ mpeg2dec->xxmc_last_slice_code = 0;
+ }
+
+ mb_frame_height =
+ (!(picture->mpeg1) && (picture->progressive_sequence)) ?
+ 2*((picture->coded_picture_height+31) >> 5) :
+ (picture->coded_picture_height+15) >> 4;
+ mpeg2dec->xxmc_mb_pic_height = (picture->picture_structure == FRAME_PICTURE ) ?
+ mb_frame_height : mb_frame_height >> 1;
+
+ ms_per_slice = 1000. / (90000. * mb_frame_height) * frame->duration;
+ xxmc->sleep = 1. / (ms_per_slice * 0.45);
+ if (xxmc->sleep < 1.) xxmc->sleep = 1.;
+
+ if (picture->mpeg1) {
+ vft->mv_ranges[0][0] = picture->b_motion.f_code[0];
+ vft->mv_ranges[0][1] = picture->b_motion.f_code[0];
+ vft->mv_ranges[1][0] = picture->f_motion.f_code[0];
+ vft->mv_ranges[1][1] = picture->f_motion.f_code[0];
+ } else {
+ vft->mv_ranges[0][0] = picture->b_motion.f_code[0];
+ vft->mv_ranges[0][1] = picture->b_motion.f_code[1];
+ vft->mv_ranges[1][0] = picture->f_motion.f_code[0];
+ vft->mv_ranges[1][1] = picture->f_motion.f_code[1];
+ }
+
+ vft->picture_structure = picture->picture_structure;
+ vft->picture_coding_type = picture->picture_coding_type;
+ vft->mpeg_coding = (picture->mpeg1) ? 0 : 1;
+ vft->progressive_sequence = picture->progressive_sequence;
+ vft->scan = (picture->scan == mpeg2_scan_alt);
+ vft->pred_dct_frame = picture->frame_pred_frame_dct;
+ vft->concealment_motion_vectors =
+ picture->concealment_motion_vectors;
+ vft->q_scale_type = picture->q_scale_type;
+ vft->intra_vlc_format = picture->intra_vlc_format;
+ vft->intra_dc_precision = picture->intra_dc_precision;
+ vft->second_field = picture->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 = picture->load_intra_quantizer_matrix)) {
+ for (i=0; i<64; ++i) {
+ vft->intra_quantizer_matrix[scan_pattern[i]] =
+ picture->intra_quantizer_matrix[picture->scan[i]];
+ }
+ }
+
+ if ((vft->load_non_intra_quantizer_matrix = picture->load_non_intra_quantizer_matrix)) {
+ for (i=0; i<64; ++i) {
+ vft->non_intra_quantizer_matrix[scan_pattern[i]] =
+ picture->non_intra_quantizer_matrix[picture->scan[i]];
+ }
+ }
+
+ picture->load_intra_quantizer_matrix = 0;
+ picture->load_non_intra_quantizer_matrix = 0;
+ vft->forward_reference_frame = picture->forward_reference_frame;
+ vft->backward_reference_frame = picture->backward_reference_frame;
+ xxmc->proc_xxmc_begin( frame );
+ if (xxmc->result != 0) {
+ xxmc->proc_xxmc_flush( frame );
+ mpeg2dec->xxmc_last_slice_code=-1;
+ }
+ }
+
+ if ((code == mpeg2dec->xxmc_last_slice_code + 1) &&
+ code <= mpeg2dec->xxmc_mb_pic_height) {
+
+ /*
+ * Send this slice to the output plugin. May stall for a long
+ * time in proc_slice;
+ */
+
+ frame->bad_frame = 1;
+ xxmc->slice_data_size = mpeg2dec->chunk_size;
+ xxmc->slice_data = mpeg2dec->chunk_buffer;
+ xxmc->slice_code = code;
+
+ xxmc->proc_xxmc_slice( frame );
+ if (xxmc->result != 0) {
+ xxmc->proc_xxmc_flush( frame );
+ mpeg2dec->xxmc_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 {
+
+ /*
+ * Keep track of slices.
+ */
+
+ mpeg2dec->xxmc_last_slice_code++;
+ }
+
+ } else {
+
+ /*
+ * An error has occured.
+ */
+
+ lprintf("libmpeg2: VLD XvMC: Slice error.\n");
+ mpeg2dec->xxmc_last_slice_code = -1;
+ xxmc->proc_xxmc_flush( frame );
+ return;
+ }
+}
+
+void mpeg2_xxmc_vld_frame_complete(mpeg2dec_t *mpeg2dec, picture_t *picture, int code)
+{
+ vo_frame_t
+ *frame = picture->current_frame;
+ xine_xxmc_t
+ *xxmc = (xine_xxmc_t *) frame->accel_data;
+
+ if (xxmc->decoded) return;
+ if (mpeg2dec->xxmc_last_slice_code >= 1) {
+ xxmc->proc_xxmc_flush( frame );
+ if (xxmc->result) {
+ mpeg2dec->xxmc_last_slice_code=-1;
+ return;
+ }
+ xxmc->decoded = 1;
+ mpeg2dec->xxmc_last_slice_code++;
+ if (picture->picture_structure == 3 || picture->second_field) {
+ if (xxmc->result == 0)
+ frame->bad_frame = 0;
+ }
+ }
+}
diff --git a/src/libmpeg2/xxmc.h b/src/libmpeg2/xxmc.h
new file mode 100644
index 000000000..c4221200b
--- /dev/null
+++ b/src/libmpeg2/xxmc.h
@@ -0,0 +1,12 @@
+#ifndef _XXMC_H
+#define _XXMC_H
+
+#include "accel_xvmc.h"
+
+extern void mpeg2_xxmc_slice( mpeg2dec_t *mpeg2dec, picture_t *picture,
+ int code, uint8_t *buffer);
+extern void mpeg2_xxmc_choose_coding(int decoder_format, picture_t *picture);
+
+extern void mpeg2_xxmc_vld_frame_complete(mpeg2dec_t *mpeg2dec, picture_t *picture, int code);
+
+#endif
diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am
index 9bd16cff7..5c4cb5187 100644
--- a/src/video_out/Makefile.am
+++ b/src/video_out/Makefile.am
@@ -24,6 +24,9 @@ endif
if HAVE_XVMC
xvmc_module = xineplug_vo_out_xvmc.la
endif
+if HAVE_XXMC
+xxmc_module = xineplug_vo_out_xxmc.la
+endif
if HAVE_OPENGL
#opengl_module =
opengl_module = xineplug_vo_out_opengl.la
@@ -87,6 +90,7 @@ lib_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) \
$(directx_module) \
$(caca_module) \
$(macosx_module) \
+ $(xxmc_module) \
xineplug_vo_out_none.la
xineplug_vo_out_xshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \
@@ -99,9 +103,14 @@ xineplug_vo_out_xv_la_LIBADD = $(XV_LIB) $(X_LIBS) -lXext $(XINE_LIB)
xineplug_vo_out_xv_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
xineplug_vo_out_xvmc_la_SOURCES = deinterlace.c alphablend.c video_out_xvmc.c
-xineplug_vo_out_xvmc_la_LIBADD = $(XV_LIB) $(XVMC_LIB) $(X_LIBS) -lXext $(XINE_LIB)
+xineplug_vo_out_xvmc_la_LIBADD = $(XVMC_LIB) $(XV_LIB) $(X_LIBS) -lXext $(XINE_LIB)
xineplug_vo_out_xvmc_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
+xineplug_vo_out_xxmc_la_SOURCES = $(X11OSD) deinterlace.c alphablend.c video_out_xxmc.c\
+ xvmc_mocomp.c xvmc_vld.c xxmc.h
+xineplug_vo_out_xxmc_la_LIBADD = $(XXMC_LIB) $(XV_LIB) $(X_LIBS) -lXext $(XINE_LIB)
+xineplug_vo_out_xxmc_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
+
xineplug_vo_out_opengl_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \
alphablend.c video_out_opengl.c
xineplug_vo_out_opengl_la_LIBADD = $(MLIB_LIBS) $(OPENGL_LIBS) $(GLUT_LIBS) \
diff --git a/src/video_out/alphablend.c b/src/video_out/alphablend.c
index be5f01617..a9f216a9e 100644
--- a/src/video_out/alphablend.c
+++ b/src/video_out/alphablend.c
@@ -1277,3 +1277,191 @@ void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
dst_y += dst_pitch;
}
}
+
+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;
+}
+
+void init_xx44_palette(xx44_palette_t *p, unsigned num_entries)
+{
+ p->size = (num_entries > XX44_PALETTE_SIZE) ? XX44_PALETTE_SIZE : num_entries;
+}
+
+void dispose_xx44_palette(xx44_palette_t *p)
+{
+}
+
+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)
+{
+ register int i;
+ register 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)
+{
+
+ register int i;
+ register uint32_t *cluts = p->cluts;
+ register 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) return p->lookup_cache[color] = i;
+ }
+
+ 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;
+ return p->lookup_cache[color] = p->max_used++;
+}
+
+static void memblend_xx44(uint8_t *mem,uint8_t val, register size_t size, uint8_t mask)
+{
+ register uint8_t masked_val = val & mask;
+
+ while(size--) {
+ if ((*mem & mask) <= masked_val ) *mem = val;
+ mem++;
+ }
+}
+
+void blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl,
+ int dst_width, int dst_height, int dst_pitch,
+ xx44_palette_t *palette,int ia44)
+{
+ int src_width = img_overl->width;
+ int src_height = img_overl->height;
+ rle_elem_t *rle = img_overl->rle;
+ rle_elem_t *rle_limit = rle + img_overl->num_rle;
+ int mask;
+ int x_off = img_overl->x;
+ int y_off = img_overl->y;
+ int x, y;
+ uint8_t norm_pixel,clip_pixel;
+ uint8_t *dst_y;
+ uint8_t *dst;
+ uint8_t alphamask = (ia44) ? 0x0F : 0xF0;
+ int clip_right;
+
+ if (!img_overl)
+ return;
+
+ dst_y = dst_img + dst_pitch*y_off + x_off;
+
+ if( (x_off + img_overl->width) < dst_width )
+ clip_right = img_overl->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 = !(img_overl->clip_top > y || img_overl->clip_bottom < y);
+ dst = dst_y;
+
+ for (x = 0; x < src_width;) {
+ int len = (x + rle->len > clip_right) ? clip_right -x + 1 : rle->len;
+
+ if (len > 0) {
+ norm_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color,
+ img_overl->color[rle->color]) << 4) |
+ (img_overl->trans[rle->color] & 0x0F));
+ clip_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color+OVL_PALETTE_SIZE,
+ img_overl->clip_color[rle->color]) << 4) |
+ (img_overl->clip_trans[rle->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 < img_overl->clip_left) {
+ if (x + len - 1 < img_overl->clip_left) {
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
+ } else {
+ memblend_xx44(dst,norm_pixel,img_overl->clip_left -x, alphamask);
+ dst += img_overl->clip_left - x;
+ len -= img_overl->clip_left - x;
+ if (len < img_overl->clip_right - img_overl->clip_left + 1) {
+ memblend_xx44(dst,clip_pixel,len, alphamask);
+ dst += len;
+ } else {
+ memblend_xx44(dst,clip_pixel,img_overl->clip_right - img_overl->clip_left +1,
+ alphamask);
+ dst += img_overl->clip_right - img_overl->clip_left +1;
+ len -= img_overl->clip_right - img_overl->clip_left +1;
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
+ }
+ }
+ } else if (x <= img_overl->clip_right) {
+ if (len < img_overl->clip_right - x + 1) {
+ memblend_xx44(dst,clip_pixel,len, alphamask);
+ dst += len;
+ } else {
+ memblend_xx44(dst,clip_pixel,img_overl->clip_right - x +1,alphamask);
+ dst += img_overl->clip_right - x +1;
+ len -= img_overl->clip_right - x +1;
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
+ }
+ } else {
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
+ }
+ } else {
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
+ }
+ }
+ x += rle->len;
+ rle++;
+ if (rle >= rle_limit) break;
+ }
+ if (rle >= rle_limit) break;
+ dst_y += dst_pitch;
+ }
+}
diff --git a/src/video_out/alphablend.h b/src/video_out/alphablend.h
index 974f363d8..dd7f799ea 100644
--- a/src/video_out/alphablend.h
+++ b/src/video_out/alphablend.h
@@ -53,10 +53,22 @@ typedef struct { /* CLUT == Color LookUp Table */
uint8_t foo : 8;
} ATTRIBUTE_PACKED clut_t;
+
#if PRAGMA_PACK
#pragma pack()
#endif
+#define XX44_PALETTE_SIZE 32
+
+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;
+
+
void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
int img_width, int img_height,
int dst_width, int dst_height);
@@ -75,4 +87,32 @@ void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
int dst_width, int dst_height, int dst_pitch);
+/*
+ * This function isn't too smart about blending. We want to avoid creating new
+ * colors in the palette as a result from two non-zero colors needed to be
+ * blended. Instead we choose the color with the highest alpha value to be
+ * visible. Some parts of the code taken from the "VeXP" project.
+ */
+
+void blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl,
+ int dst_width, int dst_height, int dst_pitch,
+ xx44_palette_t *palette,int ia44);
+
+/*
+ * Functions to handle the xine-specific palette.
+ */
+
+void clear_xx44_palette(xx44_palette_t *p);
+void init_xx44_palette(xx44_palette_t *p, unsigned num_entries);
+void dispose_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);
+
+
#endif
diff --git a/src/video_out/video_out_xvmc.c b/src/video_out/video_out_xvmc.c
index 6046910b4..8c2dee108 100644
--- a/src/video_out/video_out_xvmc.c
+++ b/src/video_out/video_out_xvmc.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out_xvmc.c,v 1.17 2004/09/22 20:29:17 miguelfreitas Exp $
+ * $Id: video_out_xvmc.c,v 1.18 2004/09/28 18:49:40 miguelfreitas Exp $
*
* video_out_xvmc.c, X11 video motion compensation extension interface for xine
*
@@ -70,6 +70,7 @@
#include "xine.h"
#include "video_out.h"
#include "xine_internal.h"
+#include "accel_xvmc.h"
/* TODO - delete these? */
#include "alphablend.h"
@@ -125,7 +126,7 @@ typedef struct {
/* temporary Xv only storage */
XvImage *image;
XShmSegmentInfo shminfo;
-
+ xine_xvmc_t xvmc_data;
} xvmc_frame_t;
@@ -494,7 +495,6 @@ static void xvmc_frame_dispose (vo_frame_t *vo_img) {
XFree (frame->image);
XUnlockDisplay (this->display);
}
-
free (frame);
}
@@ -577,6 +577,8 @@ static vo_frame_t *xvmc_alloc_frame (vo_driver_t *this_gen) {
if (!frame)
return NULL;
+ frame->vo_frame.accel_data = &frame->xvmc_data;
+
/* keep track of frames and how many frames alocated. */
this->frames[this->num_frame_buffers++] = frame;
@@ -590,8 +592,8 @@ static vo_frame_t *xvmc_alloc_frame (vo_driver_t *this_gen) {
frame->vo_frame.proc_frame = NULL;
frame->vo_frame.field = xvmc_frame_field;
frame->vo_frame.dispose = xvmc_frame_dispose;
- frame->vo_frame.proc_macro_block = xvmc_proc_macro_block;
frame->vo_frame.driver = this_gen;
+ frame->xvmc_data.proc_macro_block = xvmc_proc_macro_block;
return (vo_frame_t *) frame;
}
@@ -777,6 +779,7 @@ static void xvmc_update_frame_format (vo_driver_t *this_gen,
double ratio, int format, int flags) {
xvmc_driver_t *this = (xvmc_driver_t *) this_gen;
xvmc_frame_t *frame = (xvmc_frame_t *) frame_gen;
+ xine_xvmc_t *xvmc = (xine_xvmc_t *) frame_gen->accel_data;
lprintf ("xvmc_update_frame_format\n");
@@ -816,14 +819,16 @@ static void xvmc_update_frame_format (vo_driver_t *this_gen,
frame->ratio = ratio;
- frame->vo_frame.macroblocks = (xine_macroblocks_t *)&this->macroblocks;
+ xvmc->macroblocks = (xine_macroblocks_t *)&this->macroblocks;
if( flags & VO_NEW_SEQUENCE_FLAG ) {
xvmc_set_context (this, width, height, ratio, format, flags,
- frame->vo_frame.macroblocks);
+ xvmc->macroblocks);
}
+
this->macroblocks.num_blocks = 0;
this->macroblocks.macroblockptr = this->macroblocks.macroblockbaseptr;
this->macroblocks.xine_mc.blockptr = this->macroblocks.xine_mc.blockbaseptr;
+
}
static void xvmc_clean_output_area (xvmc_driver_t *this) {
diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c
new file mode 100644
index 000000000..98dc0db86
--- /dev/null
+++ b/src/video_out/video_out_xxmc.c
@@ -0,0 +1,2652 @@
+/*
+ * Copyright (C) 2000-2004 the xine project
+ * Copyright (C) 2004 the Unichrome project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: video_out_xxmc.c,v 1.1 2004/09/28 18:49:40 miguelfreitas Exp $
+ *
+ * video_out_xxmc.c, X11 decoding accelerated video extension interface for xine
+ *
+ * based on mpeg2dec code from
+ * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * Xv image support by Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de>
+ *
+ * overlay support by James Courtier-Dutton <James@superbug.demon.co.uk> - July 2001
+ * X11 unscaled overlay support by Miguel Freitas - Nov 2003
+ * XvMC VLD implementation by Thomas Hellström - August-Sep 2004
+ * XvMC merge by Thomas Hellström - Sep 2004
+ *
+ * Test IDCT
+ * Test VLD
+ */
+
+
+
+#include "xxmc.h"
+
+static int gX11Fail;
+static int xxmc_xvmc_update_context(xxmc_driver_t *driver,xxmc_frame_t *frame);
+static void dispose_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo,
+ XvImage *myimage);
+
+
+/*
+ * Acceleration level priority. Static for now. It may well turn out that IDCT
+ * is more efficient than VLD.
+ */
+
+static unsigned accel_priority[] = {
+#ifdef HAVE_VLDXVMC
+ XINE_XVMC_ACCEL_VLD,
+#endif
+ XINE_XVMC_ACCEL_IDCT,
+ XINE_XVMC_ACCEL_MOCOMP};
+#define NUM_ACCEL_PRIORITY (sizeof(accel_priority)/sizeof(accel_priority[0]))
+
+#ifndef XVMC_VLD
+ #define XVMC_VLD 0
+#endif
+
+/*
+ * 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;
+}
+
+static 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);
+#ifdef XVMC_THREAD_SAFE
+ c->num_readers++;
+ pthread_mutex_unlock(&c->mutex);
+#endif
+}
+
+void xvmc_context_reader_unlock(context_lock_t *c)
+{
+#ifdef XVMC_THREAD_SAFE
+ pthread_mutex_lock(&c->mutex);
+ if (c->num_readers > 0) {
+ if (--(c->num_readers) == 0) {
+ pthread_cond_broadcast(&c->cond);
+ }
+ }
+#endif
+ pthread_mutex_unlock(&c->mutex);
+}
+
+static void xvmc_context_writer_lock(context_lock_t *c)
+{
+ pthread_mutex_lock(&c->mutex);
+#ifdef XVMC_THREAD_SAFE
+ while(c->num_readers) {
+ pthread_cond_wait(&c->cond, &c->mutex);
+ }
+#endif
+}
+
+static void xvmc_context_writer_unlock(context_lock_t *c)
+{
+ pthread_mutex_unlock(&c->mutex);
+}
+
+/*
+ * A number of simple surface allocator functions that implements the
+ * notion that a surface may be invalid if it is asynchronously
+ * destroyed. Both surfaces and subpictures are handled this way.
+ */
+
+
+
+static void xxmc_xvmc_dump_surfaces(xxmc_driver_t *this )
+{
+ int
+ i;
+ xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
+
+ for (i=0; i<XVMC_MAX_SURFACES; ++i) {
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "%d %d;",handler->surfInUse[i],
+ handler->surfValid[i]);
+ }
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "\n");
+}
+
+static void xxmc_xvmc_dump_subpictures(xxmc_driver_t *this)
+{
+ int
+ i;
+ xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
+
+ for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) {
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "%d %d;",handler->subInUse[i],
+ handler->subValid[i]);
+ }
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "\n");
+}
+
+
+static void xxmc_xvmc_surface_handler_construct(xxmc_driver_t *this)
+{
+ int i;
+ xvmc_surface_handler_t *handler = &this->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_destroy_surfaces(xxmc_driver_t *this)
+{
+ int i;
+ xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
+
+ pthread_mutex_lock(&handler->mutex);
+ for (i=0; i < XVMC_MAX_SURFACES; ++i) {
+ XVMCLOCKDISPLAY( this->display );
+ if (handler->surfValid[i]) {
+ XvMCFlushSurface( this->display , handler->surfaces+i);
+ XvMCSyncSurface( this->display, handler->surfaces+i );
+ XvMCHideSurface( this->display, handler->surfaces+i );
+ XvMCDestroySurface( this->display, handler->surfaces+i );
+ }
+ XVMCUNLOCKDISPLAY( this->display );
+ handler->surfValid[i] = 0;
+ }
+ pthread_mutex_unlock(&handler->mutex);
+
+}
+
+static void xxmc_xvmc_destroy_subpictures(xxmc_driver_t *this)
+{
+ int i;
+ xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
+
+ pthread_mutex_lock(&handler->mutex);
+ for (i=0; i < XVMC_MAX_SUBPICTURES; ++i) {
+ XVMCLOCKDISPLAY( this->display );
+ if (handler->subValid[i]) {
+ XvMCFlushSubpicture( this->display , handler->subpictures+i);
+ XvMCSyncSubpicture( this->display, handler->subpictures+i );
+ XvMCDestroySubpicture( this->display, handler->subpictures+i );
+ }
+ XVMCUNLOCKDISPLAY( this->display );
+ handler->subValid[i] = 0;
+ }
+ pthread_mutex_unlock(&handler->mutex);
+}
+
+static XvMCSurface *xxmc_xvmc_alloc_surface(xxmc_driver_t *this,
+ XvMCContext *context)
+{
+ xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
+ int i;
+
+ pthread_mutex_lock(&handler->mutex);
+ xxmc_xvmc_dump_surfaces(this);
+ for (i=0; i<XVMC_MAX_SURFACES; ++i) {
+ if (handler->surfValid[i] && !handler->surfInUse[i]) {
+ handler->surfInUse[i] = 1;
+ xxmc_xvmc_dump_surfaces(this);
+ pthread_mutex_unlock(&handler->mutex);
+ return handler->surfaces + i;
+ }
+ }
+ for (i=0; i<XVMC_MAX_SURFACES; ++i) {
+ if (!handler->surfInUse[i]) {
+ XVMCLOCKDISPLAY( this->display );
+ if (Success != XvMCCreateSurface( this->display, context,
+ handler->surfaces + i)) {
+ XVMCUNLOCKDISPLAY( this->display );
+ pthread_mutex_unlock(&handler->mutex);
+ return NULL;
+ }
+ XVMCUNLOCKDISPLAY( this->display );
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Created surface %d\n",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;
+}
+
+static void xxmc_xvmc_free_surface(xxmc_driver_t *this, XvMCSurface *surf)
+{
+ xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
+ unsigned
+ index = surf - handler->surfaces;
+
+ if (index >= XVMC_MAX_SURFACES) return;
+ pthread_mutex_lock(&handler->mutex);
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Disposing of surface %d\n",index);
+ handler->surfInUse[index]--;
+ xxmc_xvmc_dump_surfaces(this);
+ pthread_mutex_unlock(&handler->mutex);
+}
+
+int xxmc_xvmc_surface_valid(xxmc_driver_t *this, XvMCSurface *surf)
+{
+ xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
+ unsigned
+ 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 XvMCSubpicture *xxmc_xvmc_alloc_subpicture
+ (xxmc_driver_t *this,
+ XvMCContext *context, unsigned short width,
+ unsigned short height, int xvimage_id)
+{
+ int i;
+ xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
+ int status;
+
+ pthread_mutex_lock(&handler->mutex);
+ xxmc_xvmc_dump_subpictures(this);
+ for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) {
+ if (handler->subValid[i] && !handler->subInUse[i]) {
+ XVMCLOCKDISPLAY( this->display );
+ if (XvMCGetSubpictureStatus( this->display, handler->subpictures + i,
+ &status)) {
+ XVMCUNLOCKDISPLAY( this->display );
+ continue;
+ }
+ XVMCUNLOCKDISPLAY( this->display );
+ if (status & XVMC_DISPLAYING)
+ continue;
+ handler->subInUse[i] = 1;
+ xxmc_xvmc_dump_subpictures(this);
+ pthread_mutex_unlock(&handler->mutex);
+ return handler->subpictures + i;
+ }
+ }
+ for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) {
+ if (!handler->subInUse[i]) {
+ XVMCLOCKDISPLAY( this->display );
+ if (Success != XvMCCreateSubpicture( this->display, context,
+ handler->subpictures + i,
+ width, height, xvimage_id)) {
+ XVMCUNLOCKDISPLAY( this->display );
+ pthread_mutex_unlock(&handler->mutex);
+ return NULL;
+ }
+ XVMCUNLOCKDISPLAY( this->display );
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "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;
+}
+
+static void xxmc_xvmc_free_subpicture(xxmc_driver_t *this, XvMCSubpicture *sub)
+{
+
+ xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
+ unsigned
+ index = sub - handler->subpictures;
+
+ if (index >= XVMC_MAX_SUBPICTURES) return;
+ pthread_mutex_lock(&handler->mutex);
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Disposing of subpicture %d\n",index);
+ handler->subInUse[index] = 0;
+ xxmc_xvmc_dump_subpictures(this);
+ pthread_mutex_unlock(&handler->mutex);
+
+}
+
+/*
+ * Here follows a number of callback function.
+ */
+
+
+/*
+ * Callback function for the VO-loop to duplicate frame data.
+ */
+
+
+static void xxmc_duplicate_frame_data(vo_frame_t *this_gen,
+ vo_frame_t *original)
+{
+ xxmc_frame_t *this = (xxmc_frame_t *) this_gen,
+ *orig = (xxmc_frame_t *) original;
+ xxmc_driver_t *driver = (xxmc_driver_t *) this_gen->driver;
+ xine_t *xine = driver->xine;
+ xine_xxmc_t *xxmc;
+ XvMCSubpicture *tmp;
+ int need_dummy;
+
+ if (original->format == XINE_IMGFMT_XXMC) {
+ xxmc = &orig->xxmc_data;
+ switch(xxmc->format) {
+ case XINE_IMGFMT_YV12:
+ yv12_to_yv12( original->base[0], original->pitches[0],
+ this_gen->base[0], this_gen->pitches[0],
+ original->base[1], original->pitches[1],
+ this_gen->base[1], this_gen->pitches[1],
+ original->base[2], original->pitches[2],
+ this_gen->base[2], this_gen->pitches[2],
+ this_gen->width, this_gen->height);
+ xprintf(xine, XINE_VERBOSITY_DEBUG, "Duplicate Frame YV12.\n");
+ break;
+ case XINE_IMGFMT_XXMC:
+ xvmc_context_writer_lock( &driver->xvmc_lock);
+ if (!xxmc_xvmc_surface_valid(driver,orig->xvmc_surf)) {
+ xvmc_context_writer_unlock( &driver->xvmc_lock );
+ return;
+ }
+ this->xxmc_data = *xxmc;
+ this->width = original->width;
+ this->height = original->height;
+ if (! xxmc_xvmc_update_context(driver,this) ) {
+ xvmc_context_writer_unlock( &driver->xvmc_lock );
+ return;
+ }
+ xvmc_context_writer_unlock( &driver->xvmc_lock );
+ xvmc_context_reader_lock( &driver->xvmc_lock );
+ if (!xxmc_xvmc_surface_valid(driver,orig->xvmc_surf) ||
+ !xxmc_xvmc_surface_valid(driver,this->xvmc_surf)) {
+ xvmc_context_reader_unlock( &driver->xvmc_lock );
+ return;
+ }
+
+ /*
+ * Allocate a dummy subpicture and copy using
+ * XvMCBlendsubpicture2. VLD implementations can do blending with a
+ * NULL subpicture. Use that if possible.
+ */
+
+ need_dummy = (xxmc->acceleration != XINE_XVMC_ACCEL_VLD);
+ tmp = NULL;
+ if (need_dummy) {
+ tmp = xxmc_xvmc_alloc_subpicture( driver, &driver->context,
+ this->width, this->height,
+ driver->xvmc_cap
+ [driver->xvmc_cur_cap].subPicType.id);
+ }
+ if (tmp || !need_dummy) {
+ XVMCLOCKDISPLAY( driver->display );
+ if (tmp) XvMCClearSubpicture(driver->display, tmp , 0,0, this->width,
+ this->height, 0);
+ if (Success == XvMCBlendSubpicture2( driver->display, orig->xvmc_surf,
+ this->xvmc_surf, tmp,
+ 0,0,this->width, this->height,
+ 0,0,this->width, this->height)) {
+ this->xxmc_data.decoded = 1;
+ }
+ XVMCUNLOCKDISPLAY( driver->display );
+ if (tmp) xxmc_xvmc_free_subpicture( driver, tmp);
+ }
+
+ xvmc_context_reader_unlock( &driver->xvmc_lock );
+ xprintf(xine, XINE_VERBOSITY_DEBUG, "Duplicated XvMC frame %d %d.\n",
+ this->width,this->height);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+
+static uint32_t xxmc_get_capabilities (vo_driver_t *this_gen) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ return this->capabilities;
+}
+
+
+static void xxmc_frame_field (vo_frame_t *vo_img, int which_field)
+{
+ xxmc_driver_t *this = (xxmc_driver_t *) vo_img->driver;
+
+
+ lprintf ("xvmc_frame_field\n");
+ if (this->xvmc_cap) {
+ if (this->xvmc_accel & (XINE_XVMC_ACCEL_IDCT | XINE_XVMC_ACCEL_MOCOMP)) {
+ this->macroblocks.num_blocks = 0;
+ this->macroblocks.macroblockptr = this->macroblocks.macroblockbaseptr;
+ this->macroblocks.xine_mc.blockptr = this->macroblocks.xine_mc.blockbaseptr;
+ }
+ }
+}
+
+static void xxmc_frame_dispose (vo_frame_t *vo_img) {
+ xxmc_frame_t *frame = (xxmc_frame_t *) vo_img ;
+ xxmc_driver_t *this = (xxmc_driver_t *) vo_img->driver;
+
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "Disposing of frame\n");
+
+ if (this->xvmc_cap && frame->xvmc_surf) {
+ xxmc_xvmc_free_surface( this, frame->xvmc_surf );
+ frame->xvmc_surf = 0;
+ }
+
+ if (frame->image) {
+
+ if (this->use_shm) {
+ XLockDisplay (this->display);
+ XShmDetach (this->display, &frame->shminfo);
+ XFree (frame->image);
+ XUnlockDisplay (this->display);
+
+ shmdt (frame->shminfo.shmaddr);
+ shmctl (frame->shminfo.shmid, IPC_RMID, NULL);
+ }
+ else {
+ if (frame->image->data) free(frame->image->data);
+ XLockDisplay (this->display);
+ XFree (frame->image);
+ XUnlockDisplay (this->display);
+ }
+ }
+ free (frame);
+}
+
+/*
+ * Note that this one does NOT allocate the XvMC surface. That is
+ * done by an additional decoder callback.
+ */
+
+static vo_frame_t *xxmc_alloc_frame (vo_driver_t *this_gen) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+ xxmc_frame_t *frame ;
+
+ frame = (xxmc_frame_t *) xine_xmalloc (sizeof (xxmc_frame_t));
+ if (!frame)
+ return NULL;
+
+ pthread_mutex_init (&frame->vo_frame.mutex, NULL);
+ frame->xvmc_surf = NULL;
+
+ /*
+ * supply required functions
+ */
+
+ frame->vo_frame.proc_slice = NULL;
+ frame->vo_frame.proc_frame = NULL;
+ frame->vo_frame.proc_duplicate_frame_data = NULL;
+ frame->vo_frame.field = xxmc_frame_field;
+ frame->vo_frame.dispose = xxmc_frame_dispose;
+ frame->vo_frame.driver = this_gen;
+
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "Allocating frame\n");
+
+ return (vo_frame_t *) frame;
+}
+
+static int HandleXError (Display *display, XErrorEvent *xevent) {
+ char str [1024];
+
+ XGetErrorText (display, xevent->error_code, str, 1024);
+ printf ("received X error event: %s\n", str);
+ gX11Fail = 1;
+
+ return 0;
+}
+
+/* called xlocked */
+static void x11_InstallXErrorHandler (xxmc_driver_t *this) {
+ this->x11_old_error_handler = XSetErrorHandler (HandleXError);
+ XSync(this->display, False);
+}
+
+/* called xlocked */
+static void x11_DeInstallXErrorHandler (xxmc_driver_t *this) {
+ XSetErrorHandler (this->x11_old_error_handler);
+ XSync(this->display, False);
+ this->x11_old_error_handler = NULL;
+}
+
+/* called xlocked */
+static XvImage *create_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo,
+ int width, int height, int format) {
+ unsigned int xv_format;
+ XvImage *image = NULL;
+
+ if (this->use_pitch_alignment) {
+ width = (width + 7) & ~0x7;
+ }
+
+ switch (format) {
+ case XINE_IMGFMT_YV12:
+ case XINE_IMGFMT_XXMC:
+ xv_format = this->xv_format_yv12;
+ break;
+ case XINE_IMGFMT_YUY2:
+ xv_format = this->xv_format_yuy2;
+ break;
+ case FOURCC_IA44:
+ case FOURCC_AI44:
+ xv_format = format;
+ break;
+ default:
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "create_ximage: unknown format %08x\n",format);
+ _x_abort();
+ }
+
+ if (this->use_shm) {
+
+ /*
+ * try shm
+ */
+
+ gX11Fail = 0;
+ x11_InstallXErrorHandler (this);
+
+ image = XvShmCreateImage(this->display, this->xv_port, xv_format, 0,
+ width, height, shminfo);
+
+ if (image == NULL ) {
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_xxmc: XvShmCreateImage failed\n"
+ "video_out_xxmc: => not using MIT Shared Memory extension.\n"));
+ this->use_shm = 0;
+ goto finishShmTesting;
+ }
+
+ shminfo->shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777);
+
+ if (image->data_size==0) {
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_xxmc: XvShmCreateImage returned a zero size\n"
+ "video_out_xxmc: => not using MIT Shared Memory extension.\n"));
+ this->use_shm = 0;
+ goto finishShmTesting;
+ }
+
+ if (shminfo->shmid < 0 ) {
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_xxmc: shared memory error in shmget: %s\n"
+ "video_out_xxmc: => not using MIT Shared Memory extension.\n"), strerror(errno));
+ this->use_shm = 0;
+ goto finishShmTesting;
+ }
+
+ shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
+
+ if (shminfo->shmaddr == NULL) {
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: shared memory error (address error NULL)\n");
+ this->use_shm = 0;
+ goto finishShmTesting;
+ }
+
+ if (shminfo->shmaddr == ((char *) -1)) {
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: shared memory error (address error)\n");
+ this->use_shm = 0;
+ goto finishShmTesting;
+ }
+
+ shminfo->readOnly = False;
+ image->data = shminfo->shmaddr;
+
+ XShmAttach(this->display, shminfo);
+
+ XSync(this->display, False);
+ shmctl(shminfo->shmid, IPC_RMID, 0);
+
+ if (gX11Fail) {
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_xxmc: x11 error during shared memory XImage creation\n"
+ "video_out_xxmc: => not using MIT Shared Memory extension.\n"));
+ shmdt (shminfo->shmaddr);
+ shmctl (shminfo->shmid, IPC_RMID, 0);
+ shminfo->shmid = -1;
+ this->use_shm = 0;
+ goto finishShmTesting;
+ }
+
+ /*
+ * Now that the Xserver has learned about and attached to the
+ * shared memory segment, delete it. It's actually deleted by
+ * the kernel when all users of that segment have detached from
+ * it. Gives an automatic shared memory cleanup in case we crash.
+ */
+ shmctl (shminfo->shmid, IPC_RMID, 0);
+ shminfo->shmid = -1;
+
+ finishShmTesting:
+ x11_DeInstallXErrorHandler(this);
+ }
+
+
+ /*
+ * fall back to plain Xv if necessary
+ */
+
+ if (!this->use_shm) {
+ char *data;
+
+ switch (format) {
+ case XINE_IMGFMT_YV12:
+ case XINE_IMGFMT_XXMC:
+ data = malloc (width * height * 3/2);
+ break;
+ case XINE_IMGFMT_YUY2:
+ data = malloc (width * height * 2);
+ break;
+ case FOURCC_IA44:
+ case FOURCC_AI44:
+ data = malloc (width * height);
+ break;
+ default:
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "create_ximage: unknown format %08x\n",format);
+ _x_abort();
+ }
+
+ image = XvCreateImage (this->display, this->xv_port,
+ xv_format, data, width, height);
+ }
+ return image;
+}
+
+
+/*
+ * Utility functions for the main update surface callback.
+ */
+
+
+static void xxmc_dispose_context(xxmc_driver_t *driver)
+{
+ if (driver->contextActive) {
+
+ if (driver->xvmc_accel & (XINE_XVMC_ACCEL_MOCOMP | XINE_XVMC_ACCEL_IDCT)) {
+ xvmc_macroblocks_t *macroblocks = &driver->macroblocks;
+
+ XvMCDestroyMacroBlocks( driver->display, &macroblocks->macro_blocks );
+ XvMCDestroyBlocks( driver->display , &macroblocks->blocks );
+ }
+
+ xprintf(driver->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: Freeing up XvMC Surfaces and subpictures.\n");
+ if (driver->xvmc_palette) free(driver->xvmc_palette);
+ dispose_xx44_palette( &driver->palette );
+ xxmc_xvmc_destroy_subpictures( driver );
+ xxmc_xvmc_destroy_surfaces( driver );
+ xprintf(driver->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: Freeing up XvMC Context.\n");
+ XLockDisplay (driver->display);
+ if (driver->subImage)
+ dispose_ximage(driver, &driver->subShmInfo, driver->subImage);
+ driver->subImage = NULL;
+ XUnlockDisplay (driver->display);
+ XVMCLOCKDISPLAY( driver->display );
+ XvMCDestroyContext( driver->display, &driver->context);
+ XVMCUNLOCKDISPLAY( driver->display );
+ driver->contextActive = 0;
+ driver->hwSubpictures = 0;
+ }
+}
+
+static int xxmc_find_context(xxmc_driver_t *driver, xine_xxmc_t *xxmc,
+ unsigned width, unsigned height)
+{
+ int i,k,found;
+ xvmc_capabilities_t *curCap;
+ unsigned request_mpeg_flags, request_accel_flags;
+
+ request_mpeg_flags = xxmc->mpeg;
+ found = 0;
+
+ for (k = 0; k < NUM_ACCEL_PRIORITY; ++k) {
+ request_accel_flags = xxmc->acceleration & accel_priority[k];
+ if (!request_accel_flags) continue;
+
+ curCap = driver->xvmc_cap;
+ for (i =0; i < driver->xvmc_num_cap; ++i) {
+ xprintf(driver->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: Surface type %d. Capabilities 0x%8x 0x%8x\n",i,
+ curCap->mpeg_flags,curCap->accel_flags);
+ xprintf(driver->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: Requests: 0x%8x 0x%8x\n",
+ 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 = 1;
+ break;
+ }
+ curCap++;
+ }
+ if ( found ) {
+ driver->xvmc_cur_cap = i;
+ break;
+ }
+ }
+ if ( found ) {
+ driver->xvmc_accel = request_accel_flags;
+ return 1;
+ }
+ driver->xvmc_accel = 0;
+ return 0;
+}
+
+static int xxmc_create_context(xxmc_driver_t *driver, unsigned width, unsigned height)
+{
+ xvmc_capabilities_t *curCap;
+
+ curCap = driver->xvmc_cap + driver->xvmc_cur_cap;
+ xprintf(driver->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: Creating new XvMC Context\n");
+ XVMCLOCKDISPLAY( driver->display );
+ if (Success == XvMCCreateContext( driver->display, driver->xv_port,
+ curCap->type_id, width,
+ height, driver->context_flags,
+ &driver->context)) {
+ driver->xvmc_mpeg = curCap->mpeg_flags;
+ driver->xvmc_width = width;
+ driver->xvmc_height = height;
+ driver->contextActive = 1;
+ }
+ XVMCUNLOCKDISPLAY( driver->display );
+ return driver->contextActive;
+}
+
+static void xxmc_setup_subpictures(xxmc_driver_t *driver, unsigned width, unsigned height)
+{
+ xvmc_capabilities_t *curCap;
+ XvMCSubpicture *sp;
+
+ if (driver->contextActive) {
+
+ /*
+ * Determine if we can use hardware subpictures, and in that case, set up an
+ * XvImage that we can use for blending.
+ */
+ curCap = driver->xvmc_cap + driver->xvmc_cur_cap;
+
+ if ((width > curCap->sub_max_width) ||
+ (height > curCap->sub_max_height)) return;
+
+ if ((driver->xvmc_backend_subpic = (curCap->flags & XVMC_BACKEND_SUBPICTURE)))
+ xprintf(driver->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: Using Backend subpictures.\n");
+
+ if (!driver->subImage) {
+ /*
+ * Note: If other image formats than xx44 are to be used here, they must be
+ * translated to XINE_IMGFMT_XXX, since that is what create_ximage
+ * expects.
+ */
+
+ XLockDisplay (driver->display);
+
+ driver->subImage =
+ create_ximage(driver, &driver->subShmInfo, width, height, curCap->subPicType.id);
+ XUnlockDisplay (driver->display);
+ if (NULL == driver->subImage) {
+ xprintf(driver->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: Failed allocating XvImage for supbictures.\n");
+ return;
+ }
+ }
+
+ sp = xxmc_xvmc_alloc_subpicture( driver, &driver->context, width,
+ height, curCap->subPicType.id);
+ if (sp == NULL) return;
+
+ init_xx44_palette( &driver->palette, sp->num_palette_entries);
+ driver->xvmc_palette = (char *) xine_xmalloc(sp->num_palette_entries
+ * sp->entry_bytes);
+ xxmc_xvmc_free_subpicture( driver, sp);
+ if (driver->xvmc_palette == NULL) return;
+ driver->hwSubpictures = 1;
+ }
+}
+
+static int xxmc_mocomp_create_macroblocks(xxmc_driver_t *driver,
+ xxmc_frame_t *frame,
+ int slices)
+{
+ Status ret;
+ xvmc_macroblocks_t *macroblocks = &driver->macroblocks;
+ xine_xxmc_t *xxmc = (xine_xxmc_t *) frame->vo_frame.accel_data;
+
+ slices = (slices * driver->xvmc_width) / 16;
+ ret = XvMCCreateMacroBlocks(driver->display, &driver->context, slices,
+ &macroblocks->macro_blocks);
+ if (ret) return 0;
+ ret = XvMCCreateBlocks(driver->display, &driver->context, slices*6,
+ &macroblocks->blocks);
+ if (ret) return 0;
+
+ macroblocks->xine_mc.blockbaseptr = macroblocks->blocks.blocks;
+ macroblocks->xine_mc.blockptr = macroblocks->xine_mc.blockbaseptr;
+ macroblocks->num_blocks = 0;
+ macroblocks->macroblockbaseptr = macroblocks->macro_blocks.macro_blocks;
+ macroblocks->macroblockptr = macroblocks->macroblockbaseptr;
+ macroblocks->slices = slices;
+ xxmc->xvmc.macroblocks = (xine_macroblocks_t *)macroblocks;
+
+ return 1;
+}
+
+static void xvmc_check_colorkey_properties(xxmc_driver_t *driver)
+{
+ int num,i;
+ XvAttribute *xvmc_attributes;
+ Atom ap;
+
+ /*
+ * Determine if the context is of "Overlay" type. If so,
+ * check whether we can autopaint.
+ */
+
+ driver->have_xvmc_autopaint = 0;
+ if (driver->context_flags & XVMC_OVERLAID_SURFACE) {
+ XVMCLOCKDISPLAY( driver->display );
+ xvmc_attributes = XvMCQueryAttributes( driver->display,
+ &driver->context,
+ &num);
+ if (xvmc_attributes) {
+ for (i=0; i<num; ++i) {
+ if (strcmp("XV_AUTOPAINT_COLORKEY", xvmc_attributes[i].name) == 0) {
+ ap = XInternAtom (driver->display, "XV_AUTOPAINT_COLORKEY", False);
+ XvMCSetAttribute(driver->display, &driver->context,ap,
+ driver->props[VO_PROP_AUTOPAINT_COLORKEY].value);
+ driver->have_xvmc_autopaint = 1;
+ }
+ }
+ }
+ XFree(xvmc_attributes);
+ XVMCUNLOCKDISPLAY( driver->display );
+
+ /*
+ * If we have a shape overlay, switch to colorkey since we have a
+ * colorkey overlay.
+ */
+
+ if ( driver->xoverlay ) {
+ if ( !driver->xoverlay_ck) {
+ XLockDisplay( driver->display );
+ x11osd_destroy( driver->xoverlay );
+ driver->xoverlay = x11osd_create( driver->xine, driver->display,
+ driver->screen, driver->drawable,
+ X11OSD_COLORKEY);
+ if ( driver->xoverlay ) {
+ x11osd_colorkey( driver->xoverlay, driver->colorkey, &driver->sc);
+ driver->xoverlay_ck = 1;
+ }
+ }
+ }
+ } else {
+
+ /*
+ * Not a colorkey overlay. Swith to shape.
+ */
+
+ if ( driver->xoverlay ) {
+ if ( driver->xoverlay_ck ) {
+ XLockDisplay( driver->display );
+ x11osd_destroy( driver->xoverlay );
+ driver->xoverlay = x11osd_create( driver->xine, driver->display,
+ driver->screen, driver->drawable,
+ X11OSD_SHAPED);
+ driver->xoverlay_ck = 0;
+ }
+ }
+ }
+}
+
+
+static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame)
+{
+ xine_xxmc_t *xxmc = &frame->xxmc_data;
+
+ /*
+ * Are we at all capable of doing XvMC ?
+ */
+
+ if (driver->xvmc_cap == 0 || frame->format != XINE_IMGFMT_XXMC)
+ return 0;
+
+ /*
+ * Determine if we have to change context.
+ */
+
+ if (((frame->width != driver->xvmc_width) ||
+ (frame->height != driver->xvmc_height) ||
+ (xxmc->mpeg != driver->xvmc_mpeg))) {
+
+
+ xprintf(driver->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: New format. Need to change XvMC Context.\n"
+ "width: %d height: %d mpeg: %d acceleration: %d\n", frame->width, frame->height,
+ xxmc->mpeg, xxmc->acceleration);
+
+ if (frame->xvmc_surf)
+ xxmc_xvmc_free_surface( driver , frame->xvmc_surf);
+ frame->xvmc_surf = NULL;
+
+
+ xxmc_dispose_context( driver );
+
+ if (xxmc_find_context( driver, xxmc, frame->width, frame->height )) {
+ xxmc_create_context( driver, frame->width, frame->height);
+ xvmc_check_colorkey_properties( driver );
+ xxmc_setup_subpictures(driver, frame->width, frame->height);
+ if ((driver->xvmc_accel & (XINE_XVMC_ACCEL_MOCOMP | XINE_XVMC_ACCEL_IDCT))) {
+ if (!xxmc_mocomp_create_macroblocks(driver, frame, 1)) {
+ lprintf("video_out_xxmc: ERROR: Macroblock allocation failed\n");
+ xxmc_dispose_context( driver );
+ }
+ }
+ }
+
+ if (!driver->contextActive) {
+ printf("video_out_xxmc: Using software decoding for this stream.\n");
+ driver->xvmc_accel = 0;
+ } else {
+ printf("video_out_xxmc: Using hardware decoding for this stream.\n");
+ }
+ }
+
+ /*
+ * 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 (frame->xvmc_surf) {
+ if (! xxmc_xvmc_surface_valid( driver, frame->xvmc_surf )) {
+ xxmc_xvmc_free_surface(driver , frame->xvmc_surf);
+ frame->xvmc_surf = NULL;
+ }
+ }
+
+ /*
+ * If it is NULL, check that we have a valid XvMC context, and in that case,
+ * create a new surface.
+ */
+
+ if ((frame->xvmc_surf == NULL) && (driver->contextActive) ) {
+ if (NULL == (frame->xvmc_surf =
+ xxmc_xvmc_alloc_surface( driver, &driver->context))) {
+ printf("video_out_xxmc: ERROR: Accelerated surface allocation failed.\n"
+ "video_out_xxmc: You are probably out of framebuffer memory.\n"
+ "video_out_xxmc: Falling back to software decoding.\n");
+
+ driver->xvmc_accel = 0;
+ xxmc_dispose_context( driver );
+ }
+ }
+
+
+ driver->xvmc_mpeg = xxmc->mpeg;
+ driver->xvmc_width = frame->width;
+ driver->xvmc_height = frame->height;
+ return driver->contextActive;
+}
+
+
+/*
+ * This one is called by the decoder to tell us what type of
+ * XxMC image format it really want to use. It could be either an
+ * XvMC format or an Xv format. This allows us to handle different
+ * stream format accelerations such as mpeg2, mpeg4, mpeg1 etc. at
+ * the same time as we can handle IDCT, MOCOMP, VLD. etc. For un-
+ * supported XvMC formats, we just fall back to YV12.
+ */
+
+static void xxmc_update_xxmc(vo_frame_t *vo_img) {
+
+ xxmc_frame_t *frame = (xxmc_frame_t *) vo_img;
+ xxmc_driver_t *driver = (xxmc_driver_t *) frame->vo_frame.driver;
+ xine_xxmc_t *xxmc = &frame->xxmc_data;
+
+ xvmc_context_writer_lock( &driver->xvmc_lock);
+ if (xxmc->format == XINE_IMGFMT_XXMC) {
+
+ /*
+ * Check if we can find a suitable context for what the
+ * decoder plugin wants! Otherwise, fall back to YV12.
+ */
+
+ if (! xxmc_xvmc_update_context(driver, frame)) {
+
+ /*
+ * Either no suitable context was found or an XvMC error occured.
+ */
+
+ xxmc->format = XINE_IMGFMT_YV12;
+ xxmc->acceleration = 0;
+ xxmc->xvmc.macroblocks = 0;
+ } else {
+
+ /*
+ * We're running accelerated.
+ */
+
+ xxmc->format = XINE_IMGFMT_XXMC;
+ xxmc->acceleration = driver->xvmc_accel;
+ xxmc->xvmc.macroblocks = (xine_macroblocks_t *) &driver->macroblocks;
+ switch(driver->xvmc_accel) {
+ case XINE_XVMC_ACCEL_IDCT:
+ xxmc->xvmc.macroblocks->xvmc_accel = XINE_VO_IDCT_ACCEL;
+ break;
+ case XINE_XVMC_ACCEL_MOCOMP:
+ xxmc->xvmc.macroblocks->xvmc_accel = XINE_VO_MOTION_ACCEL;
+ break;
+ default:
+ xxmc->xvmc.macroblocks->xvmc_accel = 0;
+ }
+ }
+ xxmc->decoded = 0;
+ }
+ xvmc_context_writer_unlock( &driver->xvmc_lock);
+}
+
+/* called xlocked */
+static void dispose_ximage (xxmc_driver_t *this,
+ XShmSegmentInfo *shminfo,
+ XvImage *myimage) {
+
+ if (this->use_shm) {
+
+ XShmDetach (this->display, shminfo);
+ XFree (myimage);
+ shmdt (shminfo->shmaddr);
+ if (shminfo->shmid >= 0) {
+ shmctl (shminfo->shmid, IPC_RMID, 0);
+ shminfo->shmid = -1;
+ }
+
+ }
+ else {
+ if (myimage->data) free(myimage->data);
+ XFree (myimage);
+ }
+
+}
+
+/*
+ * Just fills in functions. Surface and context updates are not done here.
+ */
+
+
+static void xxmc_update_frame_format (vo_driver_t *this_gen,
+ vo_frame_t *frame_gen,
+ uint32_t width, uint32_t height,
+ double ratio, int format, int flags) {
+
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+ xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen;
+
+ if ( XINE_IMGFMT_XXMC == format ) {
+ frame->xxmc_data.proc_xxmc_frame = xxmc_update_xxmc;
+ frame->xxmc_data.proc_xxmc_flush = xvmc_vld_flush;
+#ifdef HAVE_VLDXVMC
+ frame->xxmc_data.proc_xxmc_begin = xvmc_vld_frame;
+ frame->xxmc_data.proc_xxmc_slice = xvmc_vld_slice;
+#endif
+ frame->xxmc_data.xvmc.proc_macro_block = xxmc_xvmc_proc_macro_block;
+ frame->vo_frame.accel_data = &frame->xxmc_data;
+ frame->vo_frame.proc_duplicate_frame_data = xxmc_duplicate_frame_data;
+ } else {
+ frame->vo_frame.accel_data = &frame->xxmc_data;
+ frame->xxmc_data.format = format;
+ }
+
+ if (this->use_pitch_alignment) {
+ width = (width + 7) & ~0x7;
+ }
+
+ if ((frame->width != width)
+ || (frame->height != height)
+ || (frame->format != format)) {
+
+ XLockDisplay (this->display);
+
+ /*
+ * (re-) allocate xvimage
+ */
+
+ if (frame->image) {
+ dispose_ximage (this, &frame->shminfo, frame->image);
+ frame->image = NULL;
+ }
+
+ frame->image = create_ximage (this, &frame->shminfo, width, height, format);
+
+ if(format == XINE_IMGFMT_YUY2) {
+ frame->vo_frame.pitches[0] = frame->image->pitches[0];
+ frame->vo_frame.base[0] = frame->image->data + frame->image->offsets[0];
+ }
+ else {
+ frame->vo_frame.pitches[0] = frame->image->pitches[0];
+ frame->vo_frame.pitches[1] = frame->image->pitches[2];
+ frame->vo_frame.pitches[2] = frame->image->pitches[1];
+ frame->vo_frame.base[0] = frame->image->data + frame->image->offsets[0];
+ frame->vo_frame.base[1] = frame->image->data + frame->image->offsets[2];
+ frame->vo_frame.base[2] = frame->image->data + frame->image->offsets[1];
+ }
+
+ frame->width = width;
+ frame->height = height;
+ frame->format = format;
+
+ XUnlockDisplay (this->display);
+ }
+ frame->ratio = ratio;
+}
+
+/*
+ * From Xv.
+ */
+
+
+#define DEINTERLACE_CROMA
+static void xxmc_deinterlace_frame (xxmc_driver_t *this) {
+ uint8_t *recent_bitmaps[VO_NUM_RECENT_FRAMES];
+ xxmc_frame_t *frame = this->recent_frames[0];
+ int i;
+ int xvscaling;
+
+ xvscaling = (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) ? 2 : 1;
+
+ if (!this->deinterlace_frame.image
+ || (frame->width != this->deinterlace_frame.width)
+ || (frame->height != this->deinterlace_frame.height )
+ || (frame->format != this->deinterlace_frame.format)
+ || (frame->ratio != this->deinterlace_frame.ratio)) {
+ XLockDisplay (this->display);
+
+ if(this->deinterlace_frame.image)
+ dispose_ximage (this, &this->deinterlace_frame.shminfo,
+ this->deinterlace_frame.image);
+
+ this->deinterlace_frame.image = create_ximage (this, &this->deinterlace_frame.shminfo,
+ frame->width,frame->height / xvscaling,
+ frame->format);
+ this->deinterlace_frame.width = frame->width;
+ this->deinterlace_frame.height = frame->height;
+ this->deinterlace_frame.format = frame->format;
+ this->deinterlace_frame.ratio = frame->ratio;
+
+ XUnlockDisplay (this->display);
+ }
+
+
+ if ( this->deinterlace_method != DEINTERLACE_ONEFIELDXV ) {
+#ifdef DEINTERLACE_CROMA
+
+ /* I don't think this is the right way to do it (deinterlacing croma by croma info).
+ DScaler deinterlaces croma together with luma, but it's easier for them because
+ they have that components 1:1 at the same table.
+ */
+ for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ )
+ if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width &&
+ this->recent_frames[i]->height == frame->height )
+ recent_bitmaps[i] = this->recent_frames[i]->image->data + frame->width*frame->height;
+ else
+ recent_bitmaps[i] = NULL;
+
+ deinterlace_yuv( this->deinterlace_frame.image->data+frame->width*frame->height,
+ recent_bitmaps, frame->width/2, frame->height/2, this->deinterlace_method );
+ for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ )
+ if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width &&
+ this->recent_frames[i]->height == frame->height )
+ recent_bitmaps[i] = this->recent_frames[i]->image->data + frame->width*frame->height*5/4;
+ else
+ recent_bitmaps[i] = NULL;
+
+ deinterlace_yuv( this->deinterlace_frame.image->data+frame->width*frame->height*5/4,
+ recent_bitmaps, frame->width/2, frame->height/2, this->deinterlace_method );
+
+#else
+
+ /* know bug: we are not deinterlacing Cb and Cr */
+ xine_fast_memcpy(this->deinterlace_frame.image->data + frame->width*frame->height,
+ frame->image->data + frame->width*frame->height,
+ frame->width*frame->height*1/2);
+
+#endif
+
+ for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ )
+ if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width &&
+ this->recent_frames[i]->height == frame->height )
+ recent_bitmaps[i] = this->recent_frames[i]->image->data;
+ else
+ recent_bitmaps[i] = NULL;
+
+ deinterlace_yuv( this->deinterlace_frame.image->data, recent_bitmaps,
+ frame->width, frame->height, this->deinterlace_method );
+ }
+ else {
+ /*
+ dirty and cheap deinterlace method: we give half of the lines to xv
+ driver and let it scale for us.
+ note that memcpy's below don't seem to impact much on performance,
+ specially when fast memcpys are available.
+ */
+ uint8_t *dst, *src;
+
+ dst = this->deinterlace_frame.image->data;
+ src = this->recent_frames[0]->image->data;
+ for( i = 0; i < frame->height; i+=2 ) {
+ xine_fast_memcpy(dst,src,frame->width);
+ dst += frame->width;
+ src += 2 * frame->width;
+ }
+
+ dst = this->deinterlace_frame.image->data + frame->width * frame->height / 2;
+ src = this->recent_frames[0]->image->data + frame->width * frame->height;
+ for( i = 0; i < frame->height; i+=4 ) {
+ xine_fast_memcpy(dst,src,frame->width / 2);
+ dst += frame->width / 2;
+ src += frame->width;
+ }
+
+ dst = this->deinterlace_frame.image->data + frame->width * frame->height * 5 / 8;
+ src = this->recent_frames[0]->image->data + frame->width * frame->height * 5 / 4;
+ for( i = 0; i < frame->height; i+=4 ) {
+ xine_fast_memcpy(dst,src,frame->width / 2);
+ dst += frame->width / 2;
+ src += frame->width;
+ }
+ }
+
+ this->cur_frame = &this->deinterlace_frame;
+}
+
+static void xxmc_clean_output_area (xxmc_driver_t *this) {
+ int i, autopainting;
+
+ XLockDisplay (this->display);
+
+ XSetForeground (this->display, this->gc, this->black.pixel);
+
+ for( i = 0; i < 4; i++ ) {
+ if( this->sc.border[i].w && this->sc.border[i].h ) {
+ XFillRectangle(this->display, this->drawable, this->gc,
+ this->sc.border[i].x, this->sc.border[i].y,
+ this->sc.border[i].w, this->sc.border[i].h);
+ }
+ }
+
+ /*
+ * XvMC does not support autopainting regardless of whether there's an
+ * Xv attribute for this. If there is an XvMC attribute for autopainting,
+ * we ca assume it is supported. This is checked whenever a context is
+ * changed.
+ */
+
+ autopainting = (this->props[VO_PROP_AUTOPAINT_COLORKEY].value == 1);
+ if ((this->contextActive &&
+ (this->context_flags & XVMC_OVERLAID_SURFACE) &&
+ (! this->have_xvmc_autopaint ||
+ ! autopainting)) ||
+ (! this->contextActive && !autopainting)) {
+ XSetForeground (this->display, this->gc, this->colorkey);
+ XFillRectangle (this->display, this->drawable, this->gc,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height);
+ }
+
+ if (this->xoverlay) {
+ x11osd_resize (this->xoverlay, this->sc.gui_width, this->sc.gui_height);
+ this->ovl_changed = 1;
+ }
+
+ XUnlockDisplay (this->display);
+}
+
+/*
+ * convert delivered height/width to ideal width/height
+ * taking into account aspect ratio and zoom factor
+ */
+
+static void xxmc_compute_ideal_size (xxmc_driver_t *this) {
+ _x_vo_scale_compute_ideal_size( &this->sc );
+}
+
+
+/*
+ * make ideal width/height "fit" into the gui
+ */
+
+static void xxmc_compute_output_size (xxmc_driver_t *this) {
+
+ _x_vo_scale_compute_output_size( &this->sc );
+
+ /* onefield_xv divide by 2 the number of lines */
+ if (this->deinterlace_enabled
+ && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV)
+ && ((this->cur_frame->format == XINE_IMGFMT_YV12)
+ || this->cur_frame->format == XINE_IMGFMT_XXMC)) {
+ this->sc.displayed_height = this->sc.displayed_height / 2 - 1;
+ this->sc.displayed_yoffset = this->sc.displayed_yoffset / 2;
+ }
+}
+
+static void xxmc_overlay_begin (vo_driver_t *this_gen,
+ vo_frame_t *frame_gen, int changed) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ this->ovl_changed += changed;
+
+ if( this->ovl_changed && this->xoverlay ) {
+ XLockDisplay (this->display);
+ x11osd_clear(this->xoverlay);
+ XUnlockDisplay (this->display);
+ }
+ if (this->ovl_changed && this->hwSubpictures ) {
+ xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen;
+
+ LOCK_AND_SURFACE_VALID( this, frame->xvmc_surf );
+ this->new_subpic = xxmc_xvmc_alloc_subpicture
+ ( this, &this->context, this->xvmc_width,
+ this->xvmc_height,
+ this->xvmc_cap[this->xvmc_cur_cap].subPicType.id);
+
+ if (this->new_subpic) {
+ this->first_overlay = 1;
+ XVMCLOCKDISPLAY( this->display );
+ XvMCClearSubpicture(this->display, this->new_subpic, 0,0,
+ this->xvmc_width,
+ this->xvmc_height, 0x00);
+ XVMCUNLOCKDISPLAY( this->display );
+ clear_xx44_palette(&this->palette);
+ }
+ xvmc_context_reader_unlock( &this->xvmc_lock );
+ }
+}
+
+static void xxmc_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img)
+{
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+ xxmc_frame_t *frame = (xxmc_frame_t *) vo_img;
+
+
+ if( this->ovl_changed && this->xoverlay ) {
+ XLockDisplay (this->display);
+ x11osd_expose(this->xoverlay);
+ XUnlockDisplay (this->display);
+ }
+ if (this->hwSubpictures) {
+ LOCK_AND_SURFACE_VALID( this, frame->xvmc_surf );
+ if (this->ovl_changed) {
+ if (this->old_subpic) {
+ xxmc_xvmc_free_subpicture(this, this->old_subpic);
+ this->old_subpic = NULL;
+ }
+ if (this->new_subpic) {
+ this->old_subpic = this->new_subpic;
+ this->new_subpic = NULL;
+ xx44_to_xvmc_palette( &this->palette, this->xvmc_palette,
+ 0, this->old_subpic->num_palette_entries,
+ this->old_subpic->entry_bytes,
+ this->reverse_nvidia_palette ? "YVU" :
+ this->old_subpic->component_order);
+ XVMCLOCKDISPLAY( this->display );
+ XvMCSetSubpicturePalette( this->display, this->old_subpic,
+ this->xvmc_palette);
+ XvMCFlushSubpicture( this->display , this->old_subpic);
+ XvMCSyncSubpicture( this->display, this->old_subpic );
+ XVMCUNLOCKDISPLAY( this->display );
+ }
+ }
+ if (this->old_subpic && (! this->first_overlay)) {
+ XVMCLOCKDISPLAY( this->display );
+ if (this->xvmc_backend_subpic ) {
+ XvMCBlendSubpicture( this->display, frame->xvmc_surf,
+ this->old_subpic,0,0,this->xvmc_width,
+ this->xvmc_height, 0, 0,
+ this->xvmc_width, this->xvmc_height );
+ } else {
+ XvMCBlendSubpicture2( this->display, frame->xvmc_surf,
+ frame->xvmc_surf,
+ this->old_subpic, 0,0,this->xvmc_width,
+ this->xvmc_height,0,0,this->xvmc_width,
+ this->xvmc_height);
+ }
+ XVMCUNLOCKDISPLAY( this->display );
+ }
+ xvmc_context_reader_unlock(&this->xvmc_lock );
+ }
+ this->ovl_changed = 0;
+}
+
+
+static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen,
+ vo_overlay_t *overlay)
+{
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+ xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen;
+
+ if (overlay->rle) {
+ if( overlay->unscaled ) {
+ if( this->ovl_changed && this->xoverlay ) {
+ XLockDisplay (this->display);
+ x11osd_blend(this->xoverlay, overlay);
+ XUnlockDisplay (this->display);
+ }
+ } else if (this->hwSubpictures) {
+ if (this->ovl_changed) {
+ if (this->new_subpic) {
+ LOCK_AND_SURFACE_VALID( this, frame->xvmc_surf );
+ if (this->first_overlay) {
+ memset(this->subImage->data,0,this->subImage->width*
+ this->subImage->height);
+ this->first_overlay = 0;
+ }
+ blend_xx44(this->subImage->data, overlay, this->subImage->width,
+ this->subImage->height, this->subImage->width,
+ &this->palette, (this->subImage->id == FOURCC_IA44));
+ XVMCLOCKDISPLAY( this->display );
+ XvMCCompositeSubpicture( this->display, this->new_subpic,
+ this->subImage,
+ overlay->x, overlay->y,overlay->width,
+ overlay->height,
+ overlay->x, overlay->y);
+ XVMCUNLOCKDISPLAY( this->display );
+ xvmc_context_reader_unlock( &this->xvmc_lock );
+ }
+ }
+ } else {
+ if ((frame->format == XINE_IMGFMT_YV12) ||
+ (frame->format == XINE_IMGFMT_XXMC)) {
+ blend_yuv(frame->vo_frame.base, overlay,
+ frame->width, frame->height, frame->vo_frame.pitches);
+ } else {
+ blend_yuy2(frame->vo_frame.base[0], overlay,
+ frame->width, frame->height, frame->vo_frame.pitches[0]);
+ }
+ }
+ }
+}
+
+static void xxmc_add_recent_frame (xxmc_driver_t *this, xxmc_frame_t *frame)
+{
+ int i;
+ i = VO_NUM_RECENT_FRAMES-1;
+ if( this->recent_frames[i] ) {
+ this->recent_frames[i]->vo_frame.free
+ (&this->recent_frames[i]->vo_frame);
+ }
+ for( ; i ; i-- )
+ this->recent_frames[i] = this->recent_frames[i-1];
+
+ this->recent_frames[0] = frame;
+}
+
+static int xxmc_redraw_needed (vo_driver_t *this_gen)
+{
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+ int ret = 0;
+
+ if( this->cur_frame ) {
+
+ this->sc.delivered_height = this->cur_frame->height;
+ this->sc.delivered_width = this->cur_frame->width;
+ this->sc.delivered_ratio = this->cur_frame->ratio;
+
+ this->sc.crop_left = this->cur_frame->vo_frame.crop_left;
+ this->sc.crop_right = this->cur_frame->vo_frame.crop_right;
+ this->sc.crop_top = this->cur_frame->vo_frame.crop_top;
+ this->sc.crop_bottom = this->cur_frame->vo_frame.crop_bottom;
+
+ xxmc_compute_ideal_size(this);
+
+ if( _x_vo_scale_redraw_needed( &this->sc ) ) {
+
+ xxmc_compute_output_size (this);
+ xxmc_clean_output_area (this);
+
+ ret = 1;
+ }
+ }
+ else
+ ret = 1;
+
+ return ret;
+}
+
+static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
+{
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+ xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen;
+ xine_xxmc_t *xxmc = &frame->xxmc_data;
+
+ /*
+ * queue frames (deinterlacing)
+ * free old frames
+ */
+
+ xvmc_context_reader_lock( &this->xvmc_lock );
+ xxmc_add_recent_frame (this, frame); /* deinterlacing */
+
+ this->cur_frame = frame;
+
+
+ /*
+ * let's see if this frame is different in size / aspect
+ * ratio from the previous one
+ */
+ if ( (frame->width != this->sc.delivered_width)
+ || (frame->height != this->sc.delivered_height)
+ || (frame->ratio != this->sc.delivered_ratio) ) {
+ lprintf("frame format changed\n");
+ this->sc.force_redraw = 1; /* trigger re-calc of output size */
+ }
+
+
+ /*
+ * deinterlace frame if necessary
+ * (currently only working for YUV images)
+ */
+
+ if (this->deinterlace_enabled && this->deinterlace_method
+ && ((frame->format == XINE_IMGFMT_YV12) ||
+ (frame->format == XINE_IMGFMT_XXMC))
+ && deinterlace_yuv_supported( this->deinterlace_method ) == 1) {
+ if (frame->format != XINE_IMGFMT_XXMC)
+ xxmc_deinterlace_frame (this);
+ else if (xxmc->format != XINE_IMGFMT_XXMC)
+ xxmc_deinterlace_frame (this);
+ }
+
+ /*
+ * tell gui that we are about to display a frame,
+ * ask for offset and output size
+ */
+
+ xxmc_redraw_needed (this_gen);
+ if (frame->xvmc_surf && (xxmc->format == XINE_IMGFMT_XXMC)) {
+ if (xxmc->decoded && xxmc_xvmc_surface_valid(this, frame->xvmc_surf)) {
+ XVMCLOCKDISPLAY( this->display );
+ XvMCPutSurface( this->display, frame->xvmc_surf , this->drawable,
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height,
+ ((this->deinterlace_enabled) ?
+ XVMC_TOP_FIELD : XVMC_FRAME_PICTURE));
+ XVMCUNLOCKDISPLAY( this->display );
+ }
+ } else {
+ XLockDisplay (this->display);
+ if (this->use_shm) {
+ XvShmPutImage(this->display, this->xv_port,
+ this->drawable, this->gc, frame->image,
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height, True);
+
+ } else {
+ XvPutImage(this->display, this->xv_port,
+ this->drawable, this->gc, frame->image,
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height);
+ }
+ XSync(this->display, False);
+ XUnlockDisplay (this->display);
+ }
+
+ this->cur_frame = frame;
+ xvmc_context_reader_unlock( &this->xvmc_lock );
+
+}
+
+static int xxmc_get_property (vo_driver_t *this_gen, int property) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ switch (property) {
+ case VO_PROP_WINDOW_WIDTH:
+ this->props[property].value = this->sc.gui_width;
+ break;
+ case VO_PROP_WINDOW_HEIGHT:
+ this->props[property].value = this->sc.gui_height;
+ break;
+ }
+
+ lprintf("video_out_xxmc: property #%d = %d\n", property, this->props[property].value);
+
+ return this->props[property].value;
+}
+
+static void xxmc_property_callback (void *property_gen, xine_cfg_entry_t *entry) {
+ xxmc_property_t *property = (xxmc_property_t *) property_gen;
+ xxmc_driver_t *this = property->this;
+
+ xvmc_context_reader_lock( &this->xvmc_lock );
+ XLockDisplay (this->display);
+ XvSetPortAttribute (this->display, this->xv_port,
+ property->atom,
+ entry->num_value);
+ XUnlockDisplay (this->display);
+ if (this->contextActive) {
+ XVMCLOCKDISPLAY( this->display );
+ XvMCSetAttribute(this->display, &this->context,
+ property->atom,
+ entry->num_value);
+ XVMCUNLOCKDISPLAY( this->display );
+ }
+ xvmc_context_reader_unlock( &this->xvmc_lock );
+}
+
+static int xxmc_set_property (vo_driver_t *this_gen,
+ int property, int value) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ if (this->props[property].atom != None) {
+
+ /* value is out of bound */
+ if((value < this->props[property].min) || (value > this->props[property].max))
+ value = (this->props[property].min + this->props[property].max) >> 1;
+ xvmc_context_reader_lock( &this->xvmc_lock );
+ if (this->contextActive) {
+ XVMCLOCKDISPLAY( this->display );
+ XvMCSetAttribute(this->display, &this->context,
+ this->props[property].atom,
+ value);
+ XVMCUNLOCKDISPLAY( this->display );
+ }
+ xvmc_context_reader_unlock( &this->xvmc_lock );
+
+ XLockDisplay (this->display);
+ XvSetPortAttribute (this->display, this->xv_port,
+ this->props[property].atom, value);
+ XvGetPortAttribute (this->display, this->xv_port,
+ this->props[property].atom,
+ &this->props[property].value);
+ XUnlockDisplay (this->display);
+
+ if (this->props[property].entry)
+ this->props[property].entry->num_value = this->props[property].value;
+
+ return this->props[property].value;
+ }
+ else {
+ switch (property) {
+
+ case VO_PROP_INTERLACED:
+ this->props[property].value = value;
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: VO_PROP_INTERLACED(%d)\n", this->props[property].value);
+ this->deinterlace_enabled = value;
+ if (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) {
+ xxmc_compute_ideal_size (this);
+ xxmc_compute_output_size (this);
+ }
+ break;
+
+ case VO_PROP_ASPECT_RATIO:
+ if (value>=XINE_VO_ASPECT_NUM_RATIOS)
+ value = XINE_VO_ASPECT_AUTO;
+
+ this->props[property].value = value;
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: VO_PROP_ASPECT_RATIO(%d)\n", this->props[property].value);
+ this->sc.user_ratio = value;
+
+ xxmc_compute_ideal_size (this);
+
+ this->sc.force_redraw = 1; /* trigger re-calc of output size */
+ break;
+
+ case VO_PROP_ZOOM_X:
+ if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
+ this->props[property].value = value;
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: VO_PROP_ZOOM_X = %d\n", this->props[property].value);
+
+ this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP;
+
+ xxmc_compute_ideal_size (this);
+
+ this->sc.force_redraw = 1; /* trigger re-calc of output size */
+ }
+ break;
+
+ case VO_PROP_ZOOM_Y:
+ if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
+ this->props[property].value = value;
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ "video_out_xxmc: VO_PROP_ZOOM_Y = %d\n", this->props[property].value);
+
+ this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP;
+
+ xxmc_compute_ideal_size (this);
+
+ this->sc.force_redraw = 1; /* trigger re-calc of output size */
+ }
+ break;
+ }
+ }
+ return value;
+}
+
+static void xxmc_get_property_min_max (vo_driver_t *this_gen,
+ int property, int *min, int *max) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ *min = this->props[property].min;
+ *max = this->props[property].max;
+}
+
+static int xxmc_gui_data_exchange (vo_driver_t *this_gen,
+ int data_type, void *data) {
+
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ switch (data_type) {
+#ifndef XINE_DISABLE_DEPRECATED_FEATURES
+ case XINE_GUI_SEND_COMPLETION_EVENT:
+ break;
+#endif
+
+ case XINE_GUI_SEND_EXPOSE_EVENT: {
+ /* XExposeEvent * xev = (XExposeEvent *) data; */
+
+ if (this->cur_frame) {
+ xxmc_frame_t *frame = this->cur_frame;
+ xine_xxmc_t *xxmc = &frame->xxmc_data;
+
+ xxmc_redraw_needed (this_gen);
+
+ /*
+ * Paint colorkey if needed.
+ */
+
+ xxmc_clean_output_area (this);
+ xvmc_context_reader_lock( &this->xvmc_lock );
+
+ if (frame->xvmc_surf && (xxmc->format == XINE_IMGFMT_XXMC)) {
+ if (xxmc->decoded && xxmc_xvmc_surface_valid(this, frame->xvmc_surf)) {
+ XVMCLOCKDISPLAY( this->display );
+ XvMCPutSurface( this->display, frame->xvmc_surf, this->drawable,
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height,
+ ((this->deinterlace_enabled) ? XVMC_TOP_FIELD : XVMC_FRAME_PICTURE));
+ XVMCUNLOCKDISPLAY( this->display );
+ }
+ } else {
+ XLockDisplay (this->display);
+ if (this->use_shm) {
+ XvShmPutImage(this->display, this->xv_port,
+ this->drawable, this->gc, frame->image,
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height, True);
+ } else {
+ XvPutImage(this->display, this->xv_port,
+ this->drawable, this->gc, frame->image,
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height);
+ }
+ XSync(this->display, False);
+ XUnlockDisplay (this->display);
+ }
+
+ if(this->xoverlay)
+ x11osd_expose(this->xoverlay);
+ xvmc_context_reader_unlock( &this->xvmc_lock );
+ }
+ }
+ break;
+
+ case XINE_GUI_SEND_DRAWABLE_CHANGED:
+ XLockDisplay (this->display);
+ this->drawable = (Drawable) data;
+ XFreeGC(this->display, this->gc);
+ this->gc = XCreateGC (this->display, this->drawable, 0, NULL);
+ if(this->xoverlay)
+ x11osd_drawable_changed(this->xoverlay, this->drawable);
+ this->ovl_changed = 1;
+ XUnlockDisplay (this->display);
+ this->sc.force_redraw = 1;
+ break;
+
+ case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO:
+ {
+ int x1, y1, x2, y2;
+ x11_rectangle_t *rect = data;
+
+ _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y,
+ &x1, &y1);
+ _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h,
+ &x2, &y2);
+ rect->x = x1;
+ rect->y = y1;
+ rect->w = x2-x1;
+ rect->h = y2-y1;
+
+ /* onefield_xv divide by 2 the number of lines */
+ if (this->deinterlace_enabled
+ && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV)
+ && ((this->cur_frame->format == XINE_IMGFMT_YV12) ||
+ (this->cur_frame->format == XINE_IMGFMT_XXMC))) {
+ rect->y = rect->y * 2;
+ rect->h = rect->h * 2;
+ }
+
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static void xxmc_dispose (vo_driver_t *this_gen) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+ int i;
+
+
+ if (this->xvmc_cap) {
+ xvmc_context_writer_lock( &this->xvmc_lock );
+ xxmc_dispose_context( this );
+ if (this->old_subpic) {
+ xxmc_xvmc_free_subpicture(this, this->old_subpic);
+ this->old_subpic = NULL;
+ }
+ if (this->new_subpic) {
+ xxmc_xvmc_free_subpicture(this, this->old_subpic);
+ this->new_subpic = NULL;
+ }
+ xvmc_context_writer_unlock( &this->xvmc_lock );
+ }
+
+
+ if (this->deinterlace_frame.image) {
+ XLockDisplay (this->display);
+ dispose_ximage (this, &this->deinterlace_frame.shminfo,
+ this->deinterlace_frame.image);
+ XUnlockDisplay (this->display);
+ this->deinterlace_frame.image = NULL;
+ }
+
+ XLockDisplay (this->display);
+ if(XvUngrabPort (this->display, this->xv_port, CurrentTime) != Success) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: xxmc_exit: XvUngrabPort() failed.\n");
+ }
+ XFreeGC(this->display, this->gc);
+ XUnlockDisplay (this->display);
+
+ for( i=0; i < VO_NUM_RECENT_FRAMES; i++ ) {
+ if( this->recent_frames[i] )
+ this->recent_frames[i]->vo_frame.dispose
+ (&this->recent_frames[i]->vo_frame);
+ this->recent_frames[i] = NULL;
+ }
+
+ if( this->xoverlay ) {
+ XLockDisplay (this->display);
+ x11osd_destroy (this->xoverlay);
+ XUnlockDisplay (this->display);
+ }
+ free_context_lock(&this->xvmc_lock);
+
+ free (this);
+}
+
+/* called xlocked */
+static int xxmc_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) &&
+ (! (strcmp (formatValues[i].guid, "YV12")))) {
+ XFree (formatValues);
+ return 0;
+ }
+
+ XFree (formatValues);
+ return 1;
+}
+
+/* called xlocked */
+static void xxmc_check_capability (xxmc_driver_t *this,
+ int property, XvAttribute attr,
+ int base_id, char *str_prop,
+ char *config_name,
+ char *config_desc,
+ char *config_help) {
+ int int_default;
+ cfg_entry_t *entry;
+
+ if (VO_PROP_COLORKEY && (attr.max_value == ~0))
+ attr.max_value = 2147483615;
+
+ this->props[property].min = attr.min_value;
+ this->props[property].max = attr.max_value;
+ this->props[property].atom = XInternAtom (this->display, str_prop, False);
+
+ XvGetPortAttribute (this->display, this->xv_port,
+ this->props[property].atom, &int_default);
+
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: port attribute %s (%d) value is %d\n", str_prop, property, int_default);
+
+ /*
+ * We enable autopaint by default.
+ */
+ if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0)
+ int_default = 1;
+
+ if (config_name) {
+ /* is this a boolean property ? */
+ if ((attr.min_value == 0) && (attr.max_value == 1)) {
+ this->config->register_bool (this->config, config_name, int_default,
+ config_desc,
+ config_help, 20, xxmc_property_callback, &this->props[property]);
+
+ } else {
+ this->config->register_range (this->config, config_name, int_default,
+ this->props[property].min, this->props[property].max,
+ config_desc,
+ config_help, 20, xxmc_property_callback, &this->props[property]);
+ }
+
+ entry = this->config->lookup_entry (this->config, config_name);
+
+ if((entry->num_value < this->props[property].min) ||
+ (entry->num_value > this->props[property].max)) {
+
+ this->config->update_num(this->config, config_name,
+ ((this->props[property].min + this->props[property].max) >> 1));
+
+ entry = this->config->lookup_entry (this->config, config_name);
+ }
+
+ this->props[property].entry = entry;
+
+ xxmc_set_property (&this->vo_driver, property, entry->num_value);
+
+
+ if (strcmp(str_prop, "XV_COLORKEY") == 0) {
+ this->use_colorkey |= 1;
+ this->colorkey = entry->num_value;
+ } else if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0) {
+ if(entry->num_value==1)
+ this->use_colorkey |= 2;
+ }
+ } else
+ this->props[property].value = int_default;
+}
+
+static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+ Atom atom;
+ int xv_filter;
+
+ xv_filter = entry->num_value;
+
+ XLockDisplay(this->display);
+ atom = XInternAtom (this->display, "XV_FILTER", False);
+ XvSetPortAttribute (this->display, this->xv_port, atom, xv_filter);
+ XUnlockDisplay(this->display);
+
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter);
+}
+
+static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+ Atom atom;
+ int xv_double_buffer;
+
+ xv_double_buffer = entry->num_value;
+
+ XLockDisplay(this->display);
+ atom = XInternAtom (this->display, "XV_DOUBLE_BUFFER", False);
+ XvSetPortAttribute (this->display, this->xv_port, atom, xv_double_buffer);
+ XUnlockDisplay(this->display);
+
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: double buffering mode = %d\n", xv_double_buffer);
+}
+
+static void xxmc_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ this->use_pitch_alignment = entry->num_value;
+}
+
+static void xxmc_update_cpu_save(void *this_gen, xine_cfg_entry_t *entry) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ this->cpu_save_enabled = entry->num_value;
+}
+
+static void xxmc_update_nvidia_fix(void *this_gen, xine_cfg_entry_t *entry) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ this->reverse_nvidia_palette = entry->num_value;
+}
+
+static void xxmc_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ this->deinterlace_method = entry->num_value;
+}
+
+
+static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port)
+{
+ int
+ numSurf,numSub,i,j;
+ XvMCSurfaceInfo
+ *surfaceInfo,*curInfo;
+ XvMCContext
+ c;
+ xvmc_capabilities_t
+ *curCap;
+ XvImageFormatValues
+ *formatValues;
+
+ this->xvmc_cap = 0;
+ init_context_lock( &this->xvmc_lock );
+ xvmc_context_writer_lock( &this->xvmc_lock );
+ this->old_subpic = NULL;
+ this->new_subpic = NULL;
+ this->contextActive = 0;
+ this->subImage = NULL;
+ this->hwSubpictures = 0;
+ this->xvmc_palette = NULL;
+
+ XVMCLOCKDISPLAY( this->display );
+
+ if ( !XvMCQueryExtension(this->display, &this->xvmc_eventbase,
+ &this->xvmc_errbase)) {
+ XVMCUNLOCKDISPLAY( this->display );
+ xvmc_context_writer_unlock( &this->xvmc_lock );
+ return;
+ }
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: XvMC extension present.\n");
+
+ surfaceInfo = XvMCListSurfaceTypes(this->display, xv_port, &numSurf);
+ if (0 == surfaceInfo) {
+ XVMCUNLOCKDISPLAY( this->display );
+ xvmc_context_writer_unlock( &this->xvmc_lock );
+ return;
+ }
+ this->xvmc_cap = (xvmc_capabilities_t *)
+ xine_xmalloc(numSurf * sizeof(xvmc_capabilities_t));
+ if (NULL == this->xvmc_cap) return;
+ this->xvmc_num_cap = numSurf;
+ curInfo = surfaceInfo;
+ curCap = this->xvmc_cap;
+
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Found %d XvMC surface types\n",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 & XINE_XVMC_MPEG_1) ?
+ XINE_XVMC_MPEG_1 : 0);
+ curCap->mpeg_flags |= ((curInfo->mc_type & XINE_XVMC_MPEG_2) ?
+ XINE_XVMC_MPEG_2 : 0);
+ curCap->mpeg_flags |= ((curInfo->mc_type & XINE_XVMC_MPEG_4) ?
+ XINE_XVMC_MPEG_4 : 0);
+ curCap->accel_flags |= ((curInfo->mc_type & XVMC_VLD) ?
+ XINE_XVMC_ACCEL_VLD : 0);
+ curCap->accel_flags |= ((curInfo->mc_type & XVMC_IDCT) ?
+ XINE_XVMC_ACCEL_IDCT : 0);
+ curCap->accel_flags |= ((curInfo->mc_type & (XVMC_VLD | XVMC_IDCT)) ?
+ 0 : XINE_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;
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Surface type %d: Max size: %d %d.\n",
+ i,curCap->max_width,curCap->max_height);
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Surface type %d: Max subpic size: %d %d.\n",
+ i,curCap->sub_max_width,curCap->sub_max_height);
+
+ curCap->type_id = curInfo->surface_type_id;
+ formatValues = XvMCListSubpictureTypes( this->display, xv_port,
+ curCap->type_id, &numSub);
+ curCap->subPicType.id = 0;
+ if (formatValues) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Surface type %d: Found %d XvMC subpicture "
+ "types\n",i,numSub);
+ for (j = 0; j<numSub; ++j) {
+ if (formatValues[j].id == FOURCC_IA44) {
+ curCap->subPicType = formatValues[j];
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Surface type %d: Detected and using "
+ "IA44 subpicture type.\n",i);
+ /* Prefer IA44 */
+ break;
+ } else if (formatValues[j].id == FOURCC_AI44) {
+ curCap->subPicType = formatValues[j];
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Surface type %d: Detected AI44 "
+ "subpicture type.\n",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.
+ */
+
+ curCap = this->xvmc_cap;
+ if (Success == XvMCCreateContext( this->display, xv_port, curCap->type_id,
+ curCap->max_width,curCap->max_height,
+ XVMC_DIRECT, &c)) {
+ this->context_flags = XVMC_DIRECT;
+ } else if (Success == XvMCCreateContext( this->display, xv_port, curCap->type_id,
+ curCap->max_width,curCap->max_height,
+ 0, &c)) {
+ this->context_flags = 0;
+ } else {
+ free(this->xvmc_cap);
+ this->xvmc_cap = 0;
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "video_out_xxmc: Apparent attempt to use a direct XvMC "
+ "context\nvideo_out_xxmc: on a remote display. "
+ "Falling back to XV.\n");
+ XVMCUNLOCKDISPLAY( this->display );
+ xvmc_context_writer_unlock( &this->xvmc_lock );
+ return;
+ }
+ XvMCDestroyContext( this->display, &c);
+ xxmc_xvmc_surface_handler_construct(this);
+ this->capabilities |= VO_CAP_XXMC;
+ XVMCUNLOCKDISPLAY( this->display );
+ init_xx44_palette( &this->palette , 0);
+ xvmc_context_writer_unlock( &this->xvmc_lock );
+ return;
+
+}
+
+
+
+
+static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *visual_gen) {
+ xxmc_class_t *class = (xxmc_class_t *) class_gen;
+ config_values_t *config = class->config;
+ xxmc_driver_t *this;
+ int i, formats;
+ XvAttribute *attr;
+ XvImageFormatValues *fo;
+ int nattr;
+ x11_visual_t *visual = (x11_visual_t *) visual_gen;
+ XColor dummy;
+ XvImage *myimage;
+ unsigned int adaptors, j;
+ unsigned int ver,rel,req,ev,err;
+ XShmSegmentInfo myshminfo;
+ XvPortID xv_port;
+ XvAdaptorInfo *adaptor_info;
+ unsigned int adaptor_num;
+ cfg_entry_t *entry;
+ int use_more_frames;
+
+ this = (xxmc_driver_t *) xine_xmalloc (sizeof (xxmc_driver_t));
+ if (!this)
+ return NULL;
+
+ this->display = visual->display;
+ this->screen = visual->screen;
+ this->config = config;
+
+ /*
+ * check for Xvideo support
+ */
+
+ XLockDisplay(this->display);
+ if (Success != XvQueryExtension(this->display, &ver,&rel, &req, &ev,&err)) {
+ xprintf (class->xine, XINE_VERBOSITY_LOG, _("video_out_xxmc: Xv extension not present.\n"));
+ XUnlockDisplay(this->display);
+ return NULL;
+ }
+
+ /*
+ * check adaptors, search for one that supports (at least) yuv12
+ */
+
+ if (Success != XvQueryAdaptors(this->display,DefaultRootWindow(this->display), &adaptors, &adaptor_info)) {
+ xprintf(class->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: XvQueryAdaptors failed.\n");
+ XUnlockDisplay(this->display);
+ return NULL;
+ }
+
+ xv_port = 0;
+
+ for ( adaptor_num = 0; (adaptor_num < adaptors) && !xv_port; adaptor_num++ ) {
+
+ if (adaptor_info[adaptor_num].type & XvImageMask) {
+
+ for (j = 0; j < adaptor_info[adaptor_num].num_ports && !xv_port; j++)
+ if (( !(xxmc_check_yv12 (this->display,
+ adaptor_info[adaptor_num].base_id + j)))
+ && (XvGrabPort (this->display,
+ adaptor_info[adaptor_num].base_id + j,
+ 0) == Success)) {
+ xv_port = adaptor_info[adaptor_num].base_id + j;
+ }
+
+ if( xv_port )
+ break;
+ }
+ }
+
+ if (!xv_port) {
+ xprintf(class->xine, XINE_VERBOSITY_LOG,
+ _("video_out_xxmc: Xv extension is present but I couldn't find a usable yuv12 port.\n"
+ " Looks like your graphics hardware driver doesn't support Xv?!\n"));
+
+ /* XvFreeAdaptorInfo (adaptor_info); this crashed on me (gb)*/
+ XUnlockDisplay(this->display);
+ return NULL;
+ }
+ else
+ xprintf(class->xine, XINE_VERBOSITY_LOG,
+ _("video_out_xxmc: using Xv port %ld from adaptor %s for hardware "
+ "colorspace conversion and scaling.\n"), xv_port,
+ adaptor_info[adaptor_num].name);
+
+ XUnlockDisplay(this->display);
+
+ this->xv_port = xv_port;
+
+ _x_vo_scale_init (&this->sc, 1, 0, config );
+ this->sc.frame_output_cb = visual->frame_output_cb;
+ this->sc.user_data = visual->user_data;
+
+ this->drawable = visual->d;
+ XLockDisplay (this->display);
+ this->gc = XCreateGC (this->display, this->drawable, 0, NULL);
+ XUnlockDisplay (this->display);
+ this->capabilities = VO_CAP_CROP;
+ this->use_shm = 1;
+ this->deinterlace_method = 0;
+ this->deinterlace_frame.image = NULL;
+ this->use_colorkey = 0;
+ this->colorkey = 0;
+ this->xoverlay = NULL;
+ this->ovl_changed = 0;
+ this->x11_old_error_handler = NULL;
+ this->xine = class->xine;
+
+ XLockDisplay (this->display);
+ XAllocNamedColor (this->display,
+ DefaultColormap(this->display, this->screen),
+ "black", &this->black, &dummy);
+ XUnlockDisplay (this->display);
+
+ this->vo_driver.get_capabilities = xxmc_get_capabilities;
+ this->vo_driver.alloc_frame = xxmc_alloc_frame;
+ this->vo_driver.update_frame_format = xxmc_update_frame_format;
+ this->vo_driver.overlay_begin = xxmc_overlay_begin;
+ this->vo_driver.overlay_blend = xxmc_overlay_blend;
+ this->vo_driver.overlay_end = xxmc_overlay_end;
+ this->vo_driver.display_frame = xxmc_display_frame;
+ this->vo_driver.get_property = xxmc_get_property;
+ this->vo_driver.set_property = xxmc_set_property;
+ this->vo_driver.get_property_min_max = xxmc_get_property_min_max;
+ this->vo_driver.gui_data_exchange = xxmc_gui_data_exchange;
+ this->vo_driver.dispose = xxmc_dispose;
+ this->vo_driver.redraw_needed = xxmc_redraw_needed;
+
+ /*
+ * init properties
+ */
+
+ for (i = 0; i < VO_NUM_PROPERTIES; i++) {
+ this->props[i].value = 0;
+ this->props[i].min = 0;
+ this->props[i].max = 0;
+ this->props[i].atom = None;
+ this->props[i].entry = NULL;
+ this->props[i].this = this;
+ }
+
+ this->props[VO_PROP_INTERLACED].value = 0;
+ this->sc.user_ratio =
+ this->props[VO_PROP_ASPECT_RATIO].value = XINE_VO_ASPECT_AUTO;
+ this->props[VO_PROP_ZOOM_X].value = 100;
+ this->props[VO_PROP_ZOOM_Y].value = 100;
+
+ /*
+ * check this adaptor's capabilities
+ */
+
+ XLockDisplay (this->display);
+ attr = XvQueryPortAttributes(this->display, xv_port, &nattr);
+ if(attr && nattr) {
+ int k;
+
+ for(k = 0; k < nattr; k++) {
+ if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) {
+ if(!strcmp(attr[k].name, "XV_HUE")) {
+ if (!strncmp(adaptor_info[adaptor_num].name, "NV", 2)) {
+ xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xxmc: ignoring broken XV_HUE settings on NVidia cards\n");
+ } else {
+ xxmc_check_capability (this, VO_PROP_HUE, attr[k],
+ adaptor_info[adaptor_num].base_id, "XV_HUE",
+ NULL, NULL, NULL);
+ }
+ } else if(!strcmp(attr[k].name, "XV_SATURATION")) {
+ xxmc_check_capability (this, VO_PROP_SATURATION, attr[k],
+ adaptor_info[adaptor_num].base_id, "XV_SATURATION",
+ NULL, NULL, NULL);
+
+ } else if(!strcmp(attr[k].name, "XV_BRIGHTNESS")) {
+ xxmc_check_capability (this, VO_PROP_BRIGHTNESS, attr[k],
+ adaptor_info[adaptor_num].base_id, "XV_BRIGHTNESS",
+ NULL, NULL, NULL);
+
+ } else if(!strcmp(attr[k].name, "XV_CONTRAST")) {
+ xxmc_check_capability (this, VO_PROP_CONTRAST, attr[k],
+ adaptor_info[adaptor_num].base_id, "XV_CONTRAST",
+ NULL, NULL, NULL);
+
+ } else if(!strcmp(attr[k].name, "XV_COLORKEY")) {
+ xxmc_check_capability (this, VO_PROP_COLORKEY, attr[k],
+ adaptor_info[adaptor_num].base_id, "XV_COLORKEY",
+ "video.xv_colorkey",
+ _("video overlay colour key"),
+ _("The colour key is used to tell the graphics card where to "
+ "overlay the video image. Try different values, if you experience "
+ "windows becoming transparent."));
+
+ } else if(!strcmp(attr[k].name, "XV_AUTOPAINT_COLORKEY")) {
+ xxmc_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attr[k],
+ adaptor_info[adaptor_num].base_id, "XV_AUTOPAINT_COLORKEY",
+ "video.xv_autopaint_colorkey",
+ _("autopaint colour key"),
+ _("Make Xv autopaint its colorkey."));
+
+ } else if(!strcmp(attr[k].name, "XV_FILTER")) {
+ int xv_filter;
+ /* This setting is specific to Permedia 2/3 cards. */
+ xv_filter = config->register_range (config, "video.XV_FILTER", 0,
+ attr[k].min_value, attr[k].max_value,
+ _("bilinear scaling mode"),
+ _("Selects the bilinear scaling mode for Permedia cards. "
+ "The individual values are:\n\n"
+ "Permedia 2\n"
+ "0 - disable bilinear filtering\n"
+ "1 - enable bilinear filtering\n\n"
+ "Permedia 3\n"
+ "0 - disable bilinear filtering\n"
+ "1 - horizontal linear filtering\n"
+ "2 - enable full bilinear filtering"),
+ 20, xxmc_update_XV_FILTER, this);
+ config->update_num(config,"video.XV_FILTER",xv_filter);
+ } else if(!strcmp(attr[k].name, "XV_DOUBLE_BUFFER")) {
+ int xv_double_buffer;
+ xv_double_buffer =
+ config->register_bool (config, "video.XV_DOUBLE_BUFFER", 1,
+ _("enable double buffering"),
+ _("Double buffering will synchronize the update of the video image to the "
+ "repainting of the entire screen (\"vertical retrace\"). This eliminates "
+ "flickering and tearing artifacts, but will use more graphics memory."),
+ 20, xxmc_update_XV_DOUBLE_BUFFER, this);
+ config->update_num(config,"video.XV_DOUBLE_BUFFER",xv_double_buffer);
+ }
+ }
+ }
+ XFree(attr);
+ }
+ else
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: no port attributes defined.\n");
+ XvFreeAdaptorInfo(adaptor_info);
+
+ /*
+ * check XvMC capabilities
+ */
+
+ checkXvMCCap( this, xv_port );
+
+ /*
+ * check supported image formats
+ */
+
+
+ fo = XvListImageFormats(this->display, this->xv_port, (int*)&formats);
+ XUnlockDisplay (this->display);
+
+ this->xv_format_yv12 = 0;
+ this->xv_format_yuy2 = 0;
+
+ for(i = 0; i < formats; i++) {
+ lprintf ("Xv image format: 0x%x (%4.4s) %s\n",
+ fo[i].id, (char*)&fo[i].id,
+ (fo[i].format == XvPacked) ? "packed" : "planar");
+
+ if (fo[i].id == XINE_IMGFMT_YV12) {
+ this->xv_format_yv12 = fo[i].id;
+ this->capabilities |= VO_CAP_YV12;
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_xxmc: this adaptor supports the yv12 format.\n"));
+ } else if (fo[i].id == XINE_IMGFMT_YUY2) {
+ this->xv_format_yuy2 = fo[i].id;
+ this->capabilities |= VO_CAP_YUY2;
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_xxmc: this adaptor supports the yuy2 format.\n"));
+ }
+ }
+
+ if(fo) {
+ XLockDisplay(this->display);
+ XFree(fo);
+ XUnlockDisplay(this->display);
+ }
+
+ /*
+ * try to create a shared image
+ * to find out if MIT shm really works, using supported format
+ */
+
+ XLockDisplay (this->display);
+ myimage = create_ximage (this, &myshminfo, 100, 100,
+ (this->xv_format_yv12 != 0) ? XINE_IMGFMT_YV12 : XINE_IMGFMT_YUY2);
+ dispose_ximage (this, &myshminfo, myimage);
+ XUnlockDisplay (this->display);
+
+ this->use_pitch_alignment =
+ config->register_bool (config, "video.xv_pitch_alignment", 0,
+ _("pitch alignment workaround"),
+ _("Some buggy video drivers need a workaround to function properly."),
+ 10, xxmc_update_xv_pitch_alignment, this);
+
+ use_more_frames=
+ config->register_bool (config, "video.xvmc_more_frames", 0,
+ _("Make XvMC allocate more frames for better buffering."),
+ _("Some XvMC implementations allow more than 8 frames.\n"
+ "This option, when turned on, makes the driver try to\n"
+ "allocate 15 frames. A must for unichrome and live VDR.\n"),
+ 10, NULL, this);
+ this->cpu_save_enabled =
+ config->register_bool (config, "video.unichrome_cpu_save", 0,
+ _("Unichrome cpu save"),
+ _("Saves CPU time by sleeping while decoder works.\n"
+ "Only for Linux kernel 2.6 series or 2.4 with multimedia patch.\n"
+ "Experimental.\n"),
+ 10, xxmc_update_cpu_save, this);
+ this->deinterlace_method =
+ config->register_enum (config, "video.deinterlace_method", 0,
+ deinterlace_methods,
+ _("deinterlace_methods"),
+ _("This config setting is deprecated. You should use the new "
+ "deinterlacing post processing settings instead.\n"),
+ 10, xxmc_update_deinterlace, this);
+ this->reverse_nvidia_palette =
+ config->register_bool (config, "video.xvmc_nvidia_color_fix", 0,
+ _("Fix buggy NVIDIA XvMC subpicture colors"),
+ _("There's a bug in NVIDIA's XvMC lib that makes red OSD colors\n"
+ "look blue and vice versa. This option provides a workaround.\n"),
+ 10, xxmc_update_nvidia_fix, this);
+
+ this->deinterlace_enabled = 0;
+#ifdef HAVE_VLDXVMC
+ printf("video_out_xxmc: Unichrome CPU saving is %s.\n",
+ (this->cpu_save_enabled) ? "on":"off");
+#else
+ printf("video_out_xxmc: warning - compiled with no vld extensions.\n");
+#endif
+ this->props[VO_PROP_MAX_NUM_FRAMES].value = (use_more_frames) ? 15:8;
+ this->cpu_saver = 0.;
+
+ this->xoverlay = NULL;
+
+ /*
+ * FIXME: YV12 deinterlace method.
+ */
+
+
+ entry = this->config->lookup_entry (this->config, "gui.osd_use_unscaled");
+ if (entry->num_value == 1) {
+ XLockDisplay (this->display);
+ if( this->use_colorkey ) {
+ this->xoverlay = x11osd_create (this->xine, this->display, this->screen,
+ this->drawable, X11OSD_COLORKEY);
+ if(this->xoverlay)
+ x11osd_colorkey(this->xoverlay, this->colorkey, &this->sc);
+ this->xoverlay_ck = 1;
+ } else {
+ this->xoverlay = x11osd_create (this->xine, this->display, this->screen,
+ this->drawable, X11OSD_SHAPED);
+ this->xoverlay_ck = 0;
+ }
+ XUnlockDisplay (this->display);
+ }
+
+ if( this->xoverlay ) {
+ this->capabilities |= VO_CAP_UNSCALED_OVERLAY;
+ }
+ return &this->vo_driver;
+}
+
+/*
+ * class functions
+ */
+
+static char* get_identifier (video_driver_class_t *this_gen) {
+ return "XxMC";
+}
+
+static char* get_description (video_driver_class_t *this_gen) {
+ return _("xine video output plugin using the MIT X video extension");
+}
+
+static void dispose_class (video_driver_class_t *this_gen) {
+ xxmc_class_t *this = (xxmc_class_t *) this_gen;
+
+ free (this);
+}
+
+static void *init_class (xine_t *xine, void *visual_gen) {
+ xxmc_class_t *this = (xxmc_class_t *) xine_xmalloc (sizeof (xxmc_class_t));
+
+ this->driver_class.open_plugin = open_plugin;
+ this->driver_class.get_identifier = get_identifier;
+ this->driver_class.get_description = get_description;
+ this->driver_class.dispose = dispose_class;
+
+ this->config = xine->config;
+ this->xine = xine;
+
+ return this;
+}
+
+static vo_info_t vo_info_xxmc = {
+ 9, /* priority */
+ XINE_VISUAL_TYPE_X11 /* visual type */
+};
+
+/*
+ * exported plugin catalog entry
+ */
+
+plugin_info_t xine_plugin_info[] = {
+ /* type, API, "name", version, special_info, init_function */
+ { PLUGIN_VIDEO_OUT, 20, "xxmc", XINE_VERSION_CODE, &vo_info_xxmc, init_class },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
+
diff --git a/src/video_out/xvmc_mocomp.c b/src/video_out/xvmc_mocomp.c
new file mode 100644
index 000000000..94c6e9906
--- /dev/null
+++ b/src/video_out/xvmc_mocomp.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2000-2004 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: xvmc_mocomp.c,v 1.1 2004/09/28 18:49:40 miguelfreitas Exp $
+ *
+ * XvMC image support by Jack Kelliher
+ */
+
+#include "xxmc.h"
+
+
+static void calc_DMV(int DMV[][2], int *dmvector,
+ int mvx, int mvy, int picture_structure, int top_field_first) {
+
+ if (picture_structure==VO_BOTH_FIELDS) {
+ if (top_field_first) {
+ /* vector for prediction of top field from bottom field */
+ DMV[0][0] = ((mvx +(mvx>0))>>1) + dmvector[0];
+ DMV[0][1] = ((mvy +(mvy>0))>>1) + dmvector[1] - 1;
+
+ /* vector for prediction of bottom field from top field */
+ DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
+ DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1;
+ }
+ else {
+ /* vector for prediction of top field from bottom field */
+ DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
+ DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1;
+
+ /* vector for prediction of bottom field from top field */
+ DMV[1][0] = ((mvx +(mvx>0))>>1) + dmvector[0];
+ DMV[1][1] = ((mvy +(mvy>0))>>1) + dmvector[1] + 1;
+ }
+ }
+ else {
+ /* vector for prediction from field of opposite 'parity' */
+ DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0];
+ DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1];
+
+ /* correct for vertical field shift */
+ if (picture_structure==VO_TOP_FIELD)
+ DMV[0][1]--;
+ else
+ DMV[0][1]++;
+
+ }
+}
+
+
+
+
+static void xvmc_render_macro_blocks(vo_frame_t *current_image,
+ vo_frame_t *backward_ref_image,
+ vo_frame_t *forward_ref_image,
+ int picture_structure,
+ int second_field,
+ xvmc_macroblocks_t *macroblocks) {
+ xxmc_driver_t *this = (xxmc_driver_t *) current_image->driver;
+ xxmc_frame_t *current_frame = (xxmc_frame_t *) current_image;
+ xxmc_frame_t *forward_frame = (xxmc_frame_t *) forward_ref_image;
+ xxmc_frame_t *backward_frame = (xxmc_frame_t *) backward_ref_image;
+
+ lprintf ("xvmc_render_macro_blocks\n");
+ lprintf ("slices %d 0x%08lx 0x%08lx 0x%08lx\n",
+ macroblocks->slices,
+ (long) current_frame, (long) backward_frame,
+ (long) forward_frame);
+
+ XVMCLOCKDISPLAY( this->display);
+ XvMCRenderSurface(this->display, &this->context, picture_structure,
+ current_frame->xvmc_surf,
+ forward_frame ? forward_frame->xvmc_surf : NULL,
+ backward_frame ? backward_frame->xvmc_surf : NULL,
+ second_field,
+ macroblocks->slices, 0, &macroblocks->macro_blocks,
+ &macroblocks->blocks);
+ XVMCUNLOCKDISPLAY( this->display);
+}
+
+
+
+void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type,
+ int (*mv_field_sel)[2], int *dmvector, int cbp,
+ int dct_type, vo_frame_t *current_frame,
+ vo_frame_t *forward_ref_frame,
+ vo_frame_t *backward_ref_frame, int picture_structure,
+ int second_field, int (*f_mot_pmv)[2], int (*b_mot_pmv)[2])
+{
+ xxmc_driver_t *this = (xxmc_driver_t *) current_frame->driver;
+ xvmc_macroblocks_t *mbs = &this->macroblocks;
+ int top_field_first = current_frame->top_field_first;
+ int picture_coding_type = current_frame->picture_coding_type;
+
+ xvmc_context_reader_lock( &this->xvmc_lock );
+ mbs->macroblockptr->x = x;
+ mbs->macroblockptr->y = y;
+
+ if(mb_type & XINE_MACROBLOCK_INTRA) {
+ mbs->macroblockptr->macroblock_type = XVMC_MB_TYPE_INTRA;
+ }
+ else {
+ mbs->macroblockptr->macroblock_type = 0;
+ /* XvMC doesn't support skips */
+ if(!(mb_type & (XINE_MACROBLOCK_MOTION_BACKWARD | XINE_MACROBLOCK_MOTION_FORWARD))) {
+ mb_type |= XINE_MACROBLOCK_MOTION_FORWARD;
+ motion_type = (picture_structure == VO_BOTH_FIELDS) ? XINE_MC_FRAME : XINE_MC_FIELD;
+ mbs->macroblockptr->PMV[0][0][0] = 0;
+ mbs->macroblockptr->PMV[0][0][1] = 0;
+ }
+ else {
+ if(mb_type & XINE_MACROBLOCK_MOTION_BACKWARD) {
+ mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD;
+ mbs->macroblockptr->PMV[0][1][0] = b_mot_pmv[0][0];
+ mbs->macroblockptr->PMV[0][1][1] = b_mot_pmv[0][1];
+ mbs->macroblockptr->PMV[1][1][0] = b_mot_pmv[1][0];
+ mbs->macroblockptr->PMV[1][1][1] = b_mot_pmv[1][1];
+
+ }
+
+ if(mb_type & XINE_MACROBLOCK_MOTION_FORWARD) {
+ mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_FORWARD;
+ mbs->macroblockptr->PMV[0][0][0] = f_mot_pmv[0][0];
+ mbs->macroblockptr->PMV[0][0][1] = f_mot_pmv[0][1];
+ mbs->macroblockptr->PMV[1][0][0] = f_mot_pmv[1][0];
+ mbs->macroblockptr->PMV[1][0][1] = f_mot_pmv[1][1];
+ }
+ }
+
+ if((mb_type & XINE_MACROBLOCK_PATTERN) && cbp)
+ mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_PATTERN;
+
+ mbs->macroblockptr->motion_type = motion_type;
+
+ if(motion_type == XINE_MC_DMV) {
+ int DMV[2][2];
+
+ if(picture_structure == VO_BOTH_FIELDS) {
+ calc_DMV(DMV,dmvector, f_mot_pmv[0][0],
+ f_mot_pmv[0][1]>>1, picture_structure,
+ top_field_first);
+
+ mbs->macroblockptr->PMV[1][0][0] = DMV[0][0];
+ mbs->macroblockptr->PMV[1][0][1] = DMV[0][1];
+ mbs->macroblockptr->PMV[1][1][0] = DMV[1][0];
+ mbs->macroblockptr->PMV[1][1][1] = DMV[1][1];
+ }
+ else {
+ calc_DMV(DMV,dmvector, f_mot_pmv[0][0],
+ f_mot_pmv[0][1]>>1, picture_structure,
+ top_field_first);
+
+ mbs->macroblockptr->PMV[0][1][0] = DMV[0][0];
+ mbs->macroblockptr->PMV[0][1][1] = DMV[0][1];
+ }
+ }
+
+ if((motion_type == XINE_MC_FIELD) || (motion_type == XINE_MC_16X8)) {
+ mbs->macroblockptr->motion_vertical_field_select = 0;
+ if(mv_field_sel[0][0])
+ mbs->macroblockptr->motion_vertical_field_select |= 1;
+ if(mv_field_sel[0][1])
+ mbs->macroblockptr->motion_vertical_field_select |= 2;
+ if(mv_field_sel[1][0])
+ mbs->macroblockptr->motion_vertical_field_select |= 4;
+ if(mv_field_sel[1][1])
+ mbs->macroblockptr->motion_vertical_field_select |= 8;
+ }
+ } /* else of if(mb_type & XINE_MACROBLOCK_INTRA) */
+
+ mbs->macroblockptr->index = ((unsigned long)mbs->xine_mc.blockptr -
+ (unsigned long)mbs->xine_mc.blockbaseptr) >> 7;
+
+ mbs->macroblockptr->dct_type = dct_type;
+ mbs->macroblockptr->coded_block_pattern = cbp;
+
+ cbp &= 0x3F;
+ mbs->macroblockptr->coded_block_pattern = cbp;
+
+ while(cbp) {
+ if(cbp & 1) mbs->macroblockptr->index--;
+ cbp >>= 1;
+ }
+
+#ifdef PRINTDATA
+ printf("\n");
+ printf("-- %04d %04d %02x %02x %02x %02x",mbs->macroblockptr->x,mbs->macroblockptr->y,mbs->macroblockptr->macroblock_type,
+ mbs->macroblockptr->motion_type,mbs->macroblockptr->motion_vertical_field_select,mbs->macroblockptr->dct_type);
+ printf(" [%04d %04d %04d %04d %04d %04d %04d %04d] ",
+ mbs->macroblockptr->PMV[0][0][0],mbs->macroblockptr->PMV[0][0][1],mbs->macroblockptr->PMV[0][1][0],mbs->macroblockptr->PMV[0][1][1],
+ mbs->macroblockptr->PMV[1][0][0],mbs->macroblockptr->PMV[1][0][1],mbs->macroblockptr->PMV[1][1][0],mbs->macroblockptr->PMV[1][1][1]);
+
+ printf(" %04d %04x\n",mbs->macroblockptr->index,mbs->macroblockptr->coded_block_pattern);
+#endif
+
+ mbs->num_blocks++;
+ mbs->macroblockptr++;
+
+ if(mbs->num_blocks == mbs->slices) {
+#ifdef PRINTDATA
+ printf("macroblockptr %lx", mbs->macroblockptr);
+ printf("** RenderSurface %04d %04x\n",picture_structure,
+ second_field ? XVMC_SECOND_FIELD : 0);
+ fflush(stdout);
+#endif
+#ifdef PRINTFRAME
+ printf(" target %08x past %08x future %08x\n",
+ current_frame,
+ forward_ref_frame,
+ backward_ref_frame);
+#endif
+#ifdef PRINTFRAME
+ if (picture_coding_type == XINE_PICT_P_TYPE)
+ printf(" coding type P_TYPE\n");
+ if (picture_coding_type == XINE_PICT_I_TYPE)
+ printf(" coding type I_TYPE\n");
+ if (picture_coding_type == XINE_PICT_B_TYPE)
+ printf(" coding type B_TYPE\n");
+ if (picture_coding_type == XINE_PICT_D_TYPE)
+ printf(" coding type D_TYPE\n");
+ fflush(stdout);
+#endif
+
+ if (picture_coding_type == XINE_PICT_B_TYPE)
+ xvmc_render_macro_blocks(
+ current_frame,
+ backward_ref_frame,
+ forward_ref_frame,
+ picture_structure,
+ second_field ? XVMC_SECOND_FIELD : 0,
+ mbs);
+ if (picture_coding_type == XINE_PICT_P_TYPE)
+ xvmc_render_macro_blocks(
+ current_frame,
+ NULL,
+ forward_ref_frame,
+ picture_structure,
+ second_field ? XVMC_SECOND_FIELD : 0,
+ mbs);
+ if (picture_coding_type == XINE_PICT_I_TYPE)
+ xvmc_render_macro_blocks(
+ current_frame,
+ NULL,
+ NULL,
+ picture_structure,
+ second_field ? XVMC_SECOND_FIELD : 0,
+ mbs);
+
+ mbs->num_blocks = 0;
+ mbs->macroblockptr = mbs->macroblockbaseptr;
+ mbs->xine_mc.blockptr = mbs->xine_mc.blockbaseptr;
+ }
+
+ xvmc_context_reader_unlock( &this->xvmc_lock );
+
+}
+
+
+
diff --git a/src/video_out/xvmc_vld.c b/src/video_out/xvmc_vld.c
new file mode 100644
index 000000000..d542ca515
--- /dev/null
+++ b/src/video_out/xvmc_vld.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2000-2004 the xine project
+ * Copyright (C) 2004 the Unichrome project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: xvmc_vld.c,v 1.1 2004/09/28 18:49:40 miguelfreitas Exp $
+ *
+ * xvmc_vld.c, X11 decoding accelerated video extension interface for xine
+ *
+ * Author: Thomas Hellström, (2004)
+ */
+
+#include "xxmc.h"
+#include <unistd.h>
+
+#ifdef HAVE_VLDXVMC
+void xvmc_vld_frame(struct vo_frame_s *this_gen)
+
+{
+ vo_frame_t *this = (vo_frame_t *) this_gen;
+ xxmc_frame_t
+ *cf = (xxmc_frame_t *) this;
+ xine_vld_frame_t
+ *vft = &(cf->xxmc_data.vld_frame);
+ xxmc_frame_t
+ *ff = (xxmc_frame_t *) vft->forward_reference_frame,
+ *bf = (xxmc_frame_t *) vft->backward_reference_frame;
+ XvMCMpegControl ctl;
+ xxmc_driver_t
+ *driver = (xxmc_driver_t *) cf->vo_frame.driver;
+ 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 |= (this->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->xvmc_surf;
+ if (bf) bs=bf->xvmc_surf;
+
+ /*
+ * Below is for interlaced streams and second_field.
+ */
+
+ if (ctl.picture_coding_type == XVMC_P_PICTURE)
+ bs = cf->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( &driver->xvmc_lock );
+ if ( ! xxmc_xvmc_surface_valid( driver, cf->xvmc_surf)) {
+ cf->xxmc_data.result = 128;
+ xvmc_context_reader_unlock( &driver->xvmc_lock );
+ return;
+ }
+ XVMCLOCKDISPLAY( driver->display );
+ XvMCLoadQMatrix(driver->display, &driver->context, &qmx);
+ while((cf->xxmc_data.result =
+ XvMCBeginSurface(driver->display, &driver->context, cf->xvmc_surf,
+ fs, bs, &ctl)));
+ XVMCUNLOCKDISPLAY( driver->display );
+ xvmc_context_reader_unlock( &driver->xvmc_lock );
+ driver->cpu_saver = 0.;
+}
+
+void xvmc_vld_slice(vo_frame_t *this_gen)
+{
+ xxmc_frame_t
+ *cf = (xxmc_frame_t *) this_gen;
+ xxmc_driver_t
+ *driver = (xxmc_driver_t *) cf->vo_frame.driver;
+
+ xvmc_context_reader_lock( &driver->xvmc_lock );
+ if ( ! xxmc_xvmc_surface_valid( driver, cf->xvmc_surf)) {
+ cf->xxmc_data.result = 128;
+ xvmc_context_reader_unlock( &driver->xvmc_lock );
+ return;
+ }
+ XVMCLOCKDISPLAY( driver->display );
+ cf->xxmc_data.result =
+ XvMCPutSlice2(driver->display,&driver->context,cf->xxmc_data.slice_data,
+ cf->xxmc_data.slice_data_size,cf->xxmc_data.slice_code);
+ /*
+ * 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( driver->display );
+ xvmc_context_reader_unlock( &driver->xvmc_lock );
+ if (driver->cpu_save_enabled) {
+ driver->cpu_saver += 1.;
+ if (driver->cpu_saver >= cf->xxmc_data.sleep) {
+ usleep(1);
+ driver->cpu_saver -= cf->xxmc_data.sleep;
+ }
+ }
+}
+#endif
+
+extern void xvmc_vld_flush(vo_frame_t *this_gen)
+{
+
+ xxmc_frame_t
+ *frame = (xxmc_frame_t *) this_gen;
+ xxmc_driver_t
+ *driver = (xxmc_driver_t *) this_gen->driver;
+
+ xvmc_context_reader_lock( &driver->xvmc_lock );
+
+ if ( ! xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) {
+ frame->xxmc_data.result = 128;
+ xvmc_context_reader_unlock( &driver->xvmc_lock );
+ return;
+ }
+
+ XVMCLOCKDISPLAY( driver->display );
+ frame->xxmc_data.result = XvMCFlushSurface( driver->display, frame->xvmc_surf );
+ frame->xxmc_data.result = XvMCSyncSurface( driver->display, frame->xvmc_surf );
+ XVMCUNLOCKDISPLAY( driver->display );
+
+ xvmc_context_reader_unlock( &driver->xvmc_lock );
+
+}
+
diff --git a/src/video_out/xxmc.h b/src/video_out/xxmc.h
new file mode 100644
index 000000000..b11d9207e
--- /dev/null
+++ b/src/video_out/xxmc.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2000-2004 the xine project
+ * Copyright (C) 2004 the unichrome project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: xxmc.h,v 1.1 2004/09/28 18:49:40 miguelfreitas Exp $
+ *
+ * video_out_xxmc.c, X11 decoding accelerated video extension interface for xine
+ *
+ * based on mpeg2dec code from
+ * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * Xv image support by Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de>
+ *
+ * overlay support by James Courtier-Dutton <James@superbug.demon.co.uk> - July 2001
+ * X11 unscaled overlay support by Miguel Freitas - Nov 2003
+ * XxMC implementation by Thomas Hellström - August 2004
+ */
+
+#ifndef _XXMC_H
+#define _XXMC_H
+
+#undef XVMC_THREAD_SAFE
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_XV
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+
+#if defined (__SVR4) && defined (__sun)
+# include <sys/int_types.h>
+#else
+# include <stdint.h>
+#endif
+
+#include <sys/types.h>
+#if defined(__FreeBSD__)
+#include <machine/param.h>
+#endif
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include <X11/extensions/XShm.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#ifdef HAVE_VLDXVMC
+ #include <X11/extensions/vldXvMC.h>
+#else
+ #include <X11/extensions/XvMClib.h>
+ #include <X11/extensions/XvMC.h>
+#endif
+
+#define LOG_MODULE "video_out_xxmc"
+#define LOG_VERBOSE
+/*
+#define LOG
+*/
+
+#include "xine.h"
+#include "video_out.h"
+#include "xine_internal.h"
+#include "alphablend.h"
+#include "deinterlace.h"
+#include "xineutils.h"
+#include "vo_scale.h"
+#include "x11osd.h"
+#include "accel_xvmc.h"
+
+#define FOURCC_IA44 0x34344149
+#define FOURCC_AI44 0x34344941
+#define XVMC_MAX_SURFACES 16
+#define XVMC_MAX_SUBPICTURES 4
+
+typedef struct xxmc_driver_s xxmc_driver_t;
+
+typedef struct {
+ xine_macroblocks_t xine_mc;
+ XvMCBlockArray blocks; /* pointer to memory for dct block array */
+ int num_blocks;
+ XvMCMacroBlock *macroblockptr; /* pointer to current macro block */
+ XvMCMacroBlock *macroblockbaseptr; /* pointer to base MacroBlock in MB array */
+ XvMCMacroBlockArray macro_blocks; /* pointer to memory for macroblock array */
+ int slices;
+} xvmc_macroblocks_t;
+
+
+typedef struct {
+ int value;
+ int min;
+ int max;
+ Atom atom;
+
+ cfg_entry_t *entry;
+
+ xxmc_driver_t *this;
+} xxmc_property_t;
+
+typedef struct {
+ vo_frame_t vo_frame;
+
+ int width, height, format;
+ double ratio;
+
+ XvImage *image;
+ XShmSegmentInfo shminfo;
+
+ /* XvMC specific stuff */
+
+ XvMCSurface *xvmc_surf;
+ xine_xxmc_t xxmc_data;
+} xxmc_frame_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 LOCK_AND_SURFACE_VALID(driver, surface) \
+ xvmc_context_reader_lock( &(driver)->xvmc_lock ); \
+ if (!xxmc_xvmc_surface_valid((driver),(surface))) { \
+ xvmc_context_reader_unlock( &(driver)->xvmc_lock ); \
+ return; \
+ }
+
+#ifdef XVMC_THREAD_SAFE
+#define XVMCLOCKDISPLAY(display)
+#define XVMCUNLOCKDISPLAY(display)
+#else
+#define XVMCLOCKDISPLAY(display) XLockDisplay(display);
+#define XVMCUNLOCKDISPLAY(display) XUnlockDisplay(display);
+#endif
+
+struct xxmc_driver_s {
+ vo_driver_t vo_driver;
+
+ config_values_t *config;
+
+ /* X11 / Xv related stuff */
+ Display *display;
+ int screen;
+ Drawable drawable;
+ unsigned int xv_format_yv12;
+ unsigned int xv_format_yuy2;
+ XVisualInfo vinfo;
+ GC gc;
+ XvPortID xv_port;
+ XColor black;
+
+ int use_shm;
+ int use_pitch_alignment;
+ xxmc_property_t props[VO_NUM_PROPERTIES];
+ uint32_t capabilities;
+ xxmc_frame_t *recent_frames[VO_NUM_RECENT_FRAMES];
+ xxmc_frame_t *cur_frame;
+ x11osd *xoverlay;
+ int ovl_changed;
+
+ /* all scaling information goes here */
+ vo_scale_t sc;
+ xxmc_frame_t deinterlace_frame;
+ int deinterlace_method;
+ int deinterlace_enabled;
+ int use_colorkey;
+ uint32_t colorkey;
+ int (*x11_old_error_handler) (Display *, XErrorEvent *);
+ xine_t *xine;
+
+ /* XvMC related stuff here */
+ xvmc_macroblocks_t macroblocks;
+ xvmc_capabilities_t *xvmc_cap;
+ unsigned 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,*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 xvmc_width;
+ unsigned xvmc_height;
+ int have_xvmc_autopaint;
+ int xoverlay_ck;
+
+ /*
+ * 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;
+};
+
+typedef struct {
+ video_driver_class_t driver_class;
+
+ config_values_t *config;
+ xine_t *xine;
+} xxmc_class_t;
+
+extern void xvmc_context_reader_unlock(context_lock_t *c);
+extern void xvmc_context_reader_lock(context_lock_t *c);
+extern int xxmc_xvmc_surface_valid(xxmc_driver_t *this, XvMCSurface *surf);
+
+extern void xvmc_vld_slice(vo_frame_t *this_gen);
+extern void xvmc_vld_frame(struct vo_frame_s *this_gen);
+extern void xvmc_vld_flush(vo_frame_t *this_gen);
+
+extern void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type,
+ int (*mv_field_sel)[2], int *dmvector,
+ int cbp,
+ int dct_type, vo_frame_t *current_frame,
+ vo_frame_t *forward_ref_frame,
+ vo_frame_t *backward_ref_frame,
+ int picture_structure,
+ int second_field, int (*f_mot_pmv)[2],
+ int (*b_mot_pmv)[2]);
+
+#endif
+#endif
diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am
index 61f4163c4..696a501b6 100644
--- a/src/xine-engine/Makefile.am
+++ b/src/xine-engine/Makefile.am
@@ -28,7 +28,8 @@ libxine_la_SOURCES = xine.c metronom.c configfile.c buffer.c \
input_rip.c info_helper.c
# FIXME: these are currently unused:
-EXTRA_DIST = lrb.c lrb.h
+EXTRA_DIST = lrb.c lrb.h accel_xvmc.h
+
libxine_la_DEPENDENCIES = @INTLLIBS@ $(XINEUTILS_LIB) $(zlib_dep) \
$(dirent_lib) $(pthread_dep) $(LIBXINEPOSIX)
diff --git a/src/xine-engine/accel_xvmc.h b/src/xine-engine/accel_xvmc.h
new file mode 100644
index 000000000..ea10a40ff
--- /dev/null
+++ b/src/xine-engine/accel_xvmc.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2000-2003 the xine project
+ * Copyright (C) 2004 the Unichrome project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: accel_xvmc.h,v 1.1 2004/09/28 18:49:40 miguelfreitas Exp $
+ *
+ *
+ * Common acceleration definitions for XvMC.
+ *
+ *
+ */
+
+#ifndef HAVE_XINE_ACCEL_H
+#define HAVE_XINE_ACCEL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+typedef struct xine_macroblock_s {
+ short *blockptr; /* pointer to current dct block */
+ short *blockbaseptr; /* pointer to base of dct block array in blocks */
+ short xvmc_accel; /* type of acceleration supported */
+} xine_macroblocks_t;
+
+typedef struct xine_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];
+ vo_frame_t *backward_reference_frame;
+ vo_frame_t *forward_reference_frame;
+} xine_vld_frame_t;
+
+
+typedef struct xine_xvmc_s {
+ xine_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,
+ vo_frame_t *current_frame,vo_frame_t *forward_ref_frame,
+ vo_frame_t *backward_ref_frame,int picture_structure,
+ int second_field,int (*f_mot_pmv)[2],int (*b_mot_pmv)[2]);
+} xine_xvmc_t ;
+
+typedef struct xine_xxmc_s {
+
+ /*
+ * We inherit the xine_xvmc_t properties.
+ */
+
+ xine_xvmc_t xvmc;
+
+ unsigned format;
+ unsigned mpeg;
+ unsigned acceleration;
+ xine_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_frame) (vo_frame_t *vo_img);
+ void (*proc_xxmc_begin) (vo_frame_t *vo_img);
+ void (*proc_xxmc_slice) (vo_frame_t *vo_img);
+ void (*proc_xxmc_flush) (vo_frame_t *vo_img);
+} xine_xxmc_t;
+
+ /*
+ * Register XvMC stream types here.
+ */
+
+#define XINE_XVMC_MPEG_1 0x00000001
+#define XINE_XVMC_MPEG_2 0x00000002
+#define XINE_XVMC_MPEG_4 0x00000004
+
+ /*
+ * Register XvMC acceleration levels here.
+ */
+
+#define XINE_XVMC_ACCEL_MOCOMP 0x00000001
+#define XINE_XVMC_ACCEL_IDCT 0x00000002
+#define XINE_XVMC_ACCEL_VLD 0x00000004
+
+
+/* xvmc acceleration types */
+#define XINE_VO_MOTION_ACCEL 1
+#define XINE_VO_IDCT_ACCEL 2
+#define XINE_VO_SIGNED_INTRA 4
+
+/* motion types */
+#define XINE_MC_FIELD 1
+#define XINE_MC_FRAME 2
+#define XINE_MC_16X8 2
+#define XINE_MC_DMV 3
+
+/* picture coding type */
+#define XINE_PICT_I_TYPE 1
+#define XINE_PICT_P_TYPE 2
+#define XINE_PICT_B_TYPE 3
+#define XINE_PICT_D_TYPE 4
+
+/* macroblock modes */
+#define XINE_MACROBLOCK_INTRA 1
+#define XINE_MACROBLOCK_PATTERN 2
+#define XINE_MACROBLOCK_MOTION_BACKWARD 4
+#define XINE_MACROBLOCK_MOTION_FORWARD 8
+#define XINE_MACROBLOCK_QUANT 16
+#define XINE_MACROBLOCK_DCT_TYPE_INTERLACED 32
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c
index 9f49b2115..5f8eca309 100644
--- a/src/xine-engine/post.c
+++ b/src/xine-engine/post.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: post.c,v 1.26 2004/05/29 14:45:25 mroi Exp $
+ * $Id: post.c,v 1.27 2004/09/28 18:49:40 miguelfreitas Exp $
*/
/*
@@ -345,34 +345,6 @@ static void post_frame_dispose(vo_frame_t *vo_img) {
_x_post_dec_usage(port);
}
-static void post_frame_proc_macro_block(int x,
- int y,
- int mb_type,
- int motion_type,
- int (*mv_field_sel)[2],
- int *dmvector,
- int cbp,
- int dct_type,
- vo_frame_t *current_frame,
- vo_frame_t *forward_ref_frame,
- vo_frame_t *backward_ref_frame,
- int picture_structure,
- int second_field,
- int (*f_mot_pmv)[2],
- int (*b_mot_pmv)[2]) {
- post_video_port_t *port = _x_post_video_frame_to_port(current_frame);
-
- if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
- _x_post_frame_copy_down(current_frame, current_frame->next);
- current_frame->next->proc_macro_block(x, y, mb_type, motion_type, mv_field_sel,
- dmvector, cbp, dct_type, current_frame->next,
- forward_ref_frame, backward_ref_frame,
- picture_structure, second_field,
- f_mot_pmv, b_mot_pmv);
- _x_post_frame_copy_up(current_frame, current_frame->next);
- if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
-}
-
vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) {
vo_frame_t *new_frame;
@@ -397,8 +369,6 @@ vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *
port->new_frame->proc_frame ? port->new_frame->proc_frame : NULL;
new_frame->proc_slice =
port->new_frame->proc_slice ? port->new_frame->proc_slice : NULL;
- new_frame->proc_macro_block =
- port->new_frame->proc_macro_block ? port->new_frame->proc_macro_block : NULL;
new_frame->field =
port->new_frame->field ? port->new_frame->field : post_frame_field;
new_frame->draw =
@@ -417,8 +387,6 @@ vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *
new_frame->proc_frame = post_frame_proc_frame;
if (frame->proc_slice && !new_frame->proc_slice)
new_frame->proc_slice = post_frame_proc_slice;
- if (frame->proc_macro_block && !new_frame->proc_macro_block)
- new_frame->proc_macro_block = post_frame_proc_macro_block;
}
return new_frame;
@@ -450,7 +418,7 @@ void _x_post_frame_copy_down(vo_frame_t *from, vo_frame_t *to) {
to->progressive_frame = from->progressive_frame;
to->picture_coding_type = from->picture_coding_type;
to->drawn = from->drawn;
- to->macroblocks = from->macroblocks;
+ to->accel_data = from->accel_data;
to->stream = from->stream;
if (to->extra_info != from->extra_info)
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index dfc6aa5b7..b482c2784 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out.c,v 1.206 2004/09/22 20:29:17 miguelfreitas Exp $
+ * $Id: video_out.c,v 1.207 2004/09/28 18:49:40 miguelfreitas Exp $
*
* frame allocation / queuing / scheduling / output functions
*/
@@ -335,7 +335,7 @@ static vo_frame_t *vo_get_frame (xine_video_port_t *this_gen,
img->crop_right = 0;
img->crop_top = 0;
img->crop_bottom = 0;
- img->macroblocks = NULL;
+
_x_extra_info_reset ( img->extra_info );
/* let driver ensure this image has the right format */
@@ -615,31 +615,36 @@ static vo_frame_t * duplicate_frame( vos_t *this, vo_frame_t *img ) {
pthread_mutex_unlock (&dupl->mutex);
- switch (img->format) {
- case XINE_IMGFMT_YV12:
- yv12_to_yv12(
- /* Y */
- img->base[0], img->pitches[0],
- dupl->base[0], dupl->pitches[0],
- /* U */
- img->base[1], img->pitches[1],
- dupl->base[1], dupl->pitches[1],
- /* V */
- img->base[2], img->pitches[2],
- dupl->base[2], dupl->pitches[2],
- /* width x height */
- img->width, img->height);
- break;
- case XINE_IMGFMT_YUY2:
- yuy2_to_yuy2(
- /* src */
- img->base[0], img->pitches[0],
- /* dst */
- dupl->base[0], dupl->pitches[0],
- /* width x height */
- img->width, img->height);
- break;
- }
+ if (dupl->proc_duplicate_frame_data) {
+ dupl->proc_duplicate_frame_data(dupl,img);
+ } else {
+
+ switch (img->format) {
+ case XINE_IMGFMT_YV12:
+ yv12_to_yv12(
+ /* Y */
+ img->base[0], img->pitches[0],
+ dupl->base[0], dupl->pitches[0],
+ /* U */
+ img->base[1], img->pitches[1],
+ dupl->base[1], dupl->pitches[1],
+ /* V */
+ img->base[2], img->pitches[2],
+ dupl->base[2], dupl->pitches[2],
+ /* width x height */
+ img->width, img->height);
+ break;
+ case XINE_IMGFMT_YUY2:
+ yuy2_to_yuy2(
+ /* src */
+ img->base[0], img->pitches[0],
+ /* dst */
+ dupl->base[0], dupl->pitches[0],
+ /* width x height */
+ img->width, img->height);
+ break;
+ }
+ }
dupl->bad_frame = 0;
dupl->pts = 0;
@@ -1661,6 +1666,7 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon
img = driver->alloc_frame (driver) ;
if (!img) break;
+ img->proc_duplicate_frame_data = NULL;
img->id = i;
diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h
index c96307471..ba35e2e2a 100644
--- a/src/xine-engine/video_out.h
+++ b/src/xine-engine/video_out.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out.h,v 1.110 2004/09/26 22:54:52 valtri Exp $
+ * $Id: video_out.h,v 1.111 2004/09/28 18:49:40 miguelfreitas Exp $
*
*
* xine version of video_out.h
@@ -60,13 +60,6 @@ typedef struct video_driver_class_s video_driver_class_t;
typedef struct vo_overlay_s vo_overlay_t;
typedef struct video_overlay_manager_s video_overlay_manager_t;
-typedef struct xine_macroblock_s {
- short *blockptr; /* pointer to current dct block */
- short *blockbaseptr; /* pointer to base of dct block array in blocks */
- short xvmc_accel; /* type of acceleration supported */
-} xine_macroblocks_t;
-
-
/* public part, video drivers may add private fields
*
* Remember that adding new functions to this structure requires
@@ -78,6 +71,11 @@ struct vo_frame_s {
* member functions
*/
+ /* Duplicate picture data and acceleration specific data of a frame. */
+ /* if the image format isn't already known by Xine. Currently this is needed */
+ /* For all image formats except XINE_IMGFMT_YV12 and XINE_IMGFMT_YUY2 */
+ void (*proc_duplicate_frame_data) (vo_frame_t *vo_img, vo_frame_t *src);
+
/* tell video driver to copy/convert the whole of this frame, may be NULL */
/* at least one of proc_frame() and proc_slice() MUST set the variable proc_called to 1 */
void (*proc_frame) (vo_frame_t *vo_img);
@@ -86,23 +84,6 @@ struct vo_frame_s {
/* at least one of proc_frame() and proc_slice() MUST set the variable proc_called to 1 */
void (*proc_slice) (vo_frame_t *vo_img, uint8_t **src);
- /* XvMC routine for rendering macroblocks, may be NULL */
- void (*proc_macro_block)(int x,
- int y,
- int mb_type,
- int motion_type,
- int (*mv_field_sel)[2],
- int *dmvector,
- int cbp,
- int dct_type,
- vo_frame_t *current_frame,
- vo_frame_t *forward_ref_frame,
- vo_frame_t *backward_ref_frame,
- int picture_structure,
- int second_field,
- int (*f_mot_pmv)[2],
- int (*b_mot_pmv)[2]);
-
/* tell video driver that the decoder starts a new field */
void (*field) (vo_frame_t *vo_img, int which_field);
@@ -161,8 +142,8 @@ struct vo_frame_s {
int flags; /* remember the frame flags */
int proc_called; /* track use of proc_*() methods */
- /* used to carry macroblocks information for XvMC acceleration */
- xine_macroblocks_t *macroblocks;
+ /* Used to carry private data for accelerated plugins.*/
+ void *accel_data;
/* "backward" references to where this frame originates from */
xine_video_port_t *port;
@@ -292,31 +273,7 @@ struct xine_video_port_s {
#define VO_CAP_XVMC_IDCT 0x00000008 /* driver can use XvMC idct acceleration */
#define VO_CAP_UNSCALED_OVERLAY 0x00000010 /* driver can blend overlay at output resolution */
#define VO_CAP_CROP 0x00000020 /* driver can crop */
-
-/* macroblock modes */
-#define XINE_MACROBLOCK_INTRA 1
-#define XINE_MACROBLOCK_PATTERN 2
-#define XINE_MACROBLOCK_MOTION_BACKWARD 4
-#define XINE_MACROBLOCK_MOTION_FORWARD 8
-#define XINE_MACROBLOCK_QUANT 16
-#define XINE_MACROBLOCK_DCT_TYPE_INTERLACED 32
-
-/* motion types */
-#define XINE_MC_FIELD 1
-#define XINE_MC_FRAME 2
-#define XINE_MC_16X8 2
-#define XINE_MC_DMV 3
-
-/* picture coding type */
-#define XINE_PICT_I_TYPE 1
-#define XINE_PICT_P_TYPE 2
-#define XINE_PICT_B_TYPE 3
-#define XINE_PICT_D_TYPE 4
-
-/* xvmc acceleration types */
-#define XINE_VO_MOTION_ACCEL 1
-#define XINE_VO_IDCT_ACCEL 2
-#define XINE_VO_SIGNED_INTRA 4
+#define VO_CAP_XXMC 0x00000040 /* driver can use extended XvMC */
/*