7f3ad62756008bea2f0cb841913a17505694ed25
[swftools.git] / lib / example / avi2swf.cc
1 /* avi2swf.cc
2    Convert avi movie files into swf.
3    As soon as there's an algorithm implemented for writing the
4    data directly to disk, this file should maybe go to ../src.
5
6    Part of the swftools package.
7    
8    Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
9
10    This file is distributed under the GPL, see file COPYING for details */
11
12 #include <stdio.h>
13 #include <fcntl.h>
14 extern "C" {
15 #include "../rfxswf.h"
16 #include "../args.h"
17 }
18 #include "avifile.h"
19 #include "aviplay.h"
20
21 char * filename = 0;
22 char * outputfilename = "output.swf";
23
24 struct options_t options[] =
25 {
26  {"v","verbose"},
27  {"o","output"},
28  {"V","version"},
29  {0,0}
30 };
31
32 int args_callback_option(char*name,char*val)
33 {
34     if(!strcmp(name, "V")) {
35         printf("avi2swf - part of %s %s\n", PACKAGE, VERSION);
36         exit(0);
37     } else 
38     if(!strcmp(name, "o")) {
39         outputfilename = val;
40         return 1;
41     }
42 }
43 int args_callback_longoption(char*name,char*val)
44 {
45     return args_long2shortoption(options, name, val);
46 }
47 void args_callback_usage(char*name)
48 {    
49     printf("\nUsage: %s file.swf\n", name);
50     printf("\t-h , --help\t\t Print help and exit\n");
51     printf("\t-o , --output=filename\t Specify output filename\n"); 
52     printf("\t-V , --version\t\t Print program version and exit\n");
53     exit(0);
54 }
55 int args_callback_command(char*name,char*val)
56 {
57     if(filename) {
58         fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
59                  filename, name);
60     }
61     filename = name;
62     return 0;
63 }
64
65 SWF swf;
66 TAG*tag;
67
68 int main (int argc,char ** argv)
69 { int f;
70   IAviReadFile* player;
71   IAviReadStream* astream;
72   IAviReadStream* vstream;
73   MainAVIHeader head;
74   SRECT r;
75   memset(&swf, 0, sizeof(swf));
76
77   processargs(argc, argv);
78   if(!filename)
79       exit(0);
80
81   player = CreateIAviReadFile(filename);    
82   player->GetFileHeader(&head);
83   printf("fps: %d\n", 1000000/head.dwMicroSecPerFrame);
84   printf("frames: %d\n", head.dwTotalFrames);
85   printf("streams: %d\n", head.dwStreams);
86   printf("streams: %d\n", player->StreamCount());
87   printf("width: %d\n", head.dwWidth);
88   printf("height: %d\n", head.dwHeight);
89   
90   astream = player->GetStream(0, AviStream::Audio);
91   vstream = player->GetStream(0, AviStream::Video);
92
93   vstream -> StartStreaming();
94   
95   swf.frameRate = (int)(1000000.0/head.dwMicroSecPerFrame*256);
96   swf.fileVersion = 4;
97   r.xmin = 0;
98   r.ymin = 0;
99   r.xmax = head.dwWidth*20;
100   r.ymax = head.dwHeight*20;
101   swf.movieSize = r;
102   tag = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR);
103   swf.firstTag = tag;
104   swf_SetU8(tag,0); //black
105   swf_SetU8(tag,0);
106   swf_SetU8(tag,0);
107
108   U8*newdata = (U8*)malloc((head.dwWidth+3) * head.dwHeight * 4);
109
110   int frame = 0;
111
112   int lastsize = (head.dwWidth+3) * head.dwHeight * 4;
113   U8* lastdata = (U8*)malloc(lastsize);
114   U8* data;
115   memset(lastdata,0, lastsize);
116
117   while(1) {
118     if(vstream->ReadFrame()<0) {
119         printf("\n");
120         break;
121     }
122     printf("\rconvert frame %d",frame);
123     fflush(stdout);
124     CImage*img = vstream->GetFrame();
125     img->ToRGB();
126     data = img->data();
127     int width = img->width();
128     int bpp = img->bpp();
129     int width4 = width*4;
130     int height = img->height();
131     int x,y;
132     int fs,ls;
133     SHAPE*s;
134     MATRIX m;
135     SRECT r;
136     RGBA rgb;
137
138     if(frame!=0) {
139         tag = swf_InsertTag(tag, ST_REMOVEOBJECT2);
140         swf_SetU16(tag, 1); //depth
141     }
142
143     /* todo: dynamically decide whether to generate jpeg/lossless
144        bitmaps, (using transparency to modify the previous 
145        picture), and which jpeg compression depth to use.
146        (btw: Are there video frame transitions which can
147         reasonably approximated by shapes?)
148      */
149
150     int type = 1;
151     int rel = 0;
152     if(type == 0) {
153         tag = swf_InsertTag(tag, ST_DEFINEBITSLOSSLESS);
154         swf_SetU16(tag, frame*2);
155         U8*mylastdata = lastdata;
156         for(y=0;y<height;y++) {
157             U8*nd = &newdata[width4*y];
158             U8*mydata = img->at(y);
159             if(!rel)
160             for(x=0;x<width;x++) {
161                 nd[3]=mydata[0];
162                 nd[2]=mydata[1];
163                 nd[1]=mydata[2];
164                 mylastdata[2] = mydata[2];
165                 mylastdata[1] = mydata[1];
166                 mylastdata[0] = mydata[0];
167                 nd+=4;
168                 mydata+=3;
169                 mylastdata+=3;
170             }
171             else
172             for(x=0;x<width;x++) {
173                 int a = mylastdata[3]-data[3];
174                 int b = mylastdata[2]-data[2];
175                 int c = mylastdata[1]-data[1];
176                 if((a*a+b*b+c*c)>64)
177                 {
178                     nd[3]=mydata[0];
179                     nd[2]=mydata[1];
180                     nd[1]=mydata[2];
181                     nd[0]=255;
182                 } else {
183                     nd[3]=0;
184                     nd[2]=0;
185                     nd[1]=0;
186                     nd[0]=0;
187                 }
188                 mylastdata[2] = mydata[2];
189                 mylastdata[1] = mydata[1];
190                 mylastdata[0] = mydata[0];
191                 nd+=4;
192                 mydata+=3;
193                 mylastdata+=3;
194             }
195         }
196         swf_SetLosslessBits(tag,width,height,newdata,BMF_32BIT);
197     } else 
198     if(type == 1) {
199         tag = swf_InsertTag(tag, ST_DEFINEBITSJPEG2);
200         swf_SetU16(tag, frame*2);
201         JPEGBITS * jb = swf_SetJPEGBitsStart(tag,width,height,1);
202         U8*mylastdata = lastdata;
203         for(y=0;y<height;y++) {
204             U8*nd = newdata;
205             U8*mydata = img->at(y);
206             for(x=0;x<width;x++) {
207                 nd[0] = mydata[2];
208                 nd[1] = mydata[1];
209                 nd[2] = mydata[0];
210                 if(rel) {
211                     nd[0] = (mydata[2]-mylastdata[2])/2+0x80;
212                     nd[1] = (mydata[1]-mylastdata[1])/2+0x80;
213                     nd[2] = (mydata[0]-mylastdata[0])/2+0x80;
214                 }
215                 mylastdata[2] = mydata[2];
216                 mylastdata[1] = mydata[1];
217                 mylastdata[0] = mydata[0];
218                 nd+=3;
219                 mydata+=3;
220                 mylastdata+=3;
221             }
222             swf_SetJPEGBitsLine(jb,newdata);
223         }
224         swf_SetJPEGBitsFinish(jb);
225     }
226
227     tag = swf_InsertTag(tag, ST_DEFINESHAPE);
228     swf_ShapeNew(&s);
229     rgb.b = rgb.g = rgb.r = 0xff;
230     ls = swf_ShapeAddLineStyle(s,20,&rgb);  
231     swf_GetMatrix(NULL,&m);
232     m.sx = 20*65536;
233     m.sy = 20*65536;
234
235     fs = swf_ShapeAddBitmapFillStyle(s,&m,frame*2,0);
236     swf_SetU16(tag ,frame*2+1);   // ID   
237     r.xmin = 0;
238     r.ymin = 0;
239     r.xmax = width*20;
240     r.ymax = height*20;
241     swf_SetRect(tag,&r);
242
243     swf_SetShapeStyles(tag,s);
244     swf_ShapeCountBits(s,NULL,NULL);
245     swf_SetShapeBits(tag,s);
246
247     swf_ShapeSetAll(tag,s,0,0,ls,fs,0);
248
249     swf_ShapeSetLine(tag,s,width*20,0);
250     swf_ShapeSetLine(tag,s,0,height*20);
251     swf_ShapeSetLine(tag,s,-width*20,0);
252     swf_ShapeSetLine(tag,s,0,-height*20);
253     swf_ShapeSetEnd(tag);
254
255     tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
256         swf_ObjectPlace(tag,frame*2+1,1,0,0,0);
257
258     tag = swf_InsertTag(tag, ST_SHOWFRAME);
259
260 /*    frame++;
261     if(frame == 200)
262         break;*/
263   }
264   free(newdata);
265   
266   tag = swf_InsertTag(tag, ST_END);
267
268   f = open(outputfilename,O_WRONLY|O_CREAT|O_TRUNC, 0644);
269   if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n");
270   close(f);
271
272   swf_FreeTags(&swf);                       // cleanup
273
274   return 0;
275 }
276