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