summaryrefslogtreecommitdiffstats
path: root/debian/transcode/transcode-1.1.7/src
diff options
context:
space:
mode:
Diffstat (limited to 'debian/transcode/transcode-1.1.7/src')
-rw-r--r--debian/transcode/transcode-1.1.7/src/Makefile.am71
-rw-r--r--debian/transcode/transcode-1.1.7/src/Makefile.in706
-rw-r--r--debian/transcode/transcode-1.1.7/src/audio_trans.c176
-rw-r--r--debian/transcode/transcode-1.1.7/src/audio_trans.h18
-rw-r--r--debian/transcode/transcode-1.1.7/src/cmdline.c241
-rw-r--r--debian/transcode/transcode-1.1.7/src/cmdline.h47
-rw-r--r--debian/transcode/transcode-1.1.7/src/cmdline_def.h1602
-rw-r--r--debian/transcode/transcode-1.1.7/src/counter.c365
-rw-r--r--debian/transcode/transcode-1.1.7/src/counter.h33
-rw-r--r--debian/transcode/transcode-1.1.7/src/decoder.c1113
-rw-r--r--debian/transcode/transcode-1.1.7/src/decoder.h207
-rw-r--r--debian/transcode/transcode-1.1.7/src/dl_loader.c223
-rw-r--r--debian/transcode/transcode-1.1.7/src/dl_loader.h40
-rw-r--r--debian/transcode/transcode-1.1.7/src/encoder-buffer.c408
-rw-r--r--debian/transcode/transcode-1.1.7/src/encoder-common.c215
-rw-r--r--debian/transcode/transcode-1.1.7/src/encoder-common.h188
-rw-r--r--debian/transcode/transcode-1.1.7/src/encoder.c1422
-rw-r--r--debian/transcode/transcode-1.1.7/src/encoder.h324
-rw-r--r--debian/transcode/transcode-1.1.7/src/export_profile.c511
-rw-r--r--debian/transcode/transcode-1.1.7/src/export_profile.h116
-rw-r--r--debian/transcode/transcode-1.1.7/src/filter.c603
-rw-r--r--debian/transcode/transcode-1.1.7/src/filter.h62
-rw-r--r--debian/transcode/transcode-1.1.7/src/frame_threads.c376
-rw-r--r--debian/transcode/transcode-1.1.7/src/frame_threads.h84
-rw-r--r--debian/transcode/transcode-1.1.7/src/framebuffer.c1275
-rw-r--r--debian/transcode/transcode-1.1.7/src/framebuffer.h499
-rw-r--r--debian/transcode/transcode-1.1.7/src/probe.c859
-rw-r--r--debian/transcode/transcode-1.1.7/src/probe.h124
-rw-r--r--debian/transcode/transcode-1.1.7/src/socket.c881
-rw-r--r--debian/transcode/transcode-1.1.7/src/socket.h59
-rw-r--r--debian/transcode/transcode-1.1.7/src/split.c319
-rw-r--r--debian/transcode/transcode-1.1.7/src/split.h29
-rw-r--r--debian/transcode/transcode-1.1.7/src/tc_defaults.h226
-rw-r--r--debian/transcode/transcode-1.1.7/src/tcinfo.h224
-rw-r--r--debian/transcode/transcode-1.1.7/src/transcode.c2863
-rw-r--r--debian/transcode/transcode-1.1.7/src/transcode.h500
-rw-r--r--debian/transcode/transcode-1.1.7/src/video_trans.c607
-rw-r--r--debian/transcode/transcode-1.1.7/src/video_trans.h37
38 files changed, 17653 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/src/Makefile.am b/debian/transcode/transcode-1.1.7/src/Makefile.am
new file mode 100644
index 00000000..cd163146
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/Makefile.am
@@ -0,0 +1,71 @@
+# # Process this file with automake to produce Makefile.in.
+
+AM_CPPFLAGS = \
+ $(PTHREAD_CFLAGS) \
+ -DMOD_PATH=\"$(MOD_PATH)\" \
+ -DPROF_PATH=\"$(PROF_PATH)\" \
+ -I$(top_srcdir) \
+ $(LIBAVCODEC_CFLAGS) \
+ $(DLDARWIN_CFLAGS) \
+ $(X_CFLAGS)
+
+AM_LDFLAGS = -export-dynamic
+
+bin_PROGRAMS = transcode
+
+if HAVE_X11
+TC_X_LIBS = $(X_LIBS) $(X_PRE_LIBS) -lXext -lX11 $(X_EXTRA_LIBS)
+endif
+
+transcode_LDADD = \
+ $(DLDARWIN_LIBS) \
+ $(LIBTC_LIBS) \
+ $(LIBTCAUDIO_LIBS) \
+ $(LIBTCVIDEO_LIBS) \
+ $(ACLIB_LIBS) \
+ $(AVILIB_LIBS) \
+ $(WAVLIB_LIBS) \
+ $(XIO_LIBS) \
+ $(LIBXML2_LIBS) \
+ $(PTHREAD_LIBS) \
+ $(TC_X_LIBS) \
+ -lm
+
+EXTRA_DIST = \
+ audio_trans.h \
+ cmdline.h \
+ cmdline_def.h \
+ counter.h \
+ decoder.h \
+ dl_loader.h \
+ encoder.h \
+ encoder-common.h \
+ export_profile.h \
+ filter.h \
+ frame_threads.h \
+ framebuffer.h \
+ probe.h \
+ socket.h \
+ split.h \
+ tc_defaults.h \
+ tcinfo.h \
+ transcode.h \
+ video_trans.h
+
+transcode_SOURCES = \
+ transcode.c \
+ audio_trans.c \
+ cmdline.c \
+ counter.c \
+ decoder.c \
+ dl_loader.c \
+ encoder.c \
+ encoder-common.c \
+ encoder-buffer.c \
+ filter.c \
+ frame_threads.c \
+ framebuffer.c \
+ probe.c \
+ socket.c \
+ split.c \
+ video_trans.c
diff --git a/debian/transcode/transcode-1.1.7/src/Makefile.in b/debian/transcode/transcode-1.1.7/src/Makefile.in
new file mode 100644
index 00000000..48bb6d05
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/Makefile.in
@@ -0,0 +1,706 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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.
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = transcode$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_transcode_OBJECTS = transcode.$(OBJEXT) audio_trans.$(OBJEXT) \
+ cmdline.$(OBJEXT) counter.$(OBJEXT) decoder.$(OBJEXT) \
+ dl_loader.$(OBJEXT) encoder.$(OBJEXT) encoder-common.$(OBJEXT) \
+ encoder-buffer.$(OBJEXT) filter.$(OBJEXT) \
+ frame_threads.$(OBJEXT) framebuffer.$(OBJEXT) probe.$(OBJEXT) \
+ socket.$(OBJEXT) split.$(OBJEXT) video_trans.$(OBJEXT)
+transcode_OBJECTS = $(am_transcode_OBJECTS)
+am__DEPENDENCIES_1 =
+@HAVE_X11_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \
+@HAVE_X11_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+transcode_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/autotools/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(transcode_SOURCES)
+DIST_SOURCES = $(transcode_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+A52_CFLAGS = @A52_CFLAGS@
+A52_LIBS = @A52_LIBS@
+ACLIB_LIBS = @ACLIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ALTIVEC_CFLAGS = @ALTIVEC_CFLAGS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AVILIB_LIBS = @AVILIB_LIBS@
+AWK = @AWK@
+BSDAV_CFLAGS = @BSDAV_CFLAGS@
+BSDAV_LIBS = @BSDAV_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXXCPP = @CXXCPP@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLDARWIN_CFLAGS = @DLDARWIN_CFLAGS@
+DLDARWIN_LIBS = @DLDARWIN_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAAC_CFLAGS = @FAAC_CFLAGS@
+FAAC_LIBS = @FAAC_LIBS@
+FGREP = @FGREP@
+FREETYPE2_CFLAGS = @FREETYPE2_CFLAGS@
+FREETYPE2_LIBS = @FREETYPE2_LIBS@
+GREP = @GREP@
+IBP_LIBS = @IBP_LIBS@
+ICONV_CFLAGS = @ICONV_CFLAGS@
+ICONV_LIBS = @ICONV_LIBS@
+IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@
+IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LAME_CFLAGS = @LAME_CFLAGS@
+LAME_LIBS = @LAME_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBAVCODEC_CFLAGS = @LIBAVCODEC_CFLAGS@
+LIBAVCODEC_LIBS = @LIBAVCODEC_LIBS@
+LIBAVFORMAT_CFLAGS = @LIBAVFORMAT_CFLAGS@
+LIBAVFORMAT_LIBS = @LIBAVFORMAT_LIBS@
+LIBDVDREAD_CFLAGS = @LIBDVDREAD_CFLAGS@
+LIBDVDREAD_LIBS = @LIBDVDREAD_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBJPEG_CFLAGS = @LIBJPEG_CFLAGS@
+LIBJPEG_LIBS = @LIBJPEG_LIBS@
+LIBMPEG2CONVERT_CFLAGS = @LIBMPEG2CONVERT_CFLAGS@
+LIBMPEG2CONVERT_LIBS = @LIBMPEG2CONVERT_LIBS@
+LIBMPEG2_CFLAGS = @LIBMPEG2_CFLAGS@
+LIBMPEG2_LIBS = @LIBMPEG2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBPOSTPROC_CFLAGS = @LIBPOSTPROC_CFLAGS@
+LIBPOSTPROC_LIBS = @LIBPOSTPROC_LIBS@
+LIBQUICKTIME_CFLAGS = @LIBQUICKTIME_CFLAGS@
+LIBQUICKTIME_LIBS = @LIBQUICKTIME_LIBS@
+LIBS = @LIBS@
+LIBTCAUDIO_LIBS = @LIBTCAUDIO_LIBS@
+LIBTCVIDEO_LIBS = @LIBTCVIDEO_LIBS@
+LIBTC_LIBS = @LIBTC_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIBV4LCONVERT_CFLAGS = @LIBV4LCONVERT_CFLAGS@
+LIBV4LCONVERT_LIBS = @LIBV4LCONVERT_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LZO_CFLAGS = @LZO_CFLAGS@
+LZO_LIBS = @LZO_LIBS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MJPEGTOOLS_CFLAGS = @MJPEGTOOLS_CFLAGS@
+MJPEGTOOLS_LIBS = @MJPEGTOOLS_LIBS@
+MKDIR_P = @MKDIR_P@
+MOD_PATH = @MOD_PATH@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OGG_CFLAGS = @OGG_CFLAGS@
+OGG_LIBS = @OGG_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PATH_TO_AWK = @PATH_TO_AWK@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROF_PATH = @PROF_PATH@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PVM3_CFLAGS = @PVM3_CFLAGS@
+PVM3_LIBS = @PVM3_LIBS@
+PVM3_PVMGS = @PVM3_PVMGS@
+RANLIB = @RANLIB@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_LIBS = @SDL_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SIMD_FLAGS = @SIMD_FLAGS@
+STRIP = @STRIP@
+THEORA_CFLAGS = @THEORA_CFLAGS@
+THEORA_LIBS = @THEORA_LIBS@
+USE_DLDARWIN = @USE_DLDARWIN@
+VERSION = @VERSION@
+VORBIS_CFLAGS = @VORBIS_CFLAGS@
+VORBIS_LIBS = @VORBIS_LIBS@
+WAVLIB_LIBS = @WAVLIB_LIBS@
+X264_CFLAGS = @X264_CFLAGS@
+X264_LIBS = @X264_LIBS@
+XIO_CFLAGS = @XIO_CFLAGS@
+XIO_LIBS = @XIO_LIBS@
+XMKMF = @XMKMF@
+XVID_CFLAGS = @XVID_CFLAGS@
+XVID_LIBS = @XVID_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+a52_config = @a52_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+bsdav_config = @bsdav_config@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+faac_config = @faac_config@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+iconv_config = @iconv_config@
+imagemagick_config = @imagemagick_config@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+lame_config = @lame_config@
+libdir = @libdir@
+libdvdread_config = @libdvdread_config@
+libexecdir = @libexecdir@
+libjpeg_config = @libjpeg_config@
+libjpegmmx_config = @libjpegmmx_config@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lzo_config = @lzo_config@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pvm3_config = @pvm3_config@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+x_includes = @x_includes@
+x_libraries = @x_libraries@
+xvid_config = @xvid_config@
+AM_CPPFLAGS = \
+ $(PTHREAD_CFLAGS) \
+ -DMOD_PATH=\"$(MOD_PATH)\" \
+ -DPROF_PATH=\"$(PROF_PATH)\" \
+ -I$(top_srcdir) \
+ $(LIBAVCODEC_CFLAGS) \
+ $(DLDARWIN_CFLAGS) \
+ $(X_CFLAGS)
+
+AM_LDFLAGS = -export-dynamic
+@HAVE_X11_TRUE@TC_X_LIBS = $(X_LIBS) $(X_PRE_LIBS) -lXext -lX11 $(X_EXTRA_LIBS)
+transcode_LDADD = \
+ $(DLDARWIN_LIBS) \
+ $(LIBTC_LIBS) \
+ $(LIBTCAUDIO_LIBS) \
+ $(LIBTCVIDEO_LIBS) \
+ $(ACLIB_LIBS) \
+ $(AVILIB_LIBS) \
+ $(WAVLIB_LIBS) \
+ $(XIO_LIBS) \
+ $(LIBXML2_LIBS) \
+ $(PTHREAD_LIBS) \
+ $(TC_X_LIBS) \
+ -lm
+
+EXTRA_DIST = \
+ audio_trans.h \
+ cmdline.h \
+ cmdline_def.h \
+ counter.h \
+ decoder.h \
+ dl_loader.h \
+ encoder.h \
+ encoder-common.h \
+ export_profile.h \
+ filter.h \
+ frame_threads.h \
+ framebuffer.h \
+ probe.h \
+ socket.h \
+ split.h \
+ tc_defaults.h \
+ tcinfo.h \
+ transcode.h \
+ video_trans.h
+
+transcode_SOURCES = \
+ transcode.c \
+ audio_trans.c \
+ cmdline.c \
+ counter.c \
+ decoder.c \
+ dl_loader.c \
+ encoder.c \
+ encoder-common.c \
+ encoder-buffer.c \
+ filter.c \
+ frame_threads.c \
+ framebuffer.c \
+ probe.c \
+ socket.c \
+ split.c \
+ video_trans.c
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+transcode$(EXEEXT): $(transcode_OBJECTS) $(transcode_DEPENDENCIES)
+ @rm -f transcode$(EXEEXT)
+ $(LINK) $(transcode_OBJECTS) $(transcode_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audio_trans.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmdline.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/counter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decoder.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dl_loader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoder-buffer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoder-common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoder.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frame_threads.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/framebuffer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/probe.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/split.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transcode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_trans.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool ctags distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-binPROGRAMS
+
+
+# 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/debian/transcode/transcode-1.1.7/src/audio_trans.c b/debian/transcode/transcode-1.1.7/src/audio_trans.c
new file mode 100644
index 00000000..019e5212
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/audio_trans.c
@@ -0,0 +1,176 @@
+/*
+ * audio_trans.c - audio frame transformation routines
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "transcode.h"
+#include "framebuffer.h"
+#include "audio_trans.h"
+#include "libtcaudio/tcaudio.h"
+
+/*************************************************************************/
+
+/* Handle for calling tcaudio functions. */
+static TCAHandle handle = 0;
+
+/*************************************************************************/
+/*************************************************************************/
+
+/**
+ * do_process_audio: Perform actual audio processing.
+ *
+ * Parameters:
+ * vob: Global data pointer.
+ * ptr: Pointer to audio frame buffer.
+ * Return value:
+ * 1 on success, 0 on failure.
+ */
+
+static int do_process_audio(vob_t *vob, aframe_list_t *ptr)
+{
+ int srcfmt, nsamples;
+
+ /* First convert audio to destination format (also handles -d) */
+ if (vob->a_bits == 8) {
+ srcfmt = TCA_U8;
+ nsamples = ptr->audio_size;
+ } else if (vob->a_bits == 16) {
+ srcfmt = pcmswap ? TCA_S16BE : TCA_S16LE;
+ nsamples = ptr->audio_size / 2;
+ } else {
+ tc_log_error(__FILE__, "Sorry, source audio format not supported");
+ return 0;
+ }
+ tca_convert_from(handle, ptr->audio_buf, nsamples, srcfmt);
+
+ /* Convert between stereo and mono */
+ if (vob->a_chan == 1 && vob->dm_chan == 2) {
+ tca_mono_to_stereo(handle, ptr->audio_buf, nsamples);
+ nsamples *= 2;
+ } else if (vob->a_chan == 2 && vob->dm_chan == 1) {
+ nsamples /= 2;
+ tca_stereo_to_mono(handle, ptr->audio_buf, nsamples);
+ }
+
+ /* Update audio buffer size */
+ ptr->audio_size = nsamples * (vob->dm_bits/8);
+
+ /* -s: Amplify volume */
+ if (vob->volume > 0) {
+ int nclip = 0;
+ tca_amplify(handle, ptr->audio_buf, nsamples, vob->volume, &nclip);
+ vob->clip_count += nclip;
+ }
+
+ /* --av_fine_ms: Shift audio */
+ if (vob->sync_ms != 0) {
+ /* This is the first time here: convert time (ms) to samples.
+ * Note that we adjust based on the source rate */
+ vob->sync_samples = (vob->sync_ms * vob->a_rate / 1000) * vob->dm_chan;
+ if (verbose & TC_DEBUG) {
+ if (vob->sync_samples < 0) {
+ tc_log_info(__FILE__, "inserting %d PCM samples (%d ms)",
+ -vob->sync_samples, -vob->sync_ms);
+ } else {
+ tc_log_info(__FILE__, "deleting %d PCM samples (%d ms)",
+ vob->sync_samples, vob->sync_ms);
+ }
+ }
+ vob->sync_ms = 0; // Clear it so we don't come here again
+ }
+ if (vob->sync_samples < 0) {
+ int new_samples = -vob->sync_samples;
+ int new_bytes = new_samples * (vob->dm_bits/8);
+ memmove((uint8_t *)ptr->audio_buf + new_bytes, ptr->audio_buf,
+ ptr->audio_size);
+ memset(ptr->audio_buf, 0, new_bytes);
+ nsamples += new_samples;
+ ptr->audio_size += new_bytes;
+ vob->sync_samples = 0;
+ } else if (vob->sync_samples > 0) {
+ int del_samples = vob->sync_samples;
+ if (del_samples >= nsamples) {
+ del_samples = nsamples;
+ nsamples = 0;
+ ptr->audio_size = 0;
+ } else {
+ int del_bytes = del_samples * (vob->dm_bits/8);
+ memmove(ptr->audio_buf, (uint8_t *)ptr->audio_buf + del_bytes,
+ ptr->audio_size - del_bytes);
+ nsamples -= del_samples;
+ ptr->audio_size -= del_bytes;
+ }
+ vob->sync_samples -= del_samples;
+ }
+
+ /* All done */
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * process_aud_frame: Main audio frame processing routine.
+ *
+ * Parameters:
+ * vob: Global data pointer.
+ * ptr: Pointer to audio frame buffer.
+ * Return value:
+ * 0 on success, -1 on failure.
+ */
+
+int process_aud_frame(vob_t *vob, aframe_list_t *ptr)
+{
+ /* Check parameter validity */
+ if (!vob || !ptr)
+ return -1;
+
+ /* Allocate tcaudio handle if necessary */
+ if (!handle) {
+ AudioFormat format;
+ if (vob->dm_bits == 8) {
+ format = TCA_U8;
+ } else if (vob->dm_bits == 16) {
+ format = TCA_S16LE;
+ } else {
+ tc_log_error(__FILE__, "Sorry, output audio format not supported");
+ return -1;
+ }
+ handle = tca_init(format);
+ if (!handle) {
+ tc_log_error(__FILE__, "tca_init() failed!");
+ return -1;
+ }
+ }
+
+ /* Check for pass-through mode */
+ if (vob->pass_flag & TC_AUDIO)
+ return 0;
+
+ /* Check audio format */
+ if (vob->im_a_codec != CODEC_PCM) {
+ tc_log_error(__FILE__,
+ "Sorry, only PCM audio is supported for processing");
+ return -1;
+ }
+
+ /* Actually perform processing */
+ return do_process_audio(vob, ptr) ? 0 : -1;
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/audio_trans.h b/debian/transcode/transcode-1.1.7/src/audio_trans.h
new file mode 100644
index 00000000..1060ee8a
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/audio_trans.h
@@ -0,0 +1,18 @@
+/*
+ * audio_trans.h - header for audio frame transformation routines
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#ifndef _AUDIO_TRANS_H
+#define _AUDIO_TRANS_H
+
+#include "framebuffer.h"
+
+int process_aud_frame(vob_t *vob, aframe_list_t *ptr);
+
+#endif
diff --git a/debian/transcode/transcode-1.1.7/src/cmdline.c b/debian/transcode/transcode-1.1.7/src/cmdline.c
new file mode 100644
index 00000000..dec44bff
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/cmdline.c
@@ -0,0 +1,241 @@
+/*
+ * cmdline.c -- parse transcode command line
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "transcode.h"
+#include "decoder.h"
+#include "probe.h"
+#include "libtc/libtc.h"
+#include "libtc/cfgfile.h"
+#include "libtc/ratiocodes.h"
+#include "libtc/tccodecs.h"
+#include "libtc/xio.h"
+
+#include "cmdline.h"
+
+#include <ctype.h>
+#ifdef HAVE_GETOPT_LONG_ONLY
+#include <getopt.h>
+#else
+#include "libtc/getopt.h"
+#endif
+
+
+/* Global variables from transcode.c that should eventually go away. */
+int core_mode=TC_MODE_DEFAULT;
+char *im_aud_mod = NULL, *im_vid_mod = NULL;
+char *ex_aud_mod = NULL, *ex_vid_mod = NULL, *ex_mplex_mod = NULL;
+char *plugins_string = NULL;
+char
+ *nav_seek_file=NULL, *socket_file=NULL,
+ *chbase=NULL, //*dirbase=NULL,
+ base[TC_BUF_MIN];
+int psu_frame_threshold=12; //psu with less/equal frames are skipped.
+int
+ no_vin_codec=1, no_ain_codec=1,
+ no_v_out_codec=1, no_a_out_codec=1;
+int
+ frame_a=TC_FRAME_FIRST, // defaults to all frames
+ frame_b=TC_FRAME_LAST,
+ splitavi_frames=0,
+ psu_mode=TC_FALSE;
+int preset_flag=0, auto_probe=1, seek_range=1;
+int no_audio_adjust=TC_FALSE, no_split=TC_FALSE;
+char *fc_ttime_string = NULL;
+int sync_seconds=0;
+pid_t writepid = 0;
+
+
+/*************************************************************************/
+
+/* Utility routines used by option processing. */
+
+
+/**
+ * print_option_help: Print a help line for a given option.
+ *
+ * Parameters:
+ * name: Option name (long name).
+ * shortopt: Character used for the short form of the option, 0 if none.
+ * argname: String describing the option's argument, NULL if none.
+ * helptext: Help text for the option. May include newlines (\n).
+ * optwidth: Number of columns to use for the long name and argument.
+ * Return value:
+ * None.
+ */
+
+#define MAX_LINELEN 79 /* Maximum line length */
+#define MAX_OPTWIDTH 35 /* Maximum space to allocate to options */
+
+static void print_option_help(const char *name, char shortopt,
+ const char *argname, const char *helptext,
+ int optwidth)
+{
+ int helpmax;
+ char optbuf[MAX_LINELEN+1];
+ const char *s;
+
+ if (optwidth > MAX_OPTWIDTH)
+ optwidth = MAX_OPTWIDTH;
+ snprintf(optbuf, sizeof(optbuf), "--%s%s%s",
+ name,
+ argname ? " " : "",
+ argname ? argname : "");
+ printf(" %c%c%c%-*s ",
+ shortopt ? '-' : ' ',
+ shortopt ? shortopt : ' ',
+ shortopt ? '/' : ' ',
+ optwidth, optbuf);
+ if (strlen(optbuf) > optwidth) {
+ /* If the option overflowed the given width, skip to the next line */
+ printf("\n%-*s", 5 + optwidth + 2, "");
+ }
+ /* Break help text into lines at whitespace or \n */
+ helpmax = MAX_LINELEN - 5 - optwidth - 2;
+ s = helptext;
+ s += strspn(s, " \t");
+ do {
+ const char *t, *next;
+ t = s + helpmax;
+ if (t > s + strlen(s))
+ t = s + strlen(s);
+ if (t > s + strcspn(s, "\n"))
+ t = s + strcspn(s, "\n");
+ /* Don't try to break text with no whitespace */
+ if (s + strcspn(s, " \t") < t) {
+ while (t > s+1 && *t && !isspace(*t))
+ t--;
+ }
+ if (*t == '\n') {
+ /* Preserve whitespace after a newline */
+ next = t + 1;
+ } else {
+ next = t + strspn(t, " \t\n");
+ }
+ /* Only print indent if there's more text */
+ printf("%.*s\n%-*s",
+ (int)(t-s), s,
+ *next ? optwidth+7+3 : 0, "");
+ s = next;
+ /* Indent subsequent lines 3 spaces (the +3 above is also for this) */
+ helpmax = 79 - 5 - optwidth - 2 - 3;
+ } while (*s);
+}
+
+/*************************************************************************/
+
+/* The actual option definitions are located in cmdline_def.h using macros;
+ * see that file for details. */
+
+enum {
+ DUMMY = 0x100,
+#define TC_OPTIONS_TO_ENUM
+#include "cmdline_def.h"
+#undef TC_OPTIONS_TO_ENUM
+};
+
+static struct option tc_options[] = {
+#define TC_OPTIONS_TO_STRUCT_OPTION
+#include "cmdline_def.h"
+#undef TC_OPTIONS_TO_STRUCT_OPTION
+};
+
+
+/**
+ * usage: Print a command-line help message.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+static void usage(void)
+{
+ int optwidth = 0;
+
+#define TC_OPTIONS_TO_OPTWIDTH optwidth
+#include "cmdline_def.h"
+#undef TC_OPTIONS_TO_OPTWIDTH
+
+ version();
+ printf("\n");
+ printf("Usage: transcode [options...]\n");
+ printf("\n");
+ printf("Options:\n");
+#define TC_OPTIONS_TO_HELP optwidth
+#include "cmdline_def.h"
+#undef TC_OPTIONS_TO_HELP
+ printf("\n");
+ printf("use tcmodinfo to discover module properties and configurable options.\n");
+}
+
+
+/**
+ * parse_cmdline: Parse all options on the transcode command line, storing
+ * appropriate values in the global "vob" data structure.
+ *
+ * Parameters:
+ * argc: Command line argument count.
+ * argv: Command line argument vector.
+ * vob: Global data structure.
+ * Return value:
+ * Nonzero on success, zero on error.
+ */
+
+int parse_cmdline(int argc, char **argv, vob_t *vob)
+{
+ const char *shortopts;
+ int option;
+
+#define TC_OPTIONS_TO_SHORTOPTS shortopts
+#include "cmdline_def.h"
+#undef TC_OPTIONS_TO_SHORTOPTS
+
+ while (-1 != (option = getopt_long_only(argc, argv, shortopts,
+ tc_options, NULL))
+ ) {
+ switch (option) {
+#define TC_OPTIONS_TO_CODE
+#include "cmdline_def.h"
+#undef TC_OPTIONS_TO_CODE
+ default:
+ short_usage: /* error-handling label */
+ fprintf(stderr, "'transcode -h | more' shows a list of available"
+ " command line options.\n");
+ return 0;
+ }
+ }
+
+ if (optind == 1)
+ goto short_usage;
+
+#ifndef __APPLE__
+ if (optind < argc) {
+ int n;
+ tc_warn("unused command line argument detected (%d/%d)", optind, argc);
+ for (n = optind; n < argc; n++)
+ tc_warn("argc[%d]=%s (unused)", n, argv[n]);
+ }
+#endif
+
+ return 1;
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/cmdline.h b/debian/transcode/transcode-1.1.7/src/cmdline.h
new file mode 100644
index 00000000..94a3bfb2
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/cmdline.h
@@ -0,0 +1,47 @@
+/*
+ * cmdline.h -- header for transcode command line parser
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#ifndef _CMDLINE_H
+#define _CMDLINE_H
+
+/*************************************************************************/
+
+/* The parsing routine: */
+extern int parse_cmdline(int argc, char **argv, vob_t *vob);
+
+/* Global variables from transcode.c that should eventually go away. */
+extern int core_mode;
+extern char *im_aud_mod, *im_vid_mod;
+extern char *ex_aud_mod, *ex_vid_mod, *ex_mplex_mod;
+extern char *plugins_string;
+extern char *nav_seek_file, *socket_file, *chbase, //*dirbase,
+ base[TC_BUF_MIN];
+extern int psu_frame_threshold;
+extern int no_vin_codec, no_ain_codec, no_v_out_codec, no_a_out_codec;
+extern int frame_a, frame_b, splitavi_frames, psu_mode;
+extern int preset_flag, auto_probe, seek_range;
+extern int no_audio_adjust, no_split;
+extern char *fc_ttime_string;
+extern int sync_seconds;
+extern pid_t writepid;
+
+/*************************************************************************/
+
+#endif /* _CMDLINE_H */
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/cmdline_def.h b/debian/transcode/transcode-1.1.7/src/cmdline_def.h
new file mode 100644
index 00000000..1f0d23ab
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/cmdline_def.h
@@ -0,0 +1,1602 @@
+/*
+ * cmdline_def.h -- transcode command line option definitions
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+/* This file contains definitions of all command-line options supported by
+ * transcode. The options are defined using macros which evaluate to
+ * different things depending on which of the following symbols is defined
+ * (exactly one must be defined before including this file):
+ *
+ * TC_OPTIONS_TO_ENUM
+ * Output a constant name for each long option, for use in defining an
+ * enum for the "val" field in "struct option".
+ *
+ * TC_OPTIONS_TO_STRUCT_OPTION
+ * Output a "struct option" definition for each option, for use in
+ * initializing a long-option array.
+ *
+ * TC_OPTIONS_TO_SHORTOPTS
+ * Output code to create a string of the form "x" or "x:" for each
+ * option which has a short option equivalent, for use in creating the
+ * short-option list passed to getopt(). The resulting string pointer
+ * is assigned to the variable named by the TC_OPTIONS_TO_SHORTOPTS
+ * symbol.
+ *
+ * TC_OPTIONS_TO_CODE
+ * Output code to process each option, for use in a switch statement.
+ *
+ * TC_OPTIONS_TO_OPTWIDTH
+ * Output code to compute the maximum width of any long option name
+ * (including the leading "--"), storing the result in the variable
+ * named by the TC_OPTIONS_TO_OPTWIDTH symbol, which must have been
+ * initialized to zero.
+ *
+ * TC_OPTIONS_TO_HELP
+ * Output a printf() statement to print the help text for each option.
+ * Also output printf() statements for option group headers (defined
+ * with the TC_HEADER macro). The variable named by the
+ * TC_OPTIONS_TO_HELP symbol is used as the option name field width
+ * (presumed to have been computed with TC_OPTIONS_TO_OPTWIDTH).
+ *
+ * If none of the above are defined, this file simply declares the
+ * parse_cmdline() prototype.
+ *
+ * Note that we explicitly do not use a #ifdef/#endif pair to avoid
+ * multiple inclusion of this file, because it is included multiple times
+ * by transcode.c, each time with a different one of the above symbols
+ * defined.
+ */
+
+/*************************************************************************/
+
+/* Check what we've been included for, and define macros appropriately.
+ * The macros defined are:
+ *
+ * TC_OPTION(name, shortopt, argname, helptext, code)
+ * Defines an option "--name" (name should _not_ be quoted). The name
+ * must be a valid C identifier, except that it may begin with a digit.
+ * * "shortopt" should be the character constant for the option's
+ * option's short form (e.g. 'x' if the short form is "-x"), or
+ * zero if the option has no short form.
+ * * "argname" should be a string naming the option's argument (for
+ * display in help text) if the option takes an argument, zero
+ * (0, not the string "0") if it does not.
+ * * "helptext" should be the option's help text, as a string.
+ * * "code" should be the code to process the option (which will be in
+ * its own block, so local variables are allowed--however, a comma in
+ * variable declarations will be interpreted as a macro argument
+ * delimiter, so each variable must go in its own statement; see the
+ * -x code for an example).
+ *
+ * TC_HEADER(name)
+ * Defines an option group header, which will be printed as part of the
+ * help message.
+ *
+ * _TCO_INIT
+ * _TCO_FINI
+ * Local macros containing any appropriate header and trailer code for
+ * the requested output. Defined only when necessary.
+ */
+
+#ifdef TC_OPTION
+# error TC_OPTION is already defined! Check for symbol name conflicts.
+#endif
+#ifdef TC_HEADER
+# error TC_HEADER is already defined! Check for symbol name conflicts.
+#endif
+#ifdef _TCO_INIT
+# error _TCO_INIT is already defined! Check for symbol name conflicts.
+#endif
+#ifdef _TCO_FINI
+# error _TCO_FINI is already defined! Check for symbol name conflicts.
+#endif
+
+#ifdef TC_OPTIONS_TO_ENUM
+# ifdef TC_OPTION
+# error More than one TC_OPTIONS symbol defined!
+# endif
+/* Define the option value to either the character value of the short form
+ * or a unique enum constant, while not disturbing the enum sequence */
+# define TC_OPTION(name,shortopt,argname,helptext,code) \
+ OPT_TMP1_##name, \
+ OPT_##name = shortopt + (!shortopt * OPT_TMP1_##name),\
+ OPT_TMP2_##name = OPT_TMP1_##name,
+# define TC_HEADER(name) /* nothing */
+#endif
+
+#ifdef TC_OPTIONS_TO_STRUCT_OPTION
+# ifdef TC_OPTION
+# error More than one TC_OPTIONS symbol defined!
+# endif
+# define TC_OPTION(name,shortopt,argname,helptext,code) \
+ { #name, (argname) ? required_argument : no_argument, NULL, OPT_##name },
+# define TC_HEADER(name) /* nothing */
+# define _TCO_FINI {0,0,0,0}
+#endif
+
+#ifdef TC_OPTIONS_TO_SHORTOPTS
+# ifdef TC_OPTION
+# error More than one TC_OPTIONS symbol defined!
+# endif
+# define _TCO_INIT { \
+ static char shortbuf[513]; \
+ char *ptr = shortbuf; \
+ *shortbuf = 0;
+# define TC_OPTION(name,shortopt,argname,helptext,code) \
+ if (shortopt && ptr-shortbuf < sizeof(shortbuf)-3) { \
+ *ptr++ = shortopt; \
+ if (argname) \
+ *ptr++ = ':'; \
+ }
+# define TC_HEADER(name) /* nothing */
+# define _TCO_FINI \
+ *ptr = 0; \
+ TC_OPTIONS_TO_SHORTOPTS = shortbuf; \
+}
+#endif
+
+#ifdef TC_OPTIONS_TO_CODE
+# ifdef TC_OPTION
+# error More than one TC_OPTIONS symbol defined!
+# endif
+# define TC_OPTION(name,shortopt,argname,helptext,code) \
+ case OPT_##name: { code; break; }
+# define TC_HEADER(name) /* nothing */
+#endif
+
+#ifdef TC_OPTIONS_TO_OPTWIDTH
+# ifdef TC_OPTION
+# error More than one TC_OPTIONS symbol defined!
+# endif
+# define TC_OPTION(name,shortopt,argname,helptext,code) { \
+ int len = (sizeof(#name)-1)+2; \
+ if (argname) \
+ len += (sizeof(argname)-1)+1; \
+ if (len > TC_OPTIONS_TO_OPTWIDTH) \
+ TC_OPTIONS_TO_OPTWIDTH = len; \
+}
+# define TC_HEADER(name) /* nothing */
+#endif
+
+#ifdef TC_OPTIONS_TO_HELP
+# ifdef TC_OPTION
+# error More than one TC_OPTIONS symbol defined!
+# endif
+# define TC_OPTION(name,shortopt,argname,helptext,code) \
+ print_option_help(#name, shortopt, argname, helptext, TC_OPTIONS_TO_HELP);
+# define TC_HEADER(name) \
+ printf("\n ======== %s ========\n\n", name);
+#endif
+
+#ifndef TC_OPTION
+# define TC_OPTION(name,shortopt,argname,helptext,code) /* nothing */
+# define TC_HEADER(name) /* nothing */
+/* The parsing routine: */
+extern int parse_cmdline(int argc, char **argv, vob_t *vob);
+#endif
+
+
+/* Output header code, if any. */
+#ifdef _TCO_INIT
+_TCO_INIT
+#endif
+
+/*************************************************************************/
+
+/* The actual option definitions. */
+TC_OPTION(help, 'h', 0,
+ "print this usage message and exit",
+ usage();
+ return 0;
+)
+TC_OPTION(version, 'v', 0,
+ "print version and exit",
+ version();
+ return 0;
+)
+TC_OPTION(verbose, 'q', "level",
+ "verbosity (0=quiet,1=info,2=debug) [1]",
+ verbose = strtol(optarg, &optarg, 10);
+ if (*optarg) {
+ tc_error("Invalid argument for -q/--verbose");
+ goto short_usage;
+ }
+ if (verbose) // ensure TC_INFO is always set if not silent
+ verbose |= TC_INFO;
+ vob->verbose = verbose;
+)
+
+/********/ TC_HEADER("Input, output, and control files") /********/
+
+TC_OPTION(input, 'i', "file",
+#ifdef HAVE_LIBDVDREAD
+ "input file/directory/device/mountpoint name",
+#else
+ "input file/directory name",
+#endif
+ vob->video_in_file = optarg;
+)
+
+TC_OPTION(multi_input, 0, 0,
+ "enable EXPERIMENTAL multiple input mode (see manpage)",
+ core_mode = TC_MODE_DIRECTORY;
+)
+TC_OPTION(output, 'o', "file",
+ "output file name",
+ vob->video_out_file = optarg;
+)
+TC_OPTION(avi_limit, 0, "size",
+ "split output AVI file after \"size\" MB [2048]",
+ tc_avi_limit = strtol(optarg, &optarg, 10);
+ if (*optarg) {
+ tc_error("Invalid argument for --avi_limit");
+ goto short_usage;
+ }
+ if (tc_avi_limit <= 0)
+ tc_avi_limit = (unsigned int)-1;
+)
+TC_OPTION(avi_comments, 0, "file",
+ "read AVI header comments from file [off]",
+ vob->avi_comment_fd = xio_open(optarg, O_RDONLY);
+ if (vob->avi_comment_fd == -1) {
+ tc_error("Cannot open comment file \"%s\"", optarg);
+ goto short_usage;
+ }
+)
+TC_OPTION(split, 't', "n,base",
+ "split output to base%03d.avi with n frames [off]",
+ /* DANGER WILL ROBINSON! scanf("%1000s") will read up to
+ * 1000 characters--EXCLUDING the trailing null, so a
+ * buffer of 1001 bytes is needed! */
+ char buf[1001] = "";
+ if (sscanf(optarg, "%d,%1000[^,]", &splitavi_frames, buf) != 2
+ || splitavi_frames <= 0
+ ) {
+ tc_error("Invalid argument for -t/--split");
+ goto short_usage;
+ }
+ if (strlen(buf) > sizeof(base)-1) {
+ tc_error("Base name too long for -t/--split");
+ goto short_usage;
+ }
+ memcpy(base, buf, strlen(buf)+1);
+ core_mode = TC_MODE_AVI_SPLIT;
+)
+TC_OPTION(audio_input, 'p', "file",
+ "read audio stream from separate file [off]",
+ vob->audio_in_file = optarg;
+)
+TC_OPTION(audio_output, 'm', "file",
+ "write audio stream to separate file [off]",
+ if (*optarg == '-')
+ goto short_usage;
+ vob->audio_out_file = optarg;
+ vob->audio_file_flag = 1;
+)
+TC_OPTION(nav_seek, 0, "file",
+ "use VOB navigation file [off]",
+ if (*optarg == '-')
+ goto short_usage;
+ vob->nav_seek_file = optarg;
+ nav_seek_file = optarg;
+)
+TC_OPTION(socket, 0, "file",
+ "socket file for run-time control [off]",
+ if (*optarg == '-')
+ goto short_usage;
+ socket_file = optarg;
+)
+TC_OPTION(write_pid, 0, "file",
+ "write pid of transcode process to \"file\" [off]",
+ FILE *f;
+ if (*optarg == '-')
+ goto short_usage;
+ f = fopen(optarg, "w");
+ if (f) {
+ fprintf(f, "%d\n", writepid);
+ fclose(f);
+ }
+)
+TC_OPTION(config_dir, 0, "dir",
+ "assume config files are in this dir [off]",
+ if (*optarg == '-')
+ goto short_usage;
+ tc_set_config_dir(optarg);
+)
+
+/********/ TC_HEADER("Input stream selection") /********/
+
+TC_OPTION(extract_track, 'a', "a[,v]",
+ "extract audio[,video] track [0,0]",
+ if (sscanf(optarg, "%d,%d", &vob->a_track, &vob->v_track) < 1
+ || vob->a_track < 0
+ || vob->v_track < 0
+ ) {
+ tc_error("Invalid argument for -a/--extract_track");
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_TRACK;
+)
+TC_OPTION(frames, 'c', "f1-f2[,f3-f4...]",
+ "encode only given range (frames or HH:MM:SS),"
+ " f2,f4,... are *not* encoded [all]",
+ if (*optarg == '-')
+ goto short_usage;
+ fc_ttime_string = optarg;
+)
+TC_OPTION(frame_interval, 0, "N",
+ "select only every Nth frame to be exported [1]",
+ vob->frame_interval = strtol(optarg, &optarg, 0);
+ if (*optarg || vob->frame_interval < 1) {
+ tc_error("Invalid argument for --frame_interval");
+ goto short_usage;
+ }
+)
+TC_OPTION(title, 'T', "t[,c[-d][,a]]",
+ "select DVD title[,chapters[,angle]] [1,all,1]",
+ if (sscanf(optarg, "%d,%d-%d,%d", &vob->dvd_title,
+ &vob->dvd_chapter1, &vob->dvd_chapter2,
+ &vob->dvd_angle) >= 3
+ ) {
+ /* Chapter range given */
+ } else if (sscanf(optarg, "%d,%d,%d", &vob->dvd_title,
+ &vob->dvd_chapter1, &vob->dvd_angle) >= 1
+ ) {
+ /* Single (or no) chapter given */
+ vob->dvd_chapter2 = -1; /* indicate single chapter */
+ } else {
+ tc_error("Invalid argument for -T/--title");
+ goto short_usage;
+ }
+ if (vob->dvd_title < 1) {
+ tc_error("Invalid title for -T/--title");
+ goto short_usage;
+ }
+ if (vob->dvd_chapter1 != -1) {
+ if (vob->dvd_chapter1 < 1
+ || (vob->dvd_chapter2 != -1
+ && vob->dvd_chapter2 < vob->dvd_chapter1)
+ ) {
+ tc_error("Invalid chapter(s) for -T/--title");
+ goto short_usage;
+ }
+ }
+ if (vob->dvd_angle < 1) {
+ tc_error("Invalid angle for -T/--title");
+ goto short_usage;
+ }
+)
+TC_OPTION(psu, 'S', "unit[,s1-s2]",
+ "process program stream unit[,s1-s2] sequences [0,all]",
+ if (sscanf(optarg, "%d,%d-%d", &vob->ps_unit,
+ &vob->ps_seq1, &vob->ps_seq2) < 0
+ || vob->ps_unit < 0
+ || vob->ps_seq1 < 0
+ || vob->ps_seq2 < 0
+ || vob->ps_seq1 > vob->ps_seq2
+ ) {
+ tc_error("Invalid argument for -S/--psu");
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_SEEK;
+)
+TC_OPTION(vob_seek, 'L', "N",
+ "seek to VOB stream offset Nx2kB [0]",
+ vob->vob_offset = strtol(optarg, &optarg, 10);
+ if (*optarg || vob->vob_offset < 0) {
+ tc_error("Invalid argument for -L/--vob_seek");
+ goto short_usage;
+ }
+)
+TC_OPTION(ts_pid, 0, "0xNN",
+ "transport video stream pid [0]",
+ vob->ts_pid1 = strtol(optarg, &optarg, 16);
+ if (*optarg) {
+ tc_error("Invalid argument for --ts_pid");
+ goto short_usage;
+ }
+ vob->ts_pid2 = vob->ts_pid1;
+)
+
+/********/ TC_HEADER("Input stream format options") /********/
+
+TC_OPTION(probe, 'H', "n",
+ "auto-probe n MB of source (0=off) [1]",
+ seek_range = strtol(optarg, &optarg, 10);
+ if (*optarg || seek_range < 0) {
+ tc_error("Invalid argument for -H/--probe");
+ goto short_usage;
+ }
+ if (seek_range == 0)
+ auto_probe = 0;
+)
+TC_OPTION(mplayer_probe, 0, 0,
+ "use (external) mplayer to probe source [off]",
+ preset_flag |= TC_PROBE_NO_BUILTIN;
+)
+TC_OPTION(import_with, 'x', "vmod[,amod]",
+ "video[,audio] import modules [null]",
+ /* Careful here! "static char vbuf[1001], abuf[1001]" will
+ * be treated as two separate macro arguments by the
+ * preprocessor, so we have to declare each variable in a
+ * separate statement. */
+ static char vbuf[1001];
+ static char abuf[1001];
+ char quote;
+ char *s;
+ int n;
+ /* Scan the string ourselves, rather than using scanf(),
+ * so we can handle internal quotes properly for -x mplayer */
+ if (!*optarg) {
+ tc_error("Invalid argument for -x/--import_with");
+ goto short_usage;
+ }
+ *vbuf = *abuf = 0;
+ quote = 0;
+ n = 0;
+ s = vbuf;
+ while (*optarg) {
+ if (*optarg == quote) {
+ quote = 0;
+ } else if (!quote && (*optarg == '"' || *optarg == '\'')) {
+ quote = *optarg;
+ } else if (!quote && *optarg == ',') {
+ if (s == vbuf) {
+ s = abuf;
+ n = 0;
+ } else {
+ tc_error("Invalid argument for -x/--import_with");
+ goto short_usage;
+ }
+ } else {
+ if (n < (s==vbuf ? sizeof(vbuf) : sizeof(abuf))-1) {
+ s[n++] = *optarg;
+ s[n] = 0;
+ }
+ }
+ optarg++;
+ }
+ if (quote) {
+ tc_error("Invalid argument for -x/--import_with"
+ " (unbalanced quotes)");
+ }
+ s[n] = 0;
+ n = (s==vbuf ? 1 : 2);
+ im_vid_mod = vbuf;
+ // FIXME: vin -> v_in to match no_v_out_codec (same w/audio)
+ no_vin_codec = 0;
+ if ((s = strchr(im_vid_mod, '=')) != NULL) {
+ *s++ = 0;
+ if (!*s) {
+ tc_error("Invalid option string for video import"
+ " module");
+ goto short_usage;
+ }
+ vob->im_v_string = s;
+ }
+ if (n >= 2) {
+ im_aud_mod = abuf;
+ no_ain_codec = 0;
+ if ((s = strchr(im_aud_mod, '=')) != NULL) {
+ *s++ = 0;
+ if (!*s) {
+ tc_error("Invalid option string for audio import"
+ " module");
+ goto short_usage;
+ }
+ vob->im_a_string = s;
+ }
+ } else {
+ im_aud_mod = im_vid_mod;
+ }
+ /* "auto" checks have to come here, to catch "auto=..." */
+ if (strcmp(im_vid_mod, "auto") == 0) {
+ im_vid_mod = NULL;
+ no_vin_codec = 1;
+ }
+ if (strcmp(im_aud_mod, "auto") == 0) {
+ im_aud_mod = NULL;
+ no_ain_codec = 1;
+ }
+)
+TC_OPTION(frame_size, 'g', "WxH",
+ "video frame size [720x576]",
+ if (sscanf(optarg, "%dx%d", &vob->im_v_width,
+ &vob->im_v_height) != 2
+ || vob->im_v_width <= 0
+ || vob->im_v_height <= 0
+ ) {
+ tc_error("Invalid argument for -g/--frame_size");
+ goto short_usage;
+ }
+ if (vob->im_v_width > TC_MAX_V_FRAME_WIDTH
+ || vob->im_v_height > TC_MAX_V_FRAME_HEIGHT
+ ) {
+ tc_error("Video frame size out of range (max %dx%d)",
+ TC_MAX_V_FRAME_WIDTH, TC_MAX_V_FRAME_HEIGHT);
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_FRAMESIZE;
+)
+TC_OPTION(import_asr, 0, "C",
+ "set import display aspect ratio code C [auto]",
+ vob->im_asr = strtol(optarg, &optarg, 10);
+ if (*optarg || vob->im_asr < 0) {
+ tc_error("Invalid argument for --import_asr");
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_IMASR;
+)
+TC_OPTION(import_fps, 'f', "rate[,frc]",
+ "input video frame rate[,frc] [25.000,0]",
+ int n = sscanf(optarg, "%lf,%d", &vob->fps, &vob->im_frc);
+ if (n == 2) {
+ if (vob->im_frc < 0 || vob->im_frc > 15) {
+ tc_error("invalid frame rate code for option -f");
+ goto short_usage;
+ }
+ tc_frc_code_to_value(vob->im_frc, &vob->fps);
+ } else {
+ if (n < 1 || vob->fps < MIN_FPS) {
+ tc_error("invalid frame rate for option -f");
+ goto short_usage;
+ }
+ }
+ preset_flag |= TC_PROBE_NO_FPS;
+)
+TC_OPTION(hard_fps, 0, 0,
+ "disable smooth dropping (for variable fps clips) [enabled]",
+ vob->hard_fps_flag = TC_TRUE;
+)
+TC_OPTION(import_afmt, 'e', "r[,b[,c]]",
+ "import audio sample format [48000,16,2]",
+ int n = sscanf(optarg, "%d,%d,%d", &vob->a_rate,
+ &vob->a_bits, &vob->a_chan);
+ switch (n) {
+ case 3:
+ if (vob->a_chan != 0
+ && vob->a_chan != 1
+ && vob->a_chan != 2
+ && vob->a_chan != 6
+ ) {
+ tc_error("Invalid channels argument for"
+ " -e/--import_afmt");
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_CHAN;
+ /* fall through */
+ case 2:
+ if (vob->a_bits != 8 && vob->a_bits != 16) {
+ tc_error("Invalid bits argument for"
+ " -e/--import_afmt");
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_BITS;
+ /* fall through */
+ case 1:
+ if (vob->a_rate <= 0 || vob->a_rate > RATE) {
+ tc_error("Invalid rate argument for"
+ " -e/--import_afmt");
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_RATE;
+ break;
+ default:
+ tc_error("Invalid argument for -e/--import_afmt");
+ break;
+ }
+)
+TC_OPTION(import_codec, 'n', "0xNN",
+ "import audio codec ID [0x2000]",
+ vob->a_codec_flag = strtol(optarg, &optarg, 16);
+ if (*optarg) {
+ tc_error("Invalid argument for -n/--import_format");
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_ACODEC;
+)
+TC_OPTION(no_audio_adjust, 0, 0,
+ "disable audio frame size adjustment [enabled]",
+ no_audio_adjust = TC_TRUE;
+)
+
+/********/ TC_HEADER("Output stream format options") /********/
+
+TC_OPTION(export_prof, 0, "profile",
+ "export profile: {vcd|svcd|xvcd|dvd}[-pal|-ntsc|-secam]"
+ " [none]",
+ if (strncasecmp(optarg, "vcd", 3) == 0) {
+ vob->mpeg_profile = VCD; // need to guess NTSC/PAL later
+ if (strncasecmp(optarg, "vcd-pal", 7) == 0) {
+ vob->mpeg_profile = VCD_PAL;
+ } else if (strncasecmp(optarg, "vcd-ntsc", 8) == 0) {
+ vob->mpeg_profile = VCD_NTSC;
+ } else if (strncasecmp(optarg, "vcd-secam", 9) == 0) {
+ vob->mpeg_profile = VCD_PAL;
+ }
+ } else if (strncasecmp(optarg, "svcd", 4) == 0) {
+ vob->mpeg_profile = SVCD;
+ if (strncasecmp(optarg, "svcd-pal", 8) == 0) {
+ vob->mpeg_profile = SVCD_PAL;
+ } else if (strncasecmp(optarg, "svcd-ntsc", 9) == 0) {
+ vob->mpeg_profile = SVCD_NTSC;
+ } else if (strncasecmp(optarg, "svcd-secam", 10) == 0) {
+ vob->mpeg_profile = SVCD_PAL;
+ }
+ } else if (strncasecmp(optarg, "dvd", 3) == 0) {
+ vob->mpeg_profile = DVD;
+ if (strncasecmp(optarg, "dvd-pal", 7) == 0) {
+ vob->mpeg_profile = DVD_PAL;
+ } else if (strncasecmp(optarg, "dvd-ntsc", 8) == 0) {
+ vob->mpeg_profile = DVD_NTSC;
+ } else if (strncasecmp(optarg, "dvd-secam", 9) == 0) {
+ vob->mpeg_profile = DVD_PAL;
+ }
+ } else if (strncasecmp(optarg, "xvcd", 4) == 0) {
+ vob->mpeg_profile = XVCD;
+ if (strncasecmp(optarg, "xvcd-pal", 8) == 0) {
+ vob->mpeg_profile = XVCD_PAL;
+ } else if (strncasecmp(optarg, "xvcd-ntsc", 9) == 0) {
+ vob->mpeg_profile = XVCD_NTSC;
+ } else if (strncasecmp(optarg, "xvcd-secam", 10) == 0) {
+ vob->mpeg_profile = XVCD_PAL;
+ }
+ } else {
+ tc_error("Invalid argument for --export_prof");
+ }
+)
+TC_OPTION(export_with, 'y', "vm[,am[,mm]]",
+ "video[,audio[,mplex]] export modules [null]",
+ static char vbuf[1001];
+ static char abuf[1001];
+ static char mbuf[1001];
+ char *s;
+ int n;
+ /* FIXME: handle embedded quotes like -x? */
+ if ((n = sscanf(optarg, "%1000[^,],%1000[^,],%1000[^,]",
+ vbuf, abuf, mbuf)) < 1
+ ) {
+ tc_error("Invalid argument for -y/--export_with");
+ goto short_usage;
+ }
+ ex_vid_mod = vbuf;
+ no_v_out_codec = 0;
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_VMODULE;
+ if ((s = strchr(ex_vid_mod, '=')) != NULL) {
+ *s++ = 0;
+ if (!*s) {
+ tc_error("Invalid option string for video export"
+ " module");
+ goto short_usage;
+ }
+ vob->ex_v_string = s;
+ }
+ if (n >= 2) {
+ ex_aud_mod = abuf;
+ no_a_out_codec = 0;
+ if ((s = strchr(ex_aud_mod, '=')) != NULL) {
+ *s++ = 0;
+ if (!*s) {
+ tc_error("Invalid option string for audio export"
+ " module");
+ goto short_usage;
+ }
+ vob->ex_a_string = s;
+ }
+ } else {
+ ex_aud_mod = ex_vid_mod;
+ }
+ if (n >= 3) {
+ ex_mplex_mod = mbuf;
+ if ((s = strchr(ex_mplex_mod, '=')) != NULL) {
+ *s++ = 0;
+ if (!*s) {
+ tc_error("Invalid option string for multiplex"
+ " module");
+ goto short_usage;
+ }
+ vob->ex_m_string = s;
+ }
+ }
+)
+TC_OPTION(export_param, 'F', "string",
+ "encoder parameter strings [module dependent]",
+ char *s;
+ if ((s = strchr(optarg, ',')) != NULL) {
+ char *s2;
+ *s = 0;
+ vob->ex_a_fcc = s+1;
+ if ((s2 = strchr(vob->ex_a_fcc,',')) != NULL) {
+ *s2 = 0;
+ vob->ex_profile_name = s2+1;
+ }
+ }
+ vob->ex_v_fcc = optarg;
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_VCODEC;
+)
+TC_OPTION(export_codec, 'N', "format",
+ "export audio codec [mp3]",
+ if (*optarg == '-')
+ goto short_usage;
+ if (optarg[0] == '0' && optarg[1] == 'x') {
+ /* old behaviour */
+ vob->ex_a_codec = strtol(optarg, &optarg, 16);
+ if (*optarg) {
+ tc_error("Invalid argument for -N/--export_format");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_ACODEC;
+ } else {
+ char acodec[33];
+ char vcodec[33];
+ int n;
+ /* new behaviour */
+ n = sscanf(optarg, "%32[^,],%32[^,]", vcodec, acodec);
+ /* codecs in reversed order for backward compatibility */
+ switch (n) {
+ case 2: /* audio AND video codec */
+ vob->ex_v_codec = tc_codec_from_string(vcodec);
+ if (vob->ex_v_codec == TC_CODEC_ERROR) {
+ tc_error("Unknown video format for"
+ " -N/--export_format");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_VCODEC;
+ /* move acodec to vcodec */
+ memcpy(vcodec, acodec, sizeof(vcodec));
+ /* fallthrough */
+ case 1: /* audio codec */
+ vob->ex_a_codec = tc_codec_from_string(acodec);
+ if (vob->ex_a_codec == TC_CODEC_ERROR) {
+ tc_error("Unknown audio format for"
+ " -N/--export_format");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_ACODEC;
+ break;
+ default:
+ tc_error("Invalid argument for -N/--export_format");
+ goto short_usage;
+ }
+ }
+)
+TC_OPTION(multipass, 'R', "N[,vf[,af]]",
+ "enable multi-pass encoding (0-3) [0,divx4.log,pcm.log]",
+ static char vlogfile[1001] = "divx4.log";
+ static char alogfile[1001] = "pcm.log";
+ if (sscanf(optarg, "%d,%1000[^,],%1000[^,]",
+ &vob->divxmultipass, vlogfile, alogfile) < 1
+ || vob->divxmultipass < 0 || vob->divxmultipass > 3
+ || !*vlogfile
+ || !*alogfile
+ ) {
+ tc_error("Invalid argument for -R/--multipass");
+ goto short_usage;
+ }
+ vob->divxlogfile = vlogfile;
+ vob->audiologfile = alogfile;
+)
+TC_OPTION(vbitrate, 'w', "r[,k[,c]]",
+ "encoder bitrate[,keyframes[,crispness]] [1800,250,100]",
+ float ratefact = 1.0f;
+ int n = sscanf(optarg, "%f,%d,%d", &ratefact,
+ &vob->divxkeyframes, &vob->divxcrispness);
+ switch (n) {
+ case 3:
+ if (vob->divxcrispness < 0 || vob->divxcrispness > 100) {
+ tc_error("Invalid crispness argument for"
+ " -w/--vbitrate");
+ goto short_usage;
+ }
+ case 2:
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_GOP;
+ case 1:
+ if (vob->divxbitrate <= 0) {
+ tc_error("Invalid bitrate argument for"
+ " -w/--vbitrate");
+ goto short_usage;
+ }
+ vob->divxbitrate = (int)ratefact;
+ vob->m2v_requant = ratefact;
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_VBITRATE;
+ break;
+ default:
+ tc_error("Invalid argument for -w/--vbitrate");
+ goto short_usage;
+ }
+)
+TC_OPTION(video_max_bitrate, 0, "r",
+ "maximum bitrate when encoding variable bitrate MPEG-2"
+ " streams [same as -w]",
+ vob->video_max_bitrate = strtol(optarg, &optarg, 10);
+ if (*optarg || vob->video_max_bitrate < 0) {
+ tc_error("Invalid argument for --video_max_bitrate");
+ goto short_usage;
+ }
+)
+TC_OPTION(export_fps, 0, "f[,c]",
+ "output video frame rate[,code] [as input]",
+ int n = sscanf(optarg, "%lf,%d", &vob->ex_fps, &vob->ex_frc);
+ if (n < 1 || n > 2) {
+ tc_error("Invalid argument for --export_fps");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_FPS;
+ if (n == 2) {
+ if (vob->ex_frc < 0 || vob->ex_frc > 15) {
+ tc_error("Invalid frc value for --export_fps");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_FRC;
+ tc_frc_code_to_value(vob->ex_frc, &vob->ex_fps);
+ } else {
+ if (vob->ex_fps < MIN_FPS) {
+ tc_error("Invalid fps value for --export_fps");
+ goto short_usage;
+ }
+ vob->ex_frc = 0;
+ }
+)
+TC_OPTION(export_frc, 0, "C",
+ "set export frame rate code C independently of actual"
+ " frame rate [derived from export FPS]",
+ vob->ex_frc = strtol(optarg, &optarg, 10);
+ if (*optarg || vob->ex_frc < 0 || vob->ex_frc > 15) {
+ tc_error("Invalid frc value for --export_frc");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_FRC;
+)
+TC_OPTION(export_asr, 0, "C",
+ "set export display aspect ratio code C [as input]",
+ vob->ex_asr = strtol(optarg, &optarg, 10);
+ if (*optarg || vob->ex_asr < 0 || vob->ex_asr > 4) {
+ tc_error("Invalid argument for --export_asr");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_ASR;
+)
+TC_OPTION(export_par, 0, "{C | N,D}",
+ "set export pixel aspect ratio [auto]",
+ int n = sscanf(optarg, "%d,%d", &vob->ex_par_width,
+ &vob->ex_par_height);
+ if (n == 1) {
+ /* Only one argument: PAR code */
+ vob->ex_par = vob->ex_par_width;
+ if (vob->ex_par < 0 || vob->ex_par > 5) {
+ tc_error("--export_par must be between 0 and 5");
+ goto short_usage;
+ }
+ tc_par_code_to_ratio(vob->ex_par,
+ &vob->ex_par_width,
+ &vob->ex_par_height);
+ } else if (n == 2) {
+ /* Two arguments: use nonstandard PAR */
+ vob->ex_par = 0;
+ if (vob->ex_par_width <= 0 || vob->ex_par_height <= 0) {
+ tc_error("bad PAR values for --export_par:"
+ " %d/%d not [>0]/[>0]",
+ vob->ex_par_width, vob->ex_par_height);
+ goto short_usage;
+ }
+ /* correct common misbehaviour */
+ if (vob->ex_par_width == 1 && vob->ex_par_height == 1) {
+ vob->ex_par = 1;
+ tc_info("given PAR values of 1/1, reset PAR code"
+ " to 1");
+ }
+ } else {
+ /* Bad number of arguments (<1 || >2) */
+ tc_error("Invalid argument for --export_par");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_PAR;
+)
+TC_OPTION(encode_fields, 0, "C",
+ "enable field-based encoding if supported [off]\n"
+ "C can be t (top-first), b (bottom-first),\n"
+ " p (progressive), u (unknown)",
+ switch (*optarg) {
+ case 't':
+ vob->encode_fields = TC_ENCODE_FIELDS_TOP_FIRST; break;
+ case 'b':
+ vob->encode_fields = TC_ENCODE_FIELDS_BOTTOM_FIRST; break;
+ case 'p':
+ vob->encode_fields = TC_ENCODE_FIELDS_PROGRESSIVE; break;
+ case 'u':
+ vob->encode_fields = TC_ENCODE_FIELDS_UNKNOWN; break;
+ default:
+ tc_error("Invalid argument for --encode_fields");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_FIELDS;
+)
+TC_OPTION(pulldown, 0, 0,
+ "set MPEG 3:2 pulldown flags on export [off]",
+ vob->pulldown = TC_TRUE;
+)
+TC_OPTION(abitrate, 'b', "r[,v[,q[,m]]]",
+ "audio encoder bitrate kBits/s[,vbr[,quality[,mode]]]"
+ " [128,0,5,0]",
+ if (sscanf(optarg, "%d,%d,%f,%d", &vob->mp3bitrate,
+ &vob->a_vbr, &vob->mp3quality, &vob->mp3mode) < 1
+ || vob->mp3bitrate < 0
+ || vob->a_vbr < 0
+ || vob->mp3quality < -1.00001
+ || vob->mp3mode < 0
+ ) {
+ tc_error("Invalid argument for -b/--abitrate");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_ABITRATE;
+)
+TC_OPTION(export_afmt, 'E', "r[,b[,c]]",
+ "audio output samplerate, bits, channels [as input]",
+ int n = sscanf(optarg, "%d,%d,%d", &vob->mp3frequency,
+ &vob->dm_bits, &vob->dm_chan);
+ switch (n) {
+ case 3:
+ if (vob->dm_chan < 0 || vob->dm_chan > 6) {
+ tc_error("Invalid channels argument for"
+ " -E/--export_afmt");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_ACHANS;
+ /* fall through */
+ case 2:
+ if (vob->dm_bits != 0
+ && vob->dm_bits != 8
+ && vob->dm_bits != 16
+ && vob->dm_bits != 24
+ ) {
+ tc_error("Invalid bits argument for -E/--export_afmt");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_ABITS;
+ /* fall through */
+ case 1:
+ if (vob->mp3frequency < 0) {
+ tc_error("Invalid rate argument for -E/--export_afmt");
+ goto short_usage;
+ }
+ vob->export_attributes |= TC_EXPORT_ATTRIBUTE_ARATE;
+ break;
+ default:
+ tc_error("Invalid argument for -E/--export_afmt");
+ break;
+ }
+)
+
+/********/ TC_HEADER("Video processing options") /********/
+
+TC_OPTION(pre_clip, 0, "t[,l[,b[,r]]]",
+ "select initial frame region by clipping [off]",
+ int n = sscanf(optarg, "%d,%d,%d,%d",
+ &vob->pre_im_clip_top,
+ &vob->pre_im_clip_left,
+ &vob->pre_im_clip_bottom,
+ &vob->pre_im_clip_right);
+ if (n < 1) {
+ tc_error("Invalid argument for --pre_clip");
+ goto short_usage;
+ }
+ pre_im_clip = TC_TRUE;
+ // Symmetrical clipping for only 1-3 arguments
+ if (n < 2)
+ vob->pre_im_clip_left = 0;
+ if (n < 3)
+ vob->pre_im_clip_bottom = vob->pre_im_clip_top;
+ if (n < 4)
+ vob->pre_im_clip_right = vob->pre_im_clip_left;
+)
+TC_OPTION(im_clip, 'j', "t[,l[,b[,r]]]",
+ "clip or add frame border before filters [off]",
+ int n = sscanf(optarg, "%d,%d,%d,%d",
+ &vob->im_clip_top,
+ &vob->im_clip_left,
+ &vob->im_clip_bottom,
+ &vob->im_clip_right);
+ if (n < 1) {
+ tc_error("Invalid argument for -j/--im_clip");
+ goto short_usage;
+ }
+ im_clip = TC_TRUE;
+ // Symmetrical clipping for only 1-3 arguments
+ if (n < 2)
+ vob->im_clip_left = 0;
+ if (n < 3)
+ vob->im_clip_bottom = vob->im_clip_top;
+ if (n < 4)
+ vob->im_clip_right = vob->im_clip_left;
+)
+TC_OPTION(deinterlace, 'I', "mode",
+ "deinterlace video using given mode (1-5) [off]",
+ vob->deinterlace = strtol(optarg, &optarg, 10);
+ if (*optarg || vob->deinterlace < 1 || vob->deinterlace > 5) {
+ tc_error("Invalid argument for -I/--deinterlace");
+ goto short_usage;
+ }
+)
+TC_OPTION(expand, 'X', "n[,m[,M]]",
+ "expand to height+n*M rows, width+m*M columns [0,0,32]",
+ vob->hori_resize2 = 0;
+ if (sscanf(optarg, "%d,%d,%d", &vob->vert_resize2,
+ &vob->hori_resize2, &vob->resize2_mult) < 1
+ ) {
+ tc_error("Invalid argument for -X/--expand");
+ goto short_usage;
+ }
+ if (vob->resize2_mult != 8
+ && vob->resize2_mult != 16
+ && vob->resize2_mult != 32
+ ) {
+ tc_error("Invalid multiplier for -X/--expand (must be"
+ " 8, 16, or 32)");
+ goto short_usage;
+ }
+ resize2 = TC_TRUE;
+)
+TC_OPTION(shrink, 'B', "n[,m[,M]]",
+ "shrink to height-n*M rows, width-m*M columns [0,0,32]",
+ vob->hori_resize1 = 0;
+ if (sscanf(optarg, "%d,%d,%d", &vob->vert_resize1,
+ &vob->hori_resize1, &vob->resize1_mult) < 1
+ ) {
+ tc_error("Invalid argument for -X/--expand");
+ goto short_usage;
+ }
+ if (vob->resize1_mult != 8
+ && vob->resize1_mult != 16
+ && vob->resize1_mult != 32
+ ) {
+ tc_error("Invalid multiplier for -B/--shrink (must be"
+ " 8, 16, or 32)");
+ goto short_usage;
+ }
+ resize1 = TC_TRUE;
+)
+TC_OPTION(zoom, 'Z', "[W]x[H][,mode]",
+ "resize to W columns, H rows w/filtering [off]",
+ char *s = optarg;
+ if (isdigit(*s)) {
+ vob->zoom_width = strtol(s, &s, 10);
+ if (vob->zoom_width > TC_MAX_V_FRAME_WIDTH) {
+ tc_error("Invalid width for -Z/--zoom (maximum %d)",
+ TC_MAX_V_FRAME_WIDTH);
+ goto short_usage;
+ }
+ } else {
+ vob->zoom_width = 0;
+ }
+ if (*s++ != 'x') {
+ tc_error("Invalid argument for -Z/--zoom");
+ goto short_usage;
+ }
+ if (isdigit(*s)) {
+ vob->zoom_height = strtol(s, &s, 10);
+ if (vob->zoom_height > TC_MAX_V_FRAME_HEIGHT) {
+ tc_error("Invalid height for -Z/--zoom (maximum %d)",
+ TC_MAX_V_FRAME_HEIGHT);
+ goto short_usage;
+ }
+ } else {
+ vob->zoom_height = 0;
+ }
+ zoom = TC_TRUE;
+ if (*s == ',') {
+ s++;
+ if (strncmp(s, "fast", strlen(s)) == 0)
+ fast_resize = TC_TRUE;
+ else if (strncmp(s, "interlaced", strlen(s)) == 0)
+ vob->zoom_interlaced = TC_TRUE;
+ }
+)
+TC_OPTION(zoom_filter, 0, "filter",
+ "use given filter for -Z resizing [Lanczos3]",
+ vob->zoom_filter = tcv_zoom_filter_from_string(optarg);
+ if (vob->zoom_filter == TCV_ZOOM_NULL) {
+ tc_error("invalid argument for --zoom_filter\n"
+ "filter must be one of:\n"
+ " bell box b_spline hermite lanczos3"
+ " mitchell triangle cubic_keys4 sinc8");
+ goto short_usage;
+ }
+)
+TC_OPTION(ex_clip, 'Y', "t[,l[,b[,r]]]",
+ "clip or add frame border after filters [off]",
+ int n = sscanf(optarg, "%d,%d,%d,%d",
+ &vob->ex_clip_top,
+ &vob->ex_clip_left,
+ &vob->ex_clip_bottom,
+ &vob->ex_clip_right);
+ if (n < 1) {
+ tc_error("Invalid argument for -Y/--ex_clip");
+ goto short_usage;
+ }
+ ex_clip = TC_TRUE;
+ // Symmetrical clipping for only 1-3 arguments
+ if (n < 2)
+ vob->ex_clip_left = 0;
+ if (n < 3)
+ vob->ex_clip_bottom = vob->ex_clip_top;
+ if (n < 4)
+ vob->ex_clip_right = vob->ex_clip_left;
+)
+TC_OPTION(reduce, 'r', "n[,m]",
+ "reduce video height/width by n[,m] [off]",
+ int n = sscanf(optarg, "%d,%d", &vob->reduce_h,&vob->reduce_w);
+ if (n == 1)
+ vob->reduce_w = vob->reduce_h;
+ if (n < 1 || vob->reduce_h <= 0 || vob->reduce_w <= 0) {
+ tc_error("Invalid argument for -r/--reduce");
+ goto short_usage;
+ }
+ rescale = TC_TRUE;
+)
+TC_OPTION(flip, 'z', 0,
+ "flip video frame upside down [off]",
+ flip = TC_TRUE;
+)
+TC_OPTION(mirror, 'l', 0,
+ "mirror video frame [off]",
+ mirror = TC_TRUE;
+)
+TC_OPTION(swap_colors, 'k', 0,
+ "swap red/blue (Cb/Cr) in video frame [off]",
+ rgbswap = TC_TRUE;
+)
+TC_OPTION(grayscale, 'K', 0,
+ "enable grayscale mode [off]",
+ decolor = TC_TRUE;
+ vob->decolor = TC_TRUE;
+)
+TC_OPTION(gamma, 'G', "val",
+ "gamma correction (0.0-10.0) [off]",
+ vob->gamma = strtod(optarg, &optarg);
+ if (*optarg || vob->gamma < 0) {
+ tc_error("Invalid argument for -G/--gamma");
+ goto short_usage;
+ }
+ dgamma = TC_TRUE;
+)
+TC_OPTION(antialias, 'C', "mode",
+ "enable anti-aliasing mode (1-3) [off]",
+ vob->antialias = strtol(optarg, &optarg, 10);
+ if (*optarg || vob->antialias < 1 || vob->antialias > 3) {
+ tc_error("Invalid argument for -C/--antialias");
+ goto short_usage;
+ }
+)
+TC_OPTION(antialias_para, 0, "w,b",
+ "center pixel weight, xy-bias [0.333,0.500]",
+ if (sscanf(optarg, "%lf,%lf",
+ &vob->aa_weight, &vob->aa_bias) != 2) {
+ tc_error("Invalid argument for --antialias_para");
+ goto short_usage;
+ }
+ if (vob->aa_weight < 0.0 || vob->aa_weight > 1.0) {
+ tc_error("Invalid weight for --antlalias_para"
+ " (0.0 <= w <= 1.0)");
+ goto short_usage;
+ }
+ if (vob->aa_bias < 0.0 || vob->aa_bias > 1.0) {
+ tc_error("Invalid bias for --antlalias_para"
+ " (0.0 <= b <= 1.0)");
+ goto short_usage;
+ }
+)
+TC_OPTION(post_clip, 0, "t[,l[,b[,r]]]",
+ "select final frame region by clipping [off]",
+ int n = sscanf(optarg, "%d,%d,%d,%d",
+ &vob->post_ex_clip_top,
+ &vob->post_ex_clip_left,
+ &vob->post_ex_clip_bottom,
+ &vob->post_ex_clip_right);
+ if (n < 1) {
+ tc_error("Invalid argument for --post_clip");
+ goto short_usage;
+ }
+ post_ex_clip = TC_TRUE;
+ // Symmetrical clipping for only 1-3 arguments
+ if (n < 2)
+ vob->post_ex_clip_left = 0;
+ if (n < 3)
+ vob->post_ex_clip_bottom = vob->post_ex_clip_top;
+ if (n < 4)
+ vob->post_ex_clip_right = vob->post_ex_clip_left;
+)
+TC_OPTION(video_format, 'V', "fmt",
+ "select internal video format [yuv420p]\n"
+ "one of: yuv420p, yuv422p, rgb24",
+ if (strcmp(optarg, "yuv420p") == 0) {
+ tc_info("yuv420p is already the default for -V");
+ /* anyway... */
+ vob->im_v_codec = CODEC_YUV;
+ } else if (strcmp(optarg, "yuv422p") == 0) {
+ vob->im_v_codec = CODEC_YUV422;
+ } else if (strcmp(optarg, "rgb24") == 0) {
+ vob->im_v_codec = CODEC_RGB;
+ } else {
+ tc_error("bad argument for -V/--video_format, should"
+ " be one of: yuv420p (default), yuv422p, rgb24");
+ goto short_usage;
+ }
+)
+TC_OPTION(keep_asr, 0, 0,
+ "try to keep aspect ratio (broken)",
+ tc_error("--keep_asr is unavailable, calculate frame"
+ " parameters manually");
+)
+
+/********/ TC_HEADER("Audio processing options") /********/
+
+TC_OPTION(audio_swap, 'd', 0,
+ "swap bytes in audio stream [off]",
+ pcmswap = TC_TRUE;
+)
+TC_OPTION(audio_scale, 's', "g[,c,f,r]",
+ "scale volume by gain[,center,front,rear] [1,1,1,1]",
+ vob->ac3_gain[0] = 1.0;
+ vob->ac3_gain[1] = 1.0;
+ vob->ac3_gain[2] = 1.0;
+ if (sscanf(optarg, "%lf,%lf,%lf,%lf", &vob->volume,
+ &vob->ac3_gain[0], &vob->ac3_gain[1],
+ &vob->ac3_gain[2]) < 1
+ || vob->volume < 0
+ ) {
+ tc_error("Invalid argument for -s/--audio_scale");
+ goto short_usage;
+ }
+)
+TC_OPTION(audio_use_ac3, 'A', 0,
+ "use AC3 as internal audio codec [off]",
+ vob->im_a_codec = CODEC_AC3;
+)
+
+/********/ TC_HEADER("Other processing options") /********/
+
+TC_OPTION(filter, 'J', "f1[,f2...]",
+ "apply external audio/video filters [none]",
+ static int size_plugstr = 0;
+ int newlen;
+ if (*optarg == '-')
+ goto short_usage;
+ newlen = size_plugstr + strlen(optarg) + 1; // \0
+ if (size_plugstr) // it's an append...
+ newlen++; // ... so add the and ',' separator
+ plugins_string = tc_realloc(plugins_string, newlen);
+ if (!plugins_string)
+ return 0;
+ snprintf(plugins_string + size_plugstr,
+ newlen - size_plugstr,
+ "%s%s", size_plugstr ? "," : "", optarg);
+ size_plugstr = newlen - 1;
+ // cut the \0 for the next append (if any)
+)
+TC_OPTION(quality, 'Q', "enc[,dec]",
+ "encoding[,decoding] quality (0=fastest-5=best) [5,5]",
+ if (sscanf(optarg,"%d,%d",&vob->divxquality,&vob->quality) < 1
+ || vob->divxquality < 0
+ || vob->quality < 0
+ ) {
+ tc_error("Invalid argument for -Q/--quality");
+ goto short_usage;
+ }
+)
+TC_OPTION(passthrough, 'P', "flag",
+ "pass-through flag (0=off|1=V|2=A|3=A+V) [0]",
+ vob->pass_flag = strtol(optarg, &optarg, 10);
+ if (*optarg || vob->pass_flag < 0 || vob->pass_flag > 3) {
+ tc_error("Invalid argument for -P/--passthrough");
+ goto short_usage;
+ }
+)
+TC_OPTION(sync_frame, 'D', "N",
+ "sync video start with audio frame num [0]",
+ vob->sync = strtol(optarg, &optarg, 10);
+ if (*optarg) {
+ tc_error("Invalid argument for -D/--sync_frame");
+ goto short_usage;
+ }
+ sync_seconds = vob->sync;
+ preset_flag |= TC_PROBE_NO_AVSHIFT;
+)
+TC_OPTION(av_fine_ms, 0, "time",
+ "AV fine-tuning shift in millisecs [autodetect]",
+ vob->sync_ms = strtol(optarg, &optarg, 10);
+ if (*optarg) {
+ tc_error("Invalid argument for --av_sync_ms");
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_AV_FINE;
+)
+TC_OPTION(demuxer_sync, 'M', "N",
+ "demuxer PES AV sync mode\n"
+ "(0=off|1=PTS only|2=full) [1]",
+ vob->demuxer = strtol(optarg, &optarg, 10);
+ if (*optarg || vob->demuxer < 0 || vob->demuxer > 4) {
+ tc_error("Invalid argument for -M/--demuxer_sync");
+ goto short_usage;
+ }
+ preset_flag |= TC_PROBE_NO_DEMUX;
+)
+
+/********/ TC_HEADER("Codec-specific options") /********/
+
+TC_OPTION(dv_yv12_mode, 0, 0,
+ "(libdv) force YV12 mode for PAL\n"
+ "Use this option if transcode autodetection fails,"
+ " with DV video.",
+ vob->dv_yuy2_mode = TC_FALSE;
+)
+TC_OPTION(dv_yuy2_mode, 0, 0,
+ "(libdv) use YUY2 mode for PAL [YV12]\n"
+ "If you experience crashes decoding DV video,"
+ " try this option.",
+ vob->dv_yuy2_mode = TC_TRUE;
+)
+TC_OPTION(quantizers, 0, "min,max",
+ "min/max quantizer, for MPEG-like codecs [2,31]",
+ if (sscanf(optarg, "%d,%d", &vob->min_quantizer,
+ &vob->max_quantizer) != 2
+ || vob->min_quantizer < 1 || vob->min_quantizer > 31
+ || vob->max_quantizer < 1 || vob->max_quantizer > 31
+ ) {
+ tc_error("Invalid argument for --quantizers");
+ goto short_usage;
+ }
+)
+TC_OPTION(divx_quant, 0, "min,max",
+ "(DivX) min/max quantizer (deprecated) [2,31]",
+ tc_warn("--divx_quant option is deprecated and will be removed soon.");
+ tc_warn("use --quantizers instead.");
+ if (sscanf(optarg, "%d,%d", &vob->min_quantizer,
+ &vob->max_quantizer) != 2
+ || vob->min_quantizer < 1 || vob->min_quantizer > 31
+ || vob->max_quantizer < 1 || vob->max_quantizer > 31
+ ) {
+ tc_error("Invalid argument for --divx_quant");
+ goto short_usage;
+ }
+)
+TC_OPTION(divx_rc, 0, "p,rp,rr",
+ "(DivX) rate control parameter [2000,10,20]",
+ if (sscanf(optarg, "%d,%d,%d", &vob->rc_period,
+ &vob->rc_reaction_period,
+ &vob->rc_reaction_ratio) != 3
+ ) {
+ tc_error("Invalid argument for --divx_rc");
+ goto short_usage;
+ }
+)
+TC_OPTION(divx_vbv_prof, 0, "N",
+ "(DivX) VBV profile (0=free-5=hiqhq) [3]",
+ vob->divx5_vbv_prof = strtol(optarg, &optarg, 10);
+ if (*optarg
+ || vob->divx5_vbv_prof < 0
+ || vob->divx5_vbv_prof > 5
+ ) {
+ tc_error("Invalid argument for --divx_vbv_prof");
+ goto short_usage;
+ }
+)
+TC_OPTION(divx_vbv, 0, "br,sz,oc",
+ "(DivX) VBV params (bitrate,size,occupancy) [10000,192,36864]",
+ if (sscanf(optarg, "%d,%d,%d", &vob->divx5_vbv_bitrate,
+ &vob->divx5_vbv_size,
+ &vob->divx5_vbv_occupancy) != 3
+ ) {
+ tc_error("Invalid argument for --divx_vbv");
+ goto short_usage;
+ }
+)
+TC_OPTION(lame_preset, 0, "N[,fast]",
+ "(LAME) use preset named N [off]",
+ if (*optarg == '-')
+ goto short_usage;
+ vob->lame_preset = optarg;
+)
+TC_OPTION(no_bitreservoir, 0, 0,
+ "(LAME) disable bitreservoir [off]",
+ vob->bitreservoir = TC_FALSE;
+)
+TC_OPTION(encoder_noflush, 'O', 0,
+ "avoid to flush buffer(s) on encoder stop [enabled]",
+ vob->encoder_flush = TC_FALSE;
+)
+TC_OPTION(a52_demux, 0, 0,
+ "(liba52) demux AC3/A52 to separate channels [off]",
+ vob->a52_mode |= TC_A52_DEMUX;
+)
+TC_OPTION(a52_drc_off, 0, 0,
+ "(liba52) disable dynamic range compression [enabled]",
+ vob->a52_mode |= TC_A52_DRC_OFF;
+)
+TC_OPTION(a52_dolby_off, 0, 0,
+ "(liba52) disable Dolby surround [enabled]",
+ vob->a52_mode |= TC_A52_DOLBY_OFF;
+)
+
+/********/ TC_HEADER("Cluster/PSU/chapter mode processing") /********/
+
+TC_OPTION(autosplit, 'W', "n,m[,file]",
+ "autosplit VOB and process part n of m [off]",
+ static char vob_logfile[1001] = "";
+ if (sscanf(optarg, "%d,%d,%1000[^,]", &vob->vob_chunk,
+ &vob->vob_chunk_max, vob_logfile) < 2
+ || vob->vob_chunk < 0
+ || vob->vob_chunk_max <= 0
+ || vob->vob_chunk >= vob->vob_chunk_max + 1
+ ) {
+ tc_error("Invalid parameter for -W/--autosplit");
+ goto short_usage;
+ }
+ if (*vob_logfile)
+ vob->vob_info_file = vob_logfile;
+ tc_cluster_mode = TC_TRUE;
+)
+TC_OPTION(cluster_percentage, 0, 0,
+ "use percentage mode for cluster encoding [off]",
+ vob->vob_percentage = TC_TRUE;
+)
+TC_OPTION(cluster_chunks, 0, "a-b",
+ "process chunk range instead of selected chunk [off]",
+ if (sscanf(optarg,"%d-%d",
+ &vob->vob_chunk_num1, &vob->vob_chunk_num2) != 2
+ || vob->vob_chunk_num1 < 0
+ || vob->vob_chunk_num2 <= 0
+ || vob->vob_chunk_num1 >= vob->vob_chunk_num2
+ ) {
+ tc_error("invalid parameter for --cluster_chunks");
+ goto short_usage;
+ }
+)
+TC_OPTION(psu_mode, 0, 0,
+ "process VOB in PSU, -o is a filemask incl. %d [off]",
+ psu_mode = TC_TRUE;
+ core_mode = TC_MODE_PSU;
+ tc_cluster_mode = TC_TRUE;
+)
+TC_OPTION(psu_chunks, 0, "a-b",
+ "process only units a-b for PSU mode [all]",
+ if (sscanf(optarg, "%d-%d,%d",
+ &vob->vob_psu_num1, &vob->vob_psu_num2,
+ &psu_frame_threshold) < 2
+ || vob->vob_psu_num1 < 0
+ || vob->vob_psu_num2 <= 0
+ || vob->vob_psu_num1 >= vob->vob_psu_num2
+ ) {
+ tc_error("Invalid parameter for --psu_chunks");
+ goto short_usage;
+ }
+)
+TC_OPTION(no_split, 0, 0,
+ "encode to single file in chapter/psu mode [off]",
+ no_split = TC_TRUE;
+)
+TC_OPTION(chapter_mode, 'U', "base",
+ "process DVD in chapter mode to base-ch%02d.avi [off]",
+ if (*optarg == '-')
+ goto short_usage;
+ chbase = optarg;
+ core_mode = TC_MODE_DVD_CHAPTER;
+)
+
+/********/ TC_HEADER("Miscellaneous options") /********/
+
+#ifdef TC_OPTIONS_TO_HELP
+/* produce ONLY help messages since this option require special tratment */
+TC_OPTION(log_no_color, 0, 0,
+ "disable colors in log messages [use colors]",
+ ; /* nothing */
+)
+#endif /* TC_OPTIONS_TO_HELP */
+
+TC_OPTION(buffers, 'u', "N",
+ "use N framebuffers for AV processing [10]",
+ /* FIXME: threads ought to be a separate option */
+ int threads_dummy = 0;
+ if (sscanf(optarg, "%d,%d,%d,%d", &max_frame_buffer,
+ &threads_dummy, &tc_buffer_delay_dec,
+ &tc_buffer_delay_enc) < 1
+ || max_frame_buffer < 0
+ ) {
+ tc_error("Invalid argument for -u/--buffers");
+ goto short_usage;
+ }
+ if (threads_dummy != 0 && threads_dummy != max_frame_threads) {
+ tc_warn("Use --threads to specify number of threads,"
+ " not -u");
+ /* FIXME: deprecated in 1.1.0, remove later */
+ max_frame_threads = threads_dummy;
+ }
+ preset_flag |= TC_PROBE_NO_BUFFER;
+)
+TC_OPTION(threads, 0, "N",
+ "use N threads for AV processing [1]",
+ max_frame_threads = strtol(optarg, &optarg, 10);
+ if (*optarg
+ || max_frame_threads < 0
+ || max_frame_threads > TC_FRAME_THREADS_MAX
+ ) {
+ tc_error("Invalid argument for -u/--threads");
+ goto short_usage;
+ }
+)
+TC_OPTION(progress_meter, 0, "N",
+ "select type of progress meter [1]",
+ tc_progress_meter = strtol(optarg, &optarg, 0);
+ if (*optarg || tc_progress_meter < 0) {
+ tc_error("Invalid argument for --progress_meter");
+ goto short_usage;
+ }
+)
+TC_OPTION(progress_rate, 0, "N",
+ "print progress every N frames [1]",
+ tc_progress_rate = strtol(optarg, &optarg, 0);
+ if (*optarg || tc_progress_rate <= 0) {
+ tc_error("Invalid argument for --progress_rate");
+ goto short_usage;
+ }
+)
+TC_OPTION(nice, 0, "N",
+ "set niceness to N [off]",
+ tc_niceness = strtol(optarg, &optarg, 0);
+ if (*optarg) {
+ tc_error("Invalid argument for --nice");
+ goto short_usage;
+ }
+)
+TC_OPTION(accel, 0, "type[,type...]",
+ "override CPU acceleration flags (for debugging)",
+#if defined(ARCH_X86) || defined(ARCH_X86_64)
+ int parsed = ac_parseflags(optarg, &tc_accel);
+ if (!parsed) {
+ tc_error("bad --accel type, valid types: C %s",
+ ac_flagstotext(AC_ALL));
+ goto short_usage;
+ }
+#else
+ /* Not supported--leave a statement in so the macro doesn't
+ * complain about a missing argument */
+ break;
+#endif
+)
+#if 0
+TC_OPTION(debug, 0, 0,
+ "enable debugging mode [disabled]",
+ core_mode = TC_MODE_DEBUG;
+)
+#endif
+
+/*************************************************************************/
+
+/* Output trailer code, if any. */
+#ifdef _TCO_FINI
+_TCO_FINI
+#endif
+
+/* Undefine the macros we defined above. */
+
+#undef TC_OPTION
+#undef TC_HEADER
+#undef _TCO_INIT
+#undef _TCO_FINI
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/counter.c b/debian/transcode/transcode-1.1.7/src/counter.c
new file mode 100644
index 00000000..3d9a60cd
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/counter.c
@@ -0,0 +1,365 @@
+/*
+ * counter.c - transcode progress counter routines
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "transcode.h"
+#include "counter.h"
+#include "frame_threads.h"
+#include <math.h>
+
+/*************************************************************************/
+
+static int counter_active = 0; /* Is the counter active? */
+static int frames_to_encode = 0; /* Total number of frames to encode */
+static int encoded_frames = 0; /* Number of frames encoded so far */
+static double encoded_time = 0; /* Time spent encoding so far */
+static int frames_to_skip = 0; /* Total number of frames to skip */
+static int skipped_frames = 0; /* Number of frames skipped so far */
+static double skipped_time = 0; /* Time spent skipping so far */
+static int highest_frame = 0; /* Highest frame number to be seen */
+
+static int printed = 0; /* Have we printed a line? */
+
+static void print_counter_line(int encoding, int frame, int first, int last,
+ double fps, double done, double timestamp,
+ int secleft, int decodebuf[2], int filterbuf[2],
+ int encodebuf[2]);
+
+/*************************************************************************/
+/*************************************************************************/
+
+/**
+ * counter_on: Activate the counter display.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+void counter_on(void)
+{
+ counter_active = 1;
+}
+
+/*************************************************************************/
+
+/**
+ * counter_off: Deactivate the counter display.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ * Side effects:
+ * When in human-readable mode (tc_progress_meter == 1), if the counter
+ * has been displayed at least once, a newline is written to standard
+ * output.
+ */
+
+void counter_off(void)
+{
+ if (printed) {
+ if (tc_progress_meter == 1)
+ fprintf(stderr, "\n");
+ printed = 0;
+ }
+ counter_active = 0;
+}
+
+/*************************************************************************/
+
+/**
+ * counter_add_range: Add the given range of frames to the total number of
+ * frames to be encoded or skipped.
+ *
+ * Parameters:
+ * first: First frame of range.
+ * last: Last frame of range.
+ * encode: True (nonzero) if frames are to be encoded.
+ * False (zero) if frames are being skipped.
+ * Return value:
+ * None.
+ */
+
+void counter_add_range(int first, int last, int encode)
+{
+ if (encode) {
+ frames_to_encode += last+1 - first;
+ } else {
+ frames_to_skip += last+1 - first;
+ }
+ if (last > highest_frame)
+ highest_frame = last;
+}
+
+/*************************************************************************/
+
+/**
+ * counter_reset_ranges: Reset the counter's stored range data.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+void counter_reset_ranges(void)
+{
+ frames_to_encode = 0;
+ encoded_frames = 0;
+ encoded_time = 0;
+ frames_to_skip = 0;
+ skipped_frames = 0;
+ skipped_time = 0;
+ highest_frame = 0;
+}
+
+/*************************************************************************/
+
+/**
+ * counter_print: Display the progress counter, if active.
+ *
+ * Parameters:
+ * encoding: True (nonzero) if frames are being encoded.
+ * False (zero) if frames are being skipped.
+ * frame: Current frame being encoded or skipped.
+ * first: First frame of current range.
+ * last: Last frame of current range, -1 if unknown.
+ * Return value:
+ * None.
+ */
+
+void counter_print(int encoding, int frame, int first, int last)
+{
+ vob_t *vob = tc_get_vob();
+ struct timeval tv;
+ struct timezone dummy_tz = {0,0};
+ double now, timediff, fps, time;
+ int buf_im[2], buf_fl[2], buf_ex[2];
+ /* Values of 'first' and `last' during last call (-1 = not called yet) */
+ static int old_first = -1, old_last = -1;
+ /* Time of first call for this range */
+ static double start_time = 0;
+ /* Time of last call */
+ static double old_time = 0;
+
+ if (!tc_progress_meter
+ || !tc_progress_rate
+ || !counter_active
+ || frame % tc_progress_rate != 0
+ ) {
+ return;
+ }
+ if (frame < 0 || first < 0) {
+ static int warned = 0;
+ if (!warned) {
+ tc_log_warn(__FILE__, "invalid arguments to counter_print"
+ " (%d,%d,%d,%d)", encoding, frame, first, last);
+ warned = 1;
+ }
+ return;
+ }
+
+#ifdef HAVE_GETTIMEOFDAY
+ if (gettimeofday(&tv, &dummy_tz) != 0) {
+ static int warned = 0;
+ if (!warned) {
+ tc_log_warn(__FILE__, "gettimeofday() failed!");
+ warned = 1;
+ }
+ return;
+ }
+ now = tv.tv_sec + (double)tv.tv_usec/1000000.0;
+#else
+ now = time(NULL);
+#endif
+
+ timediff = now - old_time;
+ old_time = now;
+ if (old_first != first || old_last != last) {
+ /* In human-readable mode, start a new counter line for each range
+ * if we don't know the total number of frames to be encoded. */
+ if (tc_progress_meter == 1 && old_first != -1 && frames_to_encode == 0)
+ fprintf(stderr, "\n");
+ start_time = now;
+ old_first = first;
+ old_last = last;
+ /* We decrement the frame counts here to compensate for this frame
+ * which took an unknown amount of time to complete. */
+ if (encoding && frames_to_encode > 0)
+ frames_to_encode--;
+ else if (!encoding && frames_to_skip > 0)
+ frames_to_skip--;
+ return;
+ }
+
+ /* Note that we don't add 1 to the numerator here, since start_time is
+ * the time we were called for the first frame, so frame first+1 is one
+ * one frame later than start_time, not two. */
+ if (now > start_time) {
+ fps = (frame - first) / (now - start_time);
+ } else {
+ /* No time has passed (maybe we don't have gettimeofday()) */
+ fps = 0;
+ }
+
+ vframe_get_counters(&buf_im[0], &buf_fl[0], &buf_ex[0]);
+ aframe_get_counters(&buf_im[1], &buf_fl[1], &buf_ex[1]);
+
+ time = (double)frame / ((vob->ex_fps<1.0) ? 1.0 : vob->ex_fps);
+
+ if (last == -1) {
+ /* Can't calculate ETA, just display current timestamp */
+ print_counter_line(encoding, frame, first, -1, fps, -1, time, -1,
+ buf_im, buf_fl, buf_ex);
+
+ } else if (frames_to_encode == 0) {
+ /* Total number of frames unknown, just display for current range */
+ double done = (double)(frame - first + 1) / (double)(last+1 - first);
+ int secleft = fps>0 ? ((last+1)-frame) / fps : -1;
+ print_counter_line(encoding, frame, first, last, fps, done, time,
+ secleft, buf_im, buf_fl, buf_ex);
+
+ } else {
+ /* Estimate time remaining for entire run */
+ double done;
+ int secleft;
+ if (encoding) {
+ encoded_frames++;
+ encoded_time += timediff;
+ } else {
+ skipped_frames++;
+ skipped_time += timediff;
+ }
+ if (encoded_frames > frames_to_encode)
+ frames_to_encode = encoded_frames;
+ if (skipped_frames > frames_to_skip)
+ frames_to_skip = skipped_frames;
+ if (encoded_frames == 0) {
+ /* We don't know how long it will take to encode frames; avoid
+ * understating the ETA, and just say we don't know */
+ secleft = -1;
+ } else {
+ double encode_fps, skip_fps, total_time;
+ /* Find the processing speed for encoding and skipping */
+ encode_fps = encoded_time ? encoded_frames / encoded_time : 0;
+ if (skipped_frames > 0 && skipped_time > 0) {
+ skip_fps = skipped_frames / skipped_time;
+ } else {
+ /* Just assume the same FPS for skipping as for encoding.
+ * Overstating the ETA isn't as bad as understating it, and
+ * certainly better than giving the user "unknown" for an
+ * entire encoding range. */
+ skip_fps = encode_fps;
+ }
+ if (encode_fps > 0) {
+ /* Estimate the total processing time required */
+ total_time = (frames_to_encode / encode_fps)
+ + (frames_to_skip / skip_fps);
+ /* Determine time left (round up) */
+ secleft = ceil(total_time - (encoded_time + skipped_time));
+ } else {
+ total_time = -1;
+ secleft = -1;
+ }
+ /* Use the proper overall FPS in the status line */
+ fps = encoding ? encode_fps : skip_fps;
+ }
+ /* Just use the frame ratio for completion percentage */
+ done = (double)(encoded_frames + skipped_frames)
+ / (double)(frames_to_encode + frames_to_skip);
+ print_counter_line(encoding, frame, 0, highest_frame, fps, done,
+ time, secleft, buf_im, buf_fl, buf_ex);
+ }
+
+ fflush(stdout);
+}
+
+/*************************************************************************/
+
+/**
+ * print_counter_line: Helper function to format display arguments into a
+ * progress counter line depending on settings.
+ *
+ * Parameters:
+ * encoding: True (nonzero) if frames are being encoded.
+ * False (zero) if frames are being skipped.
+ * frame: Current frame being encoded or skipped.
+ * first: First frame of current range.
+ * last: Last frame of current range, -1 if unknown.
+ * fps: Estimated frames processed per second.
+ * done: Completion ratio (0..1), -1 if unknown.
+ * timestamp: Timestamp of current frame, in seconds.
+ * secleft: Estimated time remaining to completion, in seconds (-1 if
+ * unknown).
+ * decodebuf: Number of buffered frames awaiting decoding [V, A].
+ * filterbuf: Number of buffered frames awaiting filtering [V, A].
+ * encodebuf: Number of buffered frames awaiting encoding [V, A].
+ * Return value:
+ * None.
+ */
+
+static void print_counter_line(int encoding, int frame, int first, int last,
+ double fps, double done, double timestamp,
+ int secleft,
+ int decodebuf[2], int filterbuf[2], int encodebuf[2])
+{
+ if (tc_progress_meter == 2) {
+ /* Raw data format */
+ printf("encoding=%d frame=%d first=%d last=%d fps=%.3f done=%.6f"
+ " timestamp=%.3f timeleft=%d decodebuf=%d filterbuf=%d"
+ " encodebuf=%d\n",
+ encoding, frame, first, last, fps, done,
+ timestamp, secleft, decodebuf[0] + decodebuf[1],
+ filterbuf[0] + filterbuf[1], encodebuf[0] + encodebuf[1]);
+ } else if (last < 0 || done < 0 || secleft < 0) {
+ int timeint = floor(timestamp);
+ fprintf(stderr, "%s frames [%d-%d], %6.2f fps, CFT: %d:%02d:%02d,"
+ " (%2d,%2d|%2d,%2d|%2d,%2d) \r",
+ encoding ? "encoding" : "skipping",
+ first, frame,
+ fps,
+ timeint/3600, (timeint/60) % 60, timeint % 60,
+ decodebuf[0], decodebuf[1], filterbuf[0], filterbuf[1],
+ encodebuf[0], encodebuf[1]
+ );
+ } else {
+ char eta_buf[100];
+ if (secleft < 0) {
+ snprintf(eta_buf, sizeof(eta_buf), "--:--:--");
+ } else {
+ snprintf(eta_buf, sizeof(eta_buf), "%d:%02d:%02d",
+ secleft/3600, (secleft/60) % 60, secleft % 60);
+ }
+ fprintf(stderr, "%s frame [%d/%d], %6.2f fps, %5.1f%%, ETA: %s,"
+ " (%2d,%2d|%2d,%2d|%2d,%2d) \r",
+ encoding ? "encoding" : "skipping",
+ frame, last+1,
+ fps,
+ 100*done,
+ eta_buf,
+ decodebuf[0], decodebuf[1], filterbuf[0], filterbuf[1],
+ encodebuf[0], encodebuf[1]
+ );
+ }
+ printed = 1;
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/counter.h b/debian/transcode/transcode-1.1.7/src/counter.h
new file mode 100644
index 00000000..15eb0156
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/counter.h
@@ -0,0 +1,33 @@
+/*
+ * counter.h
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifndef _COUNTER_H
+#define _COUNTER_H
+
+void counter_on(void);
+void counter_off(void);
+void counter_add_range(int first, int last, int encode);
+void counter_reset_ranges(void);
+void counter_print(int encoding, int frame, int first, int last);
+
+#endif
diff --git a/debian/transcode/transcode-1.1.7/src/decoder.c b/debian/transcode/transcode-1.1.7/src/decoder.c
new file mode 100644
index 00000000..b0c0d180
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/decoder.c
@@ -0,0 +1,1113 @@
+/*
+ * decoder.c -- transcode import layer module, implementation.
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ * Updated and partially rewritten by
+ * Francesco Romani - July 2007
+ *
+ * This file is part of transcode, a 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 "transcode.h"
+#include "dl_loader.h"
+#include "filter.h"
+#include "framebuffer.h"
+#include "video_trans.h"
+#include "audio_trans.h"
+#include "decoder.h"
+#include "encoder.h"
+#include "frame_threads.h"
+#include "cmdline.h"
+#include "probe.h"
+
+
+/*************************************************************************/
+
+/* anonymous since used just internally */
+enum {
+ TC_IM_THREAD_UNKNOWN = -1, /* halting cause not specified */
+ TC_IM_THREAD_DONE = 0, /* import ends as expected */
+ TC_IM_THREAD_INTERRUPT, /* external event interrupts import */
+ TC_IM_THREAD_EXT_ERROR, /* external (I/O) error */
+ TC_IM_THREAD_INT_ERROR, /* internal (core) error */
+ TC_IM_THREAD_PROBE_ERROR, /* source is incompatible */
+};
+
+
+typedef struct tcdecoderdata_ TCDecoderData;
+struct tcdecoderdata_ {
+ const char *tag; /* audio or video? used for logging */
+ FILE *fd; /* for stream import */
+ void *im_handle; /* import module handle */
+ volatile int active_flag; /* active or not? */
+ pthread_t thread_id;
+ pthread_mutex_t lock;
+};
+
+
+/*************************************************************************/
+
+static TCDecoderData video_decdata = {
+ .tag = "video",
+ .fd = NULL,
+ .im_handle = NULL,
+ .active_flag = 0,
+ .thread_id = (pthread_t)0,
+ .lock = PTHREAD_MUTEX_INITIALIZER,
+};
+
+static TCDecoderData audio_decdata = {
+ .tag = "audio",
+ .fd = NULL,
+ .im_handle = NULL,
+ .active_flag = 0,
+ .thread_id = (pthread_t)0,
+ .lock = PTHREAD_MUTEX_INITIALIZER,
+};
+
+static pthread_t tc_pthread_main = (pthread_t)0;
+static long int vframecount = 0;
+static long int aframecount = 0;
+
+
+/*************************************************************************/
+/* Old-style compatibility support functions */
+/*************************************************************************/
+
+struct modpair {
+ int codec; /* internal codec/colorspace/format */
+ int caps; /* module capabilities */
+};
+
+static const struct modpair audpairs[] = {
+ { CODEC_PCM, TC_CAP_PCM },
+ { CODEC_AC3, TC_CAP_AC3 },
+ { CODEC_RAW, TC_CAP_AUD },
+ { CODEC_NULL, TC_CAP_NONE } /* end marker, must be the last */
+};
+
+static const struct modpair vidpairs[] = {
+ { CODEC_RGB, TC_CAP_RGB },
+ { CODEC_YUV, TC_CAP_YUV },
+ { CODEC_YUV422, TC_CAP_YUV422 },
+ { CODEC_RAW_YUV, TC_CAP_VID },
+ { CODEC_RAW, TC_CAP_VID },
+ { CODEC_NULL, TC_CAP_NONE } /* end marker, must be the last */
+};
+
+
+/*
+ * check_module_caps: verifies if a module is compatible with transcode
+ * core colorspace/format settings.
+ *
+ * Parameters:
+ * param: data describing (old-style) module capabilities.
+ * codec: codec/format/colorspace requested by core.
+ * mpairs: table of formats/capabilities to be used for check.
+ * Return Value:
+ * 0: module INcompatible with core format request.
+ * !0: module can accomplish to the core format request.
+ */
+static int check_module_caps(const transfer_t *param, int codec,
+ const struct modpair *mpairs)
+{
+ int caps = 0;
+
+ if (param->flag == verbose) {
+ caps = (codec == mpairs[0].codec);
+ /* legacy: grab the first and stay */
+ } else {
+ int i = 0;
+
+ /* module returned capability flag */
+ if (verbose >= TC_DEBUG) {
+ tc_log_msg(__FILE__, "Capability flag 0x%x | 0x%x",
+ param->flag, codec);
+ }
+
+ for (i = 0; mpairs[i].codec != CODEC_NULL; i++) {
+ if (codec == mpairs[i].codec) {
+ caps = (param->flag & mpairs[i].caps);
+ break;
+ }
+ }
+ }
+ return caps;
+}
+
+/*************************************************************************/
+/* optimized block-wise fread */
+/*************************************************************************/
+
+#ifdef PIPE_BUF
+#define BLOCKSIZE PIPE_BUF /* 4096 on linux-x86 */
+#else
+#define BLOCKSIZE 4096
+#endif
+
+static int mfread(uint8_t *buf, int size, int nelem, FILE *f)
+{
+ int fd = fileno(f);
+ int n = 0, r1 = 0, r2 = 0;
+ while (n < size*nelem-BLOCKSIZE) {
+ if ( !(r1 = read (fd, &buf[n], BLOCKSIZE))) return 0;
+ n += r1;
+ }
+ while (size*nelem-n) {
+ if ( !(r2 = read (fd, &buf[n], size*nelem-n)))return 0;
+ n += r2;
+ }
+ return nelem;
+}
+
+/*************************************************************************/
+/* some macro goodies */
+/*************************************************************************/
+
+#define RETURN_IF_NULL(HANDLE, MEDIA) do { \
+ if ((HANDLE) == NULL) { \
+ tc_log_error(PACKAGE, "Loading %s import module failed", (MEDIA)); \
+ tc_log_error(PACKAGE, \
+ "Did you enable this module when you ran configure?"); \
+ return TC_ERROR; \
+ } \
+} while (0)
+
+#define RETURN_IF_NOT_SUPPORTED(CAPS, MEDIA) do { \
+ if (!(CAPS)) { \
+ tc_log_error(PACKAGE, "%s format not supported by import module", \
+ (MEDIA)); \
+ return TC_ERROR; \
+ } \
+} while (0)
+
+#define RETURN_IF_FUNCTION_FAILED(func, ...) do { \
+ int ret = func(__VA_ARGS__); \
+ if (ret != TC_OK) { \
+ return TC_ERROR; \
+ } \
+} while (0)
+
+#define RETURN_IF_REGISTRATION_FAILED(PTR, MEDIA) do { \
+ /* ok, that's pure paranoia */ \
+ if ((PTR) == NULL) { \
+ tc_log_error(__FILE__, "frame registration failed (%s)", (MEDIA)); \
+ return TC_IM_THREAD_INT_ERROR; \
+ } \
+} while (0)
+
+/*************************************************************************/
+/* stream-specific functions */
+/*************************************************************************/
+/* status handling functions */
+/*************************************************************************/
+
+
+/*
+ * tc_import_thread_stop (Thread safe): mark the import status flag
+ * as `stopped'; the import thread will stop as soon as is possible.
+ *
+ * Parameters:
+ * decdata: pointer to a TCDecoderData structure representing the
+ * import thread to stop.
+ * Return Value:
+ * None
+ */
+static void tc_import_thread_stop(TCDecoderData *decdata)
+{
+ pthread_mutex_lock(&decdata->lock);
+ decdata->active_flag = TC_FALSE;
+ pthread_mutex_unlock(&decdata->lock);
+}
+
+/*
+ * tc_import_thread_start (Thread safe): mark the import status flag
+ * as `started'; import thread become running and it starts producing data.
+ *
+ * Parameters:
+ * decdata: pointer to a TCDecoderData structure representing the
+ * import thread to start.
+ * Return Value:
+ * None
+ */
+static void tc_import_thread_start(TCDecoderData *decdata)
+{
+ pthread_mutex_lock(&decdata->lock);
+ decdata->active_flag = TC_TRUE;
+ pthread_mutex_unlock(&decdata->lock);
+}
+
+/*
+ * tc_import_thread_is_active (Thread safe): poll for the current
+ * status flag of an import thread.
+ *
+ * Parameters:
+ * decdata: pointer to a TCDecoderData structure representing the
+ * import thread to query.
+ * Return Value:
+ * TC_FALSE: import thread is stopped or stopping.
+ * TC_TRUE: import thread is running.
+ */
+
+static int tc_import_thread_is_active(TCDecoderData *decdata)
+{
+ int flag;
+ pthread_mutex_lock(&decdata->lock);
+ flag = decdata->active_flag;
+ pthread_mutex_unlock(&decdata->lock);
+ return flag;
+}
+
+/*************************************************************************/
+/* stream open/close functions */
+/*************************************************************************/
+
+/*
+ * tc_import_{video,audio}_open: open audio stream for importing.
+ *
+ * Parameters:
+ * vob: vob structure
+ * Return Value:
+ * TC_OK: succesfull.
+ * TC_ERROR: failure; reason was tc_log*()ged out.
+ */
+static int tc_import_video_open(vob_t *vob)
+{
+ int ret;
+ transfer_t import_para;
+
+ memset(&import_para, 0, sizeof(transfer_t));
+
+ import_para.flag = TC_VIDEO;
+
+ ret = tcv_import(TC_IMPORT_OPEN, &import_para, vob);
+ if (ret < 0) {
+ tc_log_error(PACKAGE, "video import module error: OPEN failed");
+ return TC_ERROR;
+ }
+
+ video_decdata.fd = import_para.fd;
+
+ return TC_OK;
+}
+
+
+static int tc_import_audio_open(vob_t *vob)
+{
+ int ret;
+ transfer_t import_para;
+
+ memset(&import_para, 0, sizeof(transfer_t));
+
+ import_para.flag = TC_AUDIO;
+
+ ret = tca_import(TC_IMPORT_OPEN, &import_para, vob);
+ if (ret < 0) {
+ tc_log_error(PACKAGE, "audio import module error: OPEN failed");
+ return TC_ERROR;
+ }
+
+ audio_decdata.fd = import_para.fd;
+
+ return TC_OK;
+}
+
+/*
+ * tc_import_{video,audio}_close: close audio stream used for importing.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * TC_OK: succesfull.
+ * TC_ERROR: failure; reason was tc_log*()ged out.
+ */
+
+static int tc_import_audio_close(void)
+{
+ int ret;
+ transfer_t import_para;
+
+ memset(&import_para, 0, sizeof(transfer_t));
+
+ import_para.flag = TC_AUDIO;
+ import_para.fd = audio_decdata.fd;
+
+ ret = tca_import(TC_IMPORT_CLOSE, &import_para, NULL);
+ if (ret == TC_IMPORT_ERROR) {
+ tc_log_warn(PACKAGE, "audio import module error: CLOSE failed");
+ return TC_ERROR;
+ }
+ audio_decdata.fd = NULL;
+
+ return TC_OK;
+}
+
+static int tc_import_video_close(void)
+{
+ int ret;
+ transfer_t import_para;
+
+ memset(&import_para, 0, sizeof(transfer_t));
+
+ import_para.flag = TC_VIDEO;
+ import_para.fd = video_decdata.fd;
+
+ ret = tcv_import(TC_IMPORT_CLOSE, &import_para, NULL);
+ if (ret == TC_IMPORT_ERROR) {
+ tc_log_warn(PACKAGE, "video import module error: CLOSE failed");
+ return TC_ERROR;
+ }
+ video_decdata.fd = NULL;
+
+ return TC_OK;
+}
+
+
+/*************************************************************************/
+/* the import loops */
+/*************************************************************************/
+
+
+#define MARK_TIME_RANGE(PTR, VOB) do { \
+ /* Set skip attribute based on -c */ \
+ if (fc_time_contains((VOB)->ttime, (PTR)->id)) \
+ (PTR)->attributes &= ~TC_FRAME_IS_OUT_OF_RANGE; \
+ else \
+ (PTR)->attributes |= TC_FRAME_IS_OUT_OF_RANGE; \
+} while (0)
+
+
+/*
+ * stop_cause: specify the cause of an import loop termination.
+ *
+ * Parameters:
+ * ret: termination cause identifier to be specified
+ * Return Value:
+ * the most specific recognizable termination cause.
+ */
+static int stop_cause(int ret)
+{
+ if (ret == TC_IM_THREAD_UNKNOWN) {
+ if (tc_interrupted()) {
+ ret = TC_IM_THREAD_INTERRUPT;
+ } else if (tc_stopped()) {
+ ret = TC_IM_THREAD_DONE;
+ }
+ }
+ return ret;
+}
+
+/*
+ * {video,audio}_import_loop: data import loops. Feed frame FIFOs with
+ * new data forever until are interrupted or stopped.
+ *
+ * Parameters:
+ * vob: vob structure
+ * Return Value:
+ * TC_IM_THREAD_* value reporting operation status.
+ */
+static int video_import_loop(vob_t *vob)
+{
+ int ret = 0, vbytes = 0;
+ vframe_list_t *ptr = NULL;
+ transfer_t import_para;
+ TCFrameStatus next = (tc_frame_threads_have_video_workers())
+ ?TC_FRAME_WAIT :TC_FRAME_READY;
+ int im_ret = TC_IM_THREAD_UNKNOWN;
+
+ if (verbose >= TC_DEBUG)
+ tc_log_msg(__FILE__, "video thread id=%ld", (unsigned long)pthread_self());
+
+ vbytes = vob->im_v_size;
+
+ while (tc_running() && tc_import_thread_is_active(&video_decdata)) {
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(V) %10s [%ld] %i bytes", "requesting",
+ vframecount, vbytes);
+
+ /* stage 1: register new blank frame */
+ ptr = vframe_register(vframecount);
+ if (ptr == NULL) {
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(V) frame registration interrupted!");
+ break;
+ }
+
+ /* stage 2: fill the frame with data */
+ ptr->attributes = 0;
+ MARK_TIME_RANGE(ptr, vob);
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(V) new frame registered and marked, now filling...");
+
+ if (video_decdata.fd != NULL) {
+ if (vbytes && (ret = mfread(ptr->video_buf, vbytes, 1, video_decdata.fd)) != 1)
+ ret = -1;
+ ptr->video_len = vbytes;
+ ptr->video_size = vbytes;
+ } else {
+ import_para.fd = NULL;
+ import_para.buffer = ptr->video_buf;
+ import_para.buffer2 = ptr->video_buf2;
+ import_para.size = vbytes;
+ import_para.flag = TC_VIDEO;
+ import_para.attributes = ptr->attributes;
+
+ ret = tcv_import(TC_IMPORT_DECODE, &import_para, vob);
+
+ ptr->video_len = import_para.size;
+ ptr->video_size = import_para.size;
+ ptr->attributes |= import_para.attributes;
+ }
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(V) new frame filled (%s)", (ret == -1) ?"FAILED" :"OK");
+
+ if (ret < 0) {
+ if (verbose >= TC_DEBUG)
+ tc_log_msg(__FILE__, "(V) data read failed - end of stream");
+
+ ptr->video_len = 0;
+ ptr->video_size = 0;
+ if (!tc_has_more_video_in_file(vob)) {
+ ptr->attributes = TC_FRAME_IS_END_OF_STREAM;
+ } else {
+ ptr->attributes = TC_FRAME_IS_SKIPPED;
+ }
+ }
+
+ ptr->v_height = vob->im_v_height;
+ ptr->v_width = vob->im_v_width;
+ ptr->v_bpp = BPP;
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(V) new frame is being processed");
+
+ /* stage 3: account filled frame and process it if needed */
+ if (TC_FRAME_NEED_PROCESSING(ptr)) {
+ //first stage pre-processing - (synchronous)
+ preprocess_vid_frame(vob, ptr);
+
+ //filter pre-processing - (synchronous)
+ ptr->tag = TC_VIDEO|TC_PRE_S_PROCESS;
+ tc_filter_process((frame_list_t *)ptr);
+ }
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(V) new frame ready to be pushed");
+
+ /* stage 4: push frame to next transcoding layer */
+ vframe_push_next(ptr, next);
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(V) %10s [%ld] %i bytes", "received",
+ vframecount, ptr->video_size);
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(V) new frame pushed");
+
+ if (ret < 0) {
+ /*
+ * we must delay this stuff in order to properly END_OF_STREAM
+ * frames _and_ to push them to subsequent stages
+ */
+ tc_import_thread_stop(&audio_decdata);
+ im_ret = TC_IM_THREAD_DONE;
+ break;
+ }
+ vframecount++;
+ }
+ return stop_cause(im_ret);
+}
+
+
+#define GET_AUDIO_FRAME do { \
+ if (audio_decdata.fd != NULL) { \
+ if (abytes && (ret = mfread(ptr->audio_buf, abytes, 1, audio_decdata.fd)) != 1) { \
+ ret = -1; \
+ } \
+ ptr->audio_len = abytes; \
+ ptr->audio_size = abytes; \
+ } else { \
+ import_para.fd = NULL; \
+ import_para.buffer = ptr->audio_buf; \
+ import_para.size = abytes; \
+ import_para.flag = TC_AUDIO; \
+ import_para.attributes = ptr->attributes; \
+ \
+ ret = tca_import(TC_IMPORT_DECODE, &import_para, vob); \
+ \
+ ptr->audio_len = import_para.size; \
+ ptr->audio_size = import_para.size; \
+ } \
+} while (0)
+
+static int audio_import_loop(vob_t *vob)
+{
+ int ret = 0, abytes;
+ aframe_list_t *ptr = NULL;
+ transfer_t import_para;
+ TCFrameStatus next = (tc_frame_threads_have_audio_workers())
+ ?TC_FRAME_WAIT :TC_FRAME_READY;
+ int im_ret = TC_IM_THREAD_UNKNOWN;
+
+ if (verbose >= TC_DEBUG)
+ tc_log_msg(__FILE__, "audio thread id=%ld",
+ (unsigned long)pthread_self());
+
+ abytes = vob->im_a_size;
+
+ while (tc_running() && tc_import_thread_is_active(&audio_decdata)) {
+ /* stage 1: audio adjustment for non-PAL frame rates */
+ if (aframecount != 0 && aframecount % TC_LEAP_FRAME == 0) {
+ abytes = vob->im_a_size + vob->a_leap_bytes;
+ } else {
+ abytes = vob->im_a_size;
+ }
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(A) %10s [%ld] %i bytes",
+ "requesting", aframecount, abytes);
+
+ /* stage 2: register new blank frame */
+ ptr = aframe_register(aframecount);
+ if (ptr == NULL) {
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(A) frame registration interrupted!");
+ break;
+ }
+
+ ptr->attributes = 0;
+ MARK_TIME_RANGE(ptr, vob);
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(A) new frame registered and marked, now syncing...");
+
+ /* stage 3: fill the frame with data */
+ /* stage 3.1: resync audio by discarding frames, if needed */
+ if (vob->sync > 0) {
+ // discard vob->sync frames
+ while (vob->sync--) {
+ GET_AUDIO_FRAME;
+
+ if (ret == -1)
+ break;
+ }
+ vob->sync++;
+ }
+
+ /* stage 3.2: grab effective audio data */
+ if (vob->sync == 0) {
+ GET_AUDIO_FRAME;
+ }
+
+ /* stage 3.3: silence at last */
+ if (vob->sync < 0) {
+ if (verbose >= TC_DEBUG)
+ tc_log_msg(__FILE__, " zero padding %d", vob->sync);
+ memset(ptr->audio_buf, 0, abytes);
+ ptr->audio_len = abytes;
+ ptr->audio_size = abytes;
+ vob->sync++;
+ }
+ /* stage 3.x final note: all this stuff can be done in a cleaner way... */
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(A) syncing done, new frame ready to be filled...");
+
+ if (ret < 0) {
+ if (verbose >= TC_DEBUG)
+ tc_log_msg(__FILE__, "(A) data read failed - end of stream");
+
+ ptr->audio_len = 0;
+ ptr->audio_size = 0;
+ if (!tc_has_more_audio_in_file(vob)) {
+ ptr->attributes = TC_FRAME_IS_END_OF_STREAM;
+ } else {
+ ptr->attributes = TC_FRAME_IS_SKIPPED;
+ }
+ }
+
+ // init frame buffer structure with import frame data
+ ptr->a_rate = vob->a_rate;
+ ptr->a_bits = vob->a_bits;
+ ptr->a_chan = vob->a_chan;
+
+ /* stage 4: account filled frame and process it if needed */
+ if (TC_FRAME_NEED_PROCESSING(ptr)) {
+ ptr->tag = TC_AUDIO|TC_PRE_S_PROCESS;
+ tc_filter_process((frame_list_t *)ptr);
+ }
+
+ /* stage 5: push frame to next transcoding layer */
+ aframe_push_next(ptr, next);
+
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "(A) %10s [%ld] %i bytes", "received",
+ aframecount, ptr->audio_size);
+
+ if (ret < 0) {
+ tc_import_thread_stop(&audio_decdata);
+ im_ret = TC_IM_THREAD_DONE;
+ break;
+ }
+ aframecount++;
+ }
+ return stop_cause(im_ret);
+}
+
+#undef GET_AUDIO_FRAME
+#undef MARK_TIME_RANGE
+
+/*************************************************************************/
+/* ladies and gentlemens, the thread routines */
+/*************************************************************************/
+
+/* audio decode thread wrapper */
+static void *audio_import_thread(void *_vob)
+{
+ static int ret = 0;
+ ret = audio_import_loop(_vob);
+ if (verbose >= TC_CLEANUP)
+ tc_log_msg(__FILE__, "audio decode loop ends with code 0x%i", ret);
+ pthread_exit(&ret);
+}
+
+/* video decode thread wrapper */
+static void *video_import_thread(void *_vob)
+{
+ static int ret = 0;
+ ret = video_import_loop(_vob);
+ if (verbose >= TC_CLEANUP)
+ tc_log_msg(__FILE__, "video decode loop ends with code 0x%i", ret);
+ pthread_exit(&ret);
+}
+
+
+/*************************************************************************/
+/* main API functions */
+/*************************************************************************/
+
+int tc_import_status()
+{
+ return tc_import_video_status() && tc_import_audio_status();
+}
+
+int tc_import_video_running(void)
+{
+ return tc_import_thread_is_active(&video_decdata);
+}
+
+int tc_import_audio_running(void)
+{
+ return tc_import_thread_is_active(&audio_decdata);
+}
+
+int tc_import_video_status(void)
+{
+ return vframe_have_more() || tc_import_thread_is_active(&video_decdata);
+}
+
+int tc_import_audio_status(void)
+{
+ return aframe_have_more() || tc_import_thread_is_active(&audio_decdata);
+}
+
+
+void tc_import_threads_cancel(void)
+{
+ void *status = NULL;
+ int vret, aret;
+
+ if (tc_decoder_delay)
+ tc_log_info(__FILE__, "sleeping for %i seconds to cool down", tc_decoder_delay);
+ sleep(tc_decoder_delay);
+ tc_log_info(__FILE__, "cancelling the import threads");
+
+ tc_import_thread_stop(&video_decdata);
+ tc_import_thread_stop(&audio_decdata);
+
+ tc_framebuffer_interrupt_import();
+
+ vret = pthread_join(video_decdata.thread_id, &status);
+ if (verbose >= TC_DEBUG) {
+ int *pst = status; /* avoid explicit cast in log below */
+ tc_log_msg(__FILE__, "video thread exit (ret_code=%i)"
+ " (status_code=%i)", vret, *pst);
+ }
+
+ aret = pthread_join(audio_decdata.thread_id, &status);
+ if (verbose >= TC_DEBUG) {
+ int *pst = status; /* avoid explicit cast in log below */
+ tc_log_msg(__FILE__, "audio thread exit (ret_code=%i)"
+ " (status_code=%i)", aret, *pst);
+ }
+ return;
+}
+
+
+void tc_import_threads_create(vob_t *vob)
+{
+ int ret;
+
+ tc_import_thread_start(&audio_decdata);
+ ret = pthread_create(&audio_decdata.thread_id, NULL,
+ audio_import_thread, vob);
+ if (ret != 0)
+ tc_error("failed to start audio stream import thread");
+
+ tc_import_thread_start(&video_decdata);
+ ret = pthread_create(&video_decdata.thread_id, NULL,
+ video_import_thread, vob);
+ if (ret != 0)
+ tc_error("failed to start video stream import thread");
+}
+
+
+int tc_import_init(vob_t *vob, const char *a_mod, const char *v_mod)
+{
+ transfer_t import_para;
+ int caps;
+
+ a_mod = (a_mod == NULL) ?TC_DEFAULT_IMPORT_AUDIO :a_mod;
+ audio_decdata.im_handle = load_module(a_mod, TC_IMPORT+TC_AUDIO);
+ RETURN_IF_NULL(audio_decdata.im_handle, "audio");
+
+ v_mod = (v_mod == NULL) ?TC_DEFAULT_IMPORT_VIDEO :v_mod;
+ video_decdata.im_handle = load_module(v_mod, TC_IMPORT+TC_VIDEO);
+ RETURN_IF_NULL(video_decdata.im_handle, "video");
+
+ memset(&import_para, 0, sizeof(transfer_t));
+ import_para.flag = verbose;
+ tca_import(TC_IMPORT_NAME, &import_para, NULL);
+
+ caps = check_module_caps(&import_para, vob->im_a_codec, audpairs);
+ RETURN_IF_NOT_SUPPORTED(caps, "audio");
+
+ memset(&import_para, 0, sizeof(transfer_t));
+ import_para.flag = verbose;
+ tcv_import(TC_IMPORT_NAME, &import_para, NULL);
+
+ caps = check_module_caps(&import_para, vob->im_v_codec, vidpairs);
+ RETURN_IF_NOT_SUPPORTED(caps, "video");
+
+ tc_pthread_main = pthread_self();
+
+ return TC_OK;
+}
+
+
+int tc_import_open(vob_t *vob)
+{
+ RETURN_IF_FUNCTION_FAILED(tc_import_audio_open, vob);
+ RETURN_IF_FUNCTION_FAILED(tc_import_video_open, vob);
+
+ return TC_OK;
+}
+
+int tc_import_close(void)
+{
+ RETURN_IF_FUNCTION_FAILED(tc_import_audio_close);
+ RETURN_IF_FUNCTION_FAILED(tc_import_video_close);
+
+ return TC_OK;
+}
+
+void tc_import_shutdown(void)
+{
+ if (verbose >= TC_DEBUG) {
+ tc_log_msg(__FILE__, "unloading audio import module");
+ }
+
+ unload_module(audio_decdata.im_handle);
+ audio_decdata.im_handle = NULL;
+
+ if (verbose >= TC_DEBUG) {
+ tc_log_msg(__FILE__, "unloading video import module");
+ }
+
+ unload_module(video_decdata.im_handle);
+ video_decdata.im_handle = NULL;
+}
+
+
+/*************************************************************************/
+/* the new multi-input sequential API */
+/*************************************************************************/
+
+static void dump_probeinfo(const ProbeInfo *pi, int i, const char *tag)
+{
+#ifdef DEBUG
+ tc_log_warn(__FILE__, "(%s): %ix%i asr=%i frc=%i codec=0x%lX",
+ tag, pi->width, pi->height, pi->asr, pi->frc, pi->codec);
+
+ if (i >= 0) {
+ tc_log_warn(__FILE__, "(%s): #%i %iHz %ich %ibits format=0x%X",
+ tag, i,
+ pi->track[i].samplerate, pi->track[i].chan,
+ pi->track[i].bits, pi->track[i].format);
+ }
+#endif
+}
+
+static int probe_im_stream(const char *src, ProbeInfo *info)
+{
+ static pthread_mutex_t probe_mutex = PTHREAD_MUTEX_INITIALIZER; /* XXX */
+ /* UGLY! */
+ int ret = 1; /* be optimistic! */
+
+ pthread_mutex_lock(&probe_mutex);
+ ret = probe_stream_data(src, seek_range, info);
+ pthread_mutex_unlock(&probe_mutex);
+
+ dump_probeinfo(info, 0, "probed");
+
+ return ret;
+}
+
+static int probe_matches(const ProbeInfo *ref, const ProbeInfo *cand, int i)
+{
+ if (ref->width != cand->width || ref->height != cand->height
+ || ref->frc != cand->frc || ref->asr != cand->asr
+ || ref->codec != cand->codec) {
+ tc_log_error(__FILE__, "video parameters mismatch");
+ dump_probeinfo(ref, -1, "old");
+ dump_probeinfo(cand, -1, "new");
+ return 0;
+ }
+
+ if (i > ref->num_tracks || i > cand->num_tracks) {
+ tc_log_error(__FILE__, "track parameters mismatch (i=%i|ref=%i|cand=%i)",
+ i, ref->num_tracks, cand->num_tracks);
+ return 0;
+ }
+ if (ref->track[i].samplerate != cand->track[i].samplerate
+ || ref->track[i].chan != cand->track[i].chan ) {
+// || ref->track[i].bits != cand->track[i].bits ) {
+// || ref->track[i].format != cand->track[i].format ) { XXX XXX XXX
+ tc_log_error(__FILE__, "audio parameters mismatch");
+ dump_probeinfo(ref, i, "old");
+ dump_probeinfo(cand, i, "new");
+ return 0;
+ }
+
+ return 1;
+}
+
+static void probe_from_vob(ProbeInfo *info, const vob_t *vob)
+{
+ /* copy only interesting fields */
+ if (info != NULL && vob != NULL) {
+ int i = 0;
+
+ info->width = vob->im_v_width;
+ info->height = vob->im_v_height;
+ info->codec = vob->v_codec_flag;
+ info->asr = vob->im_asr;
+ info->frc = vob->im_frc;
+
+ for (i = 0; i < TC_MAX_AUD_TRACKS; i++) {
+ memset(&(info->track[i]), 0, sizeof(ProbeTrackInfo));
+ }
+ i = vob->a_track;
+
+ info->track[i].samplerate = vob->a_rate;
+ info->track[i].chan = vob->a_chan;
+ info->track[i].bits = vob->a_bits;
+ info->track[i].format = vob->a_codec_flag;
+ }
+}
+
+/* ok, that sucks. I know. I can't do any better now. */
+static const char *current_in_file(vob_t *vob, int kind)
+{
+ if (kind == TC_VIDEO)
+ return vob->video_in_file;
+ if (kind == TC_AUDIO)
+ return vob->audio_in_file;
+ return NULL; /* cannot happen */
+}
+
+#define RETURN_IF_PROBE_FAILED(ret, src) do { \
+ if (ret == 0) { \
+ tc_log_error(PACKAGE, "probing of source '%s' failed", src); \
+ status = TC_IM_THREAD_PROBE_ERROR; \
+ } \
+} while (0)
+
+/* black magic in here? Am I looking for troubles? */
+#define SWAP(type, a, b) do { \
+ type tmp = a; \
+ a = b; \
+ b = tmp; \
+} while (0)
+
+
+/*************************************************************************/
+
+typedef struct tcmultiimportdata_ TCMultiImportData;
+struct tcmultiimportdata_ {
+ int kind;
+
+ TCDecoderData *decdata;
+ vob_t *vob;
+
+ ProbeInfo infos;
+
+ int (*open)(vob_t *vob);
+ int (*import_loop)(vob_t *vob);
+ int (*close)(void);
+
+ int (*next)(vob_t *vob);
+};
+
+
+#define MULTIDATA_INIT(MEDIA, VOB, KIND) do { \
+ MEDIA ## _multidata.kind = KIND; \
+ \
+ MEDIA ## _multidata.vob = VOB; \
+ MEDIA ## _multidata.decdata = &(MEDIA ## _decdata); \
+ \
+ MEDIA ## _multidata.open = tc_import_ ## MEDIA ## _open; \
+ MEDIA ## _multidata.import_loop = MEDIA ## _import_loop; \
+ MEDIA ## _multidata.close = tc_import_ ## MEDIA ## _close; \
+ MEDIA ## _multidata.next = tc_next_ ## MEDIA ## _in_file; \
+} while (0)
+
+#define MULTIDATA_FINI(MEDIA) do { \
+ ; /* nothing */ \
+} while (0)
+
+
+
+static TCMultiImportData audio_multidata;
+static TCMultiImportData video_multidata;
+
+/*************************************************************************/
+
+static void *multi_import_thread(void *_sid)
+{
+ static int status = TC_IM_THREAD_UNKNOWN; /* can't we be more specific? */
+
+ TCMultiImportData *sid = _sid;
+ int ret = TC_OK, track_id = sid->vob->a_track;
+ ProbeInfo infos;
+ ProbeInfo *old = &(sid->infos), *new = &infos;
+ const char *fname = NULL;
+ long int i = 1;
+
+ while (tc_running() && tc_import_thread_is_active(sid->decdata)) {
+ ret = sid->open(sid->vob);
+ if (ret == TC_ERROR) {
+ status = TC_IM_THREAD_EXT_ERROR;
+ break;
+ }
+
+ status = sid->import_loop(sid->vob);
+ /* source should always be closed */
+
+ ret = sid->close();
+ if (ret == TC_ERROR) {
+ status = TC_IM_THREAD_EXT_ERROR;
+ break;
+ }
+
+ ret = sid->next(sid->vob);
+ if (ret == TC_ERROR) {
+ status = TC_IM_THREAD_DONE;
+ break;
+ }
+
+ fname = current_in_file(sid->vob, sid->kind);
+ /* probing coherency check */
+ ret = probe_im_stream(fname, new);
+ RETURN_IF_PROBE_FAILED(ret, fname);
+
+ if (probe_matches(old, new, track_id)) {
+ if (verbose) {
+ tc_log_info(__FILE__, "switching to %s source #%li: %s",
+ sid->decdata->tag, i, fname);
+ }
+ } else {
+ tc_log_error(PACKAGE, "source '%s' in directory"
+ " not compatible with former", fname);
+ status = TC_IM_THREAD_PROBE_ERROR;
+ break;
+ }
+ /* now prepare for next probing round by swapping pointers */
+ SWAP(ProbeInfo*, old, new);
+
+ i++;
+ }
+ status = stop_cause(status);
+
+ tc_framebuffer_interrupt();
+
+ pthread_exit(&status);
+}
+
+/*************************************************************************/
+
+void tc_multi_import_threads_create(vob_t *vob)
+{
+ int ret;
+
+ probe_from_vob(&(audio_multidata.infos), vob);
+ MULTIDATA_INIT(audio, vob, TC_AUDIO);
+ tc_import_thread_start(&audio_decdata);
+ ret = pthread_create(&audio_decdata.thread_id, NULL,
+ multi_import_thread, &audio_multidata);
+ if (ret != 0) {
+ tc_error("failed to start sequential audio stream import thread");
+ }
+
+ probe_from_vob(&(video_multidata.infos), vob);
+ MULTIDATA_INIT(video, vob, TC_VIDEO);
+ tc_import_thread_start(&video_decdata);
+ ret = pthread_create(&video_decdata.thread_id, NULL,
+ multi_import_thread, &video_multidata);
+ if (ret != 0) {
+ tc_error("failed to start sequential video stream import thread");
+ }
+
+ tc_info("sequential streams import threads started");
+}
+
+
+void tc_multi_import_threads_cancel(void)
+{
+ MULTIDATA_FINI(audio);
+ MULTIDATA_FINI(video);
+
+ tc_import_threads_cancel();
+}
+
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
+
diff --git a/debian/transcode/transcode-1.1.7/src/decoder.h b/debian/transcode/transcode-1.1.7/src/decoder.h
new file mode 100644
index 00000000..a1eb7d09
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/decoder.h
@@ -0,0 +1,207 @@
+/*
+ * decoder.h -- transcode import layer module, declarations.
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ * Enhancements and partial rewrite:
+ * (C) Francesco Romani - November 2007.
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifndef DECODER_H
+#define DECODER_H
+
+/*
+ * tc_import_init (NOT thread safe):
+ * prepare import layer for execution, by loading import modules,
+ * checking their capabilities against those requested by core,
+ * intializing them.
+ *
+ * After this function terminates succesfully, import threads can be
+ * created and import layer can be started.
+ *
+ * Parameters:
+ * vob: vob structure.
+ * a_mod: name of the module to be used for import audio.
+ * v_mod: name of the module to be used for import video.
+ * Return Value:
+ * TC_OK: succesfull.
+ * TC_ERROR: failure. Reason was already tc_log*()ged out.
+ * Postconditions:
+ * Import threads can now be created.
+ */
+int tc_import_init(vob_t *vob, const char *a_mod, const char *v_mod);
+
+/*
+ * tc_import_shutdown (NOT thread safe):
+ * shutdown import layer after the import threads termination, by
+ * freeing resources acquired by import modules and unloading them.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ * Preconditions:
+ * Import threads are terminated.
+ */
+void tc_import_shutdown(void);
+
+
+/*
+ * tc_import_open (Thread safe):
+ * open both the audio and video streams.
+ *
+ * Parameters:
+ * vob: vob structure.
+ * Return Value:
+ * TC_OK: succesfull.
+ * TC_ERROR: failure. Reason was already tc_log*()ged out.
+ * Preconditions:
+ * import modules are loaded and initialized correctly;
+ * tc_import_init was executed succesfully.
+ */
+int tc_import_open(vob_t *vob);
+
+/*
+ * tc_import_close (Thread safe):
+ * close both the audio and video streams.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * TC_OK: succesfull.
+ * TC_ERROR: failure. Reason was already tc_log*()ged out.
+ * Preconditions:
+ * Import threads are terminated;
+ * tc_import_threads_cancel was executed succesfully.
+ */
+int tc_import_close(void);
+
+/*
+ * tc_import_threads_create (Thread safe):
+ * create both audio and video import threads, and automatically,
+ * implicitely and immediately starts importing loops and the import
+ * layer itself.
+ *
+ * Parameters:
+ * vob: vob structure.
+ * Return Value:
+ * None.
+ * Preconditions:
+ * import modules are loaded and initialized correctly;
+ * tc_import_init was executed succesfully.
+ * import streams are been opened correctly;
+ * tc_import_open was executed succesfully.
+ */
+void tc_import_threads_create(vob_t *vob);
+
+/*
+ * tc_import_threads_cancel (Thread safe):
+ * destroy both audio and video import threads, and automatically and
+ * implicitely stop the whole import layer.
+ * It's important to note that this function assume that import loops
+ * are already been terminated.
+ * This is a blocking function.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ * Preconditions:
+ * import threads are terminated for any reason
+ * (regular stop, end of stream reached, forced interruption).
+ * tc_import_threads_create was used to startup the threads.
+ */
+void tc_import_threads_cancel(void);
+
+
+/*
+ * tc_import_{,video_,audio_}status (Thread safe):
+ * query the status of import layer.
+ *
+ * Import layer has the responsability to provide raw data for further
+ * layers. Since there always is some buffering, isn't sufficient to
+ * check if import threads are running or not, we also need to see if
+ * there is some buffered data in the frame FIFOs.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * !0: there is some futher data to process.
+ * 0: no more data avalaible.
+ */
+int tc_import_status(void);
+int tc_import_audio_status(void);
+int tc_import_video_status(void);
+
+/*
+ * tc_import_{,video_,audio_}running (Thread safe):
+ * check if respectively video or audio import thread is running.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * !0: thread is running.
+ * 0: thread is stopped or stopping.
+ */
+int tc_import_video_running(void);
+int tc_import_audio_running(void);
+
+
+/*************************************************************************/
+
+/*
+ * tc_multi_import_threads_create (Thread safe):
+ * like tc_import_threads_create, but setup internal machinery for
+ * multi-input handling.
+ *
+ * CRITICAL NOTE:
+ * You MUST use EITHER tc_multi_import_threads_create *OR*
+ * tc_import_threads_create.
+ * You CANNOT use BOTH in the same code path, or nasty things will happen
+ *
+ * Parameters:
+ * vob: vob structure.
+ * Return Value:
+ * None.
+ * Preconditions:
+ * import modules are loaded and initialized correctly;
+ * tc_import_init was executed succesfully.
+ * import streams are been opened correctly;
+ * tc_import_open was executed succesfully.
+ */
+void tc_multi_import_threads_create(vob_t *vob);
+
+/*
+ * tc_multi_import_threads_cancel (Thread safe):
+ * like tc_import_threads_cancel, but you MUST use this function if you
+ * called tc_multi_input_threads_create before.
+ * Otherwise things will turn nasty.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ * Preconditions:
+ * import threads are terminated for any reason
+ * (regular stop, end of stream reached, forced interruption).
+ * tc_multi_import_threads_create was used to startup the threads.
+ */
+void tc_multi_import_threads_cancel(void);
+
+#endif /* DECODER_H */
diff --git a/debian/transcode/transcode-1.1.7/src/dl_loader.c b/debian/transcode/transcode-1.1.7/src/dl_loader.c
new file mode 100644
index 00000000..3b4b9b8e
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/dl_loader.c
@@ -0,0 +1,223 @@
+/*
+ * dl_loader.c
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#else
+# ifdef OS_DARWIN
+# include "libdldarwin/dlfcn.h"
+# endif
+#endif
+
+#include "transcode.h"
+#include "dl_loader.h"
+
+const char *mod_path = MOD_PATH;
+
+char module[TC_BUF_MAX];
+
+int (*TCV_export)(int opt, void *para1, void *para2);
+int (*TCA_export)(int opt, void *para1, void *para2);
+int (*TCV_import)(int opt, void *para1, void *para2);
+int (*TCA_import)(int opt, void *para1, void *para2);
+
+static void watch_export_module(const char *s, int opt, transfer_t *para)
+{
+ tc_log_msg(__FILE__, "module=%s [option=%02d, flag=%d]", s, opt, ((para==NULL)? -1:para->flag));
+}
+
+static void watch_import_module(const char *s, int opt, transfer_t *para)
+{
+ tc_log_msg(__FILE__, "module=%s [option=%02d, flag=%d]", s, opt, ((para==NULL)? -1:para->flag));
+ fflush(stdout);
+}
+
+int tcv_export(int opt, void *para1, void *para2)
+{
+
+ int ret;
+
+ if(verbose & TC_WATCH)
+ watch_export_module("tcv_export", opt, (transfer_t*) para1);
+
+ ret = TCV_export(opt, para1, para2);
+
+ if(ret==TC_EXPORT_ERROR && (verbose & TC_DEBUG))
+ tc_log_msg(__FILE__, "video export module error");
+
+ if(ret==TC_EXPORT_UNKNOWN && (verbose & TC_DEBUG))
+ tc_log_msg(__FILE__, "option %d unsupported by video export module", opt);
+
+ return(ret);
+}
+
+int tca_export(int opt, void *para1, void *para2)
+{
+
+ int ret;
+
+ if(verbose & TC_WATCH)
+ watch_export_module("tca_export", opt, (transfer_t*) para1);
+
+ ret = TCA_export(opt, para1, para2);
+
+ if(ret==TC_EXPORT_ERROR && (verbose & TC_DEBUG))
+ tc_log_msg(__FILE__, "audio export module error");
+
+ if(ret==TC_EXPORT_UNKNOWN && (verbose & TC_DEBUG))
+ tc_log_msg(__FILE__, "option %d unsupported by audio export module", opt);
+
+ return(ret);
+}
+
+int tcv_import(int opt, void *para1, void *para2)
+{
+
+ int ret;
+
+ if(verbose & TC_WATCH)
+ watch_import_module("tcv_import", opt, (transfer_t*) para1);
+
+ ret = TCV_import(opt, para1, para2);
+
+ if(ret==TC_IMPORT_ERROR && (verbose & TC_DEBUG))
+ tc_log_msg(__FILE__, "video import module error");
+
+ if(ret==TC_IMPORT_UNKNOWN && (verbose & TC_DEBUG))
+ tc_log_msg(__FILE__, "option %d unsupported by video import module", opt);
+
+ return(ret);
+}
+
+int tca_import(int opt, void *para1, void *para2)
+{
+ int ret;
+
+ if(verbose & TC_WATCH)
+ watch_import_module("tca_import", opt, (transfer_t*) para1);
+
+ ret = TCA_import(opt, para1, para2);
+
+ if(ret==TC_IMPORT_ERROR && (verbose & TC_DEBUG))
+ tc_log_msg(__FILE__, "audio import module error");
+
+ if(ret==TC_IMPORT_UNKNOWN && (verbose & TC_DEBUG))
+ tc_log_msg(__FILE__, "option %d unsupported by audio import module", opt);
+
+ return(ret);
+}
+
+
+void *load_module(const char *mod_name, int mode)
+{
+ const char *error;
+ void *handle;
+
+ if(mode & TC_EXPORT) {
+
+ tc_snprintf(module, sizeof(module), "%s/export_%s.so", ((mod_path==NULL)? TC_DEFAULT_MOD_PATH:mod_path), mod_name);
+
+ if(verbose & TC_DEBUG)
+ tc_log_msg(__FILE__, "loading %s export module %s", ((mode & TC_VIDEO)? "video": "audio"), module);
+
+ handle = dlopen(module, RTLD_GLOBAL| RTLD_LAZY);
+
+ if (!handle) {
+ error=dlerror();
+ tc_warn("%s", error);
+ tc_warn("(%s) loading \"%s\" failed", __FILE__, module);
+ return(NULL);
+ }
+
+ if(mode & TC_VIDEO) {
+ TCV_export = dlsym(handle, "tc_export");
+ error = dlerror();
+ if (error != NULL) {
+ tc_warn("%s", error);
+ return(NULL);
+ }
+ }
+
+ if(mode & TC_AUDIO) {
+ TCA_export = dlsym(handle, "tc_export");
+ error = dlerror();
+ if (error != NULL) {
+ tc_warn("%s", error);
+ return(NULL);
+ }
+ }
+
+ return(handle);
+ }
+
+
+ if(mode & TC_IMPORT) {
+
+ tc_snprintf(module, sizeof(module), "%s/import_%s.so", ((mod_path==NULL)? TC_DEFAULT_MOD_PATH:mod_path), mod_name);
+
+ if(verbose & TC_DEBUG)
+ tc_log_msg(__FILE__, "loading %s import module %s", ((mode & TC_VIDEO)? "video": "audio"), module);
+
+ handle = dlopen(module, RTLD_GLOBAL| RTLD_LAZY);
+
+ if (!handle) {
+ error = dlerror();
+ tc_warn("%s", error);
+ return(NULL);
+ }
+
+ if(mode & TC_VIDEO) {
+ TCV_import = dlsym(handle, "tc_import");
+ if ((error = dlerror()) != NULL) {
+ tc_warn("%s", error);
+ return(NULL);
+ }
+ }
+
+
+ if(mode & TC_AUDIO) {
+ TCA_import = dlsym(handle, "tc_import");
+ if ((error = dlerror()) != NULL) {
+ tc_warn("%s", error);
+ return(NULL);
+ }
+ }
+
+ return(handle);
+ }
+
+ // wrong mode?
+ return(NULL);
+}
+
+void unload_module(void *handle)
+{
+ if (dlclose(handle) != 0) {
+ perror("unloading module");
+ }
+ handle=NULL;
+}
+
diff --git a/debian/transcode/transcode-1.1.7/src/dl_loader.h b/debian/transcode/transcode-1.1.7/src/dl_loader.h
new file mode 100644
index 00000000..5ebfc941
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/dl_loader.h
@@ -0,0 +1,40 @@
+/*
+ * dl_loader.h
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ *
+ * This file is part of transcode, a video 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.
+ *
+ */
+
+#ifndef _DL_LOADER_H
+#define _DL_LOADER_H
+
+void *load_module(const char *mod, int mode);
+void unload_module(void *handle);
+
+// extern int (*TCV_export)(int opt, void *para1, void *para2);
+// extern int (*TCA_export)(int opt, void *para1, void *para2);
+// extern int (*TCV_import)(int opt, void *para1, void *para2);
+// extern int (*TCA_import)(int opt, void *para1, void *para2);
+
+int tcv_export(int opt, void *para1, void *para2);
+int tca_export(int opt, void *para1, void *para2);
+int tcv_import(int opt, void *para1, void *para2);
+int tca_import(int opt, void *para1, void *para2);
+
+#endif
diff --git a/debian/transcode/transcode-1.1.7/src/encoder-buffer.c b/debian/transcode/transcode-1.1.7/src/encoder-buffer.c
new file mode 100644
index 00000000..53af7cba
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/encoder-buffer.c
@@ -0,0 +1,408 @@
+/*
+ * encoder-buffer.c -- encoder interface to transcode frame ringbuffers.
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ * Updated and partially rewritten by
+ * Francesco Romani - January 2006
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "transcode.h"
+#include "decoder.h"
+#include "encoder.h"
+#include "filter.h"
+#include "framebuffer.h"
+#include "counter.h"
+#include "video_trans.h"
+#include "audio_trans.h"
+#include "frame_threads.h"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+/*
+ * Quick Summary:
+ *
+ * This code provide glue between frames ringbuffer and real encoder
+ * code, in order to make encoder modular and independent from
+ * a single frame source, to promote reusability (tcexport).
+ * This code also take acare of some oddities like handling filtering
+ * if no frame threads are avalaible.
+ *
+ * This code isn't clean as one (i.e.: me) would like since it
+ * must cope with a lot of legacy constraints and some other nasty
+ * stuff. Of course situation will be improved in future releases
+ * when we keep going away from legacy oddities and continue
+ * sanitize/modernize the codebase.
+ *
+ * NOTE about counter/condition/mutex handling inside various
+ * encoder helpers.
+ *
+ * Code are still a little bit confusing since things aren't
+ * updated or used at the same function level.
+ * Code works, but isn't still well readable.
+ * We need stil more cleanup and refactoring for future releases.
+ */
+
+
+/*************************************************************************/
+/*************************************************************************/
+
+static int have_aud_threads = 0;
+static int have_vid_threads = 0;
+
+/*************************************************************************/
+
+/*
+ * apply_{video,audio}_filters:
+ * Apply the filter chain to current respectively video
+ * or audio frame.
+ * This function is used if no frame threads are avalaible,
+ * but of course filtering still must be applied.
+ * This function should be never exported.
+ *
+ * Parameters:
+ * vptr, aptr: respectively video or aufio framebuffer
+ * pointer to frame to be filtered.
+ * vob: pointer to vob_t structure holding stream
+ * parameters.
+ */
+static void apply_video_filters(vframe_list_t *vptr, vob_t *vob);
+static void apply_audio_filters(aframe_list_t *aptr, vob_t *vob);
+
+/*
+ * encoder_acquire_{v,a}frame:
+ * Get respectively a new video or audio framebuffer for encoding.
+ * This roughly means:
+ * 1. to wait for a new frame avalaible for encoder
+ * 2. apply the filters if no frame threads are avalaible
+ * 3. apply the encoder filters (POST_S_PROCESS)
+ * 4. verify the status of audio framebuffer after all filtering.
+ * if acquired framebuffer is skipped, we must acquire a new one
+ * before continue with encoding, so we must restart from step 1.
+ *
+ * Parameters:
+ * buf: encoder buffer to use (and fullfull with acquired frame).
+ * vob: pointer to vob_t structure describing stream parameters.
+ * Used Internally.
+ * Return Value:
+ * 0 when a new framebuffer is avalaible for encoding;
+ * <0 if no more framebuffers are avalaible.
+ * As for encoder_wait_{v,a}frame, this usually happens
+ * when video/audio stream ends.
+ */
+static int encoder_acquire_vframe(TCEncoderBuffer *buf, vob_t *vob);
+static int encoder_acquire_aframe(TCEncoderBuffer *buf, vob_t *vob);
+
+/*
+ * encoder_dispose_{v,a}frame:
+ * Mark a framebuffer (respectively video or audio) as completed
+ * from encoder viewpoint, so release it to source ringbuffer,
+ * update counters and do all cleanup actions needed internally.
+ *
+ * Parameters:
+ * buf: encoder buffer to use (release currente framebuffers
+ * and update related counters and internal variables).
+ * Return Value:
+ * None.
+ */
+static void encoder_dispose_vframe(TCEncoderBuffer *buf);
+static void encoder_dispose_aframe(TCEncoderBuffer *buf);
+
+
+/*************************************************************************/
+
+static void apply_video_filters(vframe_list_t *vptr, vob_t *vob)
+{
+ if (!have_vid_threads) {
+ if (TC_FRAME_NEED_PROCESSING(vptr)) {
+ /* external plugin pre-processing */
+ vptr->tag = TC_VIDEO|TC_PRE_M_PROCESS;
+ tc_filter_process((frame_list_t *)vptr);
+
+ /* internal processing of video */
+ vptr->tag = TC_VIDEO;
+ process_vid_frame(vob, vptr);
+
+ /* external plugin post-processing */
+ vptr->tag = TC_VIDEO|TC_POST_M_PROCESS;
+ tc_filter_process((frame_list_t *)vptr);
+ }
+ }
+
+ if (TC_FRAME_NEED_PROCESSING(vptr)) {
+ /* second stage post-processing - (synchronous) */
+ vptr->tag = TC_VIDEO|TC_POST_S_PROCESS;
+ tc_filter_process((frame_list_t *)vptr);
+ postprocess_vid_frame(vob, vptr);
+ /* preview _after_ all post-processing */
+ vptr->tag = TC_VIDEO|TC_PREVIEW;
+ tc_filter_process((frame_list_t *)vptr);
+ }
+}
+
+static void apply_audio_filters(aframe_list_t *aptr, vob_t *vob)
+{
+ /* now we try to process the audio frame */
+ if (!have_aud_threads) {
+ if (TC_FRAME_NEED_PROCESSING(aptr)) {
+ /* external plugin pre-processing */
+ aptr->tag = TC_AUDIO|TC_PRE_M_PROCESS;
+ tc_filter_process((frame_list_t *)aptr);
+
+ /* internal processing of audio */
+ aptr->tag = TC_AUDIO;
+ process_aud_frame(vob, aptr);
+
+ /* external plugin post-processing */
+ aptr->tag = TC_AUDIO|TC_POST_M_PROCESS;
+ tc_filter_process((frame_list_t *)aptr);
+ }
+ }
+
+ if (TC_FRAME_NEED_PROCESSING(aptr)) {
+ /* second stage post-processing - (synchronous) */
+ aptr->tag = TC_AUDIO|TC_POST_S_PROCESS;
+ tc_filter_process((frame_list_t *)aptr);
+ /* preview _after_ all post-processing */
+ aptr->tag = TC_AUDIO|TC_PREVIEW;
+ tc_filter_process((frame_list_t *)aptr);
+ }
+}
+
+static int encoder_acquire_vframe(TCEncoderBuffer *buf, vob_t *vob)
+{
+ int got_frame = TC_TRUE;
+
+ do {
+ buf->vptr = vframe_retrieve();
+ if (!buf->vptr) {
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "frame retrieve interrupted!");
+ return -1; /* can't acquire video frame */
+ }
+ got_frame = TC_TRUE;
+ buf->frame_id = buf->vptr->id + tc_get_frames_skipped_cloned();
+
+ if (verbose & TC_STATS) {
+ tc_log_info(__FILE__, "got frame %p (id=%i)",
+ buf->vptr, buf->frame_id);
+ }
+
+ /*
+ * now we do the post processing ... this way, if just a video frame is
+ * skipped, we'll know.
+ *
+ * we have to check to make sure that before we do any processing
+ * that this frame isn't out of range (if it is, and one is using
+ * the "-t" split option, we'll see this frame again.
+ */
+ apply_video_filters(buf->vptr, vob);
+
+ if (buf->vptr->attributes & TC_FRAME_IS_SKIPPED) {
+ if (buf->vptr != NULL
+ && (buf->vptr->attributes & TC_FRAME_WAS_CLONED)
+ ) {
+ /* XXX do we want to track skipped cloned flags? */
+ tc_update_frames_cloned(1);
+ }
+
+ if (buf->vptr != NULL
+ && (buf->vptr->attributes & TC_FRAME_IS_CLONED)
+ ) {
+ /* XXX what to do when a frame is cloned and skipped? */
+ /*
+ * I'd like to say they cancel, but perhaps they will end
+ * up also skipping the clone? or perhaps they'll keep,
+ * but modify the clone? Best to do the whole drill :/
+ */
+ if (verbose & TC_DEBUG) {
+ tc_log_info (__FILE__, "(%i) V pointer done. "
+ "Skipped and Cloned: (%i)",
+ buf->vptr->id,
+ (buf->vptr->attributes));
+ }
+
+ /* update flags */
+ buf->vptr->attributes &= ~TC_FRAME_IS_CLONED;
+ buf->vptr->attributes |= TC_FRAME_WAS_CLONED;
+ /*
+ * this has to be done here,
+ * frame_threads.c won't see the frame again
+ */
+ }
+ if (buf->vptr != NULL
+ && !(buf->vptr->attributes & TC_FRAME_IS_CLONED)
+ ) {
+ vframe_remove(buf->vptr);
+ /* reset pointer for next retrieve */
+ buf->vptr = NULL;
+ }
+ // tc_update_frames_skipped(1);
+ got_frame = TC_FALSE;
+ }
+ } while (!got_frame);
+
+ return 0;
+}
+
+static int encoder_acquire_aframe(TCEncoderBuffer *buf, vob_t *vob)
+{
+ int got_frame = TC_TRUE;
+
+ do {
+ buf->aptr = aframe_retrieve();
+ if (!buf->aptr) {
+ if (verbose >= TC_THREADS)
+ tc_log_msg(__FILE__, "frame retrieve interrupted!");
+ return -1;
+ }
+ got_frame = TC_TRUE;
+
+ if (verbose & TC_STATS) {
+ tc_log_info(__FILE__, "got audio frame (id=%i)", buf->aptr->id);
+ }
+
+ apply_audio_filters(buf->aptr, vob);
+
+ if (buf->aptr->attributes & TC_FRAME_IS_SKIPPED) {
+ if (buf->aptr != NULL
+ && !(buf->aptr->attributes & TC_FRAME_IS_CLONED)
+ ) {
+ aframe_remove(buf->aptr);
+ /* reset pointer for next retrieve */
+ buf->aptr = NULL;
+ }
+
+ if (buf->aptr != NULL
+ && (buf->aptr->attributes & TC_FRAME_IS_CLONED)
+ ) {
+ if (verbose & TC_DEBUG) {
+ tc_log_info(__FILE__, "(%i) A pointer done. Skipped and Cloned: (%i)",
+ buf->aptr->id, (buf->aptr->attributes));
+ }
+
+ /* adjust clone flags */
+ buf->aptr->attributes &= ~TC_FRAME_IS_CLONED;
+ buf->aptr->attributes |= TC_FRAME_WAS_CLONED;
+
+ /*
+ * this has to be done here,
+ * frame_threads.c won't see the frame again
+ */
+ }
+ got_frame = TC_FALSE;
+ }
+ } while (!got_frame);
+
+ return 0;
+}
+
+
+static void encoder_dispose_vframe(TCEncoderBuffer *buf)
+{
+ if (buf->vptr != NULL
+ && (buf->vptr->attributes & TC_FRAME_WAS_CLONED)
+ ) {
+ tc_update_frames_cloned(1);
+ }
+
+ if (buf->vptr != NULL
+ && !(buf->vptr->attributes & TC_FRAME_IS_CLONED)
+ ) {
+ vframe_remove(buf->vptr);
+ /* reset pointer for next retrieve */
+ buf->vptr = NULL;
+ }
+
+ if (buf->vptr != NULL
+ && (buf->vptr->attributes & TC_FRAME_IS_CLONED)
+ ) {
+ if(verbose & TC_DEBUG) {
+ tc_log_info(__FILE__, "(%i) V pointer done. Cloned: (%i)",
+ buf->vptr->id, (buf->vptr->attributes));
+ }
+ buf->vptr->attributes &= ~TC_FRAME_IS_CLONED;
+ buf->vptr->attributes |= TC_FRAME_WAS_CLONED;
+ // update counter
+ //tc_update_frames_cloned(1);
+ }
+}
+
+
+static void encoder_dispose_aframe(TCEncoderBuffer *buf)
+{
+ if (buf->aptr != NULL
+ && !(buf->aptr->attributes & TC_FRAME_IS_CLONED)
+ ) {
+ aframe_remove(buf->aptr);
+ /* reset pointer for next retrieve */
+ buf->aptr = NULL;
+ }
+
+ if (buf->aptr != NULL
+ && (buf->aptr->attributes & TC_FRAME_IS_CLONED)
+ ) {
+ if (verbose & TC_DEBUG) {
+ tc_log_info(__FILE__, "(%i) A pointer done. Cloned: (%i)",
+ buf->aptr->id, (buf->aptr->attributes));
+ }
+
+ buf->aptr->attributes &= ~TC_FRAME_IS_CLONED;
+ buf->aptr->attributes |= TC_FRAME_WAS_CLONED;
+ }
+}
+
+
+static TCEncoderBuffer tc_builtin_buffer = {
+ .frame_id = 0,
+
+ .vptr = NULL,
+ .aptr = NULL,
+
+ .acquire_video_frame = encoder_acquire_vframe,
+ .acquire_audio_frame = encoder_acquire_aframe,
+ .dispose_video_frame = encoder_dispose_vframe,
+ .dispose_audio_frame = encoder_dispose_aframe,
+};
+
+/* default main transcode buffer */
+TCEncoderBuffer *tc_get_ringbuffer(int aworkers, int vworkers)
+{
+ have_aud_threads = aworkers;
+ have_vid_threads = vworkers;
+
+ return &tc_builtin_buffer;
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/encoder-common.c b/debian/transcode/transcode-1.1.7/src/encoder-common.c
new file mode 100644
index 00000000..a9847315
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/encoder-common.c
@@ -0,0 +1,215 @@
+/*
+ * encoder-common.c -- asynchronous encoder runtime control and statistics.
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ * Updated and partially rewritten by
+ * Francesco Romani - January 2006
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdint.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "libtc/libtc.h"
+#include "encoder-common.h"
+#include "tc_defaults.h"
+
+
+/* volatile: for threadness paranoia */
+static int pause_flag = 0;
+
+
+void tc_pause_request(void)
+{
+ pause_flag = !pause_flag;
+}
+
+void tc_pause(void)
+{
+ while (pause_flag) {
+ usleep(TC_DELAY_MIN);
+ }
+}
+
+
+/* counter, for stats and more */
+static uint32_t frames_encoded = 0;
+static uint32_t frames_dropped = 0;
+static uint32_t frames_skipped = 0;
+static uint32_t frames_cloned = 0;
+/* counters can be accessed by other (ex: import) threads */
+static pthread_mutex_t frame_counter_lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+uint32_t tc_get_frames_encoded(void)
+{
+ uint32_t val;
+
+ pthread_mutex_lock(&frame_counter_lock);
+ val = frames_encoded;
+ pthread_mutex_unlock(&frame_counter_lock);
+
+ return val;
+}
+
+void tc_update_frames_encoded(uint32_t val)
+{
+ pthread_mutex_lock(&frame_counter_lock);
+ frames_encoded += val;
+ pthread_mutex_unlock(&frame_counter_lock);
+}
+
+uint32_t tc_get_frames_dropped(void)
+{
+ uint32_t val;
+
+ pthread_mutex_lock(&frame_counter_lock);
+ val = frames_dropped;
+ pthread_mutex_unlock(&frame_counter_lock);
+
+ return val;
+}
+
+void tc_update_frames_dropped(uint32_t val)
+{
+ pthread_mutex_lock(&frame_counter_lock);
+ frames_dropped += val;
+ pthread_mutex_unlock(&frame_counter_lock);
+}
+
+uint32_t tc_get_frames_skipped(void)
+{
+ uint32_t val;
+
+ pthread_mutex_lock(&frame_counter_lock);
+ val = frames_skipped;
+ pthread_mutex_unlock(&frame_counter_lock);
+
+ return val;
+}
+
+void tc_update_frames_skipped(uint32_t val)
+{
+ pthread_mutex_lock(&frame_counter_lock);
+ frames_skipped += val;
+ pthread_mutex_unlock(&frame_counter_lock);
+}
+
+uint32_t tc_get_frames_cloned(void)
+{
+ uint32_t val;
+
+ pthread_mutex_lock(&frame_counter_lock);
+ val = frames_cloned;
+ pthread_mutex_unlock(&frame_counter_lock);
+
+ return val;
+}
+
+void tc_update_frames_cloned(uint32_t val)
+{
+ pthread_mutex_lock(&frame_counter_lock);
+ frames_cloned += val;
+ pthread_mutex_unlock(&frame_counter_lock);
+}
+
+uint32_t tc_get_frames_skipped_cloned(void)
+{
+ uint32_t s, c;
+
+ pthread_mutex_lock(&frame_counter_lock);
+ s = frames_skipped;
+ c = frames_cloned;
+ pthread_mutex_unlock(&frame_counter_lock);
+
+ return (c - s);
+}
+
+/*************************************************************************/
+
+pthread_mutex_t run_status_lock = PTHREAD_MUTEX_INITIALIZER;
+static volatile int tc_run_status = TC_STATUS_RUNNING;
+/* `volatile' is for threading paranoia */
+
+static TCRunStatus tc_get_run_status(void)
+{
+ TCRunStatus rs;
+ pthread_mutex_lock(&run_status_lock);
+ rs = tc_run_status;
+ pthread_mutex_unlock(&run_status_lock);
+ return rs;
+}
+
+int tc_interrupted(void)
+{
+ return (TC_STATUS_INTERRUPTED == tc_get_run_status());
+}
+
+int tc_stopped(void)
+{
+ return (TC_STATUS_STOPPED == tc_get_run_status());
+}
+
+int tc_running(void)
+{
+ return (TC_STATUS_RUNNING == tc_get_run_status());
+}
+
+void tc_start(void)
+{
+ pthread_mutex_lock(&run_status_lock);
+ tc_run_status = TC_STATUS_RUNNING;
+ pthread_mutex_unlock(&run_status_lock);
+}
+
+void tc_stop(void)
+{
+ pthread_mutex_lock(&run_status_lock);
+ /* no preemption, be polite */
+ if (tc_run_status == TC_STATUS_RUNNING) {
+ tc_run_status = TC_STATUS_STOPPED;
+ }
+ pthread_mutex_unlock(&run_status_lock);
+}
+
+void tc_interrupt(void)
+{
+ pthread_mutex_lock(&run_status_lock);
+ /* preempt and don't care of politeness. */
+ if (tc_run_status != TC_STATUS_INTERRUPTED) {
+ tc_run_status = TC_STATUS_INTERRUPTED;
+ }
+ pthread_mutex_unlock(&run_status_lock);
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/encoder-common.h b/debian/transcode/transcode-1.1.7/src/encoder-common.h
new file mode 100644
index 00000000..d1f3134b
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/encoder-common.h
@@ -0,0 +1,188 @@
+/*
+ * encoder-common.h -- asynchronous encoder runtime control and statistics.
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ * Updated and partially rewritten by
+ * Francesco Romani - January 2006
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifndef ENCODER_COMMON_H
+#define ENCODER_COMMON_H
+
+/*
+ * MULTITHREADING NOTE:
+ * It is *GUARANTEED SAFE* to call those functions from different threads.
+ */
+/*************************************************************************/
+
+/*
+ * tc_get_frames_{dropped,skipped,encoded,cloned,skipped_cloned}:
+ * get the current value of a frame counter.
+ *
+ * Parameters:
+ * None
+ * Return Value:
+ * the current value of requested counter
+ */
+uint32_t tc_get_frames_dropped(void);
+uint32_t tc_get_frames_skipped(void);
+uint32_t tc_get_frames_encoded(void);
+uint32_t tc_get_frames_cloned(void);
+uint32_t tc_get_frames_skipped_cloned(void);
+
+/*
+ * tc_update_frames_{dropped,skipped,encoded,cloned}:
+ * update the current value of a frame counter of a given value.
+ *
+ * Parameters:
+ * val: value to be added to the current value of requested counter.
+ * This parameter is usually just '1' (one)
+ * Return Value:
+ * None
+ */
+void tc_update_frames_dropped(uint32_t val);
+void tc_update_frames_skipped(uint32_t val);
+void tc_update_frames_encoded(uint32_t val);
+void tc_update_frames_cloned(uint32_t val);
+
+/*************************************************************************/
+
+/*
+ * tc_pause_request:
+ * toggle pausing; if pausing is enabled, further calls to tc_pause()
+ * will effectively pause application's current thread; otherwise,
+ * tc_pause() calls will do just nothing.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+void tc_pause_request(void);
+
+/*
+ * tc_pause:
+ * if pausing enabled, so if tc_pause_request was previously called
+ * at least once, pause the current application thread for at least
+ * TC_DELAY_MIN microseconds.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ * Side effects:
+ * Incoming socket requests (see socket code), if any, will be handled
+ * before to return.
+ */
+void tc_pause(void);
+
+/*************************************************************************/
+/* encoder (core) run control */
+/*************************************************************************/
+
+typedef enum tcrunstatus_ TCRunStatus;
+enum tcrunstatus_ {
+ TC_STATUS_RUNNING = 0, /* default condition */
+ TC_STATUS_STOPPED = 1, /* regular stop or end of stream reched */
+ TC_STATUS_INTERRUPTED = -1, /* forced interruption (^C) */
+};
+
+/*
+ * tc_interrupt: perform an hard stop of encoder core.
+ * This means that all transcode parts has to stop as soon and as quickly
+ * as is possible.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ */
+void tc_interrupt(void);
+
+/*
+ * tc_stop: perform a soft stop of encoder core. Tipically, this function
+ * is invoked after end of stream was reached, or after all requested
+ * stream ranges were encoded succesfully, to notify all the transcode
+ * parts to shutdown properly.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ */
+void tc_stop(void);
+
+/*
+ * tc_interrupted (Thread safe): verify if the encoder (core) was halted
+ * in response of an interruption.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * 1: halting cause of encoder (core) was (user) interruption (^C).
+ * 0: otherwise.
+ *
+ * PLEASE NOTE that if this function will return 0 even if encoder (core)
+ * IS STILL RUNNING!
+ */
+int tc_interrupted(void);
+
+/*
+ * tc_stopped (Thread safe): verify if the encoder (core) was halted
+ * regulary, most likely because end of stream was reached.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * 1: halting cause of encoder (core) was regular (EOS).
+ * 0: otherwise.
+ *
+ * PLEASE NOTE that if this function will return 0 even if encoder (core)
+ * IS STILL RUNNING!
+ */
+int tc_stopped(void);
+
+/*
+ * tc_running (Thread safe): checks if encoder (core) is still running.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * 1: encoder (core) is still running.
+ * 0: encoder (core) not running.
+ */
+int tc_running(void);
+
+/*
+ * tc_start: start the encoder core. Tipically, this function
+ * is invoked once at the start of the processing; however, some core modes
+ * (e.g. PSU mode) may require multiple start.
+ * Every call to this function should be paired with a tc_stop() call into
+ * the same code path; however, it is safe to call this function multiple
+ * times.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ */
+void tc_start(void);
+
+#endif /* ENCODER_COMMON_H */
diff --git a/debian/transcode/transcode-1.1.7/src/encoder.c b/debian/transcode/transcode-1.1.7/src/encoder.c
new file mode 100644
index 00000000..d509cd3e
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/encoder.c
@@ -0,0 +1,1422 @@
+/*
+ * encoder.c -- transcode export layer module, implementation.
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ * Updated and partially rewritten by
+ * Francesco Romani - January 2006
+ * New rotation code written by
+ * Francesco Romani - May 2006
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#define SUPPORT_OLD_ENCODER // for now
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "transcode.h"
+#include "framebuffer.h"
+#include "filter.h"
+#include "counter.h"
+#include "video_trans.h"
+#include "audio_trans.h"
+#include "decoder.h"
+#include "encoder.h"
+#include "frame_threads.h"
+
+#include "libtc/tcframes.h"
+
+#include <stdint.h>
+
+/*************************************************************************/
+/* Our data structure forward declaration */
+
+typedef struct tcrotatecontext_ TCRotateContext;
+typedef struct tcencoderdata_ TCEncoderData;
+
+/*************************************************************************/
+/* private function prototypes */
+
+/* new-style rotation support */
+static void tc_rotate_init(TCRotateContext *rotor,
+ const char *video_base_name,
+ const char *audio_base_name);
+
+static void tc_rotate_set_frames_limit(TCRotateContext *rotor,
+ vob_t *vob, uint32_t frames);
+static void tc_rotate_set_bytes_limit(TCRotateContext *rotor,
+ vob_t *vob, uint64_t bytes);
+
+static void tc_rotate_output_name(TCRotateContext *rotor, vob_t *vob);
+
+static int tc_rotate_if_needed_null(TCRotateContext *rotor,
+ vob_t *vob, uint32_t bytes);
+static int tc_rotate_if_needed_by_frames(TCRotateContext *rotor,
+ vob_t *vob, uint32_t bytes);
+static int tc_rotate_if_needed_by_bytes(TCRotateContext *rotor,
+ vob_t *vob, uint32_t bytes);
+
+/* old-style rotation support is all public, see transcode.h */
+
+/* new-style encoder */
+
+static int encoder_export(TCEncoderData *data, vob_t *vob);
+static void encoder_skip(TCEncoderData *data);
+static int encoder_flush(TCEncoderData *data);
+
+/* rest of API is already public */
+
+/* old-style encoder */
+#ifdef SUPPORT_OLD_ENCODER
+
+static int OLD_tc_export_setup(vob_t *vob,
+ const char *a_mod, const char *v_mod);
+static void OLD_tc_export_shutdown(void);
+static int OLD_tc_encoder_init(vob_t *vob);
+static int OLD_tc_encoder_open(vob_t *vob);
+static int OLD_tc_encoder_close(void);
+static int OLD_tc_encoder_stop(void);
+static int OLD_encoder_export(TCEncoderData *data, vob_t *vob);
+
+#endif // SUPPORT_OLD_ENCODER
+
+/* misc helpers */
+static int need_stop(TCEncoderData *encdata);
+static int is_last_frame(TCEncoderData *encdata, int cluster_mode);
+static void export_update_formats(vob_t *vob, const TCModuleInfo *vinfo,
+ const TCModuleInfo *ainfo);
+static int alloc_buffers(TCEncoderData *data);
+static void free_buffers(TCEncoderData *data);
+
+
+/*************************************************************************/
+
+/*
+ * new encoder module design principles
+ * 1) keep it simple, stupid
+ * 2) to have more than one encoder doesn't make sense in transcode, so
+ * 3) new encoder will be monothread, like the old one
+ */
+
+/*************************************************************************/
+/*************************************************************************/
+
+/*
+ * new-style output rotation support. Always avalaible, but
+ * only new code is supposed to use it.
+ * This code is private since only encoder code it's supposed
+ * to use it. If this change, this code will be put in a
+ * separate .c/.h pair.
+ *
+ * The tricky part of this code it's mainly the
+ * vob->{video,audio}_out_file mangling.
+ * This it's still done mainly for legacy reasons.
+ * After every rotation, such fields will be updated to point
+ * not to real initialization data, but to private buffers of (a)
+ * TCRotateContext strucutre. This can hardly seen as good, and
+ * should be changed/improved in future releases.
+ * Anyway, original values of mentioned field isn't lost since it
+ * will be stored in TCRotateContext.{video,audio}_base_name.
+ * ------------------------------------------------------------
+ */
+
+/*
+ * TCExportRotate:
+ * Generic function called after *every* frame was encoded.
+ * Rotate output file(s) if condition incapsulate in specific
+ * functions is satisfied.
+ *
+ * Parameters:
+ * rotor: TCRotateContext to use to check condition.
+ * vob: pointer to vob_t structure to update with new
+ * export file(s) name after succesfull rotation.
+ * bytes: total size of byte encoded (Audio + Video) in last
+ * rencoding loop.
+ * Return value:
+ * TC_OK: successful.
+ * TC_ERROR: error happened and notified using tc_log*().
+ *
+ * Of course no error can happen if rotating condition isn't met
+ * (so no rotation it's supposed to happen).
+ * Please note that caller code CANNOT know when rotation happens:
+ * This is a feature, not a bug! Having rotation policy incapsulated
+ * into this code and rotation machinery transparent to caller
+ * it's EXACTLY the purpose oft this code! :)
+ */
+typedef int (*TCExportRotate)(TCRotateContext *rotor, vob_t *vob,
+ uint32_t bytes);
+
+
+struct tcrotatecontext_ {
+ char video_path_buf[PATH_MAX+1];
+ char audio_path_buf[PATH_MAX+1];
+ const char *video_base_name;
+ const char *audio_base_name;
+ uint32_t chunk_num;
+ int null_flag;
+
+ uint32_t chunk_frames;
+
+ uint64_t encoded_bytes;
+ uint64_t chunk_bytes;
+
+ TCExportRotate rotate_if_needed;
+};
+
+/*************************************************************************/
+
+
+/* macro goody for output rotation request */
+#define TC_ROTATE_IF_NEEDED(rotor, vob, bytes) \
+ ((rotor)->rotate_if_needed((rotor), (vob), bytes))
+
+/*
+ * tc_rotate_init:
+ * initialize a TCRotateContext with given basenames both for
+ * audio and video output files.
+ * Uses null rotation function as default rotation function:
+ * this means that output rotation just never happen.
+ *
+ * Parameters:
+ * rotor: pointer to a TCRotateContext structure to
+ * initialize.
+ * video_base_name: basename for main export file (Audio + Video).
+ * audio_base_name: basename for auxiliary export file
+ * (separate audio track).
+ * Return value:
+ * None.
+ */
+static void tc_rotate_init(TCRotateContext *rotor,
+ const char *video_base_name,
+ const char *audio_base_name)
+{
+ if (rotor != NULL) {
+ memset(rotor, 0, sizeof(TCRotateContext));
+ rotor->video_base_name = video_base_name;
+ rotor->audio_base_name = audio_base_name;
+ if (video_base_name == NULL || strlen(video_base_name) == 0
+ || strcmp(video_base_name, "/dev/null") == 0) {
+ rotor->null_flag = TC_TRUE;
+ } else {
+ rotor->null_flag = TC_FALSE;
+ strlcpy(rotor->video_path_buf, video_base_name,
+ sizeof(rotor->video_path_buf));
+ /*
+ * FIXME: Yep, this taste like a duplicate.
+ * The whole *_out_file thing need a deep review,
+ * but I want to go a little ahead with the whole
+ * NMS-powered export layer and write a few more
+ * NMS export modules before to go with this. -- FR
+ */
+ if (audio_base_name == NULL || strlen(audio_base_name) == 0
+ || strcmp(audio_base_name, video_base_name) == 0
+ || strcmp(audio_base_name, "/dev/null") == 0) {
+ /*
+ * DO NOT separate export audio track, use the same
+ * export file both for audio and for video
+ */
+ strlcpy(rotor->audio_path_buf, video_base_name,
+ sizeof(rotor->audio_path_buf));
+ } else {
+ /* separate audio file */
+ strlcpy(rotor->audio_path_buf, audio_base_name,
+ sizeof(rotor->audio_path_buf));
+ }
+ }
+ rotor->rotate_if_needed = tc_rotate_if_needed_null;
+ }
+}
+
+/*
+ * tc_rotate_set {frames,bytes}_limit:
+ * setup respecitvely frames and bytes limit for each output chunk.
+ * When calling this function user ask for rotation, so they also
+ * directly updates vob.{video,audio}_out_file so even first
+ * tc_encoder_open() later call will uses names of the right format
+ * (i.e. with the same layout of second and further chunks).
+ * This is done in order to avoid any later rename() and disomogeneities
+ * in output file name as experienced in transcode 1.0.x and before.
+ *
+ * Calling this functions multiple times will not hurt anything,
+ * but only the last limit set will be honoured. In other words,
+ * it's impossible (yet) to limit output BOTH for frames and for size.
+ * This may change in future releases.
+ *
+ * Parameters:
+ * rotor: TCRotateContext to set limit on.
+ * vob: pointer to vob structure to update.
+ * frames: frame limit for each output chunk.
+ * bytes: size limit for each output chunk.
+ * Return value:
+ * None
+ * Side effects:
+ * vob parameter will be updated. Modified fields:
+ * video_out_file, audio_out_file.
+ */
+
+#define PREPARE_OUTPUT_NAME(rotor, vob) \
+ if ((rotor)->chunk_num == 0) \
+ tc_rotate_output_name((rotor), (vob))
+
+static void tc_rotate_set_frames_limit(TCRotateContext *rotor,
+ vob_t *vob, uint32_t frames)
+{
+ if (rotor != NULL && !rotor->null_flag) {
+ rotor->chunk_frames = frames;
+ rotor->rotate_if_needed = tc_rotate_if_needed_by_frames;
+ PREPARE_OUTPUT_NAME(rotor, vob);
+ }
+}
+
+static void tc_rotate_set_bytes_limit(TCRotateContext *rotor,
+ vob_t *vob, uint64_t bytes)
+{
+ if (rotor != NULL && !rotor->null_flag) {
+ rotor->chunk_bytes = bytes;
+ rotor->rotate_if_needed = tc_rotate_if_needed_by_bytes;
+ PREPARE_OUTPUT_NAME(rotor, vob);
+ }
+}
+
+#undef PREPARE_OUTPUT_NAME
+
+/* helpers ***************************************************************/
+
+/*
+ * all rotation helpers uses at least if()s as possible, so we must
+ * drop paranoia here
+ */
+
+/*
+ * tc_rotate_output_name:
+ * make names of new main/auxiliary output file chunk and updates
+ * vob fields accordingly.
+ *
+ * Parameters:
+ * rotor: TCRotateContext to use to make new output name(s).
+ * vob: pointer to vob_t structure to update.
+ * Return value:
+ * none.
+ */
+
+/* pretty naif, yet. */
+/* FIXME: OK, we must deeply review the whole *out-file thing ASAP */
+static void tc_rotate_output_name(TCRotateContext *rotor, vob_t *vob)
+{
+ tc_snprintf(rotor->video_path_buf, sizeof(rotor->video_path_buf),
+ "%s-%03i", rotor->video_base_name, rotor->chunk_num);
+ tc_snprintf(rotor->audio_path_buf, sizeof(rotor->audio_path_buf),
+ "%s-%03i", rotor->audio_base_name, rotor->chunk_num);
+ vob->video_out_file = rotor->video_path_buf;
+ vob->audio_out_file = rotor->audio_path_buf;
+ rotor->chunk_num++;
+}
+
+/*************************************************************************/
+/*
+ * real rotation policy implementations. Rotate output file(s)
+ * respectively:
+ * - never (_null)
+ * - when encoded frames reach limit (_by_frames)
+ * - when encoded AND written *bytes* reach limit (_by_bytes).
+ *
+ * For details see documentation of TCExportRotate above.
+ */
+
+#define ROTATE_UPDATE_COUNTERS(bytes) do { \
+ rotor->encoded_bytes += (bytes); \
+} while (0);
+
+static int tc_rotate_if_needed_null(TCRotateContext *rotor,
+ vob_t *vob, uint32_t bytes)
+{
+ ROTATE_UPDATE_COUNTERS(bytes);
+ return TC_OK;
+}
+
+#define ROTATE_COMMON_CODE(rotor, vob) do { \
+ ret = tc_encoder_close(); \
+ if (ret != TC_OK) { \
+ tc_log_error(__FILE__, "unable to close output stream"); \
+ ret = TC_ERROR; \
+ } else { \
+ tc_rotate_output_name((rotor), (vob)); \
+ tc_log_info(__FILE__, "rotating video output stream to %s", \
+ (rotor)->video_path_buf); \
+ tc_log_info(__FILE__, "rotating audio output stream to %s", \
+ (rotor)->audio_path_buf); \
+ ret = tc_encoder_open((vob)); \
+ if (ret != TC_OK) { \
+ tc_log_error(__FILE__, "unable to reopen output stream"); \
+ ret = TC_ERROR; \
+ } \
+ } \
+} while (0)
+
+
+static int tc_rotate_if_needed_by_frames(TCRotateContext *rotor,
+ vob_t *vob, uint32_t bytes)
+{
+ int ret = TC_OK;
+ ROTATE_UPDATE_COUNTERS(bytes);
+
+ if (tc_get_frames_encoded() >= rotor->chunk_frames) {
+ ROTATE_COMMON_CODE(rotor, vob);
+ }
+ return ret;
+}
+
+static int tc_rotate_if_needed_by_bytes(TCRotateContext *rotor,
+ vob_t *vob, uint32_t bytes)
+{
+ int ret = TC_OK;
+ ROTATE_UPDATE_COUNTERS(bytes);
+
+ if (rotor->encoded_bytes >= rotor->chunk_bytes) {
+ ROTATE_COMMON_CODE(rotor, vob);
+ }
+ return ret;
+}
+
+#undef ROTATE_COMMON_CODE
+#undef ROTATE_UPDATE_COUNTERS
+
+/*************************************************************************/
+/*************************************************************************/
+/* real encoder code */
+
+
+struct tcencoderdata_ {
+ /* flags, used internally */
+ int error_flag;
+ int fill_flag;
+
+ /* frame boundaries */
+ int frame_first; // XXX
+ int frame_last; // XXX
+ /* needed by encoder_skip */
+ int saved_frame_last; // XXX
+
+ int this_frame_last; // XXX
+ int old_frame_last; // XXX
+
+ TCEncoderBuffer *buffer;
+
+ vframe_list_t *venc_ptr;
+ aframe_list_t *aenc_ptr;
+
+ TCFactory factory;
+
+ TCModule vid_mod;
+ TCModule aud_mod;
+ TCModule mplex_mod;
+
+ TCRotateContext rotor_data;
+
+#ifdef SUPPORT_OLD_ENCODER
+ transfer_t export_para;
+
+ void *ex_a_handle;
+ void *ex_v_handle;
+#endif
+};
+
+static TCEncoderData encdata = {
+ .error_flag = 0,
+ .fill_flag = 0,
+ .frame_first = 0,
+ .frame_last = 0,
+ .saved_frame_last = 0,
+ .this_frame_last = 0,
+ .old_frame_last = 0,
+ .buffer = NULL,
+ .venc_ptr = NULL,
+ .aenc_ptr = NULL,
+ .factory = NULL,
+ .vid_mod = NULL,
+ .aud_mod = NULL,
+ .mplex_mod = NULL,
+ /* rotor_data explicitely initialized later */
+#ifdef SUPPORT_OLD_ENCODER
+ .ex_a_handle = NULL,
+ .ex_v_handle = NULL,
+#endif
+};
+
+
+#define RESET_ATTRIBUTES(ptr) do { \
+ (ptr)->attributes = 0; \
+} while (0)
+
+/*
+ * is_last_frame:
+ * check if current frame it's supposed to be the last one in
+ * encoding frame range. Catch all all known special cases
+ *
+ * Parameters:
+ * encdata: fetch current frame id from this structure reference.
+ * cluster_mode: boolean flag. When in cluster mode we need to take
+ * some special care.
+ * Return value:
+ * !0: current frame is supposed to be the last one
+ * 0: otherwise
+ */
+static int is_last_frame(TCEncoderData *encdata, int cluster_mode)
+{
+ int fid = encdata->buffer->frame_id;
+ if (cluster_mode) {
+ fid -= tc_get_frames_dropped();
+ }
+
+ if ((encdata->buffer->vptr->attributes & TC_FRAME_IS_END_OF_STREAM
+ || encdata->buffer->aptr->attributes & TC_FRAME_IS_END_OF_STREAM)) {
+ /* `consume' the flag(s) */
+ encdata->buffer->vptr->attributes &= ~TC_FRAME_IS_END_OF_STREAM;
+ encdata->buffer->aptr->attributes &= ~TC_FRAME_IS_END_OF_STREAM;
+ return 1;
+ }
+ return (fid == encdata->frame_last);
+}
+
+/*
+ * export_update_formats:
+ * coerce exported formats to the default ones from the loaded
+ * encoder modules IF AND ONLY IF user doesn't have requested
+ * specific ones.
+ *
+ * That's a temporary workaround until we have a full-NMS
+ * export layer.
+ *
+ * Parameters:
+ * vob: pointer to vob_t structure to update.
+ * vinfo: pointer to TCModuleInfo of video encoder module.
+ * ainfo: pointer to TCModuleInfo of audio encoder module.
+ * Return value:
+ * None
+ */
+static void export_update_formats(vob_t *vob, const TCModuleInfo *vinfo,
+ const TCModuleInfo *ainfo)
+{
+ if (vob == NULL || vinfo == NULL || ainfo == NULL) {
+ /* should never happen */
+ tc_log_error(__FILE__, "missing export formats references");
+ }
+ /*
+ * OK, that's pretty hackish since export_attributes should
+ * go away in near future. Neverthless, ex_a_codec features
+ * a pretty unuseful default (CODEC_MP3), so we don't use
+ * such default value to safely distinguish between -N given
+ * or not given.
+ * And so we must use another flag, and export_attributes are
+ * the simplest things that work, now/
+ */
+ if (!(vob->export_attributes & TC_EXPORT_ATTRIBUTE_VCODEC)) {
+ vob->ex_v_codec = vinfo->codecs_out[0];
+ }
+ if (!(vob->export_attributes & TC_EXPORT_ATTRIBUTE_ACODEC)) {
+ vob->ex_a_codec = ainfo->codecs_out[0];
+ }
+}
+
+/* ------------------------------------------------------------
+ *
+ * export init
+ *
+ * ------------------------------------------------------------*/
+
+int tc_export_init(TCEncoderBuffer *buffer, TCFactory factory)
+{
+ if (buffer == NULL) {
+ tc_log_error(__FILE__, "missing encoder buffer reference");
+ return TC_ERROR;
+ }
+ encdata.buffer = buffer;
+
+#ifndef SUPPORT_OLD_ENCODER // factory==NULL to signal use of old code
+ if (factory == NULL) {
+ tc_log_error(__FILE__, "missing factory reference");
+ return TC_ERROR;
+ }
+#endif
+ encdata.factory = factory;
+ return TC_OK;
+}
+
+int tc_export_setup(vob_t *vob,
+ const char *a_mod, const char *v_mod, const char *m_mod)
+{
+ int match = 0;
+ const char *mod_name = NULL;
+
+#ifdef SUPPORT_OLD_ENCODER
+ if (!encdata.factory)
+ return OLD_tc_export_setup(vob, a_mod, v_mod);
+#endif
+
+ if (verbose >= TC_DEBUG) {
+ tc_log_info(__FILE__, "loading export modules");
+ }
+
+ mod_name = (a_mod == NULL) ?TC_DEFAULT_EXPORT_AUDIO :a_mod;
+ encdata.aud_mod = tc_new_module(encdata.factory, "encode", mod_name, TC_AUDIO);
+ if (!encdata.aud_mod) {
+ tc_log_error(__FILE__, "can't load audio encoder");
+ return TC_ERROR;
+ }
+ mod_name = (v_mod == NULL) ?TC_DEFAULT_EXPORT_VIDEO :v_mod;
+ encdata.vid_mod = tc_new_module(encdata.factory, "encode", mod_name, TC_VIDEO);
+ if (!encdata.vid_mod) {
+ tc_log_error(__FILE__, "can't load video encoder");
+ return TC_ERROR;
+ }
+ mod_name = (m_mod == NULL) ?TC_DEFAULT_EXPORT_MPLEX :m_mod;
+ encdata.mplex_mod = tc_new_module(encdata.factory, "multiplex", mod_name,
+ TC_VIDEO|TC_AUDIO);
+ if (!encdata.mplex_mod) {
+ tc_log_error(__FILE__, "can't load multiplexor");
+ return TC_ERROR;
+ }
+ export_update_formats(vob, tc_module_get_info(encdata.vid_mod),
+ tc_module_get_info(encdata.aud_mod));
+
+ match = tc_module_match(vob->ex_a_codec,
+ encdata.aud_mod, encdata.mplex_mod);
+ if (!match) {
+ tc_log_error(__FILE__, "audio encoder incompatible "
+ "with multiplexor");
+ return TC_ERROR;
+ }
+ match = tc_module_match(vob->ex_v_codec,
+ encdata.vid_mod, encdata.mplex_mod);
+ if (!match) {
+ tc_log_error(__FILE__, "video encoder incompatible "
+ "with multiplexor");
+ return TC_ERROR;
+ }
+ tc_rotate_init(&encdata.rotor_data,
+ vob->video_out_file, vob->audio_out_file);
+
+ return TC_OK;
+}
+
+/* ------------------------------------------------------------
+ *
+ * export close, unload modules
+ *
+ * ------------------------------------------------------------*/
+
+void tc_export_shutdown(void)
+{
+#ifdef SUPPORT_OLD_ENCODER
+ if (!encdata.factory)
+ return OLD_tc_export_shutdown();
+#endif
+
+ if (verbose >= TC_DEBUG) {
+ tc_log_info(__FILE__, "unloading export modules");
+ }
+
+ tc_del_module(encdata.factory, encdata.mplex_mod);
+ tc_del_module(encdata.factory, encdata.vid_mod);
+ tc_del_module(encdata.factory, encdata.aud_mod);
+}
+
+
+/* ------------------------------------------------------------
+ *
+ * encoder init
+ *
+ * ------------------------------------------------------------*/
+
+int tc_encoder_init(vob_t *vob)
+{
+ int ret;
+ const char *options = NULL;
+
+#ifdef SUPPORT_OLD_ENCODER
+ if (!encdata.factory)
+ return OLD_tc_encoder_init(vob);
+#endif
+
+ ret = alloc_buffers(&encdata);
+ if (ret != TC_OK) {
+ tc_log_error(__FILE__, "can't allocate encoder buffers");
+ return TC_ERROR;
+ }
+
+ options = (vob->ex_v_string) ?vob->ex_v_string :"";
+ ret = tc_module_configure(encdata.vid_mod, options, vob);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "video export module error: init failed");
+ return TC_ERROR;
+ }
+
+ options = (vob->ex_a_string) ?vob->ex_a_string :"";
+ ret = tc_module_configure(encdata.aud_mod, options, vob);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "audio export module error: init failed");
+ return TC_ERROR;
+ }
+
+ return TC_OK;
+}
+
+
+/* ------------------------------------------------------------
+ *
+ * encoder open
+ *
+ * ------------------------------------------------------------*/
+
+int tc_encoder_open(vob_t *vob)
+{
+ int ret;
+ const char *options = NULL;
+
+#ifdef SUPPORT_OLD_ENCODER
+ if (!encdata.factory)
+ return OLD_tc_encoder_open(vob);
+#endif
+
+ options = vob->ex_m_string ? vob->ex_m_string : "";
+ ret = tc_module_configure(encdata.mplex_mod, options, vob);
+ if (ret == TC_ERROR) {
+ tc_log_warn(__FILE__, "multiplexor module error: init failed");
+ return TC_ERROR;
+ }
+
+ // XXX
+ tc_module_pass_extradata(encdata.vid_mod, encdata.mplex_mod);
+
+ return TC_OK;
+}
+
+
+/* ------------------------------------------------------------
+ *
+ * encoder close
+ *
+ * ------------------------------------------------------------*/
+
+int tc_encoder_close(void)
+{
+ int ret;
+
+#ifdef SUPPORT_OLD_ENCODER
+ if (!encdata.factory)
+ return OLD_tc_encoder_close();
+#endif
+
+ /* old style code handle flushing in modules, not here */
+ ret = encoder_flush(&encdata);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "error while closing encoder: flush failed");
+ return TC_ERROR;
+ }
+
+ ret = tc_module_stop(encdata.mplex_mod);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "multiplexor module error: stop failed");
+ return TC_ERROR;
+ }
+
+ if(verbose >= TC_DEBUG) {
+ tc_log_info(__FILE__, "encoder closed");
+ }
+ return TC_OK;
+}
+
+
+/* ------------------------------------------------------------
+ *
+ * encoder stop
+ *
+ * ------------------------------------------------------------*/
+
+int tc_encoder_stop(void)
+{
+ int ret;
+
+#ifdef SUPPORT_OLD_ENCODER
+ if (!encdata.factory)
+ return OLD_tc_encoder_stop();
+#endif
+
+ ret = tc_module_stop(encdata.vid_mod);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "video export module error: stop failed");
+ return TC_ERROR;
+ }
+
+ ret = tc_module_stop(encdata.aud_mod);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "audio export module error: stop failed");
+ return TC_ERROR;
+ }
+
+ free_buffers(&encdata);
+
+ if(verbose >= TC_DEBUG) {
+ tc_log_info(__FILE__, "encoder stopped");
+ }
+ return TC_OK;
+}
+
+/* ------------------------------------------------------------
+ *
+ * encoder main loop helpers
+ *
+ * ------------------------------------------------------------*/
+
+static int alloc_buffers(TCEncoderData *data)
+{
+ data->venc_ptr = vframe_alloc_single();
+ if (data->venc_ptr == NULL) {
+ goto no_vframe;
+ }
+ data->aenc_ptr = aframe_alloc_single();
+ if (data->aenc_ptr == NULL) {
+ goto no_aframe;
+ }
+ return TC_OK;
+
+no_aframe:
+ tc_del_video_frame(data->venc_ptr);
+no_vframe:
+ return TC_ERROR;
+}
+
+static void free_buffers(TCEncoderData *data)
+{
+ tc_del_video_frame(data->venc_ptr);
+ tc_del_audio_frame(data->aenc_ptr);
+}
+
+/*
+ * NOTE about counter/condition/mutex handling inside various
+ * encoder helpers.
+ *
+ * Code are still a little bit confusing since things aren't
+ * updated or used at the same function level.
+ * Code works, but isn't still well readable.
+ * We need stil more cleanup and refactoring for future releases.
+ */
+
+
+/*
+ * dispatch the acquired frames to encoder modules, and adjust frame counters
+ */
+static int encoder_export(TCEncoderData *data, vob_t *vob)
+{
+ int video_delayed = 0;
+ int ret;
+
+#ifdef SUPPORT_OLD_ENCODER
+ if (!encdata.factory)
+ return OLD_encoder_export(data, vob);
+#endif
+ /* remove spurious attributes */
+ RESET_ATTRIBUTES(data->venc_ptr);
+ RESET_ATTRIBUTES(data->aenc_ptr);
+
+ /* step 1: encode video */
+ ret = tc_module_encode_video(data->vid_mod,
+ data->buffer->vptr, data->venc_ptr);
+ if (ret != TC_OK) {
+ tc_log_error(__FILE__, "error encoding video frame");
+ data->error_flag = 1;
+ }
+ if (data->venc_ptr->attributes & TC_FRAME_IS_DELAYED) {
+ data->venc_ptr->attributes &= ~TC_FRAME_IS_DELAYED;
+ video_delayed = 1;
+ }
+
+ /* step 2: encode audio */
+ if (video_delayed) {
+ data->buffer->aptr->attributes |= TC_FRAME_IS_CLONED;
+ tc_log_info(__FILE__, "Delaying audio");
+ } else {
+ ret = tc_module_encode_audio(data->aud_mod,
+ data->buffer->aptr, data->aenc_ptr);
+ if (ret != TC_OK) {
+ tc_log_error(__FILE__, "error encoding audio frame");
+ data->error_flag = 1;
+ }
+ }
+
+ /* step 3: multiplex and rotate */
+ // FIXME: Do we really need bytes-written returned from this, or can
+ // we just return TC_OK/TC_ERROR like other functions? --AC
+ ret = tc_module_multiplex(data->mplex_mod,
+ data->venc_ptr, data->aenc_ptr);
+ if (ret < 0) {
+ tc_log_error(__FILE__, "error multiplexing encoded frames");
+ data->error_flag = 1;
+ }
+ data->error_flag = TC_ROTATE_IF_NEEDED(&encdata.rotor_data, vob, ret);
+
+ /* step 4: show and update stats */
+ if (tc_progress_meter) {
+ int last = (data->frame_last == TC_FRAME_LAST)
+ ?(-1) :data->frame_last;
+ if (!data->fill_flag) {
+ data->fill_flag = 1;
+ }
+ counter_print(1, data->buffer->frame_id, data->frame_first, last);
+ }
+
+ tc_update_frames_encoded(1);
+ return (data->error_flag) ?TC_ERROR :TC_OK;
+}
+
+
+#define RETURN_IF_NOT_OK(RET, KIND) do { \
+ if ((RET) != TC_OK) { \
+ tc_log_error(__FILE__, "error encoding final %s frame", (KIND)); \
+ return TC_ERROR; \
+ } \
+} while (0)
+
+#define RETURN_IF_MUX_ERROR(BYTES) do { \
+ if ((BYTES) < 0) { \
+ tc_log_error(__FILE__, "error multiplexing final audio frame"); \
+ return TC_ERROR; \
+ } \
+} while (0)
+
+
+/* DO NOT rotate here, this data belongs to current chunk */
+static int encoder_flush(TCEncoderData *data)
+{
+ int ret = TC_ERROR, bytes = 0;
+
+ do {
+ RESET_ATTRIBUTES(data->aenc_ptr);
+ ret = tc_module_encode_audio(data->aud_mod, NULL, data->aenc_ptr);
+ RETURN_IF_NOT_OK(ret, "audio");
+
+ bytes = tc_module_multiplex(data->mplex_mod, NULL, data->aenc_ptr);
+ } while (bytes != 0);
+ RETURN_IF_MUX_ERROR(bytes);
+
+ do {
+ RESET_ATTRIBUTES(data->venc_ptr);
+ ret = tc_module_encode_video(data->vid_mod, NULL, data->venc_ptr);
+ RETURN_IF_NOT_OK(ret, "video");
+
+ bytes = tc_module_multiplex(data->mplex_mod, data->venc_ptr, NULL);
+ } while (bytes != 0);
+ RETURN_IF_MUX_ERROR(bytes);
+
+ return TC_OK;
+}
+
+
+void tc_export_rotation_limit_frames(vob_t *vob, uint32_t frames)
+{
+#ifdef SUPPORT_OLD_ENCODER
+ if (!encdata.factory)
+ return;
+#endif
+
+ tc_rotate_set_frames_limit(&encdata.rotor_data, vob, frames);
+}
+
+void tc_export_rotation_limit_megabytes(vob_t *vob, uint32_t megabytes)
+{
+#ifdef SUPPORT_OLD_ENCODER
+ if (!encdata.factory)
+ return;
+#endif
+
+ tc_rotate_set_bytes_limit(&encdata.rotor_data,
+ vob, megabytes * 1024 * 1024);
+}
+
+/*************************************************************************/
+
+#ifdef SUPPORT_OLD_ENCODER
+
+#include "dl_loader.h"
+
+/* ------------------------------------------------------------
+ *
+ * export init
+ *
+ * ------------------------------------------------------------*/
+
+static int OLD_tc_export_setup(vob_t *vob,
+ const char *a_mod, const char *v_mod)
+{
+ const char *mod_name = NULL;
+
+ // load export modules
+ mod_name = (a_mod == NULL) ?TC_DEFAULT_EXPORT_AUDIO :a_mod;
+ encdata.ex_a_handle = load_module((char*)mod_name, TC_EXPORT + TC_AUDIO);
+ if (encdata.ex_a_handle == NULL) {
+ tc_log_warn(__FILE__, "loading audio export module failed");
+ return TC_ERROR;
+ }
+
+ mod_name = (v_mod==NULL) ?TC_DEFAULT_EXPORT_VIDEO :v_mod;
+ encdata.ex_v_handle = load_module((char*)mod_name, TC_EXPORT + TC_VIDEO);
+ if (encdata.ex_v_handle == NULL) {
+ tc_log_warn(__FILE__, "loading video export module failed");
+ return TC_ERROR;
+ }
+
+ encdata.export_para.flag = verbose;
+ tca_export(TC_EXPORT_NAME, &encdata.export_para, NULL);
+
+ if(encdata.export_para.flag != verbose) {
+ // module returned capability flag
+ int cc=0;
+
+ if (verbose & TC_DEBUG) {
+ tc_log_info(__FILE__, "audio capability flag 0x%x | 0x%x",
+ encdata.export_para.flag, vob->im_a_codec);
+ }
+
+ switch (vob->im_a_codec) {
+ case CODEC_PCM:
+ cc = (encdata.export_para.flag & TC_CAP_PCM);
+ break;
+ case CODEC_AC3:
+ cc = (encdata.export_para.flag & TC_CAP_AC3);
+ break;
+ case CODEC_RAW:
+ cc = (encdata.export_para.flag & TC_CAP_AUD);
+ break;
+ default:
+ cc = 0;
+ }
+
+ if (cc == 0) {
+ tc_log_warn(__FILE__, "audio codec not supported by export module");
+ return TC_ERROR;
+ }
+ } else { /* encdata.export_para.flag == verbose */
+ if (vob->im_a_codec != CODEC_PCM) {
+ tc_log_warn(__FILE__, "audio codec not supported by export module");
+ return TC_ERROR;
+ }
+ }
+
+ encdata.export_para.flag = verbose;
+ tcv_export(TC_EXPORT_NAME, &encdata.export_para, NULL);
+
+ if (encdata.export_para.flag != verbose) {
+ // module returned capability flag
+ int cc = 0;
+
+ if (verbose & TC_DEBUG) {
+ tc_log_info(__FILE__, "video capability flag 0x%x | 0x%x",
+ encdata.export_para.flag, vob->im_v_codec);
+ }
+
+ switch (vob->im_v_codec) {
+ case CODEC_RGB:
+ cc = (encdata.export_para.flag & TC_CAP_RGB);
+ break;
+ case CODEC_YUV:
+ cc = (encdata.export_para.flag & TC_CAP_YUV);
+ break;
+ case CODEC_YUV422:
+ cc = (encdata.export_para.flag & TC_CAP_YUV422);
+ break;
+ case CODEC_RAW:
+ case CODEC_RAW_YUV: /* fallthrough */
+ cc = (encdata.export_para.flag & TC_CAP_VID);
+ break;
+ default:
+ cc = 0;
+ }
+
+ if (cc == 0) {
+ tc_log_warn(__FILE__, "video codec not supported by export module");
+ return TC_ERROR;
+ }
+ } else { /* encdata.export_para.flag == verbose */
+ if (vob->im_v_codec != CODEC_RGB) {
+ tc_log_warn(__FILE__, "video codec not supported by export module");
+ return TC_ERROR;
+ }
+ }
+
+ return TC_OK;
+}
+
+/* ------------------------------------------------------------
+ *
+ * export close, unload modules
+ *
+ * ------------------------------------------------------------*/
+
+static void OLD_tc_export_shutdown(void)
+{
+ if (verbose & TC_DEBUG) {
+ tc_log_info(__FILE__, "unloading export modules");
+ }
+
+ unload_module(encdata.ex_a_handle);
+ unload_module(encdata.ex_v_handle);
+}
+
+
+/* ------------------------------------------------------------
+ *
+ * encoder init
+ *
+ * ------------------------------------------------------------*/
+
+static int OLD_tc_encoder_init(vob_t *vob)
+{
+ int ret;
+
+ encdata.export_para.flag = TC_VIDEO;
+ ret = tcv_export(TC_EXPORT_INIT, &encdata.export_para, vob);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "video export module error: init failed");
+ return TC_ERROR;
+ }
+
+ encdata.export_para.flag = TC_AUDIO;
+ ret = tca_export(TC_EXPORT_INIT, &encdata.export_para, vob);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "audio export module error: init failed");
+ return TC_ERROR;
+ }
+
+ return TC_OK;
+}
+
+
+/* ------------------------------------------------------------
+ *
+ * encoder open
+ *
+ * ------------------------------------------------------------*/
+
+static int OLD_tc_encoder_open(vob_t *vob)
+{
+ int ret;
+
+ encdata.export_para.flag = TC_VIDEO;
+ ret = tcv_export(TC_EXPORT_OPEN, &encdata.export_para, vob);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "video export module error: open failed");
+ return TC_ERROR;
+ }
+
+ encdata.export_para.flag = TC_AUDIO;
+ ret = tca_export(TC_EXPORT_OPEN, &encdata.export_para, vob);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "audio export module error: open failed");
+ return TC_ERROR;
+ }
+
+ return TC_OK;
+}
+
+
+/* ------------------------------------------------------------
+ *
+ * encoder close
+ *
+ * ------------------------------------------------------------*/
+
+static int OLD_tc_encoder_close(void)
+{
+ /*
+ * close, errors not fatal.
+ * flushing handled internally by export modules.
+ */
+
+ encdata.export_para.flag = TC_AUDIO;
+ tca_export(TC_EXPORT_CLOSE, &encdata.export_para, NULL);
+
+ encdata.export_para.flag = TC_VIDEO;
+ tcv_export(TC_EXPORT_CLOSE, &encdata.export_para, NULL);
+
+ if(verbose & TC_DEBUG) {
+ tc_log_info(__FILE__, "encoder closed");
+ }
+ return TC_OK;
+}
+
+
+/* ------------------------------------------------------------
+ *
+ * encoder stop
+ *
+ * ------------------------------------------------------------*/
+
+static int OLD_tc_encoder_stop(void)
+{
+ int ret;
+
+ encdata.export_para.flag = TC_VIDEO;
+ ret = tcv_export(TC_EXPORT_STOP, &encdata.export_para, NULL);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "video export module error: stop failed");
+ return TC_ERROR;
+ }
+
+ encdata.export_para.flag = TC_AUDIO;
+ ret = tca_export(TC_EXPORT_STOP, &encdata.export_para, NULL);
+ if (ret != TC_OK) {
+ tc_log_warn(__FILE__, "audio export module error: stop failed");
+ return TC_ERROR;
+ }
+
+ return TC_OK;
+}
+
+/*
+ * dispatch the acquired frames to encoder modules
+ */
+static int OLD_encoder_export(TCEncoderData *data, vob_t *vob)
+{
+ int video_delayed = 0;
+
+ /* encode and export video frame */
+ data->export_para.buffer = data->buffer->vptr->video_buf;
+ data->export_para.size = data->buffer->vptr->video_size;
+ data->export_para.attributes = data->buffer->vptr->attributes;
+ if (data->buffer->vptr->attributes & TC_FRAME_IS_KEYFRAME) {
+ data->export_para.attributes |= TC_FRAME_IS_KEYFRAME;
+ }
+ data->export_para.flag = TC_VIDEO;
+
+ if(tcv_export(TC_EXPORT_ENCODE, &data->export_para, vob) < 0) {
+ tc_log_warn(__FILE__, "error encoding video frame");
+ data->error_flag = 1;
+ }
+ /* maybe clone? */
+ data->buffer->vptr->attributes = data->export_para.attributes;
+ if (data->buffer->vptr->attributes & TC_FRAME_IS_DELAYED) {
+ data->buffer->vptr->attributes &= ~TC_FRAME_IS_DELAYED;
+ video_delayed = 1;
+ }
+
+ /* encode and export audio frame */
+ data->export_para.buffer = data->buffer->aptr->audio_buf;
+ data->export_para.size = data->buffer->aptr->audio_size;
+ data->export_para.attributes = data->buffer->aptr->attributes;
+ data->export_para.flag = TC_AUDIO;
+
+ if(video_delayed > 0) {
+ data->buffer->aptr->attributes |= TC_FRAME_IS_CLONED;
+ tc_log_info(__FILE__, "Delaying audio");
+ } else {
+ if (tca_export(TC_EXPORT_ENCODE, &data->export_para, vob) < 0) {
+ tc_log_warn(__FILE__, "error encoding audio frame");
+ data->error_flag = 1;
+ }
+
+ /* maybe clone? */
+ data->buffer->aptr->attributes = data->export_para.attributes;
+ }
+
+ if (tc_progress_meter) {
+ int last = (data->frame_last == TC_FRAME_LAST) ?(-1) :data->frame_last;
+ if (!data->fill_flag) {
+ data->fill_flag = 1;
+ }
+ counter_print(1, data->buffer->frame_id, data->frame_first, last);
+ }
+
+ // XXX: _always_ update?
+ tc_update_frames_encoded(1);
+ return data->error_flag ? TC_ERROR : TC_OK;
+}
+
+
+/*************************************************************************
+ * old style rotation support code.
+ * TEMPORARY merged here until it will be deleted together with
+ * old encoder code when NMS-powered export layer is ready to switch
+ * (read: when we have enough encode/multiplexor module to go).
+ *************************************************************************/
+
+#include "libtc/xio.h"
+
+//-----------------------------------------------------------------
+//
+// r,R - switch output file
+//
+//-----------------------------------------------------------------
+
+static int rotate_ctr = 0;
+static int rotate_flag = 0;
+static char *base = NULL;
+
+void tc_outstream_rotate_request(void)
+{
+ //set flag
+ rotate_flag = 1;
+}
+
+void tc_outstream_rotate(void)
+{
+ char buf[TC_BUF_MAX];
+ vob_t *vob=tc_get_vob();
+
+ if (!rotate_flag)
+ return;
+
+ //reset flag to avoid re-entry
+ rotate_flag=0;
+
+ // do not try to rename /dev/null
+ if(strcmp(vob->video_out_file, "/dev/null") == 0)
+ return;
+
+ // get current outfile basename
+ base = tc_strdup(vob->video_out_file);
+
+ //check
+ if (base == NULL)
+ return;
+
+ // close output
+ if (tc_encoder_close()<0)
+ tc_error("failed to close output");
+
+ // create new filename
+ tc_snprintf(buf, sizeof(buf), "%s-%03d", base, rotate_ctr++);
+ //rename old outputfile
+ if (xio_rename(base, buf) < 0)
+ tc_error("failed to rename output file");
+
+ // reopen output
+ if (tc_encoder_open(vob) < 0)
+ tc_error("failed to open output");
+
+ tc_log_info(__FILE__, "outfile %s saved to %s", base, buf);
+ free(base);
+}
+
+/*************************************************************************/
+
+#endif // SUPPORT_OLD_ENCODER
+
+/*
+ * fake encoding, simply adjust frame counters.
+ */
+static void encoder_skip(TCEncoderData *data)
+{
+ if (tc_progress_meter) {
+ if (!data->fill_flag) {
+ data->fill_flag = 1;
+ }
+ counter_print(0, data->buffer->frame_id, data->saved_frame_last,
+ data->frame_first-1);
+ }
+ data->buffer->vptr->attributes |= TC_FRAME_IS_OUT_OF_RANGE;
+ data->buffer->aptr->attributes |= TC_FRAME_IS_OUT_OF_RANGE;
+}
+
+static int need_stop(TCEncoderData *encdata)
+{
+ return !tc_running() || !tc_import_status() || encdata->error_flag;
+}
+
+/* ------------------------------------------------------------
+ *
+ * encoder main loop
+ *
+ * ------------------------------------------------------------*/
+
+void tc_encoder_loop(vob_t *vob, int frame_first, int frame_last)
+{
+ int err = 0, eos = 0; /* End Of Stream flag */
+
+ if (encdata.this_frame_last != frame_last) {
+ encdata.old_frame_last = encdata.this_frame_last;
+ encdata.this_frame_last = frame_last;
+ }
+
+ encdata.error_flag = 0; /* reset */
+ encdata.frame_first = frame_first;
+ encdata.frame_last = frame_last;
+ encdata.saved_frame_last = encdata.old_frame_last;
+
+ while (!need_stop(&encdata)) {
+ /* stop here if pause requested */
+ tc_pause();
+
+ err = encdata.buffer->acquire_video_frame(encdata.buffer, vob);
+ if (err) {
+ if (verbose >= TC_DEBUG) {
+ tc_log_warn(__FILE__, "failed to acquire next raw video frame");
+ }
+ break; /* can't acquire video frame */
+ }
+
+ err = encdata.buffer->acquire_audio_frame(encdata.buffer, vob);
+ if (err) {
+ if (verbose >= TC_DEBUG) {
+ tc_log_warn(__FILE__, "failed to acquire next raw audio frame");
+ }
+ break; /* can't acquire frame */
+ }
+
+ eos = is_last_frame(&encdata, tc_cluster_mode);
+ if (eos) {
+ break;
+ }
+
+ /* check frame id */
+ if (frame_first <= encdata.buffer->frame_id
+ && encdata.buffer->frame_id < frame_last) {
+ encoder_export(&encdata, vob);
+ } else { /* frame not in range */
+ encoder_skip(&encdata);
+ } /* frame processing loop */
+
+ /* release frame buffer memory */
+ encdata.buffer->dispose_video_frame(encdata.buffer);
+ encdata.buffer->dispose_audio_frame(encdata.buffer);
+ }
+ /* main frame decoding loop */
+
+ if (verbose >= TC_CLEANUP) {
+ if (eos) {
+ tc_log_info(__FILE__, "encoder last frame finished (%i/%i)",
+ encdata.buffer->frame_id, encdata.frame_last);
+ }
+ tc_log_info(__FILE__, "export terminated - buffer(s) empty");
+ }
+ return;
+}
+
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/encoder.h b/debian/transcode/transcode-1.1.7/src/encoder.h
new file mode 100644
index 00000000..4ed26992
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/encoder.h
@@ -0,0 +1,324 @@
+/*
+ * encoder.h - interface for the main encoder loop in transcode
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ * Updated and partially rewritten by
+ * Francesco Romani - January 2006
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifndef ENCODER_H
+#define ENCODER_H
+
+#include "transcode.h"
+#include "framebuffer.h"
+
+#include "libtc/tcmodule-core.h"
+#include "encoder-common.h"
+
+/*
+ * MULTITHREADING WARNING:
+ * It is in general *NOT SAFE* to call functions declared on this header from
+ * different threads. See comments below.
+ */
+
+/*************************************************************************
+ * A TCEncoderBuffer structure, alog with it's operations, incapsulate
+ * the actions needed by encoder to acquire and dispose a single A/V frame
+ * to encode.
+ *
+ * Main purpose of this structure is to help to modularize and cleanup
+ * encoder core code. Unfortunately, a propoer cleanup and refactoring isn't
+ * fully possible without heavily reviewing transcode's inner frame buffering
+ * and frame handling, but this task is really critical and should planned
+ * really carefully.
+ *
+ * The need of TCEncoderBuffer also emerges given the actual frame buffer
+ * handling. TCEncoderBuffer operations take care of hide the most part
+ * of nasty stuff needed by current structure (see comments in
+ * encoder-buffer.c).
+ *
+ * A proper reorganization of frame handling core code will GREATLY shrink,
+ * or even make completely unuseful, the whole TCEncoderBuffer machinery.
+ */
+typedef struct tcencoderbuffer_ TCEncoderBuffer;
+struct tcencoderbuffer_ {
+ int frame_id; /* current frame identifier (both for A and V, yet) */
+
+ vframe_list_t *vptr; /* current video frame */
+ aframe_list_t *aptr; /* current audio frame */
+
+ int (*acquire_video_frame)(TCEncoderBuffer *buf, vob_t *vob);
+ int (*acquire_audio_frame)(TCEncoderBuffer *buf, vob_t *vob);
+ void (*dispose_video_frame)(TCEncoderBuffer *buf);
+ void (*dispose_audio_frame)(TCEncoderBuffer *buf);
+};
+
+/* default main transcode buffer */
+TCEncoderBuffer *tc_get_ringbuffer(int aworkers, int vworkers);
+
+
+/**
+ * tc_export_{audio,video}_notify:
+ * notify encoder that a new {audio,video} frame is ready
+ * to be encoded.
+ * You NEED to call those functions to properly syncronize encoder
+ * and avoid deadlocks.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ */
+void tc_export_audio_notify(void);
+void tc_export_video_notify(void);
+
+/*************************************************************************/
+
+
+/*************************************************************************
+ * helper routines. Client code needs to call those routines before
+ * (tc_export_init/tc_export_setup) or after (tc_export_shutdown)
+ * all the others.
+ */
+
+/*
+ * tc_export_init:
+ * select a TCEncoderBuffer and a TCFactory to use for further
+ * operations. Both buffer and factory will be used until a new
+ * call to tc_export_init occurs.
+ * PLEASE NOTE: there NOT are sensible defaults, so client
+ * cose NEEDS to call this function as first one in code using
+ * encoder.
+ *
+ * Parameters:
+ * buffer: TCEncoderBuffer to use in future encoding loops.
+ * factory: TCFactory to use for future module (un)loading.
+ * Return Value:
+ * 0: succesfull
+ * !0: given one or more bad (NULL) value(s).
+ */
+int tc_export_init(TCEncoderBuffer *buffer, TCFactory factory);
+
+/*
+ * tc_export_setup:
+ * load export modules (encoders and multiplexor) using Module Factory
+ * selected via tc_export_init, checking if loaded modules are
+ * compatible with requested audio/video codec, and prepare for
+ * real encoding.
+ *
+ * Parameters:
+ * vob: pointer to vob_t.
+ * tc_export_setup need to fetch from a vob structure some informations
+ * needed by proper loading (es: module path).
+ * a_mod: name of audio encoder module to load.
+ * v_mod: name of video encoder module to load.
+ * m_mod: name of multiplexor module to load.
+ * Return Value:
+ * 0: succesfull
+ * <0: failure: failed to load one or more requested modules,
+ * *OR* there is at least one incompatibility between requested
+ * modules and requested codecs.
+ * (i.e. audio encoder module VS requested audio codec)
+ * (i.e. video encoder module VS multiplexor module)
+ * Preconditions:
+ * Module Factory avalaible and selected using tc_export_init.
+ */
+int tc_export_setup(vob_t *vob,
+ const char *a_mod, const char *v_mod, const char *m_mod);
+
+
+/*
+ * tc_export_shutdown:
+ * revert operations done by tc_export_setup, unloading encoder and
+ * multiplexor modules.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ * Preconditions:
+ * tc_export_setup() was previously called. To call this function if
+ * tc_export_setup() wasn't called will cause undefined behaviour.
+ */
+void tc_export_shutdown(void);
+
+
+/*************************************************************************
+ * new-style output rotation support.
+ * This couple of functions
+ * tc_export_rotation_limit_frames
+ * tc_export_rotation_limit_megabytes
+ *
+ * Allow the client code to automatically split output into chunks by
+ * specifying a maxmimum size, resp. in frames OR in megabytes, for each
+ * output chunk.
+ *
+ * Those functions MUST BE used BEFORE to call first tc_encoder_open(),
+ * otherwise will fall into unspecifed behaviour.
+ * It's important to note that client code CAN call multiple times
+ * (even if isn't usually useful to do so ;) ) tc_export_rotation_limit*,
+ * but only one limit can be used, so the last limit set will be used.
+ * In other words, is NOT (yet) possible to limit output chunk size
+ * BOTH by frames and by size.
+ */
+
+/*
+ * tc_export_rotation_limit_frames:
+ * rotate output file(s) every given amount of encoded frames.
+ *
+ * Parameters:
+ * vob: pointer to main vob_t structure.
+ * frames: maximum of frames that every output chunk should contain.
+ * Return value:
+ * None.
+ */
+void tc_export_rotation_limit_frames(vob_t *vob, uint32_t frames);
+
+/*
+ * tc_export_rotation_limit_megabytes:
+ * rotate output file(s) after a given amount of data was encoded.
+ *
+ * Parameters:
+ * vob: pointer to main vob_t structure.
+ * megabytes: maximum size that every output chunk should have.
+ * Return value:
+ * None.
+ */
+void tc_export_rotation_limit_megabytes(vob_t *vob, uint32_t megabytes);
+
+
+/*************************************************************************/
+
+/*************************************************************************
+ * main encoder API.
+ *
+ * There isn't explicit reference to encoder data structure,
+ * so there always be one and only one global hidden encoder instance.
+ * In current (and in the prevedible future) doesn't make sense to
+ * have more than one encoder, so it's instance is global, hidden, implicit.
+ *
+ * PLEASE NOTE:
+ * current encoder does not _explicitely_ use more than one thread.
+ * This means that audio and video encoding, as well as multiplexing, happens
+ * sequentially on the same (and unique) encoder thread.
+ * It's definitively possible (and already happens) that real encoder code loaded
+ * by modules uses internally more than one thread, but this is completely opaque
+ * to encoder.
+ */
+
+/*
+ * tc_encoder_init:
+ * initialize the A/V encoders, by (re)configuring encoder modules.
+ *
+ * Parameters:
+ * vob: pointer to vob_t.
+ * tc_encoder_init need to fetch from a vob structure some informations
+ * needed by it's inizalitation.
+ * Return Value:
+ * -1: error configuring modules. Reason of error will be notified
+ * via tc_log*().
+ * 0: succesfull.
+ */
+int tc_encoder_init(vob_t *vob);
+
+/*
+ * tc_encoder_open:
+ * open output file(s), by (re)configuring multiplexor module.
+ *
+ * Parameters:
+ * vob: pointer to vob_t.
+ * tc_encoder_open need to fetch from a vob structure some informations
+ * needed by it's inizalitation.
+ * Return Value:
+ * -1: error configuring module(s) or opening file(s). Reason of error will be
+ * notified via tc_log*().
+ * 0: succesfull.
+ */
+int tc_encoder_open(vob_t *vob);
+
+/*
+ * tc_encoder_loop:
+ * encodes a range of frames from stream(s) using given settings.
+ * This is the main and inner encoding loop.
+ * Encoding usually halts with last frame in range is encountered, but
+ * it can also stop if some error happens when acquiring new frames,
+ * or, of course, if there is an asynchronous stop request
+ * Please note that FIRST frame in given range will be encoded, but
+ * LAST frame in given range will NOT.
+ *
+ * Parameters:
+ * vob: pointer to a vob_t structure holding both informations about
+ * input streams and settings for output streams
+ * (i.e.: bitrate, GOP size...).
+ * frame_first: sequence number of first frame in range to encode.
+ * All frames before this one will be acquired via
+ * TCEncoderBuffer routines, but will also be discarded.
+ * frame_last: sequence number of last frame in range to encode.
+ * *encoding halts when this frame is acquired*, so this
+ * frame will NOT encoded.
+ * Return Value:
+ * None.
+ * Preconditions:
+ * encoder properly initialized. This means:
+ * tc_export_init() called succesfully;
+ * tc_export_setup() called succesfully;
+ * tc_encoder_init() called succesfully;
+ * tc_encoder_open() called succesfully;
+ */
+void tc_encoder_loop(vob_t *vob, int frame_first, int frame_last);
+
+/*
+ * tc_encoder_stop:
+ * stop both the audio and the video encoders.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * 0: succesfull.
+ * <0: failure, reason will be notified via tc_log*().
+ */
+int tc_encoder_stop(void);
+
+/*
+ * tc_encoder_close:
+ * stop multiplexor and close output file.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * 0: succesfull.
+ * <0: failure, reason will be notified via tc_log*().
+ */
+int tc_encoder_close(void);
+
+
+/*************************************************************************/
+
+#endif /* ENCODER_H */
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/export_profile.c b/debian/transcode/transcode-1.1.7/src/export_profile.c
new file mode 100644
index 00000000..08703fff
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/export_profile.c
@@ -0,0 +1,511 @@
+/*
+ * export_profile.c -- transcode export profile support code - implementation
+ * (C) 2006-2010 - Francesco Romani <fromani at gmail dot com>
+ *
+ * This file is part of transcode, a 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <unistd.h>
+
+#include "export_profile.h"
+#include "libtc/libtc.h"
+#include "libtc/cfgfile.h"
+#include "libtc/tccodecs.h"
+
+/* OK, that's quite ugly but I found nothing better, yet.*/
+#ifdef TCEXPORT_PROFILE
+/* same value for both macros */
+# define TC_EXPORT_PROFILE_OPT "-P"
+#else
+# define TC_EXPORT_PROFILE_OPT "--export_prof"
+#endif
+
+#define USER_PROF_PATH ".transcode/profiles"
+
+/* all needed support variables/data packed in a nice structure */
+typedef struct tcexportprofile_ TCExportProfile;
+
+struct tcexportprofile_ {
+ size_t profile_count;
+ char **profiles;
+
+ TCExportInfo info;
+
+ /* auxiliary variables */
+ const char *video_codec;
+ const char *audio_codec;
+
+ const char *pre_clip_area;
+ const char *post_clip_area;
+};
+
+#define CLIP_AREA_INIT { 0, 0, 0, 0 }
+
+/* used in tc_log_*() calls */
+const char *package = __FILE__;
+
+static TCExportProfile prof_data = {
+ .profile_count = 0,
+ .profiles = NULL,
+
+ .video_codec = NULL,
+ .audio_codec = NULL,
+ .pre_clip_area = NULL,
+ .post_clip_area = NULL,
+
+ /*
+ * we need to take care of strings deallocating
+ * them between module_read_config() calls, to
+ * avoid memleaks, so we use NULL marking here.
+ */
+ .info.video.string = NULL,
+ .info.video.module = NULL,
+ .info.video.module_opts = NULL,
+ .info.video.log_file = NULL,
+
+ .info.audio.string = NULL,
+ .info.audio.module = NULL,
+ .info.audio.module_opts = NULL,
+
+ .info.mplex.string = NULL,
+ .info.mplex.module = NULL,
+ .info.mplex.module_opts = NULL,
+ .info.mplex.out_file = NULL,
+ .info.mplex.out_file_aux = NULL,
+
+ /* standard initialization */
+ .info.video.width = PAL_W,
+ .info.video.height = PAL_H,
+ .info.video.keep_asr_flag = TC_FALSE,
+ .info.video.fast_resize_flag = TC_FALSE,
+ .info.video.zoom_interlaced_flag = TC_FALSE,
+ .info.video.pre_clip = CLIP_AREA_INIT,
+ .info.video.post_clip = CLIP_AREA_INIT,
+ .info.video.frc = 3, // XXX (magic number)
+ .info.video.asr = -1, // XXX
+ .info.video.par = 0,
+ .info.video.encode_fields = TC_ENCODE_FIELDS_PROGRESSIVE,
+ .info.video.gop_size = VKEYFRAMES,
+ .info.video.quantizer_min = VMINQUANTIZER,
+ .info.video.quantizer_max = VMAXQUANTIZER,
+ .info.video.format = CODEC_NULL,
+ .info.video.quality = -1,
+ .info.video.bitrate = VBITRATE,
+ .info.video.bitrate_max = VBITRATE,
+ .info.video.pass_number = VMULTIPASS,
+
+ .info.audio.format = CODEC_NULL,
+ .info.audio.quality = -1,
+ .info.audio.bitrate = ABITRATE,
+ .info.audio.sample_rate = RATE,
+ .info.audio.sample_bits = BITS,
+ .info.audio.channels = CHANNELS,
+ .info.audio.mode = AMODE,
+ .info.audio.vbr_flag = TC_FALSE,
+ .info.audio.flush_flag = TC_FALSE,
+ .info.audio.bit_reservoir = TC_TRUE,
+};
+
+/* private helpers: declaration *******************************************/
+
+/*
+ * tc_load_single_export_profile:
+ * tc_load_export_profile backend.
+ * Find and load, by looking into user profile path then into system
+ * profiles path, the i-th selected profile.
+ * If profile can't be loaded, it will just skipped.
+ * If verbose >= TC_DEBUG and the profile wasn't loaded, notify
+ * the user using tc_log*.
+ * If verbose >= TC_INFO and profile was loaded, notify the user
+ * using tc_log*.
+ *
+ * Parameters:
+ * i: load the i-th already parsed (see below) export profile.
+ * config: use this TCConfigEntry array, provided by frontend, to
+ * parse profile data file
+ * sys_path: system path to look for profile data
+ * user_path: user path to look for profile data
+ * Return value:
+ * 1: profile data succesfully loaded
+ * 0: profile data not loaded for some reasons (profile file
+ * not found or not readable).
+ * Side effects:
+ * Isn't a proper side effect, anyway it's worth to note that
+ * this function _will_ alter some data not explicitely provided,
+ * via config parameter. Note that this function WILL NOT alter
+ * config data, so caller providing config data will have full
+ * control of those unproper side effects by careful craft of
+ * TCConfigEntry data.
+ * Also note that this function mangle global private prof_data
+ * variable, most notably by invoking cleanup_strings on it
+ * to avoid memleaks in subsequent calls of module_read_config.
+ * Preconditions:
+ * this function should be always used _after_ a succesfull
+ * call to tc_setup_export_profiles, which parse the profiles
+ * selected by user. Otherwise it's still safe to call this function,
+ * but it always fail.
+ */
+static int tc_load_single_export_profile(int i, TCConfigEntry *config,
+ const char *sys_path,
+ const char *user_path);
+
+/* utilities used internally (yet) */
+
+/*
+ * cleanup_strings:
+ * free()s and reset to NULL every not-NULL string in a given
+ * TCExportInfo structure
+ *
+ * Parameters:
+ * info: pointero to a TCExportInfo structure to cleanup.
+ * Return value:
+ * None.
+ */
+static void cleanup_strings(TCExportInfo *info);
+
+/*
+ * setup_clip_area:
+ * helper to parse a clipping area string into a TCArea structure.
+ * Automagically expand the clipping information using the same
+ * logic of transcode core (actually this code is a very
+ * little more than a rip-off form src/transcode.c).
+ *
+ * Parameters:
+ * str: clipping area string to parse.
+ * area: pointero to a TCArea where clipping parameters will be stored.
+ * Return value:
+ * 1: succesfull
+ * -1: error: malformed clipping string or bad parameters.
+ */
+static int setup_clip_area(const char *str, TCArea *area);
+
+
+/*************************************************************************/
+
+int tc_setup_export_profile(int *argc, char ***argv)
+{
+ const char *optval = NULL;
+ int ret;
+
+ if (argc == NULL || argv == NULL) {
+ tc_log_warn(package, "tc_setup_export_profile: bad data reference");
+ return -2;
+ }
+
+ /* guess package name from command line */
+ package = (*argv)[0];
+ ret = tc_mangle_cmdline(argc, argv,
+ TC_EXPORT_PROFILE_OPT, &optval);
+ if (ret == 0) { /* success */
+ prof_data.profiles = tc_strsplit(optval, ',',
+ &prof_data.profile_count);
+ ret = (int)prof_data.profile_count;
+ if (verbose >= TC_INFO) {
+ tc_log_info(package, "E: %-16s | %i", "profiles parsed", ret);
+ }
+ }
+ return ret;
+}
+
+void tc_cleanup_export_profile(void)
+{
+ tc_strfreev(prof_data.profiles);
+ prof_data.profile_count = 0;
+
+ cleanup_strings(&prof_data.info);
+}
+
+const TCExportInfo *tc_load_export_profile(void)
+{
+ /* not all settings will be accessible from here */
+ /* note static here */
+ static TCConfigEntry profile_conf[] = {
+ /* video stuff */
+ { "video_codec", &(prof_data.video_codec),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "video_module", &(prof_data.info.video.module),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "video_module_options", &(prof_data.info.video.module_opts),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "video_fourcc", &(prof_data.info.video.string),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "video_bitrate", &(prof_data.info.video.bitrate),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 0, 12000000 },
+ { "video_bitrate_max", &(prof_data.info.video.bitrate_max),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 0, 12000000 },
+ { "video_gop_size", &(prof_data.info.video.gop_size),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 1, 2000 },
+ { "video_encode_fields", &(prof_data.info.video.encode_fields),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 0, 3 },
+ // FIXME: switch to char/string?
+ { "video_frc", &(prof_data.info.video.frc),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 0, 5 },
+ { "video_asr", &(prof_data.info.video.asr),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 0, 9 },
+ { "video_par", &(prof_data.info.video.par),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 0, 9 },
+ // FIXME: expand achronym?
+ { "video_pre_clip", &(prof_data.pre_clip_area),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "video_post_clip", &(prof_data.post_clip_area),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "video_width", &(prof_data.info.video.width),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE,
+ 1, TC_MAX_V_FRAME_WIDTH },
+ { "video_height", &(prof_data.info.video.height),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE,
+ 1, TC_MAX_V_FRAME_HEIGHT },
+ { "video_keep_asr", &(prof_data.info.video.keep_asr_flag),
+ TCCONF_TYPE_FLAG, 0, 0, 1 },
+ { "video_fast_resize", &(prof_data.info.video.fast_resize_flag),
+ TCCONF_TYPE_FLAG, 0, 0, 1 },
+ { "video_zoom_interlaced", &(prof_data.info.video.zoom_interlaced_flag),
+ TCCONF_TYPE_FLAG, 0, 0, 1 },
+ /* audio stuff */
+ { "audio_codec", &(prof_data.audio_codec),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "audio_module", &(prof_data.info.audio.module),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "audio_module_options", &(prof_data.info.audio.module_opts),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "audio_bitrate", &(prof_data.info.audio.bitrate),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 0, 1000000 },
+ { "audio_frequency", &(prof_data.info.audio.sample_rate),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 0, 48000 },
+ // XXX: review min
+ { "audio_bits", &(prof_data.info.audio.sample_bits),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 8, 16 }, // XXX
+ { "audio_channels", &(prof_data.info.audio.channels),
+ TCCONF_TYPE_INT, TCCONF_FLAG_RANGE, 1, 2 },
+ /* multiplexing */
+ { "mplex_module", &(prof_data.info.mplex.module),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { "mplex_module_options", &(prof_data.info.mplex.module_opts),
+ TCCONF_TYPE_STRING, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 }
+ };
+ char home_path[PATH_MAX + 1];
+ const char *home = getenv("HOME");
+ int i = 0;
+
+ if (home != NULL) {
+ tc_snprintf(home_path, sizeof(home_path), "%s/%s",
+ home, USER_PROF_PATH);
+ } else {
+ tc_log_warn(package, "can't determinate home directory!");
+ return NULL;
+ }
+
+ for (i = 0; i < prof_data.profile_count; i++) {
+ tc_load_single_export_profile(i, profile_conf,
+ PROF_PATH, home_path);
+ }
+ return &prof_data.info;
+}
+
+/* it's pretty naif yet. FR */
+void tc_export_profile_to_vob(const TCExportInfo *info, vob_t *vob)
+{
+ if (info == NULL || vob == NULL) {
+ return;
+ }
+ vob->ex_v_string = info->video.module_opts;
+ vob->ex_a_string = info->audio.module_opts;
+ vob->ex_m_string = info->mplex.module_opts;
+ vob->ex_v_codec = info->video.format;
+ vob->ex_a_codec = info->audio.format;
+ vob->ex_v_fcc = info->video.string;
+ vob->ex_frc = info->video.frc;
+ vob->ex_asr = info->video.asr;
+ vob->ex_par = info->video.par;
+ vob->encode_fields = info->video.encode_fields;
+ vob->divxbitrate = info->video.bitrate;
+ vob->mp3bitrate = info->audio.bitrate;
+ vob->video_max_bitrate = info->video.bitrate_max;
+ vob->divxkeyframes = info->video.gop_size;
+ vob->mp3frequency = info->audio.sample_rate;
+ vob->dm_bits = info->audio.sample_bits;
+ vob->dm_chan = info->audio.channels;
+ vob->mp3mode = info->audio.mode;
+ vob->bitreservoir = info->audio.bit_reservoir;
+ vob->zoom_interlaced = info->video.zoom_interlaced_flag;
+ if (info->video.fast_resize_flag) {
+ tc_compute_fast_resize_values(vob, TC_FALSE);
+ } else {
+ vob->zoom_width = info->video.width;
+ vob->zoom_height = info->video.height;
+ }
+}
+
+/*************************************************************************
+ * private helpers: implementation
+ **************************************************************************/
+
+#define SETUP_CODEC(TYPE) do { \
+ int codec = 0; /* shortcut */\
+ if (prof_data.TYPE ## _codec != NULL) { \
+ codec = tc_codec_from_string(prof_data.TYPE ## _codec); \
+ prof_data.info.TYPE.format = codec; \
+ tc_free((char*)prof_data.TYPE ## _codec); /* avoid const warning */ \
+ prof_data.TYPE ## _codec = NULL; \
+ } \
+} while (0)
+
+#define SETUP_CLIPPING(TYPE) do { \
+ if (prof_data.TYPE ## _clip_area != NULL) { \
+ memset(&(prof_data.info.video.TYPE ## _clip), 0, sizeof(TCArea)); \
+ setup_clip_area(prof_data.TYPE ## _clip_area, \
+ &(prof_data.info.video.TYPE ## _clip)); \
+ tc_free((char*)prof_data.TYPE ## _clip_area); /* avoid const warning */ \
+ prof_data.TYPE ## _clip_area = NULL; \
+ } \
+} while (0)
+
+static int tc_load_single_export_profile(int i, TCConfigEntry *config,
+ const char *sys_path,
+ const char *user_path)
+{
+ int found = 0, ret = 0;
+ char path_buf[PATH_MAX+1];
+ const char *basedir = NULL;
+
+ if (sys_path == NULL || user_path == NULL || config == NULL
+ || ((i < 0) || i >= prof_data.profile_count)) {
+ /* paranoia */
+ tc_log_warn(package, "tc_load_single_export_profile:"
+ " bad data reference");
+ return -1;
+ }
+
+ tc_snprintf(path_buf, sizeof(path_buf), "%s/%s.cfg",
+ user_path, prof_data.profiles[i]);
+ ret = access(path_buf, R_OK);
+ if (ret == 0) {
+ found = 1;
+ basedir = user_path;
+ } else {
+ tc_snprintf(path_buf, sizeof(path_buf), "%s/%s.cfg",
+ sys_path, prof_data.profiles[i]);
+ ret = access(path_buf, R_OK);
+ if (ret == 0) {
+ found = 1;
+ basedir = PROF_PATH;
+ }
+ }
+
+ if (found) {
+ char prof_name[TC_BUF_MIN];
+ cleanup_strings(&prof_data.info);
+ tc_snprintf(prof_name, sizeof(prof_name), "%s.cfg",
+ prof_data.profiles[i]);
+
+ tc_set_config_dir(basedir);
+ ret = module_read_config(prof_name, NULL, config, package);
+ if (ret == 0) {
+ found = 0; /* module_read_config() failed */
+ } else {
+ if (verbose >= TC_INFO) {
+ tc_log_info(package, "E: %-16s | %s", "loaded profile",
+ path_buf);
+ }
+ SETUP_CODEC(video);
+ SETUP_CODEC(audio);
+ SETUP_CLIPPING(pre);
+ SETUP_CLIPPING(post);
+ }
+ } else {
+ if (verbose >= TC_DEBUG) {
+ tc_log_warn(package, "E: %-16s | %s (skipped)", "unable to load",
+ path_buf);
+ }
+ }
+ return found;
+}
+
+#undef SETUP_CODEC
+#undef SETUP_CLIPPING
+
+/*
+ * module_read_config (used internally, see later)
+ * allocates new strings for option values, so
+ * we need to take care of them using this couple
+ * of functions
+ */
+
+#define CLEANUP_STRING(FIELD) do { \
+ if (info->FIELD != NULL) {\
+ tc_free(info->FIELD); \
+ info->FIELD = NULL; \
+ } \
+} while (0)
+
+static void cleanup_strings(TCExportInfo *info)
+{
+ if (info != NULL) {
+ /* paranoia */
+
+ CLEANUP_STRING(video.string);
+ CLEANUP_STRING(video.module);
+ CLEANUP_STRING(video.module_opts);
+ CLEANUP_STRING(video.log_file);
+
+ CLEANUP_STRING(audio.string);
+ CLEANUP_STRING(audio.module);
+ CLEANUP_STRING(audio.module_opts);
+
+ CLEANUP_STRING(mplex.string);
+ CLEANUP_STRING(mplex.module);
+ CLEANUP_STRING(mplex.module_opts);
+ CLEANUP_STRING(mplex.out_file);
+ CLEANUP_STRING(mplex.out_file_aux);
+ }
+}
+
+#undef CLEANUP_STRING
+
+/*************************************************************************/
+
+static int setup_clip_area(const char *str, TCArea *area)
+{
+ int n = sscanf(str, "%i,%i,%i,%i",
+ &area->top, &area->left, &area->bottom, &area->right);
+ if (n < 0) {
+ return -1;
+ }
+
+ /* symmetrical clipping for only 1-3 arguments */
+ if (n == 1 || n == 2) {
+ area->bottom = area->top;
+ }
+ if (n == 2 || n == 3) {
+ area->right = area->left;
+ }
+
+ return 1;
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/export_profile.h b/debian/transcode/transcode-1.1.7/src/export_profile.h
new file mode 100644
index 00000000..98ee9071
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/export_profile.h
@@ -0,0 +1,116 @@
+/*
+ * export_profile.h -- transcode export profile support code - interface
+ * (C) 2006-2010 - Francesco Romani <fromani at gmail dot com>
+ *
+ * This file is part of transcode, a 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef EXPORT_PROFILE_H
+#define EXPORT_PROFILE_H
+
+#include "transcode.h"
+#include "tcinfo.h"
+
+/*
+ * GENERAL WARNING: none of those functions
+ * are intended to be thread-safe
+ */
+
+/*
+ * tc_setup_export_profile:
+ * determine the export profile(s) to load later, by extracting
+ * informations by command line options (argc\argv).
+ * In more detail, this function handles '--export_prof PROFILE'
+ * option.
+ * Also removes used option by options array, so later processing
+ * of used option is easier.
+ *
+ * Parameters:
+ * argc: POINTER to integer representing the number of items in argv
+ * array.
+ * argv: POINTER to array of C-string representing option keys
+ * and values.
+ * Return value:
+ * -2: internal error
+ * -1: bad parameters (== NULL)
+ * 0: bad option value
+ * >0: succesfull, and return value is number of profile parsed.
+ * Side effects:
+ * if operation is succesfull AND if user provided (valid) --export_prof
+ * option, both option and it's argument are removed from argv vector,
+ * so *TWO* items of argv vector will be NULL-ified, and argc is
+ * decreased by two.
+ * This function also trasparently set some internal variables.
+ * Preconditions:
+ * argc != NULL
+ * argv != NULL
+ */
+int tc_setup_export_profile(int *argc, char ***argv);
+
+/*
+ * tc_setup_export_profile:
+ * release all resources acquired by tc_setup_export_profile.
+ *
+ * Parameters:
+ * None.
+ * Return vaule:
+ * None
+ */
+void tc_cleanup_export_profile(void);
+
+/*
+ * tc_load_export_profile:
+ * sequentially load all profiles recognized using
+ * tc_setup_export_profile, so if two or more profile specifies
+ * a value for an option, the later will prevail.
+ *
+ * Parameters:
+ * None
+ * Return value:
+ * if succesfull, return a pointer to a TCEXportInfo structure
+ * intialized with sensible defaults and containing the values
+ * set by loaded profile(s). There is no need to free() returned
+ * structure, it's handled internally.
+ * If an error happens, return NULL, and tc_log*() reason
+ * (see side effects below).
+ * Side effects:
+ * if verbose value is >= TC_DEBUG *AND* a profile can
+ * be loaded, tc_log'd out the unavalaible profile.
+ * if verbose value is >= TC_INFO, tc_log out every loaded
+ * profile.
+ */
+const TCExportInfo *tc_load_export_profile(void);
+
+/*
+ * tc_export_profile_to_vob:
+ * translate values stored in a TCExportInfo structure into
+ * a vob_t structure, doing the needed adaptations.
+ * This function ignore bad (or unreproducible, even if it's
+ * very unlikely) values/combination sotre in TCExportInfo
+ * structures reporting errors using tc_log*.
+ *
+ * Parameters:
+ * info: pointer to TCExportInfo to translate
+ * vob: pointer to vob_t storing translated values.
+ * Return value:
+ * None
+ * Side effects:
+ * tc_log*() is used internally.
+ */
+void tc_export_profile_to_vob(const TCExportInfo *info, vob_t *vob);
+
+#endif /* EXPORT_PROFILE_H */
diff --git a/debian/transcode/transcode-1.1.7/src/filter.c b/debian/transcode/transcode-1.1.7/src/filter.c
new file mode 100644
index 00000000..8d4fe4e3
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/filter.c
@@ -0,0 +1,603 @@
+/*
+ * filter.c -- audio/video filter handling
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "transcode.h"
+#include "filter.h"
+
+// temp defines during module system switchover
+//#define SUPPORT_NMS // support NMS modules?
+#define SUPPORT_CLASSIC // support classic modules?
+
+#ifdef SUPPORT_CLASSIC
+/* For dlopening old-style modules */
+# ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+# else
+# ifdef OS_DARWIN
+# include "libdldarwin/dlfcn.h"
+# endif
+# endif
+#endif // SUPPORT_CLASSIC
+
+/*************************************************************************/
+
+/* Data for a single filter instance. An ID value of 0 indicates that no
+ * filter is present. */
+
+typedef struct FilterInstance_ {
+ char name[MAX_FILTER_NAME_LEN+1]; // Filter name
+ int id; // Unique ID value for this filter instance
+ int enabled; // Nonzero if filter is inabled
+#ifdef SUPPORT_CLASSIC
+ void *handle; // DLL handle for old-style modules
+ TCFilterOldEntryFunc entry; // Module entry point for old-style modules
+#endif
+#ifdef SUPPORT_NMS
+#error please add field(s) needed for NMS
+#endif
+} FilterInstance;
+
+
+/* Flag: are we initialized? */
+static int initialized = 0;
+
+/* Filter instance table. */
+static FilterInstance filters[MAX_FILTERS];
+
+
+/* Macro to check that tc_filter_init() has been called, and abort the
+ * function otherwise. Pass the appropriate return value (nothing for a
+ * void function) as the macro parameter. */
+#define CHECK_INITIALIZED(...) do { \
+ if (!initialized) { \
+ tc_log_warn(__FILE__, "%s() called before initialization!", \
+ __FUNCTION__); \
+ return __VA_ARGS__; \
+ } \
+} while (0)
+
+/*************************************************************************/
+
+/**
+ * id_to_index: Local helper function to convert a filter ID value to a
+ * filters[] index. Outputs an error message with tc_log_warn() on error.
+ *
+ * Parameters:
+ * id: Filter ID.
+ * func: Calling function's name (__FUNCTION__).
+ * Return value:
+ * filters[] index corresponding to given ID, or -1 on error.
+ */
+
+static int id_to_index(int id, const char *func)
+{
+ int i;
+
+ if (id <= 0) {
+ tc_log_warn(__FILE__, "Bad filter ID %d passed to %s()", id, func);
+ return -1;
+ }
+ for (i = 0; i < MAX_FILTERS; i++) {
+ if (filters[i].id == id)
+ break;
+ }
+ if (i >= MAX_FILTERS) {
+ tc_log_warn(__FILE__, "Filter ID %d does not exist in %s()", id, func);
+ return -1;
+ }
+ return i;
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/* tc_filter_init: Initialize the filter subsystem. Must be called before
+ * any other filter functions.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ */
+
+int tc_filter_init(void)
+{
+ int i;
+
+ if (initialized) {
+ tc_log_warn(__FILE__, "tc_filter_init() called twice!");
+ return 1;
+ }
+ for (i = 0; i < MAX_FILTERS; i++)
+ filters[i].id = 0;
+ initialized = 1;
+ return 1;
+}
+
+/*************************************************************************/
+
+/* tc_filter_fini: Close down the filter subsystem. If the filter system
+ * has not yet been initialized, do nothing. After calling this function,
+ * no filter functions (other than tc_filter_init()) may be called.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+void tc_filter_fini(void)
+{
+ int i;
+
+ if (!initialized)
+ return;
+
+ for (i = 0; i < MAX_FILTERS; i++) {
+ if (filters[i].id != 0)
+ tc_filter_remove(filters[i].id);
+ }
+
+ initialized = 0;
+}
+
+/*************************************************************************/
+
+/**
+ * tc_filter_process: Sends the given frame to all enabled filters for
+ * processing.
+ *
+ * Parameters:
+ * frame: Frame to process.
+ * Return value:
+ * None.
+ * Prerequisites:
+ * frame->tag is set to an appropriate value
+ */
+
+void tc_filter_process(frame_list_t *frame)
+{
+ int last_id;
+
+ CHECK_INITIALIZED();
+ if (!frame) {
+ tc_log_warn(__FILE__, "tc_filter_process: frame is NULL!");
+ return;
+ }
+
+ /* The order of the filters is given by their ID values--however, this
+ * does not necessarily match the order in the filters[] array. We
+ * keep track of the last ID processed (starting at 0, lower than any
+ * valid ID), then each time through the loop, search for the lowest ID
+ * greater than that value, which will be the next filter to process.
+ * The loop ends when no enabled filter has an ID greater than the last
+ * ID processed. */
+
+ last_id = 0;
+ for (;;) {
+ int next_filter = -1, i;
+
+ for (i = 0; i < MAX_FILTERS; i++) {
+ if (filters[i].id <= last_id || !filters[i].enabled)
+ continue;
+ if (next_filter < 0 || filters[i].id < filters[next_filter].id)
+ next_filter = i;
+ }
+ if (next_filter < 0)
+ break;
+ last_id = filters[next_filter].id;
+
+#ifdef SUPPORT_NMS
+# error please write NMS support code
+#endif
+
+#ifdef SUPPORT_CLASSIC
+ if (!filters[next_filter].entry) {
+ tc_log_warn(__FILE__, "Filter %s (%d) missing entry function"
+ " (bug?), disabling", filters[i].name, last_id);
+ filters[next_filter].enabled = 0;
+ continue;
+ }
+ frame->filter_id = last_id;
+ filters[next_filter].entry(frame, NULL);
+#endif
+ } // for (;;)
+}
+
+/*************************************************************************/
+
+/**
+ * tc_filter_add: Adds the given filter at the end of the filter chain,
+ * and initializes it using the given option string.
+ *
+ * Parameters:
+ * name: Name of filter to add.
+ * options: Options to pass to filter (if NULL, no options are passed).
+ * Return value:
+ * Filter ID (nonzero) on success, zero on failure.
+ */
+
+int tc_filter_add(const char *name, const char *options)
+{
+ int i, id;
+
+ CHECK_INITIALIZED(0);
+ if (!name) {
+ tc_log_warn(__FILE__, "tc_filter_add: name is NULL!");
+ return 0;
+ } else if (!*name) {
+ tc_log_warn(__FILE__, "tc_filter_add: name is empty!");
+ return 0;
+ } else if (strlen(name) > MAX_FILTER_NAME_LEN) {
+ tc_log_warn(__FILE__, "tc_filter_add: name \"%s\" is too long!"
+ " (max %d chars)", name, MAX_FILTER_NAME_LEN);
+ return 0;
+ }
+
+ /* Find the largest ID value currently in use, and use the next value */
+ id = 0;
+ for (i = 0; i < MAX_FILTERS; i++) {
+ if (filters[i].id > id)
+ id = filters[i].id;
+ }
+ id++;
+ if (id <= 0) { // wraparound check
+ tc_log_warn(__FILE__, "tc_filter_add: out of filter IDs, restart %s",
+ PACKAGE);
+ return 0;
+ }
+
+ /* Find the first available filter table entry, returning an error if
+ * none is found, and initialize the entry */
+ for (i = 0; i < MAX_FILTERS; i++) {
+ if (!filters[i].id)
+ break;
+ }
+ if (i >= MAX_FILTERS) {
+ tc_log_warn(__FILE__, "tc_filter_add: no free filter slots! (max %d)",
+ MAX_FILTERS);
+ return 0;
+ }
+ strlcpy(filters[i].name, name, sizeof(filters[i].name));
+ filters[i].enabled = 0;
+
+#ifdef SUPPORT_NMS
+# error please write NMS support code
+#endif
+
+#ifdef SUPPORT_CLASSIC
+ {
+ char path[1000];
+ frame_list_t dummy_frame;
+
+ /* Load the module and look up the tc_filter() address */
+ if (tc_snprintf(path, sizeof(path), "%s/filter_%s.so",
+ tc_get_vob()->mod_path, name) < 0) {
+ tc_log_error(__FILE__, "tc_filter_add: path buffer overflow");
+ return 0;
+ }
+ filters[i].handle = dlopen(path, RTLD_NOW);
+ if (!filters[i].handle) {
+ const char *error = dlerror();
+ if (!error)
+ error = "Unknown error";
+ tc_log_warn(PACKAGE, "Unable to load filter %s: %s", name, error);
+ return 0;
+ }
+ filters[i].entry = dlsym(filters[i].handle, "tc_filter");
+ if (!filters[i].entry) {
+ const char *error = dlerror();
+ if (!error)
+ error = "Unknown error (corrupt module?)";
+ tc_log_warn(PACKAGE, "Unable to initialize filter %s: %s",
+ name, error);
+ dlclose(filters[i].handle);
+ return 0;
+ }
+ filters[i].id = id; /* loaded, at least */
+ if (verbose & TC_DEBUG)
+ tc_log_msg(__FILE__, "tc_filter_add: module %s loaded", path);
+
+ /* Call tc_filter() to initialize the module */
+ dummy_frame.filter_id = id;
+ dummy_frame.tag = TC_FILTER_INIT;
+ /* Maximum size of a single frame, video or audio */
+ dummy_frame.size = 0;
+ /* XXX: it seems never used, so 0 should be safe -- FR */
+ if (filters[i].entry(&dummy_frame, (char *)options) < 0) {
+ tc_warn("Initialization of filter %s failed, skipping.", name);
+ tc_filter_remove(id);
+ }
+ if (verbose & TC_DEBUG)
+ tc_log_msg(__FILE__, "tc_filter_add: filter %s successfully"
+ " initialized", name);
+ }
+#endif // SUPPORT_CLASSIC
+
+ /* Module was successfully loaded and initialized, so enable it */
+ filters[i].enabled = 1;
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * tc_filter_find: Return the ID for the named filter.
+ *
+ * Parameters:
+ * name: Name of filter to find.
+ * Return value:
+ * Filter ID (nonzero) on success, zero on error or if given filter is
+ * not loaded.
+ */
+
+int tc_filter_find(const char *name)
+{
+ int i;
+
+ CHECK_INITIALIZED(0);
+ for (i = 0; i < MAX_FILTERS; i++) {
+ if (strcmp(filters[i].name, name) == 0)
+ return filters[i].id;
+ }
+ return 0;
+}
+
+/*************************************************************************/
+
+/**
+ * tc_filter_remove: Remove the given filter.
+ *
+ * Parameters:
+ * id: ID of filter to remove.
+ * Return value:
+ * None.
+ */
+
+void tc_filter_remove(int id)
+{
+ int i;
+
+ CHECK_INITIALIZED();
+ if ((i = id_to_index(id, __FUNCTION__)) < 0)
+ return;
+
+#ifdef SUPPORT_NMS
+# error please write NMS support code
+#endif
+
+#ifdef SUPPORT_CLASSIC
+ if (filters[i].handle) {
+ if (filters[i].entry) {
+ frame_list_t ptr;
+ ptr.tag = TC_FILTER_CLOSE;
+ ptr.filter_id = filters[i].id;
+ filters[i].entry(&ptr, NULL);
+ } else {
+ tc_log_warn(__FILE__, "Filter %s (%d) missing entry function"
+ " (bug?)", filters[i].name, id);
+ }
+ dlclose(filters[i].handle);
+ filters[i].handle = NULL;
+ filters[i].entry = NULL;
+ }
+#endif
+
+ memset(filters[i].name, 0, sizeof(filters[i].name));
+ filters[i].id = 0;
+ filters[i].enabled = 0;
+}
+
+/*************************************************************************/
+
+/**
+ * tc_filter_enable: Enable the given filter.
+ *
+ * Parameters:
+ * id: ID of filter to enable.
+ * Return value:
+ * Nonzero on success, zero on error.
+ */
+
+int tc_filter_enable(int id)
+{
+ int i;
+
+ CHECK_INITIALIZED(0);
+ i = id_to_index(id, __FUNCTION__);
+ if (i < 0)
+ return 0;
+ filters[i].enabled = 1;
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * tc_filter_disable: Disable the given filter.
+ *
+ * Parameters:
+ * id: ID of filter to enable.
+ * Return value:
+ * Nonzero on success, zero on error.
+ */
+
+int tc_filter_disable(int id)
+{
+ int i;
+
+ CHECK_INITIALIZED(0);
+ i = id_to_index(id, __FUNCTION__);
+ if (i < 0)
+ return 0;
+ filters[i].enabled = 0;
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * tc_filter_configure: Configure the given filter.
+ *
+ * Parameters:
+ * id: ID of filter to configure.
+ * options: Option string for filter.
+ * Return value:
+ * Nonzero on success, zero on error.
+ */
+
+int tc_filter_configure(int id, const char *options)
+{
+ int i;
+
+ CHECK_INITIALIZED(0);
+ i = id_to_index(id, __FUNCTION__);
+ if (i < 0)
+ return 0;
+
+#ifdef SUPPORT_NMS
+# error please write NMS support code
+#endif
+
+#ifdef SUPPORT_CLASSIC
+ {
+ frame_list_t dummy_frame;
+
+ if (!filters[i].entry) {
+ tc_log_warn(__FILE__, "Filter %s (%d) missing entry function"
+ " (bug?), disabling", filters[i].name, id);
+ filters[i].enabled = 0;
+ return 0;
+ }
+ /* Old filter API does a close before reconfiguring */
+ dummy_frame.filter_id = id;
+ dummy_frame.tag = TC_FILTER_CLOSE;
+ filters[i].entry(&dummy_frame, NULL);
+ dummy_frame.filter_id = id;
+ dummy_frame.tag = TC_FILTER_INIT;
+ dummy_frame.size = 0;
+ /* XXX: it seems never used, so 0 should be safe -- FR */
+ if (filters[i].entry(&dummy_frame, (char *)options) < 0) {
+ tc_log_warn(PACKAGE, "Reconfiguration of filter %s failed,"
+ " disabling.", filters[i].name);
+ filters[i].enabled = 0;
+ return 0;
+ }
+ return 1;
+ }
+#endif
+}
+
+/*************************************************************************/
+
+/**
+ * tc_filter_get_conf: Return current configuration information for the
+ * given option on the given filter. If `option' is NULL, returns a
+ * summary of configuration information in an undefined format.
+ *
+ * Parameters:
+ * id: ID of filter to retrieve configuration information for.
+ * option: Name of option to retrieve information for, or NULL.
+ * Return value:
+ * A pointer to an unmodifiable string containing the result, or NULL
+ * on error.
+ */
+
+const char *tc_filter_get_conf(int id, const char *option)
+{
+ int i;
+
+ CHECK_INITIALIZED(NULL);
+ i = id_to_index(id, __FUNCTION__);
+ if (i < 0)
+ return 0;
+
+#ifdef SUPPORT_NMS
+# error please write NMS support code
+#endif
+
+#ifdef SUPPORT_CLASSIC
+ {
+ frame_list_t dummy_frame;
+ static char buf[PATH_MAX];
+
+ memset(buf, 0, sizeof(buf));
+ dummy_frame.filter_id = id;
+ dummy_frame.tag = TC_FILTER_GET_CONFIG;
+ if (filters[i].entry) {
+ if (filters[i].entry(&dummy_frame, buf) == 0)
+ return buf;
+ } else {
+ tc_log_warn(__FILE__, "Filter %s (%d) missing entry function"
+ " (bug?), disabling", filters[i].name, id);
+ filters[i].enabled = 0;
+ }
+ return NULL;
+ }
+#endif
+}
+
+/*************************************************************************/
+
+/**
+ * tc_filter_list: Return a list of filters according to the given
+ * parameter. The list is comma-space separated, with each name enclosed
+ * in double quotes; filters are listed in the same order they are applied.
+ *
+ * Parameters:
+ * what: Selects what kind of modules to list (TC_FILTER_LIST_*).
+ * Return value:
+ * A pointer to an unmodifiable string containing the result.
+ */
+
+const char *tc_filter_list(enum tc_filter_list_enum what)
+{
+ static char buf[MAX_FILTERS * (MAX_FILTER_NAME_LEN+4)];
+ int last_id;
+
+ *buf = 0;
+ CHECK_INITIALIZED(buf);
+
+ /* Use the same logic as in tc_filter_process() to retrieve the filters
+ * in ID order. */
+ last_id = 0;
+ for (;;) {
+ int next_filter = -1, i;
+
+ for (i = 0; i < MAX_FILTERS; i++) {
+ if (filters[i].id <= last_id)
+ continue;
+ if (what == TC_FILTER_LIST_ENABLED && !filters[i].enabled)
+ continue;
+ if (what == TC_FILTER_LIST_DISABLED && filters[i].enabled)
+ continue;
+ if (next_filter < 0 || filters[i].id < filters[next_filter].id)
+ next_filter = i;
+ }
+ if (next_filter < 0)
+ break;
+ last_id = filters[next_filter].id;
+ tc_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s\"%s\"",
+ last_id==0 ? "" : ", ", filters[next_filter].name);
+ }
+ return buf;
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/filter.h b/debian/transcode/transcode-1.1.7/src/filter.h
new file mode 100644
index 00000000..dd2ca91e
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/filter.h
@@ -0,0 +1,62 @@
+/*
+ * filter.h -- audio/video filter include file
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#ifndef FILTER_H
+#define FILTER_H
+
+#include "framebuffer.h"
+
+/*************************************************************************/
+
+/* Maximum number of filter instances that can be loaded. */
+#define MAX_FILTERS 16
+
+/* Maximum length of a filter name, in bytes. */
+#define MAX_FILTER_NAME_LEN 32
+
+/* Parameters to tc_filter_list(). */
+enum tc_filter_list_enum {
+ TC_FILTER_LIST_LOADED,
+ TC_FILTER_LIST_ENABLED,
+ TC_FILTER_LIST_DISABLED,
+};
+
+
+/* Filter interface functions. */
+extern int tc_filter_init(void);
+extern void tc_filter_fini(void);
+extern void tc_filter_process(frame_list_t *frame);
+extern int tc_filter_add(const char *name, const char *options);
+extern int tc_filter_find(const char *name);
+extern void tc_filter_remove(int id);
+extern int tc_filter_enable(int id);
+extern int tc_filter_disable(int id);
+extern int tc_filter_configure(int id, const char *options);
+extern const char *tc_filter_get_conf(int id, const char *option);
+extern const char *tc_filter_list(enum tc_filter_list_enum what);
+
+/* Type of the exported module entry point for the old module system, and a
+ * prototype for tc_filter() for those modules. */
+typedef int (*TCFilterOldEntryFunc)(void *ptr, char *options);
+extern int tc_filter(frame_list_t *ptr, char *options);
+
+/*************************************************************************/
+
+#endif /* FILTER_H */
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/frame_threads.c b/debian/transcode/transcode-1.1.7/src/frame_threads.c
new file mode 100644
index 00000000..95a7ef7e
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/frame_threads.c
@@ -0,0 +1,376 @@
+/*
+ * frame_threads.c -- implementation of transcode multithreaded filter
+ * processing code.
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ * updates and partial rewrite:
+ * Copyright (C) Francesco Romani - October 2007
+ *
+ * This file is part of transcode, a 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 <pthread.h>
+
+#include "transcode.h"
+#include "encoder-common.h"
+#include "framebuffer.h"
+#include "video_trans.h"
+#include "audio_trans.h"
+#include "decoder.h"
+#include "filter.h"
+
+#include "frame_threads.h"
+
+/*************************************************************************/
+
+typedef struct tcframethreaddata_ TCFrameThreadData;
+struct tcframethreaddata_ {
+ pthread_t threads[TC_FRAME_THREADS_MAX]; /* thread pool */
+ int count; /* how many workers? */
+
+ pthread_mutex_t lock;
+ volatile int running; /* _pool_ running flag */
+};
+
+TCFrameThreadData audio_threads = {
+ .count = 0,
+ .lock = PTHREAD_MUTEX_INITIALIZER,
+ .running = TC_FALSE,
+};
+
+TCFrameThreadData video_threads = {
+ .count = 0,
+ .lock = PTHREAD_MUTEX_INITIALIZER,
+ .running = TC_FALSE,
+};
+
+/*************************************************************************/
+
+/*
+ * tc_frame_threads_stop (Thread safe):
+ * set the stop flag for a thread pool.
+ *
+ * Parameters:
+ * data: thread pool descriptor.
+ * Return Value:
+ * None.
+ */
+static void tc_frame_threads_stop(TCFrameThreadData *data)
+{
+ pthread_mutex_lock(&data->lock);
+ data->running = TC_FALSE;
+ pthread_mutex_unlock(&data->lock);
+}
+
+/*
+ * tc_frame_threads_are_active (Thread safe):
+ * verify if there is a pending stop request for given thread pool.
+ *
+ * Parameters:
+ * data: thread pool descriptor.
+ * Return Value:
+ * !0: there is pending pool stop request.
+ * 0: otherwise.
+ */
+static int tc_frame_threads_are_active(TCFrameThreadData *data)
+{
+ int ret;
+ pthread_mutex_lock(&data->lock);
+ ret = data->running;
+ pthread_mutex_unlock(&data->lock);
+ return ret;
+}
+
+/*
+ * stop_requested: verify if the pool thread has to stop.
+ * First thread in the pool notifying the core has to stop must
+ * set the flag to notify the others.
+ *
+ * Parameters:
+ * data: thread pool descriptor.
+ * Return Value:
+ * !0: thread pool has to halt as soon as is possible.
+ * 0: thread pool can continue to run.
+ */
+static int stop_requested(TCFrameThreadData *data)
+{
+ return (!tc_running() || !tc_frame_threads_are_active(data));
+}
+
+
+/*************************************************************************/
+/* frame processing core threads */
+/*************************************************************************/
+
+
+#define DUP_vptr_if_cloned(vptr) do { \
+ if(vptr->attributes & TC_FRAME_IS_CLONED) { \
+ vframe_list_t *tmptr = vframe_dup(vptr); \
+ \
+ /* ptr was successfully cloned */ \
+ /* delete clone flag */ \
+ tmptr->attributes &= ~TC_FRAME_IS_CLONED; \
+ vptr->attributes &= ~TC_FRAME_IS_CLONED; \
+ \
+ /* set info for filters */ \
+ tmptr->attributes |= TC_FRAME_WAS_CLONED; \
+ \
+ /* this frame is to be processed _after_ the current one */ \
+ /* so put it back into the queue */ \
+ vframe_push_next(tmptr, TC_FRAME_WAIT); \
+ \
+ } \
+} while (0)
+
+
+
+#define DUP_aptr_if_cloned(aptr) do { \
+ if(aptr->attributes & TC_FRAME_IS_CLONED) { \
+ aframe_list_t *tmptr = aframe_dup(aptr); \
+ \
+ /* ptr was successfully cloned */ \
+ \
+ /* delete clone flag */ \
+ tmptr->attributes &= ~TC_FRAME_IS_CLONED; \
+ aptr->attributes &= ~TC_FRAME_IS_CLONED; \
+ \
+ /* set info for filters */ \
+ tmptr->attributes |= TC_FRAME_WAS_CLONED; \
+ \
+ /* this frame is to be processed _after_ the current one */ \
+ /* so put it back into the queue */ \
+ aframe_push_next(tmptr, TC_FRAME_WAIT); \
+ \
+ } \
+} while (0)
+
+
+#define SET_STOP_FLAG(DATAP, MSG) do { \
+ if (verbose >= TC_CLEANUP) \
+ tc_log_msg(__FILE__, "%s", (MSG)); \
+ tc_frame_threads_stop((DATAP)); \
+} while (0)
+
+static void *process_video_frame(void *_vob)
+{
+ static int res = 0; // XXX
+ vframe_list_t *ptr = NULL;
+ vob_t *vob = _vob;
+
+ while (!stop_requested(&video_threads)) {
+ ptr = vframe_reserve();
+ if (ptr == NULL) {
+ SET_STOP_FLAG(&video_threads, "video interrupted: exiting!");
+ res = 1;
+ break;
+ }
+ if (ptr->attributes & TC_FRAME_IS_END_OF_STREAM) {
+ SET_STOP_FLAG(&video_threads, "video stream end: marking!");
+ }
+
+ if (ptr->attributes & TC_FRAME_IS_SKIPPED) {
+ vframe_remove(ptr); /* release frame buffer memory */
+ continue;
+ }
+
+ if (TC_FRAME_NEED_PROCESSING(ptr)) {
+ // external plugin pre-processing
+ ptr->tag = TC_VIDEO|TC_PRE_M_PROCESS;
+ tc_filter_process((frame_list_t *)ptr);
+
+ if (ptr->attributes & TC_FRAME_IS_SKIPPED) {
+ vframe_remove(ptr); /* release frame buffer memory */
+ continue;
+ }
+
+ // clone if the filter told us to do so.
+ DUP_vptr_if_cloned(ptr);
+
+ // internal processing of video
+ ptr->tag = TC_VIDEO;
+ process_vid_frame(vob, ptr);
+
+ // external plugin post-processing
+ ptr->tag = TC_VIDEO|TC_POST_M_PROCESS;
+ tc_filter_process((frame_list_t *)ptr);
+
+ if (ptr->attributes & TC_FRAME_IS_SKIPPED) {
+ vframe_remove(ptr); /* release frame buffer memory */
+ continue;
+ }
+ }
+
+ vframe_push_next(ptr, TC_FRAME_READY);
+ }
+ if (verbose >= TC_CLEANUP)
+ tc_log_msg(__FILE__, "video stream end: got, so exiting!");
+
+ pthread_exit(&res);
+ return NULL;
+}
+
+
+static void *process_audio_frame(void *_vob)
+{
+ static int res = 0; // XXX
+ aframe_list_t *ptr = NULL;
+ vob_t *vob = _vob;
+
+ while (!stop_requested(&audio_threads)) {
+ ptr = aframe_reserve();
+ if (ptr == NULL) {
+ SET_STOP_FLAG(&audio_threads, "audio interrupted: exiting!");
+ break;
+ res = 1;
+ }
+ if (ptr->attributes & TC_FRAME_IS_END_OF_STREAM) {
+ SET_STOP_FLAG(&audio_threads, "audio stream end: marking!");
+ }
+
+ if (ptr->attributes & TC_FRAME_IS_SKIPPED) {
+ aframe_remove(ptr); /* release frame buffer memory */
+ continue;
+ }
+
+ if (TC_FRAME_NEED_PROCESSING(ptr)) {
+ // external plugin pre-processing
+ ptr->tag = TC_AUDIO|TC_PRE_M_PROCESS;
+ tc_filter_process((frame_list_t *)ptr);
+
+ DUP_aptr_if_cloned(ptr);
+
+ if (ptr->attributes & TC_FRAME_IS_SKIPPED) {
+ aframe_remove(ptr); /* release frame buffer memory */
+ continue;
+ }
+
+ // internal processing of audio
+ ptr->tag = TC_AUDIO;
+ process_aud_frame(vob, ptr);
+
+ // external plugin post-processing
+ ptr->tag = TC_AUDIO|TC_POST_M_PROCESS;
+ tc_filter_process((frame_list_t *)ptr);
+
+ if (ptr->attributes & TC_FRAME_IS_SKIPPED) {
+ aframe_remove(ptr); /* release frame buffer memory */
+ continue;
+ }
+ }
+
+ aframe_push_next(ptr, TC_FRAME_READY);
+ }
+ if (verbose >= TC_CLEANUP)
+ tc_log_msg(__FILE__, "audio stream end: got, so exiting!");
+
+ pthread_exit(&res);
+ return NULL;
+}
+
+/*************************************************************************/
+
+
+int tc_frame_threads_have_video_workers(void)
+{
+ return (video_threads.count > 0);
+}
+
+int tc_frame_threads_have_audio_workers(void)
+{
+ return (audio_threads.count > 0);
+}
+
+
+void tc_frame_threads_init(vob_t *vob, int vworkers, int aworkers)
+{
+ int n = 0;
+
+ if (vworkers > 0 && !video_threads.running) {
+ video_threads.count = vworkers;
+ video_threads.running = TC_TRUE; /* enforce, needed when restarting */
+
+ if (verbose >= TC_DEBUG)
+ tc_log_info(__FILE__, "starting %i video frame"
+ " processing thread(s)", vworkers);
+
+ // start the thread pool
+ for (n = 0; n < vworkers; n++) {
+ if (pthread_create(&video_threads.threads[n], NULL,
+ process_video_frame, vob) != 0)
+ tc_error("failed to start video frame processing thread");
+ }
+ }
+
+ if (aworkers > 0 && !audio_threads.running) {
+ audio_threads.count = aworkers;
+ audio_threads.running = TC_TRUE; /* enforce, needed when restarting */
+
+ if (verbose >= TC_DEBUG)
+ tc_log_info(__FILE__, "starting %i audio frame"
+ " processing thread(s)", aworkers);
+
+ // start the thread pool
+ for (n = 0; n < aworkers; n++) {
+ if (pthread_create(&audio_threads.threads[n], NULL,
+ process_audio_frame, vob) != 0)
+ tc_error("failed to start audio frame processing thread");
+ }
+ }
+ return;
+}
+
+void tc_frame_threads_close(void)
+{
+ void *status = NULL;
+ int n = 0;
+
+ if (audio_threads.count > 0) {
+ tc_frame_threads_stop(&audio_threads);
+ if (verbose >= TC_CLEANUP)
+ tc_log_msg(__FILE__, "wait for %i audio frame processing threads",
+ audio_threads.count);
+ for (n = 0; n < audio_threads.count; n++)
+ pthread_join(audio_threads.threads[n], &status);
+ if (verbose >= TC_CLEANUP)
+ tc_log_msg(__FILE__, "audio frame processing threads canceled");
+ }
+
+ if (video_threads.count > 0) {
+ tc_frame_threads_stop(&video_threads);
+ if (verbose >= TC_CLEANUP)
+ tc_log_msg(__FILE__, "wait for %i video frame processing threads",
+ video_threads.count);
+ for (n = 0; n < video_threads.count; n++)
+ pthread_join(video_threads.threads[n], &status);
+ if (verbose >= TC_CLEANUP)
+ tc_log_msg(__FILE__, "video frame processing threads canceled");
+ }
+}
+
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/frame_threads.h b/debian/transcode/transcode-1.1.7/src/frame_threads.h
new file mode 100644
index 00000000..05df5760
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/frame_threads.h
@@ -0,0 +1,84 @@
+/*
+ * frame_threads.h -- declaration of transcode multithreaded filter
+ * processing code.
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifndef FRAME_THREADS_H
+#define FRAME_THREADS_H
+
+#include "transcode.h"
+
+/*
+ * SUMMARY:
+ *
+ * Those are the frame processing threads, implementing the threaded
+ * filter layer. There isn't direct control to those threads. They
+ * start to run after init(), and they are stopped by fini().
+ * It is important to note that each thread is equivalent to each
+ * other, and each one will take care of one frame and applies to
+ * it the whole filter chain.
+ */
+
+/*
+ * tc_frame_threads_init: start the frame threads pool and implicitely
+ * and automatically starts the frame filter layer.
+ *
+ * Parameters:
+ * vob: vob structure.
+ * vworkers: number of threads in the video filter pool.
+ * aworkers: number of threads in the audio filter pool.
+ * Return Value:
+ * None.
+ */
+void tc_frame_threads_init(vob_t *vob, int vworkers, int aworkers);
+
+/*
+ * tc_frame_threads_close: destroy both audio and video filter pool threads,
+ * and automatically and implicitely stop the whole filter layer.
+ * It's important to note that this function assume that all processing loops
+ * are already been terminated.
+ * This is a blocking function.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ * Preconditions:
+ * processing threads are terminated for any reason
+ * (regular stop, end of stream reached, forced interruption).
+ */
+void tc_frame_threads_close(void);
+
+/*
+ * tc_frame_threads_audio_{video,audio}_workers:
+ * query the number of avalaible (not active) audio,video frame
+ * worker threads.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * The number of avalaible audio,video frame worker threads.
+ */
+int tc_frame_threads_have_video_workers(void);
+int tc_frame_threads_have_audio_workers(void);
+
+#endif /* FRAME_THREADS_H */
diff --git a/debian/transcode/transcode-1.1.7/src/framebuffer.c b/debian/transcode/transcode-1.1.7/src/framebuffer.c
new file mode 100644
index 00000000..4a4d8cdd
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/framebuffer.c
@@ -0,0 +1,1275 @@
+/*
+ * framebuffer.c -- audio/video frame ringbuffers, reloaded.
+ * (C) 2005-2010 - Francesco Romani <fromani -at- gmail -dot- com>
+ * Based on code
+ * (C) 2001-2006 - Thomas Oestreich.
+ *
+ * This file is part of transcode, a 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <pthread.h>
+
+#include "transcode.h"
+#include "tc_defaults.h"
+#include "framebuffer.h"
+#include "decoder.h"
+#include "encoder-common.h"
+
+#include "libtc/tcframes.h"
+#include "libtc/ratiocodes.h"
+
+/*
+ * Summary:
+ * This code acts as generic ringbuffer implementation, with
+ * specializations for main (audio and video) ringbufffers
+ * in order to cope legacy constraints from 1.0.x series.
+ * It replaces former src/{audio,video}_buffer.c in (hopefully!)
+ * a more generic, clean, maintanable, compact way.
+ *
+ * Please note that there is *still* some other ringbuffer
+ * scatthered through codebase (subtitle buffer,d emux buffers,
+ * possibly more). They will be merged lately or will be dropped
+ * or reworked.
+ *
+ * This code can, of course, be further improved (and GREATLY improved,
+ * especially for multithreading safeness), but doing so
+ * hasn't high priority on my TODO list, I've covered with this
+ * piece of code most urgent todos for 1.1.0. -- FR
+ */
+
+static pthread_mutex_t aframe_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static aframe_list_t *aframe_list_head = NULL;
+static aframe_list_t *aframe_list_tail = NULL;
+static pthread_cond_t audio_import_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t audio_filter_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t audio_export_cond = PTHREAD_COND_INITIALIZER;
+
+static pthread_mutex_t vframe_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static vframe_list_t *vframe_list_head = NULL;
+static vframe_list_t *vframe_list_tail = NULL;
+static pthread_cond_t video_import_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t video_filter_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t video_export_cond = PTHREAD_COND_INITIALIZER;
+
+void tc_framebuffer_interrupt_import(void)
+{
+ pthread_mutex_lock(&aframe_list_lock);
+ pthread_cond_signal(&audio_import_cond);
+ pthread_mutex_unlock(&aframe_list_lock);
+
+ pthread_mutex_lock(&vframe_list_lock);
+ pthread_cond_signal(&video_import_cond);
+ pthread_mutex_unlock(&vframe_list_lock);
+}
+
+void tc_framebuffer_interrupt(void)
+{
+ pthread_mutex_lock(&aframe_list_lock);
+ pthread_cond_signal(&audio_import_cond);
+ pthread_cond_broadcast(&audio_filter_cond);
+ /* filter layer deserves special care */
+ pthread_cond_signal(&audio_export_cond);
+ pthread_mutex_unlock(&aframe_list_lock);
+
+ pthread_mutex_lock(&vframe_list_lock);
+ pthread_cond_signal(&video_import_cond);
+ pthread_cond_broadcast(&video_filter_cond);
+ /* filter layer deserves special care */
+ pthread_cond_signal(&video_export_cond);
+ pthread_mutex_unlock(&vframe_list_lock);
+}
+
+/* ------------------------------------------------------------------ */
+
+/*
+ * Layered, custom allocator/disposer for ringbuffer structures.
+ * The idea is to simplify (from ringbuffer viewpoint!) frame
+ * allocation/disposal and to make it as much generic as is possible
+ * (avoif if()s and so on).
+ */
+
+typedef TCFramePtr (*TCFrameAllocFn)(const TCFrameSpecs *);
+
+typedef void (*TCFrameFreeFn)(TCFramePtr);
+
+/* ------------------------------------------------------------------ */
+
+typedef struct tcringframebuffer_ TCRingFrameBuffer;
+struct tcringframebuffer_ {
+ /* real ringbuffer */
+ TCFramePtr *frames;
+
+ /* indexes of ringbuffer */
+ int next;
+ int last;
+
+ /* counters. How many frames in various TCFrameStatus-es? */
+ int null;
+ int empty;
+ int wait;
+ int locked;
+ int ready;
+
+ /* what we need here? */
+ const TCFrameSpecs *specs;
+ /* (de)allocation helpers */
+ TCFrameAllocFn alloc;
+ TCFrameFreeFn free;
+};
+
+static TCRingFrameBuffer tc_audio_ringbuffer;
+static TCRingFrameBuffer tc_video_ringbuffer;
+
+/*
+ * Specs used internally. I don't export this structure directly
+ * because I want to be free to change it if needed
+ */
+static TCFrameSpecs tc_specs = {
+ /* Largest supported values, to ensure the buffer is always big enough
+ * (see FIXME in tc_framebuffer_set_specs()) */
+ .frc = 3, // PAL, why not
+ .width = TC_MAX_V_FRAME_WIDTH,
+ .height = TC_MAX_V_FRAME_HEIGHT,
+ .format = TC_CODEC_RGB,
+ .rate = RATE,
+ .channels = CHANNELS,
+ .bits = BITS,
+ .samples = 48000.0,
+};
+
+/*
+ * Frame allocation/disposal helpers, needed by code below
+ * thin wrappers around libtc facilities
+ * I don't care about layering and performance loss, *here*, because
+ * frame are supposed to be allocated/disposed ahead of time, and
+ * always outside inner (performance-sensitive) loops.
+ */
+
+/* ------------------------------------------------------------------ */
+
+#define TCFRAMEPTR_IS_NULL(tcf) (tcf.generic == NULL)
+
+static TCFramePtr tc_video_alloc(const TCFrameSpecs *specs)
+{
+ TCFramePtr frame;
+ frame.video = tc_new_video_frame(specs->width, specs->height,
+ specs->format, TC_FALSE);
+ return frame;
+}
+
+static TCFramePtr tc_audio_alloc(const TCFrameSpecs *specs)
+{
+ TCFramePtr frame;
+ frame.audio = tc_new_audio_frame(specs->samples, specs->channels,
+ specs->bits);
+ return frame;
+}
+
+
+static void tc_video_free(TCFramePtr frame)
+{
+ tc_del_video_frame(frame.video);
+}
+
+static void tc_audio_free(TCFramePtr frame)
+{
+ tc_del_audio_frame(frame.audio);
+}
+
+/* ------------------------------------------------------------------ */
+
+/* exported commodities :) */
+
+vframe_list_t *vframe_alloc_single(void)
+{
+ return tc_new_video_frame(tc_specs.width, tc_specs.height,
+ tc_specs.format, TC_TRUE);
+}
+
+aframe_list_t *aframe_alloc_single(void)
+{
+ return tc_new_audio_frame(tc_specs.samples, tc_specs.channels,
+ tc_specs.bits);
+}
+
+/* ------------------------------------------------------------------ */
+
+static void tc_ring_framebuffer_dump_status(const TCRingFrameBuffer *rfb,
+ const char *id)
+{
+ tc_log_msg(__FILE__, "%s: null=%i empty=%i wait=%i"
+ " locked=%i ready=%i",
+ id, rfb->null, rfb->empty, rfb->wait,
+ rfb->locked, rfb->ready);
+}
+
+
+const TCFrameSpecs *tc_framebuffer_get_specs(void)
+{
+ return &tc_specs;
+}
+
+/*
+ * using an <OOP-ism>accessor</OOP-ism> is also justified here
+ * by the fact that we compute (ahead of time) samples value for
+ * later usage.
+ */
+void tc_framebuffer_set_specs(const TCFrameSpecs *specs)
+{
+ /* silently ignore NULL specs */
+ if (specs != NULL) {
+ double fps;
+
+ /* raw copy first */
+ ac_memcpy(&tc_specs, specs, sizeof(TCFrameSpecs));
+
+ /* restore width/height/bpp
+ * (FIXME: temp until we have a way to know the max size that will
+ * be used through the decode/process/encode chain; without
+ * this, -V yuv420p -y raw -F rgb (e.g.) crashes with a
+ * buffer overrun)
+ */
+ tc_specs.width = TC_MAX_V_FRAME_WIDTH;
+ tc_specs.height = TC_MAX_V_FRAME_HEIGHT;
+ tc_specs.format = TC_CODEC_RGB;
+
+ /* then deduct missing parameters */
+ if (tc_frc_code_to_value(tc_specs.frc, &fps) == TC_NULL_MATCH) {
+ fps = 1.0; /* sane, very worst case value */
+ }
+/* tc_specs.samples = (double)tc_specs.rate/fps; */
+ tc_specs.samples = (double)tc_specs.rate;
+ /*
+ * FIXME
+ * ok, so we use a MUCH larger buffer (big enough to store 1 *second*
+ * of raw audio, not 1 *frame*) than needed for reasons similar as
+ * seen for above video.
+ * Most notably, this helps in keeping buffers large enough to be
+ * suitable for encoder flush (see encode_lame.c first).
+ */
+ }
+}
+
+/* ------------------------------------------------------------------ */
+/* NEW API, yet private */
+/* ------------------------------------------------------------------ */
+
+/*
+ * Threading notice:
+ *
+ * Generic code doesn't use any locking at all (yet).
+ * That's was a design choice. For clarity, locking is
+ * provided by back-compatibility wrapper functions,
+ * or by any other higher-lever caller.
+ *
+ * Client code (= outside this code) MUST NEVER used not-thread
+ * safe code.
+ */
+
+
+/*
+ * tc_init_ring_framebuffer: (NOT thread safe)
+ * initialize a framebuffer ringbuffer by allocating needed
+ * amount of frames using given parameters.
+ *
+ * Parameters:
+ * rfb: ring framebuffer structure to initialize.
+ * specs: frame specifications to use for allocation.
+ * alloc: frame allocation function to use.
+ * free: frame disposal function to use.
+ * size: size of ringbuffer (number of frame to allocate)
+ * Return Value:
+ * > 0: wrong (NULL) parameters
+ * 0: succesfull
+ * < 0: allocation failed for one or more framesbuffers/internal error
+ */
+static int tc_init_ring_framebuffer(TCRingFrameBuffer *rfb,
+ const TCFrameSpecs *specs,
+ TCFrameAllocFn alloc,
+ TCFrameFreeFn free,
+ int size)
+{
+ if (rfb == NULL || specs == NULL || size < 0
+ || alloc == NULL || free == NULL) {
+ return 1;
+ }
+ size = (size > 0) ?size :1; /* allocate at least one frame */
+
+ rfb->frames = tc_malloc(size * sizeof(TCFramePtr));
+ if (rfb->frames == NULL) {
+ return -1;
+ }
+
+ rfb->specs = specs;
+ rfb->alloc = alloc;
+ rfb->free = free;
+
+ for (rfb->last = 0; rfb->last < size; rfb->last++) {
+ rfb->frames[rfb->last] = rfb->alloc(rfb->specs);
+ if (TCFRAMEPTR_IS_NULL(rfb->frames[rfb->last])) {
+ if (verbose >= TC_DEBUG) {
+ tc_log_error(__FILE__, "failed frame allocation");
+ }
+ return -1;
+ }
+
+ rfb->frames[rfb->last].generic->status = TC_FRAME_NULL;
+ rfb->frames[rfb->last].generic->bufid = rfb->last;
+ }
+
+ rfb->next = 0;
+
+ rfb->null = size;
+ rfb->empty = 0;
+ rfb->wait = 0;
+ rfb->locked = 0;
+ rfb->ready = 0;
+
+ if (verbose >= TC_STATS) {
+ tc_log_info(__FILE__, "allocated %i frames in ringbuffer", size);
+ }
+ return 0;
+}
+
+/*
+ * tc_fini_ring_framebuffer: (NOT thread safe)
+ * finalize a framebuffer ringbuffer by freeing all acquired
+ * resources (framebuffer memory).
+ *
+ * Parameters:
+ * rfb: ring framebuffer structure to finalize.
+ * Return Value:
+ * None.
+ */
+static void tc_fini_ring_framebuffer(TCRingFrameBuffer *rfb)
+{
+ if (rfb != NULL && rfb->free != NULL) {
+ int i = 0, n = rfb->last;
+
+ for (i = 0; i < rfb->last; i++) {
+ rfb->free(rfb->frames[i]);
+ }
+ tc_free(rfb->frames);
+ rfb->last = 0;
+
+ if (verbose >= TC_STATS) {
+ tc_log_info(__FILE__, "freed %i frames in ringbuffer", n);
+ }
+ }
+}
+
+/*
+ * tc_ring_framebuffer_retrieve_frame: (NOT thread safe)
+ * retrieve next unclaimed (TC_FRAME_NULL) framebuffer from
+ * ringbuffer and return a pointer to it for later usage
+ * by client code.
+ *
+ * Parameters:
+ * rfb: ring framebuffer to use
+ * Return Value:
+ * Always a framebuffer generic pointer. That can be pointing to
+ * NULL if there aren't no more unclaimed (TC_FRAME_NULL) framebuffer
+ * avalaible; otherwise it contains
+ * a pointer to retrieved framebuffer.
+ * DO NOT *free() such pointer directly! use
+ * tc_ring_framebuffer_release_frame() instead!
+ */
+static TCFramePtr tc_ring_framebuffer_retrieve_frame(TCRingFrameBuffer *rfb)
+{
+ TCFramePtr ptr;
+ ptr.generic = NULL;
+
+ if (rfb != NULL) {
+ int i = 0;
+
+ ptr = rfb->frames[rfb->next];
+ for (i = 0; i < rfb->last; i++) {
+ if (ptr.generic->status == TC_FRAME_NULL) {
+ break;
+ }
+ rfb->next++;
+ rfb->next %= rfb->last;
+ ptr = rfb->frames[rfb->next];
+ }
+
+ if (ptr.generic->status != TC_FRAME_NULL) {
+ if (verbose >= TC_FLIST) {
+ tc_log_warn(__FILE__, "retrieved buffer=%i, but not empty",
+ ptr.generic->status);
+ }
+ ptr.generic = NULL; /* enforce NULL-ness */
+ } else {
+ if (verbose >= TC_FLIST) {
+ tc_log_msg(__FILE__, "retrieved buffer = %i [%i]",
+ rfb->next, ptr.generic->bufid);
+ }
+ /* adjust internal pointer */
+ rfb->null--;
+ rfb->next++;
+ rfb->next %= rfb->last;
+ }
+ }
+ return ptr;
+}
+
+/*
+ * tc_ring_framebuffer_release_frame: (NOT thread safe)
+ * release a previously retrieved frame back to ringbuffer,
+ * removing claim from it and making again avalaible (TC_FRAME_NULL).
+ *
+ * Parameters:
+ * rfb: ring framebuffer to use.
+ * frame: generic pointer to frame to release.
+ * Return Value:
+ * > 0: wrong (NULL) parameters.
+ * 0: succesfull
+ * < 0: internal error (frame to be released isn't empty).
+ */
+static int tc_ring_framebuffer_release_frame(TCRingFrameBuffer *rfb,
+ TCFramePtr frame)
+{
+ if (rfb == NULL || TCFRAMEPTR_IS_NULL(frame)) {
+ return 1;
+ }
+ if (verbose >= TC_FLIST) {
+ tc_log_msg(__FILE__, "releasing frame #%i [%i]",
+ frame.generic->bufid, rfb->next);
+ }
+ frame.generic->status = TC_FRAME_NULL;
+ rfb->null++;
+ return 0;
+}
+
+/*
+ * tc_ring_framebuffer_register_frame: (NOT thread safe)
+ * retrieve and register a framebuffer from a ringbuffer by
+ * attaching an ID to it, setup properly status and updating
+ * internal ringbuffer counters.
+ *
+ * That's the function that client code is supposed to use
+ * (maybe wrapped by some thin macros to save status setting troubles).
+ * In general, dont' use retrieve_frame directly, use register_frame
+ * instead.
+ *
+ * Parameters:
+ * rfb: ring framebuffer to use
+ * id: id to attach to registered framebuffer
+ * status: status of framebuffer to register. This was needed to
+ * make registering process multi-purpose.
+ * Return Value:
+ * Always a generic framebuffer pointer. That can be pointing to NULL
+ * if there isn't no more framebuffer avalaible on given ringbuffer;
+ * otherwise, it will point to a valid framebuffer.
+ */
+static TCFramePtr tc_ring_framebuffer_register_frame(TCRingFrameBuffer *rfb,
+ int id, int status)
+{
+ TCFramePtr ptr;
+
+ /* retrive a valid pointer from the pool */
+ if (verbose >= TC_FLIST) {
+ tc_log_msg(__FILE__, "register frame id = %i", id);
+ }
+#ifdef STATBUFFER
+ ptr = tc_ring_framebuffer_retrieve_frame(rfb);
+#else
+ ptr = rfb->alloc(rfb->specs);
+#endif
+
+ if (!TCFRAMEPTR_IS_NULL(ptr)) {
+ if (status == TC_FRAME_EMPTY) {
+ rfb->empty++;
+ /* blank common attributes */
+ memset(ptr.generic, 0, sizeof(frame_list_t));
+ ptr.generic->id = id;
+ } else if (status == TC_FRAME_WAIT) {
+ rfb->wait++;
+ }
+ ptr.generic->status = status;
+
+ /* enforce */
+ ptr.generic->next = NULL;
+ ptr.generic->prev = NULL;
+
+ if (verbose >= TC_FLIST) {
+ tc_ring_framebuffer_dump_status(rfb, "register_frame");
+ }
+ }
+ return ptr;
+}
+
+/*
+ * tc_ring_framebuffer_remove_frame: (NOT thread safe)
+ * De-register and release a given framebuffer;
+ * also updates internal ringbuffer counters.
+ *
+ * That's the function that client code is supposed to use.
+ * In general, don't use release_frame directly, use remove_frame
+ * instead.
+ *
+ * Parameters:
+ * rfb: ring framebuffer to use.
+ * frame: generic pointer to frambuffer to remove.
+ * Return Value:
+ * None.
+ */
+static void tc_ring_framebuffer_remove_frame(TCRingFrameBuffer *rfb,
+ TCFramePtr frame)
+{
+ if (rfb != NULL || !TCFRAMEPTR_IS_NULL(frame)) {
+ if (frame.generic->status == TC_FRAME_READY) {
+ rfb->ready--;
+ }
+ if (frame.generic->status == TC_FRAME_LOCKED) {
+ rfb->locked--;
+ }
+ /* release valid pointer to pool */
+#ifdef STATBUFFER
+ tc_ring_framebuffer_release_frame(rfb, frame);
+#else
+ rfb->free(frame);
+#endif
+
+ if (verbose >= TC_FLIST) {
+ tc_ring_framebuffer_dump_status(rfb, "remove_frame");
+ }
+ }
+}
+
+/* ------------------------------------------------------------------ */
+/* Backwared-compatible API */
+/* ------------------------------------------------------------------ */
+
+int aframe_alloc(int num)
+{
+ return tc_init_ring_framebuffer(&tc_audio_ringbuffer, &tc_specs,
+ tc_audio_alloc, tc_audio_free, num);
+}
+
+int vframe_alloc(int num)
+{
+ return tc_init_ring_framebuffer(&tc_video_ringbuffer, &tc_specs,
+ tc_video_alloc, tc_video_free, num);
+}
+
+
+void aframe_free(void)
+{
+ tc_fini_ring_framebuffer(&tc_audio_ringbuffer);
+}
+
+void vframe_free(void)
+{
+ tc_fini_ring_framebuffer(&tc_video_ringbuffer);
+}
+
+
+/* ------------------------------------------------------------------ */
+
+/*
+ * Macro VS generic functions like above:
+ *
+ * I've used generic code and TCFramePtr in every place I was
+ * capable to introduce them in a *clean* way without using any
+ * casting. Of course there is still a lot of room for improvements,
+ * but back compatibility is an issue too. I'd like to get rid
+ * of all those macro and swtich to pure generic code of course,
+ * so this will be improved in future revisions. In the
+ * meantime, patches and suggestions welcome ;) -- FR
+ */
+
+#define LIST_FRAME_APPEND(ptr, tail) do { \
+ if ((tail) != NULL) { \
+ (tail)->next = (ptr); \
+ (ptr)->prev = (tail); \
+ } \
+ (tail) = (ptr); \
+} while (0)
+
+#define LIST_FRAME_INSERT(ptr, head) do { \
+ if ((head) == NULL) { \
+ (head) = ptr; \
+ } \
+} while (0)
+
+
+aframe_list_t *aframe_register(int id)
+{
+ int interrupted = TC_FALSE;
+ TCFramePtr frame;
+
+ pthread_mutex_lock(&aframe_list_lock);
+
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(A|register) requesting a new audio frame");
+
+ while ((!interrupted && tc_import_audio_running())
+ && tc_audio_ringbuffer.null == 0) {
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(A|register) audio frame not ready, waiting");
+ pthread_cond_wait(&audio_import_cond, &aframe_list_lock);
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(A|register) audio frame wait ended");
+ interrupted = !tc_running();
+ }
+
+ if (interrupted) {
+ frame.audio = NULL;
+ } else {
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "new audio frame ready");
+
+ frame = tc_ring_framebuffer_register_frame(&tc_audio_ringbuffer,
+ id, TC_FRAME_EMPTY);
+ if (!TCFRAMEPTR_IS_NULL(frame)) {
+ /*
+ * complete initialization:
+ * backward-compatible stuff
+ */
+ LIST_FRAME_APPEND(frame.audio, aframe_list_tail);
+ /* first frame registered must set aframe_list_head */
+ LIST_FRAME_INSERT(frame.audio, aframe_list_head);
+ }
+ }
+ pthread_mutex_unlock(&aframe_list_lock);
+ return frame.audio;
+}
+
+vframe_list_t *vframe_register(int id)
+{
+ int interrupted = TC_FALSE;
+ TCFramePtr frame;
+
+ pthread_mutex_lock(&vframe_list_lock);
+
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(V|register) requesting a new video frame");
+
+ while ((!interrupted && tc_import_video_running())
+ && tc_video_ringbuffer.null == 0) {
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(V|register) video frame not ready, waiting");
+ pthread_cond_wait(&video_import_cond, &vframe_list_lock);
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(V|register) video frame wait ended");
+ interrupted = !tc_running();
+ }
+
+ if (interrupted) {
+ frame.video = NULL;
+ } else {
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "new video frame ready");
+
+ frame = tc_ring_framebuffer_register_frame(&tc_video_ringbuffer,
+ id, TC_FRAME_EMPTY);
+ if (!TCFRAMEPTR_IS_NULL(frame)) {
+ /*
+ * complete initialization:
+ * backward-compatible stuff
+ */
+ LIST_FRAME_APPEND(frame.video, vframe_list_tail);
+ /* first frame registered must set vframe_list_head */
+ LIST_FRAME_INSERT(frame.video, vframe_list_head);
+ }
+ }
+ pthread_mutex_unlock(&vframe_list_lock);
+ return frame.video;
+}
+
+
+/* ------------------------------------------------------------------ */
+
+
+#define LIST_FRAME_LINK(ptr, f, tail) do { \
+ /* insert after ptr */ \
+ (ptr)->next = (f)->next; \
+ (f)->next = (ptr); \
+ (ptr)->prev = (f); \
+ \
+ if ((ptr)->next == NULL) { \
+ /* must be last ptr in the list */ \
+ (tail) = (ptr); \
+ } \
+} while (0)
+
+
+aframe_list_t *aframe_dup(aframe_list_t *f)
+{
+ int interrupted = TC_FALSE;
+ TCFramePtr frame;
+
+ if (f == NULL) {
+ tc_log_warn(__FILE__, "aframe_dup: empty frame");
+ return NULL;
+ }
+
+ pthread_mutex_lock(&aframe_list_lock);
+
+ while (!interrupted && tc_audio_ringbuffer.null == 0) {
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(A|dup) audio frame not ready, waiting");
+ pthread_cond_wait(&audio_import_cond, &aframe_list_lock);
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(A|dup) audio frame wait ended");
+ interrupted = !tc_running();
+ }
+
+ frame = tc_ring_framebuffer_register_frame(&tc_audio_ringbuffer,
+ 0, TC_FRAME_WAIT);
+ if (!TCFRAMEPTR_IS_NULL(frame)) {
+ aframe_copy(frame.audio, f, 1);
+
+ LIST_FRAME_LINK(frame.audio, f, aframe_list_tail);
+ }
+ pthread_mutex_unlock(&aframe_list_lock);
+ return frame.audio;
+}
+
+vframe_list_t *vframe_dup(vframe_list_t *f)
+{
+ int interrupted = TC_FALSE;
+ TCFramePtr frame;
+
+ if (f == NULL) {
+ tc_log_warn(__FILE__, "vframe_dup: empty frame");
+ return NULL;
+ }
+
+ pthread_mutex_lock(&vframe_list_lock);
+
+ while (!interrupted && tc_video_ringbuffer.null == 0) {
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(V|dup) video frame not ready, waiting");
+ pthread_cond_wait(&video_import_cond, &vframe_list_lock);
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(V|dup) video frame wait ended");
+ interrupted = !tc_running();
+ }
+
+ frame = tc_ring_framebuffer_register_frame(&tc_video_ringbuffer,
+ 0, TC_FRAME_WAIT);
+ if (!TCFRAMEPTR_IS_NULL(frame)) {
+ vframe_copy(frame.video, f, 1);
+
+ LIST_FRAME_LINK(frame.video, f, vframe_list_tail);
+ }
+ pthread_mutex_unlock(&vframe_list_lock);
+ return frame.video;
+}
+
+
+/* ------------------------------------------------------------------ */
+
+#define LIST_FRAME_REMOVE(ptr, head, tail) do { \
+ if ((ptr)->prev != NULL) { \
+ ((ptr)->prev)->next = (ptr)->next; \
+ } \
+ if ((ptr)->next != NULL) { \
+ ((ptr)->next)->prev = (ptr)->prev; \
+ } \
+ \
+ if ((ptr) == (tail)) { \
+ (tail) = (ptr)->prev; \
+ } \
+ if ((ptr) == (head)) { \
+ (head) = (ptr)->next; \
+ } \
+} while (0)
+
+void aframe_remove(aframe_list_t *ptr)
+{
+ if (ptr == NULL) {
+ tc_log_warn(__FILE__, "aframe_remove: given NULL frame pointer");
+ } else {
+ TCFramePtr frame;
+ frame.audio = ptr;
+
+ pthread_mutex_lock(&aframe_list_lock);
+
+ LIST_FRAME_REMOVE(ptr, aframe_list_head, aframe_list_tail);
+
+ tc_ring_framebuffer_remove_frame(&tc_audio_ringbuffer, frame);
+ pthread_cond_signal(&audio_import_cond);
+
+ pthread_mutex_unlock(&aframe_list_lock);
+ }
+}
+
+void vframe_remove(vframe_list_t *ptr)
+{
+ if (ptr == NULL) {
+ tc_log_warn(__FILE__, "vframe_remove: given NULL frame pointer");
+ } else {
+ TCFramePtr frame;
+ frame.video = ptr;
+
+ pthread_mutex_lock(&vframe_list_lock);
+
+ LIST_FRAME_REMOVE(ptr, vframe_list_head, vframe_list_tail);
+
+ tc_ring_framebuffer_remove_frame(&tc_video_ringbuffer, frame);
+ pthread_cond_signal(&video_import_cond);
+
+ pthread_mutex_unlock(&vframe_list_lock);
+ }
+}
+
+/* ------------------------------------------------------------------ */
+/* ------------------------------------------------------------------ */
+
+static aframe_list_t *aframe_retrieve_nowait(void)
+{
+ aframe_list_t *ptr = NULL;
+ pthread_mutex_lock(&aframe_list_lock);
+
+ if (verbose >= TC_CLEANUP) {
+ tc_log_msg(__FILE__, "(A|retrieve_nowait) requesting a new audio frame");
+ }
+ if (aframe_list_head != NULL && aframe_list_head->status == TC_FRAME_READY) {
+ ptr = aframe_list_head;
+ }
+ if (verbose >= TC_CLEANUP) {
+ tc_log_msg(__FILE__, "got a new audio frame reference: %p", ptr);
+ }
+ pthread_mutex_unlock(&aframe_list_lock);
+ return ptr;
+}
+
+
+static vframe_list_t *vframe_retrieve_nowait(void)
+{
+ vframe_list_t *ptr = NULL;
+ pthread_mutex_lock(&vframe_list_lock);
+
+ if (verbose >= TC_CLEANUP) {
+ tc_log_msg(__FILE__, "(V|retrieve_nowait) requesting a new video frame");
+ }
+ if (vframe_list_head != NULL && vframe_list_head->status == TC_FRAME_READY) {
+ ptr = vframe_list_head;
+ }
+ if (verbose >= TC_CLEANUP) {
+ tc_log_msg(__FILE__, "got a new video frame reference: %p", ptr);
+ }
+ pthread_mutex_unlock(&vframe_list_lock);
+ return ptr;
+}
+
+
+/* ------------------------------------------------------------------ */
+
+aframe_list_t *aframe_retrieve(void)
+{
+ int interrupted = TC_FALSE;
+ aframe_list_t *ptr = NULL;
+ pthread_mutex_lock(&aframe_list_lock);
+
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(A|retrieve) requesting a new audio frame");
+ while (!interrupted
+ && (aframe_list_head == NULL
+ || aframe_list_head->status != TC_FRAME_READY)) {
+ if (verbose >= TC_FLIST) {
+ tc_log_msg(__FILE__, "(A|retrieve) audio frame not ready, waiting");
+ tc_ring_framebuffer_dump_status(&tc_audio_ringbuffer, "retrieve");
+ }
+ pthread_cond_wait(&audio_export_cond, &aframe_list_lock);
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(A|retrieve) audio wait just ended");
+ interrupted = !tc_running();
+ }
+
+ if (!interrupted) {
+ ptr = aframe_list_head;
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "got a new audio frame reference: %p", ptr);
+ }
+ pthread_mutex_unlock(&aframe_list_lock);
+ return ptr;
+}
+
+
+vframe_list_t *vframe_retrieve(void)
+{
+ int interrupted = TC_FALSE;
+ vframe_list_t *ptr = NULL;
+ pthread_mutex_lock(&vframe_list_lock);
+
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(V|retrieve) requesting a new video frame");
+ while (!interrupted
+ && (vframe_list_head == NULL
+ || vframe_list_head->status != TC_FRAME_READY)) {
+ if (verbose >= TC_FLIST) {
+ tc_log_msg(__FILE__, "(V|retrieve) video frame not ready, waiting");
+ tc_ring_framebuffer_dump_status(&tc_video_ringbuffer, "retrieve");
+ }
+ pthread_cond_wait(&video_export_cond, &vframe_list_lock);
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(V|retrieve) video wait just ended");
+ interrupted = !tc_running();
+ }
+
+ if (!interrupted) {
+ ptr = vframe_list_head;
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "got a new video frame reference: %p", ptr);
+ }
+ pthread_mutex_unlock(&vframe_list_lock);
+ return ptr;
+}
+
+#undef LIST_FRAME_RETRIEVE
+
+/* ------------------------------------------------------------------ */
+
+void aframe_flush(void)
+{
+ int i = 0, done = TC_FALSE;
+
+ do {
+ aframe_list_t *ptr = aframe_retrieve_nowait();
+ if (!ptr) {
+ done = TC_TRUE;
+ } else {
+ if (verbose >= TC_CLEANUP) {
+ tc_log_msg(__FILE__,
+ "flushing audio buffer id=[%i] bufid=[%i]",
+ ptr->id, ptr->bufid);
+ }
+ aframe_remove(ptr);
+ i++;
+ }
+ } while (!done);
+
+ if (verbose >= TC_CLEANUP) {
+ tc_log_msg(__FILE__, "flushed %i audio frames", i);
+ }
+}
+
+void vframe_flush(void)
+{
+ int i = 0, done = TC_FALSE;
+
+ do {
+ vframe_list_t *ptr = vframe_retrieve_nowait();
+ if (!ptr) {
+ done = TC_TRUE;
+ } else {
+ if (verbose >= TC_CLEANUP) {
+ tc_log_msg(__FILE__,
+ "flushing video buffer id=[%i] bufid=[%i]",
+ ptr->id, ptr->bufid);
+ }
+ vframe_remove(ptr);
+ i++;
+ }
+ } while (!done);
+
+ if (verbose >= TC_CLEANUP) {
+ tc_log_msg(__FILE__, "flushed %i video frames", i);
+ }
+}
+
+void tc_framebuffer_flush(void)
+{
+ aframe_flush();
+ vframe_flush();
+}
+
+
+/* ------------------------------------------------------------------ */
+
+#define DEC_COUNTERS(RFB, STATUS) do { \
+ if ((STATUS) == TC_FRAME_READY) { \
+ (RFB)->ready--; \
+ } \
+ if ((STATUS) == TC_FRAME_LOCKED) { \
+ (RFB)->locked--; \
+ } \
+ if ((STATUS) == TC_FRAME_WAIT) { \
+ (RFB)->wait--; \
+ } \
+} while(0)
+
+#define INC_COUNTERS(RFB, STATUS) do { \
+ if ((STATUS) == TC_FRAME_READY) { \
+ (RFB)->ready++; \
+ } \
+ if ((STATUS) == TC_FRAME_LOCKED) { \
+ (RFB)->locked++; \
+ } \
+ if ((STATUS) == TC_FRAME_WAIT) { \
+ (RFB)->wait++; \
+ } \
+} while(0)
+
+#define FRAME_SET_STATUS(RFB, PTR, NEW_STATUS) do { \
+ DEC_COUNTERS((RFB), (PTR)->status); \
+ (PTR)->status = (NEW_STATUS); \
+ INC_COUNTERS((RFB), (PTR)->status); \
+} while (0)
+
+#define FRAME_LOOKUP(RFB, PTR, OLD_STATUS, NEW_STATUS) do { \
+ /* move along the chain and check for status */ \
+ for (; (PTR) != NULL; (PTR) = (PTR)->next) { \
+ if ((PTR)->status == (OLD_STATUS)) { \
+ /* found matching frame */ \
+ FRAME_SET_STATUS(RFB, PTR, NEW_STATUS); \
+ break; \
+ } \
+ } \
+} while (0)
+
+
+aframe_list_t *aframe_reserve(void)
+{
+ int interrupted = TC_FALSE;
+ aframe_list_t *ptr = NULL;
+
+ pthread_mutex_lock(&aframe_list_lock);
+
+ while (!interrupted && tc_audio_ringbuffer.wait == 0) {
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(A|reserve) audio frame not ready, waiting");
+ pthread_cond_wait(&audio_filter_cond, &aframe_list_lock);
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(A|reserve) audio wait just ended");
+ interrupted = !tc_running();
+ }
+
+ if (!interrupted) {
+ ptr = aframe_list_head;
+ FRAME_LOOKUP(&tc_audio_ringbuffer, ptr, TC_FRAME_WAIT, TC_FRAME_LOCKED);
+ }
+
+ pthread_mutex_unlock(&aframe_list_lock);
+ return ptr;
+}
+
+vframe_list_t *vframe_reserve(void)
+{
+ int interrupted = TC_FALSE;
+ vframe_list_t *ptr = NULL;
+
+ pthread_mutex_lock(&vframe_list_lock);
+
+ while (!interrupted && tc_video_ringbuffer.wait == 0) {
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(V|reserve) video frame not ready, waiting");
+ pthread_cond_wait(&video_filter_cond, &vframe_list_lock);
+ if (verbose >= TC_FLIST)
+ tc_log_msg(__FILE__, "(V|reserve) video wait just ended");
+ interrupted = !tc_running();
+ }
+
+ if (!interrupted) {
+ ptr = vframe_list_head;
+ FRAME_LOOKUP(&tc_video_ringbuffer, ptr, TC_FRAME_WAIT, TC_FRAME_LOCKED);
+ }
+
+ pthread_mutex_unlock(&vframe_list_lock);
+ return ptr;
+}
+
+#undef FRAME_LOOKUP
+
+/* ------------------------------------------------------------------ */
+
+
+#define FRAME_SET_EXT_STATUS(RFB, PTR, NEW_STATUS) do { \
+ if ((PTR)->status == TC_FRAME_EMPTY) { \
+ (RFB)->empty--; \
+ } \
+ FRAME_SET_STATUS((RFB), (PTR), (NEW_STATUS)); \
+ if ((PTR)->status == TC_FRAME_EMPTY) { \
+ (RFB)->empty++; \
+ } \
+} while (0)
+
+
+void aframe_push_next(aframe_list_t *ptr, int status)
+{
+ if (ptr == NULL) {
+ /* a bit more of paranoia */
+ tc_log_warn(__FILE__, "aframe_push_next: given NULL frame pointer");
+ } else {
+ pthread_mutex_lock(&aframe_list_lock);
+ FRAME_SET_EXT_STATUS(&tc_audio_ringbuffer, ptr, status);
+
+ if (status == TC_FRAME_WAIT) {
+ pthread_cond_signal(&audio_filter_cond);
+ } else if (status == TC_FRAME_READY && ptr == aframe_list_head) { // XXX
+ pthread_cond_signal(&audio_export_cond);
+ }
+ if (verbose >= TC_FLIST) {
+ tc_ring_framebuffer_dump_status(&tc_audio_ringbuffer, "push_next");
+ }
+ pthread_mutex_unlock(&aframe_list_lock);
+ }
+}
+
+
+void vframe_push_next(vframe_list_t *ptr, int status)
+{
+ if (ptr == NULL) {
+ /* a bit more of paranoia */
+ tc_log_warn(__FILE__, "vframe_push_next: given NULL frame pointer");
+ } else {
+ pthread_mutex_lock(&vframe_list_lock);
+ FRAME_SET_EXT_STATUS(&tc_video_ringbuffer, ptr, status);
+
+ if (status == TC_FRAME_WAIT) {
+ pthread_cond_signal(&video_filter_cond);
+ } else if (status == TC_FRAME_READY && ptr == vframe_list_head) { // XXX
+ pthread_cond_signal(&video_export_cond);
+ }
+ if (verbose >= TC_FLIST) {
+ tc_ring_framebuffer_dump_status(&tc_video_ringbuffer, "push_next");
+ }
+ pthread_mutex_unlock(&vframe_list_lock);
+ }
+}
+
+#undef FRAME_SET_STATUS
+#undef FRAME_SET_EXT_STATUS
+
+/* ------------------------------------------------------------------ */
+
+
+void aframe_dump_status(void)
+{
+ tc_ring_framebuffer_dump_status(&tc_audio_ringbuffer,
+ "audio buffer status");
+}
+
+void vframe_dump_status(void)
+{
+ tc_ring_framebuffer_dump_status(&tc_video_ringbuffer,
+ "video buffer status");
+}
+
+int vframe_have_more(void)
+{
+ int ret;
+ pthread_mutex_lock(&vframe_list_lock);
+ ret = (vframe_list_tail == NULL) ?0 :1;
+ pthread_mutex_unlock(&vframe_list_lock);
+ return ret;
+}
+
+int aframe_have_more(void)
+{
+ int ret;
+ pthread_mutex_lock(&aframe_list_lock);
+ ret = (aframe_list_tail == NULL) ?0 :1;
+ pthread_mutex_unlock(&aframe_list_lock);
+ return ret;
+}
+
+/* ------------------------------------------------------------------ */
+/* Frame copying routines */
+/* ------------------------------------------------------------------ */
+
+void aframe_copy(aframe_list_t *dst, const aframe_list_t *src,
+ int copy_data)
+{
+ if (!dst || !src) {
+ tc_log_warn(__FILE__, "aframe_copy: given NULL frame pointer");
+ return;
+ }
+
+ /* copy all common fields with just one move */
+ ac_memcpy(dst, src, sizeof(frame_list_t));
+
+ if (copy_data == 1) {
+ /* really copy video data */
+ ac_memcpy(dst->audio_buf, src->audio_buf, dst->audio_size);
+ } else {
+ /* soft copy, new frame points to old audio data */
+ dst->audio_buf = src->audio_buf;
+ }
+}
+
+void vframe_copy(vframe_list_t *dst, const vframe_list_t *src,
+ int copy_data)
+{
+ if (!dst || !src) {
+ tc_log_warn(__FILE__, "vframe_copy: given NULL frame pointer");
+ return;
+ }
+
+ /* copy all common fields with just one move */
+ ac_memcpy(dst, src, sizeof(frame_list_t));
+
+ dst->deinter_flag = src->deinter_flag;
+ dst->free = src->free;
+ /*
+ * we assert that plane pointers *are already properly set*
+ * we're focused on copy _content_ here.
+ */
+
+ if (copy_data == 1) {
+ /* really copy video data */
+ ac_memcpy(dst->video_buf, src->video_buf, dst->video_size);
+ } else {
+ /* soft copy, new frame points to old video data */
+ dst->video_buf = src->video_buf;
+ }
+}
+
+/*************************************************************************/
+
+void vframe_get_counters(int *im, int *fl, int *ex)
+{
+ pthread_mutex_lock(&vframe_list_lock);
+ *im = tc_video_ringbuffer.null + tc_video_ringbuffer.empty;
+ *fl = tc_video_ringbuffer.wait + tc_video_ringbuffer.locked;
+ *ex = tc_video_ringbuffer.ready;
+ pthread_mutex_unlock(&vframe_list_lock);
+}
+
+void aframe_get_counters(int *im, int *fl, int *ex)
+{
+ pthread_mutex_lock(&aframe_list_lock);
+ *im = tc_audio_ringbuffer.null + tc_audio_ringbuffer.empty;
+ *fl = tc_audio_ringbuffer.wait + tc_audio_ringbuffer.locked;
+ *ex = tc_audio_ringbuffer.ready;
+ pthread_mutex_unlock(&aframe_list_lock);
+}
+
+void tc_framebuffer_get_counters(int *im, int *fl, int *ex)
+{
+ int v_im, v_fl, v_ex, a_im, a_fl, a_ex;
+
+ vframe_get_counters(&v_im, &v_fl, &v_ex);
+ aframe_get_counters(&a_im, &a_fl, &a_ex);
+
+ *im = v_im + a_im;
+ *fl = v_fl + a_fl;
+ *ex = v_ex + a_ex;
+}
+
+/*************************************************************************/
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/framebuffer.h b/debian/transcode/transcode-1.1.7/src/framebuffer.h
new file mode 100644
index 00000000..30528907
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/framebuffer.h
@@ -0,0 +1,499 @@
+/*
+ * framebuffer.h -- declarations of audio/video frame ringbuffers.
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ * Updates and Enhancements
+ * (C) 2007-2010 - Francesco Romani <fromani -at- gmail -dot- com>
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+
+#ifndef FRAMEBUFFER_H
+#define FRAMEBUFFER_H
+
+#include <stdint.h>
+
+#include "libtc/tcframes.h"
+#include "tc_defaults.h"
+
+
+/*************************************************************************
+ * Transcode Framebuffer in a Nutshell (aka: how this code works)
+ * --------------------------------------------------------------
+ *
+ * Introduction:
+ * -------------
+ * This is a quick, terse overview of design principles beyond the
+ * framebuffer and about the design of this code. Full-blown
+ * documentation is avalaible under doc/.
+ *
+ * When reading framebuffer documentation/code, always take in mind
+ * the thread layout of transcode:
+ *
+ * - import layer is supposed to run 2 threads concurrently
+ * - filter layer is supposed to run 0..N threads concurrently
+ * - export layer is supposed to run 1 thread
+ *
+ * So, in any transcode execution, framebuffer code is supposed to
+ * serve from 3 to N+3 concurrent threads.
+ *
+ * Framebuffer entities:
+ * ---------------------
+ * XXX
+ *
+ * frame status transitions scheme (API reminder):
+ * -----------------------------------------------
+ *
+ * .---------<---------------<------+-------<------.
+ * V | 7 | 6
+ * .------------. .--------. .--------. .--------.
+ * | frame pool | --> | import | | filter | | export |
+ * `------------' 1 `--------' `--------' `--------'
+ * | A | A
+ * | 3 | | 4 |
+ * 2 | | V 5 |
+ * V .-------------. |
+ * `---->| frame chain |--->'
+ * `-------------'
+ *
+ * In frame lifetime order:
+ * 1. {a,v}frame_register (import)
+ * 2. {a,v}frame_push_next (import)
+ * 3. {a,v}frame_reserve (filter)
+ * 4. {a,v}frame_push_next (filter)
+ * 5. {a,v}frame_retrieve (export)
+ * 6. {a,v}frame_remove (export)
+ * [ 7. {a,v}frame_remove (filter) ]
+ *
+ * Operating conditions:
+ *
+ * 1. single source, full range, no interruptions
+ * 2. single source, full range, interruption
+ * 3. single source, sub range, no interruptions
+ * 4. single source, sub range, interruption
+ * 5. single source, multi sub ranges, no interruptions
+ * 5. single source, multi sub ranges, interruption
+ */
+
+
+/*
+ * frame*buffer* specifications, needed to properly allocate
+ * and initialize single frame buffers
+ */
+typedef struct tcframespecs_ TCFrameSpecs;
+struct tcframespecs_ {
+ int frc; /* frame ratio code is more precise than value */
+
+ /* video fields */
+ int width;
+ int height;
+ int format; /* TC_CODEC_reserve preferred,
+ * CODEC_reserve still supported for compatibility
+ */
+ /* audio fields */
+ int rate;
+ int channels;
+ int bits;
+
+ /* private field, used internally */
+ double samples;
+};
+
+/*
+ * tc_framebuffer_get_specs: (NOT thread safe)
+ * Get a pointer to a TCFrameSpecs structure representing current
+ * framebuffer structure. Frame handling code will use those parameters
+ * to allocate framebuffers.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * Constant pointer to a TCFrameSpecs structure. There is no need
+ * to *free() this structure.
+ */
+const TCFrameSpecs *tc_framebuffer_get_specs(void);
+
+/*
+ * tc_framebuffer_set_specs: (NOT thread safe)
+ * Setup new framebuffer parameters, to be used by internal framebuffer
+ * code to properly handle frame allocation.
+ * PLEASE NOTE that only allocation performed AFTER calling this function
+ * will use those parameters.
+ * PLEASE ALSO NOTE that is HIGHLY unsafe to mix allocation by changing
+ * TCFrameSpecs in between without freeing ringbuffers. Just DO NOT.
+ *
+ * Parameters:
+ * Constant pointer to a TCFrameSpecs holding new framebuffer parameters.
+ * Return Value:
+ * None.
+ */
+void tc_framebuffer_set_specs(const TCFrameSpecs *specs);
+
+/*
+ * tc_framebuffer_interrupt: (thread safe)
+ * Interrupt the framebuffer immediately (see below for specific meaning
+ * of this act in various functions).
+ * When framebuffer is interrupted, frames belonging to any processing
+ * stage are no longer avalaible; frame unavalaibility is notified as
+ * soon as is possible.
+ * When a framebuffer is interrupted, it becomes ready to be finalized;
+ * Effectively, the only operations that make sense to be performed on
+ * an interrupted framebuffer, is to finalize it.
+ * From statements above easily descend that interruption is irreversible.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ * Side effects:
+ * Any frame-claiming function will fail after the invocation of this
+ * function (see description above).
+ */
+void tc_framebuffer_interrupt(void);
+void tc_framebuffer_interrupt_import(void);
+
+/*
+ * vframe_alloc, aframe_alloc: (NOT thread safe)
+ * Allocate respectively a video or audio frame ringbuffer capable to hold
+ * given amount of frames, with a minimum of one.
+ * Each framebuffer is allocated using TCFrameSpecs parameters.
+ * Use vframe_free/aframe_free to release acquired ringbuffers.
+ *
+ * Parameters:
+ * num: size of ringbuffer to allocate (number of framebuffers holded
+ * in ringbuffer).
+ * Return Value:
+ * 0: succesfull
+ * !0: error, tipically this means that one (or more) frame
+ * can't be allocated.
+ */
+int vframe_alloc(int num);
+int aframe_alloc(int num);
+
+/*
+ * vframe_alloc_single, aframe_alloc_single: (NOT thread safe)
+ * allocate a single framebuffer (respectively, video or audio)
+ * in compliacy with last TCFrameSpecs set.
+ * Those functione are mainly intended to provide a convenient
+ * way to encoder/decoder/whatelse to allocate private framebuffers
+ * without doing any size computation or waste memory.
+ * Returned value can be SAFELY deallocated using
+ * tc_del_video_frame or tc_del_audio_frame.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * respectively a pointer to a vframe_list_t or aframe_list_t,
+ * like, tc_new_video_frame() or tc_new_audio_frame() called
+ * with right parameters.
+ * NULL if allocation fails.
+ */
+vframe_list_t *vframe_alloc_single(void);
+aframe_list_t *aframe_alloc_single(void);
+
+/*
+ * vframe_free, aframe_free: (NOT thread safe)
+ * release all framebuffer memory acquired respect. for video and
+ * audio frame ringbuffers.
+ * Please remember thet ffter those functions called, almost
+ * all other ringbuffer functions will fail.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ */
+void vframe_free(void);
+void aframe_free(void);
+
+/*
+ * vframe_flush, aframe_flush: (NOT thread safe)
+ * flush all framebuffers still in ringbuffer, by marking those as unused.
+ * This will reset ringbuffer to an empty state, ready to be (re)used again.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ */
+void vframe_flush(void);
+void aframe_flush(void);
+
+/*
+ * tc_framebuffer_flush: (NOT thread safe)
+ * flush all active ringbuffers, and mark all frames as unused.
+ * This will reset ringbuffers to an empty state, ready to be (re)used again.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ */
+void tc_framebuffer_flush(void);
+
+/*
+ * vframe_register, aframe_register: (thread safe)
+ * Frame claiming functions.
+ * Respectively wait for an empty audio and video frame,
+ * then register it in frame chain, attach the given `id'
+ * and finally return the pointer to caller.
+ *
+ * Those function are (and should be) used at the beginning
+ * of the frame chain. Those should are the first function
+ * that a framebuffer should see in it's lifecycle.
+ *
+ * In transcode, those functions are (and should be) used
+ * only in the decoder.
+ *
+ * Note:
+ * DO NOT *free() returned pointer! The memory needed for frames is
+ * handled by transcode internally.
+ *
+ * Parameters:
+ * id: set framebuffer id to this value.
+ * The meaning of `id' is enterely client-depended.
+ * Return Value:
+ * A valid pointer to respectively an empty video or audio frame.
+ * If framebuffer is interrupted, both returns NULL.
+ * Side effects:
+ * Being frame claiming functions, those functions will block
+ * calling thread until a new frame will be avalaible, OR
+ * until an interruption happens.
+ */
+vframe_list_t *vframe_register(int id);
+aframe_list_t *aframe_register(int id);
+
+/*
+ * vframe_reserve, aframe_reserve: (thread safe)
+ * Frame claiming functions.
+ * Respectively wait for a processing-needing
+ * (`waiting' in transcode slang) audio and video frame,
+ * then reserve it, preventing other calls to those functions
+ * to claim it twice, and finally return the pointer to caller.
+ *
+ * Those function are (and should be) used in the middle
+ * of the frame chain.
+ *
+ * In transcode, those functions are (and should be) used
+ * only in the filter layer.
+ *
+ * Note:
+ * DO NOT *free() returned pointer! The memory needed for frames is
+ * handled by transcode internally.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * A valid pointer to respectively an empty video or audio frame.
+ * If framebuffer is interrupted, both returns NULL.
+ * Side effects:
+ * Being frame claiming functions, those functions will block
+ * calling thread until a new frame will be avalaible, OR
+ * until an interruption happens.
+ */
+vframe_list_t *vframe_reserve(void);
+aframe_list_t *aframe_reserve(void);
+
+/*
+ * vframe_retrieve, aframe_retrieve: (thread safe)
+ * Frame claiming functions.
+ * Respectively wait for a audio and video frame ready to be
+ * encoded, then retrieve it, preventing other calls to those
+ * functions to claim it twice, and finally return the pointer
+ * to caller.
+ *
+ * Those function are (and should be) used at the end
+ * of the frame chain.
+ *
+ * In transcode, those functions are (and should be) used
+ * only in the encoder.
+ *
+ * Note:
+ * DO NOT *free() returned pointer! The memory needed for frames is
+ * handled by transcode internally.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * A valid pointer to respectively an empty video or audio frame.
+ * If framebuffer is interrupted, both returns NULL.
+ * Side effects:
+ * Being frame claiming functions, those functions will block
+ * calling thread until a new frame will be avalaible, OR
+ * until an interruption happens.
+ */
+vframe_list_t *vframe_retrieve(void);
+aframe_list_t *aframe_retrieve(void);
+
+/*
+ * vframe_remove, aframe_remove: (thread safe)
+ * Respectively release an audio or video frame,
+ * by marking it as unused and putting it back on the frame pool.
+ *
+ * Those function are (and should be) used at the end
+ * of the frame chain. Those should are the last function
+ * that a framebuffer should see in it's lifecycle.
+ *
+ * In transcode, those functions are (and should be) used
+ * only in the encoder.
+ *
+ * Parameters:
+ * ptr: framebuffer to release.
+ * Return Value:
+ * None.
+ */
+void vframe_remove(vframe_list_t *ptr);
+void aframe_remove(aframe_list_t *ptr);
+
+/*
+ * vframe_push_next, aframe_push_next: (thread safe)
+ * Push a frame into next processing stage, by changing
+ * its status.
+ * Those functions are used when a processing stage terminate
+ * its operations on a given frame and so it want to pass such
+ * frame to next stage.
+ *
+ * In transcode, those functions are (and should be) used
+ * in the decoder and in the filter stage.
+ *
+ * Parameters:
+ * ptr: framebuffer pointer to be updated.
+ * status: new framebuffer status (= stage).
+ * Return Value:
+ * None.
+ * Side effects:
+ * A blocked thread can (and it will likely) be awaken
+ * by this operation.
+ */
+void vframe_push_next(vframe_list_t *ptr, TCFrameStatus status);
+void aframe_push_next(aframe_list_t *ptr, TCFrameStatus status);
+
+/*
+ * vframe_dup, aframe_dup: (thread safe)
+ * Frame claiming functions.
+ * Duplicate given respectively video or audio framebuffer.
+ * New framebuffer will be a full (deep) copy of old one
+ * (see aframe_copy/vframe_copy documentation to learn about
+ * deep copy).
+ *
+ * Parameters:
+ * f: framebuffer to be copied.
+ * Return Value:
+ * A valid pointer to respectively duplicate video or audio frame.
+ * If framebuffer is interrupted, both returns NULL.
+ * Side Effects:
+ * Being frame claiming functions, those functions will block
+ * calling thread until a new frame will be avalaible, OR
+ * until an interruption happens.
+ */
+vframe_list_t *vframe_dup(vframe_list_t *f);
+aframe_list_t *aframe_dup(aframe_list_t *f);
+
+/*
+ * vframe_copy, aframe_copy (thread safe)
+ * perform a soft or optionally deep copy respectively of a
+ * video or audio framebuffer. A soft copy just copies metadata;
+ * #ifdef STATBUFFER
+ * soft copy also let the buffer pointers point to original frame
+ * buffers, so data isn't really copied around.
+ * #endif
+ * A deep copy just ac_memcpy()s buffer data from a frame to other
+ * one, so new frame will be an independent copy of old one.
+ *
+ * Parameters:
+ * dst: framebuffer which will hold te copied (meta)data.
+ * src: framebuffer to be copied.
+ * Mind the fact that when using softcopy real buffers will
+ * remain the ones of this frame
+ * copy_data: boolean flag. If 0, do softcopy; do deepcopy otherwise.
+ *
+ * Return Value:
+ * None.
+ */
+void vframe_copy(vframe_list_t *dst, const vframe_list_t *src, int copy_data);
+void aframe_copy(aframe_list_t *dst, const aframe_list_t *src, int copy_data);
+
+/*
+ * vframe_dump_status, aframe_dump_status: (NOT thread safe)
+ * tc_log* out current framebuffer ringbuffer internal status, e.g.
+ * counters for null/ready/empty/loacked frames) respectively for
+ * video and audio ringbuffers.
+ *
+ * THREAD SAFENESS WARNING:
+ * WRITEME
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * None.
+ * Side effects:
+ * See THREAD SAFENESS WARNING above.
+ */
+void vframe_dump_status(void);
+void aframe_dump_status(void);
+
+/*
+ * vframe_have_more, aframe_have_more (thread safe):
+ * check if video/audio frame list is empty or not.
+ *
+ * Parameters:
+ * None.
+ * Return Value:
+ * !0 if frame list has at least one frame
+ * 0 otherwise
+ */
+int vframe_have_more(void);
+int aframe_have_more(void);
+
+/*
+ * {v,a}frame_get_counters (thead safe):
+ * get the number of frames currently hold in the processing layers,
+ * respectively for video and audio pipelines.
+ *
+ * Parameters:
+ * im: if not NULL, store here the number of frames
+ * hold by import layer.
+ * fl: if not NULL, store here the number of frames
+ * hold by filter layer.
+ * ex: if not NULL, store here the number of frames
+ * hold by export layer.
+ * Return Value:
+ * None.
+ */
+void vframe_get_counters(int *im, int *fl, int *ex);
+void aframe_get_counters(int *im, int *fl, int *ex);
+
+/*
+ * tc_framebuffer_get_counters (thread safe):
+ * get the total number of frames currently hold in the processing
+ * layers, by considering both video and audio pipelines.
+ *
+ * Parameters:
+ * im: if not NULL, store here the number of frames
+ * hold by import layer.
+ * fl: if not NULL, store here the number of frames
+ * hold by filter layer.
+ * ex: if not NULL, store here the number of frames
+ * hold by export layer.
+ * Return Value:
+ * None.
+ */
+void tc_framebuffer_get_counters(int *im, int *fl, int *ex);
+
+#endif /* FRAMEBUFFER_H */
diff --git a/debian/transcode/transcode-1.1.7/src/probe.c b/debian/transcode/transcode-1.1.7/src/probe.c
new file mode 100644
index 00000000..2cdbdfc5
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/probe.c
@@ -0,0 +1,859 @@
+/*
+ * probe.c - probe input file for parameters
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "transcode.h"
+#include "probe.h"
+#include "libtc/libtc.h"
+#include "libtc/tccodecs.h"
+#include "libtc/ratiocodes.h"
+#include "import/magic.h"
+
+#include <sys/wait.h> // for waitpid()
+
+/*************************************************************************/
+
+/* Handy macro to check whether the probe flags allow setting of a
+ * particular field (pass the flag name without TC_PROBE_NO_): */
+#define MAY_SET(flagname) (!(flags & TC_PROBE_NO_##flagname))
+
+/* Internal routine declarations: */
+
+static int do_probe(const char *file, const char *nav_seek_file, int title,
+ int range, int mplayer_flag, int verbose_flag,
+ ProbeInfo *info_ret);
+static void select_modules(int flags, vob_t *vob);
+
+/*************************************************************************/
+/*************************************************************************/
+
+/* External interfaces */
+
+/*************************************************************************/
+
+/**
+ * probe_stream_data: Probe a single source file and store the stream
+ * informations in data structure.
+ *
+ * Parameters:
+ * file: File name to probe.
+ * range: Amount of input file to probe, in MB.
+ * info: Structure to be filled in with probed data.
+ * Return value:
+ * Nonzero on success, zero on error.
+ * Preconditions:
+ * info != NULL, range > 0
+ */
+int probe_stream_data(const char *file, int range, ProbeInfo *info)
+{
+ if (!info || range <= 0) {
+ tc_log_error(PACKAGE, "wrong probing parameters");
+ return 0;
+ }
+
+ if (!file) {
+ tc_log_warn(PACKAGE, "missing source to probe");
+ memset(info, 0, sizeof(ProbeInfo));
+ } else {
+ if (!do_probe(file, NULL, 0, range, 0,
+ (verbose >= TC_DEBUG) ? verbose : 0, info)
+ ) {
+ if (verbose & TC_DEBUG) {
+ tc_log_warn(PACKAGE, "(%s) failed to probe stream '%s'",
+ __FILE__, file);
+ }
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+/**
+ * probe_source: Probe the given input file(s) and store the results in
+ * the global data structure.
+ *
+ * Parameters:
+ * vid_file: Video file name, or NULL if none.
+ * aud_file: Audio file name, or NULL if none.
+ * range: Amount of input files to probe, in MB.
+ * flags: Flags indicating which global parameters should be left
+ * alone (TC_PROBE_NO_xxx flags).
+ * vob: Pointer to global data structure.
+ * Return value:
+ * Nonzero on success, zero on error.
+ * Preconditions:
+ * vob != NULL
+ */
+
+int probe_source(const char *vid_file, const char *aud_file, int range,
+ int flags, vob_t *vob)
+{
+ ProbeInfo vinfo, ainfo; // video and audio info structures
+
+ /* Probe the video file, if present */
+ if (vid_file) {
+ if (!do_probe(vid_file, vob->nav_seek_file, vob->dvd_title, range,
+ (flags & TC_PROBE_NO_BUILTIN),
+ (verbose >= TC_DEBUG) ? verbose : 0, &vinfo)
+ ) {
+ if (verbose & TC_DEBUG) {
+ tc_log_warn(PACKAGE, "(%s) failed to probe video source",
+ __FILE__);
+ }
+ return 0;
+ }
+ } else {
+ vob->has_video = 0;
+ }
+
+ /* Probe the audio file, if present */
+ if (aud_file) {
+ if (!do_probe(aud_file, vob->nav_seek_file, vob->dvd_title, range,
+ (flags & TC_PROBE_NO_BUILTIN),
+ (verbose >= TC_DEBUG) ? verbose : 0, &ainfo)
+ ) {
+ if (verbose & TC_DEBUG) {
+ tc_log_warn(PACKAGE, "(%s) failed to probe audio source",
+ __FILE__);
+ }
+ return 0;
+ }
+ } /* else it might be contained in the video file */
+
+ /* Set global parameters based on probed data */
+ probe_to_vob(vid_file ? &vinfo : NULL, aud_file ? &ainfo : NULL,
+ flags, vob);
+ if (verbose & TC_DEBUG) {
+ tc_log_info(PACKAGE, "(%s) V magic=0x%lx, A magic=0x%lx,"
+ " V codec=0x%lx, A codec=0x%lx", __FILE__,
+ vob->v_format_flag, vob->a_format_flag,
+ vob->v_codec_flag, vob->a_codec_flag);
+ tc_log_info(PACKAGE, "(%s) V magic=%s, A magic=%s, V codec=%s,"
+ " A codec=%s", __FILE__,
+ mformat2str(vob->v_format_flag),
+ mformat2str(vob->a_format_flag),
+ tc_codec_to_comment(vob->v_codec_flag),
+ tc_codec_to_comment(vob->a_codec_flag));
+ }
+
+ /* All done, return success */
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * probe_source_xml: Probe video or audio parameters from an XML file as
+ * specified by the vob_t data structure.
+ *
+ * Parameters:
+ * vob: Global vob_t data structure.
+ * which: PROBE_XML_VIDEO or PROBE_XML_AUDIO.
+ * Return value:
+ * Nonzero on success, zero on error.
+ * Side effects:
+ * Prints an error message on error.
+ */
+
+/* FIXME: is this the right place for these? */
+
+int probe_source_xml(vob_t *vob, int which)
+{
+ int retval = 1;
+#ifdef HAVE_LIBXML2
+ int tochild[2], fromchild[2]; /* pipes */
+ pid_t pid;
+ int resize;
+
+ if (pipe(tochild) == -1) {
+ tc_log_perror(PACKAGE, "probe_source_xml(): pipe(tochild) failed");
+ return 0;
+ }
+ if (pipe(fromchild) == -1) {
+ tc_log_perror(PACKAGE, "probe_source_xml(): pipe(fromchild) failed");
+ close(tochild[0]);
+ close(tochild[1]);
+ return 0;
+ }
+ pid = fork();
+ if (pid == -1) {
+ tc_log_perror(PACKAGE, "probe_source_xml(): fork failed");
+ return 0;
+ } else if (pid > 0) {
+ /* Child process */
+ const char *new_argv[6];
+ close(tochild[1]);
+ close(fromchild[0]);
+ if (tochild[0] != 0) {
+ if (dup2(tochild[0], 0) == -1) {
+ tc_log_perror(PACKAGE, "probe_source_xml(): dup2(0) failed");
+ exit(-1);
+ }
+ close(tochild[0]);
+ }
+ if (fromchild[1] != 1) { // theoretically always true, but JIC
+ if (dup2(fromchild[1], 1) == -1) {
+ tc_log_perror(PACKAGE, "probe_source_xml(): dup2(1) failed");
+ exit(-1);
+ }
+ close(fromchild[1]);
+ }
+ new_argv[0] = "tcxmlcheck";
+ new_argv[1] = "-i";
+ new_argv[2] = vob->video_in_file;
+ new_argv[3] = "-B";
+ new_argv[4] = (which==PROBE_XML_VIDEO ? "-V" : "-A");
+ new_argv[5] = NULL;
+ execvp("tcxmlcheck", (char **)new_argv);
+ tc_log_perror(PACKAGE, "probe_source_xml(): exec(tcxmlcheck) failed");
+ exit(-1);
+ }
+ /* Parent process */
+ retval = 0;
+ close(tochild[0]);
+ close(fromchild[1]);
+ if (write(tochild[1], vob, sizeof(vob_t)) != sizeof(vob_t)) {
+ tc_log_error(PACKAGE, "Error writing data to tcxmlcheck: %s",
+ strerror(errno));
+ close(tochild[1]);
+ close(fromchild[0]);
+ /* Can't just return--need to reap the child */
+ goto reapchild;
+ }
+ close(tochild[1]);
+ if (read(fromchild[0], vob, sizeof(vob_t)) != sizeof(vob_t)) {
+ tc_log_error(PACKAGE, "Error reading data from tcxmlcheck");
+ close(fromchild[0]);
+ goto reapchild;
+ }
+ if (read(fromchild[0], &resize, sizeof(int)) != sizeof(int)) {
+ tc_log_error(PACKAGE, "Error reading data from tcxmlcheck 2");
+ close(fromchild[0]);
+ goto reapchild;
+ }
+ close(fromchild[0]);
+ if (which == PROBE_XML_VIDEO && resize == 2) {
+ // XML forced resize, clear command line parameters
+ resize1 = TC_FALSE;
+ resize2 = TC_FALSE;
+ zoom = TC_FALSE;
+ vob->resize1_mult = 32;
+ vob->vert_resize1 = 0;
+ vob->hori_resize1 = 0;
+ vob->resize2_mult = 32;
+ vob->vert_resize2 = 0;
+ vob->hori_resize2 = 0;
+ vob->zoom_width = 0;
+ vob->zoom_height = 0;
+ vob->zoom_filter = TCV_ZOOM_LANCZOS3;
+ }
+ retval = 1;
+
+ reapchild: // clean up after the child process
+ waitpid(pid, NULL, 0);
+#endif // HAVE_LIBXML2
+
+ return retval;
+}
+
+/*************************************************************************/
+
+/**
+ * mformat2str: Return a descriptive
+ * string for the given video format flag.
+ *
+ * Parameters:
+ * flag: Flag to return string for.
+ * Return value:
+ * String describing `flag'.
+ */
+
+
+const char *mformat2str(int flag)
+{
+ switch (flag) {
+ case TC_MAGIC_PAL: return "PAL";
+ case TC_MAGIC_NTSC: return "NTSC";
+ case TC_MAGIC_TS: return "MPEG transport stream";
+ case TC_MAGIC_YUV4MPEG: return "YUV4MPEG";
+ case TC_MAGIC_NUV: return "NuppelVideo";
+ case TC_MAGIC_DVD_PAL: return "DVD PAL";
+ case TC_MAGIC_DVD_NTSC: return "DVD NTSC";
+ case TC_MAGIC_AVI: return "RIFF data, AVI";
+ case TC_MAGIC_MOV: return "QuickTime";
+ case TC_MAGIC_XML: return "XML file";
+ case TC_MAGIC_TIFF1: return "TIFF image";
+ case TC_MAGIC_TIFF2: return "TIFF image";
+ case TC_MAGIC_JPEG: return "JPEG image";
+ case TC_MAGIC_BMP: return "BMP image";
+ case TC_MAGIC_PNG: return "PNG image";
+ case TC_MAGIC_GIF: return "GIF image";
+ case TC_MAGIC_PPM: return "PPM image";
+ case TC_MAGIC_PGM: return "PGM image";
+ case TC_MAGIC_CDXA: return "RIFF data, CDXA";
+ case TC_MAGIC_AC3: return "AC3";
+ case TC_MAGIC_MP3: return "MP3";
+ case TC_MAGIC_MP2: return "MP2";
+ case TC_MAGIC_OGG: return "OGG stream";
+ case TC_MAGIC_WAV: return "RIFF data, WAVE";
+ case TC_MAGIC_V4L_VIDEO: return "V4L,video";
+ case TC_MAGIC_V4L_AUDIO: return "V4L,audio";
+ case TC_MAGIC_PVN: return "PVN video";
+ }
+ return "";
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/* Internal routines */
+
+/*************************************************************************/
+
+/**
+ * do_probe: Perform the actual probing of the source file.
+ *
+ * Parameters:
+ * file: Filename to probe.
+ * nav_seek_file: Navigation file for `file', or NULL if none.
+ * title: Title to probe for DVD probing.
+ * range: Amount of file to probe, in MB.
+ * mplayer_flag: If nonzero, use mplayer to probe file.
+ * verbose_flag: Verbosity flag to pass to tcprobe.
+ * info_ret: Structure to be filled in with probed data.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ * Preconditions:
+ * file != NULL
+ */
+
+static int do_probe(const char *file, const char *nav_seek_file, int title,
+ int range, int mplayer_flag, int verbose_flag,
+ ProbeInfo *info_ret)
+{
+ char cmdbuf[PATH_MAX+1000];
+ FILE *pipe;
+
+ if (mplayer_flag) {
+ if (tc_snprintf(cmdbuf, sizeof(cmdbuf),
+ "tcprobe -B -M -i \"%s\" -d %d",
+ file, verbose_flag) < 0)
+ return 0;
+ } else {
+ if (tc_snprintf(cmdbuf, sizeof(cmdbuf),
+ "tcprobe -B -i \"%s\" -T %d -H %d -d %d",
+ file, title, range, verbose_flag) < 0)
+ return 0;
+ if (nav_seek_file
+ && tc_snprintf(cmdbuf+strlen(cmdbuf), sizeof(cmdbuf)-strlen(cmdbuf),
+ " -f \"%s\"", nav_seek_file) < 0)
+ return 0;
+ }
+ pipe = popen(cmdbuf, "r");
+ if (!pipe)
+ return 0;
+ if (fread(&tc_probe_pid, sizeof(pid_t), 1, pipe) != 1) {
+ pclose(pipe);
+ return 0;
+ }
+ if (fread(info_ret, sizeof(*info_ret), 1, pipe) != 1) {
+ pclose(pipe);
+ return 0;
+ }
+ pclose(pipe);
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * probe_to_vob: Use the results of probing the input files to set global
+ * parameters.
+ *
+ * Parameters:
+ * vinfo: Pointer to probe results for video file, or NULL if no video
+ * file.
+ * ainfo: Pointer to probe results for audio file, or NULL if no audio
+ * file.
+ * flags: TC_PROBE_NO_xxx flags.
+ * vob: Pointer to global data structure.
+ * Return value:
+ * None.
+ * Preconditions:
+ * vob != NULL
+ */
+
+void probe_to_vob(ProbeInfo *vinfo, ProbeInfo *ainfo, int flags, vob_t *vob)
+{
+ int track; // user-selected audio track, sanity-checked
+
+ track = vob->a_track;
+ if (track < 0 || track >= TC_MAX_AUD_TRACKS)
+ track = 0;
+
+ if (vinfo) {
+ int D_arg, D_arg_ms; // for setting A/V sync
+
+ /* Set frame size */
+ if (MAY_SET(FRAMESIZE)) {
+ if (vinfo->width > 0)
+ vob->im_v_width = vinfo->width;
+ if (vinfo->height > 0)
+ vob->im_v_height = vinfo->height;
+ }
+
+ /* Set frame rate */
+ if (MAY_SET(FPS)) {
+ if (vinfo->frc > 0) {
+ vob->im_frc = vinfo->frc;
+ tc_frc_code_to_value(vob->im_frc, &vob->fps);
+ } else if (vinfo->fps > 0)
+ vob->fps = vinfo->fps;
+ }
+
+ /* Set aspect ratio */
+ if (MAY_SET(IMASR)) {
+ if (vinfo->asr > 0)
+ vob->im_asr = vinfo->asr;
+ }
+
+ /* Set additional attributes */
+ if (vinfo->attributes)
+ vob->attributes = vinfo->attributes;
+
+ /* Clear demux sync flag if appropriate */
+ if (MAY_SET(DEMUX) && (vob->attributes & TC_INFO_NO_DEMUX)) {
+ vob->demuxer = 0;
+ }
+
+ /* Calculate A/V sync correction */
+ if (vinfo->pts_start > 0 && vinfo->track[track].pts_start > 0) {
+ double pts_diff = vinfo->pts_start - vinfo->track[track].pts_start;
+ D_arg = (int)(vob->fps * pts_diff);
+ D_arg_ms = (int)((pts_diff - D_arg/vob->fps) * 1000);
+ } else {
+ D_arg = 0;
+ D_arg_ms = 0;
+ }
+ /* This voodoo to determine whether to set the A/V sync parameters
+ * is from the original probe.c, with the following comments:
+ * - case 1: demuxer disabled needs PTS sync mode
+ * - case 2: check if PTS of requested audio track requires
+ * video frame dropping
+ * vob->demuxer>0 and audio_pts > video_pts
+ * - case 3: fully PTS based sync modes requested
+ */
+ if ((MAY_SET(DEMUX) && (vob->attributes & TC_INFO_NO_DEMUX))
+ || (MAY_SET(DEMUX) && (vinfo->pts_start < vinfo->track[track].pts_start))
+ || (vob->demuxer == 3 || vob->demuxer == 4)
+ ) {
+ if (MAY_SET(AVSHIFT))
+ vob->sync = D_arg;
+ if (MAY_SET(AV_FINE))
+ vob->sync_ms = D_arg_ms;
+ }
+
+ /* Set starting presentation unit */
+ if (MAY_SET(SEEK)) {
+ if (vinfo->unit_cnt > 0)
+ vob->ps_unit = vinfo->unit_cnt;
+ }
+
+ /* Set format/codec flags and miscellaneous fields */
+ if (vinfo->magic)
+ vob->v_format_flag = vinfo->magic;
+ if (vinfo->codec)
+ vob->v_codec_flag = vinfo->codec;
+ vob->pts_start = vinfo->pts_start;
+
+ /* If the width or height are 0, assume no video was detected
+ * (FIXME: what about -g?) */
+ if (vinfo->width == 0 || vinfo->height == 0)
+ vob->has_video = 0;
+
+ /* If no separate audio file was found, use the video file for
+ * audio processing */
+ if (!ainfo)
+ ainfo = vinfo;
+
+ } // if (vinfo)
+
+ if (ainfo) {
+
+ /* Set audio format parameters */
+ if (MAY_SET(RATE)) {
+ if (ainfo->track[track].samplerate > 0)
+ vob->a_rate = ainfo->track[track].samplerate;
+ }
+ if (MAY_SET(BITS)) {
+ if (ainfo->track[track].bits > 0)
+ vob->a_bits = ainfo->track[track].bits;
+ }
+ if (MAY_SET(CHAN)) {
+ if (ainfo->track[track].chan > 0)
+ vob->a_chan = ainfo->track[track].chan;
+ }
+
+ /* Set audio codec, if not set by user */
+ if (MAY_SET(ACODEC)) {
+ if (ainfo->track[track].format > 0)
+ vob->a_codec_flag = ainfo->track[track].format;
+ }
+
+ /* Set format flag and miscellaneous fields */
+ if (ainfo->magic)
+ vob->a_format_flag = ainfo->magic;
+ if (ainfo->track[track].bitrate > 0)
+ vob->a_stream_bitrate = ainfo->track[track].bitrate;
+ if (ainfo->track[track].padrate > 0)
+ vob->a_padrate = ainfo->track[track].padrate;
+ if (ainfo->track[track].lang > 0)
+ vob->lang_code = ainfo->track[track].lang;
+
+ /* See if audio was detected */
+ if (ainfo->num_tracks == 0)
+ vob->has_audio = 0;
+ if (ainfo->track[track].format == CODEC_NULL)
+ vob->has_audio_track = 0;
+
+ /* Set video format/codec fields as well if no video present */
+ if (!vinfo) {
+ if (ainfo->magic)
+ vob->v_format_flag = ainfo->magic;
+ if (ainfo->codec)
+ vob->v_codec_flag = ainfo->codec;
+ }
+
+ } // if (ainfo)
+
+ /* Make note of whether the input is an XML file */
+ if (vinfo && vinfo->magic != vinfo->magic_xml)
+ vob->vmod_probed_xml = "xml";
+ else
+ vob->vmod_probed_xml = NULL;
+ if (ainfo && ainfo->magic != ainfo->magic_xml)
+ vob->amod_probed_xml = "xml";
+ else
+ vob->amod_probed_xml = NULL;
+
+ if (MAY_SET(MODULES)) {
+ /* Select appropriate import modules */
+ select_modules(flags, vob);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * select_modules: Use the results of probing the input files to set
+ * global parameters.
+ *
+ * Parameters:
+ * flags: TC_PROBE_NO_xxx flags.
+ * vob: Pointer to global data structure.
+ * Return value:
+ * None.
+ * Preconditions:
+ * vob != NULL
+ */
+
+static void select_modules(int flags, vob_t *vob)
+{
+ char *default_amod;
+
+
+ vob->vmod_probed = NULL;
+ vob->amod_probed = NULL;
+
+ /* If no video or audio, use null module */
+ if (!vob->has_video) {
+ vob->vmod_probed = "null";
+ vob->im_v_width = 0;
+ vob->im_v_height = 0;
+ }
+ if (!vob->has_audio) {
+ vob->amod_probed = "null";
+ vob->a_rate = 0;
+ vob->a_chan = 0;
+ }
+
+ /* Choose a default audio module based on the audio codec */
+ switch (vob->a_codec_flag) {
+ case CODEC_MP2: default_amod = "mp3"; break;
+ case CODEC_MP3: default_amod = "mp3"; break;
+ case CODEC_AC3: default_amod = "ac3"; break;
+ case CODEC_PCM: default_amod = "raw"; break;
+ case CODEC_VORBIS: default_amod = "ogg"; break;
+ case CODEC_VAG: default_amod = "vag"; break;
+ default: default_amod = "null"; break;
+ }
+
+ /* Choose modules based on file format */
+
+ switch (vob->v_format_flag) {
+
+ case TC_MAGIC_MPLAYER:
+ vob->vmod_probed = "mplayer";
+ vob->amod_probed = "mplayer";
+ break;
+
+ case TC_MAGIC_V4L_VIDEO:
+ vob->vmod_probed = "v4l";
+ if (MAY_SET(FRAMESIZE)) {
+ vob->im_v_width = PAL_W/2;
+ vob->im_v_height = PAL_H/2;
+ if (vob->im_v_codec != CODEC_RGB)
+ vob->im_v_width &= -16;
+ }
+ break;
+
+ case TC_MAGIC_V4L2_VIDEO:
+ vob->vmod_probed = "v4l2";
+ vob->amod_probed = "v4l2";
+ if (MAY_SET(FRAMESIZE)) {
+ vob->im_v_width = PAL_W/2;
+ vob->im_v_height = PAL_H/2;
+ if (vob->im_v_codec != CODEC_RGB)
+ vob->im_v_width &= -16;
+ }
+ break;
+
+ case TC_MAGIC_BKTR_VIDEO:
+ vob->vmod_probed = "bktr";
+ if (MAY_SET(FRAMESIZE) && !(vob->im_v_width>0 && vob->im_v_height>0)) {
+ vob->im_v_width = PAL_W/2;
+ vob->im_v_height = PAL_H/2;
+ if (vob->im_v_codec != CODEC_RGB)
+ vob->im_v_width &= -16;
+ }
+ break;
+
+ case TC_MAGIC_YUV4MPEG:
+ vob->vmod_probed = "yuv4mpeg";
+ break;
+
+ case TC_MAGIC_BSDAV:
+ vob->vmod_probed = "bsdav";
+ break;
+
+ case TC_MAGIC_NUV:
+ vob->vmod_probed = "nuv";
+ vob->amod_probed = "nuv";
+ break;
+
+ case TC_MAGIC_OGG:
+ vob->vmod_probed = "ogg";
+ vob->amod_probed = "ogg";
+
+ case TC_MAGIC_DVD_NTSC:
+ if (MAY_SET(DEMUX)) {
+ if (vob->demuxer < 0)
+ vob->demuxer = 1;
+ /* Activate special handling for 24fps video */
+ if (vob->fps < PAL_FPS && (vob->demuxer==1 || vob->demuxer==3))
+ vob->demuxer++;
+ }
+ /* Fall through to common DVD handling */
+ case TC_MAGIC_DVD_PAL:
+ vob->vmod_probed = "dvd";
+ vob->amod_probed = "dvd";
+ break;
+
+ case TC_MAGIC_AVI:
+ if (vob->pass_flag & TC_VIDEO)
+ vob->vmod_probed = "avi";
+ break;
+
+ case TC_MAGIC_MOV:
+ vob->vmod_probed = "mov";
+ break;
+
+ case TC_MAGIC_TS:
+ vob->vmod_probed = "ts";
+
+ case TC_MAGIC_TIFF1:
+ case TC_MAGIC_TIFF2:
+ case TC_MAGIC_JPEG:
+ case TC_MAGIC_PPM:
+ case TC_MAGIC_PGM:
+ case TC_MAGIC_BMP:
+ case TC_MAGIC_PNG:
+ case TC_MAGIC_GIF:
+ case TC_MAGIC_SGI:
+ vob->vmod_probed = "im";
+ break;
+
+ case TC_MAGIC_DV_NTSC:
+ case TC_MAGIC_DV_PAL:
+ if (vob->pass_flag & TC_VIDEO)
+ vob->vmod_probed = "dv";
+ break;
+
+ case TC_MAGIC_CDXA:
+ vob->vmod_probed = "vob";
+ vob->amod_probed = "vob";
+ break;
+
+ case TC_MAGIC_MP3:
+ vob->amod_probed = "mp3";
+ break;
+
+ case TC_MAGIC_AC3:
+ vob->amod_probed = "ac3";
+ break;
+
+ case TC_MAGIC_PV3:
+ vob->vmod_probed = "pv3";
+ vob->amod_probed = "pv3"; // really just BE raw after demuxing
+ break;
+
+ case TC_MAGIC_PVN:
+ vob->vmod_probed = "pvn";
+ break;
+
+ case TC_MAGIC_X11:
+ vob->vmod_probed = "x11";
+ break;
+
+ } // switch (vob->v_format_flag)
+
+ switch (vob->a_format_flag) {
+ case TC_MAGIC_V4L_AUDIO: vob->amod_probed = "v4l"; break;
+ case TC_MAGIC_V4L2_AUDIO: vob->amod_probed = "v4l2"; break;
+ case TC_MAGIC_SUNAU_AUDIO: vob->amod_probed = "sunau"; break;
+ case TC_MAGIC_BSDAV: vob->amod_probed = "bsdav"; break;
+ case TC_MAGIC_WAV: vob->amod_probed = "raw"; break;
+ case TC_MAGIC_MOV: vob->amod_probed = "mov"; break;
+ case TC_MAGIC_TS: vob->amod_probed = "ts"; break;
+ case TC_MAGIC_MP3: vob->amod_probed = "mp3"; break;
+ case TC_MAGIC_AC3: vob->amod_probed = "ac3"; break;
+ case TC_MAGIC_OSS_AUDIO:
+ if (!vob->amod_probed)
+ vob->amod_probed = "oss";
+ break;
+ case TC_MAGIC_AVI:
+ if (vob->pass_flag & TC_AUDIO)
+ vob->amod_probed = "avi";
+ break;
+ } // switch (vob->a_format_flag)
+
+ /* Choose modules based on codec */
+ switch (vob->v_codec_flag) {
+
+ case TC_CODEC_DV:
+ if (!vob->vmod_probed)
+ vob->vmod_probed = "dv";
+ if (!vob->amod_probed) {
+ if (vob->v_format_flag == TC_MAGIC_AVI)
+ vob->amod_probed = default_amod;
+ else
+ vob->amod_probed = "dv";
+ }
+ break;
+
+ case TC_CODEC_MPEG:
+ case TC_CODEC_M2V:
+ case TC_CODEC_MPEG1:
+ if (!vob->vmod_probed)
+ vob->vmod_probed = "mpeg2";
+ if (!vob->amod_probed)
+ vob->amod_probed = default_amod;
+ break;
+
+ case TC_CODEC_MPEG2:
+ if (!vob->vmod_probed) {
+ vob->vmod_probed = "vob";
+ if (MAY_SET(DEMUX)) {
+ if (vob->demuxer < 0)
+ vob->demuxer = 1;
+ /* Activate special handling for 24fps video */
+ if (vob->fps < PAL_FPS && (vob->demuxer==1 || vob->demuxer==3))
+ vob->demuxer++;
+ }
+ }
+ if (!vob->amod_probed)
+ vob->amod_probed = vob->has_audio ? "vob" : "null";
+ break;
+
+ case TC_CODEC_MJPEG:
+ case TC_CODEC_MPG1:
+ case TC_CODEC_MP42:
+ case TC_CODEC_MP43:
+ case TC_CODEC_RV10:
+ case TC_CODEC_ASV1:
+ case TC_CODEC_ASV2:
+ case TC_CODEC_FFV1:
+ case TC_CODEC_H264:
+ if (!vob->vmod_probed)
+ vob->vmod_probed = "ffmpeg";
+ if (!vob->amod_probed)
+ vob->amod_probed = default_amod;
+ break;
+
+ case TC_CODEC_LZO1:
+ case TC_CODEC_LZO2:
+ /* Overwrite video import module selected from format */
+ vob->vmod_probed = "lzo";
+ if (!vob->amod_probed)
+ vob->amod_probed = default_amod;
+ break;
+
+ case TC_CODEC_THEORA:
+ if (vob->v_format_flag != TC_MAGIC_OGG && !vob->vmod_probed)
+ vob->vmod_probed = "mplayer";
+ if (!vob->amod_probed)
+ vob->amod_probed = default_amod;
+ break;
+
+ case TC_CODEC_DIVX3:
+ case TC_CODEC_DIVX4:
+ case TC_CODEC_DIVX5:
+ case TC_CODEC_XVID:
+ if (vob->v_format_flag != TC_MAGIC_OGG && !vob->vmod_probed)
+ vob->vmod_probed = "ffmpeg";
+ if (!vob->amod_probed)
+ vob->amod_probed = default_amod;
+ break;
+
+ case TC_CODEC_YUV420P:
+ case TC_CODEC_YUV422P:
+ case TC_CODEC_RGB:
+ if (!vob->vmod_probed)
+ vob->vmod_probed = "raw";
+ if (!vob->amod_probed)
+ vob->amod_probed = default_amod;
+ break;
+
+ } // switch (vob->v_codec_flag)
+
+ /* If still not known, default to the null module */
+ if (!vob->vmod_probed)
+ vob->vmod_probed = "null";
+ if (!vob->amod_probed)
+ vob->amod_probed = "null";
+
+ /* Set XML import modules */
+ if (!vob->vmod_probed_xml)
+ vob->vmod_probed_xml = vob->vmod_probed;
+ if (!vob->amod_probed_xml)
+ vob->amod_probed_xml = vob->amod_probed;
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/probe.h b/debian/transcode/transcode-1.1.7/src/probe.h
new file mode 100644
index 00000000..9589aed3
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/probe.h
@@ -0,0 +1,124 @@
+/*
+ * probe.h - declarations for input file probing
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#ifndef PROBE_H
+#define PROBE_H
+
+/*************************************************************************/
+
+/* Structures to hold probed data */
+
+typedef struct {
+ int samplerate;
+ int chan;
+ int bits;
+ int bitrate;
+ int padrate; // Padding byterate
+ int format;
+ int lang;
+ int attribute; // 0=subtitle, 1=AC3, 2=PCM
+ int tid; // Logical track id, in case of gaps
+ double pts_start;
+} ProbeTrackInfo;
+
+
+typedef struct {
+
+ int width; // Frame width
+ int height; // Frame height
+
+ double fps; // Encoder fps
+
+ long codec; // Video codec
+ long magic; // File type/magic
+ long magic_xml; // Type/magic of content in XML file
+
+ int asr; // Aspect ratio code
+ int frc; // Frame cate code
+
+ int par_width; // Pixel aspect (== sample aspect ratio)
+ int par_height;
+
+ int attributes; // Video attributes
+
+ int num_tracks; // Number of audio tracks
+
+ ProbeTrackInfo track[TC_MAX_AUD_TRACKS];
+
+ long frames; // Total frames
+ long time; // Total time in secs
+
+ int unit_cnt; // Detected presentation units
+ double pts_start; // Video PTS start
+
+ long bitrate; // Video stream bitrate
+
+ int ext_attributes[4]; // Reserved for MPEG
+
+ int is_video; // NTSC flag
+
+} ProbeInfo;
+
+/*************************************************************************/
+
+/* External interface */
+int probe_source(const char *vid_file, const char *aud_file, int range,
+ int flags, vob_t *vob);
+int probe_source_xml(vob_t *vob, int which);
+
+int probe_stream_data(const char *file, int range, ProbeInfo *info);
+void probe_to_vob(ProbeInfo *vinfo, ProbeInfo *ainfo, int flags, vob_t *vob);
+
+/* Flags for probe_source(), indicating which parameters were specified by
+ * the user and shouldn't be overwritten */
+enum {
+ TC_PROBE_NO_FRAMESIZE = 1,
+ TC_PROBE_NO_FPS = 2,
+ TC_PROBE_NO_DEMUX = 4,
+ TC_PROBE_NO_RATE = 8,
+ TC_PROBE_NO_CHAN = 16,
+ TC_PROBE_NO_BITS = 32,
+ TC_PROBE_NO_SEEK = 64,
+ TC_PROBE_NO_TRACK = 128,
+ TC_PROBE_NO_BUFFER = 256,
+// TC_PROBE_NO_FRC = 512, // unused
+ TC_PROBE_NO_ACODEC = 1024,
+ TC_PROBE_NO_AVSHIFT = 2048,
+ TC_PROBE_NO_AV_FINE = 4096,
+ TC_PROBE_NO_IMASR = 8192,
+ TC_PROBE_NO_BUILTIN = 16384, // external probe (mplayer)
+ TC_PROBE_NO_MODULES = 32768,
+};
+
+/* `which' value for probe_xml() */
+enum {
+ PROBE_XML_VIDEO = 0,
+ PROBE_XML_AUDIO,
+};
+
+/* Auxiliary info routines */
+const char *mformat2str(int flag);
+
+/* info_server.c */
+void server_thread(vob_t *vob);
+
+/*************************************************************************/
+
+#endif // PROBE_H
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/socket.c b/debian/transcode/transcode-1.1.7/src/socket.c
new file mode 100644
index 00000000..5cf1d7e8
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/socket.c
@@ -0,0 +1,881 @@
+/* socket.c -- routines for controlling transcode over a socket
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "transcode.h"
+#include "encoder.h"
+#include "filter.h"
+#include "socket.h"
+#include "libtc/libtc.h"
+
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+/*************************************************************************/
+
+/* Pathname for listener socket */
+static char socket_path[PATH_MAX+1] = "";
+/* Socket descriptors for listener socket and client socket */
+static int server_sock = -1;
+static int client_sock = -1;
+
+/* For communicating with "pv" module (FIXME: should go away) */
+pthread_mutex_t tc_socket_msg_lock = PTHREAD_MUTEX_INITIALIZER;
+enum tc_socket_msg_cmd_enum tc_socket_msg_cmd;
+int tc_socket_msg_arg = 0;
+
+/*************************************************************************/
+/*************************************************************************/
+
+/**
+ * sendall: Send data to a client_sock, handling partial writes transparently.
+ *
+ * Parameters:
+ * sock: Socket descriptor.
+ * buf: Data to write.
+ * count: Number of bytes to send.
+ * Return value:
+ * Total number of bytes sent; -1 indicates that the send failed.
+ */
+
+static int sendall(int sock, const void *buf, size_t count)
+{
+ int total_sent = 0;
+
+ if (sock < 0 || !buf || count < 0) {
+ tc_log_warn(__FILE__, "sendall(): invalid parameters!");
+ errno = EINVAL;
+ return -1;
+ }
+ while (count > 0) {
+ int retval = send(sock, buf, count, 0);
+ if (retval <= 0) {
+ tc_log_warn(__FILE__, "sendall(): socket write failed (%s)",
+ retval<0 ? strerror(errno) : "Connection closed");
+ if (total_sent == 0)
+ return -1; /* Nothing sent yet, abort with error return */
+ break;
+ }
+ total_sent += retval;
+ buf = (int8_t *)buf + retval;
+ count -= retval;
+ }
+ return total_sent;
+}
+
+/*************************************************************************/
+
+/**
+ * sendstr: Send a string to a client_sock, handling partial writes transparently.
+ *
+ * Parameters:
+ * sock: Socket descriptor.
+ * str: String to write.
+ * Return value:
+ * Total number of bytes sent; -1 indicates that the send failed.
+ */
+
+static int sendstr(int sock, const char *str)
+{
+ return sendall(sock, str, strlen(str));
+}
+
+/*************************************************************************/
+
+/**
+ * dump_vob: Send the contents of the global `vob' structure over the
+ * socket in a "parameter=value" format, one field per line.
+ *
+ * Parameters:
+ * sock: Socket descriptor to send data to.
+ * Return value:
+ * None.
+ */
+
+static void dump_vob(int sock)
+{
+ vob_t *vob = tc_get_vob();
+ char buf[1000];
+ int n;
+
+#define SEND(field,fmt) \
+ n = tc_snprintf(buf, sizeof(buf), "%s=" fmt "\n", #field, vob->field); \
+ if (n > 0) \
+ sendall(sock, buf, n);
+
+ /* Generated via find-and-replace from vob_t definition in transcode.h */
+ SEND(vmod_probed, "%s");
+ SEND(amod_probed, "%s");
+ SEND(vmod_probed_xml, "%s");
+ SEND(amod_probed_xml, "%s");
+ SEND(verbose, "%d");
+ SEND(video_in_file, "%s");
+ SEND(audio_in_file, "%s");
+ SEND(nav_seek_file, "%s");
+ SEND(has_audio, "%d");
+ SEND(has_audio_track, "%d");
+ SEND(has_video, "%d");
+ SEND(lang_code, "%d");
+ SEND(a_track, "%d");
+ SEND(v_track, "%d");
+ SEND(s_track, "%d");
+ SEND(sync, "%d");
+ SEND(sync_ms, "%d");
+ SEND(dvd_title, "%d");
+ SEND(dvd_chapter1, "%d");
+ SEND(dvd_chapter2, "%d");
+ SEND(dvd_max_chapters, "%d");
+ SEND(dvd_angle, "%d");
+ SEND(ps_unit, "%d");
+ SEND(ps_seq1, "%d");
+ SEND(ps_seq2, "%d");
+ SEND(ts_pid1, "%d");
+ SEND(ts_pid2, "%d");
+ SEND(vob_offset, "%d");
+ SEND(vob_chunk, "%d");
+ SEND(vob_chunk_num1, "%d");
+ SEND(vob_chunk_num2, "%d");
+ SEND(vob_chunk_max, "%d");
+ SEND(vob_percentage, "%d");
+ SEND(vob_psu_num1, "%d");
+ SEND(vob_psu_num2, "%d");
+ SEND(vob_info_file, "%s");
+ SEND(pts_start, "%f");
+ SEND(psu_offset, "%f");
+ SEND(demuxer, "%d");
+ SEND(v_format_flag, "%ld");
+ SEND(v_codec_flag, "%ld");
+ SEND(a_format_flag, "%ld");
+ SEND(a_codec_flag, "%ld");
+ SEND(quality, "%d");
+ SEND(a_stream_bitrate, "%d");
+ SEND(a_chan, "%d");
+ SEND(a_bits, "%d");
+ SEND(a_rate, "%d");
+ SEND(a_padrate, "%d");
+ SEND(im_a_size, "%d");
+ SEND(ex_a_size, "%d");
+ SEND(im_a_codec, "%d");
+ SEND(a_leap_frame, "%d");
+ SEND(a_leap_bytes, "%d");
+ SEND(a_vbr, "%d");
+ SEND(a52_mode, "%d");
+ SEND(dm_bits, "%d");
+ SEND(dm_chan, "%d");
+ SEND(v_stream_bitrate, "%d");
+ SEND(fps, "%f");
+ SEND(im_frc, "%d");
+ SEND(ex_fps, "%f");
+ SEND(ex_frc, "%d");
+ SEND(hard_fps_flag, "%d");
+ SEND(pulldown, "%d");
+ SEND(im_v_height, "%d");
+ SEND(im_v_width, "%d");
+ SEND(im_v_size, "%d");
+ SEND(im_asr, "%d");
+ SEND(im_par, "%d");
+ SEND(im_par_width, "%d");
+ SEND(im_par_height, "%d");
+ SEND(ex_asr, "%d");
+ SEND(ex_par, "%d");
+ SEND(ex_par_width, "%d");
+ SEND(ex_par_height, "%d");
+ SEND(attributes, "%d");
+ SEND(im_v_codec, "%d");
+ SEND(encode_fields, "%d");
+ SEND(dv_yuy2_mode, "%d");
+ SEND(volume, "%f");
+ SEND(ac3_gain[0], "%f");
+ SEND(ac3_gain[1], "%f");
+ SEND(ac3_gain[2], "%f");
+ SEND(clip_count, "%d");
+ SEND(ex_v_width, "%d");
+ SEND(ex_v_height, "%d");
+ SEND(ex_v_size, "%d");
+ SEND(reduce_h, "%d");
+ SEND(reduce_w, "%d");
+ SEND(resize1_mult, "%d");
+ SEND(vert_resize1, "%d");
+ SEND(hori_resize1, "%d");
+ SEND(resize2_mult, "%d");
+ SEND(vert_resize2, "%d");
+ SEND(hori_resize2, "%d");
+ SEND(zoom_width, "%d");
+ SEND(zoom_height, "%d");
+ SEND(zoom_interlaced, "%d");
+ SEND(zoom_filter, "%d");
+ SEND(antialias, "%d");
+ SEND(deinterlace, "%d");
+ SEND(decolor, "%d");
+ SEND(aa_weight, "%f");
+ SEND(aa_bias, "%f");
+ SEND(gamma, "%f");
+ SEND(ex_clip_top, "%d");
+ SEND(ex_clip_bottom, "%d");
+ SEND(ex_clip_left, "%d");
+ SEND(ex_clip_right, "%d");
+ SEND(im_clip_top, "%d");
+ SEND(im_clip_bottom, "%d");
+ SEND(im_clip_left, "%d");
+ SEND(im_clip_right, "%d");
+ SEND(post_ex_clip_top, "%d");
+ SEND(post_ex_clip_bottom, "%d");
+ SEND(post_ex_clip_left, "%d");
+ SEND(post_ex_clip_right, "%d");
+ SEND(pre_im_clip_top, "%d");
+ SEND(pre_im_clip_bottom, "%d");
+ SEND(pre_im_clip_left, "%d");
+ SEND(pre_im_clip_right, "%d");
+ SEND(video_out_file, "%s");
+ SEND(audio_out_file, "%s");
+ SEND(avifile_in, "%p"); // not sure if there's any point sending these...
+ SEND(avifile_out, "%p");
+ SEND(avi_comment_fd, "%d");
+ SEND(audio_file_flag, "%d");
+ SEND(divxbitrate, "%d");
+ SEND(divxkeyframes, "%d");
+ SEND(divxquality, "%d");
+ SEND(divxcrispness, "%d");
+ SEND(divxmultipass, "%d");
+ SEND(video_max_bitrate, "%d");
+ SEND(divxlogfile, "%s");
+ SEND(min_quantizer, "%d");
+ SEND(max_quantizer, "%d");
+ SEND(rc_period, "%d");
+ SEND(rc_reaction_period, "%d");
+ SEND(rc_reaction_ratio, "%d");
+ SEND(divx5_vbv_prof, "%d");
+ SEND(divx5_vbv_bitrate, "%d");
+ SEND(divx5_vbv_size, "%d");
+ SEND(divx5_vbv_occupancy, "%d");
+ SEND(mp3bitrate, "%d");
+ SEND(mp3frequency, "%d");
+ SEND(mp3quality, "%f");
+ SEND(mp3mode, "%d");
+ SEND(bitreservoir, "%d");
+ SEND(lame_preset, "%s");
+ SEND(audiologfile, "%s");
+ SEND(ex_a_codec, "%d");
+ SEND(ex_v_codec, "%d");
+ SEND(ex_v_fcc, "%s");
+ SEND(ex_a_fcc, "%s");
+ SEND(ex_profile_name, "%s");
+ SEND(pass_flag, "%d");
+ SEND(encoder_flush, "%d");
+ SEND(mod_path, "%s");
+ SEND(ttime, "%p"); // format this as a -c style string?
+ SEND(frame_interval, "%u");
+ SEND(im_v_string, "%s");
+ SEND(im_a_string, "%s");
+ SEND(ex_v_string, "%s");
+ SEND(ex_a_string, "%s");
+ SEND(ex_m_string, "%s");
+ SEND(m2v_requant, "%f");
+ SEND(mpeg_profile, "%d");
+ SEND(export_attributes, "%u");
+
+#undef SEND
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/* Socket actions. */
+
+/*************************************************************************/
+
+/**
+ * handle_config(): Process a "config" command received on the socket.
+ *
+ * Parameters:
+ * params: Command parameters.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ */
+
+static int handle_config(char *params)
+{
+ char *filter_name, *filter_params;
+ int filter_id;
+
+ filter_name = params;
+ filter_params = filter_name + strcspn(filter_name, " \t");
+ *filter_params++ = 0;
+ filter_params += strspn(filter_params, " \t");
+ if (!*filter_name || !*filter_params)
+ return 0;
+
+ filter_id = tc_filter_find(filter_name);
+ if (!filter_id)
+ return 0;
+ else
+ return tc_filter_configure(filter_id, filter_params) == 0;
+}
+
+/*************************************************************************/
+
+/**
+ * handle_disable(): Process a "disable" command received on the socket.
+ *
+ * Parameters:
+ * params: Command parameters.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ */
+
+static int handle_disable(char *params)
+{
+ int filter_id;
+
+ filter_id = tc_filter_find(params);
+ if (!filter_id)
+ return 0;
+ else
+ return tc_filter_disable(filter_id);
+}
+
+/*************************************************************************/
+
+/**
+ * handle_enable(): Process an "enable" command received on the socket.
+ *
+ * Parameters:
+ * params: Command parameters.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ */
+
+static int handle_enable(char *params)
+{
+ int filter_id;
+
+ filter_id = tc_filter_find(params);
+ if (!filter_id)
+ return 0;
+ else
+ return tc_filter_enable(filter_id);
+}
+
+/*************************************************************************/
+
+/**
+ * handle_help(): Process a "help" command received on the socket.
+ *
+ * Parameters:
+ * params: Command parameters.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ */
+
+static int handle_help(char *params)
+{
+ sendstr(client_sock,
+ "load <filter> <initial string>\n"
+ "unload <filter>\n"
+ "enable <filter>\n"
+ "disable <filter>\n"
+ "config <filter> <string>\n"
+ "parameters <filter>\n"
+ "list [ load | enable | disable ]\n"
+ "dump\n"
+ "progress\n"
+ "pause\n"
+ "preview <command>\n"
+ " [ draw | undo | pause | fastfw |\n"
+ " slowfw | slowbw | rotate |\n"
+ " rotate | display | slower |\n"
+ " faster | toggle | grab ]\n"
+ "help\n"
+ "version\n"
+ "quit\n"
+ );
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * handle_list(): Process a "list" command received on the socket.
+ *
+ * Parameters:
+ * params: Command parameters.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ */
+
+static int handle_list(char *params)
+{
+ const char *list = NULL;
+
+ if (strncasecmp(params, "load", 2) == 0)
+ list = tc_filter_list(TC_FILTER_LIST_LOADED);
+ else if (strncasecmp(params, "enable", 2) == 0)
+ list = tc_filter_list(TC_FILTER_LIST_ENABLED);
+ else if (strncasecmp(params, "disable", 2) == 0)
+ list = tc_filter_list(TC_FILTER_LIST_DISABLED);
+
+ if (list) {
+ sendstr(client_sock, list);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * handle_load(): Process a "load" command received on the socket.
+ *
+ * Parameters:
+ * params: Command parameters.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ */
+
+static int handle_load(char *params)
+{
+ char *name, *options;
+
+ name = params;
+ options = strchr(params, ' ');
+ if (options) {
+ *options++ = 0;
+ options += strspn(options, " \t");
+ }
+ return tc_filter_add(name, options);
+}
+
+/*************************************************************************/
+
+/**
+ * handle_parameter(): Process a "parameter" command received on the
+ * socket.
+ *
+ * Parameters:
+ * params: Command parameters.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ */
+
+static int handle_parameter(char *params)
+{
+ int filter_id;
+ const char *s;
+
+ filter_id = tc_filter_find(params);
+ if (!filter_id)
+ return 0;
+ s = tc_filter_get_conf(filter_id, NULL);
+ if (!s)
+ return 0;
+ sendstr(client_sock, s);
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * handle_preview(): Process a "preview" command received on the socket.
+ *
+ * Parameters:
+ * params: Command parameters.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ */
+
+static int handle_preview(char *params)
+{
+ int filter_id, cmd, arg;
+ char *cmdstr, *argstr;
+
+ /* Check that the preview filter is loaded, and load it if not */
+ filter_id = tc_filter_find("pv");
+ if (!filter_id) {
+ filter_id = tc_filter_add("pv", "cache=20");
+ if (!filter_id)
+ return 0;
+ }
+
+ /* Parse out preview command name and (optional) argument */
+ cmdstr = strtok(params, " \t");
+ if (cmdstr) // there are strtok() implementations that crash without this!
+ argstr = strtok(NULL, " \t");
+ else
+ argstr = NULL;
+ if (argstr)
+ arg = atoi(argstr);
+ else
+ arg = 0;
+
+ if (!strncasecmp(cmdstr, "draw", 2)) {
+ cmd = TC_SOCK_PV_DRAW;
+ } else if (!strncasecmp(cmdstr, "pause", 2)) {
+ cmd = TC_SOCK_PV_PAUSE;
+ } else if (!strncasecmp(cmdstr, "undo", 2)) {
+ cmd = TC_SOCK_PV_UNDO;
+ } else if (!strncasecmp(cmdstr, "fastfw", 6)) {
+ cmd = TC_SOCK_PV_FAST_FW;
+ } else if (!strncasecmp(cmdstr, "fastbw", 6)) {
+ cmd = TC_SOCK_PV_FAST_BW;
+ } else if (!strncasecmp(cmdstr, "slowfw", 6)) {
+ cmd = TC_SOCK_PV_SLOW_FW;
+ } else if (!strncasecmp(cmdstr, "slowbw", 6)) {
+ cmd = TC_SOCK_PV_SLOW_BW;
+ } else if (!strncasecmp(cmdstr, "toggle", 6)) {
+ cmd = TC_SOCK_PV_TOGGLE;
+ } else if (!strncasecmp(cmdstr, "slower", 6)) {
+ cmd = TC_SOCK_PV_SLOWER;
+ } else if (!strncasecmp(cmdstr, "faster", 6)) {
+ cmd = TC_SOCK_PV_FASTER;
+ } else if (!strncasecmp(cmdstr, "rotate", 6)) {
+ cmd = TC_SOCK_PV_ROTATE;
+ } else if (!strncasecmp(cmdstr, "display", 6)) {
+ cmd = TC_SOCK_PV_DISPLAY;
+ } else if (!strncasecmp(cmdstr, "grab", 4)) {
+ cmd = TC_SOCK_PV_SAVE_JPG;
+ } else {
+ return 0;
+ }
+
+ pthread_mutex_lock(&tc_socket_msg_lock);
+ tc_socket_msg_cmd = cmd;
+ tc_socket_msg_arg = arg;
+ pthread_mutex_unlock(&tc_socket_msg_lock);
+
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * handle: Handle a single message from a socket.
+ *
+ * Parameters:
+ * buf: Line read from socket.
+ * Return value:
+ * Zero if the socket is to be closed, nonzero otherwise.
+ */
+
+static int handle(char *buf)
+{
+ char *cmd, *params;
+ int len, retval;
+
+ len = strlen(buf);
+ if (len > 0 && buf[len-1] == '\n')
+ buf[--len] = 0;
+ if (len > 0 && buf[len-1] == '\r')
+ buf[--len] = 0;
+ //tc_log_msg(__FILE__, "read from socket: |%s|", buf);
+
+ cmd = buf + strspn(buf, " \t");
+ params = cmd + strcspn(cmd, " \t");
+ *params++ = 0;
+ params += strspn(params, " \t");
+
+ if (!*cmd) { // not strictly necessary, but lines up else if's nicely
+ retval = 0;
+ } else if (strncasecmp(cmd, "config", 2) == 0) {
+ retval = handle_config(params);
+ } else if (strncasecmp(cmd, "disable", 2) == 0) {
+ retval = handle_disable(params);
+ } else if (strncasecmp(cmd, "dump", 2) == 0) {
+ dump_vob(client_sock);
+ retval = 1;
+ } else if (strncasecmp(cmd, "enable", 2) == 0) {
+ retval = handle_enable(params);
+ } else if (strncasecmp(cmd, "help", 2) == 0) {
+ retval = handle_help(params);
+ } else if (strncasecmp(cmd, "list", 2) == 0) {
+ retval = handle_list(params);
+ } else if (strncasecmp(cmd, "load", 2) == 0) {
+ retval = handle_load(params);
+ } else if (strncasecmp(cmd, "parameters", 3) == 0) {
+ retval = handle_parameter(params);
+ } else if (strncasecmp(cmd, "pause", 3) == 0) {
+ tc_pause_request();
+ retval = 1;
+ } else if (strncasecmp(cmd, "preview", 3) == 0) {
+ retval = handle_preview(params);
+ } else if (strncasecmp(cmd, "progress", 3) == 0) {
+ tc_progress_meter = !tc_progress_meter;
+ retval = 1;
+ } else if (strncasecmp(cmd, "quit", 2) == 0
+ || strncasecmp(cmd, "exit", 2) == 0) {
+ return 0; // tell caller to close socket
+ } else if (strncasecmp(cmd, "unload", 2) == 0) {
+ retval = 0; // FIXME: not implemented
+ } else if (strncasecmp(cmd, "version", 2) == 0) {
+ sendstr(client_sock, PACKAGE_VERSION "\n");
+ retval = 1;
+ } else {
+ retval = 0;
+ }
+
+ sendstr(client_sock, retval ? "OK\n" : "FAILED\n");
+ return 1; // socket remains open
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/* External interfaces. */
+
+/*************************************************************************/
+
+/**
+ * tc_socket_init: Initialize the socket code, and open a listener socket
+ * with the given pathname.
+ *
+ * Parameters:
+ * socket_path_: Pathname to use for communication socket.
+ * Return value:
+ * Nonzero on success, zero on failure.
+ * Side effects:
+ * If `socket_path' points to an existing file, the file is removed.
+ */
+
+int tc_socket_init(const char *socket_path_)
+{
+ struct sockaddr_un server_addr;
+
+ client_sock = -1;
+ server_sock = -1;
+
+ if (tc_snprintf(socket_path, sizeof(socket_path), "%s", socket_path_) < 0){
+ tc_log_error(__FILE__, "Socket pathname too long (1)");
+ *socket_path = 0;
+ return 0;
+ }
+
+ errno = 0;
+ if (unlink(socket_path) != 0 && errno != ENOENT) {
+ tc_log_error(__FILE__, "Unable to remove \"%s\": %s",
+ socket_path, strerror(errno));
+ return 0;
+ }
+
+ server_addr.sun_family = AF_UNIX;
+ if (tc_snprintf(server_addr.sun_path, sizeof(server_addr.sun_path),
+ "%s", socket_path) < 0
+ ) {
+ tc_log_error(__FILE__, "Socket pathname too long");
+ return 0;
+ }
+ server_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (server_sock < 0) {
+ tc_log_perror(__FILE__, "Unable to create server socket");
+ return 0;
+ }
+ if (bind(server_sock, (struct sockaddr *)&server_addr,
+ sizeof(server_addr))
+ ) {
+ tc_log_perror(__FILE__, "Unable to bind server socket");
+ close(server_sock);
+ server_sock = -1;
+ unlink(socket_path); // just in case
+ return 0;
+ }
+ if (listen(server_sock, 5) < 0) {
+ tc_log_perror(__FILE__, "Unable to activate server socket");
+ close(server_sock);
+ unlink(socket_path);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * tc_socket_fini: Close the listener and client sockets, if open, and
+ * perform any other necessary cleanup.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+void tc_socket_fini(void)
+{
+ if (client_sock >= 0) {
+ close(client_sock);
+ client_sock = -1;
+ }
+ if (server_sock >= 0) {
+ close(server_sock);
+ server_sock = -1;
+ unlink(socket_path);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * tc_socket_poll_internal: Check server and (if connected) client sockets for
+ * pending events, and process them, with tunable timeout.
+ *
+ * Parameters:
+ * blocking: if !0, blocks forever caller until next event.
+ * if 0, just check once if there is an event to process
+ * and execute (or just return) immediately.
+ * Return value:
+ * None.
+ * Preconditions:
+ * valid (!= -1) server socket avalaible.
+ */
+
+static void tc_socket_poll_internal(int blocking)
+{
+ fd_set rfds, wfds;
+ char msgbuf[TC_BUF_MAX];
+ int maxfd = -1, retval = -1;
+ struct timeval tv = {0, 0}, *ptv = (blocking) ?NULL :&tv;
+
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+
+ FD_SET(server_sock, &rfds);
+ maxfd = server_sock;
+
+ if (client_sock >= 0) {
+ FD_SET(client_sock, &rfds);
+ //FD_SET(client_sock, &wfds);
+ if (client_sock > maxfd)
+ maxfd = client_sock;
+ }
+ retval = select(maxfd+1, &rfds, &wfds, NULL, ptv);
+
+ if (retval == 0) {
+ /* nothing interesting happened. It happens :) */
+ return;
+ }
+ if (retval < 0 && errno != EINTR) {
+ /* EINTR is an expected "exceptional" condition */
+ tc_log_warn(__FILE__, "select(): %s", strerror(errno));
+ return;
+ }
+
+ if (FD_ISSET(server_sock, &rfds)) {
+ int newsock = accept(server_sock, NULL, 0);
+ if (newsock < 0) {
+ tc_log_warn(__FILE__, "Unable to accept new connection: %s",
+ strerror(errno));
+ return;
+ }
+ if (client_sock >= 0) {
+ /* We already have a connection, so drop this one */
+ close(newsock);
+ } else {
+ client_sock = newsock;
+ }
+ }
+
+ if (client_sock >= 0 && FD_ISSET(client_sock, &rfds)) {
+ retval = recv(client_sock, msgbuf, sizeof(msgbuf)-1, 0);
+ if (retval <= 0) {
+ if (retval < 0)
+ tc_log_perror(__FILE__, "Unable to read message from socket");
+ close(client_sock);
+ client_sock = -1;
+ } else {
+ if (retval > sizeof(msgbuf)-1) // paranoia
+ retval = sizeof(msgbuf)-1;
+ msgbuf[retval] = 0;
+ if (!handle(msgbuf)) {
+ close(client_sock);
+ client_sock = -1;
+ }
+ }
+ }
+}
+
+/**
+ * tc_socket_poll: Check server and (if connected) client sockets for
+ * pending events, and process them.
+ * This call should never block caller, returnin immediately if there
+ * isn't any event pending.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+void tc_socket_poll(void)
+{
+ if (server_sock < 0 && client_sock < 0) {
+ /* Nothing to poll! */
+ return;
+ }
+ tc_socket_poll_internal(0);
+}
+
+/**
+ * tc_socket_wait: Wait forever server and (if connected) client sockets
+ * for next event, and process the next first one and exit.
+ * This call will always block until next event happens.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+void tc_socket_wait(void)
+{
+ if (server_sock < 0 && client_sock < 0) {
+ pause();
+ /* if no server socket is avalaible (= no tc_socket_init
+ * called before), nothing will ever happen, so
+ * we must block forever to satisfy function requirements.
+ */
+ return;
+ }
+ tc_socket_poll_internal(1);
+}
+
+
+/*************************************************************************/
+
+/**
+ * tc_socket_submit: Send a string to the socket. Does nothing if no
+ * socket is open.
+ *
+ * Parameters:
+ * str: String to send.
+ * Return value:
+ * None.
+ */
+
+void tc_socket_submit(const char *str)
+{
+ if (socket >= 0)
+ sendstr(client_sock, str);
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/socket.h b/debian/transcode/transcode-1.1.7/src/socket.h
new file mode 100644
index 00000000..e96e3b02
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/socket.h
@@ -0,0 +1,59 @@
+/* socket.h -- include file for control socket routines
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#ifndef SOCKET_H
+#define SOCKET_H
+
+#include <pthread.h>
+
+/*************************************************************************/
+
+/* External interface. */
+int tc_socket_init(const char *socket_path);
+void tc_socket_fini(void);
+void tc_socket_poll(void);
+void tc_socket_wait(void);
+void tc_socket_submit(const char *str);
+
+/* Variables and constants for communicating with the "pv" module
+ * (FIXME: these should go away) */
+extern pthread_mutex_t tc_socket_msg_lock;
+extern int tc_socket_msg_arg;
+enum tc_socket_msg_cmd_enum {
+ TC_SOCK_PV_NONE = 0,
+ TC_SOCK_PV_PAUSE,
+ TC_SOCK_PV_DRAW,
+ TC_SOCK_PV_UNDO,
+ TC_SOCK_PV_SLOW_FW,
+ TC_SOCK_PV_SLOW_BW,
+ TC_SOCK_PV_FAST_FW,
+ TC_SOCK_PV_FAST_BW,
+ TC_SOCK_PV_SLOWER,
+ TC_SOCK_PV_FASTER,
+ TC_SOCK_PV_TOGGLE,
+ TC_SOCK_PV_ROTATE,
+ TC_SOCK_PV_DISPLAY,
+ TC_SOCK_PV_SAVE_JPG,
+};
+extern enum tc_socket_msg_cmd_enum tc_socket_msg_cmd;
+
+
+/*************************************************************************/
+
+#endif /* SOCKET_H */
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/split.c b/debian/transcode/transcode-1.1.7/src/split.c
new file mode 100644
index 00000000..9d5b1a8b
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/split.c
@@ -0,0 +1,319 @@
+/*
+ * split.c
+ *
+ * Copyright (C) Thomas Oestreich - January 2002
+ *
+ * This file is part of transcode, a 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 "transcode.h"
+#include "split.h"
+
+#define PMAX_BUF 1024
+char split_cmd_buf[PMAX_BUF];
+
+static int entries;
+
+typedef struct seq_s {
+
+ int unit;
+ long frame;
+ int seq;
+ int pseq;
+ long offset;
+ int foffset;
+} seq_t;
+
+static seq_t **seq=NULL;
+
+#define MAX_UNITS 128
+
+static long uframe[MAX_UNITS];
+static long unit_offset[MAX_UNITS];
+
+#define debug_return {return(-1);}
+
+static int split_stream_core(const char *file, const char *source)
+{
+
+ FILE *fd;
+ FILE *tmp;
+ char buffer[256];
+
+ int n=-1;
+
+ if(file == NULL) {
+
+ if(tc_snprintf(split_cmd_buf, PMAX_BUF, "tccat -i %s | tcdemux -W 2>/dev/null", source)<0) debug_return;
+ // popen
+ if((fd = popen(split_cmd_buf, "r"))== NULL) debug_return;
+
+ tc_log_info(__FILE__, "generating auto-split information from file \"%s\"", source);
+
+ // open temp. file
+ tmp = tmpfile();
+
+ while ( fgets (buffer, 256, fd) ) {
+ ++n;
+ if ( fputs (buffer, tmp) < 0 ) debug_return;
+ }
+
+ pclose(fd);
+ fd = tmp;
+
+ } else {
+
+ if((fd = fopen(file, "r"))==NULL) debug_return;
+
+ tc_log_info(__FILE__, "reading auto-split information from file \"%s\"", file);
+
+ // determine number of lines
+
+ while (fgets (buffer, 256, fd)) { ++n; }
+ }
+
+ // need n+2 pointers????
+ seq = (seq_t **) malloc( (n+2) * sizeof(seq_t*));
+ if ( seq == NULL ) debug_return;
+
+ n=-1;
+ fseek (fd, 0, SEEK_SET);
+
+ do {
+ ++n;
+
+ if((seq[n] = (seq_t *) malloc(sizeof(seq_t))) == NULL) debug_return;
+
+ } while((fscanf(fd, "%d %ld %d %d %ld %d", &seq[n]->unit, &seq[n]->frame, &seq[n]->seq, &seq[n]->pseq, &seq[n]->offset, &seq[n]->foffset)!=EOF));
+
+ entries=n;
+
+ if(seq[n]!=NULL) seq[n] = (seq_t *) malloc(sizeof(seq_t));
+
+ //add fake closing entry
+ seq[n]->unit=seq[n-1]->unit+1;
+ seq[n]->frame=seq[n-1]->frame=0;
+ seq[n]->seq=seq[n-1]->seq+1;
+
+ fclose(fd);
+
+ return(0);
+}
+
+
+static long get_frame_index(int unit, long frame_inc)
+{
+ //first entry is unique
+
+ long n;
+ int m;
+
+ if(frame_inc==0) return(unit_offset[unit]);
+
+ n=unit_offset[unit] + frame_inc;
+ m=seq[n]->seq;
+
+ while(seq[n]->unit == unit && n < entries && seq[n]->seq == m ) ++n;
+
+ return(n);
+}
+
+//----------------------------------------------
+//
+// main routine
+//
+//----------------------------------------------
+
+
+int split_stream(vob_t *vob, const char *file, int this_unit, int *fa, int *fb, int opt_flag)
+{
+
+ int n, unit_ctr=-1, last_unit=-1;
+
+ int s1, s2, video=1;
+
+ long max_frames=-1;
+ int unit=0, foff=0;
+
+ long _fa, _fb;
+
+ long _n, frame_inc=0, poff=0;
+
+ int startc, chunks;
+
+ if(split_stream_core(file, ((vob->vob_chunk == vob->vob_chunk_max) ? vob->audio_in_file:vob->video_in_file))<0) {
+ tc_log_error(__FILE__, "failed to read VOB navigation file %s", file);
+ return(-1);
+ }
+
+ tc_log_info(__FILE__, "done reading %d entries", entries);
+
+ //analyze data:
+
+ for(n=0; n<MAX_UNITS; ++n) uframe[n]=0;
+
+ // (I) determine presentation units and number of frames
+
+ for(n=0; n<entries; ++n) {
+
+ if(last_unit != seq[n]->unit) {
+ last_unit=seq[n]->unit;
+ ++unit_ctr;
+ unit_offset[unit_ctr]=n;
+ }
+
+ ++uframe[unit_ctr];
+ }
+
+ for(n=0; n<=unit_ctr; ++n) {
+ if(max_frames<=uframe[n]) {
+ unit = n;
+ max_frames = uframe[n];
+ }
+
+ if(this_unit > unit_ctr) {
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "invalid PSU %s", file);
+ return(-1);
+ }
+
+ if(-1 < this_unit) unit = this_unit;
+
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "unit=%d, frames=%ld, offset=%ld (%d)", n, uframe[n], unit_offset[n], vob->ps_unit);
+ }
+
+ // (II) determine largest (main) presentation unit
+
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "selecting unit %d, frames=%ld, offset=%ld", unit, uframe[unit], unit_offset[unit]);
+
+
+ // video or audio mode ?
+
+ if((vob->vob_percentage) ? (vob->vob_chunk==vob->vob_chunk_max && vob->vob_chunk_max==100 ) : (vob->vob_chunk == vob->vob_chunk_max)) video=0;
+
+ //check user error
+ if(vob->vob_chunk_num2>vob->vob_chunk_max) vob->vob_chunk_num2=vob->vob_chunk_max;
+ if(vob->vob_chunk_num1>vob->vob_chunk_max) vob->vob_chunk_num1=0;
+
+ // determine number of chunks to process: (0.6.0pre5)
+
+ if(video) {
+ chunks = (vob->vob_percentage || vob->vob_chunk_num2==0) ? 1:vob->vob_chunk_num2-vob->vob_chunk_num1;
+ startc = (vob->vob_percentage || vob->vob_chunk_num2==0) ? vob->vob_chunk:vob->vob_chunk_num1;
+ } else {
+ chunks = (vob->vob_percentage || vob->vob_chunk_num2==0) ? vob->vob_chunk_max:vob->vob_chunk_num2-vob->vob_chunk_num1;
+ startc = (vob->vob_percentage || vob->vob_chunk_num2==0) ? 0:vob->vob_chunk_num1;
+ }
+
+ //---------------------------------------------------------------------
+
+ // (III) determine pack offset for given number of VOB chunks
+ // Modified by CARON Dominique <domi@lpm.univ-monp2.fr> to optimize the
+ // cluster mode
+ // vob->vob_chunk = percentage of frames to skip before frames to encode
+ // vob->vob_chunk_max = percentage of frames to encode
+
+
+ frame_inc = (vob->vob_percentage) ? (long) ((startc * uframe[unit])/100) : (long) ((startc * uframe[unit])/vob->vob_chunk_max);
+
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "estimated chunk offset = %ld", frame_inc);
+
+ _n = get_frame_index(unit, frame_inc);
+
+ poff = seq[_n]->offset;
+ foff = seq[_n]->foffset;
+
+ _fa = seq[_n]->frame;
+
+ // parameter for option "-c"
+ *fa = foff;
+ *fb = foff - seq[_n]->frame;
+
+ s1 = seq[_n]->seq;
+
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "chunk %d starts at frame %ld, pack offset %ld, finc=%d", startc, _n, poff, foff);
+
+
+ // (IV) determine end of chunk(s)
+ // Modified by CARON Dominique <domi@lpm.univ-monp2.fr> to optimize the
+ // cluster mode
+
+ frame_inc = (vob->vob_percentage) ? (long) (((vob->vob_chunk+vob->vob_chunk_max) * uframe[unit])/100) : (long) (((startc+chunks) * uframe[unit])/vob->vob_chunk_max);
+
+ _n = get_frame_index(unit, frame_inc);
+
+ _fb = seq[_n]->frame;
+
+ s2 = seq[_n]->seq;
+
+ if(_fb==0) {
+ _fb = uframe[unit];
+ *fb += uframe[unit];
+ } else {
+ *fb += seq[_n]->frame;
+ }
+
+ // (V) set vob parameter
+
+ vob->vob_offset = poff;
+ vob->ps_unit = 0;
+
+ vob->ps_seq1 = 0;
+ vob->ps_seq2 = (s2==0 && _n) ? seq[_n-1]->seq-s1+3 : s2-s1+2;
+
+ tc_log_msg(__FILE__, "chunk %d/%d PU=%d (-L 0 -c %ld-%ld) mapped onto (-L %ld -c %d-%d)", vob->vob_chunk, vob->vob_chunk_max-1, unit, _fa, _fb, poff, *fa, *fb);
+
+
+ //---------------------------------------------------------------------
+
+ if(opt_flag==1) { //cluster mode
+
+ if(video) {
+
+ // no sound
+ vob->amod_probed="null";
+ vob->has_audio=0;
+
+ tc_log_info(__FILE__, "video mode");
+
+ } else {
+
+ // no video
+ vob->vmod_probed="null";
+ vob->has_video=0;
+
+ vob->vob_offset = poff;
+ vob->ps_unit = 0;
+
+ tc_log_info(__FILE__, "audio mode");
+ }
+ }
+
+ //---------------------------------------------------------------------
+
+ if(seq != NULL) {
+
+ // seq array not needed anymore
+ for (n=0; n < entries+1; ++n) {
+ free(seq[n]);
+ }
+
+ free(seq);
+ }
+
+ return(0);
+}
diff --git a/debian/transcode/transcode-1.1.7/src/split.h b/debian/transcode/transcode-1.1.7/src/split.h
new file mode 100644
index 00000000..f0eae0ce
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/split.h
@@ -0,0 +1,29 @@
+/*
+ * split.h
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifndef _SPLIT_H
+#define _SPLIT_H
+
+int split_stream(vob_t *vob, const char *file, int unit, int *fa, int *fb, int opt_flag);
+
+#endif
diff --git a/debian/transcode/transcode-1.1.7/src/tc_defaults.h b/debian/transcode/transcode-1.1.7/src/tc_defaults.h
new file mode 100644
index 00000000..801aeae5
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/tc_defaults.h
@@ -0,0 +1,226 @@
+/*
+ * tc_defaults.h
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+
+#ifndef TC_DEFAULTS_H
+#define TC_DEFAULTS_H
+
+#define TC_DEFAULT_MOD_PATH "/usr/local/lib/transcode"
+
+#define TC_DEFAULT_IN_FILE "/dev/zero"
+#define TC_DEFAULT_OUT_FILE "/dev/null"
+
+// default PAL video size
+#define PAL_W 720
+#define PAL_H 576
+#define BPP 24
+#define PAL_FPS 25.0
+#define MIN_FPS 1.0
+#define NTSC_FILM ((double)(24000)/1001.0)
+#define NTSC_VIDEO ((double)(30000)/1001.0)
+
+//NTSC
+#define NTSC_W 720
+#define NTSC_H 480
+
+//new max frame size:
+#define TC_MAX_V_FRAME_WIDTH 2500
+#define TC_MAX_V_FRAME_HEIGHT 2000
+
+// max bytes per pixel
+#define TC_MAX_V_BYTESPP 4
+
+// audio defaults
+#define RATE 48000
+#define BITS 16
+#define CHANNELS 2
+
+#define SIZE_RGB_FRAME ((int) TC_MAX_V_FRAME_WIDTH*TC_MAX_V_FRAME_HEIGHT*(BPP/8))
+#define SIZE_PCM_FRAME ((int) (RATE/MIN_FPS) * BITS/8 * CHANNELS * 3)
+
+#define TC_PAD_AUD_FRAMES 10
+#define TC_MAX_SEEK_BYTES (1<<20)
+
+// DivX/MPEG-4 encoder defaults
+#define VBITRATE 1800
+#define VKEYFRAMES 250
+#define VCRISPNESS 100
+
+#define VMULTIPASS 0
+#define VQUALITY 5
+
+#define VMINQUANTIZER 2
+#define VMAXQUANTIZER 31
+
+#define VQUANTIZER 10
+
+#define RC_PERIOD 2000
+#define RC_REACTION_PERIOD 10
+#define RC_REACTION_RATIO 20
+
+// Divx5 VBV (Video Bitrate Verifier)
+// Home theatre profile and settings
+#define DIVX5_VBV_PROFILE 3
+#define DIVX5_VBV_BITRATE (4000000/400)
+#define DIVX5_VBV_SIZE (3145728/16384)
+#define DIVX5_VBV_OCCUPANCY (2359296/64)
+
+//----------------------------------
+
+#define ABITRATE 128
+#define AQUALITY 5
+#define AVBR 0
+#define AMODE 0
+
+typedef enum tcdebugmode_ TCDebugMode;
+enum tcdebugmode_ {
+ TC_QUIET = 0,
+ TC_INFO = 1,
+ TC_DEBUG = 2,
+ TC_STATS = 4,
+ TC_CLEANUP = 8,
+ TC_FLIST = 16,
+ TC_SYNC = 32,
+ TC_COUNTER = 64,
+ TC_PRIVATE = 128,
+ TC_THREADS = 256,
+ TC_WATCH = 512,
+};
+
+//import/export/filter frame buffer status flag
+#define TC_NONE 0
+#define TC_VIDEO 1
+#define TC_AUDIO 2
+#define TC_SUBEX 4
+#define TC_RESERVED 8
+#define TC_EXTRA 16
+
+#define TC_FILTER_INIT 16
+#define TC_PRE_S_PROCESS 32
+#define TC_PRE_M_PROCESS 64
+#define TC_INT_M_PROCESS 128
+#define TC_POST_M_PROCESS 256
+#define TC_POST_S_PROCESS 512
+#define TC_PREVIEW 1024
+#define TC_FILTER_CLOSE 2048
+#define TC_FILTER_GET_CONFIG 4096
+
+#define TC_IMPORT 8192
+#define TC_EXPORT 16384
+
+#define TC_DELAY_MAX 40000
+#define TC_DELAY_MIN 10000
+
+#define TC_DEFAULT_IMPORT_AUDIO "null"
+#define TC_DEFAULT_IMPORT_VIDEO "null"
+#define TC_DEFAULT_EXPORT_AUDIO "null"
+#define TC_DEFAULT_EXPORT_VIDEO "null"
+#define TC_DEFAULT_EXPORT_MPLEX "null"
+
+#define TC_FRAME_BUFFER 10
+#define TC_FRAME_THREADS 1
+#define TC_FRAME_THREADS_MAX 32
+
+#define TC_FRAME_FIRST 0
+#define TC_FRAME_LAST INT_MAX
+
+#define TC_LEAP_FRAME 1000
+#define TC_MAX_AUD_TRACKS 32
+
+//--------------------------------------------------
+
+#define CODEC_NULL 0x0
+
+#define CODEC_RGB 1
+#define CODEC_YUV 2
+#define CODEC_MP4 4
+#define CODEC_YUY2 8
+#define CODEC_DV 16
+#define CODEC_RAW 32
+#define CODEC_RAW_RGB 64
+#define CODEC_RAW_YUV 128
+#define CODEC_YUV422 256
+
+#define CODEC_PCM 0x1
+#define CODEC_AC3 0x2000
+#define CODEC_MP2 0x50
+#define CODEC_MP3 0x55
+#define CODEC_DIVX 0x161
+#define CODEC_IMA4 0x11
+#define CODEC_LPCM 0x10001
+#define CODEC_DTS 0x1000F //??
+#define CODEC_VORBIS 0xfffe
+#define CODEC_VAG 0xfeed //me pizza
+
+#define TC_INFO_NO_DEMUX 1
+#define TC_INFO_MPEG_PS 2
+#define TC_INFO_MPEG_ES 4
+#define TC_INFO_MPEG_PES 8
+
+#define TC_FRAME_DV_PAL 144000
+#define TC_FRAME_DV_NTSC 120000
+
+#define TC_SUBTITLE_HDRMAGIC 0x00030001
+
+#define TC_DEFAULT_AAWEIGHT (1.0f/3.0f)
+#define TC_DEFAULT_AABIAS (0.5f)
+
+#define TC_A52_DRC_OFF 1
+#define TC_A52_DEMUX 2
+#define TC_A52_DOLBY_OFF 4
+
+#define AVI_FILE_LIMIT 2048
+
+#define M2V_REQUANT_FACTOR 1.00f
+
+/*
+ * flags used in modules for supporting export profiles (--export_prof)
+ * if one of those flag is set, then use the value provided by the user.
+ * otherwise use the ones the export modules suggests.
+ */
+typedef enum tcexportattribute_ TCExportAttribute;
+enum tcexportattribute_ {
+ TC_EXPORT_ATTRIBUTE_NONE = ( 0),
+ TC_EXPORT_ATTRIBUTE_VBITRATE = (1<< 1), /* -w */
+ TC_EXPORT_ATTRIBUTE_ABITRATE = (1<< 2), /* -b */
+ TC_EXPORT_ATTRIBUTE_FIELDS = (1<< 3), /* --encode_fields */
+ TC_EXPORT_ATTRIBUTE_VMODULE = (1<< 4), /* -y X,* */
+ TC_EXPORT_ATTRIBUTE_AMODULE = (1<< 5), /* -y *,X */
+ TC_EXPORT_ATTRIBUTE_FRC = (1<< 6), /* --export_fps *,X */
+ TC_EXPORT_ATTRIBUTE_FPS = (1<< 7), /* --export_fps X,* */
+ TC_EXPORT_ATTRIBUTE_VCODEC = (1<< 8), /* -F */
+ TC_EXPORT_ATTRIBUTE_ACODEC = (1<< 9), /* -N */
+ TC_EXPORT_ATTRIBUTE_ARATE = (1<<10), /* -E X,*,* */
+ TC_EXPORT_ATTRIBUTE_ABITS = (1<<11), /* -E *,X,* */
+ TC_EXPORT_ATTRIBUTE_ACHANS = (1<<12), /* -E *,*,X */
+ TC_EXPORT_ATTRIBUTE_ASR = (1<<13), /* --export_asr */
+ TC_EXPORT_ATTRIBUTE_PAR = (1<<14), /* --export_par */
+ TC_EXPORT_ATTRIBUTE_GOP = (1<<15), /* key frames */
+};
+
+#endif /* TC_DEFAULTS_H */
diff --git a/debian/transcode/transcode-1.1.7/src/tcinfo.h b/debian/transcode/transcode-1.1.7/src/tcinfo.h
new file mode 100644
index 00000000..bb81ebd5
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/tcinfo.h
@@ -0,0 +1,224 @@
+/*
+ * tcinfo.h - definitions of info_t and decode_t
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#ifndef TCINFO_H
+#define TCINFO_H
+
+#ifndef PROBE_H
+# include "probe.h" // for ProbeInfo
+#endif
+
+/*************************************************************************/
+
+typedef struct _info_t {
+
+ int fd_in; // Input stream file descriptor
+ int fd_out; // Output stream file descriptor
+
+ long magic; // Specifies file magic for extract thread
+ int track; // Track to extract
+ long stype; // Specifies stream type for extract thread
+ long codec; // Specifies codec for extract thread
+ int verbose; // Verbosity
+
+ int dvd_title;
+ int dvd_chapter;
+ int dvd_angle;
+
+ int vob_offset;
+
+ int ps_unit;
+ int ps_seq1;
+ int ps_seq2;
+
+ int ts_pid;
+
+ int seek_allowed;
+
+ int demux;
+ int select; // Selected packet payload type
+ int subid; // Selected packet substream ID
+ int keep_seq; // Do not drop first sequence (cluster mode)
+
+ double fps;
+
+ int fd_log;
+
+ const char *name; // Source name as supplied with -i option
+ const char *nav_seek_file; // Seek/index file
+
+ int probe; // Flag for probe only mode
+ int factor; // Amount of file to probe, in MB
+
+ ProbeInfo *probe_info;
+
+ int quality;
+ int error;
+
+ long frame_limit[3];
+ int hard_fps_flag; // If this is set, disable demuxer smooth drop
+
+} info_t;
+
+typedef struct {
+ int fd_in; // Input stream file descriptor
+ int fd_out; // Output stream file descriptor
+ double ac3_gain[3];
+ long frame_limit[3];
+ int dv_yuy2_mode;
+ int padrate; // Zero padding rate
+ long magic; // Specifies file magic
+ long stype; // Specifies stream type
+ long codec; // Specifies codec
+ int verbose; // Verbosity
+ int quality;
+ const char *name; // Source name as supplied with -i option
+ int width;
+ int height;
+ int a52_mode;
+ long format; // Specifies raw stream format for output
+ int select; // Selected packet payload type
+} decode_t;
+
+/*************************************************************************/
+
+#include "libtc/tccodecs.h"
+
+typedef struct tcarea_ TCArea;
+struct tcarea_ {
+ int top;
+ int left;
+ int bottom;
+ int right;
+};
+
+typedef struct tcexportinfo_ TCExportInfo;
+struct tcexportinfo_ {
+ uint32_t attributes;
+
+ /*
+ * common fields for video/audio/mplex sections:
+ * string : generic opaque string identifier
+ * (for video, mainly used for fourcc).
+ * module : (NMS) encode module to use.
+ * module_opts : (opaque) option string to module.
+ *
+ * common fields for video/audio sections:
+ * format : identifier of video format to use in encoding phase.
+ * Isn't a proper codec identifer since it can be a
+ * 'special' format like TC_CODEC_COPY
+ * FIXME: can sometimes be CODEC_XXX not TC_CODEC_XXX.
+ * quality : encoding quality condensed in a single param.
+ * Rarely used but still needed.
+ * bitrate : MEAN video bitrate to use (kbps) in encoding.
+ */
+ struct {
+ char *string;
+ char *module;
+ char *module_opts;
+
+ TCCodecID format;
+ int quality;
+ int bitrate;
+
+ char *log_file;
+ /* path to log file to use, if needed, for multipass encoding. */
+
+ int width;
+ int height;
+ /*
+ * FINAL requested video frame width/height: encoded video stream will
+ * have this width/height.
+ */
+ int keep_asr_flag;
+ /* final asr should be forced equal to import asr? */
+ int fast_resize_flag; /* self explanatory :) */
+ int zoom_interlaced_flag; /* self explanatory :) */
+ int asr;
+ /*
+ * frame aspect ratio; often (but NOT always)
+ * computed from width/height pair
+ */
+
+ int frc; /* frame rate code */
+ int par;
+ /* pixel aspect ratio; 1:1 by default, overridden by user in case */
+ int encode_fields;
+ /* field based encoding selection */
+
+ TCArea pre_clip;
+ /* clip specified area BEFORE any other operation */
+ TCArea post_clip;
+ /* clip specified area AFTER any other operation */
+
+ int gop_size;
+ /* video GOP size also known as keyframe interval */
+ int quantizer_min;
+ int quantizer_max;
+ /* quantizer range to use in encoding */
+
+ int bitrate_max;
+ /*
+ * Maximum video bitrate to use (kbps) in encoding.
+ * Rarely used but still needed.
+ */
+
+ int pass_number; /* set for usage in multipass encoding */
+ } video;
+
+ struct {
+ char *string;
+ char *module;
+ char *module_opts;
+
+ TCCodecID format;
+ int quality;
+ int bitrate;
+
+ int sample_rate; /* audio sample rate (Hz) */
+ int sample_bits; /* bits to use for each audio sample */
+ int channels; /* number of channels in audio stream */
+ int mode; /* audio mode: mode, stereo, joint stereo... */
+ /*
+ * those last three fields are mainly used by lame, but they
+ * should be generalized
+ */
+ int vbr_flag;
+ int flush_flag;
+ int bit_reservoir;
+ } audio;
+
+ struct {
+ char *string;
+ char *module;
+ char *module_opts;
+
+ char *out_file; /* self explanatory :) */
+ char *out_file_aux;
+ /*
+ * path of extra output file (separate audio track.
+ * Provided for back compatibilty, can go away in future revisions.
+ */
+ } mplex;
+};
+
+/*************************************************************************/
+
+#endif // TCINFO_H
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/transcode.c b/debian/transcode/transcode-1.1.7/src/transcode.c
new file mode 100644
index 00000000..0c7c797e
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/transcode.c
@@ -0,0 +1,2863 @@
+/*
+ * transcode.c
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ *
+ * This file is part of transcode, a 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 "transcode.h"
+#include "decoder.h"
+#include "encoder.h"
+#include "dl_loader.h"
+#include "framebuffer.h"
+#include "counter.h"
+#include "frame_threads.h"
+#include "filter.h"
+#include "probe.h"
+#include "socket.h"
+#include "split.h"
+
+#include "libtc/xio.h"
+#include "libtc/libtc.h"
+#include "libtc/cfgfile.h"
+#include "libtc/tccodecs.h"
+#include "libtc/ratiocodes.h"
+
+#include <ctype.h>
+#include <math.h>
+
+#include "cmdline.h"
+
+
+/* ------------------------------------------------------------
+ *
+ * default options
+ *
+ * ------------------------------------------------------------*/
+
+
+int pcmswap = TC_FALSE;
+int rgbswap = TC_FALSE;
+int rescale = TC_FALSE;
+int im_clip = TC_FALSE;
+int ex_clip = TC_FALSE;
+int pre_im_clip = TC_FALSE;
+int post_ex_clip= TC_FALSE;
+int flip = TC_FALSE;
+int mirror = TC_FALSE;
+int resize1 = TC_FALSE;
+int resize2 = TC_FALSE;
+int decolor = TC_FALSE;
+int zoom = TC_FALSE;
+int dgamma = TC_FALSE;
+int keepasr = TC_FALSE;
+int fast_resize = TC_FALSE;
+
+// global information structure
+static vob_t *vob = NULL;
+int verbose = TC_INFO;
+
+//-------------------------------------------------------------
+// core parameter
+
+int tc_buffer_delay_dec = -1;
+int tc_buffer_delay_enc = -1;
+int tc_cluster_mode = 0;
+int tc_decoder_delay = 0;
+int tc_progress_meter = -1; // so we know whether it's set by the user
+int tc_progress_rate = 1;
+int tc_accel = AC_ALL; //acceleration code
+unsigned int tc_avi_limit = (unsigned int)-1;
+pid_t tc_probe_pid = 0;
+int tc_niceness = 0;
+
+int max_frame_buffer = TC_FRAME_BUFFER;
+int max_frame_threads = TC_FRAME_THREADS;
+
+//-------------------------------------------------------------
+
+
+/*************************************************************************/
+/*********************** Exported utility routines ***********************/
+/*************************************************************************/
+
+/**
+ * version: Print a version message. The message is only printed for the
+ * first call.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+void version(void)
+{
+ static int tcversion = 0;
+ if (tcversion++)
+ return;
+ fprintf(stderr, "%s v%s (C) 2001-2003 Thomas Oestreich,"
+ " 2003-2010 Transcode Team\n",
+ PACKAGE, VERSION);
+}
+
+/*************************************************************************/
+
+/**
+ * tc_get_vob: Return a pointer to the global vob_t data structure.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * A pointer to the global vob_t data structure.
+ */
+
+vob_t *tc_get_vob()
+{
+ return vob;
+}
+
+/*************************************************************************/
+
+/**
+ * validate_source_path: Check whether the given string represents a valid
+ * source pathname.
+ *
+ * Parameters:
+ * path: String to check.
+ * Return value:
+ * Nonzero if the string is a valid source pathname, else zero.
+ * Side effects:
+ * Prints an error message using tc_error() if the string is not a
+ * valid pathname.
+ */
+
+static int validate_source_path(const char *path)
+{
+ struct stat st;
+
+ if (!path || !*path) {
+ tc_error("No filename given");
+ return 0;
+ }
+ if (strcmp(path, "-") == 0) // allow stdin (maybe also /dev/stdin? FIXME)
+ return 1;
+ if (*path == '!' || *path == ':') /* from transcode.c -- why? */
+ return 1;
+ if (xio_stat(path, &st) == 0)
+ return 1;
+ tc_error("Invalid filename \"%s\": %s", path, strerror(errno));
+ return 0;
+}
+
+/*************************************************************************/
+
+int tc_next_video_in_file(vob_t *vob)
+{
+ vob->video_in_file = tc_glob_next(vob->video_in_files);
+ if (vob->video_in_file != NULL) {
+ return TC_OK;
+ }
+ return TC_ERROR;
+}
+
+int tc_next_audio_in_file(vob_t *vob)
+{
+ vob->audio_in_file = tc_glob_next(vob->audio_in_files);
+ if (vob->audio_in_file != NULL) {
+ return TC_OK;
+ }
+ return TC_ERROR;
+}
+
+int tc_has_more_video_in_file(vob_t *vob)
+{
+ int ret = TC_FALSE;
+
+ if (core_mode == TC_MODE_DIRECTORY) {
+ ret = tc_glob_has_more(vob->video_in_files);
+ }
+ return ret;
+}
+
+int tc_has_more_audio_in_file(vob_t *vob)
+{
+ int ret = TC_FALSE;
+
+ if (core_mode == TC_MODE_DIRECTORY) {
+ ret = tc_glob_has_more(vob->audio_in_files);
+ }
+ return ret;
+}
+
+/*************************************************************************/
+/*********************** Internal utility routines ***********************/
+/*************************************************************************/
+
+/*************************************************************************/
+/*********************** Event thread support ****************************/
+/*************************************************************************/
+
+static pthread_t event_thread_id = (pthread_t)0;
+static const char *signame = "unknown signal";
+
+static void tc_stop_all(void)
+{
+ tc_stop();
+ tc_framebuffer_interrupt();
+}
+
+static void event_handler(int sig)
+{
+ switch (sig) {
+ case SIGINT:
+ signame = "SIGINT";
+ break;
+ case SIGTERM:
+ signame = "SIGTERM";
+ break;
+ case SIGPIPE:
+ signame = "SIGPIPE";
+ break;
+ }
+
+ tc_interrupt();
+ tc_framebuffer_interrupt();
+}
+
+/**
+ * event_thread: Thread that watches for certain termination signals,
+ * terminating the transcode process cleanly.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+static void *event_thread(void* blocked_)
+{
+ struct sigaction handler;
+ sigset_t *blocked = blocked_;
+
+ /* catch everything */
+ pthread_sigmask(SIG_UNBLOCK, blocked, NULL); /* XXX */
+
+ /* install handlers, mutually exclusive */
+ memset(&handler, 0, sizeof(struct sigaction));
+ handler.sa_flags = 0;
+ handler.sa_mask = *blocked;
+ handler.sa_handler = event_handler;
+
+ sigaction(SIGINT, &handler, NULL); // XXX
+ sigaction(SIGTERM, &handler, NULL); // XXX
+/* sigaction(SIGPIPE, &handler, NULL); */// XXX
+
+ /* Loop waiting for external events */
+ for (;;) {
+ pthread_testcancel();
+
+ tc_socket_wait();
+
+ if (tc_interrupted()) {
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "(sighandler) %s received", signame);
+
+ /* Kill the tcprobe process if it's running */
+ if (tc_probe_pid > 0)
+ kill(tc_probe_pid, SIGTERM);
+ }
+ pthread_testcancel();
+ }
+ return NULL;
+}
+
+/*************************************************************************/
+
+/**
+ * stop_event_thread: Ensure that the event handling thread is destroyed.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * None.
+ */
+
+static void stop_event_thread(void)
+{
+ if (event_thread_id) {
+ void *thread_status = NULL;
+
+// pthread_kill(event_thread_id, SIGINT);
+ pthread_cancel(event_thread_id);
+ pthread_join(event_thread_id, &thread_status);
+ }
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/**
+ * load_all_filters: Loads all filters specified by the -J option.
+ *
+ * Parameters:
+ * filter_list: String containing filter list from -J option.
+ * Return value:
+ * None.
+ * Side effects:
+ * Destroys `filter_list'.
+ */
+
+static void load_all_filters(char *filter_list)
+{
+ if (!filter_list)
+ return;
+
+ while (*filter_list) {
+ char *s = filter_list + strcspn(filter_list, ",");
+ char *options;
+
+ while (*s && s > filter_list && s[-1] == '\\')
+ s += 1 + strcspn(s+1, ",");
+ if (*s)
+ *s++ = 0;
+ options = strchr(filter_list, '=');
+ if (options)
+ *options++ = 0;
+ tc_filter_add(filter_list, options);
+ filter_list = s;
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * transcode_init: initialize the transcoding engine.
+ *
+ * Parameters:
+ * vob: Pointer to the global vob_t data structure.
+ * Return value:
+ * 0 on success, -1 on error.
+ */
+
+static int transcode_init(vob_t *vob, TCEncoderBuffer *tc_ringbuffer)
+{
+ /* load import modules and check capabilities */
+ if (tc_import_init(vob, im_aud_mod, im_vid_mod) < 0) {
+ tc_log_error(PACKAGE, "failed to init import modules");
+ return -1;
+ }
+
+ /* load and initialize filters */
+ tc_filter_init();
+ load_all_filters(plugins_string);
+
+ /* load export modules and check capabilities
+ * (only create a TCModule factory if a multiplex module was given) */
+ if (tc_export_init(tc_ringbuffer,
+ ex_mplex_mod
+ ? tc_new_module_factory(vob->mod_path,verbose)
+ : NULL) != TC_OK
+ ) {
+ tc_log_error(PACKAGE, "failed to init export layer");
+ return -1;
+ }
+ if (tc_export_setup(vob, ex_aud_mod, ex_vid_mod, ex_mplex_mod) != TC_OK) {
+ tc_log_error(PACKAGE, "failed to init export modules");
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * transcode_fini: finalize (shutdown) the transcoding engine.
+ *
+ * Parameters:
+ * vob: Pointer to the global vob_t data structure.
+ * Return value:
+ * 0 on success, -1 on error.
+ */
+
+static int transcode_fini(vob_t *vob)
+{
+ /* unload import modules */
+ tc_import_shutdown();
+ /* unload filters */
+ tc_filter_fini();
+ /* unload export modules */
+ tc_export_shutdown();
+
+ return 0;
+}
+
+/* -------------------------------------------------------------
+ * single file continuous or interval mode
+ * ------------------------------------------------------------*/
+
+/* globals: frame_a, frame_b */
+static int transcode_mode_default(vob_t *vob)
+{
+ struct fc_time *tstart = NULL;
+
+ tc_start();
+
+ // init decoder and open the source
+ if (0 != vob->ttime->vob_offset) {
+ vob->vob_offset = vob->ttime->vob_offset;
+ }
+ if (tc_import_open(vob) < 0)
+ tc_error("failed to open input source");
+
+ // start the AV import threads that load the frames into transcode
+ // this must be called after tc_import_open
+ tc_import_threads_create(vob);
+
+ // init encoder
+ if (tc_encoder_init(vob) != TC_OK)
+ tc_error("failed to init encoder");
+
+ // open output files
+ if (tc_encoder_open(vob) != TC_OK)
+ tc_error("failed to open output");
+
+ // tell counter about all encoding ranges
+ counter_reset_ranges();
+ if (!tc_cluster_mode) {
+ int last_etf = 0;
+ for (tstart = vob->ttime; tstart; tstart = tstart->next) {
+ if (tstart->etf == TC_FRAME_LAST) {
+ // variable length range, oh well
+ counter_reset_ranges();
+ break;
+ }
+ if (tstart->stf > last_etf)
+ counter_add_range(last_etf, tstart->stf-1, 0);
+ counter_add_range(tstart->stf, tstart->etf-1, 1);
+ last_etf = tstart->etf;
+ }
+ }
+
+ // get start interval
+ tstart = vob->ttime;
+
+ while (tstart) {
+ // set frame range (in cluster mode these will already be set)
+ if (!tc_cluster_mode) {
+ frame_a = tstart->stf;
+ frame_b = tstart->etf;
+ }
+ // main encoding loop, returns when done with all frames
+ tc_encoder_loop(vob, frame_a, frame_b);
+
+ // check for user cancelation request
+ if (tc_interrupted()) {
+ break;
+ }
+
+ // next range
+ tstart = tstart->next;
+ // see if we're using vob_offset
+ if ((tstart != NULL) && (tstart->vob_offset != 0)) {
+ tc_decoder_delay = 3;
+ tc_import_threads_cancel();
+ tc_import_close();
+ tc_framebuffer_flush();
+ vob->vob_offset = tstart->vob_offset;
+ vob->sync = sync_seconds;
+ if (tc_import_open(vob) < 0)
+ tc_error("failed to open input source");
+ tc_import_threads_create(vob);
+ }
+ }
+ tc_stop_all();
+
+ // close output files
+ tc_encoder_close();
+ // stop encoder
+ tc_encoder_stop();
+ // cancel import threads
+ tc_import_threads_cancel();
+ // stop decoder and close the source
+ tc_import_close();
+
+ return TC_OK;
+}
+
+
+/* ------------------------------------------------------------
+ * split output AVI file
+ * ------------------------------------------------------------*/
+
+/* globals: frame_a, frame_b, splitavi_frames, base */
+static int transcode_mode_avi_split(vob_t *vob)
+{
+ char buf[TC_BUF_MAX];
+ int fa, fb, ch1 = 0;
+
+ tc_start();
+
+ // init decoder and open the source
+ if (tc_import_open(vob) < 0)
+ tc_error("failed to open input source");
+
+ // start the AV import threads that load the frames into transcode
+ tc_import_threads_create(vob);
+
+ // encoder init
+ if (tc_encoder_init(vob) != TC_OK)
+ tc_error("failed to init encoder");
+
+ // need to loop for ch1
+ ch1 = 0;
+
+ do {
+ if (!strlen(base))
+ strlcpy(base, vob->video_out_file, TC_BUF_MIN);
+
+ // create new filename
+ tc_snprintf(buf, sizeof(buf), "%s%03d.avi", base, ch1++);
+ vob->video_out_file = buf;
+ vob->audio_out_file = buf;
+
+ // open output
+ if (tc_encoder_open(vob) != TC_OK)
+ tc_error("failed to open output");
+
+ fa = frame_a;
+ fb = frame_a + splitavi_frames;
+
+ tc_encoder_loop(vob, fa, ((fb > frame_b) ? frame_b : fb));
+
+ // close output
+ tc_encoder_close();
+
+ // restart
+ frame_a += splitavi_frames;
+ if (frame_a >= frame_b)
+ break;
+
+ if (verbose & TC_DEBUG)
+ tc_log_msg(PACKAGE, "import status=%d", tc_import_status());
+
+ // check for user cancelation request
+ if (tc_interrupted())
+ break;
+
+ } while (tc_import_status());
+
+ tc_stop_all();
+
+ tc_encoder_stop();
+
+ // cancel import threads
+ tc_import_threads_cancel();
+ // stop decoder and close the source
+ tc_import_close();
+
+ return TC_OK;
+}
+
+
+/* globals: frame_a, frame_b */
+static int transcode_mode_directory(vob_t *vob)
+{
+ struct fc_time *tstart = NULL;
+
+ tc_start();
+
+ if (strcmp(vob->audio_in_file, vob->video_in_file) != 0)
+ tc_error("directory mode DOES NOT support separate audio files (A=%s|V=%s)",
+ vob->audio_in_file, vob->video_in_file);
+
+ tc_multi_import_threads_create(vob);
+
+ if (tc_encoder_init(vob) != TC_OK)
+ tc_error("failed to init encoder");
+ if (tc_encoder_open(vob) != TC_OK)
+ tc_error("failed to open output");
+
+ // tell counter about all encoding ranges
+ counter_reset_ranges();
+ if (!tc_cluster_mode) {
+ int last_etf = 0;
+ for (tstart = vob->ttime; tstart; tstart = tstart->next) {
+ if (tstart->etf == TC_FRAME_LAST) {
+ // variable length range, oh well
+ counter_reset_ranges();
+ break;
+ }
+ if (tstart->stf > last_etf)
+ counter_add_range(last_etf, tstart->stf-1, 0);
+ counter_add_range(tstart->stf, tstart->etf-1, 1);
+ last_etf = tstart->etf;
+ }
+ }
+
+ // get start interval
+ for (tstart = vob->ttime;
+ tstart != NULL && !tc_interrupted();
+ tstart = tstart->next) {
+ // set frame range (in cluster mode these will already be set)
+ if (!tc_cluster_mode) {
+ frame_a = tstart->stf;
+ frame_b = tstart->etf;
+ }
+ // main encoding loop, returns when done with all frames
+ tc_encoder_loop(vob, frame_a, frame_b);
+ }
+
+ tc_stop_all();
+
+ tc_encoder_close();
+ tc_encoder_stop();
+ tc_multi_import_threads_cancel();
+
+ return TC_OK;
+}
+
+/* ---------------------------------------------------------------
+ * VOB PSU mode: transcode and split based on program stream units
+ * --------------------------------------------------------------*/
+
+/* globals: frame_a, frame_b */
+static int transcode_mode_psu(vob_t *vob, const char *psubase)
+{
+ char buf[TC_BUF_MAX];
+ int fa, fb, psu_cur = vob->vob_psu_num1;
+
+ if (tc_encoder_init(vob) != TC_OK)
+ tc_error("failed to init encoder");
+
+ // open output
+ if (no_split) {
+ vob->video_out_file = psubase;
+ if (tc_encoder_open(vob) != TC_OK)
+ tc_error("failed to open output");
+ }
+
+ tc_decoder_delay = 3;
+
+ counter_on();
+
+ for (;;) {
+ int ret;
+
+ memset(buf, 0, sizeof buf);
+ if (!no_split) {
+ // create new filename
+ tc_snprintf(buf, sizeof(buf), psubase, psu_cur);
+ // update vob structure
+ vob->video_out_file = buf;
+
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "using output filename %s",
+ vob->video_out_file);
+ }
+
+ // get seek/frame information for next PSU
+ // need to process whole PSU
+ vob->vob_chunk = 0;
+ vob->vob_chunk_max = 1;
+
+ ret = split_stream(vob, nav_seek_file, psu_cur, &fa, &fb, 0);
+
+ if (verbose & TC_DEBUG)
+ tc_log_msg(PACKAGE,"processing PSU %d, -L %d -c %d-%d %s (ret=%d)",
+ psu_cur, vob->vob_offset, fa, fb, buf, ret);
+
+ // exit condition
+ if (ret < 0 || psu_cur == vob->vob_psu_num2)
+ break;
+
+ // do not process units with a small frame number, assume it is junk
+ if ((fb-fa) > psu_frame_threshold) {
+ tc_start();
+
+ // start new decoding session with updated vob structure
+ // this starts the full decoder setup, including the threads
+ if (tc_import_open(vob) < 0)
+ tc_error("failed to open input source");
+
+ // start the AV import threads that load the frames into transcode
+ tc_import_threads_create(vob);
+
+ // frame threads may need a reboot too.
+ tc_frame_threads_init(vob, max_frame_threads, max_frame_threads);
+
+ // open new output file
+ if (!no_split) {
+ if (tc_encoder_open(vob) != TC_OK)
+ tc_error("failed to open output");
+ }
+
+ // core
+ // we try to encode more frames and let the decoder safely
+ // drain the queue to avoid threads not stopping
+
+ tc_encoder_loop(vob, fa, TC_FRAME_LAST);
+
+ // close output file
+ if (!no_split) {
+ if (tc_encoder_close() != TC_OK)
+ tc_warn("failed to close encoder - non fatal");
+ }
+
+ if (verbose >= TC_CLEANUP) {
+ // for debug
+ vframe_dump_status();
+ aframe_dump_status();
+ }
+
+ // cancel import threads
+ tc_import_threads_cancel();
+ // stop decoder and close the source
+ tc_import_close();
+
+ // flush all buffers before we proceed to next PSU
+ tc_framebuffer_flush();
+
+ vob->psu_offset += (double) (fb-fa);
+ } else {
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "skipping PSU %d with %d frame(s)",
+ psu_cur, fb-fa);
+
+ }
+
+ psu_cur++;
+ if (tc_interrupted())
+ break;
+ } //next PSU
+
+ // close output
+ if (no_split) {
+ if (tc_encoder_close() != TC_OK)
+ tc_warn("failed to close encoder - non fatal");
+ }
+
+ tc_stop_all();
+
+ tc_encoder_stop();
+
+ return TC_OK;
+}
+
+/* ------------------------------------------------------------
+ * DVD chapter mode
+ * ------------------------------------------------------------*/
+
+/* globals: frame_a, frame_b, chbase */
+static int transcode_mode_dvd(vob_t *vob)
+{
+#ifdef HAVE_LIBDVDREAD
+ char buf[TC_BUF_MAX];
+ int ch1, ch2;
+
+ tc_start();
+
+ if (tc_encoder_init(vob) != TC_OK)
+ tc_error("failed to init encoder");
+
+ // open output
+ if (no_split) {
+ // create new filename
+ tc_snprintf(buf, sizeof(buf), "%s.avi", chbase);
+ // update vob structure
+ vob->video_out_file = buf;
+ vob->audio_out_file = buf;
+
+ if (tc_encoder_open(vob) != TC_OK)
+ tc_error("failed to open output");
+ }
+
+ // 1 sec delay after decoder closing
+ tc_decoder_delay = 1;
+
+ // loop each chapter
+ ch1 = vob->dvd_chapter1;
+ ch2 = vob->dvd_chapter2;
+
+ //ch = -1 is allowed but makes no sense
+ if (ch1 < 0)
+ ch1 = 1;
+
+ for (;;) {
+ vob->dvd_chapter1 = ch1;
+ vob->dvd_chapter2 = -1;
+
+ if (!no_split) {
+ // create new filename
+ tc_snprintf(buf, sizeof(buf), "%s-ch%02d.avi", chbase, ch1);
+ // update vob structure
+ vob->video_out_file = buf;
+ vob->audio_out_file = buf;
+ }
+
+ // start decoding with updated vob structure
+ if (tc_import_open(vob) < 0)
+ tc_error("failed to open input source");
+
+ // start the AV import threads that load the frames into transcode
+ tc_import_threads_create(vob);
+
+ if (verbose & TC_DEBUG)
+ tc_log_msg(PACKAGE, "%d chapters for title %d detected",
+ vob->dvd_max_chapters, vob->dvd_title);
+
+ // encode
+ if (!no_split) {
+ if (tc_encoder_open(vob) != TC_OK)
+ tc_error("failed to init encoder");
+ }
+
+ // main encoding loop, selecting an interval won't work
+ tc_encoder_loop(vob, frame_a, frame_b);
+
+ if (!no_split) {
+ if (tc_encoder_close() != TC_OK)
+ tc_warn("failed to close encoder - non fatal");
+ }
+
+ // cancel import threads
+ tc_import_threads_cancel();
+ // stop decoder and close the source
+ tc_import_close();
+
+ // flush all buffers before we proceed
+ tc_framebuffer_flush();
+
+ // exit, i) if import module could not determine max_chapters
+ // ii) all chapters are done
+ // iii) someone hit ^C
+
+ if (vob->dvd_max_chapters ==- 1
+ || ch1 == vob->dvd_max_chapters || ch1 == ch2
+ || tc_interrupted())
+ break;
+ ch1++;
+ }
+
+ if (no_split) {
+ if (tc_encoder_close() != TC_OK)
+ tc_warn("failed to close encoder - non fatal");
+ }
+
+ tc_stop_all();
+ tc_encoder_stop();
+#endif
+
+ return TC_OK;
+}
+
+/*************************************************************************/
+
+/**
+ * new_vob: Create a new vob_t structure and fill it with appropriate
+ * values.
+ *
+ * Parameters:
+ * None.
+ * Return value:
+ * A pointer to the newly-created vob_t structure, or NULL on error.
+ * Notes:
+ * On error, errno is valid.
+ */
+
+static vob_t *new_vob(void)
+{
+ vob_t *vob = tc_malloc(sizeof(vob_t));
+ if (!vob)
+ return NULL;
+
+ vob->divxbitrate = VBITRATE;
+ vob->video_max_bitrate = 0; /* 0 = set by encoder */
+ vob->divxkeyframes = VKEYFRAMES;
+ vob->divxquality = VQUALITY;
+ vob->divxmultipass = VMULTIPASS;
+ vob->divxcrispness = VCRISPNESS;
+ vob->m2v_requant = M2V_REQUANT_FACTOR;
+
+ vob->min_quantizer = VMINQUANTIZER;
+ vob->max_quantizer = VMAXQUANTIZER;
+
+ vob->rc_period = RC_PERIOD;
+ vob->rc_reaction_period = RC_REACTION_PERIOD;
+ vob->rc_reaction_ratio = RC_REACTION_RATIO;
+
+ vob->divx5_vbv_prof = DIVX5_VBV_PROFILE;
+ vob->divx5_vbv_bitrate = DIVX5_VBV_BITRATE;
+ vob->divx5_vbv_size = DIVX5_VBV_SIZE;
+ vob->divx5_vbv_occupancy = DIVX5_VBV_OCCUPANCY;
+
+ vob->mp3bitrate = ABITRATE;
+ vob->mp3frequency = 0;
+ vob->mp3quality = AQUALITY;
+ vob->mp3mode = AMODE;
+ vob->a_rate = RATE;
+ vob->a_stream_bitrate = 0;
+ vob->a_bits = BITS;
+ vob->a_chan = CHANNELS;
+ vob->a_padrate = 0;
+
+ vob->dm_bits = 0;
+ vob->dm_chan = 0;
+
+ vob->im_a_size = SIZE_PCM_FRAME;
+ vob->im_v_width = PAL_W;
+ vob->im_v_height = PAL_H;
+ vob->im_v_size = SIZE_RGB_FRAME;
+ vob->ex_a_size = SIZE_PCM_FRAME;
+ vob->ex_v_width = PAL_W;
+ vob->ex_v_height = PAL_H;
+ vob->ex_v_size = SIZE_RGB_FRAME;
+ vob->a_track = 0;
+ vob->v_track = 0;
+ vob->volume = 0;
+ vob->ac3_gain[0] = 1.0;
+ vob->ac3_gain[1] = 1.0;
+ vob->ac3_gain[2] = 1.0;
+ vob->audio_out_file = NULL;
+ vob->video_out_file = NULL;
+ vob->avifile_in = NULL;
+ vob->avifile_out = NULL;
+ vob->avi_comment_fd = -1;
+ vob->nav_seek_file = NULL;
+ vob->audio_file_flag = 0;
+ vob->audio_in_file = NULL;
+ vob->video_in_file = NULL;
+ vob->clip_count = 0;
+ vob->ex_a_codec = CODEC_MP3; //or fall back to module default
+ vob->ex_v_codec = CODEC_NULL; //determined by export module type
+ vob->ex_v_fcc = NULL;
+ vob->ex_a_fcc = NULL;
+ vob->ex_profile_name = NULL;
+ vob->fps = PAL_FPS;
+ vob->ex_fps = 0;
+ vob->im_frc = 0;
+ vob->ex_frc = 0;
+ vob->pulldown = 0;
+ vob->im_clip_top = 0;
+ vob->im_clip_bottom = 0;
+ vob->im_clip_left = 0;
+ vob->im_clip_right = 0;
+ vob->ex_clip_top = 0;
+ vob->ex_clip_bottom = 0;
+ vob->ex_clip_left = 0;
+ vob->ex_clip_right = 0;
+ vob->resize1_mult = 32;
+ vob->vert_resize1 = 0;
+ vob->hori_resize1 = 0;
+ vob->resize2_mult = 32;
+ vob->vert_resize2 = 0;
+ vob->hori_resize2 = 0;
+ vob->sync = 0;
+ vob->sync_ms = 0;
+ vob->sync_samples = 0;
+ vob->dvd_title = 1;
+ vob->dvd_chapter1 = 1;
+ vob->dvd_chapter2 = -1;
+ vob->dvd_max_chapters = -1;
+ vob->dvd_angle = 1;
+ vob->pass_flag = 0;
+ vob->verbose = TC_QUIET;
+ vob->antialias = 0;
+ vob->deinterlace = 0;
+ vob->decolor = 0;
+ vob->im_a_codec = CODEC_PCM;
+ vob->im_v_codec = CODEC_YUV;
+ vob->mod_path = MOD_PATH;
+ vob->audiologfile = NULL;
+ vob->divxlogfile = NULL;
+ vob->ps_unit = 0;
+ vob->ps_seq1 = 0;
+ vob->ps_seq2 = TC_FRAME_LAST;
+ vob->a_leap_frame = TC_LEAP_FRAME;
+ vob->a_leap_bytes = 0;
+ vob->demuxer = -1;
+ vob->a_codec_flag = CODEC_AC3;
+ vob->gamma = 0.0;
+ vob->encoder_flush = TC_TRUE;
+ vob->has_video = 1;
+ vob->has_audio = 1;
+ vob->has_audio_track = 1;
+ vob->lang_code = 0;
+ vob->v_format_flag = 0;
+ vob->v_codec_flag = 0;
+ vob->a_format_flag = 0;
+ vob->im_asr = 0;
+ vob->im_par = 0;
+ vob->im_par_width = 0;
+ vob->im_par_height = 0;
+ vob->ex_asr = -1;
+ vob->ex_par = 0;
+ vob->ex_par_width = 0;
+ vob->ex_par_height = 0;
+ vob->quality = VQUALITY;
+ vob->amod_probed = "null";
+ vob->vmod_probed = "null";
+ vob->amod_probed_xml = NULL;
+ vob->vmod_probed_xml = NULL;
+ vob->a_vbr = 0;
+ vob->pts_start = 0.0f;
+ vob->vob_offset = 0;
+ vob->vob_chunk = 0;
+ vob->vob_chunk_max = 0;
+ vob->vob_chunk_num1 = 0;
+ vob->vob_chunk_num2 = 0;
+ vob->vob_psu_num1 = 0;
+ vob->vob_psu_num2 = INT_MAX;
+ vob->vob_info_file = NULL;
+ vob->vob_percentage = 0;
+ vob->im_a_string = NULL;
+ vob->im_v_string = NULL;
+ vob->ex_a_string = NULL;
+ vob->ex_v_string = NULL;
+ vob->ex_m_string = NULL;
+
+ vob->reduce_h = 1;
+ vob->reduce_w = 1;
+
+ //-Z
+ vob->zoom_width = 0;
+ vob->zoom_height = 0;
+ vob->zoom_filter = TCV_ZOOM_LANCZOS3;
+ vob->zoom_interlaced = 0;
+
+ vob->frame_interval = 1; // write every frame
+
+ //anti-alias
+ vob->aa_weight = TC_DEFAULT_AAWEIGHT;
+ vob->aa_bias = TC_DEFAULT_AABIAS;
+
+ vob->a52_mode = 0;
+ vob->encode_fields = TC_ENCODE_FIELDS_PROGRESSIVE;
+
+ vob->ttime = NULL;
+
+ vob->psu_offset = 0.0f;
+ vob->bitreservoir = TC_TRUE;
+ vob->lame_preset = NULL;
+
+ vob->ts_pid1 = 0x0;
+ vob->ts_pid2 = 0x0;
+
+ vob->dv_yuy2_mode = 0;
+ vob->hard_fps_flag = 0;
+ vob->mpeg_profile = PROF_NONE;
+
+ vob->attributes = 0;
+ vob->export_attributes = TC_EXPORT_ATTRIBUTE_NONE;
+
+ return vob;
+}
+
+/*************************************************************************/
+
+/*
+ * parse_navigation_file:
+ * parse navigation data file and setup vob data fields accordingly.
+ * This function handle both aviindex and tcdemux -W generated files.
+ *
+ * Parameters:
+ * vob: Pointer to the global vob_t data structure.
+ * nav_seek_file: Path of navigation file.
+ * Return Value:
+ * None
+ */
+static void parse_navigation_file(vob_t *vob, const char *nav_seek_file)
+{
+ if (nav_seek_file) {
+ FILE *fp = NULL;
+ struct fc_time *tmptime = NULL;
+ char buf[TC_BUF_MIN];
+ int line_count = 0;
+ int flag = 0;
+ int is_aviindex = 0;
+
+ if (vob->vob_offset) {
+ tc_warn("-L and --nav_seek are incompatible.");
+ }
+
+ fp = fopen(nav_seek_file, "r");
+ if (NULL == fp) {
+ tc_error("unable to open: %s", nav_seek_file);
+ }
+
+ tmptime = vob->ttime;
+ line_count = 0;
+
+ // check if this is an AVIIDX1 file
+ if (fgets(buf, sizeof(buf), fp)) {
+ if (strncasecmp(buf, "AVIIDX1", 7) == 0)
+ is_aviindex=1;
+ fseek(fp, 0, SEEK_SET);
+ } else {
+ tc_error("An error happend while reading the nav_seek file");
+ }
+
+ if (!is_aviindex) {
+ while (tmptime){
+ flag = 0;
+ for (; fgets(buf, sizeof(buf), fp); line_count++) {
+ int L, new_frame_a;
+
+ if (2 == sscanf(buf, "%*d %*d %*d %*d %d %d ", &L, &new_frame_a)) {
+ if (line_count == tmptime->stf) {
+ int len = tmptime->etf - tmptime->stf;
+ tmptime->stf = frame_a = new_frame_a;
+ tmptime->etf = frame_b = new_frame_a + len;
+ tmptime->vob_offset = L;
+ flag = 1;
+ line_count++;
+ break;
+ }
+ }
+ }
+ tmptime = tmptime->next;
+ }
+ } else { // is_aviindex==1
+ fgets(buf, sizeof(buf), fp); // magic
+ fgets(buf, sizeof(buf), fp); // comment
+
+ while (tmptime) {
+ int new_frame_a, type, key;
+ long chunk, chunkptype, last_keyframe = 0;
+ long long pos, len;
+ char tag[4];
+ double ms = 0.0;
+ flag = 0;
+
+ for (; fgets(buf, sizeof(buf), fp); line_count++) {
+ // TAG TYPE CHUNK CHUNK/TYPE POS LEN KEY MS
+ if (sscanf(buf, "%s %d %ld %ld %lld %lld %d %lf",
+ tag, &type, &chunk, &chunkptype, &pos, &len, &key, &ms)) {
+ if (type != 1)
+ continue;
+ if (key)
+ last_keyframe = chunkptype;
+ if (chunkptype == tmptime->stf) {
+ int lenf = tmptime->etf - tmptime->stf;
+ new_frame_a = chunkptype - last_keyframe;
+
+ // If we are doing pass-through, we cannot skip frames, but only start
+ // passthrough on a keyframe boundary. At least, we respect the
+ // last frame the user whishes.
+ if (vob->pass_flag & TC_VIDEO) {
+ new_frame_a = 0;
+ lenf += (chunkptype - last_keyframe);
+ }
+
+ tmptime->stf = frame_a = new_frame_a;
+ tmptime->etf = frame_b = new_frame_a + lenf;
+ tmptime->vob_offset = last_keyframe;
+ flag = 1;
+ line_count++;
+ break;
+ }
+ }
+ }
+ tmptime = tmptime->next;
+ }
+ }
+ fclose(fp);
+
+ if (!flag) {
+ //frame not found
+ tc_warn("%s: frame %d out of range (%d frames found)",
+ nav_seek_file, frame_a, line_count);
+ tc_error("invalid option parameter for -c / --nav_seek");
+ }
+ }
+}
+
+/*************************************************************************/
+
+static void setup_input_sources(vob_t *vob)
+{
+ if (vob->video_in_file == NULL && vob->audio_in_file == NULL)
+ tc_error("no input sources avalaible");
+ if (vob->audio_in_file == NULL)
+ vob->audio_in_file = vob->video_in_file;
+
+ /*
+ * let's try happily both sources independently.
+ * At least one will succeed, if we're here.
+ */
+ vob->video_in_files = tc_glob_open(vob->video_in_file, 0);
+ if (vob->video_in_files) {
+ /* we always have at least one source */
+ tc_next_video_in_file(vob);
+ }
+ if (!validate_source_path(vob->video_in_file)) {
+ tc_error("invalid input video file: %s", vob->video_in_file);
+ }
+
+ vob->audio_in_files = tc_glob_open(vob->audio_in_file, 0);
+ if (vob->audio_in_files) {
+ /* we always have at least one source */
+ tc_next_audio_in_file(vob);
+ }
+ if (!validate_source_path(vob->audio_in_file)) {
+ tc_error("invalid input audio file: %s", vob->audio_in_file);
+ }
+}
+
+static void teardown_input_sources(vob_t *vob)
+{
+ if (vob->video_in_files) {
+ tc_glob_close(vob->video_in_files);
+ vob->video_in_files = NULL;
+ }
+ if (vob->audio_in_files) {
+ tc_glob_close(vob->audio_in_files);
+ vob->audio_in_files = NULL;
+ }
+}
+
+/*************************************************************************/
+
+/* support macros */
+
+#define CLIP_CHECK(MODE, NAME, OPTION) do { \
+ /* force to even for YUV mode */ \
+ if (vob->im_v_codec == CODEC_YUV || vob->im_v_codec == CODEC_YUV422) { \
+ if (vob->MODE ## _left % 2 != 0) { \
+ tc_warn("left/right %s must be even in YUV/YUV422 mode", NAME); \
+ vob->MODE ## _left--; \
+ } \
+ if (vob->MODE ## _right % 2 != 0) { \
+ tc_warn("left/right %s must be even in YUV/YUV422 mode", NAME); \
+ vob->MODE ## _right--; \
+ } \
+ if (vob->im_v_codec == CODEC_YUV && vob->MODE ## _top % 2 != 0) { \
+ tc_warn("top/bottom %s must be even in YUV mode", NAME); \
+ vob->MODE ## _top--; \
+ } \
+ if (vob->im_v_codec == CODEC_YUV && vob->MODE ## _bottom % 2 != 0) { \
+ tc_warn("top/bottom %s must be even in YUV mode", NAME); \
+ vob->MODE ## _bottom--; \
+ } \
+ } \
+ /* check against import parameter, this is pre processing! */ \
+ if (vob->ex_v_height - vob->MODE ## _top - vob->MODE ## _bottom <= 0 \
+ || vob->ex_v_height - vob->MODE ## _top - vob->MODE ## _bottom > TC_MAX_V_FRAME_HEIGHT) \
+ tc_error("invalid top/bottom clip parameter for option %s", OPTION); \
+ \
+ if (vob->ex_v_width - vob->MODE ## _left - vob->MODE ## _right <= 0 \
+ || vob->ex_v_width - vob->MODE ## _left - vob->MODE ## _right > TC_MAX_V_FRAME_WIDTH) \
+ tc_error("invalid left/right clip parameter for option %s", OPTION); \
+ \
+ vob->ex_v_height -= (vob->MODE ## _top + vob->MODE ## _bottom); \
+ vob->ex_v_width -= (vob->MODE ## _left + vob->MODE ## _right); \
+} while (0)
+
+
+
+#define SHUTDOWN_MARK(STAGE) do { \
+ if (verbose & TC_DEBUG) { \
+ fprintf(stderr, " %s |", (STAGE)); \
+ fflush(stderr); \
+ } \
+} while (0)
+
+
+/*************************************************************************/
+
+/* common support data */
+
+typedef struct ratio_t {
+ int t, b;
+} ratio_t;
+
+static const ratio_t asrs[] = {
+ { 1, 1 }, { 1, 1 }, { 4, 3 }, { 16, 9 },
+ { 221, 100 }, { 250, 100 }, { 125, 100 }
+};
+
+static const char *demuxer_desc[] = {
+ "sync AV at PTS start - demuxer disabled",
+ "sync AV at initial MPEG sequence",
+ "initial MPEG sequence / enforce frame rate",
+ "sync AV at initial PTS",
+ "initial PTS / enforce frame rate",
+};
+
+static const char *deinterlace_desc[] = {
+ "disabled", /* never used */
+ "interpolate scanlines (fast)",
+ "handled by encoder (if available)",
+ "zoom to full frame (slow)",
+ "drop field / half height (fast)",
+ "interpolate scanlines / blend frames",
+
+};
+
+ static const char *antialias_desc[] = {
+ "disabled", /* never used */
+ "de-interlace effects only",
+ "resize effects only",
+ "process full frame (slow)"
+};
+
+
+/**
+ * main: transcode main routine. Performs initialization, parses command
+ * line options, and calls the transcoding routines.
+ *
+ * Parameters:
+ * argc: Command line argument count.
+ * argv: Command line argument vector.
+ * Return value:
+ * Zero on success, nonzero on error (exit code).
+ */
+
+int main(int argc, char *argv[])
+{
+ sigset_t sigs_to_block;
+
+ const char *psubase = NULL;
+
+ double fch, asr;
+ int leap_bytes1, leap_bytes2;
+ int max_frame_buffer = TC_FRAME_BUFFER;
+
+ struct fc_time *tstart = NULL;
+
+ TCFrameSpecs specs;
+
+ //main thread id
+ writepid = getpid();
+
+ /* ------------------------------------------------------------
+ *
+ * (I) set transcode defaults:
+ *
+ * ------------------------------------------------------------ */
+
+ // create global vob structure
+ vob = new_vob();
+ if (!vob) {
+ tc_error("data initialization failed");
+ }
+
+ // prepare for signal catching
+ sigemptyset(&sigs_to_block);
+ sigaddset(&sigs_to_block, SIGINT);
+ sigaddset(&sigs_to_block, SIGTERM);
+ // enabling this breaks the import_vob module.
+ //sigaddset(&sigs_to_block, SIGPIPE);
+ pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL);
+
+ // start of the signal handler thread is delayed later
+
+ // close all threads at exit
+ atexit(stop_event_thread);
+
+ /* ------------------------------------------------------------
+ *
+ * (II) parse command line
+ *
+ * ------------------------------------------------------------ */
+
+ /*
+ * A *FEW* special options that deserve separate treatment.
+ * PLEASE keep VERY LOW the number of this special cases.
+ */
+ libtc_init(&argc, &argv);
+
+ if (!parse_cmdline(argc, argv, vob))
+ exit(EXIT_FAILURE);
+
+ setup_input_sources(vob);
+
+ if (tc_progress_meter < 0) {
+ // if we have verbosity disabled, default to no progress meter.
+ if (verbose) {
+ tc_progress_meter = 1;
+ } else {
+ tc_progress_meter = 0;
+ }
+ }
+
+ if (psu_mode) {
+ if (vob->video_out_file == NULL)
+ tc_error("please specify output file name for psu mode");
+ if (!strchr(vob->video_out_file, '%') && !no_split) {
+ char *pc = tc_malloc(PATH_MAX);
+ char *suffix = strrchr(vob->video_out_file, '.');
+ if (suffix) {
+ *suffix = '\0';
+ } else {
+ suffix = "";
+ }
+ tc_snprintf(pc, PATH_MAX, "%s-psu%%02d%s",
+ vob->video_out_file, suffix);
+ psubase = pc;
+ } else {
+ psubase = vob->video_out_file;
+ }
+ }
+
+ // user doesn't want to start at all;-(
+ if (tc_interrupted())
+ goto summary;
+
+ // display program version
+ if (verbose)
+ version();
+
+ if (tc_niceness) {
+ if (nice(tc_niceness) < 0) {
+ tc_warn("setting nice to %d failed", tc_niceness);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ *
+ * (III) auto probe properties of input stream
+ *
+ * ------------------------------------------------------------ */
+
+ if (auto_probe) {
+ // interface to "tcprobe"
+ int result = probe_source(vob->video_in_file, vob->audio_in_file, seek_range,
+ preset_flag, vob);
+ if (verbose) {
+ tc_log_info(PACKAGE, "V: %-16s | %s (%s)", "auto-probing",
+ (vob->video_in_file != NULL) ?vob->video_in_file :"N/A",
+ result ? "OK" : "FAILED");
+ tc_log_info(PACKAGE, "V: %-16s | %s in %s (module=%s)",
+ "import format",
+ tc_codec_to_comment(vob->v_codec_flag),
+ mformat2str(vob->v_format_flag),
+ no_vin_codec == 0 ? im_vid_mod : vob->vmod_probed);
+ tc_log_info(PACKAGE, "A: %-16s | %s (%s)", "auto-probing",
+ (vob->audio_in_file != NULL) ?vob->audio_in_file :"N/A",
+ result ? "OK" : "FAILED");
+ tc_log_info(PACKAGE, "A: %-16s | %s in %s (module=%s)",
+ "import format",
+ tc_codec_to_comment(vob->a_codec_flag),
+ mformat2str(vob->a_format_flag),
+ no_ain_codec==0 ? im_aud_mod : vob->amod_probed);
+ }
+ }
+
+ if (vob->vmod_probed_xml && strstr(vob->vmod_probed_xml, "xml") != NULL
+ && vob->video_in_file) {
+ if (!probe_source_xml(vob, PROBE_XML_VIDEO))
+ tc_error("failed to probe video XML source");
+ }
+ if (vob->amod_probed_xml && strstr(vob->amod_probed_xml, "xml") != NULL
+ && vob->audio_in_file) {
+ if (!probe_source_xml(vob, PROBE_XML_AUDIO))
+ tc_error("failed to probe audio XML source");
+ }
+
+ /* ------------------------------------------------------------
+ *
+ * (IV) autosplit stream for cluster processing
+ *
+ * currently, only VOB streams are supported
+ *
+ * ------------------------------------------------------------*/
+
+ // set up ttime from -c or default
+ if (fc_ttime_string) {
+ // FIXME: should be in -c handler, but we need to know vob->fps first
+ free_fc_time(vob->ttime);
+ if (parse_fc_time_string(fc_ttime_string, vob->fps, ",",
+ (verbose>1 ? 1 : 0), &vob->ttime) == -1)
+ tc_error("error parsing time specifications");
+ } else {
+ vob->ttime = new_fc_time();
+ vob->ttime->fps = vob->fps;
+ vob->ttime->stf = TC_FRAME_FIRST;
+ vob->ttime->etf = TC_FRAME_LAST;
+ vob->ttime->next = NULL;
+ }
+ frame_a = vob->ttime->stf;
+ frame_b = vob->ttime->etf;
+ vob->ttime->vob_offset = 0;
+ tstart = vob->ttime;
+ counter_on(); //activate
+
+ // determine -S,-c,-L option parameter for distributed processing
+ parse_navigation_file(vob, nav_seek_file);
+
+ if (vob->vob_chunk_max) {
+ int this_unit = -1;
+
+ // overwrite tcprobe's unit preset:
+ if (preset_flag & TC_PROBE_NO_SEEK)
+ this_unit = vob->ps_unit;
+
+ if (split_stream(vob, vob->vob_info_file, this_unit, &frame_a, &frame_b, 1) < 0)
+ tc_error("cluster mode option -W error");
+ }
+
+ /* ------------------------------------------------------------
+ *
+ * some sanity checks for command line parameters
+ *
+ * ------------------------------------------------------------*/
+
+ // -M
+ if (vob->demuxer == -1) {
+ vob->demuxer = 1;
+ }
+ if (verbose & TC_INFO) {
+ tc_log_info(PACKAGE, "V: %-16s | (%i) %s", "AV demux/sync",
+ vob->demuxer, demuxer_desc[vob->demuxer]);
+ }
+
+ // -P
+ if (vob->pass_flag & TC_VIDEO) {
+ vob->im_v_codec = (vob->im_v_codec == CODEC_YUV) ?CODEC_RAW_YUV :CODEC_RAW;
+ vob->ex_v_codec = CODEC_RAW;
+
+ // suggestion:
+ if (no_v_out_codec)
+ ex_vid_mod = "raw";
+ no_v_out_codec = 0;
+
+ if (no_a_out_codec)
+ ex_aud_mod = "raw";
+ no_a_out_codec = 0;
+
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "V: %-16s | yes", "pass-through");
+ }
+
+ // -x
+ if (no_vin_codec && vob->video_in_file != NULL && vob->vmod_probed == NULL)
+ tc_error("module autoprobe failed, no option -x found");
+
+
+ //overwrite results of autoprobing if modules are provided
+ if (no_vin_codec && vob->vmod_probed!=NULL) {
+ im_vid_mod = (char *)vob->vmod_probed_xml;
+ //need to load the correct module if the input file type is xml
+ }
+
+ if (no_ain_codec && vob->amod_probed!=NULL) {
+ im_aud_mod = (char *)vob->amod_probed_xml;
+ //need to load the correct module if the input file type is xml
+ }
+
+ // make zero frame size default for no video
+ if (im_vid_mod != NULL && strcmp(im_vid_mod, "null") == 0) {
+ vob->im_v_width = 0;
+ vob->im_v_height = 0;
+ }
+
+ //initial aspect ratio
+ asr = (double) vob->im_v_width/vob->im_v_height;
+
+ // -g
+
+ // import size
+ // force to even for YUV mode
+ if (vob->im_v_codec == CODEC_YUV || vob->im_v_codec == CODEC_YUV422) {
+ if (vob->im_v_width % 2 != 0) {
+ tc_warn("frame width must be even in YUV/YUV422 mode");
+ vob->im_v_width--;
+ }
+ if (vob->im_v_codec == CODEC_YUV && vob->im_v_height % 2 != 0) {
+ tc_warn("frame height must be even in YUV mode");
+ vob->im_v_height--;
+ }
+ }
+ if (verbose & TC_INFO) {
+ if (vob->im_v_width && vob->im_v_height) {
+ tc_log_info(PACKAGE, "V: %-16s | %03dx%03d %4.2f:1 %s",
+ "import frame", vob->im_v_width, vob->im_v_height,
+ asr, tc_asr_code_describe(vob->im_asr));
+ } else {
+ tc_log_info(PACKAGE, "V: %-16s | disabled", "import frame");
+ }
+ }
+
+ // init frame size with cmd line frame size
+ vob->ex_v_height = vob->im_v_height;
+ vob->ex_v_width = vob->im_v_width;
+
+ // import bytes per frame (RGB 24bits)
+ vob->im_v_size = vob->im_v_height * vob->im_v_width * BPP/8;
+ // export bytes per frame (RGB 24bits)
+ vob->ex_v_size = vob->im_v_size;
+
+ // calc clip settings for encoding to mpeg (vcd,svcd,xvcd,dvd)
+ // --export_prof {vcd,vcd-pal,vcd-ntsc,svcd,svcd-pal,svcd-ntsc,dvd,dvd-pal,dvd-ntsc}
+
+ if (vob->mpeg_profile != PROF_NONE) {
+ ratio_t imasr = asrs[0];
+ ratio_t exasr = asrs[0];
+
+ int impal = 0;
+ int pre_clip;
+
+ // Make an educated guess if this is pal or ntsc
+ switch (vob->mpeg_profile) {
+ case VCD:
+ case SVCD:
+ case XVCD:
+ case DVD:
+ if (vob->im_v_height == 288 || vob->im_v_height == 576)
+ impal = 1;
+ if ((int)vob->fps == 25 || vob->im_frc == 3)
+ impal = 1;
+ break;
+ case VCD_PAL:
+ case SVCD_PAL:
+ case XVCD_PAL:
+ case DVD_PAL:
+ impal = 1;
+ break;
+ default:
+ break;
+ }
+
+ // choose height dependent on pal or NTSC.
+ switch (vob->mpeg_profile) {
+ case VCD:
+ case VCD_PAL:
+ case VCD_NTSC:
+ if (!vob->zoom_height)
+ vob->zoom_height = impal ?288 :240;
+ break;
+
+ case SVCD:
+ case SVCD_PAL:
+ case SVCD_NTSC:
+ case XVCD:
+ case XVCD_PAL:
+ case XVCD_NTSC:
+ case DVD:
+ case DVD_PAL:
+ case DVD_NTSC:
+ if (!vob->zoom_height)
+ vob->zoom_height = impal ?576 :480;
+ break;
+
+ default:
+ break;
+ }
+
+ // choose width if not set by user.
+ switch (vob->mpeg_profile) {
+ case VCD:
+ case VCD_PAL:
+ case VCD_NTSC:
+ if (!vob->zoom_width)
+ vob->zoom_width = 352;
+ vob->ex_asr = 2;
+ break;
+ case SVCD:
+ case SVCD_PAL:
+ case SVCD_NTSC:
+ case XVCD:
+ case XVCD_PAL:
+ case XVCD_NTSC:
+ if (!vob->zoom_width)
+ vob->zoom_width = 480;
+ vob->ex_asr = 2;
+ break;
+ case DVD:
+ case DVD_PAL:
+ case DVD_NTSC:
+ if (!vob->zoom_width)
+ vob->zoom_width = 720;
+ if (vob->ex_asr <= 0)
+ vob->ex_asr = 2; // assume 4:3
+ break;
+ default:
+ break;
+ }
+
+ // an input file without any aspect ratio setting (an AVI maybe?)
+ // so make a guess.
+
+ if (vob->im_asr == 0) {
+ int i, mini=0;
+ const ratio_t *r = &asrs[1];
+ double diffs[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+ double mindiff = 2.0;
+
+ for (i = 0; i < 6; i++) {
+ diffs[i] = (double)(r->b*vob->im_v_width) / (double)(r->t*vob->im_v_height);
+ r++;
+ }
+
+ // look for the diff which is closest to 1.0
+
+ for (i = 0; i < 6; i++) {
+ double a = fabs(1.0 - diffs[i]);
+ if (a < mindiff) {
+ mindiff = a;
+ mini = i+1;
+ }
+ }
+ vob->im_asr = mini;
+ }
+
+ imasr = asrs[vob->im_asr];
+ exasr = asrs[vob->ex_asr];
+
+ pre_clip = vob->im_v_height - (vob->im_v_height * imasr.t * exasr.b ) / (imasr.b * exasr.t );
+
+ if (pre_im_clip == TC_FALSE) {
+ if (pre_clip % 2 != 0) {
+ vob->pre_im_clip_top = pre_clip/2+1;
+ vob->pre_im_clip_bottom = pre_clip/2-1;
+ } else {
+ vob->pre_im_clip_bottom = vob->pre_im_clip_top = pre_clip/2;
+ }
+ if (vob->pre_im_clip_top % 2 != 0 || vob->pre_im_clip_bottom % 2 != 0) {
+ vob->pre_im_clip_top--;
+ vob->pre_im_clip_bottom++;
+ }
+ }
+
+ //FIXME hack, kludge, etc. EMS
+ if ((vob->im_v_height != vob->zoom_height)
+ || ((vob->im_v_width != vob->zoom_width) && (vob->ex_v_width != 704)))
+ zoom = TC_TRUE;
+ else
+ zoom = TC_FALSE;
+
+ if (pre_clip) pre_im_clip = TC_TRUE;
+
+ // shall we really go this far?
+ // If yes, there can be much more settings adjusted.
+ if (ex_vid_mod == NULL || !strcmp(ex_vid_mod, "mpeg2enc")) {
+#ifdef HAVE_MJPEGTOOLS
+ if (!ex_aud_mod)
+ ex_aud_mod = "mp2enc";
+ no_v_out_codec = 0;
+ ex_vid_mod = "mpeg2enc";
+ //FIXME this should be in export_mpeg2enc.c
+ if (!vob->ex_v_fcc) {
+ switch (vob->mpeg_profile) {
+ case VCD:
+ case VCD_PAL:
+ case VCD_NTSC:
+ vob->ex_v_fcc = "1";
+ break;
+ case SVCD:
+ case SVCD_PAL:
+ case SVCD_NTSC:
+ case XVCD:
+ case XVCD_PAL:
+ case XVCD_NTSC:
+ vob->ex_v_fcc = "4";
+ break;
+ case DVD:
+ case DVD_PAL:
+ case DVD_NTSC:
+ vob->ex_v_fcc = "8";
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+ } else if(!strcmp(ex_vid_mod, "ffmpeg")) {
+ if (!ex_aud_mod)
+ ex_aud_mod = "ffmpeg";
+ switch (vob->mpeg_profile) {
+ case VCD:
+ vob->ex_v_fcc = "vcd";
+ break;
+ case VCD_PAL:
+ vob->ex_v_fcc = "vcd-pal";
+ break;
+ case VCD_NTSC:
+ vob->ex_v_fcc = "vcd-ntsc";
+ break;
+ case SVCD:
+ vob->ex_v_fcc = "svcd";
+ break;
+ case SVCD_PAL:
+ vob->ex_v_fcc = "svcd-pal";
+ break;
+ case SVCD_NTSC:
+ vob->ex_v_fcc = "svcd-ntsc";
+ break;
+ case XVCD:
+ vob->ex_v_fcc = "xvcd";
+ break;
+ case XVCD_PAL:
+ vob->ex_v_fcc = "xvcd-pal";
+ break;
+ case XVCD_NTSC:
+ vob->ex_v_fcc = "xvcd-ntsc";
+ break;
+ case DVD:
+ vob->ex_v_fcc = "dvd";
+ break;
+ case DVD_PAL:
+ vob->ex_v_fcc = "dvd-pal";
+ break;
+ case DVD_NTSC:
+ vob->ex_v_fcc = "dvd-ntsc";
+ break;
+ case PROF_NONE:
+ break;
+ }
+ } // ffmpeg
+
+ if (ex_aud_mod == NULL) {
+#ifdef HAVE_MJPEGTOOLS
+ no_a_out_codec=0;
+ ex_aud_mod = "mp2enc";
+#endif
+ }
+ } // mpeg_profile != PROF_NONE
+
+
+ // --PRE_CLIP
+ if (pre_im_clip) {
+ CLIP_CHECK(pre_im_clip, "pre_clip", "--pre_clip");
+
+ if (verbose & TC_INFO) {
+ tc_log_info(PACKAGE, "V: %-16s | %03dx%03d (%d,%d,%d,%d)",
+ "pre clip frame", vob->ex_v_width, vob->ex_v_height,
+ vob->pre_im_clip_top, vob->pre_im_clip_left,
+ vob->pre_im_clip_bottom, vob->pre_im_clip_right);
+ }
+ }
+
+ // -j
+ if (im_clip) {
+ CLIP_CHECK(im_clip, "clip", "-j");
+
+ if (verbose & TC_INFO) {
+ tc_log_info(PACKAGE, "V: %-16s | %03dx%03d", "clip frame (<-)",
+ vob->ex_v_width, vob->ex_v_height);
+ }
+ }
+
+ // -I
+ /* can this really happen? */
+ if (vob->deinterlace < 0 || vob->deinterlace > 5) {
+ tc_error("invalid parameter for option -I");
+ }
+
+ if ((verbose & TC_INFO) && vob->deinterlace) {
+ tc_log_info(PACKAGE,
+ "V: %-16s | (mode=%i) %s",
+ "de-interlace", vob->deinterlace,
+ deinterlace_desc[vob->deinterlace]);
+ }
+
+ if (vob->deinterlace == 4)
+ vob->ex_v_height /= 2;
+
+ // Calculate the missing w or h based on the ASR
+ if (zoom && (vob->zoom_width == 0 || vob->zoom_height == 0)) {
+ enum missing_t { NONE, CALC_W, CALC_H, ALL } missing = ALL;
+ ratio_t asr = asrs[0];
+ float oldr;
+
+ // check if we have at least on width or height
+ if (vob->zoom_width == 0 && vob->zoom_height == 0)
+ missing = ALL;
+ else if (vob->zoom_width == 0 && vob->zoom_height > 0)
+ missing = CALC_W;
+ else if (vob->zoom_width > 0 && vob->zoom_height == 0)
+ missing = CALC_H;
+ else if (vob->zoom_width > 0 && vob->zoom_height > 0)
+ missing = NONE;
+
+ // try import
+ if (vob->im_asr > 0 && vob->im_asr < 5)
+ asr = asrs[vob->im_asr];
+ // try the export aspectratio
+ else if (vob->ex_asr > 0 && vob->ex_asr < 5)
+ asr = asrs[vob->ex_asr];
+
+ switch (missing) {
+ case ALL:
+ tc_error("Neither zoom width nor height set, can't guess anything");
+ case CALC_W:
+ vob->zoom_width = vob->zoom_height * asr.t; vob->zoom_width /= asr.b;
+ break;
+ case CALC_H:
+ vob->zoom_height = vob->zoom_width * asr.b; vob->zoom_height /= asr.t;
+ break;
+ case NONE:
+ default:
+ /* can't happen */
+ break;
+ }
+
+ // for error printout
+ oldr = (float)vob->zoom_width/(float)vob->zoom_height;
+
+ // align
+ if (vob->zoom_height % 8 != 0)
+ vob->zoom_height += 8-(vob->zoom_height%8);
+ if (vob->zoom_width % 8 != 0)
+ vob->zoom_width += 8-(vob->zoom_width%8);
+ oldr = ((float)vob->zoom_width/(float)vob->zoom_height-oldr)*100.0;
+ oldr = oldr<0?-oldr:oldr;
+
+ tc_log_info(PACKAGE, "V: %-16s | %03dx%03d %4.2f:1 error %.2f%%",
+ "auto resize", vob->zoom_width, vob->zoom_height,
+ (float)vob->zoom_width/(float)vob->zoom_height, oldr);
+ }
+
+ // -Z ...,fast
+ if (fast_resize) {
+ int ret = tc_compute_fast_resize_values(vob, TC_FALSE);
+ if (ret == 0) {
+ if (vob->hori_resize1 == 0 && vob->vert_resize1 == 0)
+ resize1 = TC_FALSE;
+ else
+ resize1 = TC_TRUE;
+ if (vob->hori_resize2 == 0 && vob->vert_resize2 == 0)
+ resize2 = TC_FALSE;
+ else
+ resize2 = TC_TRUE;
+
+ if (verbose & TC_INFO) {
+ tc_log_info(PACKAGE, "V: %-16s | Using -B %d,%d,8 -X %d,%d,8",
+ "fast resize",
+ vob->vert_resize1, vob->hori_resize1,
+ vob->vert_resize2, vob->hori_resize2);
+ }
+ zoom = TC_FALSE;
+ } else {
+ if(verbose & TC_INFO) {
+ tc_log_info(PACKAGE,
+ "V: %-16s | requested but can't be used (W or H mod 8 != 0)",
+ "fast resize");
+ }
+ }
+ }
+
+ // -X
+ if (resize2) {
+ if (vob->resize2_mult % 8 != 0)
+ tc_error("resize multiplier for option -X is not a multiple of 8");
+
+ // works only for frame dimension beeing an integral multiple of vob->resize2_mult:
+ if (vob->vert_resize2
+ && (vob->vert_resize2 * vob->resize2_mult + vob->ex_v_height) % vob->resize2_mult != 0)
+ tc_error("invalid frame height for option -X, check also option -j");
+
+ if (vob->hori_resize2
+ && (vob->hori_resize2 * vob->resize2_mult + vob->ex_v_width) % vob->resize2_mult != 0)
+ tc_error("invalid frame width for option -X, check also option -j");
+
+ vob->ex_v_height += (vob->vert_resize2 * vob->resize2_mult);
+ vob->ex_v_width += (vob->hori_resize2 * vob->resize2_mult);
+
+ //check2:
+
+ if (vob->ex_v_height > TC_MAX_V_FRAME_HEIGHT
+ || vob->ex_v_width >TC_MAX_V_FRAME_WIDTH)
+ tc_error("invalid resize parameter for option -X");
+
+ if (vob->vert_resize2 <0 || vob->hori_resize2 < 0)
+ tc_error("invalid resize parameter for option -X");
+
+ // new aspect ratio:
+ asr *= (double) vob->ex_v_width * (vob->ex_v_height - vob->vert_resize2*vob->resize2_mult)/
+ ((vob->ex_v_width - vob->hori_resize2*vob->resize2_mult) * vob->ex_v_height);
+
+ vob->vert_resize2 *= (vob->resize2_mult/8);
+ vob->hori_resize2 *= (vob->resize2_mult/8);
+
+ if (verbose & TC_INFO && vob->ex_v_height > 0)
+ tc_log_info(PACKAGE,
+ "V: %-16s | %03dx%03d %4.2f:1 (-X)",
+ "new aspect ratio",
+ vob->ex_v_width, vob->ex_v_height, asr);
+ }
+
+ // -B
+ if (resize1) {
+ if (vob->resize1_mult % 8 != 0)
+ tc_error("resize multiplier for option -B is not a multiple of 8");
+
+ // works only for frame dimension beeing an integral multiple of vob->resize1_mult:
+ if (vob->vert_resize1
+ && (vob->ex_v_height - vob->vert_resize1*vob->resize1_mult) % vob->resize1_mult != 0)
+ tc_error("invalid frame height for option -B, check also option -j");
+
+ if (vob->hori_resize1
+ && (vob->ex_v_width - vob->hori_resize1*vob->resize1_mult) % vob->resize1_mult != 0)
+ tc_error("invalid frame width for option -B, check also option -j");
+
+ vob->ex_v_height -= (vob->vert_resize1 * vob->resize1_mult);
+ vob->ex_v_width -= (vob->hori_resize1 * vob->resize1_mult);
+
+ //check:
+ if (vob->vert_resize1 < 0 || vob->hori_resize1 < 0)
+ tc_error("invalid resize parameter for option -B");
+
+ //new aspect ratio:
+ asr *= (double) vob->ex_v_width * (vob->ex_v_height + vob->vert_resize1*vob->resize1_mult)/
+ ((vob->ex_v_width + vob->hori_resize1*vob->resize1_mult) * vob->ex_v_height);
+
+ vob->vert_resize1 *= (vob->resize1_mult/8);
+ vob->hori_resize1 *= (vob->resize1_mult/8);
+
+ if (verbose & TC_INFO && vob->ex_v_height > 0)
+ tc_log_info(PACKAGE,
+ "V: %-16s | %03dx%03d %4.2f:1 (-B)",
+ "new aspect ratio",
+ vob->ex_v_width, vob->ex_v_height, asr);
+ }
+
+ // -Z
+ if (zoom) {
+ // new aspect ratio:
+ asr *= (double) vob->zoom_width*vob->ex_v_height/(vob->ex_v_width * vob->zoom_height);
+
+ vob->ex_v_width = vob->zoom_width;
+ vob->ex_v_height = vob->zoom_height;
+
+ if (verbose & TC_INFO && vob->ex_v_height > 0)
+ tc_log_info(PACKAGE,
+ "V: %-16s | %03dx%03d %4.2f:1 (%s)",
+ "zoom",
+ vob->ex_v_width, vob->ex_v_height, asr,
+ tcv_zoom_filter_to_string(vob->zoom_filter));
+ }
+
+ // -Y
+ if (ex_clip) {
+ CLIP_CHECK(ex_clip, "clip", "-Y");
+
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "V: %-16s | %03dx%03d", "clip frame (->)",
+ vob->ex_v_width, vob->ex_v_height);
+ }
+
+ // -r
+ if (rescale) {
+ vob->ex_v_height /= vob->reduce_h;
+ vob->ex_v_width /= vob->reduce_w;
+
+ //new aspect ratio:
+ asr *= (double)vob->ex_v_width/vob->ex_v_height*(vob->reduce_h*vob->ex_v_height)/
+ (vob->reduce_w*vob->ex_v_width);
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "V: %-16s | %03dx%03d %4.2f:1 (-r)",
+ "rescale frame",
+ vob->ex_v_width, vob->ex_v_height,asr);
+
+ // sanity check for YUV
+ if (vob->im_v_codec == CODEC_YUV || vob->im_v_codec == CODEC_YUV422) {
+ if (vob->ex_v_width%2 != 0 || (vob->im_v_codec == CODEC_YUV && vob->ex_v_height % 2 != 0)) {
+ tc_error("rescaled width/height must be even for YUV mode, try -V rgb24");
+ }
+ }
+ }
+
+ // --keep_asr
+ if (keepasr) {
+ int clip, zoomto;
+ double asr_out = (double)vob->ex_v_width/(double)vob->ex_v_height;
+ double asr_in = (double)vob->im_v_width/(double)vob->im_v_height;
+ double delta = 0.01;
+ double asr_cor = 1.0;
+
+
+ if (vob->im_asr) {
+ switch (vob->im_asr) {
+ case 1:
+ asr_cor = (1.0);
+ break;
+ case 2:
+ asr_cor = (4.0/3.0);
+ break;
+ case 3:
+ asr_cor = (16.0/9.0);
+ break;
+ case 4:
+ asr_cor = (2.21);
+ break;
+ }
+ }
+
+ if (!zoom)
+ tc_error ("keep_asr only works with -Z");
+
+ if (asr_in-delta < asr_out && asr_out < asr_in+delta)
+ tc_error ("Aspect ratios are too similar, don't use --keep_asr ");
+
+ if (asr_in > asr_out) {
+ /* adjust height */
+ int clipV = (vob->im_clip_top +vob->im_clip_bottom);
+ int clipH = (vob->im_clip_left+vob->im_clip_right);
+ int clip1 = 0;
+ int clip2 = 0;
+
+ zoomto = (int)((double)(vob->ex_v_width) /
+ ( ((double)(vob->im_v_width -clipH) / (vob->im_v_width/asr_cor/vob->im_v_height) )/
+ (double)(vob->im_v_height-clipV))+.5);
+ clip = vob->ex_v_height - zoomto;
+ if (zoomto % 2 != 0)
+ (clip>0?zoomto--:zoomto++); // XXX
+ clip = vob->ex_v_height - zoomto;
+ clip /= 2;
+ clip1 = clip2 = clip;
+
+ if (clip & 1) {
+ clip1--;
+ clip2++;
+ }
+ ex_clip = TC_TRUE;
+ vob->ex_clip_top = -clip1;
+ vob->ex_clip_bottom = -clip2;
+
+ vob->zoom_height = zoomto;
+ } else {
+ /* adjust width */
+ int clipV = (vob->im_clip_top +vob->im_clip_bottom);
+ int clipH = (vob->im_clip_left+vob->im_clip_right);
+ int clip1 = 0;
+ int clip2 = 0;
+ zoomto = (int)((double)vob->ex_v_height * (
+ ( ((double)(vob->im_v_width-clipH)) / (vob->im_v_width/asr_cor/vob->im_v_height) ) /
+ (double)(vob->im_v_height-clipV)) +.5);
+
+ clip = vob->ex_v_width - zoomto;
+
+ if (zoomto % 2 != 0)
+ (clip>0?zoomto--:zoomto++); // XXX
+ clip = vob->ex_v_width - zoomto;
+ clip /= 2;
+ clip1 = clip2 = clip;
+
+ if (clip & 1) {
+ clip1--;
+ clip2++;
+ }
+ ex_clip = TC_TRUE;
+ vob->ex_clip_left = -clip1;
+ vob->ex_clip_right = -clip2;
+
+ vob->zoom_width = zoomto;
+ }
+
+ if (vob->ex_v_height - vob->ex_clip_top - vob->ex_clip_bottom <= 0)
+ tc_error("invalid top/bottom clip parameter calculated from --keep_asr");
+
+ if (vob->ex_v_width - vob->ex_clip_left - vob->ex_clip_right <= 0)
+ tc_error("invalid left/right clip parameter calculated from --keep_asr");
+
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "V: %-16s | yes (%d,%d,%d,%d)", "keep aspect",
+ vob->ex_clip_top, vob->ex_clip_left,
+ vob->ex_clip_bottom, vob->ex_clip_right);
+ }
+
+ // -z
+
+ if (flip && verbose & TC_INFO)
+ tc_log_info(PACKAGE, "V: %-16s | yes", "flip frame");
+
+ // -l
+ if (mirror && verbose & TC_INFO)
+ tc_log_info(PACKAGE, "V: %-16s | yes", "mirror frame");
+
+ // -k
+ if (rgbswap && verbose & TC_INFO)
+ tc_log_info(PACKAGE, "V: %-16s | yes", "rgb2bgr");
+
+ // -K
+ if (decolor && verbose & TC_INFO)
+ tc_log_info(PACKAGE, "V: %-16s | yes", "b/w reduction");
+
+ // -G
+ if (dgamma && verbose & TC_INFO)
+ tc_log_info(PACKAGE, "V: %-16s | %.3f", "gamma correction", vob->gamma);
+
+ // number of bits/pixel
+ //
+ // Christoph Lampert writes in transcode-users/2002-July/003670.html
+ // B*1000 B*1000*asr
+ // bpp = --------; W^2 = ------------
+ // W*H*F bpp * F
+ // If this number is less than 0.15, you will
+ // most likely see visual artefacts (e.g. in high motion scenes). If you
+ // reach 0.2 or more, the visual quality normally is rather good.
+ // For my tests, this corresponded roughly to a fixed quantizer of 4,
+ // which is not brilliant, but okay.
+
+ if (vob->divxbitrate > 0 && vob->divxmultipass != 3
+ && verbose & TC_INFO) {
+ double div = vob->ex_v_width * vob->ex_v_height * vob->fps;
+ double bpp = vob->divxbitrate * 1000;
+ const char *judge = "";
+
+ if (div < 1.0)
+ bpp = 0.0;
+ else
+ bpp /= div;
+
+ if (bpp <= 0.0)
+ judge = " (unknown)";
+ else if (bpp > 0.0 && bpp <= 0.15)
+ judge = " (low)";
+
+ tc_log_info(PACKAGE, "V: %-16s | %.3f%s", "bits/pixel", bpp, judge);
+ }
+
+ // -C
+ if (vob->antialias < 0 || vob->antialias > 3) {
+ tc_error("invalid parameter for option -C");
+ } else {
+ if ((verbose & TC_INFO) && vob->antialias) {
+ tc_log_info(PACKAGE,
+ "V: %-16s | (mode=%d|%.2f|%.2f) %s",
+ "anti-alias",
+ vob->antialias, vob->aa_weight, vob->aa_bias,
+ antialias_desc[vob->antialias]);
+ }
+ }
+
+ // --POST_CLIP
+
+ if (post_ex_clip) {
+ CLIP_CHECK(post_ex_clip, "post_clip", "--post_clip");
+
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "V: %-16s | %03dx%03d",
+ "post clip frame",
+ vob->ex_v_width, vob->ex_v_height);
+ }
+
+
+ // -W
+ if (vob->vob_percentage) {
+ if (vob->vob_chunk < 0 || vob->vob_chunk < 0)
+ tc_error("invalid parameter for option -W");
+ } else {
+ if (vob->vob_chunk < 0 || vob->vob_chunk > vob->vob_chunk_max + 1)
+ tc_error("invalid parameter for option -W");
+ }
+
+ // -f
+
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "V: %-16s | %.3f,%d",
+ "decoding fps,frc",
+ vob->fps, vob->im_frc);
+
+ // -R
+ if (vob->divxmultipass && verbose & TC_INFO) {
+ switch (vob->divxmultipass) {
+ case 1:
+ tc_log_info(PACKAGE,
+ "V: %-16s | (mode=%d) %s %s",
+ "multi-pass",
+ vob->divxmultipass,
+ "writing data (pass 1) to",
+ vob->divxlogfile);
+ break;
+ case 2:
+ tc_log_info(PACKAGE,
+ "V: %-16s | (mode=%d) %s %s",
+ "multi-pass",
+ vob->divxmultipass,
+ "reading data (pass2) from",
+ vob->divxlogfile);
+ break;
+ case 3:
+ if (vob->divxbitrate > VMAXQUANTIZER)
+ vob->divxbitrate = VQUANTIZER;
+ tc_log_info(PACKAGE,
+ "V: %-16s | (mode=%d) %s (quant=%d)",
+ "single-pass",
+ vob->divxmultipass,
+ "constant quantizer/quality",
+ vob->divxbitrate);
+ break;
+ }
+ }
+
+ // export frame size final check
+ if (vob->ex_v_height < 0 || vob->ex_v_width < 0) {
+ tc_warn("invalid export frame combination %dx%d", vob->ex_v_width, vob->ex_v_height);
+ tc_error("invalid frame processing requested");
+ }
+
+ // -V
+ if (vob->im_v_codec == CODEC_YUV) {
+ vob->ex_v_size = (3*vob->ex_v_height * vob->ex_v_width)>>1;
+ vob->im_v_size = (3*vob->im_v_height * vob->im_v_width)>>1;
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "V: %-16s | YUV420 (4:2:0) aka I420",
+ "video format");
+ } else if (vob->im_v_codec == CODEC_YUV422) {
+ vob->ex_v_size = (2*vob->ex_v_height * vob->ex_v_width);
+ vob->im_v_size = (2*vob->im_v_height * vob->im_v_width);
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "V: %-16s | YUV422 (4:2:2)",
+ "video format");
+ } else {
+ vob->ex_v_size = vob->ex_v_height * vob->ex_v_width * BPP/8;
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "V: %-16s | RGB24",
+ "video format");
+ }
+
+ // -m
+ // different audio/video output files not yet supported
+ if (vob->audio_out_file == NULL)
+ vob->audio_out_file = vob->video_out_file;
+
+ // -n
+ if (no_ain_codec == 1 && vob->has_audio == 0
+ && vob->a_codec_flag == CODEC_AC3) {
+ if (vob->amod_probed == NULL || strcmp(vob->amod_probed,"null") == 0) {
+ if (verbose & TC_DEBUG)
+ tc_log_warn(PACKAGE,
+ "problems detecting audio format - using 'null' module");
+ vob->a_codec_flag = 0;
+ }
+ }
+
+ if (preset_flag & TC_PROBE_NO_TRACK) {
+ //tracks specified by user
+ } else {
+ if (!vob->has_audio_track && vob->has_audio) {
+ tc_warn("requested audio track %d not found - using 'null' module", vob->a_track);
+ vob->a_codec_flag = 0;
+ }
+ }
+
+ //audio import disabled
+ if (vob->a_codec_flag == 0) {
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "A: %-16s | disabled", "import");
+ im_aud_mod = "null";
+ } else {
+ //audio format, if probed sucessfully
+ if (verbose & TC_INFO) {
+ if (vob->a_stream_bitrate)
+ tc_log_info(PACKAGE,
+ "A: %-16s | 0x%-5lx %-12s [%4d,%2d,%1d] %4d kbps",
+ "import format",
+ vob->a_codec_flag,
+ tc_codec_to_comment(vob->a_codec_flag),
+ vob->a_rate, vob->a_bits, vob->a_chan,
+ vob->a_stream_bitrate);
+ else
+ tc_log_info(PACKAGE,
+ "A: %-16s | 0x%-5lx %-12s [%4d,%2d,%1d]",
+ "import format",
+ vob->a_codec_flag,
+ tc_codec_to_comment(vob->a_codec_flag),
+ vob->a_rate, vob->a_bits, vob->a_chan);
+ }
+ }
+
+ if (vob->im_a_codec == CODEC_PCM && vob->a_chan > 2 && !(vob->pass_flag & TC_AUDIO)) {
+ // Input is more than 2 channels (i.e. 5.1 AC3) but PCM internal
+ // representation can't handle that, adjust the channel count to reflect
+ // what modules will actually have presented to them.
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "A: %-16s | %d channels -> %d channels",
+ "downmix", vob->a_chan, 2);
+ vob->a_chan = 2;
+ }
+
+ if (vob->ex_a_codec == 0 || vob->a_codec_flag == 0
+ || ex_aud_mod == NULL || strcmp(ex_aud_mod, "null") == 0) {
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "A: %-16s | disabled", "export");
+ ex_aud_mod = "null";
+ } else {
+ // audio format
+ if (ex_aud_mod && strlen(ex_aud_mod) != 0) {
+ if (strcmp(ex_aud_mod, "mpeg") == 0)
+ vob->ex_a_codec = CODEC_MP2;
+ if (strcmp(ex_aud_mod, "mp2enc") == 0)
+ vob->ex_a_codec = CODEC_MP2;
+ if (strcmp(ex_aud_mod, "mp1e") == 0)
+ vob->ex_a_codec=CODEC_MP2;
+ }
+
+ // calc export bitrate
+ switch (vob->ex_a_codec) {
+ case 0x1: // PCM
+ vob->mp3bitrate = ((vob->mp3frequency > 0) ?vob->mp3frequency :vob->a_rate) *
+ ((vob->dm_bits > 0) ?vob->dm_bits :vob->a_bits) *
+ ((vob->dm_chan > 0) ?vob->dm_chan :vob->a_chan) / 1000;
+ break;
+ case 0x2000: // PCM
+ if (vob->im_a_codec == CODEC_AC3) {
+ vob->mp3bitrate = vob->a_stream_bitrate;
+ }
+ break;
+ }
+
+ if (verbose & TC_INFO) {
+ if (vob->pass_flag & TC_AUDIO)
+ tc_log_info(PACKAGE,
+ "A: %-16s | 0x%-5x %-12s [%4d,%2d,%1d] %4d kbps",
+ "export format",
+ vob->im_a_codec,
+ tc_codec_to_comment(vob->im_a_codec),
+ vob->a_rate, vob->a_bits, vob->a_chan,
+ vob->a_stream_bitrate);
+ else
+ tc_log_info(PACKAGE,
+ "A: %-16s | 0x%-5x %-12s [%4d,%2d,%1d] %4d kbps",
+ "export format",
+ vob->ex_a_codec,
+ tc_codec_to_comment(vob->ex_a_codec),
+ ((vob->mp3frequency > 0) ?vob->mp3frequency :vob->a_rate),
+ ((vob->dm_bits > 0) ?vob->dm_bits :vob->a_bits),
+ ((vob->dm_chan > 0) ?vob->dm_chan :vob->a_chan),
+ vob->mp3bitrate);
+ tc_log_info(PACKAGE, "V: %-16s | %s%s", "export format",
+ tc_codec_to_string(vob->ex_v_codec),
+ (vob->ex_v_codec == 0) ?" (module dependant)" :"");
+ }
+ }
+
+ // Do not run out of audio-data
+ // import_ac3 now correctly probes the channels of the ac3 stream
+ // (previous versions always returned "2"). This breakes transcode
+ // when doing -A --tibit
+ if (vob->im_a_codec == CODEC_AC3)
+ vob->a_chan = vob->a_chan > 2 ?2 :vob->a_chan;
+
+ // -f and --export_fps/export_frc
+ //
+ // set import/export frc/fps
+ if (vob->im_frc == 0)
+ tc_frc_code_from_value(&vob->im_frc, vob->fps);
+
+ // ex_fps given, but not ex_frc
+ if (vob->ex_frc == 0 && (vob->ex_fps != 0.0))
+ tc_frc_code_from_value(&vob->ex_frc, vob->ex_fps);
+
+ if (vob->ex_frc == 0 && vob->im_frc != 0)
+ vob->ex_frc = vob->im_frc;
+
+ // ex_frc always overwrites ex_fps
+ if (vob->ex_frc > 0)
+ tc_frc_code_to_value(vob->ex_frc, &vob->ex_fps);
+
+ if (vob->im_frc <= 0 && vob->ex_frc <= 0 && vob->ex_fps == 0)
+ vob->ex_fps = vob->fps;
+
+ if (vob->im_frc == -1)
+ vob->im_frc = 0;
+ if (vob->ex_frc == -1)
+ vob->ex_frc = 0;
+
+ // --export_fps
+
+ if(verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "V: %-16s | %.3f,%d",
+ "encoding fps,frc",
+ vob->ex_fps, vob->ex_frc);
+
+
+ // --a52_demux
+
+ if ((vob->a52_mode & TC_A52_DEMUX) && (verbose & TC_INFO))
+ tc_log_info(PACKAGE,
+ "A: %-16s | %s", "A52 demuxing",
+ "(yes) 3 front, 2 rear, 1 LFE (5.1)");
+
+ //audio language, if probed sucessfully
+ if(vob->lang_code > 0 && (verbose & TC_INFO))
+ tc_log_info(PACKAGE,
+ "A: %-16s | %c%c",
+ "language",
+ vob->lang_code >> 8, vob->lang_code & 0xff);
+
+ // recalculate audio bytes per frame since video frames per second
+ // may have changed
+
+ // samples per audio frame
+ fch = vob->a_rate/vob->ex_fps;
+
+ // bytes per audio frame
+ vob->im_a_size = (int)(fch * (vob->a_bits/8) * vob->a_chan);
+ vob->im_a_size = (vob->im_a_size >> 2) << 2;
+
+ // rest:
+ fch *= (vob->a_bits/8) * vob->a_chan;
+
+ leap_bytes1 = TC_LEAP_FRAME * (fch - vob->im_a_size);
+ leap_bytes2 = - leap_bytes1 + TC_LEAP_FRAME * (vob->a_bits/8) * vob->a_chan;
+ leap_bytes1 = (leap_bytes1 >> 2) << 2;
+ leap_bytes2 = (leap_bytes2 >> 2) << 2;
+
+ if(leap_bytes1<leap_bytes2) {
+ vob->a_leap_bytes = leap_bytes1;
+ } else {
+ vob->a_leap_bytes = -leap_bytes2;
+ vob->im_a_size += (vob->a_bits/8) * vob->a_chan;
+ }
+
+ // final size in bytes
+ vob->ex_a_size = vob->im_a_size;
+
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "A: %-16s | %d (%.6f)",
+ "bytes per frame", vob->im_a_size, fch);
+
+ if(no_audio_adjust) {
+ vob->a_leap_bytes=0;
+
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "A: %-16s | disabled", "adjustment");
+
+ } else
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE,
+ "A: %-16s | %d@%d", "adjustment",
+ vob->a_leap_bytes, vob->a_leap_frame);
+
+ // -s
+
+ if (vob->volume > 0 && vob->a_chan != 2) {
+ //tc_error("option -s not yet implemented for mono streams");
+ }
+
+ if (vob->volume > 0 && (verbose & TC_INFO))
+ tc_log_info(PACKAGE,
+ "A: %-16s | %5.3f",
+ "rescale stream", vob->volume);
+
+ // -D
+ if (vob->sync_ms >= (int) (1000.0/vob->ex_fps)
+ || vob->sync_ms <= - (int) (1000.0/vob->ex_fps)) {
+ vob->sync = (int) (vob->sync_ms/1000.0*vob->ex_fps);
+ vob->sync_ms -= vob->sync * (int) (1000.0/vob->ex_fps);
+ }
+
+ if ((vob->sync || vob->sync_ms) && (verbose & TC_INFO))
+ tc_log_info(PACKAGE,
+ "A: %-16s | %d ms [ %d (A) | %d ms ]",
+ "AV shift",
+ vob->sync * (int) (1000.0/vob->ex_fps) + vob->sync_ms,
+ vob->sync, vob->sync_ms);
+
+ // -d
+ if (pcmswap)
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "A: %-16s | yes", "swap bytes");
+
+ // -E
+
+ //set export parameter to input parameter, if no re-sampling is requested
+ if (vob->dm_chan == 0)
+ vob->dm_chan = vob->a_chan;
+ if (vob->dm_bits == 0)
+ vob->dm_bits = vob->a_bits;
+
+ // -P
+ if (vob->pass_flag & TC_AUDIO) {
+ vob->im_a_codec = CODEC_RAW;
+ vob->ex_a_codec = CODEC_RAW;
+ //suggestion:
+ if (no_a_out_codec)
+ ex_aud_mod = "raw";
+ no_a_out_codec = 0;
+
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "A: %-16s | yes", "pass-through");
+ }
+
+ // -m
+ // different audio/video output files need two export modules
+ if (no_a_out_codec == 0 && vob->audio_out_file == NULL
+ && strcmp(ex_vid_mod, ex_aud_mod) != 0)
+ tc_error("different audio/export modules require use of option -m");
+
+
+ // --accel
+#if defined(ARCH_X86) || defined(ARCH_X86_64)
+ if (verbose & TC_INFO)
+ tc_log_info(PACKAGE, "V: IA32/AMD64 accel | %s ",
+ ac_flagstotext(tc_accel & ac_cpuinfo()));
+#endif
+
+ ac_init(tc_accel);
+
+ // more checks with warnings
+
+ if (verbose & TC_INFO) {
+ // -o
+ if (vob->video_out_file == NULL && vob->audio_out_file == NULL
+ && core_mode == TC_MODE_DEFAULT) {
+ vob->video_out_file = TC_DEFAULT_OUT_FILE;
+ vob->audio_out_file = TC_DEFAULT_OUT_FILE;
+ tc_warn("no option -o found, encoded frames send to \"%s\"",
+ vob->video_out_file);
+ }
+
+ // -y
+ if (core_mode == TC_MODE_DEFAULT
+ && vob->video_out_file != NULL && no_v_out_codec)
+ tc_warn("no option -y found, option -o ignored, writing to \"/dev/null\"");
+
+ if (core_mode == TC_MODE_AVI_SPLIT && no_v_out_codec)
+ tc_warn("no option -y found, option -t ignored, writing to \"/dev/null\"");
+
+ if (vob->im_v_codec == CODEC_YUV
+ && (vob->im_clip_left % 2 != 0 || vob->im_clip_right % 2
+ || vob->im_clip_top % 2 != 0 || vob->im_clip_bottom % 2 != 0))
+ tc_warn ("Odd import clipping paramter(s) detected, may cause distortion");
+
+ if (vob->im_v_codec == CODEC_YUV
+ && (vob->ex_clip_left % 2 != 0 || vob->ex_clip_right % 2
+ || vob->ex_clip_top % 2 != 0 || vob->ex_clip_bottom % 2 != 0))
+ tc_warn ("Odd export clipping paramter(s) detected, may cause distortion");
+ }
+
+ // -u
+ if (tc_buffer_delay_dec == -1) //adjust core parameter
+ tc_buffer_delay_dec = (vob->pass_flag & TC_VIDEO || ex_vid_mod==NULL || strcmp(ex_vid_mod, "null") == 0)
+ ?TC_DELAY_MIN :TC_DELAY_MAX;
+
+ if (tc_buffer_delay_enc == -1) //adjust core parameter
+ tc_buffer_delay_enc = (vob->pass_flag & TC_VIDEO || ex_vid_mod==NULL || strcmp(ex_vid_mod, "null") == 0)
+ ?TC_DELAY_MIN :TC_DELAY_MAX;
+
+ if (verbose & TC_DEBUG)
+ tc_log_msg(PACKAGE, "encoder delay = decode=%d encode=%d usec",
+ tc_buffer_delay_dec, tc_buffer_delay_enc);
+
+ if (core_mode == TC_MODE_AVI_SPLIT && !strlen(base) && !vob->video_out_file)
+ tc_error("no option -o found, no base for -t given, so what?");
+
+ /* -------------------------------------------------------------
+ *
+ * OK, so far, now start the support threads, setup buffers, ...
+ *
+ * ------------------------------------------------------------- */
+
+ //this will speed up in pass-through mode
+ if(vob->pass_flag && !(preset_flag & TC_PROBE_NO_BUFFER))
+ max_frame_buffer = 50;
+
+ if (vob->fps >= vob->ex_fps) {
+ /* worst case -> lesser fps (more audio samples for second) */
+ specs.frc = vob->im_frc;
+ } else {
+ specs.frc = vob->ex_frc;
+ }
+ specs.width = TC_MAX(vob->im_v_width, vob->ex_v_width);
+ specs.height = TC_MAX(vob->im_v_height, vob->ex_v_height);
+ specs.format = vob->im_v_codec;
+
+ /* XXX: explain me up */
+ specs.rate = TC_MAX(vob->a_rate, vob->mp3frequency);
+ specs.channels = TC_MAX(vob->a_chan, vob->dm_chan);
+ specs.bits = TC_MAX(vob->a_bits, vob->dm_bits);
+
+ tc_framebuffer_set_specs(&specs);
+
+ if (verbose & TC_INFO) {
+ tc_log_info(PACKAGE, "V: video buffer | %i @ %ix%i [0x%x]",
+ max_frame_buffer, specs.width, specs.height, specs.format);
+ tc_log_info(PACKAGE, "A: audio buffer | %i @ %ix%ix%i",
+ max_frame_buffer, specs.rate, specs.channels, specs.bits);
+ }
+
+#ifdef STATBUFFER
+ // allocate buffer
+ if (verbose & TC_DEBUG)
+ tc_log_msg(PACKAGE, "allocating %d framebuffers (static)",
+ max_frame_buffer);
+
+ if (vframe_alloc(max_frame_buffer) < 0)
+ tc_error("static framebuffer allocation failed");
+ if (aframe_alloc(max_frame_buffer) < 0)
+ tc_error("static framebuffer allocation failed");
+
+#else
+ if(verbose & TC_DEBUG)
+ tc_log_msg(PACKAGE, "%d framebuffers (dynamic) requested",
+ max_frame_buffer);
+#endif
+
+ // load import/export modules and filters plugins
+ if (transcode_init(vob, tc_get_ringbuffer(max_frame_threads, max_frame_threads)) < 0)
+ tc_error("plug-in initialization failed");
+
+ // start socket stuff
+ if (socket_file)
+ if (!tc_socket_init(socket_file))
+ tc_error("failed to initialize socket handler");
+
+ // now we start the signal handler thread
+ if (pthread_create(&event_thread_id, NULL, event_thread, &sigs_to_block) != 0)
+ tc_error("failed to start signal handler thread");
+
+
+ // start frame processing threads
+ tc_frame_threads_init(vob, max_frame_threads, max_frame_threads);
+
+
+ /* ------------------------------------------------------------
+ *
+ * transcoder core modes
+ *
+ * ------------------------------------------------------------*/
+
+ switch (core_mode) {
+ case TC_MODE_DEFAULT:
+ transcode_mode_default(vob);
+ break;
+
+ case TC_MODE_AVI_SPLIT:
+ transcode_mode_avi_split(vob);
+ break;
+
+ case TC_MODE_PSU:
+ transcode_mode_psu(vob, psubase);
+ break;
+
+ case TC_MODE_DIRECTORY:
+ transcode_mode_directory(vob);
+ break;
+
+ case TC_MODE_DVD_CHAPTER:
+ transcode_mode_dvd(vob);
+ break;
+
+ case TC_MODE_DEBUG:
+ /* FIXME: get rid of this? */
+ tc_log_msg(PACKAGE, "debug \"core\" mode");
+ break;
+
+ default:
+ //should not get here:
+ tc_error("internal error");
+ }
+
+ /* ------------------------------------------------------------
+ * shutdown transcode, all cores modes end up here, core modes
+ * must take care of proper import/export API shutdown.
+ *
+ * 1) stop and cancel frame processing threads
+ * 2) unload all external modules
+ * 3) cancel internal signal/server thread
+ * ------------------------------------------------------------*/
+
+ // turn counter off
+ counter_off();
+
+ SHUTDOWN_MARK("clean up");
+
+ // stop and cancel frame processing threads
+ tc_frame_threads_close();
+ SHUTDOWN_MARK("frame threads");
+
+ // unload all external modules
+ transcode_fini(NULL);
+ SHUTDOWN_MARK("unload modules");
+
+ // cancel no longer used internal signal handler threads
+ if (event_thread_id) {
+ SHUTDOWN_MARK("cancel signal");
+ stop_event_thread();
+ event_thread_id = (pthread_t)0;
+ }
+
+ SHUTDOWN_MARK("internal threads");
+
+ // shut down control socket, if active
+ tc_socket_fini();
+ SHUTDOWN_MARK("control socket");
+
+ // all done
+ if (verbose & TC_DEBUG)
+ fprintf(stderr, " done\n");
+
+ summary:
+ // print a summary
+ if ((verbose & TC_INFO) && vob->clip_count)
+ tc_log_info(PACKAGE, "clipped %d audio samples",
+ vob->clip_count/2);
+
+ if (verbose & TC_INFO) {
+ long drop = - tc_get_frames_dropped();
+
+ tc_log_info(PACKAGE, "encoded %ld frames (%ld dropped, %ld cloned),"
+ " clip length %6.2f s",
+ (long)tc_get_frames_encoded(), drop,
+ (long)tc_get_frames_cloned(),
+ tc_get_frames_encoded()/vob->ex_fps);
+ }
+
+#ifdef STATBUFFER
+ // free buffers
+ vframe_free();
+ aframe_free();
+ if(verbose & TC_DEBUG)
+ tc_log_msg(PACKAGE, "buffer released");
+#endif
+
+ teardown_input_sources(vob);
+
+ if (vob)
+ tc_free(vob);
+
+ //exit at last
+ if (tc_interrupted())
+ return 127;
+ return 0;
+}
+
+// this Code below here _never_ gets called.
+// it is just there to trick the linker to not remove
+// unneeded object files from a .a file.
+
+#include "libtc/static_tclist.h"
+#include "libtc/static_optstr.h"
+#include "libtc/static_tctimer.h"
+#include "avilib/static_avilib.h"
+#include "avilib/static_wavlib.h"
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/transcode.h b/debian/transcode/transcode-1.1.7/src/transcode.h
new file mode 100644
index 00000000..90c2a22d
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/transcode.h
@@ -0,0 +1,500 @@
+/*
+ * transcode.h
+ *
+ * Copyright (C) Thomas Oestreich - June 2001
+ *
+ * This file is part of transcode, a 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.
+ *
+ */
+
+#ifndef _TRANSCODE_H
+#define _TRANSCODE_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "avilib/avilib.h"
+#include "aclib/ac.h"
+#include "libtc/tcglob.h"
+#include "libtc/framecode.h"
+#include "libtcvideo/tcvideo.h"
+
+
+#ifdef __bsdi__
+typedef unsigned int uint32_t;
+#endif
+
+#include "tc_defaults.h"
+#include "framebuffer.h"
+#include "libtc/libtc.h"
+
+/*************************************************************************/
+
+/* ----------------------------
+ *
+ * MPEG profiles for setting
+ * sensible defaults
+ *
+ * ----------------------------*/
+
+typedef enum {
+ PROF_NONE = 0,
+ VCD,
+ VCD_PAL,
+ VCD_NTSC,
+ SVCD,
+ SVCD_PAL,
+ SVCD_NTSC,
+ XVCD,
+ XVCD_PAL,
+ XVCD_NTSC,
+ DVD,
+ DVD_PAL,
+ DVD_NTSC
+} mpeg_profile_t;
+
+
+/* ----------------------------
+ *
+ * Global information structure
+ *
+ * ----------------------------*/
+
+typedef struct _transfer_t {
+ int flag;
+ FILE *fd;
+ int size;
+ uint8_t *buffer;
+ uint8_t *buffer2;
+ int attributes;
+} transfer_t;
+
+typedef struct _vob_t {
+
+ // import info
+
+ const char *vmod_probed;
+ const char *amod_probed;
+ const char *vmod_probed_xml; // Modules for reading XML data
+ const char *amod_probed_xml;
+
+ int verbose;
+
+ TCGlob *video_in_files;
+ TCGlob *audio_in_files;
+ const char *video_in_file; // Video source file
+ const char *audio_in_file; // Audio source file
+
+ const char *nav_seek_file; // Seek/index information
+
+ int has_audio; // Does the stream have audio?
+ int has_audio_track; // Does the requested audio track exist?
+ int has_video; // Does the stream have video?
+
+ int lang_code; // Language of audio track
+
+ int a_track; // Audio track ID
+ int v_track; // Video track ID
+ int s_track; // Subtitle track ID
+
+ int sync; // Frame offset for audio/video synchronization
+ int sync_ms; // Fine-tuning for audio/video synchronization
+ int sync_samples; // sync_ms converted to samples
+
+ int dvd_title;
+ int dvd_chapter1;
+ int dvd_chapter2;
+ int dvd_max_chapters;
+ int dvd_angle;
+
+ int ps_unit;
+ int ps_seq1;
+ int ps_seq2;
+
+ int ts_pid1;
+ int ts_pid2;
+
+ int vob_offset;
+ int vob_chunk;
+ int vob_chunk_num1;
+ int vob_chunk_num2;
+ int vob_chunk_max;
+ int vob_percentage;
+
+ int vob_psu_num1;
+ int vob_psu_num2;
+
+ const char *vob_info_file;
+
+ double pts_start;
+
+ double psu_offset; // PSU offset to pass to extsub
+
+ int demuxer;
+
+ long v_format_flag; // Video stream format
+ long v_codec_flag; // Video codec
+ long a_format_flag; // Audio stream format
+ long a_codec_flag; // Audio codec
+
+ int quality;
+
+ // Audio stream parameters
+
+ int a_stream_bitrate; // Source stream bitrate
+
+ int a_chan;
+ int a_bits;
+ int a_rate;
+
+ int a_padrate; // Zero padding rate
+
+ int im_a_size; // Import total bytes per audio frame
+ int ex_a_size; // Export total bytes per audio frame
+
+ int im_a_codec; // True frame buffer audio codec
+
+ int a_leap_frame;
+ int a_leap_bytes;
+
+ int a_vbr; // LAME VBR switch
+
+ int a52_mode;
+
+ int dm_bits;
+ int dm_chan;
+
+ // Video stream parameters
+
+ int v_stream_bitrate; // Source stream bitrate
+
+ double fps; // Import frame rate (default 25 fps)
+ int im_frc; // Import frame rate code
+ double ex_fps; // Export frame rate (default 25 fps)
+ int ex_frc; // Export frame rate code
+ int hard_fps_flag; // If this is set, disable demuxer smooth drop
+
+ int pulldown; // Set 3:2 pulldown flags on MPEG export
+
+ int im_v_height; // Import picture height
+ int im_v_width; // Import picture width
+ int im_v_size; // Total number of bytes per frame
+
+ int im_asr; // Import aspect ratio code
+ int im_par; // Import pixel aspect (code)
+ int im_par_width; // Import pixel aspect width
+ int im_par_height; // Import pixel aspect height
+ int ex_asr; // Export aspect ratio code
+ int ex_par; // Export pixel aspect (code)
+ int ex_par_width; // Export pixel aspect width
+ int ex_par_height; // Export pixel aspect height
+
+ int attributes; // More video frame attributes
+
+ int im_v_codec; // True frame buffer video codec
+
+ int encode_fields; // Interlaced field handling flag
+
+ int dv_yuy2_mode; // Decode DV video in YUY2 mode?
+
+ // Audio frame manipulation info
+
+ double volume; // Audio amplitude rescale parameter
+ double ac3_gain[3]; // Audio amplitude rescale parameter for ac3
+ int clip_count; // # of bytes clipped after volume adjustment
+
+ // Video frame manipulation info
+
+ int ex_v_width; // Export picture width
+ int ex_v_height; // Export picture height
+ int ex_v_size; // Total number of bytes per frame
+
+ int reduce_h; // Reduction factor for frame height
+ int reduce_w; // Reduction factor for frame width
+
+ int resize1_mult; // Multiplier for {vert,hori}_resize1
+ int vert_resize1; // Height resize amount (shrink)
+ int hori_resize1; // Width resize amount (shrink)
+
+ int resize2_mult; // Multiplier for {vert,hori}_resize2
+ int vert_resize2; // Height resize amount (expand)
+ int hori_resize2; // Width resize amount (expand)
+
+ int zoom_width; // Zoom width
+ int zoom_height; // Zoom height
+ int zoom_interlaced; // Zoom in interlaced mode?
+
+ TCVZoomFilter zoom_filter;
+
+ int antialias;
+ int deinterlace;
+ int decolor;
+
+ double aa_weight; // Antialiasing center pixel weight
+ double aa_bias; // Antialiasing horizontal/vertical bias
+
+ double gamma;
+
+ int ex_clip_top;
+ int ex_clip_bottom;
+ int ex_clip_left;
+ int ex_clip_right;
+
+ int im_clip_top;
+ int im_clip_bottom;
+ int im_clip_left;
+ int im_clip_right;
+
+ int post_ex_clip_top;
+ int post_ex_clip_bottom;
+ int post_ex_clip_left;
+ int post_ex_clip_right;
+
+ int pre_im_clip_top;
+ int pre_im_clip_bottom;
+ int pre_im_clip_left;
+ int pre_im_clip_right;
+
+ // Export info
+
+ const char *video_out_file;
+ const char *audio_out_file;
+
+ avi_t *avifile_in;
+ avi_t *avifile_out;
+ int avi_comment_fd; // Text file to read AVI header comments from
+
+ int audio_file_flag; // Nonzero if audio goes to its own file
+
+ // Encoding parameters
+
+ int divxbitrate;
+ int divxkeyframes;
+ int divxquality;
+ int divxcrispness;
+ int divxmultipass;
+ int video_max_bitrate;
+ const char *divxlogfile;
+
+ int min_quantizer;
+ int max_quantizer;
+
+ int rc_period;
+ int rc_reaction_period;
+ int rc_reaction_ratio;
+
+ int divx5_vbv_prof; // Profile number
+ int divx5_vbv_bitrate; // Video Bitrate Verifier constraint overrides
+ int divx5_vbv_size;
+ int divx5_vbv_occupancy;
+
+ int mp3bitrate;
+ int mp3frequency;
+ float mp3quality; // 0=best (very slow), 9=worst (default=5)
+ int mp3mode; // 0=joint-stereo, 1=full-stereo, 2=mono
+
+ int bitreservoir;
+ const char *lame_preset;
+
+ const char *audiologfile;
+
+ int ex_a_codec; // Audio codec for export module
+ int ex_v_codec; // Video codec for export module
+
+ const char *ex_v_fcc; // Video fourcc string
+ const char *ex_a_fcc; // Audio fourcc string/identifier
+ const char *ex_profile_name; // User profile name
+
+ int pass_flag;
+ int encoder_flush; // flush encoders on close (yes)
+
+ const char *mod_path;
+
+ struct fc_time *ttime; // For framecode parsing (list of structs)
+
+ unsigned int frame_interval; // Select every `frame_interval' frames only
+
+ char *im_v_string; // Extra options for import video module
+ char *im_a_string; // Extra options for import audio module
+ char *ex_v_string; // Extra options for export video module
+ char *ex_a_string; // Extra options for export audio module
+ char *ex_m_string; // Extra options for multiplexor module
+
+ float m2v_requant; // Requantize factor for mpeg2 video streams
+
+ mpeg_profile_t mpeg_profile;
+
+ unsigned int export_attributes;
+} vob_t;
+
+
+typedef struct subtitle_header_s {
+
+ unsigned int header_length;
+ unsigned int header_version;
+ unsigned int payload_length;
+
+ unsigned int lpts;
+ double rpts;
+
+ unsigned int discont_ctr;
+
+} subtitle_header_t;
+
+/*************************************************************************/
+
+// Module functions
+
+int tc_import(int opt, void *para1, void *para2);
+int tc_export(int opt, void *para1, void *para2);
+
+// Some functions exported by transcode
+
+vob_t *tc_get_vob(void);
+
+int tc_next_video_in_file(vob_t *vob);
+int tc_next_audio_in_file(vob_t *vob);
+
+int tc_has_more_video_in_file(vob_t *vob);
+int tc_has_more_audio_in_file(vob_t *vob);
+
+void tc_outstream_rotate(void);
+void tc_outstream_rotate_request(void);
+
+void version(void);
+
+extern int verbose;
+extern int pcmswap;
+extern int rescale;
+extern int im_clip;
+extern int ex_clip;
+extern int pre_im_clip;
+extern int post_ex_clip;
+extern int flip;
+extern int mirror;
+extern int rgbswap;
+extern int resize1;
+extern int resize2;
+extern int decolor;
+extern int zoom;
+extern int dgamma;
+extern int keepasr;
+extern int fast_resize;
+
+// Core parameters
+
+extern int tc_buffer_delay_dec;
+extern int tc_buffer_delay_enc;
+extern int tc_cluster_mode;
+extern int tc_decoder_delay;
+extern int tc_progress_meter;
+extern int tc_progress_rate;
+extern int tc_accel;
+extern unsigned int tc_avi_limit;
+extern pid_t tc_probe_pid;
+extern int tc_niceness;
+
+extern int max_frame_buffer;
+extern int max_frame_threads;
+
+// Various constants
+
+enum {
+ TC_EXPORT_NAME = 10,
+ TC_EXPORT_OPEN,
+ TC_EXPORT_INIT,
+ TC_EXPORT_ENCODE,
+ TC_EXPORT_CLOSE,
+ TC_EXPORT_STOP,
+};
+
+enum {
+ TC_EXPORT_ERROR = -1,
+ TC_EXPORT_OK = 0,
+ TC_EXPORT_UNKNOWN = 1,
+};
+
+enum {
+ TC_IMPORT_NAME = 20,
+ TC_IMPORT_OPEN,
+ TC_IMPORT_DECODE,
+ TC_IMPORT_CLOSE,
+};
+
+enum {
+ TC_IMPORT_ERROR = -1,
+ TC_IMPORT_OK = 0,
+ TC_IMPORT_UNKNOWN = 1,
+};
+
+enum {
+ TC_CAP_NONE = 0,
+ TC_CAP_PCM = 1,
+ TC_CAP_RGB = 2,
+ TC_CAP_AC3 = 4,
+ TC_CAP_YUV = 8,
+ TC_CAP_AUD = 16,
+ TC_CAP_VID = 32,
+ TC_CAP_MP3 = 64,
+ TC_CAP_YUY2 = 128,
+ TC_CAP_DV = 256,
+ TC_CAP_YUV422 = 512,
+};
+
+enum {
+ TC_MODE_DEFAULT = 0,
+ TC_MODE_AVI_SPLIT = 1,
+ TC_MODE_DVD_CHAPTER = 2,
+ TC_MODE_PSU = 4,
+ TC_MODE_DIRECTORY = 16,
+ TC_MODE_DEBUG = 32,
+};
+
+enum {
+ TC_ENCODE_FIELDS_PROGRESSIVE = 0,
+ TC_ENCODE_FIELDS_TOP_FIRST,
+ TC_ENCODE_FIELDS_BOTTOM_FIRST,
+ TC_ENCODE_FIELDS_UNKNOWN,
+};
+
+/*************************************************************************/
+
+#endif // _TRANSCODE_H
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/video_trans.c b/debian/transcode/transcode-1.1.7/src/video_trans.c
new file mode 100644
index 00000000..bee77ef1
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/video_trans.c
@@ -0,0 +1,607 @@
+/*
+ * video_trans.c - video frame transformation routines
+ * Written by Andrew Church <achurch@achurch.org>
+ * Based on code written by Thomas Oestreich.
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "transcode.h"
+#include "framebuffer.h"
+#include "video_trans.h"
+#include "libtcvideo/tcvideo.h"
+
+/*************************************************************************/
+
+/* Structure that holds video frame information for passing around to
+ * processing routines. Since this is used only locally, we don't add
+ * the fields to vframe_list_t itself. */
+
+typedef struct {
+ vframe_list_t *ptr;
+ int preadj_w, preadj_h; // width and height used for secondary buffer
+ int Bpp; // BYTES (not bits) per pixel
+ int nplanes; // number of planes
+ uint8_t *planes[3]; // pointer to start of each plane
+ uint8_t *tmpplanes[3]; // same, for secondary buffer
+ int width_div[3]; // width divisors for each plane
+ int height_div[3]; // height divisors for each plane
+ uint8_t black_pixel[3]; // "black" value for each plane (e.g. 128 for U/V)
+} video_trans_data_t;
+
+/* Macro to perform a transformation on a frame. `vtd' is a pointer to a
+ * video_trans_data_t; the given function `func' will be called for each
+ * plane `i' as:
+ * func(handle, vtd->planes[i], vtd->tmpplanes[i], vtd->ptr->v_width,
+ * vtd->ptr->v_height, vtd->Bpp, args)
+ * where `args' are all arguments to this macro (if any) following `vtd'.
+ * swap_buffers(vtd) is called after the processing is complete.
+ */
+#define PROCESS_FRAME(func,vtd,args...) do { \
+ int i; \
+ for (i = 0; i < (vtd)->nplanes; i++) { \
+ func(handle, (vtd)->planes[i], (vtd)->tmpplanes[i], \
+ (vtd)->ptr->v_width / (vtd)->width_div[i], \
+ (vtd)->ptr->v_height / (vtd)->height_div[i], \
+ (vtd)->Bpp , ## args); \
+ } \
+ swap_buffers(vtd); \
+} while (0)
+
+/* Handle for calling tcvideo functions. */
+static TCVHandle handle = 0;
+
+/*************************************************************************/
+/*************************** Internal routines ***************************/
+/*************************************************************************/
+
+/**
+ * set_vtd: Initialize the given vtd structure from the given
+ * vframe_list_t, and update ptr->video_size.
+ *
+ * Parameters:
+ * vtd: Pointer to video frame data to be initialized.
+ * ptr: Pointer to video frame buffer.
+ * Return value:
+ * None.
+ */
+
+static void set_vtd(video_trans_data_t *vtd, vframe_list_t *ptr)
+{
+ int i;
+
+ vtd->ptr = ptr;
+ vtd->preadj_w = 0;
+ vtd->preadj_h = 0;
+ /* Set some defaults */
+ vtd->Bpp = 1;
+ vtd->nplanes = 1;
+ vtd->planes[0] = ptr->video_buf;
+ vtd->tmpplanes[0] = ptr->video_buf_Y[ptr->free];
+ vtd->width_div[0] = 1;
+ vtd->height_div[0] = 1;
+ vtd->black_pixel[0] = 0;
+ /* Now set parameters based on image format */
+ if (ptr->v_codec == CODEC_YUV) {
+ vtd->nplanes = 3;
+ vtd->Bpp = 1;
+ vtd->width_div[1] = 2;
+ vtd->width_div[2] = 2;
+ vtd->height_div[1] = 2;
+ vtd->height_div[2] = 2;
+ vtd->black_pixel[1] = 128;
+ vtd->black_pixel[2] = 128;
+ } else if (vtd->ptr->v_codec == CODEC_YUV422) {
+ vtd->nplanes = 3;
+ vtd->Bpp = 1;
+ vtd->width_div[1] = 2;
+ vtd->width_div[2] = 2;
+ vtd->height_div[1] = 1;
+ vtd->height_div[2] = 1;
+ vtd->black_pixel[1] = 128;
+ vtd->black_pixel[2] = 128;
+ } else if (vtd->ptr->v_codec == CODEC_RGB) {
+ vtd->Bpp = 3;
+ }
+ ptr->video_size = 0;
+ for (i = 0; i < vtd->nplanes; i++) {
+ int planesize = (ptr->v_width/vtd->width_div[i])
+ * (ptr->v_height/vtd->height_div[i])
+ * vtd->Bpp;
+ ptr->video_size += planesize;
+ if (i < vtd->nplanes-1) {
+ vtd->planes[i+1] = vtd->planes[i] + planesize;
+ vtd->tmpplanes[i+1] = vtd->tmpplanes[i] + planesize;
+ }
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * preadjust_frame_size: Prepare for an operation that will change the
+ * frame size, setting up the secondary buffer plane pointers with the new
+ * size. Calling swap_buffers() will store the new size in the
+ * vframe_list_t structure.
+ *
+ * Parameters:
+ * vtd: Pointer to video frame data.
+ * new_w: New frame width.
+ * new_h: New frame height.
+ * Return value:
+ * None.
+ */
+
+static void preadjust_frame_size(video_trans_data_t *vtd, int new_w, int new_h)
+{
+ int i;
+
+ vtd->preadj_w = new_w;
+ vtd->preadj_h = new_h;
+ for (i = 0; i < vtd->nplanes-1; i++) {
+ int planesize = (new_w/vtd->width_div[i]) * (new_h/vtd->height_div[i])
+ * vtd->Bpp;
+ vtd->tmpplanes[i+1] = vtd->tmpplanes[i] + planesize;
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * swap_buffers: Swap current video frame buffer with free buffer. Also
+ * updates frame size if preadjust_frame_size() has been called.
+ *
+ * Parameters:
+ * vtd: Pointer to video frame data.
+ * Return value:
+ * None.
+ */
+
+static void swap_buffers(video_trans_data_t *vtd)
+{
+ vtd->ptr->video_buf = vtd->ptr->video_buf_Y[vtd->ptr->free];
+ vtd->ptr->free = (vtd->ptr->free==0) ? 1 : 0;
+ /* Install new width/height if preadjust_frame_size() was called */
+ if (vtd->preadj_w && vtd->preadj_h) {
+ vtd->ptr->v_width = vtd->preadj_w;
+ vtd->ptr->v_height = vtd->preadj_h;
+ vtd->preadj_w = 0;
+ vtd->preadj_h = 0;
+ }
+ /* Set up plane pointers again */
+ set_vtd(vtd, vtd->ptr);
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/**
+ * do_process_frame: Perform video frame transformations based on global
+ * transcoding settings (derived from command-line arguments).
+ *
+ * Parameters:
+ * vob: Global data pointer.
+ * ptr: Pointer to video frame buffer.
+ * Return value:
+ * 0 on success, -1 on failure.
+ */
+
+static int do_process_frame(vob_t *vob, vframe_list_t *ptr)
+{
+ video_trans_data_t vtd; /* for passing to subroutines */
+
+
+ /**** Sanity check and initialization ****/
+
+ if (ptr->video_buf_Y[0] == ptr->video_buf_Y[1]) {
+ tc_log_error(__FILE__, "video frame has no temporary buffer!");
+ return -1;
+ }
+ if (ptr->video_buf == ptr->video_buf_Y[ptr->free]) {
+ static int warned = 0;
+ if (!warned) {
+ tc_log_warn(__FILE__, "ptr->free points to wrong buffer"
+ " (BUG in transcode or modules)");
+ warned = 1;
+ }
+ ptr->free = !ptr->free;
+ }
+ set_vtd(&vtd, ptr);
+
+ /**** -j: clip frame (import) ****/
+
+ if (im_clip) {
+ preadjust_frame_size(&vtd,
+ ptr->v_width - vob->im_clip_left - vob->im_clip_right,
+ ptr->v_height - vob->im_clip_top - vob->im_clip_bottom);
+ PROCESS_FRAME(tcv_clip, &vtd,
+ vob->im_clip_left / vtd.width_div[i],
+ vob->im_clip_right / vtd.width_div[i],
+ vob->im_clip_top / vtd.height_div[i],
+ vob->im_clip_bottom / vtd.height_div[i],
+ vtd.black_pixel[i]);
+ }
+
+ /**** -I: deinterlace video frame ****/
+
+ if (vob->deinterlace > 0
+ || ((ptr->attributes & TC_FRAME_IS_INTERLACED) && ptr->deinter_flag > 0)
+ ) {
+ int mode = (vob->deinterlace>0 ? vob->deinterlace : ptr->deinter_flag);
+ if (mode == 1) {
+ /* Simple linear interpolation */
+ /* Note that for YUV, we can just leave U and V alone, since
+ * they already cover pairs of lines; thus instead of using
+ * PROCESS_FRAME, we just call tcv_deinterlace() on the Y/RGB
+ * plane, then copy the other two planes and swap_buffers(). */
+ int i;
+ tcv_deinterlace(handle, vtd.planes[0], vtd.tmpplanes[0],
+ ptr->v_width, ptr->v_height, vtd.Bpp,
+ TCV_DEINTERLACE_INTERPOLATE);
+ for (i = 1; i < vtd.nplanes; i++) {
+ ac_memcpy(vtd.tmpplanes[i], vtd.planes[i],
+ (ptr->v_width/vtd.width_div[i])
+ * (ptr->v_height/vtd.height_div[i]));
+ }
+ swap_buffers(&vtd);
+ } else if (mode == 3 || mode == 4) {
+ /* Drop every other line (and zoom back out in mode 3) */
+ preadjust_frame_size(&vtd, ptr->v_width, ptr->v_height/2);
+ /* Drop the top or the bottom field? (Does it matter?) */
+ PROCESS_FRAME(tcv_deinterlace, &vtd,
+ TCV_DEINTERLACE_DROP_FIELD_BOTTOM);
+ if (mode == 3) {
+ int w = ptr->v_width, h = ptr->v_height*2;
+ preadjust_frame_size(&vtd, w, h);
+ PROCESS_FRAME(tcv_zoom, &vtd, w / vtd.width_div[i],
+ h / vtd.height_div[i], vob->zoom_filter);
+ }
+ } else if (mode == 5) {
+ /* Linear blend; as for -I 1, only Y is processed in YUV mode */
+ int i;
+ tcv_deinterlace(handle, vtd.planes[0], vtd.tmpplanes[0],
+ ptr->v_width, ptr->v_height, vtd.Bpp,
+ TCV_DEINTERLACE_LINEAR_BLEND);
+ for (i = 1; i < vtd.nplanes; i++) {
+ ac_memcpy(vtd.tmpplanes[i], vtd.planes[i],
+ (ptr->v_width/vtd.width_div[i])
+ * (ptr->v_height/vtd.height_div[i]));
+ }
+ swap_buffers(&vtd);
+ }
+ /* else mode 2 (handled by encoder) or unknown: do nothing */
+ ptr->attributes &= ~TC_FRAME_IS_INTERLACED;
+ }
+
+ /**** -X: fast resize (up) ****/
+ /**** -B: fast resize (down) ****/
+
+ if (resize1 || resize2) {
+ int width = ptr->v_width, height = ptr->v_height;
+ int resize_w = vob->hori_resize2 - vob->hori_resize1;
+ int resize_h = vob->vert_resize2 - vob->vert_resize1;
+ if (resize_h) {
+ preadjust_frame_size(&vtd, width, height+resize_h*8);
+ PROCESS_FRAME(tcv_resize, &vtd, 0, resize_h, 8/vtd.width_div[i],
+ 8/vtd.height_div[i]);
+ height += resize_h * 8;
+ }
+ if (resize_w) {
+ preadjust_frame_size(&vtd, width+resize_w*8, height);
+ PROCESS_FRAME(tcv_resize, &vtd, resize_w, 0, 8/vtd.width_div[i],
+ 8/vtd.height_div[i]);
+ }
+ }
+
+ /**** -Z: zoom frame (slow resize) ****/
+
+ if (zoom) {
+ preadjust_frame_size(&vtd, vob->zoom_width, vob->zoom_height);
+ if (vob->zoom_interlaced) {
+ /* In YUV mode, only handle the first place as interlaced;
+ * the U and V planes are shared between both fields */
+ int i;
+ tcv_zoom(handle, vtd.planes[0], vtd.tmpplanes[0],
+ ptr->v_width, ptr->v_height, vtd.Bpp,
+ vob->zoom_width, -vob->zoom_height, vob->zoom_filter);
+ for (i = 1; i < vtd.nplanes; i++) {
+ tcv_zoom(handle, vtd.planes[i], vtd.tmpplanes[i],
+ ptr->v_width / vtd.width_div[i],
+ ptr->v_height / vtd.height_div[i], vtd.Bpp,
+ vob->zoom_width / vtd.width_div[i],
+ vob->zoom_height / vtd.height_div[i],
+ vob->zoom_filter);
+ }
+ swap_buffers(&vtd);
+ } else {
+ PROCESS_FRAME(tcv_zoom, &vtd, vob->zoom_width / vtd.width_div[i],
+ vob->zoom_height / vtd.height_div[i],
+ vob->zoom_filter);
+ }
+ }
+
+ /**** -Y: clip frame (export) ****/
+
+ if (ex_clip) {
+ preadjust_frame_size(&vtd,
+ ptr->v_width - vob->ex_clip_left-vob->ex_clip_right,
+ ptr->v_height - vob->ex_clip_top - vob->ex_clip_bottom);
+ PROCESS_FRAME(tcv_clip, &vtd,
+ vob->ex_clip_left / vtd.width_div[i],
+ vob->ex_clip_right / vtd.width_div[i],
+ vob->ex_clip_top / vtd.height_div[i],
+ vob->ex_clip_bottom / vtd.height_div[i],
+ vtd.black_pixel[i]);
+ }
+
+ /**** -r: rescale video frame ****/
+
+ if (rescale) {
+ preadjust_frame_size(&vtd, ptr->v_width / vob->reduce_w,
+ ptr->v_height / vob->reduce_h);
+ PROCESS_FRAME(tcv_reduce, &vtd, vob->reduce_w, vob->reduce_h);
+ }
+
+ /**** -z: flip frame vertically ****/
+
+ if (flip) {
+ PROCESS_FRAME(tcv_flip_v, &vtd);
+ }
+
+ /**** -l: flip flame horizontally (mirror) ****/
+
+ if (mirror) {
+ PROCESS_FRAME(tcv_flip_h, &vtd);
+ }
+
+ /**** -k: red/blue swap ****/
+
+ if (rgbswap) {
+ if (ptr->v_codec == CODEC_RGB) {
+ int i;
+ for (i = 0; i < ptr->v_width * ptr->v_height; i++) {
+ uint8_t tmp = vtd.planes[0][i*3];
+ vtd.planes[0][i*3] = vtd.planes[0][i*3+2];
+ vtd.planes[0][i*3+2] = tmp;
+ }
+ } else {
+ int UVsize = (ptr->v_width / vtd.width_div[1])
+ * (ptr->v_height / vtd.height_div[1]) * vtd.Bpp;
+ ac_memcpy(vtd.tmpplanes[1], vtd.planes[1], UVsize); /* tmp<-U */
+ ac_memcpy(vtd.planes[1], vtd.planes[2], UVsize); /* U<-V */
+ ac_memcpy(vtd.planes[2], vtd.tmpplanes[1], UVsize); /* V<-tmp */
+ }
+ }
+
+ /**** -K: grayscale ****/
+
+ if (decolor) {
+ if (ptr->v_codec == CODEC_RGB) {
+ /* Convert to 8-bit grayscale, then back to RGB24. Just
+ * averaging the values won't give us the right intensity. */
+ tcv_convert(handle, vtd.planes[0], vtd.tmpplanes[0],
+ ptr->v_width, ptr->v_height, IMG_RGB24, IMG_GRAY8);
+ tcv_convert(handle, vtd.tmpplanes[0], vtd.planes[0],
+ ptr->v_width, ptr->v_height, IMG_GRAY8, IMG_RGB24);
+ } else {
+ /* YUV is easy: just set U and V to 128 */
+ int UVsize = (ptr->v_width / vtd.width_div[1])
+ * (ptr->v_height / vtd.height_div[1]) * vtd.Bpp;
+ memset(vtd.planes[1], 128, UVsize);
+ memset(vtd.planes[2], 128, UVsize);
+ }
+ }
+
+ /**** -G: gamma correction ****/
+
+ if (dgamma) {
+ /* Only process the first plane (Y) for YUV; for RGB it's all in
+ * one plane anyway */
+ tcv_gamma_correct(handle, ptr->video_buf, ptr->video_buf,
+ ptr->v_width, ptr->v_height, vtd.Bpp, vob->gamma);
+ }
+
+ /**** -C: antialiasing ****/
+
+ if (vob->antialias) {
+ /* Only Y is antialiased; U and V remain the same */
+ tcv_antialias(handle, vtd.planes[0], vtd.tmpplanes[0],
+ ptr->v_width, ptr->v_height, vtd.Bpp,
+ vob->aa_weight, vob->aa_bias);
+ if (ptr->v_codec != CODEC_RGB) {
+ int UVsize = (ptr->v_width / vtd.width_div[1])
+ * (ptr->v_height / vtd.height_div[1]) * vtd.Bpp;
+ ac_memcpy(vtd.tmpplanes[1], vtd.planes[1], UVsize);
+ ac_memcpy(vtd.tmpplanes[2], vtd.planes[2], UVsize);
+ }
+ swap_buffers(&vtd);
+ }
+
+ /**** End of processing ****/
+
+ return 0;
+}
+
+/*************************************************************************/
+/*************************** Exported routines ***************************/
+/*************************************************************************/
+
+/**
+ * process_vid_frame: Main video frame processing routine. The image is
+ * passed in ptr->video_buf; this can be updated as needed, e.g. to point
+ * to the secondary buffer after transformations.
+ *
+ * Parameters:
+ * vob: Global data pointer.
+ * ptr: Pointer to video frame buffer.
+ * Return value:
+ * 0 on success, -1 on failure.
+ */
+
+int process_vid_frame(vob_t *vob, vframe_list_t *ptr)
+{
+ /* Check parameter validity */
+ if (!vob || !ptr)
+ return -1;
+
+ /* Check for pass-through mode or skipped frames */
+ if (vob->pass_flag & TC_VIDEO)
+ return 0;
+ if (ptr->attributes & TC_FRAME_IS_SKIPPED)
+ return 0;
+
+ /* It's a valid frame, check the colorspace for validity and process it */
+ if (vob->im_v_codec == CODEC_RGB
+ || vob->im_v_codec == CODEC_YUV
+ || vob->im_v_codec == CODEC_YUV422
+ ) {
+ ptr->v_codec = vob->im_v_codec;
+ return do_process_frame(vob, ptr);
+ }
+
+ /* Invalid colorspace, bail out */
+ tc_error("Oops, invalid colorspace video frame data");
+ return -1;
+}
+
+/*************************************************************************/
+
+/**
+ * preprocess_vid_frame: Frame preprocessing routine. Checks for frame
+ * out of -c range and performs early clipping.
+ *
+ * Parameters:
+ * vob: Global data pointer.
+ * ptr: Pointer to video frame buffer.
+ * Return value:
+ * 0 on success, -1 on failure.
+ */
+
+int preprocess_vid_frame(vob_t *vob, vframe_list_t *ptr)
+{
+ /* Check parameter validity */
+ if (!vob || !ptr)
+ return -1;
+
+ /* Allocate tcvideo handle if necessary */
+ if (!handle) {
+ handle = tcv_init();
+ if (!handle) {
+ tc_log_error(PACKAGE, "video_trans.c: tcv_init() failed!");
+ return -1;
+ }
+ }
+
+ /* Check for pass-through mode */
+ if (vob->pass_flag & TC_VIDEO)
+ return 0;
+
+ /* Check frame colorspace */
+ if (vob->im_v_codec != CODEC_RGB
+ && vob->im_v_codec != CODEC_YUV
+ && vob->im_v_codec != CODEC_YUV422
+ ) {
+ tc_error("Oops, invalid colorspace video frame data");
+ return -1;
+ }
+
+ /* Perform early clipping */
+ if (pre_im_clip) {
+ video_trans_data_t vtd;
+ ptr->v_codec = vob->im_v_codec;
+ set_vtd(&vtd, ptr);
+ preadjust_frame_size(&vtd,
+ ptr->v_width - vob->pre_im_clip_left - vob->pre_im_clip_right,
+ ptr->v_height - vob->pre_im_clip_top - vob->pre_im_clip_bottom);
+ PROCESS_FRAME(tcv_clip, &vtd,
+ vob->pre_im_clip_left / vtd.width_div[i],
+ vob->pre_im_clip_right / vtd.width_div[i],
+ vob->pre_im_clip_top / vtd.height_div[i],
+ vob->pre_im_clip_bottom / vtd.height_div[i],
+ vtd.black_pixel[i]);
+ }
+
+ /* Finished with preprocessing */
+ return 0;
+}
+
+/*************************************************************************/
+
+/**
+ * postprocess_vid_frame: Frame postprocessing routine. Performs final
+ * clipping and sanity checks.
+ *
+ * Parameters:
+ * vob: Global data pointer.
+ * ptr: Pointer to video frame buffer.
+ * Return value:
+ * 0 on success, -1 on failure.
+ */
+
+/* Frame postprocessing routine. Performs final clipping and sanity
+ * checks. Parameters are as for process_vid_frame().
+ */
+
+int postprocess_vid_frame(vob_t *vob, vframe_list_t *ptr)
+{
+ /* Check parameter validity */
+ if (!vob || !ptr)
+ return -1;
+
+ /* Check for pass-through mode or skipped frames */
+ if (vob->pass_flag & TC_VIDEO)
+ return 0;
+ if (ptr->attributes & TC_FRAME_IS_SKIPPED)
+ return 0;
+
+ /* Check frame colorspace */
+ if (vob->im_v_codec != CODEC_RGB
+ && vob->im_v_codec != CODEC_YUV
+ && vob->im_v_codec != CODEC_YUV422
+ ) {
+ tc_error("Oops, invalid colorspace video frame data");
+ return -1;
+ }
+
+ /* Perform final clipping, if this isn't a cloned frame */
+ if (post_ex_clip && !(ptr->attributes & TC_FRAME_WAS_CLONED)) {
+ video_trans_data_t vtd;
+ ptr->v_codec = vob->im_v_codec;
+ set_vtd(&vtd, ptr);
+ preadjust_frame_size(&vtd,
+ ptr->v_width - vob->post_ex_clip_left - vob->post_ex_clip_right,
+ ptr->v_height - vob->post_ex_clip_top - vob->post_ex_clip_bottom);
+ PROCESS_FRAME(tcv_clip, &vtd,
+ vob->post_ex_clip_left / vtd.width_div[i],
+ vob->post_ex_clip_right / vtd.width_div[i],
+ vob->post_ex_clip_top / vtd.height_div[i],
+ vob->post_ex_clip_bottom / vtd.height_div[i],
+ vtd.black_pixel[i]);
+ }
+
+ /* Sanity check: make sure the frame size is what we're expecting */
+ if (ptr->v_width != vob->ex_v_width || ptr->v_height != vob->ex_v_height) {
+ tc_log_msg(__FILE__, "width %d %d | height %d %d",
+ ptr->v_width, vob->ex_v_width,
+ ptr->v_height, vob->ex_v_height);
+ tc_error("Oops, frame parameter mismatch detected");
+ }
+
+ /* Finished with postprocessing */
+ return 0;
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
diff --git a/debian/transcode/transcode-1.1.7/src/video_trans.h b/debian/transcode/transcode-1.1.7/src/video_trans.h
new file mode 100644
index 00000000..45880879
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/video_trans.h
@@ -0,0 +1,37 @@
+/*
+ * video_trans.h - header for video frame transformation routines
+ * Written by Andrew Church <achurch@achurch.org>
+ * Based on code written by Thomas Oestreich.
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#ifndef _VIDEO_TRANS_H
+#define _VIDEO_TRANS_H
+
+#include "transcode.h"
+
+/*************************************************************************/
+
+/* Video frame processing functions. */
+
+int process_vid_frame(vob_t *vob, vframe_list_t *ptr);
+int preprocess_vid_frame(vob_t *vob, vframe_list_t *ptr);
+int postprocess_vid_frame(vob_t *vob, vframe_list_t *ptr);
+
+/*************************************************************************/
+
+#endif /* _VIDEO_TRANS_H */
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */