changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext...
[libav.git] / libavformat / swf.c
CommitLineData
de6d9b64
FB
1/*
2 * Flash Compatible Streaming Format
17269bdf 3 * Copyright (c) 2000 Fabrice Bellard.
747a0554 4 * Copyright (c) 2003 Tinic Uro.
de6d9b64 5 *
17269bdf
FB
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.
de6d9b64 10 *
17269bdf 11 * This library is distributed in the hope that it will be useful,
de6d9b64 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17269bdf
FB
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
de6d9b64 15 *
17269bdf
FB
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
de6d9b64 19 */
de6d9b64 20#include "avformat.h"
2de7795a 21#include "bitstream.h"
de6d9b64 22
de6d9b64
FB
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
98d82b22 33#define TAG_STREAMHEAD 18
de6d9b64
FB
34#define TAG_STREAMBLOCK 19
35#define TAG_JPEG2 21
747a0554
TU
36#define TAG_PLACEOBJECT2 26
37#define TAG_STREAMHEAD2 45
38#define TAG_VIDEOSTREAM 60
39#define TAG_VIDEOFRAME 61
de6d9b64
FB
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
747a0554
TU
48#define SWF_VIDEO_CODEC_FLV1 0x02
49
50#define AUDIO_FIFO_SIZE 65536
51
de6d9b64
FB
52/* character id used */
53#define BITMAP_ID 0
747a0554 54#define VIDEO_ID 0
de6d9b64
FB
55#define SHAPE_ID 1
56
14a68b89
MN
57#undef NDEBUG
58#include <assert.h>
747a0554 59
de6d9b64 60typedef struct {
747a0554 61
8be1c656
FB
62 offset_t duration_pos;
63 offset_t tag_pos;
747a0554
TU
64
65 int samples_per_frame;
66 int sound_samples;
67 int video_samples;
747a0554
TU
68 int swf_frame_number;
69 int video_frame_number;
70 int ms_per_frame;
71 int ch_id;
de6d9b64 72 int tag;
747a0554
TU
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;
de6d9b64
FB
81} SWFContext;
82
747a0554
TU
83static const int sSampleRates[3][4] = {
84 {44100, 48000, 32000, 0},
85 {22050, 24000, 16000, 0},
86 {11025, 12000, 8000, 0},
87};
88
89static 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
100static const int sSamplesPerFrame[3][3] =
101{
102 { 384, 1152, 1152 },
103 { 384, 1152, 576 },
104 { 384, 1152, 576 }
105};
106
107static const int sBitsPerSlot[3] = {
108 32,
109 8,
110 8
111};
112
113static 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
764ef400 151#ifdef CONFIG_ENCODERS
de6d9b64
FB
152static 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
168static void put_swf_end_tag(AVFormatContext *s)
169{
170 SWFContext *swf = s->priv_data;
171 ByteIOContext *pb = &s->pb;
8be1c656 172 offset_t pos;
de6d9b64
FB
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
190static 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
206static void put_swf_rect(ByteIOContext *pb,
207 int xmin, int xmax, int ymin, int ymax)
208{
209 PutBitContext p;
0c1a9eda 210 uint8_t buf[256];
de6d9b64
FB
211 int nbits, mask;
212
117a5490 213 init_put_bits(&p, buf, sizeof(buf));
de6d9b64
FB
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);
17592475 230 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
de6d9b64
FB
231}
232
233static 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
747a0554 262/* put matrix */
de6d9b64
FB
263static void put_swf_matrix(ByteIOContext *pb,
264 int a, int b, int c, int d, int tx, int ty)
265{
266 PutBitContext p;
0c1a9eda 267 uint8_t buf[256];
747a0554 268 int nbits;
de6d9b64 269
117a5490 270 init_put_bits(&p, buf, sizeof(buf));
de6d9b64
FB
271
272 put_bits(&p, 1, 1); /* a, d present */
747a0554
TU
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);
de6d9b64
FB
279
280 put_bits(&p, 1, 1); /* b, c present */
747a0554
TU
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);
de6d9b64
FB
294
295 flush_put_bits(&p);
17592475 296 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
de6d9b64
FB
297}
298
747a0554 299/* */
de6d9b64
FB
300static 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;
0c1a9eda 306 uint8_t buf1[256];
14bea432 307 int i, width, height, rate, rate_base;
de6d9b64 308
1ea4f593 309 swf = av_malloc(sizeof(SWFContext));
de6d9b64
FB
310 if (!swf)
311 return -1;
312 s->priv_data = swf;
313
747a0554
TU
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);
747a0554
TU
319 swf->sound_samples = 0;
320 swf->video_samples = 0;
321 swf->swf_frame_number = 0;
322 swf->video_frame_number = 0;
747a0554 323
de6d9b64
FB
324 video_enc = NULL;
325 audio_enc = NULL;
326 for(i=0;i<s->nb_streams;i++) {
01f4895c 327 enc = s->streams[i]->codec;
de6d9b64
FB
328 if (enc->codec_type == CODEC_TYPE_AUDIO)
329 audio_enc = enc;
747a0554
TU
330 else {
331 if ( enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == CODEC_ID_MJPEG ) {
332 video_enc = enc;
333 } else {
bc874dae 334 av_log(enc, AV_LOG_ERROR, "SWF only supports FLV1 and MJPEG\n");
747a0554
TU
335 return -1;
336 }
337 }
de6d9b64
FB
338 }
339
340 if (!video_enc) {
341 /* currenty, cannot work correctly if audio only */
747a0554 342 swf->video_type = 0;
de6d9b64
FB
343 width = 320;
344 height = 200;
14bea432
MN
345 rate = 10;
346 rate_base= 1;
de6d9b64 347 } else {
747a0554 348 swf->video_type = video_enc->codec_id;
de6d9b64
FB
349 width = video_enc->width;
350 height = video_enc->height;
c0df9d75
MN
351 rate = video_enc->time_base.den;
352 rate_base = video_enc->time_base.num;
de6d9b64
FB
353 }
354
747a0554
TU
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
de6d9b64 363 put_tag(pb, "FWS");
747a0554
TU
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 }
de6d9b64
FB
369 put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
370 (will be patched if not streamed) */
371
747a0554 372 put_swf_rect(pb, 0, width * 20, 0, height * 20);
14bea432 373 put_le16(pb, (rate * 256) / rate_base); /* frame rate */
de6d9b64 374 swf->duration_pos = url_ftell(pb);
14bea432 375 put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
de6d9b64
FB
376
377 /* define a shape with the jpeg inside */
747a0554
TU
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 */
de6d9b64 393
747a0554
TU
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 */
de6d9b64 405
747a0554
TU
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);
de6d9b64 411
747a0554
TU
412 /* end of shape */
413 put_bits(&p, 1, 0); /* not an edge */
414 put_bits(&p, 5, 0);
de6d9b64 415
747a0554
TU
416 flush_put_bits(&p);
417 put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
de6d9b64 418
747a0554
TU
419 put_swf_end_tag(s);
420 }
de6d9b64 421
747a0554 422 if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
de6d9b64
FB
423 int v;
424
425 /* start sound */
747a0554 426 put_swf_tag(s, TAG_STREAMHEAD2);
de6d9b64
FB
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 */
747a0554 441 av_free(swf->audio_fifo);
1ea4f593 442 av_free(swf);
de6d9b64
FB
443 return -1;
444 }
747a0554 445 v |= 0x02; /* 16 bit playback */
de6d9b64 446 if (audio_enc->channels == 2)
747a0554
TU
447 v |= 0x01; /* stereo playback */
448 put_byte(&s->pb, v);
de6d9b64 449 v |= 0x20; /* mp3 compressed */
de6d9b64 450 put_byte(&s->pb, v);
747a0554
TU
451 put_le16(&s->pb, swf->samples_per_frame); /* avg samples per frame */
452 put_le16(&s->pb, 0);
de6d9b64
FB
453
454 put_swf_end_tag(s);
455 }
456
457 put_flush_packet(&s->pb);
458 return 0;
459}
460
461static int swf_write_video(AVFormatContext *s,
49057904 462 AVCodecContext *enc, const uint8_t *buf, int size)
de6d9b64 463{
747a0554 464 SWFContext *swf = s->priv_data;
de6d9b64 465 ByteIOContext *pb = &s->pb;
747a0554
TU
466 int c = 0;
467 int outSize = 0;
468 int outSamples = 0;
469
470 /* Flash Player limit */
d3e18ad0 471 if ( swf->swf_frame_number == 16000 ) {
bc874dae 472 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
de6d9b64
FB
473 }
474
747a0554
TU
475 if ( swf->audio_type ) {
476 /* Prescan audio data for this swf frame */
477retry_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 }
747a0554 513 }
de6d9b64 514
747a0554
TU
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
747a0554
TU
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++ );
14a68b89 554 put_buffer(pb, buf, size);
747a0554 555 put_swf_end_tag(s);
747a0554
TU
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 */
14a68b89 580 put_buffer(pb, buf, size);
747a0554
TU
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
747a0554 595 swf->swf_frame_number ++;
de6d9b64 596
747a0554 597 swf->video_samples += swf->samples_per_frame;
de6d9b64 598
747a0554
TU
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);
de6d9b64 608
747a0554
TU
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
de6d9b64
FB
616 /* output the frame */
617 put_swf_tag(s, TAG_SHOWFRAME);
618 put_swf_end_tag(s);
619
620 put_flush_packet(&s->pb);
747a0554 621
de6d9b64
FB
622 return 0;
623}
624
747a0554
TU
625static int swf_write_audio(AVFormatContext *s,
626 AVCodecContext *enc, const uint8_t *buf, int size)
de6d9b64 627{
747a0554
TU
628 SWFContext *swf = s->priv_data;
629 int c = 0;
de6d9b64 630
747a0554 631 /* Flash Player limit */
d3e18ad0 632 if ( swf->swf_frame_number == 16000 ) {
bc874dae 633 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
747a0554
TU
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 }
de6d9b64 649
de6d9b64
FB
650 return 0;
651}
652
e928649b 653static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
de6d9b64 654{
01f4895c 655 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
de6d9b64 656 if (codec->codec_type == CODEC_TYPE_AUDIO)
e928649b 657 return swf_write_audio(s, codec, pkt->data, pkt->size);
de6d9b64 658 else
e928649b 659 return swf_write_video(s, codec, pkt->data, pkt->size);
de6d9b64
FB
660}
661
662static 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++) {
01f4895c 671 enc = s->streams[i]->codec;
de6d9b64
FB
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 }
747a0554
TU
689
690 av_free(swf->audio_fifo);
691
de6d9b64
FB
692 return 0;
693}
764ef400 694#endif //CONFIG_ENCODERS
de6d9b64 695
747a0554
TU
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 */
de6d9b64
FB
702
703static 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 }
e227d197 716// av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
de6d9b64
FB
717 *len_ptr = len;
718 return tag;
719}
720
c9a65ca8
FB
721
722static int swf_probe(AVProbeData *p)
723{
724 /* check file header */
725 if (p->buf_size <= 16)
726 return 0;
e227d197 727 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
17269bdf 728 p->buf[2] == 'S')
c9a65ca8
FB
729 return AVPROBE_SCORE_MAX;
730 else
731 return 0;
732}
733
de6d9b64
FB
734static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
735{
747a0554 736 SWFContext *swf = 0;
de6d9b64
FB
737 ByteIOContext *pb = &s->pb;
738 int nbits, len, frame_rate, tag, v;
747a0554
TU
739 offset_t firstTagOff;
740 AVStream *ast = 0;
741 AVStream *vst = 0;
742
743 swf = av_malloc(sizeof(SWFContext));
744 if (!swf)
745 return -1;
746 s->priv_data = swf;
de6d9b64 747
e227d197
AB
748 tag = get_be32(pb) & 0xffffff00;
749
750 if (tag == MKBETAG('C', 'W', 'S', 0))
751 {
752 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
753 return AVERROR_IO;
754 }
755 if (tag != MKBETAG('F', 'W', 'S', 0))
0bd586c5 756 return AVERROR_IO;
de6d9b64
FB
757 get_le32(pb);
758 /* skip rectangle size */
759 nbits = get_byte(pb) >> 3;
760 len = (4 * nbits - 3 + 7) / 8;
761 url_fskip(pb, len);
762 frame_rate = get_le16(pb);
763 get_le16(pb); /* frame count */
747a0554 764
747a0554
TU
765 /* The Flash Player converts 8.8 frame rates
766 to milliseconds internally. Do the same to get
767 a correct framerate */
768 swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
769 swf->samples_per_frame = 0;
770 swf->ch_id = -1;
771
772 firstTagOff = url_ftell(pb);
de6d9b64
FB
773 for(;;) {
774 tag = get_swf_tag(pb, &len);
775 if (tag < 0) {
747a0554
TU
776 if ( ast || vst ) {
777 if ( vst && ast ) {
01f4895c
MN
778 vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;
779 vst->codec->time_base.num = 1;
747a0554
TU
780 }
781 break;
782 }
bc874dae 783 av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
0bd586c5 784 return AVERROR_IO;
de6d9b64 785 }
747a0554
TU
786 if ( tag == TAG_VIDEOSTREAM && !vst) {
787 swf->ch_id = get_le16(pb);
788 get_le16(pb);
789 get_le16(pb);
790 get_le16(pb);
791 get_byte(pb);
792 /* Check for FLV1 */
793 if ( get_byte(pb) == SWF_VIDEO_CODEC_FLV1 ) {
794 vst = av_new_stream(s, 0);
9ee91c2f
MN
795 av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
796
01f4895c
MN
797 vst->codec->codec_type = CODEC_TYPE_VIDEO;
798 vst->codec->codec_id = CODEC_ID_FLV1;
747a0554 799 if ( swf->samples_per_frame ) {
01f4895c
MN
800 vst->codec->time_base.den = 1000. / swf->ms_per_frame;
801 vst->codec->time_base.num = 1;
747a0554
TU
802 }
803 }
804 } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
de6d9b64
FB
805 /* streaming found */
806 get_byte(pb);
807 v = get_byte(pb);
747a0554 808 swf->samples_per_frame = get_le16(pb);
647b7762
GK
809 if (len!=4)
810 url_fskip(pb,len-4);
de6d9b64
FB
811 /* if mp3 streaming found, OK */
812 if ((v & 0x20) != 0) {
747a0554
TU
813 if ( tag == TAG_STREAMHEAD2 ) {
814 get_le16(pb);
815 }
816 ast = av_new_stream(s, 1);
9ee91c2f 817 av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
747a0554 818 if (!ast)
de6d9b64 819 return -ENOMEM;
1e491e29 820
de6d9b64 821 if (v & 0x01)
01f4895c 822 ast->codec->channels = 2;
de6d9b64 823 else
01f4895c 824 ast->codec->channels = 1;
de6d9b64
FB
825
826 switch((v>> 2) & 0x03) {
827 case 1:
01f4895c 828 ast->codec->sample_rate = 11025;
de6d9b64
FB
829 break;
830 case 2:
01f4895c 831 ast->codec->sample_rate = 22050;
de6d9b64
FB
832 break;
833 case 3:
01f4895c 834 ast->codec->sample_rate = 44100;
de6d9b64
FB
835 break;
836 default:
747a0554 837 av_free(ast);
0bd586c5 838 return AVERROR_IO;
de6d9b64 839 }
01f4895c
MN
840 ast->codec->codec_type = CODEC_TYPE_AUDIO;
841 ast->codec->codec_id = CODEC_ID_MP3;
de6d9b64
FB
842 }
843 } else {
844 url_fskip(pb, len);
845 }
846 }
747a0554
TU
847 url_fseek(pb, firstTagOff, SEEK_SET);
848
de6d9b64
FB
849 return 0;
850}
851
852static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
853{
747a0554 854 SWFContext *swf = s->priv_data;
de6d9b64 855 ByteIOContext *pb = &s->pb;
747a0554
TU
856 AVStream *st = 0;
857 int tag, len, i, frame;
de6d9b64
FB
858
859 for(;;) {
860 tag = get_swf_tag(pb, &len);
861 if (tag < 0)
0bd586c5 862 return AVERROR_IO;
747a0554
TU
863 if (tag == TAG_VIDEOFRAME) {
864 for( i=0; i<s->nb_streams; i++ ) {
865 st = s->streams[i];
866 if (st->id == 0) {
867 if ( get_le16(pb) == swf->ch_id ) {
868 frame = get_le16(pb);
2692067a 869 av_get_packet(pb, pkt, len-4);
747a0554
TU
870 pkt->pts = frame * swf->ms_per_frame;
871 pkt->stream_index = st->index;
747a0554
TU
872 return pkt->size;
873 } else {
874 url_fskip(pb, len-2);
875 continue;
876 }
877 }
878 }
879 url_fskip(pb, len);
880 } else if (tag == TAG_STREAMBLOCK) {
881 for( i=0; i<s->nb_streams; i++ ) {
882 st = s->streams[i];
883 if (st->id == 1) {
2692067a 884 av_get_packet(pb, pkt, len);
747a0554 885 pkt->stream_index = st->index;
747a0554
TU
886 return pkt->size;
887 }
888 }
889 url_fskip(pb, len);
de6d9b64
FB
890 } else {
891 url_fskip(pb, len);
892 }
893 }
894 return 0;
895}
896
897static int swf_read_close(AVFormatContext *s)
898{
899 return 0;
900}
901
c9a65ca8
FB
902static AVInputFormat swf_iformat = {
903 "swf",
904 "Flash format",
747a0554 905 sizeof(SWFContext),
c9a65ca8
FB
906 swf_probe,
907 swf_read_header,
908 swf_read_packet,
909 swf_read_close,
910};
911
764ef400 912#ifdef CONFIG_ENCODERS
c9a65ca8 913static AVOutputFormat swf_oformat = {
de6d9b64
FB
914 "swf",
915 "Flash format",
916 "application/x-shockwave-flash",
917 "swf",
c9a65ca8 918 sizeof(SWFContext),
747a0554
TU
919 CODEC_ID_MP3,
920 CODEC_ID_FLV1,
de6d9b64
FB
921 swf_write_header,
922 swf_write_packet,
923 swf_write_trailer,
de6d9b64 924};
764ef400 925#endif //CONFIG_ENCODERS
c9a65ca8
FB
926
927int swf_init(void)
928{
929 av_register_input_format(&swf_iformat);
764ef400 930#ifdef CONFIG_ENCODERS
c9a65ca8 931 av_register_output_format(&swf_oformat);
764ef400 932#endif //CONFIG_ENCODERS
c9a65ca8
FB
933 return 0;
934}