moved avifile stuff into videoreader_avifile.cc
[swftools.git] / avi2swf / avi2swf.cc
1 /* avi2swf.cc
2    Convert avi movie files into swf.
3
4    Part of the swftools package.
5    
6    Copyright (c) 2001,2002,2003 Matthias Kramm <kramm@quiss.org>
7  
8    This program 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 of the License, or
11    (at your option) any later version.
12
13    This program 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 this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <fcntl.h>
26
27 #include "../config.h"
28
29 #ifdef HAVE_SIGNAL_H
30 #ifdef HAVE_PTHREAD_H
31 #include <pthread.h>
32 #include <signal.h>
33 #define DO_SIGNALS
34 #endif
35 #endif
36
37 extern "C" {
38 #include "../lib/args.h"
39 }
40 #include "v2swf.h"
41 #include "videoreader_avifile.hh"
42
43 static char * filename = 0;
44 static char * outputfilename = "output.swf";
45 int verbose = 0;
46
47 static int quality = 80;
48 static double scale = 1.0;
49 static int flip = 0;
50 static int expensive = 0;
51 static int flashversion = 6;
52 static int keyframe_interval = -1;
53 static int skip = 0;
54 static float audio_adjust = 0;
55 static int mp3_bitrate = 32;
56 static int samplerate = 11025;
57
58 static struct options_t options[] = {
59 {"h", "help"},
60 {"o", "output"},
61 {"A", "adjust"},
62 {"n", "num"},
63 {"m", "mp3-bitrate"},
64 {"r", "mp3-samplerate"},
65 {"d", "scale"},
66 {"p", "flip"},
67 {"q", "quality"},
68 {"x", "extragood"},
69 {"T", "flashversion"},
70 {"V", "version"},
71 {0,0}
72 };
73
74 int args_callback_option(char*name,char*val)
75 {
76     if(!strcmp(name, "V")) {
77         printf("avi2swf-ng - part of %s %s\n", PACKAGE, VERSION);
78         exit(0);
79     } 
80     else if(!strcmp(name, "o")) {
81         outputfilename = val;
82         return 1;
83     }
84     else if(!strcmp(name, "q")) {
85         quality = atoi(val);
86         if(quality<0)
87             quality = 0;
88         if(quality>100)
89             quality = 100;
90         return 1;
91     }
92     else if(!strcmp(name, "p")) {
93         flip = 1;
94         return 0;
95     }
96     else if(!strcmp(name, "A")) {
97         audio_adjust = atof(val);
98         return 1;
99     }
100     else if(!strcmp(name, "v")) {
101         verbose = 1;
102         return 0;
103     }
104     else if(!strcmp(name, "T")) {
105         flashversion = atoi(val);
106         return 1;
107     }
108     else if(!strcmp(name, "x")) {
109         expensive = 1;
110         return 0;
111     }
112     else if(!strcmp(name, "m")) {
113         mp3_bitrate = atoi(val);
114         return 0;
115     }
116     else if(!strcmp(name, "r")) {
117         samplerate = atoi(val);
118         if(samplerate >= 11000 && samplerate <= 12000)
119             samplerate = 11025;
120         else if(samplerate >= 22000 && samplerate <= 23000)
121             samplerate = 22050;
122         else if(samplerate >= 44000 && samplerate <= 45000)
123             samplerate = 44100;
124         else {
125             fprintf(stderr, "Invalid samplerate: %d\n", samplerate);
126             fprintf(stderr, "Allowed values: 11025, 22050, 44100\n", samplerate);
127             exit(1);
128         }
129         return 1;
130     }
131     else if(!strcmp(name, "S")) {
132         skip = atoi(val);
133         return 1;
134     }
135     else if(!strcmp(name, "s")) {
136         scale = atoi(val)/100.0;
137         if(scale>1.0 || scale<=0) {
138             fprintf(stderr, "Scale must be in the range 1-100!\n");
139             exit(1);
140         }
141         return 1;
142     }
143     fprintf(stderr, "Unknown option: -%s\n", name);
144     exit(1);
145 }
146 int args_callback_longoption(char*name,char*val)
147 {
148     return args_long2shortoption(options, name, val);
149 }
150 void args_callback_usage(char *name)
151 {
152     printf("\n");
153     printf("Usage: %s file.avi [-o output.swf]\n", name);
154     printf("\n");
155     printf("-h , --help                    Print help and exit\n");
156     printf("-o , --output filename         Specify output filename\n");
157     printf("-A , --adjust seconds          Audio adjust: Shift sound -seconds to the future or +seconds into the past.\n");
158     printf("-n , --num frames              Number of frames to encode\n");
159     printf("-m , --mp3-bitrate <rate> (kbps)    Set the mp3 bitrate to encode audio with\n");
160     printf("-r , --mp3-samplerate <rate> (Hz)    Set the mp3 samplerate to encode audio with (default: 11025)\n");
161     printf("-d , --scale <val>             Scale down to factor <val>. (in %, e.g. 100 = original size)\n");
162     printf("-p , --flip                    Turn movie upside down\n");
163     printf("-q , --quality <val>           Set the quality to <val>. (0-100, 0=worst, 100=best, default:80)\n");
164     printf("-x , --extragood               Enable some *very* expensive compression strategies.\n");
165     printf("-T , --flashversion <n>        Set output flash version to <n>.\n");
166     printf("-V , --version                 Print program version and exit\n");
167     printf("\n");
168 }
169 int args_callback_command(char*name,char*val)
170 {
171     if(filename) {
172         fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
173                  filename, name);
174     }
175     filename = name;
176     return 0;
177 }
178
179 static char toabuf[128];
180 static char*ftoa(double a)
181 {
182     sprintf(toabuf, "%f", a);
183     return toabuf;
184 }
185 static char*itoa(int a)
186 {
187     sprintf(toabuf, "%d", a);
188     return toabuf;
189 }
190
191 static int shutdown_avi2swf = 0;
192 static int frameno = 0;
193
194 #ifdef DO_SIGNALS
195 pthread_t main_thread;
196 static void sigterm(int sig)
197 {
198     if(pthread_equal (pthread_self(), main_thread))
199     {
200         if(frameno>0 && !shutdown_avi2swf) {
201             if(verbose)
202                 printf("Thread [%08x] got sigterm %d\n", pthread_self(), sig);
203             shutdown_avi2swf++;
204         } else {
205             exit(1);
206         }
207     }
208 }
209 #endif
210
211 int main (int argc,char ** argv)
212
213     videoreader_t video;
214     v2swf_t v2swf;
215     int ret;
216     FILE*fi;
217
218 #ifdef DO_SIGNALS
219     signal(SIGTERM, sigterm);
220     signal(SIGINT , sigterm);
221     signal(SIGQUIT, sigterm);
222     main_thread = pthread_self();
223 #endif
224
225     processargs(argc, argv);
226     if(!filename)
227         exit(0);
228     if(keyframe_interval<0) {
229         if(flashversion>=6)
230             keyframe_interval=200;
231         else
232             keyframe_interval=5;
233     }
234     
235     fi = fopen(outputfilename, "wb");
236     if(!fi) {
237         fflush(stdout); fflush(stderr);
238         fprintf(stderr, "Couldn't open %s\n", outputfilename);
239         exit(1);
240     }
241
242     ret = videoreader_avifile_open(&video, filename);
243
244     if(!ret) {
245         printf("Error opening %s\n", filename);
246         exit(1);
247     }
248
249     if(verbose) {
250         printf("| video framerate: %f\n", video.fps);
251         printf("| video size: %dx%d\n", video.width, video.height);
252         printf("| audio rate: %d\n", video.rate);
253         printf("| audio channels: %d\n", video.channels);
254     }
255
256     ret = v2swf_init(&v2swf, &video);
257     if(verbose)
258         v2swf_setparameter(&v2swf, "verbose", "1");
259     v2swf_setparameter(&v2swf, "quality", itoa(quality));
260     v2swf_setparameter(&v2swf, "blockdiff", "0");
261     v2swf_setparameter(&v2swf, "blockdiff_mode", "exact");
262     v2swf_setparameter(&v2swf, "mp3_bitrate", itoa(mp3_bitrate));
263     v2swf_setparameter(&v2swf, "samplerate", itoa(samplerate));
264     //v2swf_setparameter(&v2swf, "fixheader", "1");
265     //v2swf_setparameter(&v2swf, "framerate", "15");
266     v2swf_setparameter(&v2swf, "scale", ftoa(scale));
267     v2swf_setparameter(&v2swf, "prescale", "1");
268     v2swf_setparameter(&v2swf, "flash_version", itoa(flashversion));
269     v2swf_setparameter(&v2swf, "keyframe_interval", itoa(keyframe_interval));
270     if(expensive)
271         v2swf_setparameter(&v2swf, "motioncompensation", "1");
272
273     if(!verbose)
274         printf("\n");
275
276     if(audio_adjust>0) {
277         int num = ((int)(audio_adjust*video.rate))*video.channels*2;
278         void*buf = malloc(num);
279         video.getsamples(&video, buf, num);
280         free(buf);
281     } else if(audio_adjust<0) {
282         int num = (int)(-audio_adjust*video.fps);
283         void*buf = malloc(video.width*video.height*4);
284         int t;
285         for(t=0;t<num;t++) {
286             video.getimage(&video, buf);
287         }
288         free(buf);
289     }
290
291     if(skip) {
292         int t;
293         void*buf = malloc(video.width*video.height*4);
294         for(t=0;t<skip;t++) {
295             video.getimage(&video, buf);
296             video.getsamples(&video, buf, (int)((video.rate/video.fps)*video.channels*2));
297             if(!verbose) {
298                 printf("\rSkipping frame %d", frameno);fflush(stdout);
299             }
300         }
301         free(buf);
302     }
303
304     char buffer[4096];
305     while(1) {
306         int l=v2swf_read(&v2swf, buffer, 4096);
307         fwrite(buffer, l, 1, fi);
308         if(!l)
309             break;
310         if(!verbose) {
311             printf("\rConverting frame %d", frameno);fflush(stdout);
312         }
313     }
314     if(!verbose)
315         printf("\n");
316     fclose(fi);
317     v2swf_backpatch(&v2swf, outputfilename);
318     v2swf_close(&v2swf);
319 }
320