diff --git a/avilib/Makefile b/avilib/Makefile new file mode 100644 index 000000000..1e47e6371 --- /dev/null +++ b/avilib/Makefile @@ -0,0 +1,324 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# avilib/Makefile. Generated from Makefile.in by configure. + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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. + + + +# # Process this file with automake to produce Makefile.in. +SHELL = /bin/sh + +srcdir = . +top_srcdir = .. + +prefix = /usr/local +exec_prefix = ${prefix} + +bindir = ${exec_prefix}/bin +sbindir = ${exec_prefix}/sbin +libexecdir = ${exec_prefix}/libexec +datadir = ${prefix}/share +sysconfdir = ${prefix}/etc +sharedstatedir = ${prefix}/com +localstatedir = ${prefix}/var +libdir = ${exec_prefix}/lib +infodir = ${prefix}/info +mandir = ${prefix}/man +includedir = ${prefix}/include +oldincludedir = /usr/include +pkgdatadir = $(datadir)/ogmtools +pkglibdir = $(libdir)/ogmtools +pkgincludedir = $(includedir)/ogmtools +top_builddir = .. + +ACLOCAL = ${SHELL} /home/mosu/prog/video/ogmtools/missing --run aclocal-1.6 +AUTOCONF = ${SHELL} /home/mosu/prog/video/ogmtools/missing --run autoconf +AUTOMAKE = ${SHELL} /home/mosu/prog/video/ogmtools/missing --run automake-1.6 +AUTOHEADER = ${SHELL} /home/mosu/prog/video/ogmtools/missing --run autoheader + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = ${INSTALL} +INSTALL_HEADER = $(INSTALL_DATA) +transform = s,x,x, +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = +OBJEXT = o +PATH_SEPARATOR = : +AMTAR = ${SHELL} /home/mosu/prog/video/ogmtools/missing --run tar +AVILIB_CFLAGS = -Iavilib -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +AVILIB_CXXFLAGS = -Iavilib -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +AVILIB_LIBS = -Lavilib -lavi +AWK = gawk +CC = gcc +CPP = gcc -E +CXX = g++ +DEBUG_CFLAGS = -g -DDEBUG +DEPDIR = .deps +DMALLOC_CFLAGS = +DMALLOC_LIBS = +DVDREAD_CFLAGS = -I/usr/include -I/usr/local/include +DVDREAD_LIBS = -L/usr/lib -ldvdread -lm +INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s +OGG_CFLAGS = +OGG_LIBS = -logg +PACKAGE = ogmtools +PROFILING_CFLAGS = +PROFILING_LIBS = +RANLIB = ranlib +STRIP = +VERSION = 0.973 +VORBISENC_LIBS = -lvorbisenc +VORBISFILE_LIBS = -lvorbisfile +VORBIS_CFLAGS = +VORBIS_LIBS = -lvorbis -lm +am__include = include +am__quote = +install_sh = /home/mosu/prog/video/ogmtools/install-sh + +AUTOMAKE_OPTIONS = 1.3 foreign +DEFAULT_INCLUDES = -I$(top_srcdir) -I$(srcdir) -I$(top_builddir) -I. + +noinst_LIBRARIES = libavi.a + +INCLUDES = -I./ + +CFLAGS = -O3 -funroll-loops -ffast-math -DLINUX -Wall -Wall -Wno-sign-compare -Iavilib -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -g -DDEBUG +libavi_a_SOURCES = avilib.c avidump.c avimisc.c + +EXTRA_DIST = avilib.h README.avilib +subdir = avilib +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libavi_a_AR = $(AR) cru +libavi_a_LIBADD = +am_libavi_a_OBJECTS = avilib.$(OBJEXT) avidump.$(OBJEXT) \ + avimisc.$(OBJEXT) +libavi_a_OBJECTS = $(am_libavi_a_OBJECTS) + +DEFS = -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"ogmtools\" -DVERSION=\"0.973\" -DHAVE_LIBDVDREAD=1 -DHAVE_LIBDVDREAD_INC=1 -DSTDC_HEADERS=1 +CPPFLAGS = +LDFLAGS = +LIBS = +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +DEP_FILES = ./$(DEPDIR)/avidump.Po ./$(DEPDIR)/avilib.Po \ + ./$(DEPDIR)/avimisc.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libavi_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libavi_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign avilib/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libavi.a: $(libavi_a_OBJECTS) $(libavi_a_DEPENDENCIES) + -rm -f libavi.a + $(libavi_a_AR) libavi.a $(libavi_a_OBJECTS) $(libavi_a_LIBADD) + $(RANLIB) libavi.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/avidump.Po +include ./$(DEPDIR)/avilib.Po +include ./$(DEPDIR)/avimisc.Po + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: + source='$<' object='$@' libtool=no \ + depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \ + $(CCDEPMODE) $(depcomp) \ + $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: + source='$<' object='$@' libtool=no \ + depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \ + $(CCDEPMODE) $(depcomp) \ + $(COMPILE) -c `cygpath -w $<` +CCDEPMODE = depmode=gcc3 +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_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 +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/avilib/Makefile.am b/avilib/Makefile.am new file mode 100644 index 000000000..2f17b7882 --- /dev/null +++ b/avilib/Makefile.am @@ -0,0 +1,16 @@ +# # Process this file with automake to produce Makefile.in. + +AUTOMAKE_OPTIONS = 1.3 foreign +DEFAULT_INCLUDES = -I$(top_srcdir) -I$(srcdir) -I$(top_builddir) -I. + +noinst_LIBRARIES = libavi.a + +INCLUDES = -I./ + +CFLAGS=-O3 -funroll-loops -ffast-math -DLINUX -Wall @CFLAGS@ +libavi_a_SOURCES = avilib.c avidump.c avimisc.c + +EXTRA_DIST = avilib.h README.avilib + + + diff --git a/avilib/Makefile.in b/avilib/Makefile.in new file mode 100644 index 000000000..29522423a --- /dev/null +++ b/avilib/Makefile.in @@ -0,0 +1,324 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +# # Process this file with automake to produce Makefile.in. +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AVILIB_CFLAGS = @AVILIB_CFLAGS@ +AVILIB_CXXFLAGS = @AVILIB_CXXFLAGS@ +AVILIB_LIBS = @AVILIB_LIBS@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEBUG_CFLAGS = @DEBUG_CFLAGS@ +DEPDIR = @DEPDIR@ +DMALLOC_CFLAGS = @DMALLOC_CFLAGS@ +DMALLOC_LIBS = @DMALLOC_LIBS@ +DVDREAD_CFLAGS = @DVDREAD_CFLAGS@ +DVDREAD_LIBS = @DVDREAD_LIBS@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +OGG_CFLAGS = @OGG_CFLAGS@ +OGG_LIBS = @OGG_LIBS@ +PACKAGE = @PACKAGE@ +PROFILING_CFLAGS = @PROFILING_CFLAGS@ +PROFILING_LIBS = @PROFILING_LIBS@ +RANLIB = @RANLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VORBISENC_LIBS = @VORBISENC_LIBS@ +VORBISFILE_LIBS = @VORBISFILE_LIBS@ +VORBIS_CFLAGS = @VORBIS_CFLAGS@ +VORBIS_LIBS = @VORBIS_LIBS@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +AUTOMAKE_OPTIONS = 1.3 foreign +DEFAULT_INCLUDES = -I$(top_srcdir) -I$(srcdir) -I$(top_builddir) -I. + +noinst_LIBRARIES = libavi.a + +INCLUDES = -I./ + +CFLAGS = -O3 -funroll-loops -ffast-math -DLINUX -Wall @CFLAGS@ +libavi_a_SOURCES = avilib.c avidump.c avimisc.c + +EXTRA_DIST = avilib.h README.avilib +subdir = avilib +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libavi_a_AR = $(AR) cru +libavi_a_LIBADD = +am_libavi_a_OBJECTS = avilib.$(OBJEXT) avidump.$(OBJEXT) \ + avimisc.$(OBJEXT) +libavi_a_OBJECTS = $(am_libavi_a_OBJECTS) + +DEFS = @DEFS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/avidump.Po ./$(DEPDIR)/avilib.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/avimisc.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libavi_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libavi_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign avilib/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libavi.a: $(libavi_a_OBJECTS) $(libavi_a_DEPENDENCIES) + -rm -f libavi.a + $(libavi_a_AR) libavi.a $(libavi_a_OBJECTS) $(libavi_a_LIBADD) + $(RANLIB) libavi.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avidump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avilib.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avimisc.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `cygpath -w $<` +CCDEPMODE = @CCDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_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 +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/avilib/README.avilib b/avilib/README.avilib new file mode 100644 index 000000000..495c2960a --- /dev/null +++ b/avilib/README.avilib @@ -0,0 +1,221 @@ +avilib: Reading and writing avi files +===================================== + +Copyright (C) 1999 Rainer Johanni + +avilib is a open source library for dealing with AVI +files under Linux or other UNIX operating systems. + +It provides a framework for extracting or adding raw +audio and single raw (=compressed) frames from/to AVI Files. + +It does not deal with any compression issues which have to be +handled on a higher level by the user of avilib. + +AVI files may have several video and audiotracks. + +avilib writes only one video track and (optionally) one +audio track and also extracts only the first video and audio +track (but input files may contain more than one track, the others +just being ingored). + +The interface to avilib is kept similar to the quicktime4linux interface +(by Adam Williams) with the following important differences: + +- since only the first track of video and audio is considered, + there is no track argument in any of the routines. + +- audio is generally considered as a byte stream and therefore + all size arguments used in reading/writing audio are in bytes + and not in samples. + +- as mentioned above, there are no routines dealing with compression issues. + + +Compiling: +========== + +Since the library consists only of one c source file, I have not provided +a Makefile or similar, just compile with + +cc -c avilib.c + + +Portability: +============ + +AVI-Files use little endian numbers throughout the file, I have tried +to read/write these numbers in a way which doesn't depent on endianness. +This library should therefore also be useable on big endian machines. +This feature is not so heavily tested, however. + + +Usage: +====== + +Basics, opening, closing +------------------------ + +Include "avilib.h" in your source and declare a pointer: + + avi_t *avifile; + +Open the AVI file with: + + avifile = AVI_open_input_file("xxx.avi",1); + +or + + avifile = AVI_open_output_file("xxx.avi"); + +You may either only read from the input file (leaving it unchanged) +or create a completly new AVI file. There is no editing or append +mode available. + +Both routines will either return a pointer to avi_t or a zero pointer +in the case of an error. + +For closing the file, use: + + int AVI_close(avi_t *AVI); + +Files you have written MUST be closed (the header is written at close time), +else they will not be readable by any other software. + +Files opened for reading should be closed to free the file descriptor +and some data (unless your program is finishing anyway). + + +Error handling: +--------------- + +Most routines (besides open/close) will return 0 or a usefull number if successfull +and a -1 in the case of an error. If an error occured, the external variable +AVI_errno is set. See avilib.h for the meaning of the error codes in AVI_errno. + +There is also a routine (which acts like perror) to output a description +of the last error to stderr: + +AVI_print_error(char *str) + + + +Reading from an AVI file: +------------------------- + +After opening the file, you can obtain the parameters of the AVI +with the following routines: + +long AVI_video_frames(avi_t *AVI); + number of video frames in the file + +int AVI_video_width(avi_t *AVI); +int AVI_video_height(avi_t *AVI); + width and height of the video in pixels + +double AVI_frame_rate(avi_t *AVI); + frame rate in frames per second, notice that this is a double value! + +char* AVI_video_compressor(avi_t *AVI); + string describing the compressor + +int AVI_audio_channels(avi_t *AVI); + number of audio channels, 1 for mono, 2 for stereo, 0 if no audio present + +int AVI_audio_bits(avi_t *AVI); + audio bits, usually 8 or 16 + +int AVI_audio_format(avi_t *AVI); + audio format, most common is 1 for raw PCM, look into avilib.h for others + +long AVI_audio_rate(avi_t *AVI); + audio rate in samples/second + +long AVI_audio_bytes(avi_t *AVI); + total number of audio bytes in the file + + +In order to read the video frame by frame, use +(frame numbers are starting from 0 !!!!!) + +long AVI_frame_size(avi_t *AVI, long frame); + to get the size of frame with number "frame" + +long AVI_read_frame(avi_t *AVI, char *vidbuf); + to read the next frame (frame posittion is advanced by 1 after the read) + +int AVI_seek_start(avi_t *AVI); +int AVI_set_video_position(avi_t *AVI, long frame); + to position in the AVI file + (for reading the frames out of order) + + +Read audio with + +int AVI_set_audio_position(avi_t *AVI, long byte); + to position to an arbitrary byte position within the audio stream + +long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes); + to actually read "bytes" number of audio bytes. + the audio position is advanced by "bytes", so there is no + need to reposition before every call when reading in order. + + +Avoiding lengthy index searches: +-------------------------------- + +When opening the AVI file, avilib looks if the file has an index attached +and if this is not the case, it creates one by reading through the whole file. + +If you want to read through the file only once, creation of an index is +not necessary in that case. You may use AVI_open_input_file with the second +argument set to 0 and then use AVI_read_data for readin through the file. + +Look to the source for the arguments of AVI_read_data. + + +Writing to an AVI file: +----------------------- + +After you have opened the file, use the following routines to set +the properties of the AVI file: + +void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor); +void AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format); + +with: + +width, height width and height of the video in pixels + +fps frame rate in frames per second, notice that this is a double value! + +compressor string describing the compressor + +channels number of audio channels, 1 for mono, 2 for stereo, 0 if no audio present + +rate audio rate in samples/second + +bits audio bits, usually 8 or 16, 0 if no audio present + +format audio format, most common is 1 for raw PCM, look into avilib.h for others + + +to write video frames or audio, use: + +int AVI_write_frame(avi_t *AVI, char *data, long bytes); +int AVI_write_audio(avi_t *AVI, char *data, long bytes); + +there is also a feature to duplicate the index entry of the last +frame without writing the data again to the file, this should +used with care since I don't know if all AVI players can handle +the resulting file (xanim can do it!): + +int AVI_dup_frame(avi_t *AVI); + +AVI files have a 2 GB limit (as has the Linux ext2 file system), +avilib will return an error if you try to add more data to the file +(and it cares that the file still can be correctly closed). +If you want to check yourself how far you are away from that limit +(for example to synchronize the amount of audio and video data) use: + +long AVI_bytes_remain(avi_t *AVI); diff --git a/avilib/avidump.c b/avilib/avidump.c new file mode 100644 index 000000000..06cab7a90 --- /dev/null +++ b/avilib/avidump.c @@ -0,0 +1,784 @@ +/* + * avidump.c + * + * Copyright (C) Thomas Östreich - June 2001 + * + * based on code: + * (c)94 UP-Vision Computergrafik for c't + * Extracts some infos from RIFF files, modified by Gerd Knorr. + * + * This file is part of transcode, a linux video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__bsdi__) || defined(__FreeBSD__) +typedef off_t off64_t; +#define lseek64 lseek +#endif + +//#define AVI_DEBUG + +#ifdef HAVE_ENDIAN_H +# include +#endif +#if BYTE_ORDER == BIG_ENDIAN +# define SWAP2(x) (((x>>8) & 0x00ff) |\ + ((x<<8) & 0xff00)) + +# define SWAP4(x) (((x>>24) & 0x000000ff) |\ + ((x>>8) & 0x0000ff00) |\ + ((x<<8) & 0x00ff0000) |\ + ((x<<24) & 0xff000000)) +#else +# define SWAP2(a) (a) +# define SWAP4(a) (a) +#endif + +typedef unsigned long DWORD; +typedef unsigned short WORD; +typedef DWORD FOURCC; /* Type of FOUR Character Codes */ +typedef unsigned char boolean; +#define TRUE 1 +#define FALSE 0 +#define BUFSIZE 4096 + +/* Macro to convert expressions of form 'F','O','U','R' to + numbers of type FOURCC: */ + +#if BYTE_ORDER == BIG_ENDIAN +# define MAKEFOURCC(a,b,c,d) ((((DWORD)a)<<24) | (((DWORD)b)<<16) | \ + (((DWORD)c)<< 8) | ( (DWORD)d) ) +#else +# define MAKEFOURCC(a,b,c,d) ( ((DWORD)a) | (((DWORD)b)<< 8) | \ + (((DWORD)c)<<16) | (((DWORD)d)<<24) ) +#endif + +/* The only FOURCCs interpreted by this program: */ + +#define RIFFtag MAKEFOURCC('R','I','F','F') +#define LISTtag MAKEFOURCC('L','I','S','T') +#define avihtag MAKEFOURCC('a','v','i','h') +#define strhtag MAKEFOURCC('s','t','r','h') +#define strftag MAKEFOURCC('s','t','r','f') +#define vidstag MAKEFOURCC('v','i','d','s') +#define audstag MAKEFOURCC('a','u','d','s') +#define dmlhtag MAKEFOURCC('d','m','l','h') +#define idx1tag MAKEFOURCC('i','d','x','1') +#define Tag00db MAKEFOURCC('0','0','d','b') +#define Tag00dc MAKEFOURCC('0','0','d','c') +#define Tag01wb MAKEFOURCC('0','1','w','b') +#define Tagwave MAKEFOURCC('f','m','t',' ') +#define Tagdata MAKEFOURCC('d','a','t','a') +#define TagDATA MAKEFOURCC('D','A','T','A') +#define Tag00__ MAKEFOURCC('0','0','_','_') + +/* Build a string from a FOURCC number + (s must have room for at least 5 chars) */ + +static void FOURCC2Str(FOURCC fcc, char* s) +{ +#if BYTE_ORDER == BIG_ENDIAN + s[0]=(fcc >> 24) & 0xFF; + s[1]=(fcc >> 16) & 0xFF; + s[2]=(fcc >> 8) & 0xFF; + s[3]=(fcc ) & 0xFF; +#else + s[0]=(fcc ) & 0xFF; + s[1]=(fcc >> 8) & 0xFF; + s[2]=(fcc >> 16) & 0xFF; + s[3]=(fcc >> 24) & 0xFF; +#endif + s[4]=0; +} + +static DWORD fcc_type; + +#define EoLST 0 +#define INT32 1 +#define INT16 2 +#define FLAGS 3 +#define CCODE 4 +#define HEX16 5 +#define _TAG 6 + +struct FLAGLIST { + int bit; + char *name; +}; + +struct VAL { + int type; + char *name; + struct FLAGLIST *flags; +}; + +struct FLAGLIST flags_avih[] = { + { 0x00000010, "hasindex" }, + { 0x00000020, "useindex" }, + { 0x00000100, "interleaved" }, + { 0x00010000, "for_capture" }, + { 0x00020000, "copyrighted" }, + { 0, NULL } +}; + +struct VAL names_avih[] = { + { INT32, "us_frame" }, + { INT32, "max_bps" }, + { INT32, "pad_gran" }, + { FLAGS, "flags", flags_avih }, + { INT32, "tot_frames" }, + { INT32, "init_frames" }, + { INT32, "streams" }, + { INT32, "sug_bsize" }, + { INT32, "width" }, + { INT32, "height" }, + { INT32, "scale" }, + { INT32, "rate" }, + { INT32, "start" }, + { INT32, "length" }, + { EoLST, NULL } +}; + +struct VAL names_strh[] = { + { CCODE, "fcc_handler" }, + { FLAGS, "flags" }, + { INT32, "priority" }, + { INT32, "init_frames" }, + { INT32, "scale" }, + { INT32, "rate" }, + { INT32, "start" }, + { INT32, "length" }, + { INT32, "sug_bsize" }, + { INT32, "quality" }, + { INT32, "samp_size" }, + { EoLST, NULL } +}; + +struct VAL names_strf_vids[] = { + { INT32, "size" }, + { INT32, "width" }, + { INT32, "height" }, + { INT16, "planes" }, + { INT16, "bit_cnt" }, + { CCODE, "compression" }, + { INT32, "image_size" }, + { INT32, "xpels_meter" }, + { INT32, "ypels_meter" }, + { INT32, "num_colors" }, + { INT32, "imp_colors" }, + { EoLST, NULL } +}; + +struct VAL names_strf_auds[] = { + { HEX16, "format" }, + { INT16, "channels" }, + { INT32, "rate" }, + { INT32, "av_bps" }, + { INT16, "blockalign" }, + { INT16, "bits" }, + { EoLST, NULL } +}; + +struct VAL names_dmlh[] = { + { INT32, "frames" }, + { EoLST, NULL } +}; + +struct VAL names_idx1[] = { + { _TAG, "tag" }, + { INT32, "flags" }, + { INT32, "pos" }, + { INT32, "length" }, + { EoLST, NULL } +}; + +#define MAX_BUF (4096) +static char buffer[MAX_BUF]; + +static size_t avi_read(int fd, char *buf, size_t len) +{ + size_t n = 0; + size_t r = 0; + + while (r < len) { + n = read (fd, buf + r, len - r); + + if (n <= 0) + return r; + r += n; + } + + return r; +} + +static size_t avi_write (int fd, char *buf, size_t len) +{ + size_t n = 0; + size_t r = 0; + + while (r < len) { + n = write (fd, buf + r, len - r); + if (n < 0) + return n; + + r += n; + } + return r; +} + +static size_t avi_read_write (int fd_in, int fd_out, size_t len) +{ + + size_t w=len, z=0; + + while(w>0) { + + if(w>MAX_BUF) { + z=avi_read(fd_in, buffer, MAX_BUF); + if(z<0) return(z); + z=avi_write(fd_out, buffer, MAX_BUF); + if(z<0) return(z); + w -=MAX_BUF; + } else { + z=avi_read(fd_in, buffer, w); + if(z<0) return(z); + z=avi_write(fd_out, buffer, w); + if(z<0) return(z); + w = 0; + } + } //data > 0 + + return(len); +} + + +static void dump_vals(int fd, int count, struct VAL *names) +{ + DWORD i,j,val32; + WORD val16; + + for (i = 0; names[i].type != EoLST; i++) { + switch (names[i].type) { + case INT32: + read(fd, &val32, 4); + val32 = SWAP4(val32); + printf("\t%-12s = %ld\n",names[i].name,val32); + break; + case CCODE: + read(fd, &val32,4); + val32 = SWAP4(val32); + if (val32) { + printf("\t%-12s = %c%c%c%c (0x%lx)\n",names[i].name, + (int)( val32 & 0xff), + (int)((val32 >> 8) & 0xff), + (int)((val32 >> 16) & 0xff), + (int)((val32 >> 24) & 0xff), + val32); + } else { + printf("\t%-12s = unset (0)\n",names[i].name); + } + break; + case _TAG: + read(fd, &val32,4); + val32 = SWAP4(val32); + if (val32) { + printf("\t%-12s = %c%c%c%c\n",names[i].name, + (int)( val32 & 0xff), + (int)((val32 >> 8) & 0xff), + (int)((val32 >> 16) & 0xff), + (int)((val32 >> 24) & 0xff)); + } else { + printf("\t%-12s = unset (0)\n",names[i].name); + } + break; + case FLAGS: + read(fd, &val32,4); + val32 = SWAP4(val32); + printf("\t%-12s = 0x%lx\n",names[i].name,val32); + if (names[i].flags) { + for (j = 0; names[i].flags[j].bit != 0; j++) + if (names[i].flags[j].bit & val32) + printf("\t\t0x%x: %s\n", + names[i].flags[j].bit,names[i].flags[j].name); + } + break; + case INT16: + read(fd, &val16,2); + val16 = SWAP2(val16); + printf("\t%-12s = %ld\n",names[i].name,(long)val16); + break; + + case HEX16: + read(fd, &val16,2); + val16 = SWAP2(val16); + printf("\t%-12s = 0x%lx\n",names[i].name,(long)val16); + break; + } + } +} + +static void hexlog(unsigned char *buf, int count) +{ + int l,i; + + for (l = 0; l < count; l+= 16) { + printf("\t "); + for (i = l; i < l+16; i++) { + if (i < count) + printf("%02x ",buf[i]); + else + printf(" "); + if ((i%4) == 3) + printf(" "); + } + for (i = l; i < l+16; i++) { + if (i < count) + printf("%c",isprint(buf[i]) ? buf[i] : '.'); + } + printf("\n"); + } +} + +static unsigned char* +off_t_to_char(off_t val, int base, int len) +{ + static const char digit[] = "0123456789abcdef"; + static char outbuf[32]; + char *p = outbuf + sizeof(outbuf); + int i; + + *(--p) = 0; + for (i = 0; i < len || val > 0; i++) { + *(--p) = digit[ val % base ]; + val = val / base; + } + return p; +} + +/* Reads a chunk ID and the chunk's size from file f at actual + file position : */ + +static boolean ReadChunkHead(int fd, FOURCC* ID, DWORD* size) +{ + if (!read(fd, ID, sizeof(FOURCC))) return(FALSE); + if (!read(fd, size, sizeof(DWORD))) return(FALSE); + + *size = SWAP4(*size); + +#ifdef AVI_DEBUG + printf("ReadChunkHead size = %lu\n", *size); +#endif + + return(TRUE); +} + +/* Processing of a chunk. (Will be called recursively!). + Processes file f starting at position filepos. + f contains filesize bytes. + If DesiredTag!=0, ProcessChunk tests, whether the chunk begins + with the DesiredTag. If the read chunk is not identical to + DesiredTag, an error message is printed. + RekDepth determines the recursion depth of the chunk. + chunksize is set to the length of the chunk's data (excluding + header and padding byte). + ProcessChunk prints out information of the chunk to stdout + and returns FALSE, if an error occured. */ + +static off_t datapos_tmp[8]; + +static boolean ProcessChunk(int fd, off_t filepos, off_t filesize, + FOURCC DesiredTag, int RekDepth, + DWORD* chunksize) +{ + char tagstr[5]; /* FOURCC of chunk converted to string */ + FOURCC chunkid; /* read FOURCC of chunk */ + off_t datapos; /* position of data in file to process */ + + off_t tt; + + if (filepos>filesize-1) { /* Oops. Must be something wrong! */ + printf(" ***** Error: Data would be behind end of file!\n"); + } + + tt=lseek64(fd, filepos, SEEK_SET); /* Go to desired file position! */ + +#ifdef AVI_DEBUG + printf("lseek64=%Lu/%Lu (%Lu)\n", tt, filepos, filesize); +#endif + + if (!ReadChunkHead(fd, &chunkid, chunksize)) { /* read chunk header */ + printf(" ***** Error reading chunk at filepos 0x%s\n", + off_t_to_char(filepos,16,1)); + return(FALSE); + } + FOURCC2Str(chunkid,tagstr); /* now we can PRINT the chunkid */ + if (DesiredTag) { /* do we have to test identity? */ + if (DesiredTag!=chunkid) { + char ds[5]; + FOURCC2Str(DesiredTag,ds); + printf("\n\n *** Error: Expected chunk '%s', found '%s'\n", + ds,tagstr); + return(FALSE); + } + } + + datapos=filepos+sizeof(FOURCC)+sizeof(DWORD); /* here is the data */ + + /* print out header: */ +#ifdef AVI_DEBUG + printf("(%Lu) %*c ID:<%s> Size: %lu\n", + filepos ,(RekDepth+1)*4,' ',tagstr, *chunksize); +#else + printf("(0x%s) %*c ID:<%s> Size: 0x%08lx %8lu\n", + off_t_to_char(filepos,16,8),(RekDepth+1)*4,' ',tagstr, *chunksize, *chunksize); +#endif + + + if (datapos + ((*chunksize+1)&~1) > filesize) { /* too long? */ + printf(" ***** Error: Chunk exceeds file\n"); + } + + switch (chunkid) { + + /* Depending on the ID of the chunk and the internal state, the + different IDs can be interpreted. At the moment the only + interpreted chunks are RIFF- and LIST-chunks. For all other + chunks only their header is printed out. */ + + case RIFFtag: + case LISTtag: { + + DWORD datashowed=0; + FOURCC formtype; /* format of chunk */ + char formstr[5]; /* format of chunk converted to string */ + DWORD subchunksize=0; /* size of a read subchunk */ + + if (!read(fd, &formtype, sizeof(FOURCC))) printf("ERROR\n"); /* read the form type */ + FOURCC2Str(formtype,formstr); /* make it printable */ + + + /* print out the indented form of the chunk: */ + if (chunkid==RIFFtag) + printf("%12c %*c Form Type = <%s>\n", + ' ',(RekDepth+1)*4,' ',formstr); + else + printf("%12c %*c List Type = <%s>\n", + ' ',(RekDepth+1)*4,' ',formstr); + + datashowed=sizeof(FOURCC); /* we showed the form type */ + datapos+=(off_t) datashowed; /* for the rest of the routine */ + + while (datashowed<*chunksize) { /* while not showed all: */ + + long subchunklen; /* complete size of a subchunk */ + + datapos_tmp[RekDepth]=datapos; + + /* recurse for subchunks of RIFF and LIST chunks: */ +#ifdef AVI_DEBUG + printf("enter [%d] size=%lu pos=%Lu left=%lu\n", RekDepth, subchunksize, datapos, *chunksize-datashowed); +#endif + if (!ProcessChunk(fd, datapos, filesize, (off_t) 0, + RekDepth+1, &subchunksize)) return(FALSE); + + subchunklen = sizeof(FOURCC) + /* this is the complete.. */ + sizeof(DWORD) + /* .. size of the subchunk */ + ((subchunksize+1) & ~1); + + datashowed += subchunklen; /* we showed the subchunk */ + datapos = datapos_tmp[RekDepth] + (off_t) subchunklen; /* for the rest of the loop */ + +#ifdef AVI_DEBUG + printf(" exit [%d] size=%lu/%lu pos=%Lu left=%lu\n", RekDepth, subchunksize, subchunklen, datapos, *chunksize-datashowed); +#endif + } + } break; + + /* Feel free to put your extensions here! */ + + case avihtag: + dump_vals(fd,sizeof(names_avih)/sizeof(struct VAL),names_avih); + break; + case strhtag: + { + char typestr[5]; + read(fd, &fcc_type,sizeof(FOURCC)); + FOURCC2Str(fcc_type,typestr); + printf("\tfcc_type = %s\n",typestr); + dump_vals(fd,sizeof(names_strh)/sizeof(struct VAL),names_strh); + break; + } + case strftag: + + switch (fcc_type) { + case vidstag: + dump_vals(fd,sizeof(names_strf_vids)/sizeof(struct VAL),names_strf_vids); + break; + case audstag: + dump_vals(fd,sizeof(names_strf_auds)/sizeof(char*),names_strf_auds); + break; + default: + printf("unknown\n"); + break; + } + break; + + case Tagwave: + dump_vals(fd,sizeof(names_strf_auds)/sizeof(char*),names_strf_auds); + break; + + case idx1tag: + + while (datapos> 8) & 0xff), + (int)((val32 >> 16) & 0xff), + (int)((val32 >> 24) & 0xff)); + } else printf("\t\t %s=%c%c%c%c ", "tag", + (int)( val32 & 0xff), + (int)((val32 >> 8) & 0xff), + (int)((val32 >> 16) & 0xff), + (int)((val32 >> 24) & 0xff)); + + + //flag + read(fd, &val32, 4); + val32 = SWAP4(val32); + printf("flags=%02ld ",val32); + + //pos + read(fd, &val32, 4); + val32 = SWAP4(val32); + printf("0x%08lx",val32); + + //size + read(fd, &val32, 4); + val32 = SWAP4(val32); + printf("%8ld\n",val32); + + datapos+=16; + } + break; + + case dmlhtag: + dump_vals(fd,sizeof(names_dmlh)/sizeof(struct VAL),names_dmlh); + break; + } + + return(TRUE); +} + +static DWORD size; +static int eos=0; + +static boolean DumpChunk(int fd, off_t filepos, off_t filesize, + FOURCC DesiredTag, int RekDepth, + DWORD* chunksize, int mode) +{ + char tagstr[5]; /* FOURCC of chunk converted to string */ + FOURCC chunkid; /* read FOURCC of chunk */ + off_t datapos; /* position of data in file to process */ + + if (filepos>filesize-1) /* Oops. Must be something wrong! */ + return(FALSE); + + lseek64(fd, filepos, SEEK_SET); + + if (!ReadChunkHead(fd, &chunkid,chunksize)) { /* read chunk header */ + return(FALSE); + } + + FOURCC2Str(chunkid,tagstr); /* now we can PRINT the chunkid */ + + if (DesiredTag) { /* do we have to test identity? */ + if (DesiredTag!=chunkid) { + char ds[5]; + FOURCC2Str(DesiredTag,ds); + return(FALSE); + } + } + + datapos=filepos+sizeof(FOURCC)+sizeof(DWORD); /* here is the data */ + + //support for broken files + if (datapos + ((*chunksize+1)&~1) > filesize) { + size = filesize-datapos; + eos=1; + } else { + size = *chunksize; + } + + switch (chunkid) { + + /* Depending on the ID of the chunk and the internal state, the + different IDs can be interpreted. At the moment the only + interpreted chunks are RIFF- and LIST-chunks. For all other + chunks only their header is printed out. */ + + case RIFFtag: + case LISTtag: { + + DWORD datashowed; + FOURCC formtype; /* format of chunk */ + char formstr[5]; /* format of chunk converted to string */ + DWORD subchunksize; /* size of a read subchunk */ + + read(fd, &formtype,sizeof(FOURCC)); /* read the form type */ + FOURCC2Str(formtype,formstr); /* make it printable */ + + datashowed=sizeof(FOURCC); /* we showed the form type */ + datapos+=(off_t)datashowed; /* for the rest of the routine */ + + while (datashowed<*chunksize) { /* while not showed all: */ + + long subchunklen; /* complete size of a subchunk */ + + /* recurse for subchunks of RIFF and LIST chunks: */ + if (!DumpChunk(fd, datapos,filesize,0, + RekDepth+1,&subchunksize,mode)) return(FALSE); + + subchunklen = sizeof(FOURCC) + /* this is the complete.. */ + sizeof(DWORD) + /* .. size of the subchunk */ + ((subchunksize+1) & ~1); + + datashowed += subchunklen; /* we showed the subchunk */ + datapos += (off_t) subchunklen; /* for the rest of the loop */ + } + } + + break; + + case Tag01wb: + + if(mode==1) { + lseek(fd, datapos, SEEK_SET); + if(avi_read_write(fd, STDOUT_FILENO, size)!=size) return(FALSE); + } + if(eos) return(FALSE); + + break; + + case Tag00db: + case Tag00dc: + case Tag00__: + + if(mode==0) { + lseek(fd, datapos, SEEK_SET); + if(avi_read_write(fd, STDOUT_FILENO, size)!=size) return(FALSE); + } + + if(eos) return(FALSE); + + break; + + case Tagdata: + case TagDATA: + + if(mode==2) { + lseek(fd, datapos, SEEK_SET); + if(avi_read_write(fd, STDOUT_FILENO, size)!=size) return(FALSE); + } + + if(eos) exit(1); + + break; + } + + return(TRUE); +} + + +int AVI_scan(char *file_name) +{ + off_t filesize; /* its size */ + off_t filepos; + + int fd; + + DWORD chunksize; /* size of the RIFF chunk data */ + + if (!(fd=open(file_name, O_RDONLY))) { + printf("\n\n *** Error opening file %s. Program aborted!\n", + file_name); + return(1); + } + + filesize = lseek64(fd, 0, SEEK_END); + lseek64(fd, 0, SEEK_SET); + + printf("Contents of file %s (%s/", file_name, + off_t_to_char(filesize,10,1)); + printf("0x%s bytes):\n\n",off_t_to_char(filesize,16,1)); + + for (filepos = 0; filepos < filesize;) { + chunksize = 0; + if (!ProcessChunk(fd, filepos,filesize,RIFFtag,0,&chunksize)) + break; + filepos += chunksize + 8; + printf("\n"); + } + + close(fd); + + return(0); +} + + +int AVI_dump(char *file_name, int mode) +{ + off_t filesize; /* its size */ + off_t filepos; + int fd; + + DWORD chunksize; /* size of the RIFF chunk data */ + + if (!(fd=open(file_name,O_RDONLY))) return(1); + + filesize = lseek64(fd, 0, SEEK_END); + lseek64(fd, 0, SEEK_SET); + + for (filepos = 0; filepos < filesize;) { + chunksize = 0; + if (!DumpChunk(fd,filepos,filesize,RIFFtag,0,&chunksize,mode)) + break; + filepos += chunksize + 8; + } + + close(fd); + + return(0); +} diff --git a/avilib/avidump.o b/avilib/avidump.o new file mode 100644 index 000000000..002a3e980 Binary files /dev/null and b/avilib/avidump.o differ diff --git a/avilib/avilib.c b/avilib/avilib.c new file mode 100644 index 000000000..fa690bb9d --- /dev/null +++ b/avilib/avilib.c @@ -0,0 +1,1852 @@ +/* + * avilib.c + * + * Copyright (C) Thomas Östreich - June 2001 + * multiple audio track support Copyright (C) 2002 Thomas Östreich + * + * Original code: + * Copyright (C) 1999 Rainer Johanni + * + * This file is part of transcode, a linux video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "avilib.h" +//#include + +#define INFO_LIST + +/* The following variable indicates the kind of error */ + +long AVI_errno = 0; + +#define MAX_INFO_STRLEN 64 +static char id_str[MAX_INFO_STRLEN]; + +#define FRAME_RATE_SCALE 1000000 + +/******************************************************************* + * * + * Utilities for writing an AVI File * + * * + *******************************************************************/ + +static size_t avi_read(int fd, char *buf, size_t len) +{ + size_t n = 0; + size_t r = 0; + + while (r < len) { + n = read (fd, buf + r, len - r); + + if ((ssize_t)n <= 0) + return r; + r += n; + } + + return r; +} + +static size_t avi_write (int fd, char *buf, size_t len) +{ + size_t n = 0; + size_t r = 0; + + while (r < len) { + n = write (fd, buf + r, len - r); + if ((ssize_t)n < 0) + return n; + + r += n; + } + return r; +} + +/* HEADERBYTES: The number of bytes to reserve for the header */ + +#define HEADERBYTES 2048 + +/* AVI_MAX_LEN: The maximum length of an AVI file, we stay a bit below + the 2GB limit (Remember: 2*10^9 is smaller than 2 GB) */ + +#define AVI_MAX_LEN (UINT_MAX-(1<<20)*16-HEADERBYTES) + +#define PAD_EVEN(x) ( ((x)+1) & ~1 ) + + +/* Copy n into dst as a 4 byte, little endian number. + Should also work on big endian machines */ + +static void long2str(unsigned char *dst, int n) +{ + dst[0] = (n )&0xff; + dst[1] = (n>> 8)&0xff; + dst[2] = (n>>16)&0xff; + dst[3] = (n>>24)&0xff; +} + +/* Convert a string of 4 or 2 bytes to a number, + also working on big endian machines */ + +static unsigned long str2ulong(unsigned char *str) +{ + return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) ); +} +static unsigned long str2ushort(unsigned char *str) +{ + return ( str[0] | (str[1]<<8) ); +} + +/* Calculate audio sample size from number of bits and number of channels. + This may have to be adjusted for eg. 12 bits and stereo */ + +static int avi_sampsize(avi_t *AVI, int j) +{ + int s; + s = ((AVI->track[j].a_bits+7)/8)*AVI->track[j].a_chans; + // if(s==0) s=1; /* avoid possible zero divisions */ + if(s<4) s=4; /* avoid possible zero divisions */ + return s; +} + +/* Add a chunk (=tag and data) to the AVI file, + returns -1 on write error, 0 on success */ + +static int avi_add_chunk(avi_t *AVI, unsigned char *tag, unsigned char *data, int length) +{ + unsigned char c[8]; + + /* Copy tag and length int c, so that we need only 1 write system call + for these two values */ + + memcpy(c,tag,4); + long2str(c+4,length); + + /* Output tag, length and data, restore previous position + if the write fails */ + + length = PAD_EVEN(length); + + if( avi_write(AVI->fdes,c,8) != 8 || + avi_write(AVI->fdes,data,length) != length ) + { + lseek(AVI->fdes,AVI->pos,SEEK_SET); + AVI_errno = AVI_ERR_WRITE; + return -1; + } + + /* Update file position */ + + AVI->pos += 8 + length; + + //fprintf(stderr, "pos=%lu %s\n", AVI->pos, tag); + + return 0; +} + +static int avi_add_index_entry(avi_t *AVI, unsigned char *tag, long flags, unsigned long pos, unsigned long len) +{ + void *ptr; + + if(AVI->n_idx>=AVI->max_idx) { + ptr = realloc((void *)AVI->idx,(AVI->max_idx+4096)*16); + + if(ptr == 0) { + AVI_errno = AVI_ERR_NO_MEM; + return -1; + } + AVI->max_idx += 4096; + AVI->idx = (unsigned char((*)[16]) ) ptr; + } + + /* Add index entry */ + + // fprintf(stderr, "INDEX %s %ld %lu %lu\n", tag, flags, pos, len); + + memcpy(AVI->idx[AVI->n_idx],tag,4); + long2str(AVI->idx[AVI->n_idx]+ 4,flags); + long2str(AVI->idx[AVI->n_idx]+ 8, pos); + long2str(AVI->idx[AVI->n_idx]+12, len); + + /* Update counter */ + + AVI->n_idx++; + + if(len>AVI->max_len) AVI->max_len=len; + + return 0; +} + +/* + AVI_open_output_file: Open an AVI File and write a bunch + of zero bytes as space for the header. + + returns a pointer to avi_t on success, a zero pointer on error +*/ + +avi_t* AVI_open_output_file(char * filename) +{ + avi_t *AVI; + int i; + + int mask; + + unsigned char AVI_header[HEADERBYTES]; + + /* Allocate the avi_t struct and zero it */ + + AVI = (avi_t *) malloc(sizeof(avi_t)); + if(AVI==0) + { + AVI_errno = AVI_ERR_NO_MEM; + return 0; + } + memset((void *)AVI,0,sizeof(avi_t)); + + /* Since Linux needs a long time when deleting big files, + we do not truncate the file when we open it. + Instead it is truncated when the AVI file is closed */ + + mask = umask (0); + umask (mask); + + AVI->fdes = open(filename, O_RDWR|O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) &~ mask); + if (AVI->fdes < 0) + { + AVI_errno = AVI_ERR_OPEN; + free(AVI); + return 0; + } + + /* Write out HEADERBYTES bytes, the header will go here + when we are finished with writing */ + + for (i=0;ifdes,AVI_header,HEADERBYTES); + if (i != HEADERBYTES) + { + close(AVI->fdes); + AVI_errno = AVI_ERR_WRITE; + free(AVI); + return 0; + } + + AVI->pos = HEADERBYTES; + AVI->mode = AVI_MODE_WRITE; /* open for writing */ + + //init + AVI->anum = 0; + AVI->aptr = 0; + + return AVI; +} + +void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor) +{ + /* may only be called if file is open for writing */ + + if(AVI->mode==AVI_MODE_READ) return; + + AVI->width = width; + AVI->height = height; + AVI->fps = fps; + + if(strncmp(compressor, "RGB", 3)==0) { + memset(AVI->compressor, 0, 4); + } else { + memcpy(AVI->compressor,compressor,4); + } + + AVI->compressor[4] = 0; + + avi_update_header(AVI); +} + +void AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format, long mp3rate) +{ + /* may only be called if file is open for writing */ + + if(AVI->mode==AVI_MODE_READ) return; + + //inc audio tracks + AVI->aptr=AVI->anum; + ++AVI->anum; + + if(AVI->anum > AVI_MAX_TRACKS) { + fprintf(stderr, "error - only %d audio tracks supported\n", AVI_MAX_TRACKS); + exit(1); + } + + AVI->track[AVI->aptr].a_chans = channels; + AVI->track[AVI->aptr].a_rate = rate; + AVI->track[AVI->aptr].a_bits = bits; + AVI->track[AVI->aptr].a_fmt = format; + AVI->track[AVI->aptr].mp3rate = mp3rate; + + avi_update_header(AVI); +} + +#define OUT4CC(s) \ + if(nhb<=HEADERBYTES-4) memcpy(AVI_header+nhb,s,4); nhb += 4 + +#define OUTLONG(n) \ + if(nhb<=HEADERBYTES-4) long2str(AVI_header+nhb,n); nhb += 4 + +#define OUTSHRT(n) \ + if(nhb<=HEADERBYTES-2) { \ + AVI_header[nhb ] = (n )&0xff; \ + AVI_header[nhb+1] = (n>>8)&0xff; \ + } \ + nhb += 2 + + +//ThOe write preliminary AVI file header: 0 frames, max vid/aud size +int avi_update_header(avi_t *AVI) +{ + int njunk, sampsize, hasIndex, ms_per_frame, frate, flag; + int movi_len, hdrl_start, strl_start, j; + unsigned char AVI_header[HEADERBYTES]; + long nhb; + + //assume max size + movi_len = AVI_MAX_LEN - HEADERBYTES + 4; + + //assume index will be written + hasIndex=1; + + if(AVI->fps < 0.001) { + frate=0; + ms_per_frame=0; + } else { + frate = (int) (FRAME_RATE_SCALE*AVI->fps + 0.5); + ms_per_frame=(int) (1000000/AVI->fps + 0.5); + } + + /* Prepare the file header */ + + nhb = 0; + + /* The RIFF header */ + + OUT4CC ("RIFF"); + OUTLONG(movi_len); // assume max size + OUT4CC ("AVI "); + + /* Start the header list */ + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + hdrl_start = nhb; /* Store start position */ + OUT4CC ("hdrl"); + + /* The main AVI header */ + + /* The Flags in AVI File header */ + +#define AVIF_HASINDEX 0x00000010 /* Index at end of file */ +#define AVIF_MUSTUSEINDEX 0x00000020 +#define AVIF_ISINTERLEAVED 0x00000100 +#define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames */ +#define AVIF_WASCAPTUREFILE 0x00010000 +#define AVIF_COPYRIGHTED 0x00020000 + + OUT4CC ("avih"); + OUTLONG(56); /* # of bytes to follow */ + OUTLONG(ms_per_frame); /* Microseconds per frame */ + //ThOe ->0 + // OUTLONG(10000000); /* MaxBytesPerSec, I hope this will never be used */ + OUTLONG(0); + OUTLONG(0); /* PaddingGranularity (whatever that might be) */ + /* Other sources call it 'reserved' */ + flag = AVIF_ISINTERLEAVED; + if(hasIndex) flag |= AVIF_HASINDEX; + if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX; + OUTLONG(flag); /* Flags */ + OUTLONG(0); // no frames yet + OUTLONG(0); /* InitialFrames */ + + OUTLONG(AVI->anum+1); + + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(AVI->width); /* Width */ + OUTLONG(AVI->height); /* Height */ + /* MS calls the following 'reserved': */ + OUTLONG(0); /* TimeScale: Unit used to measure time */ + OUTLONG(0); /* DataRate: Data rate of playback */ + OUTLONG(0); /* StartTime: Starting time of AVI data */ + OUTLONG(0); /* DataLength: Size of AVI data chunk */ + + + /* Start the video stream list ---------------------------------- */ + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + strl_start = nhb; /* Store start position */ + OUT4CC ("strl"); + + /* The video stream header */ + + OUT4CC ("strh"); + OUTLONG(56); /* # of bytes to follow */ + OUT4CC ("vids"); /* Type */ + OUT4CC (AVI->compressor); /* Handler */ + OUTLONG(0); /* Flags */ + OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ + OUTLONG(0); /* InitialFrames */ + OUTLONG(FRAME_RATE_SCALE); /* Scale */ + OUTLONG(frate); /* Rate: Rate/Scale == samples/second */ + OUTLONG(0); /* Start */ + OUTLONG(0); // no frames yet + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(-1); /* Quality */ + OUTLONG(0); /* SampleSize */ + OUTLONG(0); /* Frame */ + OUTLONG(0); /* Frame */ + // OUTLONG(0); /* Frame */ + //OUTLONG(0); /* Frame */ + + /* The video stream format */ + + OUT4CC ("strf"); + OUTLONG(40); /* # of bytes to follow */ + OUTLONG(40); /* Size */ + OUTLONG(AVI->width); /* Width */ + OUTLONG(AVI->height); /* Height */ + OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ + OUT4CC (AVI->compressor); /* Compression */ + // ThOe (*3) + OUTLONG(AVI->width*AVI->height*3); /* SizeImage (in bytes?) */ + OUTLONG(0); /* XPelsPerMeter */ + OUTLONG(0); /* YPelsPerMeter */ + OUTLONG(0); /* ClrUsed: Number of colors used */ + OUTLONG(0); /* ClrImportant: Number of colors important */ + + /* Finish stream list, i.e. put number of bytes in the list to proper pos */ + + long2str(AVI_header+strl_start-4,nhb-strl_start); + + + /* Start the audio stream list ---------------------------------- */ + + for(j=0; janum; ++j) { + + sampsize = avi_sampsize(AVI, j); + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + strl_start = nhb; /* Store start position */ + OUT4CC ("strl"); + + /* The audio stream header */ + + OUT4CC ("strh"); + OUTLONG(56); /* # of bytes to follow */ + OUT4CC ("auds"); + + // ----------- + // ThOe + OUTLONG(0); /* Format (Optionally) */ + // ----------- + + OUTLONG(0); /* Flags */ + OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ + OUTLONG(0); /* InitialFrames */ + + // ThOe /4 + OUTLONG(sampsize/4); /* Scale */ + OUTLONG(1000*AVI->track[j].mp3rate/8); + OUTLONG(0); /* Start */ + OUTLONG(4*AVI->track[j].audio_bytes/sampsize); /* Length */ + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(-1); /* Quality */ + + // ThOe /4 + OUTLONG(sampsize/4); /* SampleSize */ + + OUTLONG(0); /* Frame */ + OUTLONG(0); /* Frame */ + // OUTLONG(0); /* Frame */ + //OUTLONG(0); /* Frame */ + + /* The audio stream format */ + + OUT4CC ("strf"); + OUTLONG(16); /* # of bytes to follow */ + OUTSHRT(AVI->track[j].a_fmt); /* Format */ + OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ + OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ + // ThOe + OUTLONG(1000*AVI->track[j].mp3rate/8); + //ThOe (/4) + + OUTSHRT(sampsize/4); /* BlockAlign */ + + + OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ + + /* Finish stream list, i.e. put number of bytes in the list to proper pos */ + + long2str(AVI_header+strl_start-4,nhb-strl_start); + } + + /* Finish header list */ + + long2str(AVI_header+hdrl_start-4,nhb-hdrl_start); + + + /* Calculate the needed amount of junk bytes, output junk */ + + njunk = HEADERBYTES - nhb - 8 - 12; + + /* Safety first: if njunk <= 0, somebody has played with + HEADERBYTES without knowing what (s)he did. + This is a fatal error */ + + if(njunk<=0) + { + fprintf(stderr,"AVI_close_output_file: # of header bytes too small\n"); + exit(1); + } + + OUT4CC ("JUNK"); + OUTLONG(njunk); + memset(AVI_header+nhb,0,njunk); + + //2001-11-14 added id string + + if(njunk > strlen(id_str)+8) { + sprintf(id_str, "%s-%s", PACKAGE, VERSION); + memcpy(AVI_header+nhb, id_str, strlen(id_str)); + } + + nhb += njunk; + + /* Start the movi list */ + + OUT4CC ("LIST"); + OUTLONG(movi_len); /* Length of list in bytes */ + OUT4CC ("movi"); + + /* Output the header, truncate the file to the number of bytes + actually written, report an error if someting goes wrong */ + + if ( lseek(AVI->fdes,0,SEEK_SET)<0 || + avi_write(AVI->fdes,AVI_header,HEADERBYTES)!=HEADERBYTES || + lseek(AVI->fdes,AVI->pos,SEEK_SET)<0) + { + AVI_errno = AVI_ERR_CLOSE; + return -1; + } + + return 0; +} + +/* + Write the header of an AVI file and close it. + returns 0 on success, -1 on write error. +*/ + +static int avi_close_output_file(avi_t *AVI) +{ + + int ret, njunk, sampsize, hasIndex, ms_per_frame, frate, idxerror, flag; + unsigned long movi_len; + int hdrl_start, strl_start, j; + unsigned char AVI_header[HEADERBYTES]; + long nhb; + +#ifdef INFO_LIST + long info_len; +// time_t calptr; +#endif + + /* Calculate length of movi list */ + + movi_len = AVI->pos - HEADERBYTES + 4; + + /* Try to ouput the index entries. This may fail e.g. if no space + is left on device. We will report this as an error, but we still + try to write the header correctly (so that the file still may be + readable in the most cases */ + + idxerror = 0; + // fprintf(stderr, "pos=%lu, index_len=%ld \n", AVI->pos, AVI->n_idx*16); + ret = avi_add_chunk(AVI, "idx1", (void*)AVI->idx, AVI->n_idx*16); + hasIndex = (ret==0); + //fprintf(stderr, "pos=%lu, index_len=%d\n", AVI->pos, hasIndex); + + if(ret) { + idxerror = 1; + AVI_errno = AVI_ERR_WRITE_INDEX; + } + + /* Calculate Microseconds per frame */ + + if(AVI->fps < 0.001) { + frate=0; + ms_per_frame=0; + } else { + frate = (int) (FRAME_RATE_SCALE*AVI->fps + 0.5); + ms_per_frame=(int) (1000000/AVI->fps + 0.5); + } + + /* Prepare the file header */ + + nhb = 0; + + /* The RIFF header */ + + OUT4CC ("RIFF"); + OUTLONG(AVI->pos - 8); /* # of bytes to follow */ + OUT4CC ("AVI "); + + /* Start the header list */ + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + hdrl_start = nhb; /* Store start position */ + OUT4CC ("hdrl"); + + /* The main AVI header */ + + /* The Flags in AVI File header */ + +#define AVIF_HASINDEX 0x00000010 /* Index at end of file */ +#define AVIF_MUSTUSEINDEX 0x00000020 +#define AVIF_ISINTERLEAVED 0x00000100 +#define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames */ +#define AVIF_WASCAPTUREFILE 0x00010000 +#define AVIF_COPYRIGHTED 0x00020000 + + OUT4CC ("avih"); + OUTLONG(56); /* # of bytes to follow */ + OUTLONG(ms_per_frame); /* Microseconds per frame */ + //ThOe ->0 + // OUTLONG(10000000); /* MaxBytesPerSec, I hope this will never be used */ + OUTLONG(0); + OUTLONG(0); /* PaddingGranularity (whatever that might be) */ + /* Other sources call it 'reserved' */ + flag = AVIF_ISINTERLEAVED; + if(hasIndex) flag |= AVIF_HASINDEX; + if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX; + OUTLONG(flag); /* Flags */ + OUTLONG(AVI->video_frames); /* TotalFrames */ + OUTLONG(0); /* InitialFrames */ + + OUTLONG(AVI->anum+1); +// if (AVI->track[0].audio_bytes) +// { OUTLONG(2); } /* Streams */ +// else +// { OUTLONG(1); } /* Streams */ + + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(AVI->width); /* Width */ + OUTLONG(AVI->height); /* Height */ + /* MS calls the following 'reserved': */ + OUTLONG(0); /* TimeScale: Unit used to measure time */ + OUTLONG(0); /* DataRate: Data rate of playback */ + OUTLONG(0); /* StartTime: Starting time of AVI data */ + OUTLONG(0); /* DataLength: Size of AVI data chunk */ + + + /* Start the video stream list ---------------------------------- */ + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + strl_start = nhb; /* Store start position */ + OUT4CC ("strl"); + + /* The video stream header */ + + OUT4CC ("strh"); + OUTLONG(56); /* # of bytes to follow */ + OUT4CC ("vids"); /* Type */ + OUT4CC (AVI->compressor); /* Handler */ + OUTLONG(0); /* Flags */ + OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ + OUTLONG(0); /* InitialFrames */ + OUTLONG(FRAME_RATE_SCALE); /* Scale */ + OUTLONG(frate); /* Rate: Rate/Scale == samples/second */ + OUTLONG(0); /* Start */ + OUTLONG(AVI->video_frames); /* Length */ + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(-1); /* Quality */ + OUTLONG(0); /* SampleSize */ + OUTLONG(0); /* Frame */ + OUTLONG(0); /* Frame */ + // OUTLONG(0); /* Frame */ + //OUTLONG(0); /* Frame */ + + /* The video stream format */ + + OUT4CC ("strf"); + OUTLONG(40); /* # of bytes to follow */ + OUTLONG(40); /* Size */ + OUTLONG(AVI->width); /* Width */ + OUTLONG(AVI->height); /* Height */ + OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ + OUT4CC (AVI->compressor); /* Compression */ + // ThOe (*3) + OUTLONG(AVI->width*AVI->height*3); /* SizeImage (in bytes?) */ + OUTLONG(0); /* XPelsPerMeter */ + OUTLONG(0); /* YPelsPerMeter */ + OUTLONG(0); /* ClrUsed: Number of colors used */ + OUTLONG(0); /* ClrImportant: Number of colors important */ + + /* Finish stream list, i.e. put number of bytes in the list to proper pos */ + + long2str(AVI_header+strl_start-4,nhb-strl_start); + + /* Start the audio stream list ---------------------------------- */ + + for(j=0; janum; ++j) { + + //if (AVI->track[j].a_chans && AVI->track[j].audio_bytes) + { + + sampsize = avi_sampsize(AVI, j); + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + strl_start = nhb; /* Store start position */ + OUT4CC ("strl"); + + /* The audio stream header */ + + OUT4CC ("strh"); + OUTLONG(56); /* # of bytes to follow */ + OUT4CC ("auds"); + + // ----------- + // ThOe + OUTLONG(0); /* Format (Optionally) */ + // ----------- + + OUTLONG(0); /* Flags */ + OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ + OUTLONG(0); /* InitialFrames */ + + // ThOe /4 + OUTLONG(sampsize/4); /* Scale */ + OUTLONG(1000*AVI->track[j].mp3rate/8); + OUTLONG(0); /* Start */ + OUTLONG(4*AVI->track[j].audio_bytes/sampsize); /* Length */ + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(-1); /* Quality */ + + // ThOe /4 + OUTLONG(sampsize/4); /* SampleSize */ + + OUTLONG(0); /* Frame */ + OUTLONG(0); /* Frame */ + // OUTLONG(0); /* Frame */ + //OUTLONG(0); /* Frame */ + + /* The audio stream format */ + + OUT4CC ("strf"); + OUTLONG(16); /* # of bytes to follow */ + OUTSHRT(AVI->track[j].a_fmt); /* Format */ + OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ + OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ + // ThOe + OUTLONG(1000*AVI->track[j].mp3rate/8); + //ThOe (/4) + + OUTSHRT(sampsize/4); /* BlockAlign */ + + + OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ + + /* Finish stream list, i.e. put number of bytes in the list to proper pos */ + } + long2str(AVI_header+strl_start-4,nhb-strl_start); + } + + /* Finish header list */ + + long2str(AVI_header+hdrl_start-4,nhb-hdrl_start); + + + // add INFO list --- (0.6.0pre4) + +#ifdef INFO_LIST + OUT4CC ("LIST"); + + //FIXME + info_len = MAX_INFO_STRLEN + 12; + OUTLONG(info_len); + OUT4CC ("INFO"); + +// OUT4CC ("INAM"); +// OUTLONG(MAX_INFO_STRLEN); + +// sprintf(id_str, "\t"); +// memset(AVI_header+nhb, 0, MAX_INFO_STRLEN); +// memcpy(AVI_header+nhb, id_str, strlen(id_str)); +// nhb += MAX_INFO_STRLEN; + + OUT4CC ("ISFT"); + OUTLONG(MAX_INFO_STRLEN); + + sprintf(id_str, "%s-%s", PACKAGE, VERSION); + memset(AVI_header+nhb, 0, MAX_INFO_STRLEN); + memcpy(AVI_header+nhb, id_str, strlen(id_str)); + nhb += MAX_INFO_STRLEN; + +// OUT4CC ("ICMT"); +// OUTLONG(MAX_INFO_STRLEN); + +// calptr=time(NULL); +// sprintf(id_str, "\t%s %s", ctime(&calptr), ""); +// memset(AVI_header+nhb, 0, MAX_INFO_STRLEN); +// memcpy(AVI_header+nhb, id_str, 25); +// nhb += MAX_INFO_STRLEN; +#endif + + // ---------------------------- + + /* Calculate the needed amount of junk bytes, output junk */ + + njunk = HEADERBYTES - nhb - 8 - 12; + + /* Safety first: if njunk <= 0, somebody has played with + HEADERBYTES without knowing what (s)he did. + This is a fatal error */ + + if(njunk<=0) + { + fprintf(stderr,"AVI_close_output_file: # of header bytes too small\n"); + exit(1); + } + + OUT4CC ("JUNK"); + OUTLONG(njunk); + memset(AVI_header+nhb,0,njunk); + + nhb += njunk; + + /* Start the movi list */ + + OUT4CC ("LIST"); + OUTLONG(movi_len); /* Length of list in bytes */ + OUT4CC ("movi"); + + /* Output the header, truncate the file to the number of bytes + actually written, report an error if someting goes wrong */ + + if ( lseek(AVI->fdes,0,SEEK_SET)<0 || + avi_write(AVI->fdes,AVI_header,HEADERBYTES)!=HEADERBYTES || + ftruncate(AVI->fdes,AVI->pos)<0 ) + { + AVI_errno = AVI_ERR_CLOSE; + return -1; + } + + if(idxerror) return -1; + + return 0; +} + +/* + AVI_write_data: + Add video or audio data to the file; + + Return values: + 0 No error; + -1 Error, AVI_errno is set appropriatly; + +*/ + +static int avi_write_data(avi_t *AVI, char *data, unsigned long length, int audio, int keyframe) +{ + int n; + + unsigned char astr[5]; + + /* Check for maximum file length */ + + if ( (AVI->pos + 8 + length + 8 + (AVI->n_idx+1)*16) > AVI_MAX_LEN ) { + AVI_errno = AVI_ERR_SIZELIM; + return -1; + } + + /* Add index entry */ + + //set tag for current audio track + sprintf(astr, "0%1dwb", AVI->aptr+1); + + if(audio) + n = avi_add_index_entry(AVI,astr,0x00,AVI->pos,length); + else + n = avi_add_index_entry(AVI,"00db",((keyframe)?0x10:0x0),AVI->pos,length); + + if(n) return -1; + + /* Output tag and data */ + + if(audio) + n = avi_add_chunk(AVI,astr,data,length); + else + n = avi_add_chunk(AVI,"00db",data,length); + + if (n) return -1; + + return 0; +} + +int AVI_write_frame(avi_t *AVI, char *data, long bytes, int keyframe) +{ + unsigned long pos; + + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + pos = AVI->pos; + + if(avi_write_data(AVI,data,bytes,0,keyframe)) return -1; + + AVI->last_pos = pos; + AVI->last_len = bytes; + AVI->video_frames++; + return 0; +} + +int AVI_dup_frame(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + if(AVI->last_pos==0) return 0; /* No previous real frame */ + if(avi_add_index_entry(AVI,"00db",0x10,AVI->last_pos,AVI->last_len)) return -1; + AVI->video_frames++; + AVI->must_use_index = 1; + return 0; +} + +int AVI_write_audio(avi_t *AVI, char *data, long bytes) +{ + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + if( avi_write_data(AVI,data,bytes,1,0) ) return -1; + AVI->track[AVI->aptr].audio_bytes += bytes; + return 0; +} + + +int AVI_append_audio(avi_t *AVI, char *data, long bytes) +{ + + long i, length, pos; + unsigned char c[4]; + + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + // update last index entry: + + --AVI->n_idx; + length = str2ulong(AVI->idx[AVI->n_idx]+12); + pos = str2ulong(AVI->idx[AVI->n_idx]+8); + + //update; + long2str(AVI->idx[AVI->n_idx]+12,length+bytes); + + ++AVI->n_idx; + + AVI->track[AVI->aptr].audio_bytes += bytes; + + //update chunk header + lseek(AVI->fdes, pos+4, SEEK_SET); + long2str(c, length+bytes); + avi_write(AVI->fdes, c, 4); + + lseek(AVI->fdes, pos+8+length, SEEK_SET); + + i=PAD_EVEN(length + bytes); + + bytes = i - length; + avi_write(AVI->fdes, data, bytes); + AVI->pos = pos + 8 + i; + + return 0; +} + + +long AVI_bytes_remain(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_READ) return 0; + + return ( AVI_MAX_LEN - (AVI->pos + 8 + 16*AVI->n_idx)); +} + +long AVI_bytes_written(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_READ) return 0; + + return (AVI->pos + 8 + 16*AVI->n_idx); +} + +int AVI_set_audio_track(avi_t *AVI, int track) +{ + + if(track < 0 || track + 1 > AVI->anum) return(-1); + + //this info is not written to file anyway + AVI->aptr=track; + return 0; +} + +int AVI_get_audio_track(avi_t *AVI) +{ + return(AVI->aptr); +} + + +/******************************************************************* + * * + * Utilities for reading video and audio from an AVI File * + * * + *******************************************************************/ + +int AVI_close(avi_t *AVI) +{ + int ret; + + /* If the file was open for writing, the header and index still have + to be written */ + + if(AVI->mode == AVI_MODE_WRITE) + ret = avi_close_output_file(AVI); + else + ret = 0; + + /* Even if there happened an error, we first clean up */ + + close(AVI->fdes); + if(AVI->idx) free(AVI->idx); + if(AVI->video_index) free(AVI->video_index); + //FIXME + //if(AVI->audio_index) free(AVI->audio_index); + free(AVI); + + return ret; +} + + +#define ERR_EXIT(x) \ +{ \ + AVI_close(AVI); \ + AVI_errno = x; \ + return 0; \ +} + +avi_t *AVI_open_input_file(char *filename, int getIndex) +{ + avi_t *AVI=NULL; + + /* Create avi_t structure */ + + AVI = (avi_t *) malloc(sizeof(avi_t)); + if(AVI==NULL) + { + AVI_errno = AVI_ERR_NO_MEM; + return 0; + } + memset((void *)AVI,0,sizeof(avi_t)); + + AVI->mode = AVI_MODE_READ; /* open for reading */ + + /* Open the file */ + + AVI->fdes = open(filename,O_RDONLY); + if(AVI->fdes < 0) + { + AVI_errno = AVI_ERR_OPEN; + free(AVI); + return 0; + } + + avi_parse_input_file(AVI, getIndex); + + AVI->aptr=0; //reset + + return AVI; +} + +avi_t *AVI_open_fd(int fd, int getIndex) +{ + avi_t *AVI=NULL; + + /* Create avi_t structure */ + + AVI = (avi_t *) malloc(sizeof(avi_t)); + if(AVI==NULL) + { + AVI_errno = AVI_ERR_NO_MEM; + return 0; + } + memset((void *)AVI,0,sizeof(avi_t)); + + AVI->mode = AVI_MODE_READ; /* open for reading */ + + // file alread open + AVI->fdes = fd; + + avi_parse_input_file(AVI, getIndex); + + AVI->aptr=0; //reset + + return AVI; +} + +int avi_parse_input_file(avi_t *AVI, int getIndex) +{ + long i, n, rate, scale, idx_type; + unsigned char *hdrl_data; + long header_offset=0, hdrl_len=0; + long nvi, nai[AVI_MAX_TRACKS], ioff; + long tot[AVI_MAX_TRACKS]; + int j; + int lasttag = 0; + int vids_strh_seen = 0; + int vids_strf_seen = 0; + int auds_strh_seen = 0; + // int auds_strf_seen = 0; + int num_stream = 0; + char data[256]; + + /* Read first 12 bytes and check that this is an AVI file */ + + if( avi_read(AVI->fdes,data,12) != 12 ) ERR_EXIT(AVI_ERR_READ) + + if( strncasecmp(data ,"RIFF",4) !=0 || + strncasecmp(data+8,"AVI ",4) !=0 ) ERR_EXIT(AVI_ERR_NO_AVI) + + /* Go through the AVI file and extract the header list, + the start position of the 'movi' list and an optionally + present idx1 tag */ + + hdrl_data = 0; + + while(1) + { + if( avi_read(AVI->fdes,data,8) != 8 ) break; /* We assume it's EOF */ + + n = str2ulong(data+4); + n = PAD_EVEN(n); + + if(strncasecmp(data,"LIST",4) == 0) + { + if( avi_read(AVI->fdes,data,4) != 4 ) ERR_EXIT(AVI_ERR_READ) + n -= 4; + if(strncasecmp(data,"hdrl",4) == 0) + { + hdrl_len = n; + hdrl_data = (unsigned char *) malloc(n); + if(hdrl_data==0) ERR_EXIT(AVI_ERR_NO_MEM); + + // offset of header + + header_offset = lseek(AVI->fdes,0,SEEK_CUR); + + if( avi_read(AVI->fdes,hdrl_data,n) != n ) ERR_EXIT(AVI_ERR_READ) + } + else if(strncasecmp(data,"movi",4) == 0) + { + AVI->movi_start = lseek(AVI->fdes,0,SEEK_CUR); + lseek(AVI->fdes,n,SEEK_CUR); + } + else + lseek(AVI->fdes,n,SEEK_CUR); + } + else if(strncasecmp(data,"idx1",4) == 0) + { + /* n must be a multiple of 16, but the reading does not + break if this is not the case */ + + AVI->n_idx = AVI->max_idx = n/16; + AVI->idx = (unsigned char((*)[16]) ) malloc(n); + if(AVI->idx==0) ERR_EXIT(AVI_ERR_NO_MEM) + if(avi_read(AVI->fdes, (char *) AVI->idx, n) != n ) ERR_EXIT(AVI_ERR_READ) + } + else + lseek(AVI->fdes,n,SEEK_CUR); + } + + if(!hdrl_data ) ERR_EXIT(AVI_ERR_NO_HDRL) + if(!AVI->movi_start) ERR_EXIT(AVI_ERR_NO_MOVI) + + /* Interpret the header list */ + + for(i=0;icompressor,hdrl_data+i+4,4); + AVI->compressor[4] = 0; + + // ThOe + AVI->v_codech_off = header_offset + i+4; + + scale = str2ulong(hdrl_data+i+20); + rate = str2ulong(hdrl_data+i+24); + if(scale!=0) AVI->fps = (double)rate/(double)scale; + AVI->video_frames = str2ulong(hdrl_data+i+32); + AVI->video_strn = num_stream; + AVI->max_len = 0; + vids_strh_seen = 1; + lasttag = 1; /* vids */ + } + else if (strncasecmp (hdrl_data+i,"auds",4) ==0 && ! auds_strh_seen) + { + + //inc audio tracks + AVI->aptr=AVI->anum; + ++AVI->anum; + + if(AVI->anum > AVI_MAX_TRACKS) { + fprintf(stderr, "error - only %d audio tracks supported\n", AVI_MAX_TRACKS); + return(-1); + } + + AVI->track[AVI->aptr].audio_bytes = str2ulong(hdrl_data+i+32)*avi_sampsize(AVI, 0); + AVI->track[AVI->aptr].audio_strn = num_stream; + // auds_strh_seen = 1; + lasttag = 2; /* auds */ + + // ThOe + AVI->track[AVI->aptr].a_codech_off = header_offset + i; + + } + else + lasttag = 0; + num_stream++; + } + else if(strncasecmp(hdrl_data+i,"strf",4)==0) + { + i += 8; + if(lasttag == 1) + { + AVI->width = str2ulong(hdrl_data+i+4); + AVI->height = str2ulong(hdrl_data+i+8); + vids_strf_seen = 1; + //ThOe + AVI->v_codecf_off = header_offset + i+16; + + memcpy(AVI->compressor2, hdrl_data+i+16, 4); + AVI->compressor2[4] = 0; + + } + else if(lasttag == 2) + { + AVI->track[AVI->aptr].a_fmt = str2ushort(hdrl_data+i ); + + //ThOe + AVI->track[AVI->aptr].a_codecf_off = header_offset + i; + + AVI->track[AVI->aptr].a_chans = str2ushort(hdrl_data+i+2); + AVI->track[AVI->aptr].a_rate = str2ulong (hdrl_data+i+4); + //ThOe: read mp3bitrate + AVI->track[AVI->aptr].mp3rate = 8*str2ulong(hdrl_data+i+8)/1000; + //:ThOe + AVI->track[AVI->aptr].a_bits = str2ushort(hdrl_data+i+14); + // auds_strf_seen = 1; + } + lasttag = 0; + } + else + { + i += 8; + lasttag = 0; + } + + i += n; + } + + free(hdrl_data); + + if(!vids_strh_seen || !vids_strf_seen) ERR_EXIT(AVI_ERR_NO_VIDS) + + AVI->video_tag[0] = AVI->video_strn/10 + '0'; + AVI->video_tag[1] = AVI->video_strn%10 + '0'; + AVI->video_tag[2] = 'd'; + AVI->video_tag[3] = 'b'; + + /* Audio tag is set to "99wb" if no audio present */ + if(!AVI->track[0].a_chans) AVI->track[0].audio_strn = 99; + + for(j=0; janum; ++j) { + AVI->track[j].audio_tag[0] = (j+1)/10 + '0'; + AVI->track[j].audio_tag[1] = (j+1)%10 + '0'; + AVI->track[j].audio_tag[2] = 'w'; + AVI->track[j].audio_tag[3] = 'b'; + } + + lseek(AVI->fdes,AVI->movi_start,SEEK_SET); + + /* get index if wanted */ + + if(!getIndex) return(0); + + /* if the file has an idx1, check if this is relative + to the start of the file or to the start of the movi list */ + + idx_type = 0; + + if(AVI->idx) + { + long pos, len; + + /* Search the first videoframe in the idx1 and look where + it is in the file */ + + for(i=0;in_idx;i++) + if( strncasecmp(AVI->idx[i],AVI->video_tag,3)==0 ) break; + if(i>=AVI->n_idx) ERR_EXIT(AVI_ERR_NO_VIDS) + + pos = str2ulong(AVI->idx[i]+ 8); + len = str2ulong(AVI->idx[i]+12); + + lseek(AVI->fdes,pos,SEEK_SET); + if(avi_read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ) + if( strncasecmp(data,AVI->idx[i],4)==0 && str2ulong(data+4)==len ) + { + idx_type = 1; /* Index from start of file */ + } + else + { + lseek(AVI->fdes,pos+AVI->movi_start-4,SEEK_SET); + if(avi_read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ) + if( strncasecmp(data,AVI->idx[i],4)==0 && str2ulong(data+4)==len ) + { + idx_type = 2; /* Index from start of movi list */ + } + } + /* idx_type remains 0 if neither of the two tests above succeeds */ + } + + if(idx_type == 0) + { + /* we must search through the file to get the index */ + + lseek(AVI->fdes, AVI->movi_start, SEEK_SET); + + AVI->n_idx = 0; + + while(1) + { + if( avi_read(AVI->fdes,data,8) != 8 ) break; + n = str2ulong(data+4); + + /* The movi list may contain sub-lists, ignore them */ + + if(strncasecmp(data,"LIST",4)==0) + { + lseek(AVI->fdes,4,SEEK_CUR); + continue; + } + + /* Check if we got a tag ##db, ##dc or ##wb */ + + if( ( (data[2]=='d' || data[2]=='D') && + (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) + || ( (data[2]=='w' || data[2]=='W') && + (data[3]=='b' || data[3]=='B') ) ) + { + avi_add_index_entry(AVI,data,0,lseek(AVI->fdes,0,SEEK_CUR)-8,n); + } + + lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR); + } + idx_type = 1; + } + + /* Now generate the video index and audio index arrays */ + + nvi = 0; + for(j=0; janum; ++j) nai[j] = 0; + + for(i=0;in_idx;i++) { + + if(strncasecmp(AVI->idx[i],AVI->video_tag,3) == 0) nvi++; + + for(j=0; janum; ++j) if(strncasecmp(AVI->idx[i], AVI->track[j].audio_tag,4) == 0) nai[j]++; + } + + AVI->video_frames = nvi; + for(j=0; janum; ++j) AVI->track[j].audio_chunks = nai[j]; + +// fprintf(stderr, "chunks = %ld %d %s\n", AVI->track[0].audio_chunks, AVI->anum, AVI->track[0].audio_tag); + + if(AVI->video_frames==0) ERR_EXIT(AVI_ERR_NO_VIDS); + AVI->video_index = (video_index_entry *) malloc(nvi*sizeof(video_index_entry)); + if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM); + + for(j=0; janum; ++j) { + if(AVI->track[j].audio_chunks) { + AVI->track[j].audio_index = (audio_index_entry *) malloc(nai[j]*sizeof(audio_index_entry)); + if(AVI->track[j].audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM); + } + } + + nvi = 0; + for(j=0; janum; ++j) nai[j] = tot[j] = 0; + + ioff = idx_type == 1 ? 8 : AVI->movi_start+4; + + for(i=0;in_idx;i++) { + + //video + if(strncasecmp(AVI->idx[i],AVI->video_tag,3) == 0) { + AVI->video_index[nvi].key = str2ulong(AVI->idx[i]+ 4); + AVI->video_index[nvi].pos = str2ulong(AVI->idx[i]+ 8)+ioff; + AVI->video_index[nvi].len = str2ulong(AVI->idx[i]+12); + nvi++; + } + + //audio + for(j=0; janum; ++j) { + + if(strncasecmp(AVI->idx[i],AVI->track[j].audio_tag,4) == 0) { + AVI->track[j].audio_index[nai[j]].pos = str2ulong(AVI->idx[i]+ 8)+ioff; + AVI->track[j].audio_index[nai[j]].len = str2ulong(AVI->idx[i]+12); + AVI->track[j].audio_index[nai[j]].tot = tot[j]; + tot[j] += AVI->track[j].audio_index[nai[j]].len; + nai[j]++; + } + } + } + + + for(j=0; janum; ++j) AVI->track[j].audio_bytes = tot[j]; + + /* Reposition the file */ + + lseek(AVI->fdes,AVI->movi_start,SEEK_SET); + AVI->video_pos = 0; + + return(0); +} + +long AVI_video_frames(avi_t *AVI) +{ + return AVI->video_frames; +} +int AVI_video_width(avi_t *AVI) +{ + return AVI->width; +} +int AVI_video_height(avi_t *AVI) +{ + return AVI->height; +} +double AVI_frame_rate(avi_t *AVI) +{ + return AVI->fps; +} +char* AVI_video_compressor(avi_t *AVI) +{ + return AVI->compressor2; +} + +long AVI_max_video_chunk(avi_t *AVI) +{ + return AVI->max_len; +} + +int AVI_audio_tracks(avi_t *AVI) +{ + return(AVI->anum); +} + +int AVI_audio_channels(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_chans; +} + +long AVI_audio_mp3rate(avi_t *AVI) +{ + return AVI->track[AVI->aptr].mp3rate; +} + +int AVI_audio_bits(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_bits; +} + +int AVI_audio_format(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_fmt; +} + +long AVI_audio_rate(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_rate; +} + +long AVI_audio_bytes(avi_t *AVI) +{ + return AVI->track[AVI->aptr].audio_bytes; +} + +long AVI_audio_chunks(avi_t *AVI) +{ + return AVI->track[AVI->aptr].audio_chunks; +} + +long AVI_audio_codech_offset(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_codech_off; +} + +long AVI_audio_codecf_offset(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_codecf_off; +} + +long AVI_video_codech_offset(avi_t *AVI) +{ + return AVI->v_codech_off; +} + +long AVI_video_codecf_offset(avi_t *AVI) +{ + return AVI->v_codecf_off; +} + +long AVI_frame_size(avi_t *AVI, long frame) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if(frame < 0 || frame >= AVI->video_frames) return 0; + return(AVI->video_index[frame].len); +} + +long AVI_audio_size(avi_t *AVI, long frame) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if(frame < 0 || frame >= AVI->track[AVI->aptr].audio_chunks) return 0; + return(AVI->track[AVI->aptr].audio_index[frame].len); +} + +long AVI_get_video_position(avi_t *AVI, long frame) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if(frame < 0 || frame >= AVI->video_frames) return 0; + return(AVI->video_index[frame].pos); +} + + +int AVI_seek_start(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + lseek(AVI->fdes,AVI->movi_start,SEEK_SET); + AVI->video_pos = 0; + return 0; +} + +int AVI_set_video_position(avi_t *AVI, long frame) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if (frame < 0 ) frame = 0; + AVI->video_pos = frame; + return 0; +} + +int AVI_set_audio_bitrate(avi_t *AVI, long bitrate) +{ + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + AVI->track[AVI->aptr].mp3rate = bitrate; + return 0; +} + + +long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe) +{ + long n; + + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if(AVI->video_pos < 0 || AVI->video_pos >= AVI->video_frames) return -1; + n = AVI->video_index[AVI->video_pos].len; + + *keyframe = (AVI->video_index[AVI->video_pos].key==0x10) ? 1:0; + + lseek(AVI->fdes, AVI->video_index[AVI->video_pos].pos, SEEK_SET); + + if (avi_read(AVI->fdes,vidbuf,n) != n) + { + AVI_errno = AVI_ERR_READ; + return -1; + } + + AVI->video_pos++; + + return n; +} + +int AVI_set_audio_position(avi_t *AVI, long byte) +{ + long n0, n1, n; + + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if(byte < 0) byte = 0; + + /* Binary search in the audio chunks */ + + n0 = 0; + n1 = AVI->track[AVI->aptr].audio_chunks; + + while(n0track[AVI->aptr].audio_index[n].tot>byte) + n1 = n; + else + n0 = n; + } + + AVI->track[AVI->aptr].audio_posc = n0; + AVI->track[AVI->aptr].audio_posb = byte - AVI->track[AVI->aptr].audio_index[n0].tot; + + return 0; +} + +long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes) +{ + long nr, pos, left, todo; + + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + nr = 0; /* total number of bytes read */ + + while(bytes>0) + { + left = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].len - AVI->track[AVI->aptr].audio_posb; + if(left==0) + { + if(AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks-1) return nr; + AVI->track[AVI->aptr].audio_posc++; + AVI->track[AVI->aptr].audio_posb = 0; + continue; + } + if(bytestrack[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos + AVI->track[AVI->aptr].audio_posb; + lseek(AVI->fdes, pos, SEEK_SET); + if (avi_read(AVI->fdes,audbuf+nr,todo) != todo) + { + AVI_errno = AVI_ERR_READ; + return -1; + } + bytes -= todo; + nr += todo; + AVI->track[AVI->aptr].audio_posb += todo; + } + + return nr; +} + +long AVI_read_audio_chunk(avi_t *AVI, char *audbuf) +{ + long pos, left; + + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + left = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].len - AVI->track[AVI->aptr].audio_posb; + + if (audbuf == NULL) return left; + + if(left==0) return 0; + + pos = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos + AVI->track[AVI->aptr].audio_posb; + lseek(AVI->fdes, pos, SEEK_SET); + if (avi_read(AVI->fdes,audbuf,left) != left) + { + AVI_errno = AVI_ERR_READ; + return -1; + } + AVI->track[AVI->aptr].audio_posc++; + AVI->track[AVI->aptr].audio_posb = 0; + + return left; +} + +/* AVI_read_data: Special routine for reading the next audio or video chunk + without having an index of the file. */ + +int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf, + char *audbuf, long max_audbuf, + long *len) +{ + +/* + * Return codes: + * + * 1 = video data read + * 2 = audio data read + * 0 = reached EOF + * -1 = video buffer too small + * -2 = audio buffer too small + */ + + int n; + char data[8]; + + if(AVI->mode==AVI_MODE_WRITE) return 0; + + while(1) + { + /* Read tag and length */ + + if( avi_read(AVI->fdes,data,8) != 8 ) return 0; + + /* if we got a list tag, ignore it */ + + if(strncasecmp(data,"LIST",4) == 0) + { + lseek(AVI->fdes,4,SEEK_CUR); + continue; + } + + n = PAD_EVEN(str2ulong(data+4)); + + if(strncasecmp(data,AVI->video_tag,3) == 0) + { + *len = n; + AVI->video_pos++; + if(n>max_vidbuf) + { + lseek(AVI->fdes,n,SEEK_CUR); + return -1; + } + if(avi_read(AVI->fdes,vidbuf,n) != n ) return 0; + return 1; + } + else if(strncasecmp(data,AVI->track[AVI->aptr].audio_tag,4) == 0) + { + *len = n; + if(n>max_audbuf) + { + lseek(AVI->fdes,n,SEEK_CUR); + return -2; + } + if(avi_read(AVI->fdes,audbuf,n) != n ) return 0; + return 2; + break; + } + else + if(lseek(AVI->fdes,n,SEEK_CUR)<0) return 0; + } +} + +/* AVI_print_error: Print most recent error (similar to perror) */ + +char *(avi_errors[]) = +{ + /* 0 */ "avilib - No Error", + /* 1 */ "avilib - AVI file size limit reached", + /* 2 */ "avilib - Error opening AVI file", + /* 3 */ "avilib - Error reading from AVI file", + /* 4 */ "avilib - Error writing to AVI file", + /* 5 */ "avilib - Error writing index (file may still be useable)", + /* 6 */ "avilib - Error closing AVI file", + /* 7 */ "avilib - Operation (read/write) not permitted", + /* 8 */ "avilib - Out of memory (malloc failed)", + /* 9 */ "avilib - Not an AVI file", + /* 10 */ "avilib - AVI file has no header list (corrupted?)", + /* 11 */ "avilib - AVI file has no MOVI list (corrupted?)", + /* 12 */ "avilib - AVI file has no video data", + /* 13 */ "avilib - operation needs an index", + /* 14 */ "avilib - Unkown Error" +}; +static int num_avi_errors = sizeof(avi_errors)/sizeof(char*); + +static char error_string[4096]; + +void AVI_print_error(char *str) +{ + int aerrno; + + aerrno = (AVI_errno>=0 && AVI_errno=0 && AVI_errno + * + * This file is part of transcode, a linux video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef AVILIB_H +#define AVILIB_H + +#define AVI_MAX_TRACKS 8 + +typedef struct +{ + unsigned long key; + unsigned long pos; + unsigned long len; +} video_index_entry; + +typedef struct +{ + unsigned long pos; + unsigned long len; + unsigned long tot; +} audio_index_entry; + +typedef struct track_s +{ + + long a_fmt; /* Audio format, see #defines below */ + long a_chans; /* Audio channels, 0 for no audio */ + long a_rate; /* Rate in Hz */ + long a_bits; /* bits per audio sample */ + long mp3rate; /* mp3 bitrate kbs*/ + + long audio_strn; /* Audio stream number */ + long audio_bytes; /* Total number of bytes of audio data */ + long audio_chunks; /* Chunks of audio data in the file */ + + char audio_tag[4]; /* Tag of audio data */ + long audio_posc; /* Audio position: chunk */ + long audio_posb; /* Audio position: byte within chunk */ + + long a_codech_off; /* absolut offset of audio codec information */ + long a_codecf_off; /* absolut offset of audio codec information */ + + audio_index_entry *audio_index; + +} track_t; + +typedef struct +{ + + long fdes; /* File descriptor of AVI file */ + long mode; /* 0 for reading, 1 for writing */ + + long width; /* Width of a video frame */ + long height; /* Height of a video frame */ + double fps; /* Frames per second */ + char compressor[8]; /* Type of compressor, 4 bytes + padding for 0 byte */ + char compressor2[8]; /* Type of compressor, 4 bytes + padding for 0 byte */ + long video_strn; /* Video stream number */ + long video_frames; /* Number of video frames */ + char video_tag[4]; /* Tag of video data */ + long video_pos; /* Number of next frame to be read + (if index present) */ + + unsigned long max_len; /* maximum video chunk present */ + + track_t track[AVI_MAX_TRACKS]; // up to AVI_MAX_TRACKS audio tracks supported + + unsigned long pos; /* position in file */ + long n_idx; /* number of index entries actually filled */ + long max_idx; /* number of index entries actually allocated */ + + long v_codech_off; /* absolut offset of video codec (strh) info */ + long v_codecf_off; /* absolut offset of video codec (strf) info */ + + unsigned char (*idx)[16]; /* index entries (AVI idx1 tag) */ + video_index_entry *video_index; + + unsigned long last_pos; /* Position of last frame written */ + unsigned long last_len; /* Length of last frame written */ + int must_use_index; /* Flag if frames are duplicated */ + unsigned long movi_start; + + int anum; // total number of audio tracks + int aptr; // current audio working track + +} avi_t; + +#define AVI_MODE_WRITE 0 +#define AVI_MODE_READ 1 + +/* The error codes delivered by avi_open_input_file */ + +#define AVI_ERR_SIZELIM 1 /* The write of the data would exceed + the maximum size of the AVI file. + This is more a warning than an error + since the file may be closed safely */ + +#define AVI_ERR_OPEN 2 /* Error opening the AVI file - wrong path + name or file nor readable/writable */ + +#define AVI_ERR_READ 3 /* Error reading from AVI File */ + +#define AVI_ERR_WRITE 4 /* Error writing to AVI File, + disk full ??? */ + +#define AVI_ERR_WRITE_INDEX 5 /* Could not write index to AVI file + during close, file may still be + usable */ + +#define AVI_ERR_CLOSE 6 /* Could not write header to AVI file + or not truncate the file during close, + file is most probably corrupted */ + +#define AVI_ERR_NOT_PERM 7 /* Operation not permitted: + trying to read from a file open + for writing or vice versa */ + +#define AVI_ERR_NO_MEM 8 /* malloc failed */ + +#define AVI_ERR_NO_AVI 9 /* Not an AVI file */ + +#define AVI_ERR_NO_HDRL 10 /* AVI file has no has no header list, + corrupted ??? */ + +#define AVI_ERR_NO_MOVI 11 /* AVI file has no has no MOVI list, + corrupted ??? */ + +#define AVI_ERR_NO_VIDS 12 /* AVI file contains no video data */ + +#define AVI_ERR_NO_IDX 13 /* The file has been opened with + getIndex==0, but an operation has been + performed that needs an index */ + +/* Possible Audio formats */ + +#ifndef WAVE_FORMAT_PCM +#define WAVE_FORMAT_UNKNOWN (0x0000) +#define WAVE_FORMAT_PCM (0x0001) +#define WAVE_FORMAT_ADPCM (0x0002) +#define WAVE_FORMAT_IBM_CVSD (0x0005) +#define WAVE_FORMAT_ALAW (0x0006) +#define WAVE_FORMAT_MULAW (0x0007) +#define WAVE_FORMAT_OKI_ADPCM (0x0010) +#define WAVE_FORMAT_DVI_ADPCM (0x0011) +#define WAVE_FORMAT_DIGISTD (0x0015) +#define WAVE_FORMAT_DIGIFIX (0x0016) +#define WAVE_FORMAT_YAMAHA_ADPCM (0x0020) +#define WAVE_FORMAT_DSP_TRUESPEECH (0x0022) +#define WAVE_FORMAT_GSM610 (0x0031) +#define IBM_FORMAT_MULAW (0x0101) +#define IBM_FORMAT_ALAW (0x0102) +#define IBM_FORMAT_ADPCM (0x0103) +#endif + +avi_t* AVI_open_output_file(char * filename); +void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor); +void AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format, long mp3rate); +int AVI_write_frame(avi_t *AVI, char *data, long bytes, int keyframe); +int AVI_dup_frame(avi_t *AVI); +int AVI_write_audio(avi_t *AVI, char *data, long bytes); +int AVI_append_audio(avi_t *AVI, char *data, long bytes); +long AVI_bytes_remain(avi_t *AVI); +int AVI_close(avi_t *AVI); +long AVI_bytes_written(avi_t *AVI); + +avi_t *AVI_open_input_file(char *filename, int getIndex); +avi_t *AVI_open_fd(int fd, int getIndex); +int avi_parse_input_file(avi_t *AVI, int getIndex); +long AVI_audio_mp3rate(avi_t *AVI); +long AVI_video_frames(avi_t *AVI); +int AVI_video_width(avi_t *AVI); +int AVI_video_height(avi_t *AVI); +double AVI_frame_rate(avi_t *AVI); +char* AVI_video_compressor(avi_t *AVI); + +int AVI_audio_channels(avi_t *AVI); +int AVI_audio_bits(avi_t *AVI); +int AVI_audio_format(avi_t *AVI); +long AVI_audio_rate(avi_t *AVI); +long AVI_audio_bytes(avi_t *AVI); +long AVI_audio_chunks(avi_t *AVI); + +long AVI_max_video_chunk(avi_t *AVI); + +long AVI_frame_size(avi_t *AVI, long frame); +long AVI_audio_size(avi_t *AVI, long frame); +int AVI_seek_start(avi_t *AVI); +int AVI_set_video_position(avi_t *AVI, long frame); +long AVI_get_video_position(avi_t *AVI, long frame); +long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe); + +int AVI_set_audio_position(avi_t *AVI, long byte); +int AVI_set_audio_bitrate(avi_t *AVI, long bitrate); + +long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes); +long AVI_read_audio_chunk(avi_t *AVI, char *audbuf); + +long AVI_audio_codech_offset(avi_t *AVI); +long AVI_audio_codecf_offset(avi_t *AVI); +long AVI_video_codech_offset(avi_t *AVI); +long AVI_video_codecf_offset(avi_t *AVI); + +int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf, + char *audbuf, long max_audbuf, + long *len); + +void AVI_print_error(char *str); +char *AVI_strerror(); +char *AVI_syserror(); + +int AVI_scan(char *name); +int AVI_dump(char *name, int mode); + +char *AVI_codec2str(short cc); +int AVI_file_check(char *import_file); + +void AVI_info(avi_t *avifile); +uint64_t AVI_max_size(); +int avi_update_header(avi_t *AVI); + +int AVI_set_audio_track(avi_t *AVI, int track); +int AVI_get_audio_track(avi_t *AVI); +int AVI_audio_tracks(avi_t *AVI); + + +struct riff_struct +{ + unsigned char id[4]; /* RIFF */ + unsigned long len; + unsigned char wave_id[4]; /* WAVE */ +}; + + +struct chunk_struct +{ + unsigned char id[4]; + unsigned long len; +}; + +struct common_struct +{ + unsigned short wFormatTag; + unsigned short wChannels; + unsigned long dwSamplesPerSec; + unsigned long dwAvgBytesPerSec; + unsigned short wBlockAlign; + unsigned short wBitsPerSample; /* Only for PCM */ +}; + +struct wave_header +{ + struct riff_struct riff; + struct chunk_struct format; + struct common_struct common; + struct chunk_struct data; +}; + + + +struct AVIStreamHeader { + long fccType; + long fccHandler; + long dwFlags; + long dwPriority; + long dwInitialFrames; + long dwScale; + long dwRate; + long dwStart; + long dwLength; + long dwSuggestedBufferSize; + long dwQuality; + long dwSampleSize; +}; + +#endif diff --git a/avilib/avilib.o b/avilib/avilib.o new file mode 100644 index 000000000..c216ba577 Binary files /dev/null and b/avilib/avilib.o differ diff --git a/avilib/avimisc.c b/avilib/avimisc.c new file mode 100644 index 000000000..2dfeb4bfd --- /dev/null +++ b/avilib/avimisc.c @@ -0,0 +1,137 @@ +/* + * avimisc.c + * + * Copyright (C) Thomas Östreich - June 2001 + * + * This file is part of transcode, a linux video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include + +#include "avilib.h" + +void AVI_info(avi_t *avifile) +{ + + long frames, rate, mp3rate, chunks, tot_bytes; + + int width, height, format, chan, bits; + + int j, tracks, tmp; + + double fps; + + char *codec; + + frames = AVI_video_frames(avifile); + width = AVI_video_width(avifile); + height = AVI_video_height(avifile); + + fps = AVI_frame_rate(avifile); + codec = AVI_video_compressor(avifile); + + printf("[avilib] V: %6.3f fps, codec=%s, frames=%ld, width=%d, height=%d\n", fps, ((strlen(codec)==0)? "RGB": codec), frames, width, height); + + tracks=AVI_audio_tracks(avifile); + + tmp=AVI_get_audio_track(avifile); + + for(j=0; j0) { + printf("[avilib] A: %ld Hz, format=0x%02x, bits=%d, channels=%d, bitrate=%ld kbps,\n", rate, format, bits, chan, mp3rate); + printf("[avilib] %ld chunks, %ld bytes\n", chunks, tot_bytes); + } else + printf("[avilib] A: no audio track found\n"); + } + + AVI_set_audio_track(avifile, tmp); //reset + +} + + +int AVI_file_check(char *import_file) +{ + // check for sane video file + struct stat fbuf; + + if(stat(import_file, &fbuf) || import_file==NULL){ + fprintf(stderr, "(%s) invalid input file \"%s\"\n", __FILE__, + import_file); + return(1); + } + + return(0); +} + + +char *AVI_codec2str(short cc) +{ + + switch (cc) { + + case 0x1://PCM + return("PCM"); + break; + case 0x2://MS ADPCM + return("MS ADPCM"); + break; + case 0x11://IMA ADPCM + printf("Audio in ADPCM format\n"); + break; + case 0x31://MS GSM 6.10 + case 0x32://MSN Audio + printf("Audio in MS GSM 6.10 format\n"); + break; + case 0x50://MPEG Layer-1,2 + return("MPEG Layer-1/2"); + break; + case 0x55://MPEG Layer-3 + return("MPEG Layer-3"); + break; + case 0x160: + case 0x161://DivX audio + return("DivX WMA"); + break; + case 0x401://Intel Music Coder + printf("Audio in IMC format\n"); + break; + case 0x2000://AC3 + return("AC3"); + break; + default: + return("unknown"); + } + return("unknown"); +} diff --git a/avilib/avimisc.o b/avilib/avimisc.o new file mode 100644 index 000000000..b13970371 Binary files /dev/null and b/avilib/avimisc.o differ diff --git a/avilib/libavi.a b/avilib/libavi.a new file mode 100644 index 000000000..02406592b Binary files /dev/null and b/avilib/libavi.a differ