Initial revision
[ffmpeg.git] / libav / swf.c
1 /*
2  * Flash Compatible Streaming Format
3  * Copyright (c) 2000 Gerard Lantau.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <errno.h>
23
24 #include "avformat.h"
25
26 #include <assert.h>
27
28 /* should have a generic way to indicate probable size */
29 #define DUMMY_FILE_SIZE   (100 * 1024 * 1024)
30 #define DUMMY_DURATION    600 /* in seconds */
31
32 #define TAG_END           0
33 #define TAG_SHOWFRAME     1
34 #define TAG_DEFINESHAPE   2
35 #define TAG_FREECHARACTER 3
36 #define TAG_PLACEOBJECT   4
37 #define TAG_REMOVEOBJECT  5
38 #define TAG_STREAMHEAD    18
39 #define TAG_STREAMBLOCK   19
40 #define TAG_JPEG2         21
41
42 #define TAG_LONG         0x100
43
44 /* flags for shape definition */
45 #define FLAG_MOVETO      0x01
46 #define FLAG_SETFILL0    0x02
47 #define FLAG_SETFILL1    0x04
48
49 /* character id used */
50 #define BITMAP_ID 0
51 #define SHAPE_ID  1
52
53 typedef struct {
54     long long duration_pos;
55     long long tag_pos;
56     int tag;
57 } SWFContext;
58
59 static void put_swf_tag(AVFormatContext *s, int tag)
60 {
61     SWFContext *swf = s->priv_data;
62     ByteIOContext *pb = &s->pb;
63
64     swf->tag_pos = url_ftell(pb);
65     swf->tag = tag;
66     /* reserve some room for the tag */
67     if (tag & TAG_LONG) {
68         put_le16(pb, 0);
69         put_le32(pb, 0);
70     } else {
71         put_le16(pb, 0);
72     }
73 }
74
75 static void put_swf_end_tag(AVFormatContext *s)
76 {
77     SWFContext *swf = s->priv_data;
78     ByteIOContext *pb = &s->pb;
79     long long pos;
80     int tag_len, tag;
81
82     pos = url_ftell(pb);
83     tag_len = pos - swf->tag_pos - 2;
84     tag = swf->tag;
85     url_fseek(pb, swf->tag_pos, SEEK_SET);
86     if (tag & TAG_LONG) {
87         tag &= ~TAG_LONG;
88         put_le16(pb, (tag << 6) | 0x3f);
89         put_le32(pb, tag_len - 4);
90     } else {
91         assert(tag_len < 0x3f);
92         put_le16(pb, (tag << 6) | tag_len);
93     }
94     url_fseek(pb, pos, SEEK_SET);
95 }
96
97 static inline void max_nbits(int *nbits_ptr, int val)
98 {
99     int n;
100
101     if (val == 0)
102         return;
103     val = abs(val);
104     n = 1;
105     while (val != 0) {
106         n++;
107         val >>= 1;
108     }
109     if (n > *nbits_ptr)
110         *nbits_ptr = n;
111 }
112
113 static void put_swf_rect(ByteIOContext *pb, 
114                          int xmin, int xmax, int ymin, int ymax)
115 {
116     PutBitContext p;
117     UINT8 buf[256];
118     int nbits, mask;
119
120     init_put_bits(&p, buf, sizeof(buf), NULL, NULL);
121     
122     nbits = 0;
123     max_nbits(&nbits, xmin);
124     max_nbits(&nbits, xmax);
125     max_nbits(&nbits, ymin);
126     max_nbits(&nbits, ymax);
127     mask = (1 << nbits) - 1;
128
129     /* rectangle info */
130     put_bits(&p, 5, nbits);
131     put_bits(&p, nbits, xmin & mask);
132     put_bits(&p, nbits, xmax & mask);
133     put_bits(&p, nbits, ymin & mask);
134     put_bits(&p, nbits, ymax & mask);
135     
136     flush_put_bits(&p);
137     put_buffer(pb, buf, p.buf_ptr - p.buf);
138 }
139
140 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
141 {
142     int nbits, mask;
143
144     put_bits(pb, 1, 1); /* edge */
145     put_bits(pb, 1, 1); /* line select */
146     nbits = 2;
147     max_nbits(&nbits, dx);
148     max_nbits(&nbits, dy);
149
150     mask = (1 << nbits) - 1;
151     put_bits(pb, 4, nbits - 2); /* 16 bits precision */
152     if (dx == 0) {
153       put_bits(pb, 1, 0); 
154       put_bits(pb, 1, 1); 
155       put_bits(pb, nbits, dy & mask);
156     } else if (dy == 0) {
157       put_bits(pb, 1, 0); 
158       put_bits(pb, 1, 0); 
159       put_bits(pb, nbits, dx & mask);
160     } else {
161       put_bits(pb, 1, 1); 
162       put_bits(pb, nbits, dx & mask);
163       put_bits(pb, nbits, dy & mask);
164     }
165 }
166
167 #define FRAC_BITS 16
168
169 /* put matrix (not size optimized */
170 static void put_swf_matrix(ByteIOContext *pb,
171                            int a, int b, int c, int d, int tx, int ty)
172 {
173     PutBitContext p;
174     UINT8 buf[256];
175
176     init_put_bits(&p, buf, sizeof(buf), NULL, NULL);
177     
178     put_bits(&p, 1, 1); /* a, d present */
179     put_bits(&p, 5, 20); /* nb bits */
180     put_bits(&p, 20, a);
181     put_bits(&p, 20, d);
182     
183     put_bits(&p, 1, 1); /* b, c present */
184     put_bits(&p, 5, 20); /* nb bits */
185     put_bits(&p, 20, c);
186     put_bits(&p, 20, b);
187
188     put_bits(&p, 5, 20); /* nb bits */
189     put_bits(&p, 20, tx);
190     put_bits(&p, 20, ty);
191
192     flush_put_bits(&p);
193     put_buffer(pb, buf, p.buf_ptr - p.buf);
194 }
195
196 /* XXX: handle audio only */
197 static int swf_write_header(AVFormatContext *s)
198 {
199     SWFContext *swf;
200     ByteIOContext *pb = &s->pb;
201     AVCodecContext *enc, *audio_enc, *video_enc;
202     PutBitContext p;
203     UINT8 buf1[256];
204     int i, width, height, rate;
205
206     swf = malloc(sizeof(SWFContext));
207     if (!swf)
208         return -1;
209     s->priv_data = swf;
210
211     video_enc = NULL;
212     audio_enc = NULL;
213     for(i=0;i<s->nb_streams;i++) {
214         enc = &s->streams[i]->codec;
215         if (enc->codec_type == CODEC_TYPE_AUDIO)
216             audio_enc = enc;
217         else
218             video_enc = enc;
219     }
220
221     if (!video_enc) {
222         /* currenty, cannot work correctly if audio only */
223         width = 320;
224         height = 200;
225         rate = 10 * FRAME_RATE_BASE;
226     } else {
227         width = video_enc->width;
228         height = video_enc->height;
229         rate = video_enc->frame_rate;
230     }
231
232     put_tag(pb, "FWS");
233     put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
234     put_le32(pb, DUMMY_FILE_SIZE); /* dummy size 
235                                       (will be patched if not streamed) */ 
236
237     put_swf_rect(pb, 0, width, 0, height);
238     put_le16(pb, (rate * 256) / FRAME_RATE_BASE); /* frame rate */
239     swf->duration_pos = url_ftell(pb);
240     put_le16(pb, DUMMY_DURATION * (INT64)rate / FRAME_RATE_BASE); /* frame count */
241     
242     /* define a shape with the jpeg inside */
243
244     put_swf_tag(s, TAG_DEFINESHAPE);
245
246     put_le16(pb, SHAPE_ID); /* ID of shape */
247     /* bounding rectangle */
248     put_swf_rect(pb, 0, width, 0, height);
249     /* style info */
250     put_byte(pb, 1); /* one fill style */
251     put_byte(pb, 0x41); /* clipped bitmap fill */
252     put_le16(pb, BITMAP_ID); /* bitmap ID */
253     /* position of the bitmap */
254     put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0, 
255                    0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
256     put_byte(pb, 0); /* no line style */
257     
258     /* shape drawing */
259     init_put_bits(&p, buf1, sizeof(buf1), NULL, NULL);
260     put_bits(&p, 4, 1); /* one fill bit */
261     put_bits(&p, 4, 0); /* zero line bit */
262     
263     put_bits(&p, 1, 0); /* not an edge */
264     put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
265     put_bits(&p, 5, 1); /* nbits */
266     put_bits(&p, 1, 0); /* X */
267     put_bits(&p, 1, 0); /* Y */
268     put_bits(&p, 1, 1); /* set fill style 1 */
269     
270     /* draw the rectangle ! */
271     put_swf_line_edge(&p, width, 0);
272     put_swf_line_edge(&p, 0, height);
273     put_swf_line_edge(&p, -width, 0);
274     put_swf_line_edge(&p, 0, -height);
275     
276     /* end of shape */
277     put_bits(&p, 1, 0); /* not an edge */
278     put_bits(&p, 5, 0);
279
280     flush_put_bits(&p);
281     put_buffer(pb, buf1, p.buf_ptr - p.buf);
282
283     put_swf_end_tag(s);
284
285     
286     if (audio_enc) {
287         int v;
288
289         /* start sound */
290
291         v = 0;
292         switch(audio_enc->sample_rate) {
293         case 11025:
294             v |= 1 << 2;
295             break;
296         case 22050:
297             v |= 2 << 2;
298             break;
299         case 44100:
300             v |= 3 << 2;
301             break;
302         default:
303             /* not supported */
304             free(swf);
305             return -1;
306         }
307         if (audio_enc->channels == 2)
308             v |= 1;
309         v |= 0x20; /* mp3 compressed */
310         v |= 0x02; /* 16 bits */
311         
312         put_swf_tag(s, TAG_STREAMHEAD);
313         put_byte(&s->pb, 0);
314         put_byte(&s->pb, v);
315         put_le16(&s->pb, (audio_enc->sample_rate * FRAME_RATE_BASE) / rate);  /* avg samples per frame */
316         
317         
318         put_swf_end_tag(s);
319     }
320
321     put_flush_packet(&s->pb);
322     return 0;
323 }
324
325 static int swf_write_video(AVFormatContext *s, 
326                            AVCodecContext *enc, UINT8 *buf, int size)
327 {
328     ByteIOContext *pb = &s->pb;
329     static int tag_id = 0;
330
331     if (enc->frame_number > 1) {
332         /* remove the shape */
333         put_swf_tag(s, TAG_REMOVEOBJECT);
334         put_le16(pb, SHAPE_ID); /* shape ID */
335         put_le16(pb, 1); /* depth */
336         put_swf_end_tag(s);
337         
338         /* free the bitmap */
339         put_swf_tag(s, TAG_FREECHARACTER);
340         put_le16(pb, BITMAP_ID);
341         put_swf_end_tag(s);
342     }
343
344     put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
345
346     put_le16(pb, tag_id); /* ID of the image */
347
348     /* a dummy jpeg header seems to be required */
349     put_byte(pb, 0xff); 
350     put_byte(pb, 0xd8);
351     put_byte(pb, 0xff);
352     put_byte(pb, 0xd9);
353     /* write the jpeg image */
354     put_buffer(pb, buf, size);
355
356     put_swf_end_tag(s);
357
358     /* draw the shape */
359
360     put_swf_tag(s, TAG_PLACEOBJECT);
361     put_le16(pb, SHAPE_ID); /* shape ID */
362     put_le16(pb, 1); /* depth */
363     put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
364     put_swf_end_tag(s);
365     
366     /* output the frame */
367     put_swf_tag(s, TAG_SHOWFRAME);
368     put_swf_end_tag(s);
369     
370     put_flush_packet(&s->pb);
371     return 0;
372 }
373
374 static int swf_write_audio(AVFormatContext *s, UINT8 *buf, int size)
375 {
376     ByteIOContext *pb = &s->pb;
377
378     put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
379
380     put_buffer(pb, buf, size);
381     
382     put_swf_end_tag(s);
383     put_flush_packet(&s->pb);
384     return 0;
385 }
386
387 static int swf_write_packet(AVFormatContext *s, int stream_index, 
388                            UINT8 *buf, int size)
389 {
390     AVCodecContext *codec = &s->streams[stream_index]->codec;
391     if (codec->codec_type == CODEC_TYPE_AUDIO)
392         return swf_write_audio(s, buf, size);
393     else
394         return swf_write_video(s, codec, buf, size);
395 }
396
397 static int swf_write_trailer(AVFormatContext *s)
398 {
399     SWFContext *swf = s->priv_data;
400     ByteIOContext *pb = &s->pb;
401     AVCodecContext *enc, *video_enc;
402     int file_size, i;
403
404     video_enc = NULL;
405     for(i=0;i<s->nb_streams;i++) {
406         enc = &s->streams[i]->codec;
407         if (enc->codec_type == CODEC_TYPE_VIDEO)
408             video_enc = enc;
409     }
410
411     put_swf_tag(s, TAG_END);
412     put_swf_end_tag(s);
413     
414     put_flush_packet(&s->pb);
415
416     /* patch file size and number of frames if not streamed */
417     if (!url_is_streamed(&s->pb) && video_enc) {
418         file_size = url_ftell(pb);
419         url_fseek(pb, 4, SEEK_SET);
420         put_le32(pb, file_size);
421         url_fseek(pb, swf->duration_pos, SEEK_SET);
422         put_le16(pb, video_enc->frame_number);
423     }
424     free(swf);
425     return 0;
426 }
427
428 /***********************************/
429 /* just to extract MP3 from swf */
430
431 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
432 {
433     int tag, len;
434     
435     if (url_feof(pb))
436         return -1;
437
438     tag = get_le16(pb);
439     len = tag & 0x3f;
440     tag = tag >> 6;
441     if (len == 0x3f) {
442         len = get_le32(pb);
443     }
444     *len_ptr = len;
445     return tag;
446 }
447
448 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
449 {
450     ByteIOContext *pb = &s->pb;
451     int nbits, len, frame_rate, tag, v;
452     AVStream *st;
453
454     if ((get_be32(pb) & 0xffffff00) != MKBETAG('F', 'W', 'S', 0))
455         return -EIO;
456     get_le32(pb);
457     /* skip rectangle size */
458     nbits = get_byte(pb) >> 3;
459     len = (4 * nbits - 3 + 7) / 8;
460     url_fskip(pb, len);
461     frame_rate = get_le16(pb);
462     get_le16(pb); /* frame count */
463
464     for(;;) {
465         tag = get_swf_tag(pb, &len);
466         if (tag < 0) {
467             fprintf(stderr, "No streaming found in SWF\n");
468             return -EIO;
469         }
470         if (tag == TAG_STREAMHEAD) {
471             /* streaming found */
472             get_byte(pb);
473             v = get_byte(pb);
474             get_le16(pb);
475             /* if mp3 streaming found, OK */
476             if ((v & 0x20) != 0) {
477                 st = av_mallocz(sizeof(AVStream));
478                 if (!st)
479                     return -ENOMEM;
480                 if (v & 0x01)
481                     st->codec.channels = 2;
482                 else
483                     st->codec.channels = 1;
484                 s->nb_streams = 1;
485                 s->streams[0] = st;
486
487                 switch((v>> 2) & 0x03) {
488                 case 1:
489                     st->codec.sample_rate = 11025;
490                     break;
491                 case 2:
492                     st->codec.sample_rate = 22050;
493                     break;
494                 case 3:
495                     st->codec.sample_rate = 44100;
496                     break;
497                 default:
498                     free(st);
499                     return -EIO;
500                 }
501                 st->codec.codec_type = CODEC_TYPE_AUDIO;
502                 st->codec.codec_id = CODEC_ID_MP2;
503                 break;
504             }
505         } else {
506             url_fskip(pb, len);
507         }
508     }
509
510     return 0;
511 }
512
513 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
514 {
515     ByteIOContext *pb = &s->pb;
516     int tag, len;
517     
518     for(;;) {
519         tag = get_swf_tag(pb, &len);
520         if (tag < 0) 
521             return -EIO;
522         if (tag == TAG_STREAMBLOCK) {
523             av_new_packet(pkt, len);
524             get_buffer(pb, pkt->data, pkt->size);
525             break;
526         } else {
527             url_fskip(pb, len);
528         }
529     }
530     return 0;
531 }
532
533 static int swf_read_close(AVFormatContext *s)
534 {
535      return 0;
536 }
537
538 AVFormat swf_format = {
539     "swf",
540     "Flash format",
541     "application/x-shockwave-flash",
542     "swf",
543     CODEC_ID_MP2,
544     CODEC_ID_MJPEG,
545     swf_write_header,
546     swf_write_packet,
547     swf_write_trailer,
548
549     swf_read_header,
550     swf_read_packet,
551     swf_read_close,
552 };