1 /*
2  *  tcdecode.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 
29 #include "ioaux.h"
30 #include "tc.h"
31 #include "libtc/xio.h"
32 
33 #define EXE "tcdecode"
34 
35 extern long fileinfo(int fd, int skip);
36 
37 int verbose = TC_QUIET;
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  *
49  * print a usage/version message
50  *
51  * ------------------------------------------------------------*/
52 
53 
version(void)54 void version(void)
55 {
56     /* print id string to stderr */
57     fprintf(stderr, "%s (%s v%s) (C) 2001-2003 Thomas Oestreich,"
58                                     " 2003-2010 Transcode Team\n",
59                     EXE, PACKAGE, VERSION);
60 }
61 
62 
usage(int status)63 static void usage(int status)
64 {
65   version();
66 
67   fprintf(stderr,"\nUsage: %s [options]\n", EXE);
68 
69   fprintf(stderr,"    -i file           input file [stdin]\n");
70   fprintf(stderr,"    -x codec          source codec (required)\n");
71   fprintf(stderr,"    -t package        codec package\n");
72   fprintf(stderr,"    -g wxh            stream frame size [autodetect]\n");
73   fprintf(stderr,"    -y format         output raw stream format [rgb]\n");
74   fprintf(stderr,"    -Q mode           decoding quality (0=fastest-5=best) [%d]\n", VQUALITY);
75   fprintf(stderr,"    -d mode           verbosity mode\n");
76   fprintf(stderr,"    -s c,f,r          audio gain for ac3 downmixing [1,1,1]\n");
77   fprintf(stderr,"    -A n              A52 decoder flag [0]\n");
78   fprintf(stderr,"    -C s,e            decode only from start to end ((V) frames/(A) bytes) [all]\n");
79   fprintf(stderr,"    -Y                use libdv YUY2 decoder mode\n");
80   fprintf(stderr,"    -z r              convert zero padding to silence\n");
81   fprintf(stderr,"    -v                print version\n");
82 
83   exit(status);
84 }
85 
86 /* ------------------------------------------------------------
87  *
88  * universal decode thread frontend
89  *
90  * ------------------------------------------------------------*/
91 
main(int argc,char * argv[])92 int main(int argc, char *argv[])
93 {
94     decode_t decode;
95     int ch, done=0;
96     char *codec=NULL, *format="rgb", *magic="none";
97 
98     memset(&decode, 0, sizeof(decode));
99     decode.magic = TC_MAGIC_UNKNOWN;
100     decode.stype = TC_STYPE_UNKNOWN;
101     decode.quality = VQUALITY;
102     decode.ac3_gain[0] = decode.ac3_gain[1] = decode.ac3_gain[2] = 1.0;
103     decode.frame_limit[0]=0;
104     decode.frame_limit[1]=LONG_MAX;
105 
106     libtc_init(&argc, &argv);
107 
108     while ((ch = getopt(argc, argv, "Q:t:d:x:i:a:g:vy:s:YC:A:z:?h")) != -1) {
109 	switch (ch) {
110 
111 	case 'i':
112 	  if (optarg[0]=='-') usage(EXIT_FAILURE);
113 	  decode.name = optarg;
114 	  break;
115 
116 	case 'd':
117 	  if (optarg[0]=='-') usage(EXIT_FAILURE);
118 	  verbose = atoi(optarg);
119 	  break;
120 
121 	case 'Q':
122 	  if (optarg[0]=='-') usage(EXIT_FAILURE);
123 	  decode.quality = atoi(optarg);
124 	  break;
125 
126 	case 'A':
127 	  if (optarg[0]=='-') usage(EXIT_FAILURE);
128 	  decode.a52_mode = atoi(optarg);
129 	  break;
130 
131 	case 'x':
132 	  if (optarg[0]=='-') usage(EXIT_FAILURE);
133 	  codec = optarg;
134 	  break;
135 
136 	case 't':
137 	  if (optarg[0]=='-') usage(EXIT_FAILURE);
138 	  magic = optarg;
139 	  break;
140 
141 	case 'y':
142 	  if (optarg[0]=='-') usage(EXIT_FAILURE);
143 	  format = optarg;
144 	  break;
145 
146 	case 'g':
147 	  if (optarg[0]=='-') usage(EXIT_FAILURE);
148 	  if (2 != sscanf(optarg,"%dx%d", &decode.width, &decode.height)) usage(EXIT_FAILURE);
149 	  break;
150 
151 	case 'v':
152 	  version();
153 	  exit(0);
154 	  break;
155 
156 	case 'Y':
157 	  decode.dv_yuy2_mode=1;
158 	  break;
159 
160 	case 's':
161 	  if(optarg[0]=='-') usage(EXIT_FAILURE);
162 	  if (3 != sscanf(optarg,"%lf,%lf,%lf", &decode.ac3_gain[0], &decode.ac3_gain[1], &decode.ac3_gain[2])) usage(EXIT_FAILURE);
163 	  break;
164 
165 	case 'C':
166 	  if(optarg[0]=='-') usage(EXIT_FAILURE);
167 	  if (2 != sscanf(optarg,"%ld,%ld", &decode.frame_limit[0], &decode.frame_limit[1])) usage(EXIT_FAILURE);
168  	  if (decode.frame_limit[0] >= decode.frame_limit[1])
169 	  {
170   		tc_log_error(EXE, "Invalid -C options");
171 		usage(EXIT_FAILURE);
172 	  }
173 	  break;
174 
175 	case 'z':
176 	  if(optarg[0]=='-') usage(EXIT_FAILURE);
177 	  decode.padrate = atoi(optarg);
178 	  break;
179 
180 	case 'h':
181 	  usage(EXIT_SUCCESS);
182 	default:
183 	  usage(EXIT_FAILURE);
184 	}
185     }
186 
187     ac_init(AC_ALL);
188 
189     /* ------------------------------------------------------------
190      *
191      * fill out defaults for info structure
192      *
193      * ------------------------------------------------------------*/
194 
195     // assume defaults
196     if(decode.name==NULL) decode.stype=TC_STYPE_STDIN;
197 
198     // no autodetection yet
199     if(codec==NULL) {
200 	tc_log_error(EXE, "codec must be specified");
201 	usage(EXIT_FAILURE);
202     }
203 
204     // do not try to mess with the stream
205     if (decode.stype != TC_STYPE_STDIN) {
206 	if (tc_file_check(decode.name)) exit(1);
207 	if ((decode.fd_in = xio_open(decode.name, O_RDONLY)) < 0) {
208 	    tc_log_perror(EXE, "open file");
209 	    exit(1);
210 	}
211 
212 	// try to find out the filetype
213 	decode.magic = fileinfo(decode.fd_in, 0);
214 	if (verbose)
215 	    tc_log_msg(EXE, "(pid=%d) %s", getpid(), filetype(decode.magic));
216 
217     } else decode.fd_in = STDIN_FILENO;
218 
219     decode.fd_out = STDOUT_FILENO;
220     decode.codec = TC_CODEC_UNKNOWN;
221     decode.verbose = verbose;
222     if (decode.width < 0) decode.width = 0;
223     if (decode.height < 0) decode.height = 0;
224 
225     /* ------------------------------------------------------------
226      *
227      * output raw stream format
228      *
229      * ------------------------------------------------------------*/
230 
231     if (!strcmp(format, "rgb")) decode.format = TC_CODEC_RGB;
232     else if (!strcmp(format, "yuv420p")) decode.format = TC_CODEC_YUV420P;
233     else if (!strcmp(format, "yuv2")) decode.format = TC_CODEC_YUV2;
234     else if (!strcmp(format, "yuy2")) decode.format = TC_CODEC_YUY2;
235     else if (!strcmp(format, "pcm")) decode.format = TC_CODEC_PCM;
236     else if (!strcmp(format, "raw")) decode.format = TC_CODEC_RAW;
237 
238     /* ------------------------------------------------------------
239      *
240      * codec specific section
241      *
242      * note: user provided values overwrite autodetection!
243      *
244      * ------------------------------------------------------------*/
245 
246     // FFMPEG can decode a lot
247     if(!strcmp(magic, "ffmpeg") || !strcmp(magic, "lavc")) {
248 	if (!strcmp(codec, "mpeg2")) decode.codec = TC_CODEC_MPEG2;
249 	else if (!strcmp(codec, "mpeg2video")) decode.codec = TC_CODEC_MPEG2;
250 	else if (!strcmp(codec, "mpeg1video")) decode.codec = TC_CODEC_MPEG1;
251 	else if (!strcmp(codec, "divx3")) decode.codec = TC_CODEC_DIVX3;
252 	else if (!strcmp(codec, "divx")) decode.codec = TC_CODEC_DIVX4;
253 	else if (!strcmp(codec, "divx4")) decode.codec = TC_CODEC_DIVX4;
254 	else if (!strcmp(codec, "mp42")) decode.codec = TC_CODEC_MP42;
255 	else if (!strcmp(codec, "mjpg")) decode.codec = TC_CODEC_MJPEG;
256 	else if (!strcmp(codec, "mjpeg")) decode.codec = TC_CODEC_MJPEG;
257 	else if (!strcmp(codec, "rv10")) decode.codec = TC_CODEC_RV10;
258 	else if (!strcmp(codec, "svq1")) decode.codec = TC_CODEC_SVQ1;
259 	else if (!strcmp(codec, "svq3")) decode.codec = TC_CODEC_SVQ3;
260 	else if (!strcmp(codec, "vp3")) decode.codec = TC_CODEC_VP3;
261 	else if (!strcmp(codec, "4xm")) decode.codec = TC_CODEC_4XM;
262 	else if (!strcmp(codec, "wmv1")) decode.codec = TC_CODEC_WMV1;
263 	else if (!strcmp(codec, "wmv2")) decode.codec = TC_CODEC_WMV2;
264 	else if (!strcmp(codec, "hfyu")) decode.codec = TC_CODEC_HUFFYUV;
265 	else if (!strcmp(codec, "indeo3")) decode.codec = TC_CODEC_INDEO3;
266 	else if (!strcmp(codec, "h263p")) decode.codec = TC_CODEC_H263P;
267 	else if (!strcmp(codec, "h263i")) decode.codec = TC_CODEC_H263I;
268 	else if (!strcmp(codec, "dvvideo")) decode.codec = TC_CODEC_DV;
269 	else if (!strcmp(codec, "dv")) decode.codec = TC_CODEC_DV;
270 	else if (!strcmp(codec, "vag")) decode.codec = TC_CODEC_VAG;
271 
272 	decode_lavc(&decode);
273     }
274 
275     // MPEG2
276     if (!strcmp(codec, "mpeg2")) {
277 	decode.codec = TC_CODEC_MPEG2;
278 	decode_mpeg2(&decode);
279 	done = 1;
280     }
281 
282     // OGG
283     if (!strcmp(codec, "ogg")) {
284 	decode.codec = TC_CODEC_VORBIS;
285 	decode_ogg(&decode);
286 	done = 1;
287     }
288 
289     // AC3
290     if (!strcmp(codec, "ac3")) {
291 	decode.codec = TC_CODEC_AC3;
292 	decode_a52(&decode);
293 	done = 1;
294     }
295 
296     // MP3
297     if (!strcmp(codec, "mp3")) {
298 	decode.codec = TC_CODEC_MP3;
299 	decode_mp3(&decode);
300 	done = 1;
301     }
302 
303     // MP2
304     if (!strcmp(codec, "mp2")) {
305 	decode.codec = TC_CODEC_MP3;
306 	decode_mp2(&decode);
307 	done = 1;
308     }
309 
310     // DV
311     if (!strcmp(codec, "dv")) {
312 	decode.codec = TC_CODEC_DV;
313 	decode_dv(&decode);
314 	done = 1;
315     }
316 
317     // YUV420P
318     if (!strcmp(codec, "yuv420p")) {
319 	decode.codec = TC_CODEC_YUV420P;
320 	decode_yuv(&decode);
321 	done = 1;
322     }
323 
324 #if 0
325     // DivX Video
326     if (!strcmp(codec, "divx")) {
327       decode.select = TC_VIDEO;
328       decode_divx(&decode);
329       done = 1;
330     }
331 #endif
332 
333     // MOV
334     if (!strcmp(codec, "mov")) {
335       decode_mov(&decode);
336       done = 1;
337     }
338 
339     // LZO
340     if (!strcmp(codec, "lzo")) {
341       decode_lzo(&decode);
342       done = 1;
343     }
344 
345     if(!done) {
346 	tc_log_error(EXE, "(pid=%d) unable to handle codec %s", getpid(), codec);
347 	exit(1);
348     }
349 
350     if (decode.fd_in != STDIN_FILENO) xio_close(decode.fd_in);
351 
352     return 0;
353 }
354 
355 #include "libtc/static_xio.h"
356