You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

351 lines
10 KiB

/*
* tcdemux.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/xio.h"
#include "ioaux.h"
#include "tc.h"
#include "demuxer.h"
#define EXE "tcdemux"
#define MAX_BUF 1024
int verbose = TC_QUIET;
/* ------------------------------------------------------------
*
* auxiliary routines
*
* ------------------------------------------------------------*/
void import_exit(int code)
{
if (verbose & TC_DEBUG)
tc_log_msg(EXE, "(pid=%d) exit (code %d)", (int) getpid(), code);
exit(code);
}
/* ------------------------------------------------------------
*
* print a usage/version message
*
* ------------------------------------------------------------*/
void version(void)
{
/* print id string to stderr */
fprintf(stderr, "%s (%s v%s) (C) 2001-2003 Thomas Oestreich,"
" 2003-2010 Transcode Team\n",
EXE, PACKAGE, VERSION);
}
static void usage(int status)
{
version();
fprintf(stderr,"\nUsage: %s [options]\n", EXE);
fprintf(stderr," -i name input file name [stdin]\n");
fprintf(stderr," -t magic input file type [autodetect]\n");
fprintf(stderr," -x codec process only packs with codec payload [all]\n");
fprintf(stderr," -S unit[,s1-s2] presentation unit[,s1-s2] sequences [0,all]\n");
fprintf(stderr," -a ach[,vch] extract audio[,video] track [0,0]\n");
fprintf(stderr," -s 0xnn sync with private substream id 0xnn [off]\n");
fprintf(stderr," -M mode demuxer PES A-V sync mode (0=off|1=PTS only|2=full) [1]\n");
fprintf(stderr," -O do not skip initial sequence\n");
fprintf(stderr," -P name write synchronization data to file\n");
fprintf(stderr," -W write navigation data to stdout\n");
fprintf(stderr," -f fps frame rate [%.3f]\n", PAL_FPS);
fprintf(stderr," -d mode verbosity mode\n");
fprintf(stderr," -A n[,m[...]] pass-through packet payload id\n");
fprintf(stderr," -H sync hard to supplied fps (no smooth drop)\n");
fprintf(stderr," -v print version\n");
exit(status);
}
/* ------------------------------------------------------------
*
* demuxer thread frontend
*
* ------------------------------------------------------------*/
int main(int argc, char *argv[])
{
info_t ipipe;
int ch, n, user = 0, demux_mode = TC_DEMUX_SEQ_ADJUST;
int npass = 0, *pass = NULL, *new_pass = NULL;
int keep_initial_seq = 0, hard_fps_flag = 0, pack_sl = PACKAGE_ALL;
int unit_seek = 0, resync_seq1 = 0, resync_seq2 = INT_MAX;
int a_track = 0, v_track = 0, subid = 0x80;
double fps = PAL_FPS;
long stream_stype = TC_STYPE_UNKNOWN;
long stream_codec = TC_CODEC_UNKNOWN;
long stream_magic = TC_MAGIC_UNKNOWN;
long x;
char *magic = "", *codec = NULL, *name = NULL;
char *logfile = SYNC_LOGFILE, *str = NULL, *end = NULL;
//defaults:
//proper initialization
memset(&ipipe, 0, sizeof(info_t));
libtc_init(&argc, &argv);
while ((ch = getopt(argc, argv, "A:a:d:x:i:vt:S:M:f:P:WHs:O?h")) != -1) {
switch (ch) {
case 'i':
if (optarg[0] == '-') usage(EXIT_FAILURE);
name = optarg;
break;
case 'O':
keep_initial_seq = 1;
break;
case 'P':
if (optarg[0] == '-') usage(EXIT_FAILURE);
logfile = optarg;
break;
case 'S':
if (optarg[0] == '-') usage(EXIT_FAILURE);
n = sscanf(optarg,"%d,%d-%d",
&unit_seek, &resync_seq1, &resync_seq2);
if (n < 0) {
tc_log_error(EXE, "invalid parameter for option -S");
usage(EXIT_FAILURE);
}
if (unit_seek < 0) {
tc_log_error(EXE, "invalid unit parameter for option -S");
usage(EXIT_FAILURE);
}
if (resync_seq1 < 0 || resync_seq2 < 0
|| resync_seq1 >= resync_seq2) {
tc_log_error(EXE, "invalid sequence parameter for option -S");
usage(EXIT_FAILURE);
}
break;
case 'd':
if (optarg[0] == '-') usage(EXIT_FAILURE);
verbose = atoi(optarg);
break;
case 'f':
if (optarg[0] == '-') usage(EXIT_FAILURE);
fps = atof(optarg);
break;
case 'W':
demux_mode = TC_DEMUX_SEQ_LIST;
logfile = NULL;
break;
case 'H':
hard_fps_flag = 1;
break;
case 'x':
if (optarg[0] == '-') usage(EXIT_FAILURE);
codec = optarg;
if (strcmp(codec,"ac3") == 0) {
pack_sl = PACKAGE_AUDIO_AC3;
stream_codec = TC_CODEC_AC3;
}
if (strcmp(codec,"mpeg2") == 0) {
pack_sl = PACKAGE_VIDEO;
stream_codec = TC_CODEC_MPEG2;
}
if (strcmp(codec,"mp3") == 0) {
pack_sl = PACKAGE_AUDIO_MP3;
stream_codec = TC_CODEC_MP3;
}
if (strcmp(codec,"pcm") == 0) {
pack_sl = PACKAGE_AUDIO_PCM;
stream_codec = TC_CODEC_PCM;
}
if (strcmp(codec,"ps1") == 0) {
pack_sl = PACKAGE_SUBTITLE;
stream_codec = TC_CODEC_SUB;
}
break;
case 't':
if (optarg[0] == '-') usage(EXIT_FAILURE);
magic = optarg;
user = 1;
break;
case 's':
if (optarg[0] == '-') usage(EXIT_FAILURE);
subid = strtol(optarg, NULL, 16);
break;
case 'A':
if (optarg[0] == '-') usage(EXIT_FAILURE);
str = optarg;
while (1) {
x = strtol(str, &end, 0);
if ((end == str) || (x < 1) || (x > 0xff)) {
tc_log_error(EXE, "invalid parameter for option -A");
exit(1);
}
if (*end == '\0') {
break;
}
if (*end != ',') {
tc_log_error(EXE, "invalid parameter for option -A");
exit(1);
}
str = end + 1;
new_pass = tc_realloc(pass, (npass + 1) * sizeof (int));
if (new_pass == NULL) {
tc_log_error(EXE, "out of memory");
exit(1);
}
pass = new_pass;
pass[npass] = (int)x;
npass++;
}
break;
case 'M':
if (optarg[0] == '-') usage(EXIT_FAILURE);
demux_mode = atoi(optarg);
if (demux_mode == TC_DEMUX_OFF)
verbose = TC_QUIET;
if (demux_mode < 0 || demux_mode > TC_DEMUX_MAX_OPTS) {
tc_log_error(EXE, "invalid parameter for option -M");
exit(1);
}
break;
case 'a':
if (optarg[0] == '-') usage(EXIT_FAILURE);
if ((n = sscanf(optarg,"%d,%d", &a_track, &v_track)) <= 0) {
tc_log_error(EXE, "invalid parameter for option -a");
exit(1);
}
break;
case 'v':
version();
exit(0);
break;
case 'h':
usage(EXIT_SUCCESS);
default:
usage(EXIT_FAILURE);
}
}
ac_init(AC_ALL);
/* ------------------------------------------------------------
* fill out defaults for info structure
* ------------------------------------------------------------*/
// assume defaults
if (name == NULL)
stream_stype=TC_STYPE_STDIN;
// no autodetection yet
if (argc == 1) {
usage(EXIT_FAILURE);
}
// do not try to mess with the stream
if (stream_stype == TC_STYPE_STDIN) {
ipipe.fd_in = STDIN_FILENO;
} else {
if (tc_file_check(name))
exit(1);
ipipe.fd_in = xio_open(name, O_RDONLY);
if (ipipe.fd_in < 0) {
tc_log_perror(EXE, "open file");
exit(1);
}
// try to find out the filetype
stream_magic = fileinfo(ipipe.fd_in, 0);
if (verbose)
tc_log_msg(EXE, "(pid=%d) %s", getpid(), filetype(stream_magic));
}
// fill out defaults for info structure
ipipe.fd_out = STDOUT_FILENO;
ipipe.magic = stream_magic;
ipipe.stype = stream_stype;
ipipe.codec = stream_codec;
ipipe.verbose = verbose;
ipipe.ps_unit = unit_seek;
ipipe.ps_seq1 = resync_seq1;
ipipe.ps_seq2 = resync_seq2;
ipipe.demux = demux_mode;
ipipe.select = pack_sl;
ipipe.keep_seq = keep_initial_seq;
ipipe.subid = subid;
ipipe.fps = fps;
ipipe.hard_fps_flag = hard_fps_flag;
ipipe.track = a_track;
ipipe.name = logfile;
//FIXME: video defaults to 0
/* ------------------------------------------------------------
* main processing mode
* ------------------------------------------------------------*/
if (npass > 0)
tcdemux_pass_through(&ipipe, pass, npass);
else
tcdemux_thread(&ipipe);
return 0;
}
#include "libtc/static_xio.h"