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