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.
450 lines
9.9 KiB
450 lines
9.9 KiB
4 years ago
|
/*
|
||
|
* tcextract.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 "libtc/xio.h"
|
||
|
#include "ioaux.h"
|
||
|
#include "tc.h"
|
||
|
|
||
|
|
||
|
#define EXE "tcextract"
|
||
|
|
||
|
#define MAX_BUF 1024
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
/* ------------------------------------------------------------
|
||
|
*
|
||
|
* 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 file type [autodetect]\n");
|
||
|
fprintf(stderr," -a track track number [0]\n");
|
||
|
fprintf(stderr," -x codec source codec\n");
|
||
|
fprintf(stderr," -d mode verbosity mode\n");
|
||
|
fprintf(stderr," -C s-e process only (video frame/audio byte) range [all]\n");
|
||
|
fprintf(stderr," -f seekfile seek/index file [off]\n");
|
||
|
fprintf(stderr," -v print version\n");
|
||
|
|
||
|
exit(status);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ------------------------------------------------------------
|
||
|
*
|
||
|
* universal extract thread frontend
|
||
|
*
|
||
|
* ------------------------------------------------------------*/
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
|
||
|
info_t ipipe;
|
||
|
|
||
|
int user=0;
|
||
|
|
||
|
long
|
||
|
stream_stype = TC_STYPE_UNKNOWN,
|
||
|
stream_magic = TC_MAGIC_UNKNOWN,
|
||
|
stream_codec = TC_CODEC_UNKNOWN;
|
||
|
|
||
|
int ch, done=0, track=0;
|
||
|
char *magic=NULL, *codec=NULL, *name=NULL;
|
||
|
|
||
|
//proper initialization
|
||
|
memset(&ipipe, 0, sizeof(info_t));
|
||
|
ipipe.frame_limit[0]=0;
|
||
|
ipipe.frame_limit[1]=LONG_MAX;
|
||
|
|
||
|
libtc_init(&argc, &argv);
|
||
|
|
||
|
while ((ch = getopt(argc, argv, "d:x:i:f:a:vt:C:?h")) != -1) {
|
||
|
|
||
|
switch (ch) {
|
||
|
|
||
|
case 'i':
|
||
|
|
||
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
||
|
name = optarg;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 'd':
|
||
|
|
||
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
||
|
verbose = atoi(optarg);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 'x':
|
||
|
|
||
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
||
|
codec = optarg;
|
||
|
break;
|
||
|
|
||
|
case 'f':
|
||
|
|
||
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
||
|
ipipe.nav_seek_file = optarg;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 't':
|
||
|
|
||
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
||
|
magic = optarg;
|
||
|
user=1;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 'a':
|
||
|
|
||
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
||
|
track = strtol(optarg, NULL, 0);
|
||
|
break;
|
||
|
|
||
|
case 'C':
|
||
|
|
||
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
||
|
if (2 != sscanf(optarg,"%ld-%ld", &ipipe.frame_limit[0], &ipipe.frame_limit[1])) usage(EXIT_FAILURE);
|
||
|
if (ipipe.frame_limit[0] > ipipe.frame_limit[1])
|
||
|
{
|
||
|
tc_log_error(EXE, "Invalid -C options");
|
||
|
usage(EXIT_FAILURE);
|
||
|
}
|
||
|
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(codec==NULL && magic==NULL) {
|
||
|
tc_log_error(EXE, "invalid codec %s", codec);
|
||
|
usage(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
if(codec==NULL) codec="";
|
||
|
|
||
|
// do not try to mess with the stream
|
||
|
if(stream_stype!=TC_STYPE_STDIN) {
|
||
|
|
||
|
if(tc_file_check(name)) exit(1);
|
||
|
|
||
|
if((ipipe.fd_in = xio_open(name, O_RDONLY))<0) {
|
||
|
tc_log_perror(EXE, "file open");
|
||
|
return(-1);
|
||
|
}
|
||
|
|
||
|
stream_magic = fileinfo(ipipe.fd_in, 0);
|
||
|
|
||
|
if(verbose & TC_DEBUG)
|
||
|
tc_log_msg(EXE, "(pid=%d) %s", getpid(), filetype(stream_magic));
|
||
|
|
||
|
} else ipipe.fd_in = STDIN_FILENO;
|
||
|
|
||
|
if(verbose & TC_DEBUG)
|
||
|
tc_log_msg(EXE, "(pid=%d) starting, doing %s", getpid(), codec);
|
||
|
|
||
|
// fill out defaults for info structure
|
||
|
ipipe.fd_out = STDOUT_FILENO;
|
||
|
|
||
|
ipipe.magic = stream_magic;
|
||
|
ipipe.stype = stream_stype;
|
||
|
ipipe.codec = stream_codec;
|
||
|
ipipe.track = track;
|
||
|
ipipe.select = TC_VIDEO;
|
||
|
|
||
|
ipipe.verbose = verbose;
|
||
|
|
||
|
ipipe.name = name;
|
||
|
|
||
|
/* ------------------------------------------------------------
|
||
|
*
|
||
|
* codec specific section
|
||
|
*
|
||
|
* note: user provided magic values overwrite autodetection!
|
||
|
*
|
||
|
* ------------------------------------------------------------*/
|
||
|
|
||
|
if(magic==NULL) magic="";
|
||
|
|
||
|
// OGM
|
||
|
|
||
|
if (ipipe.magic == TC_MAGIC_OGG) {
|
||
|
|
||
|
// dummy for video
|
||
|
if(strcmp(codec, "raw")==0) ipipe.codec = TC_CODEC_RGB;
|
||
|
if((strcmp(codec, "vorbis")==0) || (strcmp(codec, "ogg")==0)) {
|
||
|
ipipe.codec = TC_CODEC_VORBIS;
|
||
|
ipipe.select = TC_AUDIO;
|
||
|
}
|
||
|
if(strcmp(codec, "mp3")==0) {
|
||
|
ipipe.codec = TC_CODEC_MP3;
|
||
|
ipipe.select = TC_AUDIO;
|
||
|
}
|
||
|
if(strcmp(codec, "pcm")==0) {
|
||
|
ipipe.codec = TC_CODEC_PCM;
|
||
|
ipipe.select = TC_AUDIO;
|
||
|
}
|
||
|
|
||
|
extract_ogm(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
// MPEG2
|
||
|
if(strcmp(codec,"mpeg2")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_MPEG2;
|
||
|
|
||
|
if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
|
||
|
if(strcmp(magic, "m2v")==0) ipipe.magic = TC_MAGIC_M2V;
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
|
||
|
extract_mpeg2(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
// PCM
|
||
|
if(strcmp(codec,"pcm")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_PCM;
|
||
|
ipipe.select = TC_AUDIO;
|
||
|
|
||
|
if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
|
||
|
if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
if(strcmp(magic, "wav")==0) ipipe.magic = TC_MAGIC_WAV;
|
||
|
|
||
|
extract_pcm(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
// SUBTITLE (private_stream_1)
|
||
|
if(strcmp(codec,"ps1")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_PS1;
|
||
|
ipipe.select = TC_AUDIO;
|
||
|
|
||
|
if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
|
||
|
if(strcmp(magic, "vdr")==0) ipipe.magic = TC_MAGIC_VDR;
|
||
|
|
||
|
extract_ac3(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
// DV
|
||
|
if(strcmp(codec,"dv")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_DV;
|
||
|
|
||
|
if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
|
||
|
extract_dv(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
// RGB
|
||
|
if(strcmp(codec,"rgb")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_RGB;
|
||
|
|
||
|
if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
if(strcmp(magic, "wav")==0) ipipe.magic = TC_MAGIC_WAV;
|
||
|
|
||
|
extract_rgb(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
// DTS
|
||
|
if(strcmp(codec,"dts")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_DTS;
|
||
|
ipipe.select = TC_AUDIO;
|
||
|
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
|
||
|
|
||
|
extract_ac3(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
// AC3
|
||
|
if(strcmp(codec,"ac3")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_AC3;
|
||
|
ipipe.select = TC_AUDIO;
|
||
|
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
|
||
|
|
||
|
extract_ac3(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
// MP3
|
||
|
if(strcmp(codec,"mp3")==0 || strcmp(codec,"mp2")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_MP3;
|
||
|
ipipe.select = TC_AUDIO;
|
||
|
|
||
|
if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
|
||
|
|
||
|
extract_mp3(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
// YUV420P
|
||
|
if(strcmp(codec,"yuv420p")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_YUV420P;
|
||
|
|
||
|
if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
if(strcmp(magic, "yuv4mpeg")==0) ipipe.magic = TC_MAGIC_YUV4MPEG;
|
||
|
|
||
|
extract_yuv(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
// YUV422P
|
||
|
if(strcmp(codec,"yuv422p")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_YUV422P;
|
||
|
|
||
|
if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
if(strcmp(magic, "yuv4mpeg")==0) ipipe.magic = TC_MAGIC_YUV4MPEG;
|
||
|
|
||
|
extract_yuv(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
// UYVY
|
||
|
if(strcmp(codec,"uyvy")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_UYVY;
|
||
|
|
||
|
if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
|
||
|
extract_yuv(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
// LZO
|
||
|
if(strcmp(codec,"lzo")==0) {
|
||
|
|
||
|
ipipe.codec = TC_CODEC_YUV420P;
|
||
|
|
||
|
if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
|
||
|
if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
|
||
|
|
||
|
extract_lzo(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
// AVI extraction
|
||
|
|
||
|
//need to check if there isn't a codec from the input option (if we have a file with TC_MAGIC_AVI and we specify -x pcm we have pcm and rgb output)
|
||
|
if ((strcmp(magic, "avi")==0 || ipipe.magic==TC_MAGIC_AVI)&& (codec == NULL)) {
|
||
|
|
||
|
ipipe.magic=TC_MAGIC_AVI;
|
||
|
extract_avi(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
if (strcmp(codec, "raw")==0 || strcmp(codec, "video")==0) {
|
||
|
ipipe.select=TC_VIDEO-1;
|
||
|
ipipe.magic=TC_MAGIC_AVI;
|
||
|
extract_avi(&ipipe);
|
||
|
done = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
if(!done) {
|
||
|
tc_log_error(EXE, "(pid=%d) unable to handle codec %s", getpid(), codec);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if(ipipe.fd_in != STDIN_FILENO) xio_close(ipipe.fd_in);
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
#include "libtc/static_xio.h"
|