7bde752d9a5a8a1bb612ada1f2f189ea5c400f37
[libav.git] / libavformat / swf.c
1 /*
2 * Flash Compatible Streaming Format
3 * Copyright (c) 2000 Fabrice Bellard.
4 * Copyright (c) 2003 Tinic Uro.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include "avformat.h"
21
22 /* should have a generic way to indicate probable size */
23 #define DUMMY_FILE_SIZE (100 * 1024 * 1024)
24 #define DUMMY_DURATION 600 /* in seconds */
25
26 #define TAG_END 0
27 #define TAG_SHOWFRAME 1
28 #define TAG_DEFINESHAPE 2
29 #define TAG_FREECHARACTER 3
30 #define TAG_PLACEOBJECT 4
31 #define TAG_REMOVEOBJECT 5
32 #define TAG_STREAMHEAD 45
33 #define TAG_STREAMBLOCK 19
34 #define TAG_JPEG2 21
35 #define TAG_PLACEOBJECT2 26
36 #define TAG_STREAMHEAD2 45
37 #define TAG_VIDEOSTREAM 60
38 #define TAG_VIDEOFRAME 61
39
40 #define TAG_LONG 0x100
41
42 /* flags for shape definition */
43 #define FLAG_MOVETO 0x01
44 #define FLAG_SETFILL0 0x02
45 #define FLAG_SETFILL1 0x04
46
47 #define SWF_VIDEO_CODEC_FLV1 0x02
48
49 #define AUDIO_FIFO_SIZE 65536
50
51 /* character id used */
52 #define BITMAP_ID 0
53 #define VIDEO_ID 0
54 #define SHAPE_ID 1
55
56 typedef struct SWFFrame_s {
57 void *data;
58 int size;
59 struct SWFFrame_s *prev;
60 struct SWFFrame_s *next;
61 } SWFFrame;
62
63 typedef struct {
64
65 offset_t duration_pos;
66 offset_t tag_pos;
67
68 int samples_per_frame;
69 int sound_samples;
70 int video_samples;
71 int skip_samples;
72 int swf_frame_number;
73 int video_frame_number;
74 int ms_per_frame;
75 int ch_id;
76 int tag;
77
78 uint8_t *audio_fifo;
79 int audio_in_pos;
80 int audio_out_pos;
81 int audio_size;
82
83 int video_type;
84 int audio_type;
85
86 SWFFrame *frame_head;
87 SWFFrame *frame_tail;
88 } SWFContext;
89
90 static const int sSampleRates[3][4] = {
91 {44100, 48000, 32000, 0},
92 {22050, 24000, 16000, 0},
93 {11025, 12000, 8000, 0},
94 };
95
96 static const int sBitRates[2][3][15] = {
97 { { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
98 { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
99 { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
100 },
101 { { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
102 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
103 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
104 },
105 };
106
107 static const int sSamplesPerFrame[3][3] =
108 {
109 { 384, 1152, 1152 },
110 { 384, 1152, 576 },
111 { 384, 1152, 576 }
112 };
113
114 static const int sBitsPerSlot[3] = {
115 32,
116 8,
117 8
118 };
119
120 static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
121 {
122 uint8_t *dataTmp = (uint8_t *)data;
123 uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
124 int layerID = 3 - ((header >> 17) & 0x03);
125 int bitRateID = ((header >> 12) & 0x0f);
126 int sampleRateID = ((header >> 10) & 0x03);
127 int bitRate = 0;
128 int bitsPerSlot = sBitsPerSlot[layerID];
129 int isPadded = ((header >> 9) & 0x01);
130
131 if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
132 return 0;
133 }
134
135 *isMono = ((header >> 6) & 0x03) == 0x03;
136
137 if ( (header >> 19 ) & 0x01 ) {
138 *sampleRate = sSampleRates[0][sampleRateID];
139 bitRate = sBitRates[0][layerID][bitRateID] * 1000;
140 *samplesPerFrame = sSamplesPerFrame[0][layerID];
141 } else {
142 if ( (header >> 20) & 0x01 ) {
143 *sampleRate = sSampleRates[1][sampleRateID];
144 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
145 *samplesPerFrame = sSamplesPerFrame[1][layerID];
146 } else {
147 *sampleRate = sSampleRates[2][sampleRateID];
148 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
149 *samplesPerFrame = sSamplesPerFrame[2][layerID];
150 }
151 }
152
153 *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
154
155 return 1;
156 }
157
158 #ifdef CONFIG_ENCODERS
159 static void put_swf_tag(AVFormatContext *s, int tag)
160 {
161 SWFContext *swf = s->priv_data;
162 ByteIOContext *pb = &s->pb;
163
164 swf->tag_pos = url_ftell(pb);
165 swf->tag = tag;
166 /* reserve some room for the tag */
167 if (tag & TAG_LONG) {
168 put_le16(pb, 0);
169 put_le32(pb, 0);
170 } else {
171 put_le16(pb, 0);
172 }
173 }
174
175 static void put_swf_end_tag(AVFormatContext *s)
176 {
177 SWFContext *swf = s->priv_data;
178 ByteIOContext *pb = &s->pb;
179 offset_t pos;
180 int tag_len, tag;
181
182 pos = url_ftell(pb);
183 tag_len = pos - swf->tag_pos - 2;
184 tag = swf->tag;
185 url_fseek(pb, swf->tag_pos, SEEK_SET);
186 if (tag & TAG_LONG) {
187 tag &= ~TAG_LONG;
188 put_le16(pb, (tag << 6) | 0x3f);
189 put_le32(pb, tag_len - 4);
190 } else {
191 assert(tag_len < 0x3f);
192 put_le16(pb, (tag << 6) | tag_len);
193 }
194 url_fseek(pb, pos, SEEK_SET);
195 }
196
197 static inline void max_nbits(int *nbits_ptr, int val)
198 {
199 int n;
200
201 if (val == 0)
202 return;
203 val = abs(val);
204 n = 1;
205 while (val != 0) {
206 n++;
207 val >>= 1;
208 }
209 if (n > *nbits_ptr)
210 *nbits_ptr = n;
211 }
212
213 static void put_swf_rect(ByteIOContext *pb,
214 int xmin, int xmax, int ymin, int ymax)
215 {
216 PutBitContext p;
217 uint8_t buf[256];
218 int nbits, mask;
219
220 init_put_bits(&p, buf, sizeof(buf));
221
222 nbits = 0;
223 max_nbits(&nbits, xmin);
224 max_nbits(&nbits, xmax);
225 max_nbits(&nbits, ymin);
226 max_nbits(&nbits, ymax);
227 mask = (1 << nbits) - 1;
228
229 /* rectangle info */
230 put_bits(&p, 5, nbits);
231 put_bits(&p, nbits, xmin & mask);
232 put_bits(&p, nbits, xmax & mask);
233 put_bits(&p, nbits, ymin & mask);
234 put_bits(&p, nbits, ymax & mask);
235
236 flush_put_bits(&p);
237 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
238 }
239
240 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
241 {
242 int nbits, mask;
243
244 put_bits(pb, 1, 1); /* edge */
245 put_bits(pb, 1, 1); /* line select */
246 nbits = 2;
247 max_nbits(&nbits, dx);
248 max_nbits(&nbits, dy);
249
250 mask = (1 << nbits) - 1;
251 put_bits(pb, 4, nbits - 2); /* 16 bits precision */
252 if (dx == 0) {
253 put_bits(pb, 1, 0);
254 put_bits(pb, 1, 1);
255 put_bits(pb, nbits, dy & mask);
256 } else if (dy == 0) {
257 put_bits(pb, 1, 0);
258 put_bits(pb, 1, 0);
259 put_bits(pb, nbits, dx & mask);
260 } else {
261 put_bits(pb, 1, 1);
262 put_bits(pb, nbits, dx & mask);
263 put_bits(pb, nbits, dy & mask);
264 }
265 }
266
267 #define FRAC_BITS 16
268
269 /* put matrix */
270 static void put_swf_matrix(ByteIOContext *pb,
271 int a, int b, int c, int d, int tx, int ty)
272 {
273 PutBitContext p;
274 uint8_t buf[256];
275 int nbits;
276
277 init_put_bits(&p, buf, sizeof(buf));
278
279 put_bits(&p, 1, 1); /* a, d present */
280 nbits = 1;
281 max_nbits(&nbits, a);
282 max_nbits(&nbits, d);
283 put_bits(&p, 5, nbits); /* nb bits */
284 put_bits(&p, nbits, a);
285 put_bits(&p, nbits, d);
286
287 put_bits(&p, 1, 1); /* b, c present */
288 nbits = 1;
289 max_nbits(&nbits, c);
290 max_nbits(&nbits, b);
291 put_bits(&p, 5, nbits); /* nb bits */
292 put_bits(&p, nbits, c);
293 put_bits(&p, nbits, b);
294
295 nbits = 1;
296 max_nbits(&nbits, tx);
297 max_nbits(&nbits, ty);
298 put_bits(&p, 5, nbits); /* nb bits */
299 put_bits(&p, nbits, tx);
300 put_bits(&p, nbits, ty);
301
302 flush_put_bits(&p);
303 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
304 }
305
306 /* */
307 static int swf_write_header(AVFormatContext *s)
308 {
309 SWFContext *swf;
310 ByteIOContext *pb = &s->pb;
311 AVCodecContext *enc, *audio_enc, *video_enc;
312 PutBitContext p;
313 uint8_t buf1[256];
314 int i, width, height, rate, rate_base;
315
316 swf = av_malloc(sizeof(SWFContext));
317 if (!swf)
318 return -1;
319 s->priv_data = swf;
320
321 swf->ch_id = -1;
322 swf->audio_in_pos = 0;
323 swf->audio_out_pos = 0;
324 swf->audio_size = 0;
325 swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
326 swf->frame_head = 0;
327 swf->frame_tail = 0;
328 swf->sound_samples = 0;
329 swf->video_samples = 0;
330 swf->swf_frame_number = 0;
331 swf->video_frame_number = 0;
332 swf->skip_samples = 0;
333
334 video_enc = NULL;
335 audio_enc = NULL;
336 for(i=0;i<s->nb_streams;i++) {
337 enc = &s->streams[i]->codec;
338 if (enc->codec_type == CODEC_TYPE_AUDIO)
339 audio_enc = enc;
340 else {
341 if ( enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == CODEC_ID_MJPEG ) {
342 video_enc = enc;
343 } else {
344 av_log(enc, AV_LOG_ERROR, "SWF only supports FLV1 and MJPEG\n");
345 return -1;
346 }
347 }
348 }
349
350 if (!video_enc) {
351 /* currenty, cannot work correctly if audio only */
352 swf->video_type = 0;
353 width = 320;
354 height = 200;
355 rate = 10;
356 rate_base= 1;
357 } else {
358 swf->video_type = video_enc->codec_id;
359 width = video_enc->width;
360 height = video_enc->height;
361 rate = video_enc->frame_rate;
362 rate_base = video_enc->frame_rate_base;
363 }
364
365 if (!audio_enc ) {
366 swf->audio_type = 0;
367 swf->samples_per_frame = ( 44100. * rate_base ) / rate;
368 } else {
369 swf->audio_type = audio_enc->codec_id;
370 swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
371 }
372
373 put_tag(pb, "FWS");
374 if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
375 put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
376 } else {
377 put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
378 }
379 put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
380 (will be patched if not streamed) */
381
382 put_swf_rect(pb, 0, width * 20, 0, height * 20);
383 put_le16(pb, (rate * 256) / rate_base); /* frame rate */
384 swf->duration_pos = url_ftell(pb);
385 put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
386
387 /* define a shape with the jpeg inside */
388 if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
389 } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
390 put_swf_tag(s, TAG_DEFINESHAPE);
391
392 put_le16(pb, SHAPE_ID); /* ID of shape */
393 /* bounding rectangle */
394 put_swf_rect(pb, 0, width, 0, height);
395 /* style info */
396 put_byte(pb, 1); /* one fill style */
397 put_byte(pb, 0x41); /* clipped bitmap fill */
398 put_le16(pb, BITMAP_ID); /* bitmap ID */
399 /* position of the bitmap */
400 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
401 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
402 put_byte(pb, 0); /* no line style */
403
404 /* shape drawing */
405 init_put_bits(&p, buf1, sizeof(buf1));
406 put_bits(&p, 4, 1); /* one fill bit */
407 put_bits(&p, 4, 0); /* zero line bit */
408
409 put_bits(&p, 1, 0); /* not an edge */
410 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
411 put_bits(&p, 5, 1); /* nbits */
412 put_bits(&p, 1, 0); /* X */
413 put_bits(&p, 1, 0); /* Y */
414 put_bits(&p, 1, 1); /* set fill style 1 */
415
416 /* draw the rectangle ! */
417 put_swf_line_edge(&p, width, 0);
418 put_swf_line_edge(&p, 0, height);
419 put_swf_line_edge(&p, -width, 0);
420 put_swf_line_edge(&p, 0, -height);
421
422 /* end of shape */
423 put_bits(&p, 1, 0); /* not an edge */
424 put_bits(&p, 5, 0);
425
426 flush_put_bits(&p);
427 put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
428
429 put_swf_end_tag(s);
430 }
431
432 if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
433 int v;
434
435 /* start sound */
436 put_swf_tag(s, TAG_STREAMHEAD2);
437
438 v = 0;
439 switch(audio_enc->sample_rate) {
440 case 11025:
441 v |= 1 << 2;
442 break;
443 case 22050:
444 v |= 2 << 2;
445 break;
446 case 44100:
447 v |= 3 << 2;
448 break;
449 default:
450 /* not supported */
451 av_free(swf->audio_fifo);
452 av_free(swf);
453 return -1;
454 }
455 v |= 0x02; /* 16 bit playback */
456 if (audio_enc->channels == 2)
457 v |= 0x01; /* stereo playback */
458 put_byte(&s->pb, v);
459 v |= 0x20; /* mp3 compressed */
460 put_byte(&s->pb, v);
461 put_le16(&s->pb, swf->samples_per_frame); /* avg samples per frame */
462 put_le16(&s->pb, 0);
463
464 put_swf_end_tag(s);
465 }
466
467 put_flush_packet(&s->pb);
468 return 0;
469 }
470
471 static int swf_write_video(AVFormatContext *s,
472 AVCodecContext *enc, const uint8_t *buf, int size)
473 {
474 SWFContext *swf = s->priv_data;
475 ByteIOContext *pb = &s->pb;
476 int c = 0;
477 int outSize = 0;
478 int outSamples = 0;
479
480 /* Flash Player limit */
481 if ( swf->swf_frame_number == 16000 ) {
482 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
483 }
484
485 /* Store video data in queue */
486 if ( enc->codec_type == CODEC_TYPE_VIDEO ) {
487 SWFFrame *new_frame = av_malloc(sizeof(SWFFrame));
488 new_frame->prev = 0;
489 new_frame->next = swf->frame_head;
490 new_frame->data = av_malloc(size);
491 new_frame->size = size;
492 memcpy(new_frame->data,buf,size);
493 swf->frame_head = new_frame;
494 if ( swf->frame_tail == 0 ) {
495 swf->frame_tail = new_frame;
496 }
497 }
498
499 if ( swf->audio_type ) {
500 /* Prescan audio data for this swf frame */
501 retry_swf_audio_packet:
502 if ( ( swf->audio_size-outSize ) >= 4 ) {
503 int mp3FrameSize = 0;
504 int mp3SampleRate = 0;
505 int mp3IsMono = 0;
506 int mp3SamplesPerFrame = 0;
507
508 /* copy out mp3 header from ring buffer */
509 uint8_t header[4];
510 for (c=0; c<4; c++) {
511 header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
512 }
513
514 if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
515 if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
516 outSize += mp3FrameSize;
517 outSamples += mp3SamplesPerFrame;
518 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
519 goto retry_swf_audio_packet;
520 }
521 }
522 } else {
523 /* invalid mp3 data, skip forward
524 we need to do this since the Flash Player
525 does not like custom headers */
526 swf->audio_in_pos ++;
527 swf->audio_size --;
528 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
529 goto retry_swf_audio_packet;
530 }
531 }
532
533 /* audio stream is behind video stream, bail */
534 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
535 return 0;
536 }
537
538 /* compute audio/video drift */
539 if ( enc->codec_type == CODEC_TYPE_VIDEO ) {
540 swf->skip_samples = (int)( ( (double)(swf->swf_frame_number) * (double)enc->frame_rate_base * 44100. ) / (double)(enc->frame_rate) );
541 swf->skip_samples -= swf->video_samples;
542 }
543 }
544
545 /* check if we need to insert a padding frame */
546 if (swf->skip_samples <= ( swf->samples_per_frame / 2 ) ) {
547 /* no, it is time for a real frame, check if one is available */
548 if ( swf->frame_tail ) {
549 if ( swf->video_type == CODEC_ID_FLV1 ) {
550 if ( swf->video_frame_number == 0 ) {
551 /* create a new video object */
552 put_swf_tag(s, TAG_VIDEOSTREAM);
553 put_le16(pb, VIDEO_ID);
554 put_le16(pb, 15000 ); /* hard flash player limit */
555 put_le16(pb, enc->width);
556 put_le16(pb, enc->height);
557 put_byte(pb, 0);
558 put_byte(pb, SWF_VIDEO_CODEC_FLV1);
559 put_swf_end_tag(s);
560
561 /* place the video object for the first time */
562 put_swf_tag(s, TAG_PLACEOBJECT2);
563 put_byte(pb, 0x36);
564 put_le16(pb, 1);
565 put_le16(pb, VIDEO_ID);
566 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
567 put_le16(pb, swf->video_frame_number );
568 put_byte(pb, 'v');
569 put_byte(pb, 'i');
570 put_byte(pb, 'd');
571 put_byte(pb, 'e');
572 put_byte(pb, 'o');
573 put_byte(pb, 0x00);
574 put_swf_end_tag(s);
575 } else {
576 /* mark the character for update */
577 put_swf_tag(s, TAG_PLACEOBJECT2);
578 put_byte(pb, 0x11);
579 put_le16(pb, 1);
580 put_le16(pb, swf->video_frame_number );
581 put_swf_end_tag(s);
582 }
583
584 // write out pending frames
585 for (; ( enc->frame_number - swf->video_frame_number ) > 0;) {
586 /* set video frame data */
587 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
588 put_le16(pb, VIDEO_ID);
589 put_le16(pb, swf->video_frame_number++ );
590 put_buffer(pb, swf->frame_tail->data, swf->frame_tail->size);
591 put_swf_end_tag(s);
592 }
593
594 } else if ( swf->video_type == CODEC_ID_MJPEG ) {
595 if (swf->swf_frame_number > 0) {
596 /* remove the shape */
597 put_swf_tag(s, TAG_REMOVEOBJECT);
598 put_le16(pb, SHAPE_ID); /* shape ID */
599 put_le16(pb, 1); /* depth */
600 put_swf_end_tag(s);
601
602 /* free the bitmap */
603 put_swf_tag(s, TAG_FREECHARACTER);
604 put_le16(pb, BITMAP_ID);
605 put_swf_end_tag(s);
606 }
607
608 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
609
610 put_le16(pb, BITMAP_ID); /* ID of the image */
611
612 /* a dummy jpeg header seems to be required */
613 put_byte(pb, 0xff);
614 put_byte(pb, 0xd8);
615 put_byte(pb, 0xff);
616 put_byte(pb, 0xd9);
617 /* write the jpeg image */
618 put_buffer(pb, swf->frame_tail->data, swf->frame_tail->size);
619
620 put_swf_end_tag(s);
621
622 /* draw the shape */
623
624 put_swf_tag(s, TAG_PLACEOBJECT);
625 put_le16(pb, SHAPE_ID); /* shape ID */
626 put_le16(pb, 1); /* depth */
627 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
628 put_swf_end_tag(s);
629 } else {
630 /* invalid codec */
631 }
632
633 av_free(swf->frame_tail->data);
634 swf->frame_tail = swf->frame_tail->prev;
635 if ( swf->frame_tail ) {
636 if ( swf->frame_tail->next ) {
637 av_free(swf->frame_tail->next);
638 }
639 swf->frame_tail->next = 0;
640 } else {
641 swf->frame_head = 0;
642 }
643 swf->swf_frame_number ++;
644 }
645 }
646
647 swf->video_samples += swf->samples_per_frame;
648
649 /* streaming sound always should be placed just before showframe tags */
650 if ( outSize > 0 ) {
651 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
652 put_le16(pb, outSamples);
653 put_le16(pb, 0);
654 for (c=0; c<outSize; c++) {
655 put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
656 }
657 put_swf_end_tag(s);
658
659 /* update FIFO */
660 swf->sound_samples += outSamples;
661 swf->audio_in_pos += outSize;
662 swf->audio_size -= outSize;
663 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
664 }
665
666 /* output the frame */
667 put_swf_tag(s, TAG_SHOWFRAME);
668 put_swf_end_tag(s);
669
670 put_flush_packet(&s->pb);
671
672 return 0;
673 }
674
675 static int swf_write_audio(AVFormatContext *s,
676 AVCodecContext *enc, const uint8_t *buf, int size)
677 {
678 SWFContext *swf = s->priv_data;
679 int c = 0;
680
681 /* Flash Player limit */
682 if ( swf->swf_frame_number == 16000 ) {
683 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
684 }
685
686 if (enc->codec_id == CODEC_ID_MP3 ) {
687 for (c=0; c<size; c++) {
688 swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
689 }
690 swf->audio_size += size;
691 swf->audio_out_pos += size;
692 swf->audio_out_pos %= AUDIO_FIFO_SIZE;
693 }
694
695 /* if audio only stream make sure we add swf frames */
696 if ( swf->video_type == 0 ) {
697 swf_write_video(s, enc, 0, 0);
698 }
699
700 return 0;
701 }
702
703 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
704 {
705 AVCodecContext *codec = &s->streams[pkt->stream_index]->codec;
706 if (codec->codec_type == CODEC_TYPE_AUDIO)
707 return swf_write_audio(s, codec, pkt->data, pkt->size);
708 else
709 return swf_write_video(s, codec, pkt->data, pkt->size);
710 }
711
712 static int swf_write_trailer(AVFormatContext *s)
713 {
714 SWFContext *swf = s->priv_data;
715 ByteIOContext *pb = &s->pb;
716 AVCodecContext *enc, *video_enc;
717 int file_size, i;
718
719 video_enc = NULL;
720 for(i=0;i<s->nb_streams;i++) {
721 enc = &s->streams[i]->codec;
722 if (enc->codec_type == CODEC_TYPE_VIDEO)
723 video_enc = enc;
724 }
725
726 put_swf_tag(s, TAG_END);
727 put_swf_end_tag(s);
728
729 put_flush_packet(&s->pb);
730
731 /* patch file size and number of frames if not streamed */
732 if (!url_is_streamed(&s->pb) && video_enc) {
733 file_size = url_ftell(pb);
734 url_fseek(pb, 4, SEEK_SET);
735 put_le32(pb, file_size);
736 url_fseek(pb, swf->duration_pos, SEEK_SET);
737 put_le16(pb, video_enc->frame_number);
738 }
739
740 av_free(swf->audio_fifo);
741
742 return 0;
743 }
744 #endif //CONFIG_ENCODERS
745
746 /*********************************************/
747 /* Extract FLV encoded frame and MP3 from swf
748 Note that the detection of the real frame
749 is inaccurate at this point as it can be
750 quite tricky to determine, you almost certainly
751 will get a bad audio/video sync */
752
753 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
754 {
755 int tag, len;
756
757 if (url_feof(pb))
758 return -1;
759
760 tag = get_le16(pb);
761 len = tag & 0x3f;
762 tag = tag >> 6;
763 if (len == 0x3f) {
764 len = get_le32(pb);
765 }
766 *len_ptr = len;
767 return tag;
768 }
769
770
771 static int swf_probe(AVProbeData *p)
772 {
773 /* check file header */
774 if (p->buf_size <= 16)
775 return 0;
776 if (p->buf[0] == 'F' && p->buf[1] == 'W' &&
777 p->buf[2] == 'S')
778 return AVPROBE_SCORE_MAX;
779 else
780 return 0;
781 }
782
783 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
784 {
785 SWFContext *swf = 0;
786 ByteIOContext *pb = &s->pb;
787 int nbits, len, frame_rate, tag, v;
788 offset_t firstTagOff;
789 AVStream *ast = 0;
790 AVStream *vst = 0;
791
792 swf = av_malloc(sizeof(SWFContext));
793 if (!swf)
794 return -1;
795 s->priv_data = swf;
796
797 if ((get_be32(pb) & 0xffffff00) != MKBETAG('F', 'W', 'S', 0))
798 return AVERROR_IO;
799 get_le32(pb);
800 /* skip rectangle size */
801 nbits = get_byte(pb) >> 3;
802 len = (4 * nbits - 3 + 7) / 8;
803 url_fskip(pb, len);
804 frame_rate = get_le16(pb);
805 get_le16(pb); /* frame count */
806
807 /* The Flash Player converts 8.8 frame rates
808 to milliseconds internally. Do the same to get
809 a correct framerate */
810 swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
811 swf->samples_per_frame = 0;
812 swf->ch_id = -1;
813
814 firstTagOff = url_ftell(pb);
815 for(;;) {
816 tag = get_swf_tag(pb, &len);
817 if (tag < 0) {
818 if ( ast || vst ) {
819 if ( vst && ast ) {
820 vst->codec.frame_rate = ast->codec.sample_rate / swf->samples_per_frame;
821 vst->codec.frame_rate_base = 1;
822 }
823 break;
824 }
825 av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
826 return AVERROR_IO;
827 }
828 if ( tag == TAG_VIDEOSTREAM && !vst) {
829 swf->ch_id = get_le16(pb);
830 get_le16(pb);
831 get_le16(pb);
832 get_le16(pb);
833 get_byte(pb);
834 /* Check for FLV1 */
835 if ( get_byte(pb) == SWF_VIDEO_CODEC_FLV1 ) {
836 vst = av_new_stream(s, 0);
837 av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
838
839 vst->codec.codec_type = CODEC_TYPE_VIDEO;
840 vst->codec.codec_id = CODEC_ID_FLV1;
841 if ( swf->samples_per_frame ) {
842 vst->codec.frame_rate = 1000. / swf->ms_per_frame;
843 vst->codec.frame_rate_base = 1;
844 }
845 }
846 } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
847 /* streaming found */
848 get_byte(pb);
849 v = get_byte(pb);
850 swf->samples_per_frame = get_le16(pb);
851 if (len!=4)
852 url_fskip(pb,len-4);
853 /* if mp3 streaming found, OK */
854 if ((v & 0x20) != 0) {
855 if ( tag == TAG_STREAMHEAD2 ) {
856 get_le16(pb);
857 }
858 ast = av_new_stream(s, 1);
859 av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
860 if (!ast)
861 return -ENOMEM;
862
863 if (v & 0x01)
864 ast->codec.channels = 2;
865 else
866 ast->codec.channels = 1;
867
868 switch((v>> 2) & 0x03) {
869 case 1:
870 ast->codec.sample_rate = 11025;
871 break;
872 case 2:
873 ast->codec.sample_rate = 22050;
874 break;
875 case 3:
876 ast->codec.sample_rate = 44100;
877 break;
878 default:
879 av_free(ast);
880 return AVERROR_IO;
881 }
882 ast->codec.codec_type = CODEC_TYPE_AUDIO;
883 ast->codec.codec_id = CODEC_ID_MP3;
884 }
885 } else {
886 url_fskip(pb, len);
887 }
888 }
889 url_fseek(pb, firstTagOff, SEEK_SET);
890
891 return 0;
892 }
893
894 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
895 {
896 SWFContext *swf = s->priv_data;
897 ByteIOContext *pb = &s->pb;
898 AVStream *st = 0;
899 int tag, len, i, frame;
900
901 for(;;) {
902 tag = get_swf_tag(pb, &len);
903 if (tag < 0)
904 return AVERROR_IO;
905 if (tag == TAG_VIDEOFRAME) {
906 for( i=0; i<s->nb_streams; i++ ) {
907 st = s->streams[i];
908 if (st->id == 0) {
909 if ( get_le16(pb) == swf->ch_id ) {
910 frame = get_le16(pb);
911 av_new_packet(pkt, len-4);
912 pkt->pts = frame * swf->ms_per_frame;
913 pkt->stream_index = st->index;
914 get_buffer(pb, pkt->data, pkt->size);
915 return pkt->size;
916 } else {
917 url_fskip(pb, len-2);
918 continue;
919 }
920 }
921 }
922 url_fskip(pb, len);
923 } else if (tag == TAG_STREAMBLOCK) {
924 for( i=0; i<s->nb_streams; i++ ) {
925 st = s->streams[i];
926 if (st->id == 1) {
927 av_new_packet(pkt, len);
928 pkt->stream_index = st->index;
929 get_buffer(pb, pkt->data, pkt->size);
930 return pkt->size;
931 }
932 }
933 url_fskip(pb, len);
934 } else {
935 url_fskip(pb, len);
936 }
937 }
938 return 0;
939 }
940
941 static int swf_read_close(AVFormatContext *s)
942 {
943 return 0;
944 }
945
946 static AVInputFormat swf_iformat = {
947 "swf",
948 "Flash format",
949 sizeof(SWFContext),
950 swf_probe,
951 swf_read_header,
952 swf_read_packet,
953 swf_read_close,
954 };
955
956 #ifdef CONFIG_ENCODERS
957 static AVOutputFormat swf_oformat = {
958 "swf",
959 "Flash format",
960 "application/x-shockwave-flash",
961 "swf",
962 sizeof(SWFContext),
963 CODEC_ID_MP3,
964 CODEC_ID_FLV1,
965 swf_write_header,
966 swf_write_packet,
967 swf_write_trailer,
968 };
969 #endif //CONFIG_ENCODERS
970
971 int swf_init(void)
972 {
973 av_register_input_format(&swf_iformat);
974 #ifdef CONFIG_ENCODERS
975 av_register_output_format(&swf_oformat);
976 #endif //CONFIG_ENCODERS
977 return 0;
978 }