1 /*
2 * tcextract.c
3 *
4 * Copyright (C) Thomas Oestreich - June 2001
5 *
6 * This file is part of transcode, a video stream processing tool
7 *
8 * transcode is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * transcode is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Make; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24 #include "transcode.h"
25 #include "tcinfo.h"
26
27 #include <limits.h>
28 #include "libtc/xio.h"
29 #include "ioaux.h"
30 #include "tc.h"
31
32
33 #define EXE "tcextract"
34
35 #define MAX_BUF 1024
36
37 int verbose=TC_INFO;
38
import_exit(int code)39 void import_exit(int code)
40 {
41 if(verbose & TC_DEBUG)
42 tc_log_msg(EXE, "(pid=%d) exit (code %d)", (int) getpid(), code);
43 exit(code);
44 }
45
46 /* ------------------------------------------------------------
47 *
48 * print a usage/version message
49 *
50 * ------------------------------------------------------------*/
51
version(void)52 void version(void)
53 {
54 /* print id string to stderr */
55 fprintf(stderr, "%s (%s v%s) (C) 2001-2003 Thomas Oestreich"
56 " 2003-2010 Transcode Team\n",
57 EXE, PACKAGE, VERSION);
58 }
59
usage(int status)60 static void usage(int status)
61 {
62 version();
63
64 fprintf(stderr,"\nUsage: %s [options]\n", EXE);
65 fprintf(stderr," -i name input file name [stdin]\n");
66 fprintf(stderr," -t magic file type [autodetect]\n");
67 fprintf(stderr," -a track track number [0]\n");
68 fprintf(stderr," -x codec source codec\n");
69 fprintf(stderr," -d mode verbosity mode\n");
70 fprintf(stderr," -C s-e process only (video frame/audio byte) range [all]\n");
71 fprintf(stderr," -f seekfile seek/index file [off]\n");
72 fprintf(stderr," -v print version\n");
73
74 exit(status);
75
76 }
77
78
79 /* ------------------------------------------------------------
80 *
81 * universal extract thread frontend
82 *
83 * ------------------------------------------------------------*/
84
main(int argc,char * argv[])85 int main(int argc, char *argv[])
86 {
87
88 info_t ipipe;
89
90 int user=0;
91
92 long
93 stream_stype = TC_STYPE_UNKNOWN,
94 stream_magic = TC_MAGIC_UNKNOWN,
95 stream_codec = TC_CODEC_UNKNOWN;
96
97 int ch, done=0, track=0;
98 char *magic=NULL, *codec=NULL, *name=NULL;
99
100 //proper initialization
101 memset(&ipipe, 0, sizeof(info_t));
102 ipipe.frame_limit[0]=0;
103 ipipe.frame_limit[1]=LONG_MAX;
104
105 libtc_init(&argc, &argv);
106
107 while ((ch = getopt(argc, argv, "d:x:i:f:a:vt:C:?h")) != -1) {
108
109 switch (ch) {
110
111 case 'i':
112
113 if(optarg[0]=='-') usage(EXIT_FAILURE);
114 name = optarg;
115
116 break;
117
118 case 'd':
119
120 if(optarg[0]=='-') usage(EXIT_FAILURE);
121 verbose = atoi(optarg);
122
123 break;
124
125 case 'x':
126
127 if(optarg[0]=='-') usage(EXIT_FAILURE);
128 codec = optarg;
129 break;
130
131 case 'f':
132
133 if(optarg[0]=='-') usage(EXIT_FAILURE);
134 ipipe.nav_seek_file = optarg;
135
136 break;
137
138 case 't':
139
140 if(optarg[0]=='-') usage(EXIT_FAILURE);
141 magic = optarg;
142 user=1;
143
144 break;
145
146 case 'a':
147
148 if(optarg[0]=='-') usage(EXIT_FAILURE);
149 track = strtol(optarg, NULL, 0);
150 break;
151
152 case 'C':
153
154 if(optarg[0]=='-') usage(EXIT_FAILURE);
155 if (2 != sscanf(optarg,"%ld-%ld", &ipipe.frame_limit[0], &ipipe.frame_limit[1])) usage(EXIT_FAILURE);
156 if (ipipe.frame_limit[0] > ipipe.frame_limit[1])
157 {
158 tc_log_error(EXE, "Invalid -C options");
159 usage(EXIT_FAILURE);
160 }
161 break;
162
163 case 'v':
164 version();
165 exit(0);
166 break;
167
168 case 'h':
169 usage(EXIT_SUCCESS);
170 default:
171 usage(EXIT_FAILURE);
172 }
173 }
174
175 ac_init(AC_ALL);
176
177 /* ------------------------------------------------------------
178 *
179 * fill out defaults for info structure
180 *
181 * ------------------------------------------------------------*/
182
183 // assume defaults
184 if(name==NULL) stream_stype=TC_STYPE_STDIN;
185
186 // no autodetection yet
187 if(codec==NULL && magic==NULL) {
188 tc_log_error(EXE, "invalid codec %s", codec);
189 usage(EXIT_FAILURE);
190 }
191
192 if(codec==NULL) codec="";
193
194 // do not try to mess with the stream
195 if(stream_stype!=TC_STYPE_STDIN) {
196
197 if(tc_file_check(name)) exit(1);
198
199 if((ipipe.fd_in = xio_open(name, O_RDONLY))<0) {
200 tc_log_perror(EXE, "file open");
201 return(-1);
202 }
203
204 stream_magic = fileinfo(ipipe.fd_in, 0);
205
206 if(verbose & TC_DEBUG)
207 tc_log_msg(EXE, "(pid=%d) %s", getpid(), filetype(stream_magic));
208
209 } else ipipe.fd_in = STDIN_FILENO;
210
211 if(verbose & TC_DEBUG)
212 tc_log_msg(EXE, "(pid=%d) starting, doing %s", getpid(), codec);
213
214 // fill out defaults for info structure
215 ipipe.fd_out = STDOUT_FILENO;
216
217 ipipe.magic = stream_magic;
218 ipipe.stype = stream_stype;
219 ipipe.codec = stream_codec;
220 ipipe.track = track;
221 ipipe.select = TC_VIDEO;
222
223 ipipe.verbose = verbose;
224
225 ipipe.name = name;
226
227 /* ------------------------------------------------------------
228 *
229 * codec specific section
230 *
231 * note: user provided magic values overwrite autodetection!
232 *
233 * ------------------------------------------------------------*/
234
235 if(magic==NULL) magic="";
236
237 // OGM
238
239 if (ipipe.magic == TC_MAGIC_OGG) {
240
241 // dummy for video
242 if(strcmp(codec, "raw")==0) ipipe.codec = TC_CODEC_RGB;
243 if((strcmp(codec, "vorbis")==0) || (strcmp(codec, "ogg")==0)) {
244 ipipe.codec = TC_CODEC_VORBIS;
245 ipipe.select = TC_AUDIO;
246 }
247 if(strcmp(codec, "mp3")==0) {
248 ipipe.codec = TC_CODEC_MP3;
249 ipipe.select = TC_AUDIO;
250 }
251 if(strcmp(codec, "pcm")==0) {
252 ipipe.codec = TC_CODEC_PCM;
253 ipipe.select = TC_AUDIO;
254 }
255
256 extract_ogm(&ipipe);
257 done = 1;
258 }
259
260 // MPEG2
261 if(strcmp(codec,"mpeg2")==0) {
262
263 ipipe.codec = TC_CODEC_MPEG2;
264
265 if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
266 if(strcmp(magic, "m2v")==0) ipipe.magic = TC_MAGIC_M2V;
267 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
268
269 extract_mpeg2(&ipipe);
270 done = 1;
271 }
272
273 // PCM
274 if(strcmp(codec,"pcm")==0) {
275
276 ipipe.codec = TC_CODEC_PCM;
277 ipipe.select = TC_AUDIO;
278
279 if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
280 if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
281 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
282 if(strcmp(magic, "wav")==0) ipipe.magic = TC_MAGIC_WAV;
283
284 extract_pcm(&ipipe);
285 done = 1;
286 }
287
288 // SUBTITLE (private_stream_1)
289 if(strcmp(codec,"ps1")==0) {
290
291 ipipe.codec = TC_CODEC_PS1;
292 ipipe.select = TC_AUDIO;
293
294 if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
295 if(strcmp(magic, "vdr")==0) ipipe.magic = TC_MAGIC_VDR;
296
297 extract_ac3(&ipipe);
298 done = 1;
299 }
300
301
302 // DV
303 if(strcmp(codec,"dv")==0) {
304
305 ipipe.codec = TC_CODEC_DV;
306
307 if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
308 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
309
310 extract_dv(&ipipe);
311 done = 1;
312 }
313
314
315 // RGB
316 if(strcmp(codec,"rgb")==0) {
317
318 ipipe.codec = TC_CODEC_RGB;
319
320 if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
321 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
322 if(strcmp(magic, "wav")==0) ipipe.magic = TC_MAGIC_WAV;
323
324 extract_rgb(&ipipe);
325 done = 1;
326 }
327
328
329 // DTS
330 if(strcmp(codec,"dts")==0) {
331
332 ipipe.codec = TC_CODEC_DTS;
333 ipipe.select = TC_AUDIO;
334
335 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
336 if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
337
338 extract_ac3(&ipipe);
339 done = 1;
340 }
341
342 // AC3
343 if(strcmp(codec,"ac3")==0) {
344
345 ipipe.codec = TC_CODEC_AC3;
346 ipipe.select = TC_AUDIO;
347
348 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
349 if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
350
351 extract_ac3(&ipipe);
352 done = 1;
353 }
354
355 // MP3
356 if(strcmp(codec,"mp3")==0 || strcmp(codec,"mp2")==0) {
357
358 ipipe.codec = TC_CODEC_MP3;
359 ipipe.select = TC_AUDIO;
360
361 if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
362 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
363 if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB;
364
365 extract_mp3(&ipipe);
366 done = 1;
367 }
368
369 // YUV420P
370 if(strcmp(codec,"yuv420p")==0) {
371
372 ipipe.codec = TC_CODEC_YUV420P;
373
374 if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
375 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
376 if(strcmp(magic, "yuv4mpeg")==0) ipipe.magic = TC_MAGIC_YUV4MPEG;
377
378 extract_yuv(&ipipe);
379 done = 1;
380 }
381
382 // YUV422P
383 if(strcmp(codec,"yuv422p")==0) {
384
385 ipipe.codec = TC_CODEC_YUV422P;
386
387 if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
388 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
389 if(strcmp(magic, "yuv4mpeg")==0) ipipe.magic = TC_MAGIC_YUV4MPEG;
390
391 extract_yuv(&ipipe);
392 done = 1;
393 }
394
395 // UYVY
396 if(strcmp(codec,"uyvy")==0) {
397
398 ipipe.codec = TC_CODEC_UYVY;
399
400 if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
401 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
402
403 extract_yuv(&ipipe);
404 done = 1;
405 }
406
407
408 // LZO
409 if(strcmp(codec,"lzo")==0) {
410
411 ipipe.codec = TC_CODEC_YUV420P;
412
413 if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI;
414 if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW;
415
416 extract_lzo(&ipipe);
417 done = 1;
418 }
419
420
421 // AVI extraction
422
423 //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)
424 if ((strcmp(magic, "avi")==0 || ipipe.magic==TC_MAGIC_AVI)&& (codec == NULL)) {
425
426 ipipe.magic=TC_MAGIC_AVI;
427 extract_avi(&ipipe);
428 done = 1;
429 }
430
431 if (strcmp(codec, "raw")==0 || strcmp(codec, "video")==0) {
432 ipipe.select=TC_VIDEO-1;
433 ipipe.magic=TC_MAGIC_AVI;
434 extract_avi(&ipipe);
435 done = 1;
436 }
437
438
439 if(!done) {
440 tc_log_error(EXE, "(pid=%d) unable to handle codec %s", getpid(), codec);
441 exit(1);
442 }
443
444 if(ipipe.fd_in != STDIN_FILENO) xio_close(ipipe.fd_in);
445
446 return(0);
447 }
448
449 #include "libtc/static_xio.h"
450