summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am15
-rw-r--r--src/Makefile.in564
-rw-r--r--src/corrupt_mpeg2.c346
-rw-r--r--src/dump_state.c445
-rw-r--r--src/extract_mpeg2.135
-rw-r--r--src/extract_mpeg2.c462
-rw-r--r--src/getopt.c1055
-rw-r--r--src/getopt.h169
-rw-r--r--src/gettimeofday.c40
-rw-r--r--src/gettimeofday.h52
-rw-r--r--src/mpeg2dec.143
-rw-r--r--src/mpeg2dec.c800
12 files changed, 4026 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..778032b
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,15 @@
+AM_CFLAGS = $(MPEG2DEC_CFLAGS) $(LIBVO_CFLAGS)
+
+libmpeg2 = $(top_builddir)/libmpeg2/libmpeg2.la
+libmpeg2convert = $(top_builddir)/libmpeg2/convert/libmpeg2convert.la
+libvo = $(top_builddir)/libvo/libvo.a $(LIBVO_LIBS)
+
+bin_PROGRAMS = mpeg2dec extract_mpeg2 corrupt_mpeg2
+mpeg2dec_SOURCES = mpeg2dec.c dump_state.c getopt.c gettimeofday.c
+mpeg2dec_LDADD = $(libvo) $(libmpeg2) $(libmpeg2convert)
+extract_mpeg2_SOURCES = extract_mpeg2.c getopt.c
+corrupt_mpeg2_SOURCES = corrupt_mpeg2.c getopt.c
+
+man_MANS = mpeg2dec.1 extract_mpeg2.1
+
+EXTRA_DIST = getopt.h gettimeofday.h $(man_MANS)
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..22932d9
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,564 @@
+# 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@
+bin_PROGRAMS = mpeg2dec$(EXEEXT) extract_mpeg2$(EXEEXT) \
+ corrupt_mpeg2$(EXEEXT)
+subdir = src
+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 =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_corrupt_mpeg2_OBJECTS = corrupt_mpeg2.$(OBJEXT) getopt.$(OBJEXT)
+corrupt_mpeg2_OBJECTS = $(am_corrupt_mpeg2_OBJECTS)
+corrupt_mpeg2_LDADD = $(LDADD)
+am_extract_mpeg2_OBJECTS = extract_mpeg2.$(OBJEXT) getopt.$(OBJEXT)
+extract_mpeg2_OBJECTS = $(am_extract_mpeg2_OBJECTS)
+extract_mpeg2_LDADD = $(LDADD)
+am_mpeg2dec_OBJECTS = mpeg2dec.$(OBJEXT) dump_state.$(OBJEXT) \
+ getopt.$(OBJEXT) gettimeofday.$(OBJEXT)
+mpeg2dec_OBJECTS = $(am_mpeg2dec_OBJECTS)
+am__DEPENDENCIES_1 =
+am__DEPENDENCIES_2 = $(top_builddir)/libvo/libvo.a \
+ $(am__DEPENDENCIES_1)
+mpeg2dec_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libmpeg2) \
+ $(libmpeg2convert)
+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 = $(corrupt_mpeg2_SOURCES) $(extract_mpeg2_SOURCES) \
+ $(mpeg2dec_SOURCES)
+DIST_SOURCES = $(corrupt_mpeg2_SOURCES) $(extract_mpeg2_SOURCES) \
+ $(mpeg2dec_SOURCES)
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(man_MANS)
+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 = $(MPEG2DEC_CFLAGS) $(LIBVO_CFLAGS)
+libmpeg2 = $(top_builddir)/libmpeg2/libmpeg2.la
+libmpeg2convert = $(top_builddir)/libmpeg2/convert/libmpeg2convert.la
+libvo = $(top_builddir)/libvo/libvo.a $(LIBVO_LIBS)
+mpeg2dec_SOURCES = mpeg2dec.c dump_state.c getopt.c gettimeofday.c
+mpeg2dec_LDADD = $(libvo) $(libmpeg2) $(libmpeg2convert)
+extract_mpeg2_SOURCES = extract_mpeg2.c getopt.c
+corrupt_mpeg2_SOURCES = corrupt_mpeg2.c getopt.c
+man_MANS = mpeg2dec.1 extract_mpeg2.1
+EXTRA_DIST = getopt.h gettimeofday.h $(man_MANS)
+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 src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/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
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+corrupt_mpeg2$(EXEEXT): $(corrupt_mpeg2_OBJECTS) $(corrupt_mpeg2_DEPENDENCIES)
+ @rm -f corrupt_mpeg2$(EXEEXT)
+ $(LINK) $(corrupt_mpeg2_OBJECTS) $(corrupt_mpeg2_LDADD) $(LIBS)
+extract_mpeg2$(EXEEXT): $(extract_mpeg2_OBJECTS) $(extract_mpeg2_DEPENDENCIES)
+ @rm -f extract_mpeg2$(EXEEXT)
+ $(LINK) $(extract_mpeg2_OBJECTS) $(extract_mpeg2_LDADD) $(LIBS)
+mpeg2dec$(EXEEXT): $(mpeg2dec_OBJECTS) $(mpeg2dec_DEPENDENCIES)
+ @rm -f mpeg2dec$(EXEEXT)
+ $(LINK) $(mpeg2dec_OBJECTS) $(mpeg2dec_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/corrupt_mpeg2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump_state.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract_mpeg2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettimeofday.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpeg2dec.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
+install-man1: $(man1_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+
+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 $(PROGRAMS) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+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-binPROGRAMS clean-generic clean-libtool 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-man
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man: install-man1
+
+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: uninstall-binPROGRAMS uninstall-man
+
+uninstall-man: uninstall-man1
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool ctags distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS 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-man1 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 uninstall-binPROGRAMS uninstall-man \
+ uninstall-man1
+
+# 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/src/corrupt_mpeg2.c b/src/corrupt_mpeg2.c
new file mode 100644
index 0000000..86a71c6
--- /dev/null
+++ b/src/corrupt_mpeg2.c
@@ -0,0 +1,346 @@
+/*
+ * corrupt_mpeg2.c
+ * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+ * See http://libmpeg2.sourceforge.net/ for updates.
+ *
+ * mpeg2dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpeg2dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ctype.h>
+#ifdef HAVE_IO_H
+#include <fcntl.h>
+#include <io.h>
+#endif
+#include <inttypes.h>
+
+static FILE * in_file;
+static FILE * seed_file;
+static int seed_loaded = 0;
+static uint32_t rsl[55];
+static int rsl_i = -1;
+
+typedef struct {
+ uint32_t p, q[8], r;
+} randbyte_t;
+
+#define CORRUPT_RANDOM 0
+#define CORRUPT_VALUE 1
+
+typedef struct corrupt_s {
+ int type;
+ int chunk_start, chunk_stop;
+ int bit_start, bit_stop;
+ union {
+ randbyte_t prob;
+ } u;
+ struct corrupt_s * next;
+ uint8_t mask;
+} corrupt_t;
+
+#define CORRUPT_LIST_SIZE 10
+static corrupt_t corrupt_list[10];
+static int corrupt_list_index = 0;
+static corrupt_t * corrupt_head = NULL;
+static int current_chunk = -1, current_bit = 0, target_bit = 0x7fffffff;
+
+static inline uint32_t fastrand (void)
+{
+ if (++rsl_i == 55) rsl_i = 0;
+ return rsl[rsl_i] += rsl[(rsl_i < 31) ? rsl_i + 24 : rsl_i - 31];
+}
+
+static uint32_t clip (double p)
+{
+ return (p < 0) ? 0 : ((p >= 1) ? 0xffffffff : (uint32_t)(p*4294967296.0));
+}
+
+static void randbyte_init (double p, randbyte_t * rnd)
+{
+ double q, r;
+ int i;
+
+ rnd->p = clip (p);
+ r = 1;
+ for (i = 0; i < 8; i++) {
+ r *= 1 - p;
+ q = p / (1 - r);
+ rnd->q[i] = clip (q);
+ }
+ rnd->r = clip (1 - r);
+}
+
+static inline uint8_t randbyte (const randbyte_t * const rnd)
+{
+ int i, j;
+
+ if (fastrand () > rnd->r || rnd->r == 0)
+ return 0;
+
+ i = 7; j = 0;
+ do
+ if (fastrand () <= (j ? rnd->p : rnd->q[i]))
+ j |= 1 << i;
+ while (i--);
+ return j;
+}
+
+static void print_usage (char ** argv)
+{
+ fprintf (stderr, "usage: %s [-h] [-l <seed>] [-s <seedfile>] \\\n"
+ "\t\t[-r prob[,restrict] [-v prob[,restrict]] <file>\n"
+ "\t-h\tdisplay help\n"
+ "\t-l load seed\n"
+ "\t-s save seed file\n"
+ "\t-r random corruption\n"
+ "\t-v random value\n"
+ "restrict: chunk[-endchunk][,bit[-endbit]]\n", argv[0]);
+
+ exit (1);
+}
+
+static void corrupt_arg (corrupt_t * corrupt, int type, char * s, char ** argv)
+{
+ corrupt->type = type;
+ if (! *s)
+ s = (char *)",0-0xff,0-";
+ else if (*s != ',' || !isdigit (s[1]))
+ print_usage (argv);
+ corrupt->chunk_start = strtol (s + 1, &s, 0);
+ if (*s != '-')
+ corrupt->chunk_stop = corrupt->chunk_start;
+ else if (isdigit (* ++s))
+ corrupt->chunk_stop = strtol (s, &s, 0);
+ else
+ print_usage (argv);
+ if (! *s)
+ s = (char *)",32-";
+ else if (*s != ',' || !isdigit (s[1]))
+ print_usage (argv);
+ corrupt->bit_start = strtol (s + 1, &s, 0);
+ if (*s != '-')
+ corrupt->bit_stop = corrupt->bit_start;
+ else if (isdigit (* ++s))
+ corrupt->bit_stop = strtol (s, &s, 0);
+ else
+ corrupt->bit_stop = 0x7ffffffe;
+ if (corrupt->chunk_start < 0 ||
+ corrupt->chunk_start > corrupt->chunk_stop ||
+ corrupt->chunk_stop >= 0x1000 ||
+ corrupt->bit_start < 0 || corrupt->bit_start > corrupt->bit_stop || *s)
+ print_usage (argv);
+ if (corrupt->chunk_stop < 0x100) {
+ corrupt->chunk_start <<= 4;
+ corrupt->chunk_stop = (corrupt->chunk_stop << 4) | 0xf;
+ }
+}
+
+static void handle_args (int argc, char ** argv)
+{
+ int c;
+ double prob;
+ char * s;
+ corrupt_t * corrupt;
+
+ while ((c = getopt (argc, argv, "hl:s:r:v:")) != -1)
+ switch (c) {
+ case 'l':
+ if (seed_file || seed_loaded)
+ print_usage (argv);
+ if (sscanf (optarg, "%08x%08x%08x%08x",
+ rsl, rsl+1, rsl+2, rsl+3) != 4)
+ print_usage (argv);
+ seed_loaded = 1;
+ break;
+
+ case 's':
+ if (seed_file || seed_loaded)
+ print_usage (argv);
+ seed_file = fopen (optarg, "wt");
+ if (!seed_file)
+ print_usage (argv);
+ break;
+
+ case 'r':
+ prob = strtod (optarg, &s);
+ if (prob < 0 || prob > 1 ||
+ corrupt_list_index == CORRUPT_LIST_SIZE)
+ print_usage (argv);
+ corrupt = corrupt_list + corrupt_list_index++;
+ corrupt_arg (corrupt, CORRUPT_RANDOM, s, argv);
+ randbyte_init (prob, &corrupt->u.prob);
+ break;
+
+ case 'v':
+ prob = strtod (optarg, &s);
+ if (prob < 0 || prob > 1 ||
+ corrupt_list_index == CORRUPT_LIST_SIZE)
+ print_usage (argv);
+ corrupt = corrupt_list + corrupt_list_index++;
+ corrupt_arg (corrupt, CORRUPT_VALUE, s, argv);
+ randbyte_init (prob, &corrupt->u.prob);
+ break;
+
+ default:
+ print_usage (argv);
+ }
+
+ if (optind < argc) {
+ in_file = fopen (argv[optind], "rb");
+ if (!in_file) {
+ fprintf (stderr, "%s - could not open file %s\n", strerror (errno),
+ argv[optind]);
+ exit (1);
+ }
+ } else
+ in_file = stdin;
+
+ if (!seed_file && !seed_loaded)
+ seed_file = fopen ("seed", "wt");
+}
+
+static void update_corrupt_list (void)
+{
+ corrupt_t * corrupt;
+ corrupt_t ** corrupt_link;
+
+ corrupt_link = &corrupt_head;
+ target_bit = 0x7fffffff;
+ for (corrupt = corrupt_list;
+ corrupt < corrupt_list + corrupt_list_index; corrupt++)
+ if (corrupt->chunk_start <= current_chunk &&
+ corrupt->chunk_stop >= current_chunk &&
+ corrupt->bit_stop >= current_bit) {
+ if (corrupt->bit_start >= current_bit + 8) {
+ if (corrupt->bit_start <= target_bit)
+ target_bit = corrupt->bit_start & ~7;
+ } else {
+ *corrupt_link = corrupt;
+ corrupt_link = &corrupt->next;
+ if (corrupt->bit_stop >= current_bit + 7) {
+ corrupt->mask = 0xff;
+ if (corrupt->bit_stop <= target_bit)
+ target_bit = (corrupt->bit_stop + 1) & ~7;
+ } else {
+ corrupt->mask = -1 << (7 - (corrupt->bit_stop & 7));
+ target_bit = current_bit + 8;
+ }
+ if (corrupt->bit_start > current_bit) {
+ corrupt->mask &= 0xff >> (corrupt->bit_start & 7);
+ target_bit = current_bit + 8;
+ }
+ }
+ }
+ *corrupt_link = NULL;
+}
+
+static void corrupt (uint8_t * ptr)
+{
+ corrupt_t * corrupt_ptr;
+
+ if (ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 1) {
+ current_chunk = (ptr[3] << 4) | (ptr[4] >> 4);
+ current_bit = 0;
+ update_corrupt_list ();
+ } else if (current_bit == target_bit)
+ update_corrupt_list ();
+
+ current_bit += 8;
+
+ for (corrupt_ptr = corrupt_head; corrupt_ptr; corrupt_ptr = corrupt_ptr->next)
+ switch (corrupt_ptr->type) {
+ case CORRUPT_RANDOM:
+ *ptr ^= randbyte (&corrupt_ptr->u.prob) & corrupt_ptr->mask;
+ break;
+ case CORRUPT_VALUE:
+ *ptr = ((*ptr & ~corrupt_ptr->mask) |
+ (randbyte (&corrupt_ptr->u.prob) & corrupt_ptr->mask));
+ break;
+ }
+}
+
+static void corrupt_loop (void)
+{
+#define BUFFER_SIZE 4096
+ static uint8_t buffer1[BUFFER_SIZE + 4];
+ static uint8_t buffer2[BUFFER_SIZE + 4];
+ static uint8_t terminator[4] = {0xff, 0xff, 0xff, 0xff};
+
+ uint8_t * buf;
+ uint8_t * end;
+ uint8_t * current;
+
+ buf = buffer1;
+ end = buf + fread (buf, 1, BUFFER_SIZE, in_file);
+
+ while (end == buf + BUFFER_SIZE) {
+ uint8_t * lastbuf;
+ uint8_t * lastbuf_end;
+
+ lastbuf = buf; lastbuf_end = buf + BUFFER_SIZE;
+ buf = (buf == buffer1) ? buffer2 : buffer1;
+ memcpy (buf, terminator, 4);
+ end = buf + fread (buf, 1, BUFFER_SIZE, in_file);
+ memcpy (lastbuf_end, buf, 4);
+ for (current = lastbuf; current < lastbuf_end; current++)
+ corrupt (current);
+ fwrite (lastbuf, BUFFER_SIZE, 1, stdout);
+ }
+
+ memcpy (end, terminator, 4);
+ for (current = buf; current < end; current++)
+ corrupt (current);
+ fwrite (buf, end - buf, 1, stdout);
+}
+
+int main (int argc, char ** argv)
+{
+ int i;
+
+#ifdef HAVE_IO_H
+ setmode (fileno (stdin), O_BINARY);
+ setmode (fileno (stdout), O_BINARY);
+#endif
+
+ handle_args (argc, argv);
+
+ if (!seed_loaded) {
+ srand (time (NULL));
+ for (i = 0; i < 4; i++)
+ rsl[i] = rand ();
+ fprintf (seed_file, "%08x%08x%08x%08x\n",
+ rsl[0], rsl[1], rsl[2], rsl[3]);
+ fclose (seed_file);
+ }
+
+ for (i = 4; i < 55; i++)
+ rsl[i] = 0;
+ for (i = 0; i < 1000; i++)
+ fastrand ();
+
+ corrupt_loop ();
+
+ return 0;
+}
diff --git a/src/dump_state.c b/src/dump_state.c
new file mode 100644
index 0000000..dbba70a
--- /dev/null
+++ b/src/dump_state.c
@@ -0,0 +1,445 @@
+/*
+ * dump_state.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+ * See http://libmpeg2.sourceforge.net/ for updates.
+ *
+ * mpeg2dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpeg2dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "mpeg2.h"
+
+void dump_state (FILE * f, mpeg2_state_t state, const mpeg2_info_t * info,
+ int offset, int verbose);
+
+static struct {
+ const mpeg2_sequence_t * ptr;
+ mpeg2_sequence_t value;
+} last_sequence;
+static struct {
+ const mpeg2_gop_t * ptr;
+ mpeg2_gop_t value;
+} last_gop;
+static struct save_buf {
+ const mpeg2_fbuf_t * ptr;
+ mpeg2_fbuf_t value;
+} last_curbuf, last_dispbuf, last_discbuf, buf_code_list[26];
+static int buf_code_index = 0;
+static int buf_code_new = -1;
+static struct save_pic {
+ const mpeg2_picture_t * ptr;
+ mpeg2_picture_t value;
+} last_curpic, last_curpic2, last_disppic, last_disppic2, pic_code_list[26];
+static int pic_code_index = 0;
+static int pic_code_new = -1;
+
+static int sequence_match (const mpeg2_sequence_t * seq)
+{
+ return (last_sequence.ptr == seq &&
+ (seq == NULL ||
+ !memcmp (seq, &last_sequence.value, sizeof (mpeg2_sequence_t))));
+}
+
+static void sequence_save (const mpeg2_sequence_t * seq)
+{
+ last_sequence.ptr = seq;
+ if (seq != NULL)
+ last_sequence.value = *seq;
+}
+
+static char seq_code (const mpeg2_sequence_t * seq)
+{
+ if (seq == NULL)
+ return '-';
+ else if (sequence_match (seq))
+ return 'S';
+ else
+ return '?';
+}
+
+static int gop_match (const mpeg2_gop_t * gop)
+{
+ return (last_gop.ptr == gop &&
+ (gop == NULL ||
+ !memcmp (gop, &last_gop.value, sizeof (mpeg2_gop_t))));
+}
+
+static void gop_save (const mpeg2_gop_t * gop)
+{
+ last_gop.ptr = gop;
+ if (gop != NULL)
+ last_gop.value = *gop;
+}
+
+static char gop_code (const mpeg2_gop_t * gop)
+{
+ if (gop == NULL)
+ return '-';
+ else if (gop_match (gop))
+ return 'G';
+ else
+ return '?';
+}
+
+static int fbuf_match (const mpeg2_fbuf_t * fbuf, struct save_buf * saved)
+{
+ return (saved->ptr == fbuf &&
+ (fbuf == NULL ||
+ !memcmp (fbuf, &saved->value, sizeof (mpeg2_fbuf_t))));
+}
+
+static void fbuf_save (const mpeg2_fbuf_t * fbuf, struct save_buf * saved)
+{
+ saved->ptr = fbuf;
+ if (fbuf != NULL)
+ saved->value = *fbuf;
+}
+
+static char buf_code (const mpeg2_fbuf_t * fbuf)
+{
+ int i;
+
+ if (fbuf == NULL)
+ return '-';
+ for (i = 0; i < 26; i++)
+ if (fbuf_match (fbuf, buf_code_list + i))
+ return ((i == buf_code_new) ? 'A' : 'a') + i;
+ return '?';
+}
+
+static void buf_code_add (const mpeg2_fbuf_t * fbuf, FILE * f)
+{
+ int i;
+
+ if (fbuf == NULL)
+ fprintf (f, "buf_code_add error\n");
+ for (i = 0; i < 26; i++)
+ if (buf_code_list[i].ptr == fbuf)
+ fprintf (f, "buf_code_add error\n");
+ buf_code_new = buf_code_index;
+ fbuf_save (fbuf, buf_code_list + buf_code_index);
+ if (++buf_code_index == 26)
+ buf_code_index = 0;
+}
+
+static void buf_code_del (const mpeg2_fbuf_t * fbuf)
+{
+ int i;
+
+ if (fbuf == NULL)
+ return;
+ for (i = 0; i < 26; i++)
+ if (fbuf_match (fbuf, buf_code_list + i)) {
+ buf_code_list[i].ptr = NULL;
+ return;
+ }
+}
+
+static int picture_match (const mpeg2_picture_t * pic, struct save_pic * saved)
+{
+ return (saved->ptr == pic &&
+ (pic == NULL ||
+ !memcmp (pic, &saved->value, sizeof (mpeg2_picture_t))));
+}
+
+static void picture_save (const mpeg2_picture_t * pic, struct save_pic * saved)
+{
+ saved->ptr = pic;
+ if (pic != NULL)
+ saved->value = *pic;
+}
+
+static char pic_code (const mpeg2_picture_t * pic)
+{
+ int i;
+
+ if (pic == NULL)
+ return '-';
+ for (i = 0; i < 26; i++)
+ if (picture_match (pic, pic_code_list + i))
+ return ((i == pic_code_new) ? 'A' : 'a') + i;
+ return '?';
+}
+
+static void pic_code_add (const mpeg2_picture_t * pic, FILE * f)
+{
+ int i;
+
+ if (pic == NULL)
+ fprintf (f, "pic_code_add error\n");
+ for (i = 0; i < 26; i++)
+ if (pic_code_list[i].ptr == pic)
+ fprintf (f, "pic_code_add error\n");
+ pic_code_new = pic_code_index;
+ picture_save (pic, pic_code_list + pic_code_index);
+ if (++pic_code_index == 26)
+ pic_code_index = 0;
+}
+
+static void pic_code_del (const mpeg2_picture_t * pic)
+{
+ int i;
+
+ if (pic == NULL)
+ return;
+ for (i = 0; i < 26; i++)
+ if (picture_match (pic, pic_code_list + i)) {
+ pic_code_list[i].ptr = NULL;
+ return;
+ }
+}
+
+void dump_state (FILE * f, mpeg2_state_t state, const mpeg2_info_t * info,
+ int offset, int verbose)
+{
+ static const char * state_name[] = {
+ "BUFFER", "SEQUENCE", "SEQUENCE_REPEATED","GOP",
+ "PICTURE", "SLICE_1ST", "PICTURE_2ND", "SLICE", "END",
+ "INVALID", "INVALID_END", "SEQUENCE_MODIFIED"
+ };
+ static const char * profile[] = { "HP", "Spatial", "SNR", "MP", "SP" };
+ static const char * level[] = { "HL", "H-14", "ML", "LL" };
+ static const char * profile2[] = { "422@HL", NULL, NULL, "422@ML",
+ NULL, NULL, NULL, NULL, "MV@HL",
+ "MV@H-14", NULL, "MV@ML", "MV@LL" };
+ static const char * video_fmt[] = { "COMPONENT", "PAL", "NTSC", "SECAM", "MAC"};
+ static const char coding_type[] = { '0', 'I', 'P', 'B', 'D', '5', '6', '7'};
+ static const char * colour[] = { NULL, "BT.709", "UNSPECIFIED", NULL,
+ "BT.470-2/M", "BT.470-2/B,G",
+ "SMPTE170M", "SMPTE240M", "LINEAR" };
+ static const char * colour3[] = { NULL, "BT.709", "UNSPEC_COLORS", NULL, NULL,
+ "BT.470-2/B,G", "SMPTE170M", "SMPTE240M" };
+ const mpeg2_sequence_t * seq = info->sequence;
+ const mpeg2_gop_t * gop = info->gop;
+ const mpeg2_picture_t * pic;
+ unsigned int i, nb_pos, pixel_width, pixel_height;
+
+ if (state == STATE_BUFFER &&
+ sequence_match (seq) && gop_match (gop) &&
+ info->user_data == NULL && info->user_data_len == 0 &&
+ fbuf_match (info->current_fbuf, &last_curbuf) &&
+ fbuf_match (info->display_fbuf, &last_dispbuf) &&
+ fbuf_match (info->discard_fbuf, &last_discbuf) &&
+ picture_match (info->current_picture, &last_curpic) &&
+ picture_match (info->current_picture_2nd, &last_curpic2) &&
+ picture_match (info->display_picture, &last_disppic) &&
+ picture_match (info->display_picture_2nd, &last_disppic2))
+ return;
+ fprintf (f, "%8x", offset);
+ if (verbose > 1) {
+ switch (state) {
+ case STATE_PICTURE:
+ buf_code_add (info->current_fbuf, f);
+ pic_code_add (info->current_picture, f);
+ break;
+ case STATE_PICTURE_2ND:
+ pic_code_add (info->current_picture_2nd, f);
+ break;
+ case STATE_SEQUENCE_MODIFIED:
+ if (last_sequence.value.width != seq->width ||
+ last_sequence.value.height != seq->height ||
+ last_sequence.value.chroma_width != seq->chroma_width ||
+ last_sequence.value.chroma_height != seq->chroma_height ||
+ ((last_sequence.value.flags & SEQ_FLAG_LOW_DELAY) !=
+ (seq->flags & SEQ_FLAG_LOW_DELAY)))
+ fprintf (f, " (INVALID)");
+ case STATE_SEQUENCE:
+ sequence_save (seq);
+ break;
+ break;
+ case STATE_GOP:
+ gop_save (gop);
+ break;
+ default:
+ break;
+ }
+ fprintf (f, " %c%c %c%c%c %c%c%c %c", seq_code (seq), gop_code (gop),
+ buf_code (info->current_fbuf),
+ pic_code (info->current_picture),
+ pic_code (info->current_picture_2nd),
+ buf_code (info->display_fbuf),
+ pic_code (info->display_picture),
+ pic_code (info->display_picture_2nd),
+ buf_code (info->discard_fbuf));
+ if (state == STATE_SLICE || state == STATE_END ||
+ state == STATE_INVALID_END) {
+ if (state != STATE_SLICE)
+ buf_code_del (info->display_fbuf);
+ buf_code_del (info->discard_fbuf);
+ pic_code_del (info->display_picture);
+ pic_code_del (info->display_picture_2nd);
+ }
+ buf_code_new = pic_code_new = -1;
+ }
+ fprintf (f, " %s", state_name[state]);
+ switch (state) {
+ case STATE_SEQUENCE:
+ case STATE_SEQUENCE_REPEATED:
+ case STATE_SEQUENCE_MODIFIED:
+ if (seq->flags & SEQ_FLAG_MPEG2)
+ fprintf (f, " MPEG2");
+ if (0x10 <= seq->profile_level_id && seq->profile_level_id < 0x60 &&
+ !(seq->profile_level_id & 1) &&
+ 4 <= (seq->profile_level_id & 15) &&
+ (seq->profile_level_id & 15) <= 10)
+ fprintf (f, " %s@%s",
+ profile[(seq->profile_level_id >> 4) - 1],
+ level[((seq->profile_level_id & 15) - 4) >> 1]);
+ else if (0x82 <= seq->profile_level_id &&
+ seq->profile_level_id<= 0x8e &&
+ profile2[seq->profile_level_id - 0x82])
+ fprintf (f, " %s", profile2[seq->profile_level_id - 0x82]);
+ else if (seq->flags & SEQ_FLAG_MPEG2)
+ fprintf (f, " profile %02x", seq->profile_level_id);
+ if (seq->flags & SEQ_FLAG_CONSTRAINED_PARAMETERS)
+ fprintf (f, " CONST");
+ if (seq->flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE)
+ fprintf (f, " PROG");
+ if (seq->flags & SEQ_FLAG_LOW_DELAY)
+ fprintf (f, " LOWDELAY");
+ if ((seq->flags & SEQ_MASK_VIDEO_FORMAT) <
+ SEQ_VIDEO_FORMAT_UNSPECIFIED)
+ fprintf (f, " %s", video_fmt[(seq->flags & SEQ_MASK_VIDEO_FORMAT) /
+ SEQ_VIDEO_FORMAT_PAL]);
+ if (seq->flags & SEQ_FLAG_COLOUR_DESCRIPTION) {
+ if (seq->colour_primaries == seq->transfer_characteristics &&
+ seq->colour_primaries == seq->matrix_coefficients &&
+ seq->colour_primaries <= 7 && colour3[seq->colour_primaries])
+ fprintf (f, " %s", colour3[seq->colour_primaries]);
+ else {
+ char prim[16], trans[16], matrix[16];
+ sprintf (prim, "%d", seq->colour_primaries);
+ sprintf (trans, "%d", seq->transfer_characteristics);
+ sprintf (matrix, "%d", seq->matrix_coefficients);
+ if (seq->colour_primaries <= 7 &&
+ colour[seq->colour_primaries])
+ strncpy (prim, colour[seq->colour_primaries], 15);
+ if (seq->transfer_characteristics <= 8 &&
+ colour[seq->transfer_characteristics])
+ strncpy (trans, colour[seq->transfer_characteristics], 15);
+ if (seq->matrix_coefficients == 4)
+ strncpy (matrix, "FCC", 15);
+ else if (seq->matrix_coefficients <= 7 &&
+ colour[seq->matrix_coefficients])
+ strncpy (matrix, colour[seq->matrix_coefficients], 15);
+ fprintf (f, " COLORS (prim %s trans %s matrix %s)",
+ prim, trans, matrix);
+ }
+ }
+ fprintf (f, " %dx%d chroma %dx%d fps %.*f maxBps %d vbv %d "
+ "picture %dx%d display %dx%d pixel %dx%d",
+ seq->width, seq->height,
+ seq->chroma_width, seq->chroma_height,
+ 27000000%seq->frame_period?2:0, 27000000.0/seq->frame_period,
+ seq->byte_rate, seq->vbv_buffer_size,
+ seq->picture_width, seq->picture_height,
+ seq->display_width, seq->display_height,
+ seq->pixel_width, seq->pixel_height);
+ if (mpeg2_guess_aspect (seq, &pixel_width, &pixel_height))
+ fprintf (f, " guessed %dx%d", pixel_width, pixel_height);
+ fprintf (f, "\n");
+ break;
+ case STATE_GOP:
+ if (gop->flags & GOP_FLAG_DROP_FRAME)
+ fprintf (f, " DROP");
+ if (gop->flags & GOP_FLAG_CLOSED_GOP)
+ fprintf (f, " CLOSED");
+ if (gop->flags & GOP_FLAG_BROKEN_LINK)
+ fprintf (f, " BROKEN");
+ fprintf (f, " %2d:%2d:%2d:%2d\n",
+ gop->hours, gop->minutes, gop->seconds, gop->pictures);
+ break;
+ case STATE_PICTURE:
+ case STATE_PICTURE_2ND:
+ pic = ((state == STATE_PICTURE) ?
+ info->current_picture : info->current_picture_2nd);
+ fprintf (f, " %c",
+ coding_type[pic->flags & PIC_MASK_CODING_TYPE]);
+ if (pic->flags & PIC_FLAG_PROGRESSIVE_FRAME)
+ fprintf (f, " PROG");
+ if (pic->flags & PIC_FLAG_SKIP)
+ fprintf (f, " SKIP");
+ fprintf (f, " fields %d", pic->nb_fields);
+ if (pic->flags & PIC_FLAG_TOP_FIELD_FIRST)
+ fprintf (f, " TFF");
+ if (pic->flags & PIC_FLAG_TAGS)
+ fprintf (f, " pts %08x dts %08x", pic->tag, pic->tag2);
+ fprintf (f, " time_ref %d", pic->temporal_reference);
+ if (pic->flags & PIC_FLAG_COMPOSITE_DISPLAY)
+ fprintf (f, " composite %05x", pic->flags >> 12);
+ fprintf (f, " offset");
+ nb_pos = pic->nb_fields;
+ if (seq->flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE)
+ nb_pos >>= 1;
+ for (i = 0; i < nb_pos; i++)
+ fprintf (f, " %d/%d",
+ pic->display_offset[i].x, pic->display_offset[i].y);
+ fprintf (f, "\n");
+ break;
+ default:
+ fprintf (f, "\n");
+ }
+ if (verbose > 2 && info->user_data_len) {
+ fprintf (f, " USER_DATA %d bytes\n", info->user_data_len);
+ if (verbose > 3)
+ for (i = 0; i < info->user_data_len; i += 16) {
+ unsigned int j;
+
+ fprintf (f, " ");
+ for (j = i; j < i + 16; j++)
+ if (j < info->user_data_len)
+ fprintf (f, "%02x ", info->user_data[j]);
+ else
+ fprintf (f, " ");
+ fprintf (f, " ");
+ for (j = i; j < i + 16; j++)
+ if (j < info->user_data_len &&
+ 32 <= info->user_data[j] && info->user_data[j] <= 126)
+ fprintf (f, "%c", info->user_data[j]);
+ else
+ fprintf (f, " ");
+ fprintf (f, "\n");
+ }
+ }
+ if (state == STATE_END || state == STATE_INVALID_END) {
+ sequence_save (NULL);
+ gop_save (NULL);
+ fbuf_save (NULL, &last_curbuf);
+ fbuf_save (NULL, &last_dispbuf);
+ fbuf_save (NULL, &last_discbuf);
+ picture_save (NULL, &last_curpic);
+ picture_save (NULL, &last_curpic2);
+ picture_save (NULL, &last_disppic);
+ picture_save (NULL, &last_disppic2);
+ } else {
+ sequence_save (seq);
+ gop_save (gop);
+ fbuf_save (info->current_fbuf, &last_curbuf);
+ fbuf_save (info->display_fbuf, &last_dispbuf);
+ fbuf_save (info->discard_fbuf, &last_discbuf);
+ picture_save (info->current_picture, &last_curpic);
+ picture_save (info->current_picture_2nd, &last_curpic2);
+ picture_save (info->display_picture, &last_disppic);
+ picture_save (info->display_picture_2nd, &last_disppic2);
+ }
+}
diff --git a/src/extract_mpeg2.1 b/src/extract_mpeg2.1
new file mode 100644
index 0000000..99c6c5a
--- /dev/null
+++ b/src/extract_mpeg2.1
@@ -0,0 +1,35 @@
+.TH mpeg2dec "1" "extract_mpeg2"
+.SH NAME
+extract_mpeg2 \- extract MPEG video streams from a multiplexed stream.
+.SH SYNOPSIS
+.B extract_mpeg2
+[\fI-h\fR] [\fI-s [track]\fR] [\fI-t pid\fR] [\fIfile\fR]
+.SH DESCRIPTION
+`extract_mpeg2' extracts MPEG video streams from a multiplexed stream.
+Input is from stdin if no file is given.
+.TP
+\fB\-h\fR
+display help
+.TP
+\fB\-s track\fR
+set track number (0-0xf or 0xe0-0xef)
+.TP
+\fB\-t pid\fR
+use transport stream demultiplexer, pid 0x10-0x1ffe
+.SH AUTHORS
+Michel Lespinasse <walken@zoy.org>
+.br
+Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+.br
+And many others on the net.
+.SH "REPORTING BUGS"
+Report bugs to <libmpeg2-devel@lists.sourceforge.net>.
+.SH COPYRIGHT
+Copyright \(co 2000-2003 Michel Lespinasse
+.br
+Copyright \(co 1999-2000 Aaron Holtzman
+.br
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.BR mpeg2dec "(1)"
diff --git a/src/extract_mpeg2.c b/src/extract_mpeg2.c
new file mode 100644
index 0000000..ba3c469
--- /dev/null
+++ b/src/extract_mpeg2.c
@@ -0,0 +1,462 @@
+/*
+ * extract_mpeg2.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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#ifdef HAVE_IO_H
+#include <fcntl.h>
+#include <io.h>
+#endif
+#include <inttypes.h>
+
+#define BUFFER_SIZE 4096
+static uint8_t buffer[BUFFER_SIZE];
+static FILE * in_file;
+static int demux_track = 0xe0;
+static int demux_pid = 0;
+static int demux_pva = 0;
+
+static void print_usage (char ** argv)
+{
+ fprintf (stderr, "usage: %s [-h] [-s <track>] [-t <pid>] [-p] <file>\n"
+ "\t-h\tdisplay help\n"
+ "\t-s\tset track number (0-15 or 0xe0-0xef)\n"
+ "\t-t\tuse transport stream demultiplexer, pid 0x10-0x1ffe\n"
+ "\t-p\tuse pva demultiplexer\n",
+ argv[0]);
+
+ exit (1);
+}
+
+static void handle_args (int argc, char ** argv)
+{
+ int c;
+ char * s;
+
+ while ((c = getopt (argc, argv, "hs:t:p")) != -1)
+ switch (c) {
+ case 's':
+ demux_track = strtol (optarg, &s, 0);
+ if (demux_track < 0xe0)
+ demux_track += 0xe0;
+ if (demux_track < 0xe0 || demux_track > 0xef || *s) {
+ fprintf (stderr, "Invalid track number: %s\n", optarg);
+ print_usage (argv);
+ }
+ break;
+
+ case 't':
+ demux_pid = strtol (optarg, &s, 0);
+ if (demux_pid < 0x10 || demux_pid > 0x1ffe || *s) {
+ fprintf (stderr, "Invalid pid: %s\n", optarg);
+ print_usage (argv);
+ }
+ break;
+
+ case 'p':
+ demux_pva = 1;
+ break;
+
+ default:
+ print_usage (argv);
+ }
+
+ if (optind < argc) {
+ in_file = fopen (argv[optind], "rb");
+ if (!in_file) {
+ fprintf (stderr, "%s - could not open file %s\n", strerror (errno),
+ argv[optind]);
+ exit (1);
+ }
+ } else
+ in_file = stdin;
+}
+
+#define DEMUX_PAYLOAD_START 1
+static int demux (uint8_t * buf, uint8_t * end, int flags)
+{
+ static int mpeg1_skip_table[16] = {
+ 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ /*
+ * the demuxer keeps some state between calls:
+ * if "state" = DEMUX_HEADER, then "head_buf" contains the first
+ * "bytes" bytes from some header.
+ * if "state" == DEMUX_DATA, then we need to copy "bytes" bytes
+ * of ES data before the next header.
+ * if "state" == DEMUX_SKIP, then we need to skip "bytes" bytes
+ * of data before the next header.
+ *
+ * NEEDBYTES makes sure we have the requested number of bytes for a
+ * header. If we dont, it copies what we have into head_buf and returns,
+ * so that when we come back with more data we finish decoding this header.
+ *
+ * DONEBYTES updates "buf" to point after the header we just parsed.
+ */
+
+#define DEMUX_HEADER 0
+#define DEMUX_DATA 1
+#define DEMUX_SKIP 2
+ static int state = DEMUX_SKIP;
+ static int state_bytes = 0;
+ static uint8_t head_buf[264];
+
+ uint8_t * header;
+ int bytes;
+ int len;
+
+#define NEEDBYTES(x) \
+ do { \
+ int missing; \
+ \
+ missing = (x) - bytes; \
+ if (missing > 0) { \
+ if (header == head_buf) { \
+ if (missing <= end - buf) { \
+ memcpy (header + bytes, buf, missing); \
+ buf += missing; \
+ bytes = (x); \
+ } else { \
+ memcpy (header + bytes, buf, end - buf); \
+ state_bytes = bytes + end - buf; \
+ return 0; \
+ } \
+ } else { \
+ memcpy (head_buf, header, bytes); \
+ state = DEMUX_HEADER; \
+ state_bytes = bytes; \
+ return 0; \
+ } \
+ } \
+ } while (0)
+
+#define DONEBYTES(x) \
+ do { \
+ if (header != head_buf) \
+ buf = header + (x); \
+ } while (0)
+
+ if (flags & DEMUX_PAYLOAD_START)
+ goto payload_start;
+ switch (state) {
+ case DEMUX_HEADER:
+ if (state_bytes > 0) {
+ header = head_buf;
+ bytes = state_bytes;
+ goto continue_header;
+ }
+ break;
+ case DEMUX_DATA:
+ if (demux_pid || (state_bytes > end - buf)) {
+ fwrite (buf, end - buf, 1, stdout);
+ state_bytes -= end - buf;
+ return 0;
+ }
+ fwrite (buf, state_bytes, 1, stdout);
+ buf += state_bytes;
+ break;
+ case DEMUX_SKIP:
+ if (demux_pid || (state_bytes > end - buf)) {
+ state_bytes -= end - buf;
+ return 0;
+ }
+ buf += state_bytes;
+ break;
+ }
+
+ while (1) {
+ if (demux_pid) {
+ state = DEMUX_SKIP;
+ return 0;
+ }
+ payload_start:
+ header = buf;
+ bytes = end - buf;
+ continue_header:
+ NEEDBYTES (4);
+ if (header[0] || header[1] || (header[2] != 1)) {
+ if (demux_pid) {
+ state = DEMUX_SKIP;
+ return 0;
+ } else if (header != head_buf) {
+ buf++;
+ goto payload_start;
+ } else {
+ header[0] = header[1];
+ header[1] = header[2];
+ header[2] = header[3];
+ bytes = 3;
+ goto continue_header;
+ }
+ }
+ if (demux_pid) {
+ if ((header[3] >= 0xe0) && (header[3] <= 0xef))
+ goto pes;
+ fprintf (stderr, "bad stream id %x\n", header[3]);
+ exit (1);
+ }
+ switch (header[3]) {
+ case 0xb9: /* program end code */
+ /* DONEBYTES (4); */
+ /* break; */
+ return 1;
+ case 0xba: /* pack header */
+ NEEDBYTES (5);
+ if ((header[4] & 0xc0) == 0x40) { /* mpeg2 */
+ NEEDBYTES (14);
+ len = 14 + (header[13] & 7);
+ NEEDBYTES (len);
+ DONEBYTES (len);
+ /* header points to the mpeg2 pack header */
+ } else if ((header[4] & 0xf0) == 0x20) { /* mpeg1 */
+ NEEDBYTES (12);
+ DONEBYTES (12);
+ /* header points to the mpeg1 pack header */
+ } else {
+ fprintf (stderr, "weird pack header\n");
+ DONEBYTES (5);
+ }
+ break;
+ default:
+ if (header[3] == demux_track) {
+ pes:
+ NEEDBYTES (7);
+ if ((header[6] & 0xc0) == 0x80) { /* mpeg2 */
+ NEEDBYTES (9);
+ len = 9 + header[8];
+ NEEDBYTES (len);
+ /* header points to the mpeg2 pes header */
+ } else { /* mpeg1 */
+ len = 7;
+ while ((header-1)[len] == 0xff) {
+ len++;
+ NEEDBYTES (len);
+ if (len > 23) {
+ fprintf (stderr, "too much stuffing\n");
+ break;
+ }
+ }
+ if (((header-1)[len] & 0xc0) == 0x40) {
+ len += 2;
+ NEEDBYTES (len);
+ }
+ len += mpeg1_skip_table[(header - 1)[len] >> 4];
+ NEEDBYTES (len);
+ /* header points to the mpeg1 pes header */
+ }
+ DONEBYTES (len);
+ bytes = 6 + (header[4] << 8) + header[5] - len;
+ if (demux_pid || (bytes > end - buf)) {
+ fwrite (buf, end - buf, 1, stdout);
+ state = DEMUX_DATA;
+ state_bytes = bytes - (end - buf);
+ return 0;
+ } else if (bytes <= 0)
+ continue;
+ fwrite (buf, bytes, 1, stdout);
+ buf += bytes;
+ } else if (header[3] < 0xb9) {
+ fprintf (stderr,
+ "looks like a video stream, not system stream\n");
+ DONEBYTES (4);
+ } else {
+ NEEDBYTES (6);
+ DONEBYTES (6);
+ bytes = (header[4] << 8) + header[5];
+ if (bytes > end - buf) {
+ state = DEMUX_SKIP;
+ state_bytes = bytes - (end - buf);
+ return 0;
+ }
+ buf += bytes;
+ }
+ }
+ }
+}
+
+static void ps_loop (void)
+{
+ uint8_t * end;
+
+ do {
+ end = buffer + fread (buffer, 1, BUFFER_SIZE, in_file);
+ if (demux (buffer, end, 0))
+ break; /* hit program_end_code */
+ } while (end == buffer + BUFFER_SIZE);
+}
+
+static int pva_demux (uint8_t * buf, uint8_t * end)
+{
+ static int state = DEMUX_SKIP;
+ static int state_bytes = 0;
+ static uint8_t head_buf[12];
+
+ uint8_t * header;
+ int bytes;
+ int len;
+
+ switch (state) {
+ case DEMUX_HEADER:
+ if (state_bytes > 0) {
+ header = head_buf;
+ bytes = state_bytes;
+ goto continue_header;
+ }
+ break;
+ case DEMUX_DATA:
+ if (state_bytes > end - buf) {
+ fwrite (buf, end - buf, 1, stdout);
+ state_bytes -= end - buf;
+ return 0;
+ }
+ fwrite (buf, state_bytes, 1, stdout);
+ buf += state_bytes;
+ break;
+ case DEMUX_SKIP:
+ if (state_bytes > end - buf) {
+ state_bytes -= end - buf;
+ return 0;
+ }
+ buf += state_bytes;
+ break;
+ }
+
+ while (1) {
+ payload_start:
+ header = buf;
+ bytes = end - buf;
+ continue_header:
+ NEEDBYTES (2);
+ if (header[0] != 0x41 || header[1] != 0x56) {
+ if (header != head_buf) {
+ buf++;
+ goto payload_start;
+ } else {
+ header[0] = header[1];
+ bytes = 1;
+ goto continue_header;
+ }
+ }
+ NEEDBYTES (8);
+ if (header[2] != 1) {
+ DONEBYTES (8);
+ bytes = (header[6] << 8) + header[7];
+ if (bytes > end - buf) {
+ state = DEMUX_SKIP;
+ state_bytes = bytes - (end - buf);
+ return 0;
+ }
+ buf += bytes;
+ } else {
+ len = 8;
+ if (header[5] & 0x10) {
+ len = 12;
+ NEEDBYTES (len);
+ }
+ DONEBYTES (len);
+ bytes = (header[6] << 8) + header[7] + 8 - len;
+ if (bytes > end - buf) {
+ fwrite (buf, end - buf, 1, stdout);
+ state = DEMUX_DATA;
+ state_bytes = bytes - (end - buf);
+ return 0;
+ } else if (bytes > 0) {
+ fwrite (buf, bytes, 1, stdout);
+ buf += bytes;
+ }
+ }
+ }
+}
+
+static void pva_loop (void)
+{
+ uint8_t * end;
+
+ do {
+ end = buffer + fread (buffer, 1, BUFFER_SIZE, in_file);
+ pva_demux (buffer, end);
+ } while (end == buffer + BUFFER_SIZE);
+}
+
+static void ts_loop (void)
+{
+ uint8_t * buf;
+ uint8_t * nextbuf;
+ uint8_t * data;
+ uint8_t * end;
+ int pid;
+
+ buf = buffer;
+ while (1) {
+ end = buf + fread (buf, 1, buffer + BUFFER_SIZE - buf, in_file);
+ buf = buffer;
+ for (; (nextbuf = buf + 188) <= end; buf = nextbuf) {
+ if (*buf != 0x47) {
+ fprintf (stderr, "bad sync byte\n");
+ nextbuf = buf + 1;
+ continue;
+ }
+ pid = ((buf[1] << 8) + buf[2]) & 0x1fff;
+ if (pid != demux_pid)
+ continue;
+ data = buf + 4;
+ if (buf[3] & 0x20) { /* buf contains an adaptation field */
+ data = buf + 5 + buf[4];
+ if (data > nextbuf)
+ continue;
+ }
+ if (buf[3] & 0x10)
+ demux (data, nextbuf,
+ (buf[1] & 0x40) ? DEMUX_PAYLOAD_START : 0);
+ }
+ if (end != buffer + BUFFER_SIZE)
+ break;
+ memcpy (buffer, buf, end - buf);
+ buf = buffer + (end - buf);
+ }
+}
+
+int main (int argc, char ** argv)
+{
+#ifdef HAVE_IO_H
+ setmode (fileno (stdin), O_BINARY);
+ setmode (fileno (stdout), O_BINARY);
+#endif
+
+ handle_args (argc, argv);
+
+ if (demux_pva)
+ pva_loop ();
+ if (demux_pid)
+ ts_loop ();
+ else
+ ps_loop ();
+
+ return 0;
+}
diff --git a/src/getopt.c b/src/getopt.c
new file mode 100644
index 0000000..4744e43
--- /dev/null
+++ b/src/getopt.c
@@ -0,0 +1,1055 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to drepper@gnu.org
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+ Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+# ifndef const
+# define const
+# endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+# include <gnu-versions.h>
+# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+# define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+# include <stdlib.h>
+# include <unistd.h>
+#endif /* GNU C library. */
+
+#ifdef VMS
+# include <unixlib.h>
+# if HAVE_STRING_H - 0
+# include <string.h>
+# endif
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+ When compiling libc, the _ macro is predefined. */
+# ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# define _(msgid) gettext (msgid)
+# else
+# define _(msgid) (msgid)
+# endif
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+ causes problems with re-calling getopt as programs generally don't
+ know that. */
+
+int __getopt_initialized;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+# include <string.h>
+# define my_index strchr
+#else
+
+# if HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+#ifndef getenv
+extern char *getenv ();
+#endif
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+# if (!defined __STDC__ || !__STDC__) && !defined strlen
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+# endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+/* Defined in getopt_init.c */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+ is valid for the getopt call we must make sure that the ARGV passed
+ to getopt is that one passed to the process. */
+static void
+__attribute__ ((unused))
+store_args_and_env (int argc, char *const *argv)
+{
+ /* XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+ original_argc = argc;
+ original_argv = argv;
+}
+# ifdef text_set_element
+text_set_element (__libc_subinit, store_args_and_env);
+# endif /* text_set_element */
+
+# define SWAP_FLAGS(ch1, ch2) \
+ if (nonoption_flags_len > 0) \
+ { \
+ char __tmp = __getopt_nonoption_flags[ch1]; \
+ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
+ __getopt_nonoption_flags[ch2] = __tmp; \
+ }
+#else /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+#if defined __STDC__ && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+#ifdef _LIBC
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+ {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc (top + 1);
+ if (new_str == NULL)
+ nonoption_flags_len = nonoption_flags_max_len = 0;
+ else
+ {
+ memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ nonoption_flags_max_len),
+ '\0', top + 1 - nonoption_flags_max_len);
+ nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
+ }
+#endif
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ SWAP_FLAGS (bottom + i, middle + i);
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+#if defined __STDC__ && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+#ifdef _LIBC
+ if (posixly_correct == NULL
+ && argc == original_argc && argv == original_argv)
+ {
+ if (nonoption_flags_max_len == 0)
+ {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ nonoption_flags_max_len = -1;
+ else
+ {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = nonoption_flags_max_len = strlen (orig_str);
+ if (nonoption_flags_max_len < argc)
+ nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *) malloc (nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ nonoption_flags_max_len = -1;
+ else
+ memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ '\0', nonoption_flags_max_len - len);
+ }
+ }
+ nonoption_flags_len = nonoption_flags_max_len;
+ }
+ else
+ nonoption_flags_len = 0;
+#endif
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns -1.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ int print_errors = opterr;
+ if (optstring[0] == ':')
+ print_errors = 0;
+
+ optarg = NULL;
+
+ if (optind == 0 || !__getopt_initialized)
+ {
+ if (optind == 0)
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize (argc, argv, optstring);
+ __getopt_initialized = 1;
+ }
+
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#ifdef _LIBC
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+ || (optind < nonoption_flags_len \
+ && __getopt_nonoption_flags[optind] == '1'))
+#else
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc && NONOPTION_P)
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return -1;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if (NONOPTION_P)
+ {
+ if (ordering == REQUIRE_ORDER)
+ return -1;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar)
+ == (unsigned int) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ _("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ _("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+
+ nextchar += strlen (nextchar);
+
+ optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (print_errors)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (print_errors)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+ else
+ fprintf (stderr, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/src/getopt.h b/src/getopt.h
new file mode 100644
index 0000000..b0147e9
--- /dev/null
+++ b/src/getopt.h
@@ -0,0 +1,169 @@
+/* Declarations for getopt.
+ Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+# if defined __STDC__ && __STDC__
+ const char *name;
+# else
+ char *name;
+# endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+# define no_argument 0
+# define required_argument 1
+# define optional_argument 2
+#endif /* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+ arguments in ARGV (ARGC of them, minus the program name) for
+ options given in OPTS.
+
+ Return the option character from OPTS just read. Return -1 when
+ there are no more options. For unrecognized options, or options
+ missing arguments, `optopt' is set to the option letter, and '?' is
+ returned.
+
+ The OPTS string is a list of characters which are recognized option
+ letters, optionally followed by colons, specifying that that letter
+ takes an argument, to be placed in `optarg'.
+
+ If a letter in OPTS is followed by two colons, its argument is
+ optional. This behavior is specific to the GNU `getopt'.
+
+ The argument `--' causes premature termination of argument
+ scanning, explicitly telling `getopt' that there are no more
+ options.
+
+ If OPTS begins with `--', then non-option arguments are treated as
+ arguments to the option '\0'. This behavior is specific to the GNU
+ `getopt'. */
+
+#if defined __STDC__ && __STDC__
+# ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
+# else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+# endif /* __GNU_LIBRARY__ */
+
+# ifndef __need_getopt
+extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
+ const struct option *__longopts, int *__longind);
+extern int getopt_long_only (int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ int __long_only);
+# endif
+#else /* not __STDC__ */
+extern int getopt ();
+# ifndef __need_getopt
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+# endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations. */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/src/gettimeofday.c b/src/gettimeofday.c
new file mode 100644
index 0000000..b0eefc9
--- /dev/null
+++ b/src/gettimeofday.c
@@ -0,0 +1,40 @@
+/*
+ * gettimeofday.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 "gettimeofday.h"
+
+#ifdef CUSTOM_GETTIMEOFDAY
+
+#include <sys/timeb.h>
+
+void gettimeofday (struct timeval * tp, void * dummy)
+{
+ struct timeb tm;
+ ftime (&tm);
+ tp->tv_sec = tm.time;
+ tp->tv_usec = tm.millitm * 1000;
+}
+
+#endif
diff --git a/src/gettimeofday.h b/src/gettimeofday.h
new file mode 100644
index 0000000..bad06b4
--- /dev/null
+++ b/src/gettimeofday.h
@@ -0,0 +1,52 @@
+/*
+ * gettimeofday.h
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+ * See http://libmpeg2.sourceforge.net/ for updates.
+ *
+ * mpeg2dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpeg2dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LIBMPEG2_GETTIMEOFDAY_H
+#define LIBMPEG2_GETTIMEOFDAY_H
+
+#if defined(HAVE_STRUCT_TIMEVAL) && defined(HAVE_GETTIMEOFDAY)
+#if defined(TIME_WITH_SYS_TIME)
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#elif defined(HAVE_SYS_TIMEB_H) && defined(HAVE_FTIME)
+
+#define HAVE_GETTIMEOFDAY 1
+#define CUSTOM_GETTIMEOFDAY 1
+
+struct timeval {
+ long tv_sec;
+ long tv_usec;
+};
+
+void gettimeofday (struct timeval * tp, void * dummy);
+
+#else
+#undef HAVE_GETTIMEOFDAY
+#endif
+
+#endif /* LIBMPEG2_GETTIMEOFDAY_H */
diff --git a/src/mpeg2dec.1 b/src/mpeg2dec.1
new file mode 100644
index 0000000..547ee6c
--- /dev/null
+++ b/src/mpeg2dec.1
@@ -0,0 +1,43 @@
+.TH mpeg2dec "1" "mpeg2dec"
+.SH NAME
+mpeg2dec \- decode MPEG and MPEG2 video streams
+.SH SYNOPSIS
+.B mpeg2dec
+[\fI-h\fR] [\fI-s [track]\fR] [\fI-t pid\fR] [\fI-c\fR] [\fI-o mode\fR] [\fIfile\fR]
+.SH DESCRIPTION
+`mpeg2dec' displays MPEG1 and MPEG2 video stream.
+Input is from stdin if no file is given.
+.TP
+\fB\-h\fR
+display help and available video modes
+.TP
+\fB\-s\fR
+use program stream demultiplexer, track 0-0xf or 0xe0-0xef
+.TP
+\fB\-t pid\fR
+use transport stream demultiplexer, pid 0x10-0x1ffe
+.TP
+\fB\-c\fR
+use c implementation, disables all accelerations
+.TP
+\fB\-o\fR \fImode\fR
+use video output driver `mode'.
+.br
+A list of modes is available using the \fB\-h\fR option.
+.SH AUTHORS
+Michel Lespinasse <walken@zoy.org>
+.br
+Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+.br
+And many others on the net.
+.SH "REPORTING BUGS"
+Report bugs to <libmpeg2-devel@lists.sourceforge.net>.
+.SH COPYRIGHT
+Copyright \(co 2000-2003 Michel Lespinasse
+.br
+Copyright \(co 1999-2000 Aaron Holtzman
+.br
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.BR extract_mpeg2 "(1)"
diff --git a/src/mpeg2dec.c b/src/mpeg2dec.c
new file mode 100644
index 0000000..59b36d7
--- /dev/null
+++ b/src/mpeg2dec.c
@@ -0,0 +1,800 @@
+/*
+ * mpeg2dec.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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <getopt.h>
+#ifdef HAVE_IO_H
+#include <fcntl.h>
+#include <io.h>
+#endif
+#ifdef LIBVO_SDL
+#include <SDL/SDL.h>
+#endif
+#include <inttypes.h>
+
+#include "mpeg2.h"
+#include "video_out.h"
+#include "gettimeofday.h"
+
+static int buffer_size = 4096;
+static FILE * in_file;
+static int demux_track = 0;
+static int demux_pid = 0;
+static int demux_pva = 0;
+static mpeg2dec_t * mpeg2dec;
+static vo_open_t * output_open = NULL;
+static vo_instance_t * output;
+static int sigint = 0;
+static int total_offset = 0;
+static int verbose = 0;
+
+void dump_state (FILE * f, mpeg2_state_t state, const mpeg2_info_t * info,
+ int offset, int verbose);
+
+#ifdef HAVE_GETTIMEOFDAY
+
+static RETSIGTYPE signal_handler (int sig)
+{
+ sigint = 1;
+ signal (sig, SIG_DFL);
+ return (RETSIGTYPE)0;
+}
+
+static void print_fps (int final)
+{
+ static uint32_t frame_counter = 0;
+ static struct timeval tv_beg, tv_start;
+ static int total_elapsed;
+ static int last_count = 0;
+ struct timeval tv_end;
+ double fps, tfps;
+ int frames, elapsed;
+
+ if (verbose)
+ return;
+
+ gettimeofday (&tv_end, NULL);
+
+ if (!frame_counter) {
+ tv_start = tv_beg = tv_end;
+ signal (SIGINT, signal_handler);
+ }
+
+ elapsed = (tv_end.tv_sec - tv_beg.tv_sec) * 100 +
+ (tv_end.tv_usec - tv_beg.tv_usec) / 10000;
+ total_elapsed = (tv_end.tv_sec - tv_start.tv_sec) * 100 +
+ (tv_end.tv_usec - tv_start.tv_usec) / 10000;
+
+ if (final) {
+ if (total_elapsed)
+ tfps = frame_counter * 100.0 / total_elapsed;
+ else
+ tfps = 0;
+
+ fprintf (stderr,"\n%d frames decoded in %.2f seconds (%.2f fps)\n",
+ frame_counter, total_elapsed / 100.0, tfps);
+
+ return;
+ }
+
+ frame_counter++;
+
+ if (elapsed < 50) /* only display every 0.50 seconds */
+ return;
+
+ tv_beg = tv_end;
+ frames = frame_counter - last_count;
+
+ fps = frames * 100.0 / elapsed;
+ tfps = frame_counter * 100.0 / total_elapsed;
+
+ fprintf (stderr, "%d frames in %.2f sec (%.2f fps), "
+ "%d last %.2f sec (%.2f fps)\033[K\r", frame_counter,
+ total_elapsed / 100.0, tfps, frames, elapsed / 100.0, fps);
+
+ last_count = frame_counter;
+}
+
+#else /* !HAVE_GETTIMEOFDAY */
+
+static void print_fps (int final)
+{
+}
+
+#endif
+
+static void print_usage (char ** argv)
+{
+ int i;
+ vo_driver_t const * drivers;
+
+ fprintf (stderr, "usage: "
+ "%s [-h] [-o <mode>] [-s [<track>]] [-t <pid>] [-p] [-c] \\\n"
+ "\t\t[-v] [-b <bufsize>] <file>\n"
+ "\t-h\tdisplay help and available video output modes\n"
+ "\t-s\tuse program stream demultiplexer, "
+ "track 0-15 or 0xe0-0xef\n"
+ "\t-t\tuse transport stream demultiplexer, pid 0x10-0x1ffe\n"
+ "\t-p\tuse pva demultiplexer\n"
+ "\t-c\tuse c implementation, disables all accelerations\n"
+ "\t-v\tverbose information about the MPEG stream\n"
+ "\t-b\tset input buffer size, default 4096 bytes\n"
+ "\t-o\tvideo output mode\n", argv[0]);
+
+ drivers = vo_drivers ();
+ for (i = 0; drivers[i].name; i++)
+ fprintf (stderr, "\t\t\t%s\n", drivers[i].name);
+
+ exit (1);
+}
+
+static void handle_args (int argc, char ** argv)
+{
+ int c;
+ vo_driver_t const * drivers;
+ int i;
+ char * s;
+
+ drivers = vo_drivers ();
+ while ((c = getopt (argc, argv, "hs::t:pco:vb::")) != -1)
+ switch (c) {
+ case 'o':
+ for (i = 0; drivers[i].name != NULL; i++)
+ if (strcmp (drivers[i].name, optarg) == 0)
+ output_open = drivers[i].open;
+ if (output_open == NULL) {
+ fprintf (stderr, "Invalid video driver: %s\n", optarg);
+ print_usage (argv);
+ }
+ break;
+
+ case 's':
+ demux_track = 0xe0;
+ if (optarg != NULL) {
+ demux_track = strtol (optarg, &s, 0);
+ if (demux_track < 0xe0)
+ demux_track += 0xe0;
+ if (demux_track < 0xe0 || demux_track > 0xef || *s) {
+ fprintf (stderr, "Invalid track number: %s\n", optarg);
+ print_usage (argv);
+ }
+ }
+ break;
+
+ case 't':
+ demux_pid = strtol (optarg, &s, 0);
+ if (demux_pid < 0x10 || demux_pid > 0x1ffe || *s) {
+ fprintf (stderr, "Invalid pid: %s\n", optarg);
+ print_usage (argv);
+ }
+ break;
+
+ case 'p':
+ demux_pva = 1;
+ break;
+
+ case 'c':
+ mpeg2_accel (0);
+ break;
+
+ case 'v':
+ if (++verbose > 4)
+ print_usage (argv);
+ break;
+
+ case 'b':
+ buffer_size = 1;
+ if (optarg != NULL) {
+ buffer_size = strtol (optarg, &s, 0);
+ if (buffer_size < 1 || *s) {
+ fprintf (stderr, "Invalid buffer size: %s\n", optarg);
+ print_usage (argv);
+ }
+ }
+ break;
+
+ default:
+ print_usage (argv);
+ }
+
+ /* -o not specified, use a default driver */
+ if (output_open == NULL)
+ output_open = drivers[0].open;
+
+ if (optind < argc) {
+ in_file = fopen (argv[optind], "rb");
+ if (!in_file) {
+ fprintf (stderr, "%s - could not open file %s\n", strerror (errno),
+ argv[optind]);
+ exit (1);
+ }
+ } else
+ in_file = stdin;
+}
+
+static void * malloc_hook (unsigned size, mpeg2_alloc_t reason)
+{
+ void * buf;
+
+ /*
+ * Invalid streams can refer to fbufs that have not been
+ * initialized yet. For example the stream could start with a
+ * picture type onther than I. Or it could have a B picture before
+ * it gets two reference frames. Or, some slices could be missing.
+ *
+ * Consequently, the output depends on the content 2 output
+ * buffers have when the sequence begins. In release builds, this
+ * does not matter (garbage in, garbage out), but in test code, we
+ * always zero all our output buffers to:
+ * - make our test produce deterministic outputs
+ * - hint checkergcc that it is fine to read from all our output
+ * buffers at any time
+ */
+ if ((int)reason < 0) {
+ return NULL;
+ }
+ buf = mpeg2_malloc (size, (mpeg2_alloc_t)-1);
+ if (buf && (reason == MPEG2_ALLOC_YUV || reason == MPEG2_ALLOC_CONVERTED))
+ memset (buf, 0, size);
+ return buf;
+}
+
+static void decode_mpeg2 (uint8_t * current, uint8_t * end)
+{
+ const mpeg2_info_t * info;
+ mpeg2_state_t state;
+ vo_setup_result_t setup_result;
+
+ mpeg2_buffer (mpeg2dec, current, end);
+ total_offset += end - current;
+
+ info = mpeg2_info (mpeg2dec);
+ while (1) {
+ state = mpeg2_parse (mpeg2dec);
+ if (verbose)
+ dump_state (stderr, state, info,
+ total_offset - mpeg2_getpos (mpeg2dec), verbose);
+ switch (state) {
+ case STATE_BUFFER:
+ return;
+ case STATE_SEQUENCE:
+ /* might set nb fbuf, convert format, stride */
+ /* might set fbufs */
+ if (output->setup (output, info->sequence->width,
+ info->sequence->height,
+ info->sequence->chroma_width,
+ info->sequence->chroma_height, &setup_result)) {
+ fprintf (stderr, "display setup failed\n");
+ exit (1);
+ }
+ if (setup_result.convert &&
+ mpeg2_convert (mpeg2dec, setup_result.convert, NULL)) {
+ fprintf (stderr, "color conversion setup failed\n");
+ exit (1);
+ }
+ if (output->set_fbuf) {
+ uint8_t * buf[3];
+ void * id;
+
+ mpeg2_custom_fbuf (mpeg2dec, 1);
+ output->set_fbuf (output, buf, &id);
+ mpeg2_set_buf (mpeg2dec, buf, id);
+ output->set_fbuf (output, buf, &id);
+ mpeg2_set_buf (mpeg2dec, buf, id);
+ } else if (output->setup_fbuf) {
+ uint8_t * buf[3];
+ void * id;
+
+ output->setup_fbuf (output, buf, &id);
+ mpeg2_set_buf (mpeg2dec, buf, id);
+ output->setup_fbuf (output, buf, &id);
+ mpeg2_set_buf (mpeg2dec, buf, id);
+ output->setup_fbuf (output, buf, &id);
+ mpeg2_set_buf (mpeg2dec, buf, id);
+ }
+ mpeg2_skip (mpeg2dec, (output->draw == NULL));
+ break;
+ case STATE_PICTURE:
+ /* might skip */
+ /* might set fbuf */
+ if (output->set_fbuf) {
+ uint8_t * buf[3];
+ void * id;
+
+ output->set_fbuf (output, buf, &id);
+ mpeg2_set_buf (mpeg2dec, buf, id);
+ }
+ if (output->start_fbuf)
+ output->start_fbuf (output, info->current_fbuf->buf,
+ info->current_fbuf->id);
+ break;
+ case STATE_SLICE:
+ case STATE_END:
+ case STATE_INVALID_END:
+ /* draw current picture */
+ /* might free frame buffer */
+ if (info->display_fbuf) {
+ if (output->draw)
+ output->draw (output, info->display_fbuf->buf,
+ info->display_fbuf->id);
+ print_fps (0);
+ }
+ if (output->discard && info->discard_fbuf)
+ output->discard (output, info->discard_fbuf->buf,
+ info->discard_fbuf->id);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+#define DEMUX_PAYLOAD_START 1
+static int demux (uint8_t * buf, uint8_t * end, int flags)
+{
+ static int mpeg1_skip_table[16] = {
+ 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ /*
+ * the demuxer keeps some state between calls:
+ * if "state" = DEMUX_HEADER, then "head_buf" contains the first
+ * "bytes" bytes from some header.
+ * if "state" == DEMUX_DATA, then we need to copy "bytes" bytes
+ * of ES data before the next header.
+ * if "state" == DEMUX_SKIP, then we need to skip "bytes" bytes
+ * of data before the next header.
+ *
+ * NEEDBYTES makes sure we have the requested number of bytes for a
+ * header. If we dont, it copies what we have into head_buf and returns,
+ * so that when we come back with more data we finish decoding this header.
+ *
+ * DONEBYTES updates "buf" to point after the header we just parsed.
+ */
+
+#define DEMUX_HEADER 0
+#define DEMUX_DATA 1
+#define DEMUX_SKIP 2
+ static int state = DEMUX_SKIP;
+ static int state_bytes = 0;
+ static uint8_t head_buf[264];
+
+ uint8_t * header;
+ int bytes;
+ int len;
+
+#define NEEDBYTES(x) \
+ do { \
+ int missing; \
+ \
+ missing = (x) - bytes; \
+ if (missing > 0) { \
+ if (header == head_buf) { \
+ if (missing <= end - buf) { \
+ memcpy (header + bytes, buf, missing); \
+ buf += missing; \
+ bytes = (x); \
+ } else { \
+ memcpy (header + bytes, buf, end - buf); \
+ state_bytes = bytes + end - buf; \
+ return 0; \
+ } \
+ } else { \
+ memcpy (head_buf, header, bytes); \
+ state = DEMUX_HEADER; \
+ state_bytes = bytes; \
+ return 0; \
+ } \
+ } \
+ } while (0)
+
+#define DONEBYTES(x) \
+ do { \
+ if (header != head_buf) \
+ buf = header + (x); \
+ } while (0)
+
+ if (flags & DEMUX_PAYLOAD_START)
+ goto payload_start;
+ switch (state) {
+ case DEMUX_HEADER:
+ if (state_bytes > 0) {
+ header = head_buf;
+ bytes = state_bytes;
+ goto continue_header;
+ }
+ break;
+ case DEMUX_DATA:
+ if (demux_pid || (state_bytes > end - buf)) {
+ decode_mpeg2 (buf, end);
+ state_bytes -= end - buf;
+ return 0;
+ }
+ decode_mpeg2 (buf, buf + state_bytes);
+ buf += state_bytes;
+ break;
+ case DEMUX_SKIP:
+ if (demux_pid || (state_bytes > end - buf)) {
+ state_bytes -= end - buf;
+ return 0;
+ }
+ buf += state_bytes;
+ break;
+ }
+
+ while (1) {
+ if (demux_pid) {
+ state = DEMUX_SKIP;
+ return 0;
+ }
+ payload_start:
+ header = buf;
+ bytes = end - buf;
+ continue_header:
+ NEEDBYTES (4);
+ if (header[0] || header[1] || (header[2] != 1)) {
+ if (demux_pid) {
+ state = DEMUX_SKIP;
+ return 0;
+ } else if (header != head_buf) {
+ buf++;
+ goto payload_start;
+ } else {
+ header[0] = header[1];
+ header[1] = header[2];
+ header[2] = header[3];
+ bytes = 3;
+ goto continue_header;
+ }
+ }
+ if (demux_pid) {
+ if ((header[3] >= 0xe0) && (header[3] <= 0xef))
+ goto pes;
+ fprintf (stderr, "bad stream id %x\n", header[3]);
+ exit (1);
+ }
+ switch (header[3]) {
+ case 0xb9: /* program end code */
+ /* DONEBYTES (4); */
+ /* break; */
+ return 1;
+ case 0xba: /* pack header */
+ NEEDBYTES (5);
+ if ((header[4] & 0xc0) == 0x40) { /* mpeg2 */
+ NEEDBYTES (14);
+ len = 14 + (header[13] & 7);
+ NEEDBYTES (len);
+ DONEBYTES (len);
+ /* header points to the mpeg2 pack header */
+ } else if ((header[4] & 0xf0) == 0x20) { /* mpeg1 */
+ NEEDBYTES (12);
+ DONEBYTES (12);
+ /* header points to the mpeg1 pack header */
+ } else {
+ fprintf (stderr, "weird pack header\n");
+ DONEBYTES (5);
+ }
+ break;
+ default:
+ if (header[3] == demux_track) {
+ pes:
+ NEEDBYTES (7);
+ if ((header[6] & 0xc0) == 0x80) { /* mpeg2 */
+ NEEDBYTES (9);
+ len = 9 + header[8];
+ NEEDBYTES (len);
+ /* header points to the mpeg2 pes header */
+ if (header[7] & 0x80) {
+ uint32_t pts, dts;
+
+ pts = (((header[9] >> 1) << 30) |
+ (header[10] << 22) | ((header[11] >> 1) << 15) |
+ (header[12] << 7) | (header[13] >> 1));
+ dts = (!(header[7] & 0x40) ? pts :
+ (uint32_t)(((header[14] >> 1) << 30) |
+ (header[15] << 22) |
+ ((header[16] >> 1) << 15) |
+ (header[17] << 7) | (header[18] >> 1)));
+ mpeg2_tag_picture (mpeg2dec, pts, dts);
+ }
+ } else { /* mpeg1 */
+ int len_skip;
+ uint8_t * ptsbuf;
+
+ len = 7;
+ while (header[len - 1] == 0xff) {
+ len++;
+ NEEDBYTES (len);
+ if (len > 23) {
+ fprintf (stderr, "too much stuffing\n");
+ break;
+ }
+ }
+ if ((header[len - 1] & 0xc0) == 0x40) {
+ len += 2;
+ NEEDBYTES (len);
+ }
+ len_skip = len;
+ len += mpeg1_skip_table[header[len - 1] >> 4];
+ NEEDBYTES (len);
+ /* header points to the mpeg1 pes header */
+ ptsbuf = header + len_skip;
+ if ((ptsbuf[-1] & 0xe0) == 0x20) {
+ uint32_t pts, dts;
+
+ pts = (((ptsbuf[-1] >> 1) << 30) |
+ (ptsbuf[0] << 22) | ((ptsbuf[1] >> 1) << 15) |
+ (ptsbuf[2] << 7) | (ptsbuf[3] >> 1));
+ dts = (((ptsbuf[-1] & 0xf0) != 0x30) ? pts :
+ (uint32_t)(((ptsbuf[4] >> 1) << 30) |
+ (ptsbuf[5] << 22) | ((ptsbuf[6] >> 1) << 15) |
+ (ptsbuf[7] << 7) | (ptsbuf[18] >> 1)));
+ mpeg2_tag_picture (mpeg2dec, pts, dts);
+ }
+ }
+ DONEBYTES (len);
+ bytes = 6 + (header[4] << 8) + header[5] - len;
+ if (demux_pid || (bytes > end - buf)) {
+ decode_mpeg2 (buf, end);
+ state = DEMUX_DATA;
+ state_bytes = bytes - (end - buf);
+ return 0;
+ } else if (bytes > 0) {
+ decode_mpeg2 (buf, buf + bytes);
+ buf += bytes;
+ }
+ } else if (header[3] < 0xb9) {
+ fprintf (stderr,
+ "looks like a video stream, not system stream\n");
+ DONEBYTES (4);
+ } else {
+ NEEDBYTES (6);
+ DONEBYTES (6);
+ bytes = (header[4] << 8) + header[5];
+ if (bytes > end - buf) {
+ state = DEMUX_SKIP;
+ state_bytes = bytes - (end - buf);
+ return 0;
+ }
+ buf += bytes;
+ }
+ }
+ }
+}
+
+static void ps_loop (void)
+{
+ uint8_t * buffer = (uint8_t *) malloc (buffer_size);
+ uint8_t * end;
+
+ if (buffer == NULL)
+ exit (1);
+ do {
+ end = buffer + fread (buffer, 1, buffer_size, in_file);
+ if (demux (buffer, end, 0))
+ break; /* hit program_end_code */
+ } while (end == buffer + buffer_size && !sigint);
+ free (buffer);
+}
+
+static int pva_demux (uint8_t * buf, uint8_t * end)
+{
+ static int state = DEMUX_SKIP;
+ static int state_bytes = 0;
+ static uint8_t head_buf[15];
+
+ uint8_t * header;
+ int bytes;
+ int len;
+
+ switch (state) {
+ case DEMUX_HEADER:
+ if (state_bytes > 0) {
+ header = head_buf;
+ bytes = state_bytes;
+ goto continue_header;
+ }
+ break;
+ case DEMUX_DATA:
+ if (state_bytes > end - buf) {
+ decode_mpeg2 (buf, end);
+ state_bytes -= end - buf;
+ return 0;
+ }
+ decode_mpeg2 (buf, buf + state_bytes);
+ buf += state_bytes;
+ break;
+ case DEMUX_SKIP:
+ if (state_bytes > end - buf) {
+ state_bytes -= end - buf;
+ return 0;
+ }
+ buf += state_bytes;
+ break;
+ }
+
+ while (1) {
+ payload_start:
+ header = buf;
+ bytes = end - buf;
+ continue_header:
+ NEEDBYTES (2);
+ if (header[0] != 0x41 || header[1] != 0x56) {
+ if (header != head_buf) {
+ buf++;
+ goto payload_start;
+ } else {
+ header[0] = header[1];
+ bytes = 1;
+ goto continue_header;
+ }
+ }
+ NEEDBYTES (8);
+ if (header[2] != 1) {
+ DONEBYTES (8);
+ bytes = (header[6] << 8) + header[7];
+ if (bytes > end - buf) {
+ state = DEMUX_SKIP;
+ state_bytes = bytes - (end - buf);
+ return 0;
+ }
+ buf += bytes;
+ } else {
+ len = 8;
+ if (header[5] & 0x10) {
+ len = 12 + (header[5] & 3);
+ NEEDBYTES (len);
+ decode_mpeg2 (header + 12, header + len);
+ mpeg2_tag_picture (mpeg2dec,
+ ((header[8] << 24) | (header[9] << 16) |
+ (header[10] << 8) | header[11]), 0);
+ }
+ DONEBYTES (len);
+ bytes = (header[6] << 8) + header[7] + 8 - len;
+ if (bytes > end - buf) {
+ decode_mpeg2 (buf, end);
+ state = DEMUX_DATA;
+ state_bytes = bytes - (end - buf);
+ return 0;
+ } else if (bytes > 0) {
+ decode_mpeg2 (buf, buf + bytes);
+ buf += bytes;
+ }
+ }
+ }
+}
+
+static void pva_loop (void)
+{
+ uint8_t * buffer = (uint8_t *) malloc (buffer_size);
+ uint8_t * end;
+
+ if (buffer == NULL)
+ exit (1);
+ do {
+ end = buffer + fread (buffer, 1, buffer_size, in_file);
+ pva_demux (buffer, end);
+ } while (end == buffer + buffer_size && !sigint);
+ free (buffer);
+}
+
+static void ts_loop (void)
+{
+ uint8_t * buffer = (uint8_t *) malloc (buffer_size);
+ uint8_t * buf;
+ uint8_t * nextbuf;
+ uint8_t * data;
+ uint8_t * end;
+ int pid;
+
+ if (buffer == NULL || buffer_size < 188)
+ exit (1);
+ buf = buffer;
+ do {
+ end = buf + fread (buf, 1, buffer + buffer_size - buf, in_file);
+ buf = buffer;
+ for (; (nextbuf = buf + 188) <= end; buf = nextbuf) {
+ if (*buf != 0x47) {
+ fprintf (stderr, "bad sync byte\n");
+ nextbuf = buf + 1;
+ continue;
+ }
+ pid = ((buf[1] << 8) + buf[2]) & 0x1fff;
+ if (pid != demux_pid)
+ continue;
+ data = buf + 4;
+ if (buf[3] & 0x20) { /* buf contains an adaptation field */
+ data = buf + 5 + buf[4];
+ if (data > nextbuf)
+ continue;
+ }
+ if (buf[3] & 0x10)
+ demux (data, nextbuf,
+ (buf[1] & 0x40) ? DEMUX_PAYLOAD_START : 0);
+ }
+ if (end != buffer + buffer_size)
+ break;
+ memcpy (buffer, buf, end - buf);
+ buf = buffer + (end - buf);
+ } while (!sigint);
+ free (buffer);
+}
+
+static void es_loop (void)
+{
+ uint8_t * buffer = (uint8_t *) malloc (buffer_size);
+ uint8_t * end;
+
+ if (buffer == NULL)
+ exit (1);
+ do {
+ end = buffer + fread (buffer, 1, buffer_size, in_file);
+ decode_mpeg2 (buffer, end);
+ } while (end == buffer + buffer_size && !sigint);
+ free (buffer);
+}
+
+int main (int argc, char ** argv)
+{
+#ifdef HAVE_IO_H
+ setmode (fileno (stdin), O_BINARY);
+ setmode (fileno (stdout), O_BINARY);
+#endif
+
+ fprintf (stderr, PACKAGE"-"VERSION
+ " - by Michel Lespinasse <walken@zoy.org> and Aaron Holtzman\n");
+
+ handle_args (argc, argv);
+
+ output = output_open ();
+ if (output == NULL) {
+ fprintf (stderr, "Can not open output\n");
+ return 1;
+ }
+ mpeg2dec = mpeg2_init ();
+ if (mpeg2dec == NULL)
+ exit (1);
+ mpeg2_malloc_hooks (malloc_hook, NULL);
+
+ if (demux_pva)
+ pva_loop ();
+ else if (demux_pid)
+ ts_loop ();
+ else if (demux_track)
+ ps_loop ();
+ else
+ es_loop ();
+
+ mpeg2_close (mpeg2dec);
+ if (output->close)
+ output->close (output);
+ print_fps (1);
+ fclose (in_file);
+ return 0;
+}