summaryrefslogtreecommitdiffstats
path: root/debian/transcode/transcode-1.1.7/import/tccat.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/tccat.c')
-rw-r--r--debian/transcode/transcode-1.1.7/import/tccat.c533
1 files changed, 533 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/import/tccat.c b/debian/transcode/transcode-1.1.7/import/tccat.c
new file mode 100644
index 00000000..f6ccd089
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/import/tccat.c
@@ -0,0 +1,533 @@
+/*
+ * tccat.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 "tcinfo.h"
+#include "libtc/libtc.h"
+#include "libtc/iodir.h"
+#include "libtc/xio.h"
+#include "ioaux.h"
+#include "tc.h"
+#include "dvd_reader.h"
+
+#include <sys/types.h>
+
+#ifdef HAVE_LIBDVDREAD
+#ifdef HAVE_LIBDVDREAD_INC
+#include <dvdread/dvd_reader.h>
+#else
+#include <dvd_reader.h>
+#endif
+#else
+#include "dvd_reader.h"
+#endif
+
+#define EXE "tccat"
+
+//static char buf[TC_BUF_MAX];
+
+int verbose = TC_INFO;
+
+void import_exit(int code)
+{
+ if (verbose & TC_DEBUG) {
+ tc_log_msg(EXE, "(pid=%d) exit (code %d)", (int) getpid(), code);
+ }
+ exit(code);
+}
+
+
+/* ------------------------------------------------------------
+ *
+ * source extract thread
+ *
+ * ------------------------------------------------------------*/
+
+#define IO_BUF_SIZE 1024
+#define DVD_VIDEO_LB_LEN 2048
+
+static void tccat_thread(info_t *ipipe)
+{
+ const char *name = NULL;
+ int found = 0, itype = TC_MAGIC_UNKNOWN, type = TC_MAGIC_UNKNOWN;
+ int verbose_flag = ipipe->verbose;
+ int vob_offset = ipipe->vob_offset;
+ info_t ipipe_avi;
+ TCDirList tcdir;
+
+ switch(ipipe->magic) {
+ case TC_MAGIC_DVD_PAL: /* fallthrough */
+ case TC_MAGIC_DVD_NTSC:
+ if (verbose_flag & TC_DEBUG) {
+ tc_log_msg(__FILE__, "%s", filetype(ipipe->magic));
+ }
+ dvd_read(ipipe->dvd_title, ipipe->dvd_chapter, ipipe->dvd_angle);
+ break;
+
+ case TC_MAGIC_TS:
+ ts_read(ipipe->fd_in, ipipe->fd_out, ipipe->ts_pid);
+ break;
+
+ case TC_MAGIC_RAW:
+ if (verbose_flag & TC_DEBUG) {
+ tc_log_msg(__FILE__, "%s", filetype(ipipe->magic));
+ }
+ if(vob_offset > 0) {
+ /* get filesize in units of packs (2kB) */
+ off_t off = lseek(ipipe->fd_in,
+ vob_offset * (off_t) DVD_VIDEO_LB_LEN,
+ SEEK_SET);
+
+ if (off != (vob_offset * (off_t)DVD_VIDEO_LB_LEN)) {
+ tc_log_warn(__FILE__, "unable to seek to block %d",
+ vob_offset); /* drop this chunk/file */
+ goto vob_skip2;
+ }
+ }
+ tc_preadwrite(ipipe->fd_in, ipipe->fd_out);
+vob_skip2:
+ break;
+
+ case TC_MAGIC_DIR:
+ /* PASS 1: check file type - file order not important */
+ if (tc_dirlist_open(&tcdir, ipipe->name, 0) < 0) {
+ tc_log_error(__FILE__, "unable to open directory \"%s\"",
+ ipipe->name);
+ exit(1);
+ } else if (verbose_flag & TC_DEBUG) {
+ tc_log_msg(__FILE__, "scanning directory \"%s\"", ipipe->name);
+ }
+
+ while ((name = tc_dirlist_scan(&tcdir)) != NULL) {
+ if ((ipipe->fd_in = open(name, O_RDONLY)) < 0) {
+ tc_log_perror(__FILE__, "file open");
+ exit(1);
+ }
+ /*
+ * first valid magic must be the same for all
+ * files to follow
+ */
+ itype = fileinfo(ipipe->fd_in, 0);
+ close(ipipe->fd_in);
+
+ if (itype == TC_MAGIC_UNKNOWN || itype == TC_MAGIC_PIPE
+ || itype == TC_MAGIC_ERROR) {
+ tc_log_error(__FILE__, "this version of transcode"
+ " supports only");
+ tc_log_error(__FILE__, "directories containing files of"
+ " identical file type.");
+ tc_log_error(__FILE__, "Please clean up directory %s and"
+ " restart.", ipipe->name);
+
+ tc_log_error(__FILE__, "file %s with filetype %s is invalid"
+ " for directory mode.",
+ name, filetype(itype));
+
+ exit(1);
+ } /* bad magic */
+
+ switch(itype) { /* supported file types, global fallthrough */
+ case TC_MAGIC_VOB:
+ case TC_MAGIC_DV_PAL:
+ case TC_MAGIC_DV_NTSC:
+ case TC_MAGIC_AC3:
+ case TC_MAGIC_YUV4MPEG:
+ case TC_MAGIC_AVI:
+ case TC_MAGIC_MPEG:
+ if (!found) { /* very first time only */
+ type = itype;
+ }
+ if (itype!=type) {
+ tc_log_error(__FILE__,"multiple filetypes not valid for"
+ " directory mode.");
+ exit(1);
+ }
+ found = 1;
+ break;
+ default:
+ tc_log_error(__FILE__, "invalid filetype %s for directory"
+ " mode.", filetype(type));
+ exit(1);
+ } /* check itype */
+ } /* process files */
+ tc_dirlist_close(&tcdir);
+
+ if (!found) {
+ tc_log_error(__FILE__, "no valid files found in %s", name);
+ exit(1);
+ } else if (verbose_flag & TC_DEBUG) {
+ tc_log_msg(__FILE__, "%s", filetype(type));
+ }
+
+ /* PASS 2: dump files in correct order */
+ if (tc_dirlist_open(&tcdir, ipipe->name, 1) < 0) {
+ tc_log_error(__FILE__, "unable to sort directory entries\"%s\"",
+ name);
+ exit(1);
+ }
+
+ while ((name = tc_dirlist_scan(&tcdir)) != NULL) {
+ if ((ipipe->fd_in = open(name, O_RDONLY)) < 0) {
+ tc_log_perror(__FILE__, "file open");
+ exit(1);
+ } else if(verbose_flag & TC_STATS) {
+ tc_log_msg(__FILE__, "processing %s", name);
+ }
+
+ /* type determined in pass 1 */
+ switch (type) {
+ case TC_MAGIC_VOB:
+ if (vob_offset > 0) {
+ /* get filesize in units of packs (2kB) */
+ off_t off;
+ off_t size = lseek(ipipe->fd_in, 0, SEEK_END);
+ lseek(ipipe->fd_in, 0, SEEK_SET);
+
+ if (size > vob_offset * (off_t)DVD_VIDEO_LB_LEN) {
+ /* offset within current file */
+ off = lseek(ipipe->fd_in,
+ vob_offset * (off_t)DVD_VIDEO_LB_LEN,
+ SEEK_SET);
+ vob_offset = 0;
+ } else {
+ vob_offset -= size/DVD_VIDEO_LB_LEN;
+ goto vob_skip;
+ }
+ }
+ tc_preadwrite(ipipe->fd_in, ipipe->fd_out);
+vob_skip:
+ break;
+ /*
+ * all following (fallthrough stream typeas are all handlead in
+ * the same way since they can be viewd as concatenation of
+ * frames (no header or other things
+ */
+ case TC_MAGIC_DV_PAL: /* fallthrough */
+ case TC_MAGIC_DV_NTSC: /* fallthrough */
+ case TC_MAGIC_AC3: /* fallthrough */
+ case TC_MAGIC_YUV4MPEG: /* fallthrough */
+ case TC_MAGIC_MPEG: /* fallthrough */
+ tc_preadwrite(ipipe->fd_in, ipipe->fd_out);
+ break;
+
+ case TC_MAGIC_AVI:
+ /* extract and concatenate streams. avilib must do it. */
+ ac_memcpy(&ipipe_avi, ipipe, sizeof(info_t));
+ ipipe_avi.name = (char *)name; /* real AVI file name */
+ ipipe_avi.magic = TC_MAGIC_AVI;
+ extract_avi(&ipipe_avi);
+ break;
+
+ default:
+ tc_log_error(__FILE__, "invalid filetype %s for directory"
+ " mode.", filetype(type));
+ exit(1);
+ }
+ close(ipipe->fd_in);
+ } /* process files */
+ tc_dirlist_close(&tcdir);
+ break;
+ }
+}
+
+
+void version(void)
+{
+ /* XXX why not plain old printf? */
+ tc_log_msg(EXE, "(%s v%s) (C) 2001-2003 Thomas Oestreich,"
+ " 2003-2010 Transcode Team",
+ PACKAGE, VERSION);
+}
+
+
+static void usage(int status)
+{
+ /* XXX why not plain old printf? */
+ version();
+
+ fprintf(stderr,"\nUsage: %s [options]\n", EXE);
+ fprintf(stderr," -i name input file/directory%s name\n",
+#ifdef HAVE_LIBDVDREAD
+ "/device/mountpoint"
+#else
+ ""
+#endif
+ );
+ fprintf(stderr," -t magic file type [autodetect]\n");
+#ifdef HAVE_LIBDVDREAD
+ fprintf(stderr," -T t[,c[-d][,a]] DVD title[,chapter(s)[,angle]]"
+ " [1,1,1]\n");
+ fprintf(stderr," -L process all following chapters"
+ " [off]\n");
+#endif
+ fprintf(stderr," -S n seek to VOB stream offset nx2kB"
+ " [0]\n");
+ fprintf(stderr," -P stream DVD ( needs -T )\n");
+ fprintf(stderr," -a dump AVI-file/socket audio"
+ " stream\n");
+ fprintf(stderr," -n id transport stream id [0x10]\n");
+ fprintf(stderr," -d mode verbosity mode\n");
+ fprintf(stderr," -v print version\n");
+
+ exit(status);
+}
+
+typedef enum {
+ TCCAT_SOURCE_STDIN = 1,
+ TCCAT_SOURCE_FILE,
+ TCCAT_SOURCE_DVD,
+ TCCAT_SOURCE_DIR,
+ TCCAT_SOURCE_TS
+} TCCatSources;
+
+/* ------------------------------------------------------------
+ * universal extract frontend
+ * ------------------------------------------------------------*/
+
+#define VALIDATE_OPTION \
+ if (optarg[0] == '-') usage(EXIT_FAILURE)
+
+int main(int argc, char *argv[])
+{
+ struct stat fbuf;
+ info_t ipipe;
+ int end_chapter, start_chapter;
+ int title = 1, chapter1 = 1, chapter2 = -1, angle = 1;
+ int max_chapters, max_angles, max_titles;
+ int n = 0, j, stream = 0, audio = 0, user = 0, source = 0;
+
+ int vob_offset = 0;
+ int ch, ts_pid = 0x10;
+ char *magic="", *name=NULL;
+
+ /* proper initialization */
+ memset(&ipipe, 0, sizeof(info_t));
+
+ libtc_init(&argc, &argv);
+
+ while ((ch = getopt(argc, argv, "S:T:d:i:vt:LaP?hn:")) != -1) {
+ switch (ch) {
+ case 'i':
+ VALIDATE_OPTION;
+ name = optarg;
+ break;
+
+ case 'T':
+ VALIDATE_OPTION;
+ n = sscanf(optarg,"%d,%d-%d,%d", &title, &chapter1, &chapter2, &angle);
+ if (n != 4) {
+ n = sscanf(optarg,"%d,%d-%d", &title, &chapter1, &chapter2);
+ if (n != 3) {
+ n = sscanf(optarg,"%d,%d,%d", &title, &chapter1, &angle);
+ /* only do one chapter ! */
+ chapter2 = chapter1;
+
+ if (n < 0 || n > 3) {
+ tc_log_error(EXE, "invalid parameter for option -T");
+ exit(1);
+ }
+ }
+ }
+ source = TCCAT_SOURCE_DVD;
+
+ if (chapter2 != -1) {
+ if (chapter2 < chapter1) {
+ tc_log_error(EXE, "invalid parameter for option -T");
+ exit(1);
+ }
+ }
+ break;
+
+ case 'P':
+ stream = 1;
+ break;
+
+ case 'a':
+ audio = 1;
+ break;
+
+ case 'd':
+ VALIDATE_OPTION;
+ verbose = atoi(optarg);
+ break;
+
+ case 'n':
+ VALIDATE_OPTION;
+ ts_pid = strtol(optarg, NULL, 16);
+ source = TCCAT_SOURCE_TS;
+ break;
+
+ case 'S':
+ VALIDATE_OPTION;
+ vob_offset = atoi(optarg);
+ break;
+
+ case 't':
+ VALIDATE_OPTION;
+ magic = optarg;
+ user = 1;
+
+ if (strcmp(magic, "dvd") == 0) {
+ source = TCCAT_SOURCE_DVD;
+ }
+ break;
+
+ case 'v':
+ version();
+ exit(0);
+ break;
+
+ case 'h':
+ usage(EXIT_SUCCESS);
+ default:
+ usage(EXIT_FAILURE);
+ }
+ }
+
+ /* DVD debugging information */
+ if ((verbose & TC_DEBUG) && source == TCCAT_SOURCE_DVD) {
+ tc_log_msg(EXE, "T=%d %d %d %d %d", n, title, chapter1,
+ chapter2, angle);
+ }
+
+ /* ------------------------------------------------------------
+ * fill out defaults for info structure
+ * ------------------------------------------------------------*/
+
+ /* no autodetection yet */
+ if (argc == 1) {
+ usage(EXIT_FAILURE);
+ }
+
+ /* assume defaults */
+ if (name == NULL) {
+ source = TCCAT_SOURCE_STDIN;
+ ipipe.fd_in = STDIN_FILENO;
+ }
+
+ /* no stdin for DVD */
+ if (name == NULL && source == TCCAT_SOURCE_DVD) {
+ tc_log_error(EXE, "invalid directory/path_to_device");
+ usage(EXIT_FAILURE);
+ }
+
+ /* do not try to mess with the stdin stream */
+ if ((source != TCCAT_SOURCE_DVD) && (source != TCCAT_SOURCE_TS)
+ && (source != TCCAT_SOURCE_STDIN)) {
+ /* file or directory? */
+ if (stat(name, &fbuf)) {
+ tc_log_error(EXE, "invalid file \"%s\"", name);
+ exit(1);
+ }
+
+ source = (S_ISDIR(fbuf.st_mode))
+ ?TCCAT_SOURCE_DIR :TCCAT_SOURCE_FILE;
+ }
+
+ /* fill out defaults for info structure */
+ ipipe.fd_out = STDOUT_FILENO;
+ ipipe.verbose = verbose;
+ ipipe.dvd_title = title;
+ ipipe.dvd_chapter = chapter1;
+ ipipe.dvd_angle = angle;
+ ipipe.ts_pid = ts_pid;
+ ipipe.vob_offset = vob_offset;
+
+ if (name) {
+ ipipe.name = tc_strdup(name);
+ if (ipipe.name == NULL) {
+ tc_log_error(EXE, "could not allocate memory");
+ exit(1);
+ }
+ } else {
+ ipipe.name = NULL;
+ }
+
+ ipipe.select = audio;
+
+ /* ------------------------------------------------------------
+ * source specific section
+ * ------------------------------------------------------------*/
+
+ switch(source) {
+ case TCCAT_SOURCE_TS:
+ ipipe.fd_in = xio_open(name, O_RDONLY);
+ if (ipipe.fd_in < 0) {
+ tc_log_perror(EXE, "file open");
+ exit(1);
+ }
+ ipipe.magic = TC_MAGIC_TS;
+ tccat_thread(&ipipe);
+ xio_close(ipipe.fd_in);
+ break;
+
+ case TCCAT_SOURCE_DVD:
+ if (dvd_init(name, &max_titles, verbose) < 0) {
+ tc_log_error(EXE, "(pid=%d) failed to open DVD %s", getpid(), name);
+ exit(1);
+ }
+ ipipe.magic = TC_MAGIC_DVD_PAL; /* FIXME */
+ dvd_query(title, &max_chapters, &max_angles);
+ /* set chapternumbers now we know how much there are */
+ start_chapter = (chapter1!=-1 && chapter1 <=max_chapters) ? chapter1:1;
+ end_chapter = (chapter2!=-1 && chapter2 <=max_chapters) ? chapter2:max_chapters;
+
+ for (j = start_chapter; j < end_chapter+1; j++) {
+ ipipe.dvd_chapter = j;
+ if (verbose & TC_DEBUG) {
+ tc_log_msg(EXE, "(pid=%d) processing chapter (%d/%d)",
+ getpid(), j, max_chapters);
+ }
+ if (stream) {
+ dvd_stream(title, j);
+ } else {
+ tccat_thread(&ipipe);
+ }
+ }
+ dvd_close();
+ break;
+
+ case TCCAT_SOURCE_FILE:
+ ipipe.fd_in = open(name, O_RDONLY);
+ if (ipipe.fd_in < 0) {
+ tc_log_perror(EXE, "file open");
+ exit(1);
+ }
+
+ case TCCAT_SOURCE_STDIN:
+ ipipe.magic = TC_MAGIC_RAW;
+ tccat_thread(&ipipe);
+ if (ipipe.fd_in != STDIN_FILENO) {
+ close(ipipe.fd_in);
+ }
+ break;
+
+ case TCCAT_SOURCE_DIR:
+ ipipe.magic = TC_MAGIC_DIR;
+ tccat_thread(&ipipe);
+ break;
+ }
+ return 0;
+}
+
+#include "libtc/static_xio.h"