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