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.

356 lines
9.6 KiB

/*
* tcdecode.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 <limits.h>
#include "ioaux.h"
#include "tc.h"
#include "libtc/xio.h"
#define EXE "tcdecode"
extern long fileinfo(int fd, int skip);
int verbose = TC_QUIET;
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 file input file [stdin]\n");
fprintf(stderr," -x codec source codec (required)\n");
fprintf(stderr," -t package codec package\n");
fprintf(stderr," -g wxh stream frame size [autodetect]\n");
fprintf(stderr," -y format output raw stream format [rgb]\n");
fprintf(stderr," -Q mode decoding quality (0=fastest-5=best) [%d]\n", VQUALITY);
fprintf(stderr," -d mode verbosity mode\n");
fprintf(stderr," -s c,f,r audio gain for ac3 downmixing [1,1,1]\n");
fprintf(stderr," -A n A52 decoder flag [0]\n");
fprintf(stderr," -C s,e decode only from start to end ((V) frames/(A) bytes) [all]\n");
fprintf(stderr," -Y use libdv YUY2 decoder mode\n");
fprintf(stderr," -z r convert zero padding to silence\n");
fprintf(stderr," -v print version\n");
exit(status);
}
/* ------------------------------------------------------------
*
* universal decode thread frontend
*
* ------------------------------------------------------------*/
int main(int argc, char *argv[])
{
decode_t decode;
int ch, done=0;
char *codec=NULL, *format="rgb", *magic="none";
memset(&decode, 0, sizeof(decode));
decode.magic = TC_MAGIC_UNKNOWN;
decode.stype = TC_STYPE_UNKNOWN;
decode.quality = VQUALITY;
decode.ac3_gain[0] = decode.ac3_gain[1] = decode.ac3_gain[2] = 1.0;
decode.frame_limit[0]=0;
decode.frame_limit[1]=LONG_MAX;
libtc_init(&argc, &argv);
while ((ch = getopt(argc, argv, "Q:t:d:x:i:a:g:vy:s:YC:A:z:?h")) != -1) {
switch (ch) {
case 'i':
if (optarg[0]=='-') usage(EXIT_FAILURE);
decode.name = optarg;
break;
case 'd':
if (optarg[0]=='-') usage(EXIT_FAILURE);
verbose = atoi(optarg);
break;
case 'Q':
if (optarg[0]=='-') usage(EXIT_FAILURE);
decode.quality = atoi(optarg);
break;
case 'A':
if (optarg[0]=='-') usage(EXIT_FAILURE);
decode.a52_mode = atoi(optarg);
break;
case 'x':
if (optarg[0]=='-') usage(EXIT_FAILURE);
codec = optarg;
break;
case 't':
if (optarg[0]=='-') usage(EXIT_FAILURE);
magic = optarg;
break;
case 'y':
if (optarg[0]=='-') usage(EXIT_FAILURE);
format = optarg;
break;
case 'g':
if (optarg[0]=='-') usage(EXIT_FAILURE);
if (2 != sscanf(optarg,"%dx%d", &decode.width, &decode.height)) usage(EXIT_FAILURE);
break;
case 'v':
version();
exit(0);
break;
case 'Y':
decode.dv_yuy2_mode=1;
break;
case 's':
if(optarg[0]=='-') usage(EXIT_FAILURE);
if (3 != sscanf(optarg,"%lf,%lf,%lf", &decode.ac3_gain[0], &decode.ac3_gain[1], &decode.ac3_gain[2])) usage(EXIT_FAILURE);
break;
case 'C':
if(optarg[0]=='-') usage(EXIT_FAILURE);
if (2 != sscanf(optarg,"%ld,%ld", &decode.frame_limit[0], &decode.frame_limit[1])) usage(EXIT_FAILURE);
if (decode.frame_limit[0] >= decode.frame_limit[1])
{
tc_log_error(EXE, "Invalid -C options");
usage(EXIT_FAILURE);
}
break;
case 'z':
if(optarg[0]=='-') usage(EXIT_FAILURE);
decode.padrate = atoi(optarg);
break;
case 'h':
usage(EXIT_SUCCESS);
default:
usage(EXIT_FAILURE);
}
}
ac_init(AC_ALL);
/* ------------------------------------------------------------
*
* fill out defaults for info structure
*
* ------------------------------------------------------------*/
// assume defaults
if(decode.name==NULL) decode.stype=TC_STYPE_STDIN;
// no autodetection yet
if(codec==NULL) {
tc_log_error(EXE, "codec must be specified");
usage(EXIT_FAILURE);
}
// do not try to mess with the stream
if (decode.stype != TC_STYPE_STDIN) {
if (tc_file_check(decode.name)) exit(1);
if ((decode.fd_in = xio_open(decode.name, O_RDONLY)) < 0) {
tc_log_perror(EXE, "open file");
exit(1);
}
// try to find out the filetype
decode.magic = fileinfo(decode.fd_in, 0);
if (verbose)
tc_log_msg(EXE, "(pid=%d) %s", getpid(), filetype(decode.magic));
} else decode.fd_in = STDIN_FILENO;
decode.fd_out = STDOUT_FILENO;
decode.codec = TC_CODEC_UNKNOWN;
decode.verbose = verbose;
if (decode.width < 0) decode.width = 0;
if (decode.height < 0) decode.height = 0;
/* ------------------------------------------------------------
*
* output raw stream format
*
* ------------------------------------------------------------*/
if (!strcmp(format, "rgb")) decode.format = TC_CODEC_RGB;
else if (!strcmp(format, "yuv420p")) decode.format = TC_CODEC_YUV420P;
else if (!strcmp(format, "yuv2")) decode.format = TC_CODEC_YUV2;
else if (!strcmp(format, "yuy2")) decode.format = TC_CODEC_YUY2;
else if (!strcmp(format, "pcm")) decode.format = TC_CODEC_PCM;
else if (!strcmp(format, "raw")) decode.format = TC_CODEC_RAW;
/* ------------------------------------------------------------
*
* codec specific section
*
* note: user provided values overwrite autodetection!
*
* ------------------------------------------------------------*/
// FFMPEG can decode a lot
if(!strcmp(magic, "ffmpeg") || !strcmp(magic, "lavc")) {
if (!strcmp(codec, "mpeg2")) decode.codec = TC_CODEC_MPEG2;
else if (!strcmp(codec, "mpeg2video")) decode.codec = TC_CODEC_MPEG2;
else if (!strcmp(codec, "mpeg1video")) decode.codec = TC_CODEC_MPEG1;
else if (!strcmp(codec, "divx3")) decode.codec = TC_CODEC_DIVX3;
else if (!strcmp(codec, "divx")) decode.codec = TC_CODEC_DIVX4;
else if (!strcmp(codec, "divx4")) decode.codec = TC_CODEC_DIVX4;
else if (!strcmp(codec, "mp42")) decode.codec = TC_CODEC_MP42;
else if (!strcmp(codec, "mjpg")) decode.codec = TC_CODEC_MJPEG;
else if (!strcmp(codec, "mjpeg")) decode.codec = TC_CODEC_MJPEG;
else if (!strcmp(codec, "rv10")) decode.codec = TC_CODEC_RV10;
else if (!strcmp(codec, "svq1")) decode.codec = TC_CODEC_SVQ1;
else if (!strcmp(codec, "svq3")) decode.codec = TC_CODEC_SVQ3;
else if (!strcmp(codec, "vp3")) decode.codec = TC_CODEC_VP3;
else if (!strcmp(codec, "4xm")) decode.codec = TC_CODEC_4XM;
else if (!strcmp(codec, "wmv1")) decode.codec = TC_CODEC_WMV1;
else if (!strcmp(codec, "wmv2")) decode.codec = TC_CODEC_WMV2;
else if (!strcmp(codec, "hfyu")) decode.codec = TC_CODEC_HUFFYUV;
else if (!strcmp(codec, "indeo3")) decode.codec = TC_CODEC_INDEO3;
else if (!strcmp(codec, "h263p")) decode.codec = TC_CODEC_H263P;
else if (!strcmp(codec, "h263i")) decode.codec = TC_CODEC_H263I;
else if (!strcmp(codec, "dvvideo")) decode.codec = TC_CODEC_DV;
else if (!strcmp(codec, "dv")) decode.codec = TC_CODEC_DV;
else if (!strcmp(codec, "vag")) decode.codec = TC_CODEC_VAG;
decode_lavc(&decode);
}
// MPEG2
if (!strcmp(codec, "mpeg2")) {
decode.codec = TC_CODEC_MPEG2;
decode_mpeg2(&decode);
done = 1;
}
// OGG
if (!strcmp(codec, "ogg")) {
decode.codec = TC_CODEC_VORBIS;
decode_ogg(&decode);
done = 1;
}
// AC3
if (!strcmp(codec, "ac3")) {
decode.codec = TC_CODEC_AC3;
decode_a52(&decode);
done = 1;
}
// MP3
if (!strcmp(codec, "mp3")) {
decode.codec = TC_CODEC_MP3;
decode_mp3(&decode);
done = 1;
}
// MP2
if (!strcmp(codec, "mp2")) {
decode.codec = TC_CODEC_MP3;
decode_mp2(&decode);
done = 1;
}
// DV
if (!strcmp(codec, "dv")) {
decode.codec = TC_CODEC_DV;
decode_dv(&decode);
done = 1;
}
// YUV420P
if (!strcmp(codec, "yuv420p")) {
decode.codec = TC_CODEC_YUV420P;
decode_yuv(&decode);
done = 1;
}
#if 0
// DivX Video
if (!strcmp(codec, "divx")) {
decode.select = TC_VIDEO;
decode_divx(&decode);
done = 1;
}
#endif
// MOV
if (!strcmp(codec, "mov")) {
decode_mov(&decode);
done = 1;
}
// LZO
if (!strcmp(codec, "lzo")) {
decode_lzo(&decode);
done = 1;
}
if(!done) {
tc_log_error(EXE, "(pid=%d) unable to handle codec %s", getpid(), codec);
exit(1);
}
if (decode.fd_in != STDIN_FILENO) xio_close(decode.fd_in);
return 0;
}
#include "libtc/static_xio.h"