diff options
Diffstat (limited to 'libvo')
-rw-r--r-- | libvo/Makefile.am | 5 | ||||
-rw-r--r-- | libvo/Makefile.in | 462 | ||||
-rw-r--r-- | libvo/video_out.c | 63 | ||||
-rw-r--r-- | libvo/video_out_dx.c | 524 | ||||
-rw-r--r-- | libvo/video_out_null.c | 144 | ||||
-rw-r--r-- | libvo/video_out_pgm.c | 345 | ||||
-rw-r--r-- | libvo/video_out_sdl.c | 171 | ||||
-rw-r--r-- | libvo/video_out_x11.c | 638 | ||||
-rw-r--r-- | libvo/vo_internal.h | 38 |
9 files changed, 2390 insertions, 0 deletions
diff --git a/libvo/Makefile.am b/libvo/Makefile.am new file mode 100644 index 0000000..9fee50a --- /dev/null +++ b/libvo/Makefile.am @@ -0,0 +1,5 @@ +AM_CFLAGS = $(OPT_CFLAGS) $(LIBVO_CFLAGS) + +noinst_LIBRARIES = libvo.a +libvo_a_SOURCES = video_out.c video_out_x11.c video_out_dx.c video_out_sdl.c \ + video_out_null.c video_out_pgm.c vo_internal.h diff --git a/libvo/Makefile.in b/libvo/Makefile.in new file mode 100644 index 0000000..8707fe0 --- /dev/null +++ b/libvo/Makefile.in @@ -0,0 +1,462 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = libvo +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/cflags.m4 \ + $(top_srcdir)/m4/inttypes.m4 $(top_srcdir)/m4/keywords.m4 \ + $(top_srcdir)/m4/nonpic.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +libvo_a_AR = $(AR) $(ARFLAGS) +libvo_a_LIBADD = +am_libvo_a_OBJECTS = video_out.$(OBJEXT) video_out_x11.$(OBJEXT) \ + video_out_dx.$(OBJEXT) video_out_sdl.$(OBJEXT) \ + video_out_null.$(OBJEXT) video_out_pgm.$(OBJEXT) +libvo_a_OBJECTS = $(am_libvo_a_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/.auto/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libvo_a_SOURCES) +DIST_SOURCES = $(libvo_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AR = @AR@ +ARCH_OPT_CFLAGS = @ARCH_OPT_CFLAGS@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBMPEG2_CFLAGS = @LIBMPEG2_CFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVO_CFLAGS = @LIBVO_CFLAGS@ +LIBVO_LIBS = @LIBVO_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MPEG2DEC_CFLAGS = @MPEG2DEC_CFLAGS@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPT_CFLAGS = @OPT_CFLAGS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SDLCONFIG = @SDLCONFIG@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XMKMF = @XMKMF@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CFLAGS = $(OPT_CFLAGS) $(LIBVO_CFLAGS) +noinst_LIBRARIES = libvo.a +libvo_a_SOURCES = video_out.c video_out_x11.c video_out_dx.c video_out_sdl.c \ + video_out_null.c video_out_pgm.c vo_internal.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libvo/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign libvo/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libvo.a: $(libvo_a_OBJECTS) $(libvo_a_DEPENDENCIES) + -rm -f libvo.a + $(libvo_a_AR) libvo.a $(libvo_a_OBJECTS) $(libvo_a_LIBADD) + $(RANLIB) libvo.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_out.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_out_dx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_out_null.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_out_pgm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_out_sdl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_out_x11.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libvo/video_out.c b/libvo/video_out.c new file mode 100644 index 0000000..ebe0c53 --- /dev/null +++ b/libvo/video_out.c @@ -0,0 +1,63 @@ +/* + * video_out.c + * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include <stdlib.h> +#include <inttypes.h> + +#include "video_out.h" +#include "vo_internal.h" + +/* Externally visible list of all vo drivers */ + +static vo_driver_t video_out_drivers[] = { +#ifdef LIBVO_XV + {"xv", vo_xv_open}, + {"xv2", vo_xv2_open}, +#endif +#ifdef LIBVO_X11 + {"x11", vo_x11_open}, +#endif +#ifdef LIBVO_DX + {"dxrgb", vo_dxrgb_open}, + {"dx", vo_dx_open}, +#endif +#ifdef LIBVO_SDL + {"sdl", vo_sdl_open}, +#endif + {"null", vo_null_open}, + {"nullslice", vo_nullslice_open}, + {"nullskip", vo_nullskip_open}, + {"nullrgb16", vo_nullrgb16_open}, + {"nullrgb32", vo_nullrgb32_open}, + {"pgm", vo_pgm_open}, + {"pgmpipe", vo_pgmpipe_open}, + {"md5", vo_md5_open}, + {NULL, NULL} +}; + +vo_driver_t const * vo_drivers (void) +{ + return video_out_drivers; +} diff --git a/libvo/video_out_dx.c b/libvo/video_out_dx.c new file mode 100644 index 0000000..36de68a --- /dev/null +++ b/libvo/video_out_dx.c @@ -0,0 +1,524 @@ +/* + * video_out_dx.c + * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> + * + * Contributed by Gildas Bazin <gbazin@netcourrier.com> + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#ifdef LIBVO_DX + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> + +#include "mpeg2.h" +#include "video_out.h" +#include "mpeg2convert.h" + +#include <ddraw.h> +#include <initguid.h> + +#define USE_OVERLAY_TRIPLE_BUFFERING 0 + +/* + * DirectDraw GUIDs. + * Defining them here allows us to get rid of the dxguid library during link. + */ +DEFINE_GUID (IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56); +DEFINE_GUID (IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27); + +#define FOURCC_YV12 0x32315659 + +typedef struct { + vo_instance_t vo; + int width; + int height; + + HWND window; + RECT window_coords; + HINSTANCE hddraw_dll; + LPDIRECTDRAW2 ddraw; + LPDIRECTDRAWSURFACE2 display; + LPDIRECTDRAWCLIPPER clipper; + LPDIRECTDRAWSURFACE2 frame[3]; + int index; + + LPDIRECTDRAWSURFACE2 overlay; + uint8_t * yuv[3]; + int stride; +} dx_instance_t; + +static void update_overlay (dx_instance_t * instance) +{ + DDOVERLAYFX ddofx; + DWORD dwFlags; + + memset (&ddofx, 0, sizeof (DDOVERLAYFX)); + ddofx.dwSize = sizeof (DDOVERLAYFX); + dwFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE; + IDirectDrawSurface2_UpdateOverlay (instance->overlay, NULL, + instance->display, + &instance->window_coords, + dwFlags, &ddofx); +} + +static long FAR PASCAL event_procedure (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + RECT rect_window; + POINT point_window; + dx_instance_t * instance; + + switch (message) { + + case WM_WINDOWPOSCHANGED: + instance = (dx_instance_t *) GetWindowLong (hwnd, GWL_USERDATA); + + /* update the window position and size */ + point_window.x = 0; + point_window.y = 0; + ClientToScreen (hwnd, &point_window); + instance->window_coords.left = point_window.x; + instance->window_coords.top = point_window.y; + GetClientRect (hwnd, &rect_window); + instance->window_coords.right = rect_window.right + point_window.x; + instance->window_coords.bottom = rect_window.bottom + point_window.y; + + /* update the overlay */ + if (instance->overlay && instance->display) + update_overlay (instance); + + return 0; + + case WM_CLOSE: /* forbid the user to close the window */ + return 0; + + case WM_DESTROY: /* just destroy the window */ + PostQuitMessage (0); + return 0; + } + + return DefWindowProc (hwnd, message, wParam, lParam); +} + +static void check_events (dx_instance_t * instance) +{ + MSG msg; + + while (PeekMessage (&msg, instance->window, 0, 0, PM_REMOVE)) { + TranslateMessage (&msg); + DispatchMessage (&msg); + } +} + +static int create_window (dx_instance_t * instance) +{ + RECT rect_window; + WNDCLASSEX wc; + + wc.cbSize = sizeof (WNDCLASSEX); + wc.style = CS_DBLCLKS; + wc.lpfnWndProc = (WNDPROC) event_procedure; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle (NULL); + wc.hIcon = NULL; + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hbrBackground = CreateSolidBrush (RGB (0, 0, 0)); + wc.lpszMenuName = NULL; + wc.lpszClassName = "libvo_dx"; + wc.hIconSm = NULL; + if (!RegisterClassEx (&wc)) { + fprintf (stderr, "Can not register window class\n"); + return 1; + } + + rect_window.top = 10; + rect_window.left = 10; + rect_window.right = rect_window.left + instance->width; + rect_window.bottom = rect_window.top + instance->height; + AdjustWindowRect (&rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0); + + instance->window = CreateWindow ("libvo_dx", "mpeg2dec", + WS_OVERLAPPEDWINDOW | WS_SIZEBOX, + CW_USEDEFAULT, 0, + rect_window.right - rect_window.left, + rect_window.bottom - rect_window.top, + NULL, NULL, GetModuleHandle (NULL), NULL); + if (instance->window == NULL) { + fprintf (stderr, "Can not create window\n"); + return 1; + } + + /* store a directx_instance pointer into the window local storage + * (for later use in event_handler). + * We need to use SetWindowLongPtr when it is available in mingw */ + SetWindowLong (instance->window, GWL_USERDATA, (LONG) instance); + + ShowWindow (instance->window, SW_SHOW); + + return 0; +} + +static LPDIRECTDRAWSURFACE2 alloc_surface (dx_instance_t * instance, + DDSURFACEDESC * ddsd) +{ + LPDIRECTDRAWSURFACE surface; + LPDIRECTDRAWSURFACE2 surface2; + + if (DD_OK != IDirectDraw2_CreateSurface (instance->ddraw, ddsd, + &surface, NULL) || + DD_OK != IDirectDrawSurface_QueryInterface (surface, + &IID_IDirectDrawSurface2, + (LPVOID *) &surface2)) { + fprintf (stderr, "Can not create directDraw frame surface\n"); + return NULL; + } + IDirectDrawSurface_Release (surface); + + return surface2; +} + +static int dx_init (dx_instance_t *instance) +{ + HRESULT (WINAPI * OurDirectDrawCreate) (GUID *, LPDIRECTDRAW *, + IUnknown *); + LPDIRECTDRAW ddraw; + DDSURFACEDESC ddsd; + + /* load direct draw DLL */ + instance->hddraw_dll = LoadLibrary ("DDRAW.DLL"); + if (instance->hddraw_dll == NULL) { + fprintf (stderr, "Can not load DDRAW.DLL\n"); + return 1; + } + + ddraw = NULL; + OurDirectDrawCreate = (void *) GetProcAddress (instance->hddraw_dll, + "DirectDrawCreate"); + if (OurDirectDrawCreate == NULL || + DD_OK != OurDirectDrawCreate (NULL, &ddraw, NULL) || + DD_OK != IDirectDraw_QueryInterface (ddraw, &IID_IDirectDraw2, + (LPVOID *) &instance->ddraw) || + DD_OK != IDirectDraw_SetCooperativeLevel (instance->ddraw, + instance->window, + DDSCL_NORMAL)) { + fprintf (stderr, "Can not initialize directDraw interface\n"); + return 1; + } + IDirectDraw_Release (ddraw); + + memset (&ddsd, 0, sizeof (DDSURFACEDESC)); + ddsd.dwSize = sizeof (DDSURFACEDESC); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + instance->display = alloc_surface (instance, &ddsd); + if (instance->display == NULL) { + fprintf (stderr, "Can not create directDraw display surface\n"); + return 1; + } + + if (DD_OK != IDirectDraw2_CreateClipper (instance->ddraw, 0, + &instance->clipper, NULL) || + DD_OK != IDirectDrawClipper_SetHWnd (instance->clipper, 0, + instance->window) || + DD_OK != IDirectDrawSurface_SetClipper (instance->display, + instance->clipper)) { + fprintf (stderr, "Can not initialize directDraw clipper\n"); + return 1; + } + + return 0; +} + +static int common_setup (dx_instance_t * instance, int width, int height) +{ + instance->width = width; + instance->height = height; + instance->index = 0; + + if (create_window (instance) || dx_init (instance)) + return 1; + return 0; +} + +static int dxrgb_setup (vo_instance_t * _instance, unsigned int width, + unsigned int height, unsigned int chroma_width, + unsigned int chroma_height, vo_setup_result_t * result) +{ + dx_instance_t * instance = (dx_instance_t *) _instance; + HDC hdc; + int bpp; + + if (common_setup (instance, width, height)) + return 1; + + hdc = GetDC (NULL); + bpp = GetDeviceCaps (hdc, BITSPIXEL); + ReleaseDC (NULL, hdc); + + result->convert = mpeg2convert_rgb (MPEG2CONVERT_RGB, bpp); + return 0; +} + +static LPDIRECTDRAWSURFACE2 alloc_frame (dx_instance_t * instance) +{ + DDSURFACEDESC ddsd; + LPDIRECTDRAWSURFACE2 surface; + + memset (&ddsd, 0, sizeof (DDSURFACEDESC)); + ddsd.dwSize = sizeof (DDSURFACEDESC); + ddsd.ddpfPixelFormat.dwSize = sizeof (DDPIXELFORMAT); + ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS; + ddsd.dwHeight = instance->height; + ddsd.dwWidth = instance->width; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + + surface = alloc_surface (instance, &ddsd); + if (surface == NULL) + fprintf (stderr, "Can not create directDraw frame surface\n"); + return surface; +} + +static void * surface_addr (LPDIRECTDRAWSURFACE2 surface, int * stride) +{ + DDSURFACEDESC ddsd; + + memset (&ddsd, 0, sizeof (DDSURFACEDESC)); + ddsd.dwSize = sizeof (DDSURFACEDESC); + IDirectDrawSurface2_Lock (surface, NULL, &ddsd, + DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL); + IDirectDrawSurface2_Unlock (surface, NULL); + *stride = ddsd.lPitch; + return ddsd.lpSurface; +} + +static void dx_setup_fbuf (vo_instance_t * _instance, + uint8_t ** buf, void ** id) +{ + dx_instance_t * instance = (dx_instance_t *) _instance; + int stride; + + *id = instance->frame[instance->index++] = alloc_frame (instance); + buf[0] = surface_addr (*id, &stride); + buf[1] = NULL; buf[2] = NULL; +} + +static void dxrgb_draw_frame (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + dx_instance_t * instance = (dx_instance_t *) _instance; + LPDIRECTDRAWSURFACE2 surface = (LPDIRECTDRAWSURFACE2) id; + DDBLTFX ddbltfx; + + check_events (instance); + + memset (&ddbltfx, 0, sizeof (DDBLTFX)); + ddbltfx.dwSize = sizeof (DDBLTFX); + ddbltfx.dwDDFX = DDBLTFX_NOTEARING; + if (DDERR_SURFACELOST == + IDirectDrawSurface2_Blt (instance->display, &instance->window_coords, + surface, NULL, DDBLT_WAIT, &ddbltfx)) { + /* restore surface and try again */ + IDirectDrawSurface2_Restore (instance->display); + IDirectDrawSurface2_Blt (instance->display, &instance->window_coords, + surface, NULL, DDBLT_WAIT, &ddbltfx); + } +} + +static vo_instance_t * common_open (int setup (vo_instance_t *, + unsigned int, unsigned int, + unsigned int, unsigned int, + vo_setup_result_t *), + void setup_fbuf (vo_instance_t *, + uint8_t **, void **), + void draw (vo_instance_t *, + uint8_t * const *, void * id)) +{ + dx_instance_t * instance; + + instance = malloc (sizeof (dx_instance_t)); + if (instance == NULL) + return NULL; + + memset (instance, 0, sizeof (dx_instance_t)); + instance->vo.setup = setup; + instance->vo.setup_fbuf = setup_fbuf; + instance->vo.set_fbuf = NULL; + instance->vo.start_fbuf = NULL; + instance->vo.draw = draw; + instance->vo.discard = NULL; + instance->vo.close = NULL; //dx_close; + + return (vo_instance_t *) instance; +} + +vo_instance_t * vo_dxrgb_open (void) +{ + return common_open (dxrgb_setup, dx_setup_fbuf, dxrgb_draw_frame); +} + +static LPDIRECTDRAWSURFACE2 alloc_overlay (dx_instance_t * instance) +{ + DDSURFACEDESC ddsd; + LPDIRECTDRAWSURFACE2 surface; + + memset (&ddsd, 0, sizeof (DDSURFACEDESC)); + ddsd.dwSize = sizeof (DDSURFACEDESC); + ddsd.ddpfPixelFormat.dwSize = sizeof (DDPIXELFORMAT); + ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS; + ddsd.dwHeight = instance->height; + ddsd.dwWidth = instance->width; + ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + ddsd.ddpfPixelFormat.dwFourCC = FOURCC_YV12; + ddsd.dwFlags |= DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY; +#if USE_OVERLAY_TRIPLE_BUFFERING + ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP; +#endif + ddsd.dwBackBufferCount = 2; + + surface = alloc_surface (instance, &ddsd); + if (surface == NULL) + fprintf (stderr, "Can not create directDraw frame surface\n"); + return surface; +} + +static int dx_setup (vo_instance_t * _instance, unsigned int width, + unsigned int height, unsigned int chroma_width, + unsigned int chroma_height, vo_setup_result_t * result) +{ + dx_instance_t * instance = (dx_instance_t *) _instance; + LPDIRECTDRAWSURFACE2 surface; + DDSURFACEDESC ddsd; + + if (common_setup (instance, width, height)) + return 1; + + instance->overlay = alloc_overlay (instance); + if (!instance->overlay) + return 1; + update_overlay (instance); + + surface = instance->overlay; + + /* Get the back buffer */ + memset (&ddsd.ddsCaps, 0, sizeof (DDSCAPS)); + ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; + if (DD_OK != IDirectDrawSurface2_GetAttachedSurface (instance->overlay, + &ddsd.ddsCaps, + &surface)) + surface = instance->overlay; + + instance->yuv[0] = surface_addr (surface, &instance->stride); + instance->yuv[2] = instance->yuv[0] + instance->stride * instance->height; + instance->yuv[1] = + instance->yuv[2] + (instance->stride * instance->height >> 2); + + result->convert = NULL; + return 0; +} + +static void copy_yuv_picture (dx_instance_t * instance, + uint8_t * const * buf, void * id) +{ + uint8_t * dest[3]; + int width, i; + + dest[0] = instance->yuv[0]; + dest[1] = instance->yuv[1]; + dest[2] = instance->yuv[2]; + + width = instance->width; + for (i = 0; i < instance->height >> 1; i++) { + memcpy (dest[0], buf[0] + 2 * i * width, width); + dest[0] += instance->stride; + memcpy (dest[0], buf[0] + (2 * i + 1) * width, width); + dest[0] += instance->stride; + memcpy (dest[1], buf[1] + i * (width >> 1), width >> 1); + dest[1] += instance->stride >> 1; + memcpy (dest[2], buf[2] + i * (width >> 1), width >> 1); + dest[2] += instance->stride >> 1; + } +} + +static void dx_draw_frame (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + dx_instance_t * instance = (dx_instance_t *) _instance; + + check_events (instance); + + copy_yuv_picture (instance, buf, id); + + if (DDERR_SURFACELOST == + IDirectDrawSurface2_Flip (instance->overlay, NULL, DDFLIP_WAIT)) { + /* restore surfaces and try again */ + IDirectDrawSurface2_Restore (instance->display); + IDirectDrawSurface2_Restore (instance->overlay); + IDirectDrawSurface2_Flip (instance->overlay, NULL, DDFLIP_WAIT); + } +} + +vo_instance_t * vo_dx_open (void) +{ + return common_open (dx_setup, NULL, dx_draw_frame); +} + +#if 0 +static void dx_close (vo_instance_t * _instance) +{ + dx_instance_t * instance; + int i; + + instance = (dx_instance_t *) _instance; + + if (instance->using_overlay && instance->overlay) { + IDirectDrawSurface2_Release (instance->overlay); + instance->overlay = NULL; + } else + for (i = 0; i < 3; i++) { + if (instance->frame[i].p_surface != NULL) + IDirectDrawSurface2_Release (instance->frame[i].p_surface); + instance->frame[i].p_surface = NULL; + } + + if (instance->clipper != NULL) + IDirectDrawClipper_Release (instance->clipper); + + if (instance->display != NULL) + IDirectDrawSurface2_Release (instance->display); + + if (instance->ddraw != NULL) + IDirectDraw2_Release (instance->ddraw); + + if (instance->hddraw_dll != NULL) + FreeLibrary (instance->hddraw_dll); + + if (instance->window != NULL) + DestroyWindow (instance->window); +} + +#endif +#endif diff --git a/libvo/video_out_null.c b/libvo/video_out_null.c new file mode 100644 index 0000000..eb2608f --- /dev/null +++ b/libvo/video_out_null.c @@ -0,0 +1,144 @@ +/* + * video_out_null.c + * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include <stdlib.h> +#include <inttypes.h> + +#include "mpeg2.h" +#include "video_out.h" +#include "vo_internal.h" +#include "mpeg2convert.h" + +static void null_draw_frame (vo_instance_t * instance, + uint8_t * const * buf, void * id) +{ +} + +static vo_instance_t * internal_open (int setup (vo_instance_t *, unsigned int, + unsigned int, unsigned int, + unsigned int, + vo_setup_result_t *), + void draw (vo_instance_t *, + uint8_t * const *, void *)) +{ + vo_instance_t * instance; + + instance = (vo_instance_t *) malloc (sizeof (vo_instance_t)); + if (instance == NULL) + return NULL; + + instance->setup = setup; + instance->setup_fbuf = NULL; + instance->set_fbuf = NULL; + instance->start_fbuf = NULL; + instance->draw = draw; + instance->discard = NULL; + instance->close = (void (*) (vo_instance_t *)) free; + + return instance; +} + +static int null_setup (vo_instance_t * instance, unsigned int width, + unsigned int height, unsigned int chroma_width, + unsigned int chroma_height, vo_setup_result_t * result) +{ + result->convert = NULL; + return 0; +} + +vo_instance_t * vo_null_open (void) +{ + return internal_open (null_setup, null_draw_frame); +} + +vo_instance_t * vo_nullskip_open (void) +{ + return internal_open (null_setup, NULL); +} + +static void nullslice_start (void * id, const mpeg2_fbuf_t * fbuf, + const mpeg2_picture_t * picture, + const mpeg2_gop_t * gop) +{ +} + +static void nullslice_copy (void * id, uint8_t * const * src, + unsigned int v_offset) +{ +} + +static int nullslice_convert (int stage, void * id, + const mpeg2_sequence_t * seq, + int stride, uint32_t accel, void * arg, + mpeg2_convert_init_t * result) +{ + result->id_size = 0; + result->buf_size[0] = result->buf_size[1] = result->buf_size[2] = 0; + result->start = nullslice_start; + result->copy = nullslice_copy; + return 0; +} + +static int nullslice_setup (vo_instance_t * instance, unsigned int width, + unsigned int height, unsigned int chroma_width, + unsigned int chroma_height, + vo_setup_result_t * result) +{ + result->convert = nullslice_convert; + return 0; +} + +vo_instance_t * vo_nullslice_open (void) +{ + return internal_open (nullslice_setup, null_draw_frame); +} + +static int nullrgb16_setup (vo_instance_t * instance, unsigned int width, + unsigned int height, unsigned int chroma_width, + unsigned int chroma_height, + vo_setup_result_t * result) +{ + result->convert = mpeg2convert_rgb16; + return 0; +} + +static int nullrgb32_setup (vo_instance_t * instance, unsigned int width, + unsigned int height, unsigned int chroma_width, + unsigned int chroma_height, + vo_setup_result_t * result) +{ + result->convert = mpeg2convert_rgb32; + return 0; +} + +vo_instance_t * vo_nullrgb16_open (void) +{ + return internal_open (nullrgb16_setup, null_draw_frame); +} + +vo_instance_t * vo_nullrgb32_open (void) +{ + return internal_open (nullrgb32_setup, null_draw_frame); +} diff --git a/libvo/video_out_pgm.c b/libvo/video_out_pgm.c new file mode 100644 index 0000000..ef9ad65 --- /dev/null +++ b/libvo/video_out_pgm.c @@ -0,0 +1,345 @@ +/* + * video_out_pgm.c + * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 2003 Regis Duchesne <hpreg@zoy.org> + * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * MD5 code derived from linux kernel GPL implementation + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> + +#include "video_out.h" +#include "vo_internal.h" + +typedef struct pgm_instance_s { + vo_instance_t vo; + int framenum; + int width; + int height; + int chroma_width; + int chroma_height; + char header[1024]; + void (* writer) (struct pgm_instance_s *, uint8_t *, size_t); + FILE * file; + uint32_t md5_hash[4]; + uint32_t md5_block[16]; + uint32_t md5_bytes; +} pgm_instance_t; + +static void file_writer (pgm_instance_t * instance, uint8_t * ptr, size_t size) +{ + fwrite (ptr, size, 1, instance->file); +} + +static void internal_draw_frame (pgm_instance_t * instance, + uint8_t * const * buf) +{ + static uint8_t black[16384] = { 0 }; + int i; + + instance->writer (instance, (uint8_t *)instance->header, + strlen (instance->header)); + for (i = 0; i < instance->height; i++) { + instance->writer (instance, buf[0] + i * instance->width, + instance->width); + instance->writer (instance, black, + 2 * instance->chroma_width - instance->width); + } + for (i = 0; i < instance->chroma_height; i++) { + instance->writer (instance, buf[1] + i * instance->chroma_width, + instance->chroma_width); + instance->writer (instance, buf[2] + i * instance->chroma_width, + instance->chroma_width); + } +} + +static void pgm_draw_frame (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + pgm_instance_t * instance = (pgm_instance_t *) _instance; + char filename[128]; + + sprintf (filename, "%d.pgm", instance->framenum++); + instance->file = fopen (filename, "wb"); + if (instance->file == NULL) + return; + internal_draw_frame (instance, buf); + fclose (instance->file); +} + +static int pgm_setup (vo_instance_t * _instance, unsigned int width, + unsigned int height, unsigned int chroma_width, + unsigned int chroma_height, vo_setup_result_t * result) +{ + pgm_instance_t * instance; + + instance = (pgm_instance_t *) _instance; + + /* + * Layout of the Y, U, and V buffers in our pgm image + * + * YY YY YY + * 420: YY 422: YY 444: YY + * UV UV UUVV + * UV UUVV + */ + if (width > 2 * chroma_width) + return 1; + + instance->width = width; + instance->height = height; + instance->chroma_width = chroma_width; + instance->chroma_height = chroma_height; + sprintf (instance->header, "P5\n%d %d\n255\n", 2 * chroma_width, + height + chroma_height); + result->convert = NULL; + return 0; +} + +static vo_instance_t * internal_open (void draw (vo_instance_t *, + uint8_t * const *, void *), + void writer (pgm_instance_t *, + uint8_t *, size_t)) +{ + pgm_instance_t * instance; + + instance = (pgm_instance_t *) malloc (sizeof (pgm_instance_t)); + if (instance == NULL) + return NULL; + + instance->vo.setup = pgm_setup; + instance->vo.setup_fbuf = NULL; + instance->vo.set_fbuf = NULL; + instance->vo.start_fbuf = NULL; + instance->vo.draw = draw; + instance->vo.discard = NULL; + instance->vo.close = (void (*) (vo_instance_t *)) free; + instance->framenum = 0; + instance->writer = writer; + instance->file = stdout; + + return (vo_instance_t *) instance; +} + +vo_instance_t * vo_pgm_open (void) +{ + return internal_open (pgm_draw_frame, file_writer); +} + +static void pgmpipe_draw_frame (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + pgm_instance_t * instance = (pgm_instance_t *) _instance; + internal_draw_frame (instance, buf); +} + +vo_instance_t * vo_pgmpipe_open (void) +{ + return internal_open (pgmpipe_draw_frame, file_writer); +} + +#define F1(x,y,z) (z ^ (x & (y ^ z))) +#define F2(x,y,z) F1 (z, x, y) +#define F3(x,y,z) (x ^ y ^ z) +#define F4(x,y,z) (y ^ (x | ~z)) + +#define MD5STEP(f,w,x,y,z,in,s) do { \ + w += f (x, y, z) + in; w = ((w << s) | (w >> (32 - s))) + x; \ +} while (0) + +static void md5_transform (uint32_t * hash, uint32_t const * in) +{ + uint32_t a, b, c, d; + + a = hash[0]; + b = hash[1]; + c = hash[2]; + d = hash[3]; + + MD5STEP (F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP (F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP (F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP (F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP (F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP (F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP (F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP (F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP (F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP (F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP (F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP (F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP (F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP (F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP (F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP (F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP (F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP (F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP (F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP (F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP (F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP (F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP (F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP (F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP (F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP (F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP (F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP (F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP (F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP (F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP (F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP (F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP (F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP (F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP (F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP (F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP (F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP (F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP (F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP (F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP (F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP (F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP (F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP (F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP (F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP (F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP (F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP (F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP (F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP (F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP (F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP (F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP (F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP (F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP (F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP (F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP (F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP (F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP (F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP (F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP (F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP (F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; +} + +static inline uint32_t swap (uint32_t x) +{ + return (((x & 0xff) << 24) | ((x & 0xff00) << 8) | + ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24)); +} + +static inline void little_endian (uint32_t * buf, unsigned int words) +{ +#ifdef WORDS_BIGENDIAN + while (words--) + buf[words] = swap (buf[words]); +#endif +} + +static void md5_writer (pgm_instance_t * instance, uint8_t * ptr, size_t size) +{ + const unsigned int offset = instance->md5_bytes & 0x3f; + + instance->md5_bytes += size; + + if (offset + size < 64) { + memcpy ((char *)instance->md5_block + offset, ptr, size); + return; + } else if (offset) { + const int avail = 64 - offset; + memcpy ((char *)instance->md5_block + offset, ptr, avail); + little_endian (instance->md5_block, 16); + md5_transform (instance->md5_hash, instance->md5_block); + ptr += avail; + size -= avail; + } + + while (size >= 64) { +#ifndef ARCH_X86 + memcpy (instance->md5_block, ptr, 64); + little_endian (instance->md5_block, 16); + md5_transform (instance->md5_hash, instance->md5_block); +#else + md5_transform (instance->md5_hash, (uint32_t *)ptr); +#endif + ptr += 64; + size -= 64; + } + + memcpy (instance->md5_block, ptr, size); +} + +static void md5_draw_frame (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + pgm_instance_t * instance = (pgm_instance_t *) _instance; + unsigned int offset; + uint8_t * p; + int padding; + + instance->md5_hash[0] = 0x67452301; + instance->md5_hash[1] = 0xefcdab89; + instance->md5_hash[2] = 0x98badcfe; + instance->md5_hash[3] = 0x10325476; + instance->md5_bytes = 0; + + internal_draw_frame (instance, buf); + + offset = instance->md5_bytes & 0x3f; + p = (uint8_t *)instance->md5_block + offset; + padding = 55 - offset; + + *p++ = 0x80; + if (padding < 0) { + memset (p, 0, padding + 8); + little_endian (instance->md5_block, 16); + md5_transform (instance->md5_hash, instance->md5_block); + p = (uint8_t *)instance->md5_block; + padding = 56; + } + + memset (p, 0, padding); + instance->md5_block[14] = instance->md5_bytes << 3; + instance->md5_block[15] = instance->md5_bytes >> 29; + little_endian (instance->md5_block, 14); + md5_transform (instance->md5_hash, instance->md5_block); + + printf ("%08x%08x%08x%08x *%d.pgm\n", swap (instance->md5_hash[0]), + swap (instance->md5_hash[1]) , swap (instance->md5_hash[2]), + swap (instance->md5_hash[3]), instance->framenum++); +} + +vo_instance_t * vo_md5_open (void) +{ + return internal_open (md5_draw_frame, md5_writer); +} diff --git a/libvo/video_out_sdl.c b/libvo/video_out_sdl.c new file mode 100644 index 0000000..6dc32f5 --- /dev/null +++ b/libvo/video_out_sdl.c @@ -0,0 +1,171 @@ +/* + * video_out_sdl.c + * + * Copyright (C) 2000-2003 Ryan C. Gordon <icculus@lokigames.com> and + * Dominik Schnitzer <aeneas@linuxvideo.org> + * + * SDL info, source, and binaries can be found at http://www.libsdl.org/ + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#ifdef LIBVO_SDL + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <SDL/SDL.h> +#include <inttypes.h> + +#include "video_out.h" +#include "vo_internal.h" + +typedef struct { + vo_instance_t vo; + int width; + int height; + SDL_Surface * surface; + Uint32 sdlflags; + Uint8 bpp; +} sdl_instance_t; + +static void sdl_setup_fbuf (vo_instance_t * _instance, + uint8_t ** buf, void ** id) +{ + sdl_instance_t * instance = (sdl_instance_t *) _instance; + SDL_Overlay * overlay; + + *id = overlay = SDL_CreateYUVOverlay (instance->width, instance->height, + SDL_YV12_OVERLAY, instance->surface); + buf[0] = overlay->pixels[0]; + buf[1] = overlay->pixels[2]; + buf[2] = overlay->pixels[1]; + if (((long)buf[0] & 15) || ((long)buf[1] & 15) || ((long)buf[2] & 15)) { + fprintf (stderr, "Unaligned buffers. Anyone know how to fix this ?\n"); + exit (1); + } +} + +static void sdl_start_fbuf (vo_instance_t * instance, + uint8_t * const * buf, void * id) +{ + SDL_LockYUVOverlay ((SDL_Overlay *) id); +} + +static void sdl_draw_frame (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + sdl_instance_t * instance = (sdl_instance_t *) _instance; + SDL_Overlay * overlay = (SDL_Overlay *) id; + SDL_Event event; + + while (SDL_PollEvent (&event)) + if (event.type == SDL_VIDEORESIZE) + instance->surface = + SDL_SetVideoMode (event.resize.w, event.resize.h, + instance->bpp, instance->sdlflags); + SDL_DisplayYUVOverlay (overlay, &(instance->surface->clip_rect)); +} + +static void sdl_discard (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + SDL_UnlockYUVOverlay ((SDL_Overlay *) id); +} + +#if 0 +static void sdl_close (vo_instance_t * _instance) +{ + sdl_instance_t * instance; + int i; + + instance = (sdl_instance_t *) _instance; + for (i = 0; i < 3; i++) + SDL_FreeYUVOverlay (instance->frame[i].overlay); + SDL_FreeSurface (instance->surface); + SDL_QuitSubSystem (SDL_INIT_VIDEO); +} +#endif + +static int sdl_setup (vo_instance_t * _instance, unsigned int width, + unsigned int height, unsigned int chroma_width, + unsigned int chroma_height, vo_setup_result_t * result) +{ + sdl_instance_t * instance; + + instance = (sdl_instance_t *) _instance; + + instance->width = width; + instance->height = height; + instance->surface = SDL_SetVideoMode (width, height, instance->bpp, + instance->sdlflags); + if (! (instance->surface)) { + fprintf (stderr, "sdl could not set the desired video mode\n"); + return 1; + } + + result->convert = NULL; + return 0; +} + +vo_instance_t * vo_sdl_open (void) +{ + sdl_instance_t * instance; + const SDL_VideoInfo * vidInfo; + + instance = (sdl_instance_t *) malloc (sizeof (sdl_instance_t)); + if (instance == NULL) + return NULL; + + instance->vo.setup = sdl_setup; + instance->vo.setup_fbuf = sdl_setup_fbuf; + instance->vo.set_fbuf = NULL; + instance->vo.start_fbuf = sdl_start_fbuf; + instance->vo.discard = sdl_discard; + instance->vo.draw = sdl_draw_frame; + instance->vo.close = NULL; /* sdl_close; */ + instance->sdlflags = SDL_HWSURFACE | SDL_RESIZABLE; + + putenv((char *)"SDL_VIDEO_YUV_HWACCEL=1"); + putenv((char *)"SDL_VIDEO_X11_NODIRECTCOLOR=1"); + + if (SDL_Init (SDL_INIT_VIDEO)) { + fprintf (stderr, "sdl video initialization failed.\n"); + return NULL; + } + + vidInfo = SDL_GetVideoInfo (); + if (!SDL_ListModes (vidInfo->vfmt, SDL_HWSURFACE | SDL_RESIZABLE)) { + instance->sdlflags = SDL_RESIZABLE; + if (!SDL_ListModes (vidInfo->vfmt, SDL_RESIZABLE)) { + fprintf (stderr, "sdl couldn't get any acceptable video mode\n"); + return NULL; + } + } + instance->bpp = vidInfo->vfmt->BitsPerPixel; + if (instance->bpp < 16) { + fprintf(stderr, "sdl has to emulate a 16 bit surfaces, " + "that will slow things down.\n"); + instance->bpp = 16; + } + + return (vo_instance_t *) instance; +} +#endif diff --git a/libvo/video_out_x11.c b/libvo/video_out_x11.c new file mode 100644 index 0000000..afc7fc2 --- /dev/null +++ b/libvo/video_out_x11.c @@ -0,0 +1,638 @@ +/* + * video_out_x11.c + * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 2003 Regis Duchesne <hpreg@zoy.org> + * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#ifdef LIBVO_X11 + +#include <stdio.h> +#include <stdlib.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> +#include <inttypes.h> +#include <unistd.h> +/* since it doesn't seem to be defined on some platforms */ +int XShmGetEventBase (Display *); + +#ifdef LIBVO_XV +#include <string.h> /* strcmp */ +#include <X11/extensions/Xvlib.h> +#define FOURCC_YV12 0x32315659 +#define FOURCC_UYVY 0x59565955 +#endif + +#include "mpeg2.h" +#include "video_out.h" +#include "vo_internal.h" +#include "mpeg2convert.h" + +typedef struct { + void * data; + int wait_completion; + XImage * ximage; +#ifdef LIBVO_XV + XvImage * xvimage; +#endif +} x11_frame_t; + +typedef struct x11_instance_s { + vo_instance_t vo; + x11_frame_t frame[3]; + int index; + int width; + int height; + Display * display; + Window window; + GC gc; + XVisualInfo vinfo; + XShmSegmentInfo shminfo; + int xshm_extension; + int completion_type; + int xshm; +#ifdef LIBVO_XV + unsigned int adaptors; + XvAdaptorInfo * adaptorInfo; + XvPortID port; + int xv; +#endif + void (* teardown) (struct x11_instance_s * instance); +} x11_instance_t; + +static int open_display (x11_instance_t * instance, int width, int height) +{ + int major; + int minor; + Bool pixmaps; + XVisualInfo visualTemplate; + XVisualInfo * XvisualInfoTable; + XVisualInfo * XvisualInfo; + int number; + int i; + XSetWindowAttributes attr; + XGCValues gcValues; + + instance->display = XOpenDisplay (NULL); + if (! (instance->display)) { + fprintf (stderr, "Can not open display\n"); + return 1; + } + + instance->xshm_extension = 0; + if (XShmQueryVersion (instance->display, &major, &minor, + &pixmaps) != 0 && + (major > 1 || (major == 1 && minor >= 1))) { + instance->xshm_extension = 1; + instance->completion_type = + XShmGetEventBase (instance->display) + ShmCompletion; + } else + fprintf (stderr, "No xshm extension\n"); + + /* list truecolor visuals for the default screen */ +#ifdef __cplusplus + visualTemplate.c_class = TrueColor; +#else + visualTemplate.class = TrueColor; +#endif + visualTemplate.screen = DefaultScreen (instance->display); + XvisualInfoTable = XGetVisualInfo (instance->display, + VisualScreenMask | VisualClassMask, + &visualTemplate, &number); + if (XvisualInfoTable == NULL) { + fprintf (stderr, "No truecolor visual\n"); + return 1; + } + + /* find the visual with the highest depth */ + XvisualInfo = XvisualInfoTable; + for (i = 1; i < number; i++) + if (XvisualInfoTable[i].depth > XvisualInfo->depth) + XvisualInfo = XvisualInfoTable + i; + + instance->vinfo = *XvisualInfo; + XFree (XvisualInfoTable); + + attr.background_pixmap = None; + attr.backing_store = NotUseful; + attr.border_pixel = 0; + attr.event_mask = 0; + /* fucking sun blows me - you have to create a colormap there... */ + attr.colormap = XCreateColormap (instance->display, + RootWindow (instance->display, + instance->vinfo.screen), + instance->vinfo.visual, AllocNone); + instance->window = + XCreateWindow (instance->display, + DefaultRootWindow (instance->display), + 0 /* x */, 0 /* y */, width, height, + 0 /* border_width */, instance->vinfo.depth, + InputOutput, instance->vinfo.visual, + (CWBackPixmap | CWBackingStore | CWBorderPixel | + CWEventMask | CWColormap), &attr); + + instance->gc = XCreateGC (instance->display, instance->window, 0, + &gcValues); + +#ifdef LIBVO_XV + instance->adaptors = 0; + instance->adaptorInfo = NULL; +#endif + + return 0; +} + +static int shmerror = 0; + +static int handle_error (Display * display, XErrorEvent * error) +{ + shmerror = 1; + return 0; +} + +static void * create_shm (x11_instance_t * instance, int size) +{ + instance->shminfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777); + if (instance->shminfo.shmid == -1) + goto error; + + instance->shminfo.shmaddr = (char *) shmat (instance->shminfo.shmid, 0, 0); + if (instance->shminfo.shmaddr == (char *)-1) + goto error; + + /* on linux the IPC_RMID only kicks off once everyone detaches the shm */ + /* doing this early avoids shm leaks when we are interrupted. */ + /* this would break the solaris port though :-/ */ + /* shmctl (instance->shminfo.shmid, IPC_RMID, 0); */ + + /* XShmAttach fails on remote displays, so we have to catch this event */ + + XSync (instance->display, False); + XSetErrorHandler (handle_error); + + instance->shminfo.readOnly = True; + if (! (XShmAttach (instance->display, &(instance->shminfo)))) + shmerror = 1; + + XSync (instance->display, False); + XSetErrorHandler (NULL); + if (shmerror) { + error: + fprintf (stderr, "cannot create shared memory\n"); + if (instance->shminfo.shmid != -1) { + shmdt (instance->shminfo.shmaddr); + shmctl (instance->shminfo.shmid, IPC_RMID, 0); + } + return NULL; + } + + return instance->shminfo.shmaddr; +} + +static void destroy_shm (x11_instance_t * instance) +{ + XShmDetach (instance->display, &(instance->shminfo)); + shmdt (instance->shminfo.shmaddr); + shmctl (instance->shminfo.shmid, IPC_RMID, 0); +} + +static void x11_event (x11_instance_t * instance) +{ + XEvent event; + char * addr; + int i; + + XNextEvent (instance->display, &event); + if (event.type == instance->completion_type) { + addr = (instance->shminfo.shmaddr + + ((XShmCompletionEvent *)&event)->offset); + for (i = 0; i < 3; i++) + if (addr == instance->frame[i].data) + instance->frame[i].wait_completion = 0; + } +} + +static void x11_start_fbuf (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + x11_instance_t * instance = (x11_instance_t *) _instance; + x11_frame_t * frame = (x11_frame_t *) id; + + while (frame->wait_completion) + x11_event (instance); +} + +static void x11_setup_fbuf (vo_instance_t * _instance, + uint8_t ** buf, void ** id) +{ + x11_instance_t * instance = (x11_instance_t *) _instance; + + buf[0] = (uint8_t *) instance->frame[instance->index].data; + buf[1] = buf[2] = NULL; + *id = instance->frame + instance->index++; +} + +static void x11_draw_frame (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + x11_frame_t * frame; + x11_instance_t * instance; + + frame = (x11_frame_t *) id; + instance = (x11_instance_t *) _instance; + if (instance->xshm) + XShmPutImage (instance->display, instance->window, instance->gc, + frame->ximage, 0, 0, 0, 0, + instance->width, instance->height, True); + else + XPutImage (instance->display, instance->window, instance->gc, + frame->ximage, 0, 0, 0, 0, + instance->width, instance->height); + XFlush (instance->display); + frame->wait_completion = instance->xshm; +} + +static int x11_alloc_frames (x11_instance_t * instance, int xshm) +{ + int size; + char * alloc; + int i = 0; + + if (xshm && !instance->xshm_extension) + return 1; + + size = 0; + alloc = NULL; + while (i < 3) { + instance->frame[i].wait_completion = 0; + instance->frame[i].ximage = xshm ? + XShmCreateImage (instance->display, instance->vinfo.visual, + instance->vinfo.depth, ZPixmap, NULL /* data */, + &(instance->shminfo), + instance->width, instance->height) : + XCreateImage(instance->display, instance->vinfo.visual, + instance->vinfo.depth, ZPixmap, 0, NULL /* data */, + instance->width, instance->height, 8, 0); + if (instance->frame[i].ximage == NULL) { + fprintf (stderr, "Cannot create ximage\n"); + return 1; + } else if (xshm) { + if (i == 0) { + size = (instance->frame[0].ximage->bytes_per_line * + instance->frame[0].ximage->height); + alloc = (char *) create_shm (instance, 3 * size); + } else if (size != (instance->frame[i].ximage->bytes_per_line * + instance->frame[i].ximage->height)) { + fprintf (stderr, "unexpected ximage data size\n"); + return 1; + } + } else + alloc = + (char *) malloc (instance->frame[i].ximage->bytes_per_line * + instance->frame[i].ximage->height); + instance->frame[i].data = instance->frame[i].ximage->data = alloc; + i++; + if (alloc == NULL) { + while (--i >= 0) + XDestroyImage (instance->frame[i].ximage); + return 1; + } + alloc += size; + } + + instance->xshm = xshm; + return 0; +} + +static void x11_teardown (x11_instance_t * instance) +{ + int i; + + for (i = 0; i < 3; i++) { + while (instance->frame[i].wait_completion) + x11_event (instance); + XDestroyImage (instance->frame[i].ximage); + } + if (instance->xshm) + destroy_shm (instance); +} + +static void x11_close (vo_instance_t * _instance) +{ + x11_instance_t * instance = (x11_instance_t *) _instance; + + if (instance->teardown != NULL) + instance->teardown (instance); + XFreeGC (instance->display, instance->gc); + XDestroyWindow (instance->display, instance->window); +#ifdef LIBVO_XV + if (instance->adaptors) + XvFreeAdaptorInfo (instance->adaptorInfo); +#endif + XCloseDisplay (instance->display); + free (instance); +} + +#ifdef LIBVO_XV +static void xv_setup_fbuf (vo_instance_t * _instance, + uint8_t ** buf, void ** id) +{ + x11_instance_t * instance = (x11_instance_t *) _instance; + uint8_t * data; + + data = (uint8_t *) instance->frame[instance->index].xvimage->data; + buf[0] = data + instance->frame[instance->index].xvimage->offsets[0]; + buf[1] = data + instance->frame[instance->index].xvimage->offsets[2]; + buf[2] = data + instance->frame[instance->index].xvimage->offsets[1]; + *id = instance->frame + instance->index++; +} + +static void xv_draw_frame (vo_instance_t * _instance, + uint8_t * const * buf, void * id) +{ + x11_frame_t * frame = (x11_frame_t *) id; + x11_instance_t * instance = (x11_instance_t *) _instance; + + if (instance->xshm) + XvShmPutImage (instance->display, instance->port, instance->window, + instance->gc, frame->xvimage, 0, 0, + instance->width, instance->height, 0, 0, + instance->width, instance->height, True); + else + XvPutImage (instance->display, instance->port, instance->window, + instance->gc, frame->xvimage, 0, 0, + instance->width, instance->height, 0, 0, + instance->width, instance->height); + XFlush (instance->display); + frame->wait_completion = instance->xshm; +} + +static int xv_check_fourcc (x11_instance_t * instance, XvPortID port, + int fourcc, const char * fourcc_str) +{ + XvImageFormatValues * formatValues; + int formats; + int i; + + formatValues = XvListImageFormats (instance->display, port, &formats); + for (i = 0; i < formats; i++) + if ((formatValues[i].id == fourcc) && + (! (strcmp (formatValues[i].guid, fourcc_str)))) { + XFree (formatValues); + return 0; + } + XFree (formatValues); + return 1; +} + +static int xv_check_extension (x11_instance_t * instance, + int fourcc, const char * fourcc_str) +{ + unsigned int i; + unsigned long j; + + if (!instance->adaptorInfo) { + unsigned int version; + unsigned int release; + unsigned int dummy; + + if ((XvQueryExtension (instance->display, &version, &release, + &dummy, &dummy, &dummy) != Success) || + (version < 2) || ((version == 2) && (release < 2))) { + fprintf (stderr, "No xv extension\n"); + return 1; + } + + XvQueryAdaptors (instance->display, instance->window, + &instance->adaptors, &instance->adaptorInfo); + } + + for (i = 0; i < instance->adaptors; i++) + if (instance->adaptorInfo[i].type & XvImageMask) + for (j = 0; j < instance->adaptorInfo[i].num_ports; j++) + if ((! (xv_check_fourcc (instance, + instance->adaptorInfo[i].base_id + j, + fourcc, fourcc_str))) && + (XvGrabPort (instance->display, + instance->adaptorInfo[i].base_id + j, + 0) == Success)) { + instance->port = instance->adaptorInfo[i].base_id + j; + return 0; + } + + fprintf (stderr, "Cannot find xv %s port\n", fourcc_str); + return 1; +} + +static int xv_alloc_frames (x11_instance_t * instance, int size, + int fourcc) +{ + char * alloc; + int i = 0; + + instance->xshm = 1; + alloc = instance->xshm_extension ? + (char *) create_shm (instance, 3 * size) : NULL; + if (alloc == NULL) { + instance->xshm = 0; + alloc = (char *) malloc (3 * size); + if (alloc == NULL) + return 1; + } + + while (i < 3) { + instance->frame[i].wait_completion = 0; + instance->frame[i].xvimage = instance->xshm ? + XvShmCreateImage (instance->display, instance->port, fourcc, + alloc, instance->width, instance->height, + &(instance->shminfo)) : + XvCreateImage (instance->display, instance->port, fourcc, + alloc, instance->width, instance->height); + instance->frame[i].data = alloc; + alloc += size; + if ((instance->frame[i].xvimage == NULL) || + (instance->frame[i++].xvimage->data_size != size)) { + while (--i >= 0) + XFree (instance->frame[i].xvimage); + if (instance->xshm) + destroy_shm (instance); + else + free (instance->frame[0].data); + return 1; + } + } + + return 0; +} + +static void xv_teardown (x11_instance_t * instance) +{ + int i; + + for (i = 0; i < 3; i++) { + while (instance->frame[i].wait_completion) + x11_event (instance); + XFree (instance->frame[i].xvimage); + } + if (instance->xshm) + destroy_shm (instance); + else + free (instance->frame[0].data); + XvUngrabPort (instance->display, instance->port, 0); +} +#endif + +static int common_setup (vo_instance_t * _instance, unsigned int width, + unsigned int height, unsigned int chroma_width, + unsigned int chroma_height, + vo_setup_result_t * result) +{ + x11_instance_t * instance = (x11_instance_t *) _instance; + + if (instance->display != NULL) { + /* Already setup, just adjust to the new size */ + if (instance->teardown != NULL) + instance->teardown (instance); + XResizeWindow (instance->display, instance->window, width, height); + } else { + /* Not setup yet, do the full monty */ + if (open_display (instance, width, height)) + return 1; + XMapWindow (instance->display, instance->window); + } + instance->vo.setup_fbuf = NULL; + instance->vo.start_fbuf = NULL; + instance->vo.set_fbuf = NULL; + instance->vo.draw = NULL; + instance->vo.discard = NULL; + instance->vo.close = x11_close; + instance->width = width; + instance->height = height; + instance->index = 0; + instance->teardown = NULL; + result->convert = NULL; + +#ifdef LIBVO_XV + if (instance->xv == 1 && + (chroma_width == width >> 1) && (chroma_height == height >> 1) && + !xv_check_extension (instance, FOURCC_YV12, "YV12") && + !xv_alloc_frames (instance, 3 * width * height / 2, FOURCC_YV12)) { + instance->vo.setup_fbuf = xv_setup_fbuf; + instance->vo.start_fbuf = x11_start_fbuf; + instance->vo.draw = xv_draw_frame; + instance->teardown = xv_teardown; + } else if (instance->xv && (chroma_width == width >> 1) && + !xv_check_extension (instance, FOURCC_UYVY, "UYVY") && + !xv_alloc_frames (instance, 2 * width * height, FOURCC_UYVY)) { + instance->vo.setup_fbuf = x11_setup_fbuf; + instance->vo.start_fbuf = x11_start_fbuf; + instance->vo.draw = xv_draw_frame; + instance->teardown = xv_teardown; + result->convert = mpeg2convert_uyvy; + } else +#endif + if (!x11_alloc_frames (instance, 1) || !x11_alloc_frames (instance, 0)) { + int bpp; + + instance->vo.setup_fbuf = x11_setup_fbuf; + instance->vo.start_fbuf = x11_start_fbuf; + instance->vo.draw = x11_draw_frame; + instance->teardown = x11_teardown; + +#ifdef WORDS_BIGENDIAN + if (instance->frame[0].ximage->byte_order != MSBFirst) { + fprintf (stderr, "No support for non-native byte order\n"); + return 1; + } +#else + if (instance->frame[0].ximage->byte_order != LSBFirst) { + fprintf (stderr, "No support for non-native byte order\n"); + return 1; + } +#endif + + /* + * depth in X11 terminology land is the number of bits used to + * actually represent the colour. + * + * bpp in X11 land means how many bits in the frame buffer per + * pixel. + * + * ex. 15 bit color is 15 bit depth and 16 bpp. Also 24 bit + * color is 24 bit depth, but can be 24 bpp or 32 bpp. + * + * If we have blue in the lowest bit then "obviously" RGB + * (the guy who wrote this convention never heard of endianness ?) + */ + + bpp = ((instance->vinfo.depth == 24) ? + instance->frame[0].ximage->bits_per_pixel : + instance->vinfo.depth); + result->convert = + mpeg2convert_rgb (((instance->frame[0].ximage->blue_mask & 1) ? + MPEG2CONVERT_RGB : MPEG2CONVERT_BGR), bpp); + if (result->convert == NULL) { + fprintf (stderr, "%dbpp not supported\n", bpp); + return 1; + } + } + + return 0; +} + +static vo_instance_t * common_open (int xv) +{ + x11_instance_t * instance; + + instance = (x11_instance_t *) malloc (sizeof (x11_instance_t)); + if (instance == NULL) + return NULL; + + instance->vo.setup = common_setup; + instance->vo.close = (void (*) (vo_instance_t *)) free; + instance->display = NULL; +#ifdef LIBVO_XV + instance->xv = xv; +#endif + return (vo_instance_t *) instance; +} + +vo_instance_t * vo_x11_open (void) +{ + return common_open (0); +} + +#ifdef LIBVO_XV +vo_instance_t * vo_xv_open (void) +{ + return common_open (1); +} + +vo_instance_t * vo_xv2_open (void) +{ + return common_open (2); +} +#endif +#endif diff --git a/libvo/vo_internal.h b/libvo/vo_internal.h new file mode 100644 index 0000000..d8d57ba --- /dev/null +++ b/libvo/vo_internal.h @@ -0,0 +1,38 @@ +/* + * vo_internal.h + * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +extern vo_open_t vo_xv_open; +extern vo_open_t vo_xv2_open; +extern vo_open_t vo_x11_open; +extern vo_open_t vo_dxrgb_open; +extern vo_open_t vo_dx_open; +extern vo_open_t vo_sdl_open; +extern vo_open_t vo_null_open; +extern vo_open_t vo_nullslice_open; +extern vo_open_t vo_nullskip_open; +extern vo_open_t vo_nullrgb16_open; +extern vo_open_t vo_nullrgb32_open; +extern vo_open_t vo_pgm_open; +extern vo_open_t vo_pgmpipe_open; +extern vo_open_t vo_md5_open; + |