Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 1ae7518d

History | View | Annotate | Download (27.7 KB)

1
/*
2
 * Flash Compatible Streaming Format
3
 * Copyright (c) 2000 Fabrice Bellard.
4
 * Copyright (c) 2003 Tinic Uro.
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
#include "avformat.h"
23
#include "bitstream.h"
24
#include "riff.h"    /* for CodecTag */
25

    
26
/* should have a generic way to indicate probable size */
27
#define DUMMY_FILE_SIZE   (100 * 1024 * 1024)
28
#define DUMMY_DURATION    600 /* in seconds */
29

    
30
#define TAG_END           0
31
#define TAG_SHOWFRAME     1
32
#define TAG_DEFINESHAPE   2
33
#define TAG_FREECHARACTER 3
34
#define TAG_PLACEOBJECT   4
35
#define TAG_REMOVEOBJECT  5
36
#define TAG_STREAMHEAD    18
37
#define TAG_STREAMBLOCK   19
38
#define TAG_JPEG2         21
39
#define TAG_PLACEOBJECT2  26
40
#define TAG_STREAMHEAD2   45
41
#define TAG_VIDEOSTREAM   60
42
#define TAG_VIDEOFRAME    61
43

    
44
#define TAG_LONG         0x100
45

    
46
/* flags for shape definition */
47
#define FLAG_MOVETO      0x01
48
#define FLAG_SETFILL0    0x02
49
#define FLAG_SETFILL1    0x04
50

    
51
#define AUDIO_FIFO_SIZE 65536
52

    
53
/* character id used */
54
#define BITMAP_ID 0
55
#define VIDEO_ID 0
56
#define SHAPE_ID  1
57

    
58
#undef NDEBUG
59
#include <assert.h>
60

    
61
typedef struct {
62
    int audio_stream_index;
63
    offset_t duration_pos;
64
    offset_t tag_pos;
65

    
66
    int samples_per_frame;
67
    int sound_samples;
68
    int video_samples;
69
    int swf_frame_number;
70
    int video_frame_number;
71
    int ms_per_frame;
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 AVCodecTag swf_codec_tags[] = {
84
    {CODEC_ID_FLV1, 0x02},
85
    {CODEC_ID_VP6F, 0x04},
86
    {0, 0},
87
};
88

    
89
static const int sSampleRates[3][4] = {
90
    {44100, 48000, 32000, 0},
91
    {22050, 24000, 16000, 0},
92
    {11025, 12000,  8000, 0},
93
};
94

    
95
static const int sBitRates[2][3][15] = {
96
    {   {  0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
97
        {  0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
98
        {  0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
99
    },
100
    {   {  0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
101
        {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
102
        {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
103
    },
104
};
105

    
106
static const int sSamplesPerFrame[3][3] =
107
{
108
    {  384,     1152,    1152 },
109
    {  384,     1152,     576 },
110
    {  384,     1152,     576 }
111
};
112

    
113
static const int sBitsPerSlot[3] = {
114
    32,
115
    8,
116
    8
117
};
118

    
119
static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
120
{
121
    uint8_t *dataTmp = (uint8_t *)data;
122
    uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
123
    int layerID = 3 - ((header >> 17) & 0x03);
124
    int bitRateID = ((header >> 12) & 0x0f);
125
    int sampleRateID = ((header >> 10) & 0x03);
126
    int bitRate = 0;
127
    int bitsPerSlot = sBitsPerSlot[layerID];
128
    int isPadded = ((header >> 9) & 0x01);
129

    
130
    if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
131
        return 0;
132
    }
133

    
134
    *isMono = ((header >>  6) & 0x03) == 0x03;
135

    
136
    if ( (header >> 19 ) & 0x01 ) {
137
        *sampleRate = sSampleRates[0][sampleRateID];
138
        bitRate = sBitRates[0][layerID][bitRateID] * 1000;
139
        *samplesPerFrame = sSamplesPerFrame[0][layerID];
140
    } else {
141
        if ( (header >> 20) & 0x01 ) {
142
            *sampleRate = sSampleRates[1][sampleRateID];
143
            bitRate = sBitRates[1][layerID][bitRateID] * 1000;
144
            *samplesPerFrame = sSamplesPerFrame[1][layerID];
145
        } else {
146
            *sampleRate = sSampleRates[2][sampleRateID];
147
            bitRate = sBitRates[1][layerID][bitRateID] * 1000;
148
            *samplesPerFrame = sSamplesPerFrame[2][layerID];
149
        }
150
    }
151

    
152
    *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
153

    
154
    return 1;
155
}
156

    
157
#ifdef CONFIG_MUXERS
158
static void put_swf_tag(AVFormatContext *s, int tag)
159
{
160
    SWFContext *swf = s->priv_data;
161
    ByteIOContext *pb = &s->pb;
162

    
163
    swf->tag_pos = url_ftell(pb);
164
    swf->tag = tag;
165
    /* reserve some room for the tag */
166
    if (tag & TAG_LONG) {
167
        put_le16(pb, 0);
168
        put_le32(pb, 0);
169
    } else {
170
        put_le16(pb, 0);
171
    }
172
}
173

    
174
static void put_swf_end_tag(AVFormatContext *s)
175
{
176
    SWFContext *swf = s->priv_data;
177
    ByteIOContext *pb = &s->pb;
178
    offset_t pos;
179
    int tag_len, tag;
180

    
181
    pos = url_ftell(pb);
182
    tag_len = pos - swf->tag_pos - 2;
183
    tag = swf->tag;
184
    url_fseek(pb, swf->tag_pos, SEEK_SET);
185
    if (tag & TAG_LONG) {
186
        tag &= ~TAG_LONG;
187
        put_le16(pb, (tag << 6) | 0x3f);
188
        put_le32(pb, tag_len - 4);
189
    } else {
190
        assert(tag_len < 0x3f);
191
        put_le16(pb, (tag << 6) | tag_len);
192
    }
193
    url_fseek(pb, pos, SEEK_SET);
194
}
195

    
196
static inline void max_nbits(int *nbits_ptr, int val)
197
{
198
    int n;
199

    
200
    if (val == 0)
201
        return;
202
    val = abs(val);
203
    n = 1;
204
    while (val != 0) {
205
        n++;
206
        val >>= 1;
207
    }
208
    if (n > *nbits_ptr)
209
        *nbits_ptr = n;
210
}
211

    
212
static void put_swf_rect(ByteIOContext *pb,
213
                         int xmin, int xmax, int ymin, int ymax)
214
{
215
    PutBitContext p;
216
    uint8_t buf[256];
217
    int nbits, mask;
218

    
219
    init_put_bits(&p, buf, sizeof(buf));
220

    
221
    nbits = 0;
222
    max_nbits(&nbits, xmin);
223
    max_nbits(&nbits, xmax);
224
    max_nbits(&nbits, ymin);
225
    max_nbits(&nbits, ymax);
226
    mask = (1 << nbits) - 1;
227

    
228
    /* rectangle info */
229
    put_bits(&p, 5, nbits);
230
    put_bits(&p, nbits, xmin & mask);
231
    put_bits(&p, nbits, xmax & mask);
232
    put_bits(&p, nbits, ymin & mask);
233
    put_bits(&p, nbits, ymax & mask);
234

    
235
    flush_put_bits(&p);
236
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
237
}
238

    
239
static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
240
{
241
    int nbits, mask;
242

    
243
    put_bits(pb, 1, 1); /* edge */
244
    put_bits(pb, 1, 1); /* line select */
245
    nbits = 2;
246
    max_nbits(&nbits, dx);
247
    max_nbits(&nbits, dy);
248

    
249
    mask = (1 << nbits) - 1;
250
    put_bits(pb, 4, nbits - 2); /* 16 bits precision */
251
    if (dx == 0) {
252
      put_bits(pb, 1, 0);
253
      put_bits(pb, 1, 1);
254
      put_bits(pb, nbits, dy & mask);
255
    } else if (dy == 0) {
256
      put_bits(pb, 1, 0);
257
      put_bits(pb, 1, 0);
258
      put_bits(pb, nbits, dx & mask);
259
    } else {
260
      put_bits(pb, 1, 1);
261
      put_bits(pb, nbits, dx & mask);
262
      put_bits(pb, nbits, dy & mask);
263
    }
264
}
265

    
266
#define FRAC_BITS 16
267

    
268
/* put matrix */
269
static void put_swf_matrix(ByteIOContext *pb,
270
                           int a, int b, int c, int d, int tx, int ty)
271
{
272
    PutBitContext p;
273
    uint8_t buf[256];
274
    int nbits;
275

    
276
    init_put_bits(&p, buf, sizeof(buf));
277

    
278
    put_bits(&p, 1, 1); /* a, d present */
279
    nbits = 1;
280
    max_nbits(&nbits, a);
281
    max_nbits(&nbits, d);
282
    put_bits(&p, 5, nbits); /* nb bits */
283
    put_bits(&p, nbits, a);
284
    put_bits(&p, nbits, d);
285

    
286
    put_bits(&p, 1, 1); /* b, c present */
287
    nbits = 1;
288
    max_nbits(&nbits, c);
289
    max_nbits(&nbits, b);
290
    put_bits(&p, 5, nbits); /* nb bits */
291
    put_bits(&p, nbits, c);
292
    put_bits(&p, nbits, b);
293

    
294
    nbits = 1;
295
    max_nbits(&nbits, tx);
296
    max_nbits(&nbits, ty);
297
    put_bits(&p, 5, nbits); /* nb bits */
298
    put_bits(&p, nbits, tx);
299
    put_bits(&p, nbits, ty);
300

    
301
    flush_put_bits(&p);
302
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
303
}
304

    
305
/* */
306
static int swf_write_header(AVFormatContext *s)
307
{
308
    SWFContext *swf = s->priv_data;
309
    ByteIOContext *pb = &s->pb;
310
    AVCodecContext *enc, *audio_enc, *video_enc;
311
    PutBitContext p;
312
    uint8_t buf1[256];
313
    int i, width, height, rate, rate_base;
314

    
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_VP6F ||
332
                 enc->codec_id == CODEC_ID_FLV1 ||
333
                 enc->codec_id == CODEC_ID_MJPEG ) {
334
                video_enc = enc;
335
            } else {
336
                av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
337
                return -1;
338
            }
339
        }
340
    }
341

    
342
    if (!video_enc) {
343
        /* currenty, cannot work correctly if audio only */
344
        swf->video_type = 0;
345
        width = 320;
346
        height = 200;
347
        rate = 10;
348
        rate_base= 1;
349
    } else {
350
        swf->video_type = video_enc->codec_id;
351
        width = video_enc->width;
352
        height = video_enc->height;
353
        rate = video_enc->time_base.den;
354
        rate_base = video_enc->time_base.num;
355
    }
356

    
357
    if (!audio_enc ) {
358
        swf->audio_type = 0;
359
        swf->samples_per_frame = ( 44100. * rate_base ) / rate;
360
    } else {
361
        swf->audio_type = audio_enc->codec_id;
362
        swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
363
    }
364

    
365
    put_tag(pb, "FWS");
366
    if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
367
        put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
368
    } else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
369
        put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
370
    } else {
371
        put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
372
    }
373
    put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
374
                                      (will be patched if not streamed) */
375

    
376
    put_swf_rect(pb, 0, width * 20, 0, height * 20);
377
    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
378
    swf->duration_pos = url_ftell(pb);
379
    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
380

    
381
    /* define a shape with the jpeg inside */
382
    if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
383
                       video_enc->codec_id == CODEC_ID_FLV1 )) {
384
    } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
385
        put_swf_tag(s, TAG_DEFINESHAPE);
386

    
387
        put_le16(pb, SHAPE_ID); /* ID of shape */
388
        /* bounding rectangle */
389
        put_swf_rect(pb, 0, width, 0, height);
390
        /* style info */
391
        put_byte(pb, 1); /* one fill style */
392
        put_byte(pb, 0x41); /* clipped bitmap fill */
393
        put_le16(pb, BITMAP_ID); /* bitmap ID */
394
        /* position of the bitmap */
395
        put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
396
                        0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
397
        put_byte(pb, 0); /* no line style */
398

    
399
        /* shape drawing */
400
        init_put_bits(&p, buf1, sizeof(buf1));
401
        put_bits(&p, 4, 1); /* one fill bit */
402
        put_bits(&p, 4, 0); /* zero line bit */
403

    
404
        put_bits(&p, 1, 0); /* not an edge */
405
        put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
406
        put_bits(&p, 5, 1); /* nbits */
407
        put_bits(&p, 1, 0); /* X */
408
        put_bits(&p, 1, 0); /* Y */
409
        put_bits(&p, 1, 1); /* set fill style 1 */
410

    
411
        /* draw the rectangle ! */
412
        put_swf_line_edge(&p, width, 0);
413
        put_swf_line_edge(&p, 0, height);
414
        put_swf_line_edge(&p, -width, 0);
415
        put_swf_line_edge(&p, 0, -height);
416

    
417
        /* end of shape */
418
        put_bits(&p, 1, 0); /* not an edge */
419
        put_bits(&p, 5, 0);
420

    
421
        flush_put_bits(&p);
422
        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
423

    
424
        put_swf_end_tag(s);
425
    }
426

    
427
    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
428
        int v;
429

    
430
        /* start sound */
431
        put_swf_tag(s, TAG_STREAMHEAD2);
432

    
433
        v = 0;
434
        switch(audio_enc->sample_rate) {
435
        case 11025:
436
            v |= 1 << 2;
437
            break;
438
        case 22050:
439
            v |= 2 << 2;
440
            break;
441
        case 44100:
442
            v |= 3 << 2;
443
            break;
444
        default:
445
            /* not supported */
446
            av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
447
            av_free(swf->audio_fifo);
448
            return -1;
449
        }
450
        v |= 0x02; /* 16 bit playback */
451
        if (audio_enc->channels == 2)
452
            v |= 0x01; /* stereo playback */
453
        put_byte(&s->pb, v);
454
        v |= 0x20; /* mp3 compressed */
455
        put_byte(&s->pb, v);
456
        put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
457
        put_le16(&s->pb, 0);
458

    
459
        put_swf_end_tag(s);
460
    }
461

    
462
    put_flush_packet(&s->pb);
463
    return 0;
464
}
465

    
466
static int swf_write_video(AVFormatContext *s,
467
                           AVCodecContext *enc, const uint8_t *buf, int size)
468
{
469
    SWFContext *swf = s->priv_data;
470
    ByteIOContext *pb = &s->pb;
471
    int c = 0;
472
    int outSize = 0;
473
    int outSamples = 0;
474

    
475
    /* Flash Player limit */
476
    if ( swf->swf_frame_number == 16000 ) {
477
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
478
    }
479

    
480
    if ( swf->audio_type ) {
481
        /* Prescan audio data for this swf frame */
482
retry_swf_audio_packet:
483
        if ( ( swf->audio_size-outSize ) >= 4 ) {
484
            int mp3FrameSize = 0;
485
            int mp3SampleRate = 0;
486
            int mp3IsMono = 0;
487
            int mp3SamplesPerFrame = 0;
488

    
489
            /* copy out mp3 header from ring buffer */
490
            uint8_t header[4];
491
            for (c=0; c<4; c++) {
492
                header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
493
            }
494

    
495
            if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
496
                if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
497
                    outSize += mp3FrameSize;
498
                    outSamples += mp3SamplesPerFrame;
499
                    if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
500
                        goto retry_swf_audio_packet;
501
                    }
502
                }
503
            } else {
504
                /* invalid mp3 data, skip forward
505
                we need to do this since the Flash Player
506
                does not like custom headers */
507
                swf->audio_in_pos ++;
508
                swf->audio_size --;
509
                swf->audio_in_pos %= AUDIO_FIFO_SIZE;
510
                goto retry_swf_audio_packet;
511
            }
512
        }
513

    
514
        /* audio stream is behind video stream, bail */
515
        if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
516
            return 0;
517
        }
518
    }
519

    
520
            if ( swf->video_type == CODEC_ID_VP6F ||
521
                 swf->video_type == CODEC_ID_FLV1 ) {
522
                if ( swf->video_frame_number == 0 ) {
523
                    /* create a new video object */
524
                    put_swf_tag(s, TAG_VIDEOSTREAM);
525
                    put_le16(pb, VIDEO_ID);
526
                    put_le16(pb, 15000 ); /* hard flash player limit */
527
                    put_le16(pb, enc->width);
528
                    put_le16(pb, enc->height);
529
                    put_byte(pb, 0);
530
                    put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
531
                    put_swf_end_tag(s);
532

    
533
                    /* place the video object for the first time */
534
                    put_swf_tag(s, TAG_PLACEOBJECT2);
535
                    put_byte(pb, 0x36);
536
                    put_le16(pb, 1);
537
                    put_le16(pb, VIDEO_ID);
538
                    put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
539
                    put_le16(pb, swf->video_frame_number );
540
                    put_byte(pb, 'v');
541
                    put_byte(pb, 'i');
542
                    put_byte(pb, 'd');
543
                    put_byte(pb, 'e');
544
                    put_byte(pb, 'o');
545
                    put_byte(pb, 0x00);
546
                    put_swf_end_tag(s);
547
                } else {
548
                    /* mark the character for update */
549
                    put_swf_tag(s, TAG_PLACEOBJECT2);
550
                    put_byte(pb, 0x11);
551
                    put_le16(pb, 1);
552
                    put_le16(pb, swf->video_frame_number );
553
                    put_swf_end_tag(s);
554
                }
555

    
556
                    /* set video frame data */
557
                    put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
558
                    put_le16(pb, VIDEO_ID);
559
                    put_le16(pb, swf->video_frame_number++ );
560
                    put_buffer(pb, buf, size);
561
                    put_swf_end_tag(s);
562
            } else if ( swf->video_type == CODEC_ID_MJPEG ) {
563
                if (swf->swf_frame_number > 0) {
564
                    /* remove the shape */
565
                    put_swf_tag(s, TAG_REMOVEOBJECT);
566
                    put_le16(pb, SHAPE_ID); /* shape ID */
567
                    put_le16(pb, 1); /* depth */
568
                    put_swf_end_tag(s);
569

    
570
                    /* free the bitmap */
571
                    put_swf_tag(s, TAG_FREECHARACTER);
572
                    put_le16(pb, BITMAP_ID);
573
                    put_swf_end_tag(s);
574
                }
575

    
576
                put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
577

    
578
                put_le16(pb, BITMAP_ID); /* ID of the image */
579

    
580
                /* a dummy jpeg header seems to be required */
581
                put_byte(pb, 0xff);
582
                put_byte(pb, 0xd8);
583
                put_byte(pb, 0xff);
584
                put_byte(pb, 0xd9);
585
                /* write the jpeg image */
586
                put_buffer(pb, buf, size);
587

    
588
                put_swf_end_tag(s);
589

    
590
                /* draw the shape */
591

    
592
                put_swf_tag(s, TAG_PLACEOBJECT);
593
                put_le16(pb, SHAPE_ID); /* shape ID */
594
                put_le16(pb, 1); /* depth */
595
                put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
596
                put_swf_end_tag(s);
597
            } else {
598
                /* invalid codec */
599
            }
600

    
601
            swf->swf_frame_number ++;
602

    
603
    swf->video_samples += swf->samples_per_frame;
604

    
605
    /* streaming sound always should be placed just before showframe tags */
606
    if ( outSize > 0 ) {
607
        put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
608
        put_le16(pb, outSamples);
609
        put_le16(pb, 0);
610
        for (c=0; c<outSize; c++) {
611
            put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
612
        }
613
        put_swf_end_tag(s);
614

    
615
        /* update FIFO */
616
        swf->sound_samples += outSamples;
617
        swf->audio_in_pos += outSize;
618
        swf->audio_size -= outSize;
619
        swf->audio_in_pos %= AUDIO_FIFO_SIZE;
620
    }
621

    
622
    /* output the frame */
623
    put_swf_tag(s, TAG_SHOWFRAME);
624
    put_swf_end_tag(s);
625

    
626
    put_flush_packet(&s->pb);
627

    
628
    return 0;
629
}
630

    
631
static int swf_write_audio(AVFormatContext *s,
632
                           AVCodecContext *enc, const uint8_t *buf, int size)
633
{
634
    SWFContext *swf = s->priv_data;
635
    int c = 0;
636

    
637
    /* Flash Player limit */
638
    if ( swf->swf_frame_number == 16000 ) {
639
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
640
    }
641

    
642
    if (enc->codec_id == CODEC_ID_MP3 ) {
643
        for (c=0; c<size; c++) {
644
            swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
645
        }
646
        swf->audio_size += size;
647
        swf->audio_out_pos += size;
648
        swf->audio_out_pos %= AUDIO_FIFO_SIZE;
649
    }
650

    
651
    /* if audio only stream make sure we add swf frames */
652
    if ( swf->video_type == 0 ) {
653
        swf_write_video(s, enc, 0, 0);
654
    }
655

    
656
    return 0;
657
}
658

    
659
static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
660
{
661
    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
662
    if (codec->codec_type == CODEC_TYPE_AUDIO)
663
        return swf_write_audio(s, codec, pkt->data, pkt->size);
664
    else
665
        return swf_write_video(s, codec, pkt->data, pkt->size);
666
}
667

    
668
static int swf_write_trailer(AVFormatContext *s)
669
{
670
    SWFContext *swf = s->priv_data;
671
    ByteIOContext *pb = &s->pb;
672
    AVCodecContext *enc, *video_enc;
673
    int file_size, i;
674

    
675
    video_enc = NULL;
676
    for(i=0;i<s->nb_streams;i++) {
677
        enc = s->streams[i]->codec;
678
        if (enc->codec_type == CODEC_TYPE_VIDEO)
679
            video_enc = enc;
680
    }
681

    
682
    put_swf_tag(s, TAG_END);
683
    put_swf_end_tag(s);
684

    
685
    put_flush_packet(&s->pb);
686

    
687
    /* patch file size and number of frames if not streamed */
688
    if (!url_is_streamed(&s->pb) && video_enc) {
689
        file_size = url_ftell(pb);
690
        url_fseek(pb, 4, SEEK_SET);
691
        put_le32(pb, file_size);
692
        url_fseek(pb, swf->duration_pos, SEEK_SET);
693
        put_le16(pb, video_enc->frame_number);
694
        url_fseek(pb, file_size, SEEK_SET);
695
    }
696

    
697
    av_free(swf->audio_fifo);
698

    
699
    return 0;
700
}
701
#endif //CONFIG_MUXERS
702

    
703
/*********************************************/
704
/* Extract FLV encoded frame and MP3 from swf
705
   Note that the detection of the real frame
706
   is inaccurate at this point as it can be
707
   quite tricky to determine, you almost certainly
708
   will get a bad audio/video sync */
709

    
710
static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
711
{
712
    int tag, len;
713

    
714
    if (url_feof(pb))
715
        return -1;
716

    
717
    tag = get_le16(pb);
718
    len = tag & 0x3f;
719
    tag = tag >> 6;
720
    if (len == 0x3f) {
721
        len = get_le32(pb);
722
    }
723
//    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
724
    *len_ptr = len;
725
    return tag;
726
}
727

    
728

    
729
static int swf_probe(AVProbeData *p)
730
{
731
    /* check file header */
732
    if (p->buf_size <= 16)
733
        return 0;
734
    if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
735
        p->buf[2] == 'S')
736
        return AVPROBE_SCORE_MAX;
737
    else
738
        return 0;
739
}
740

    
741
static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
742
{
743
    SWFContext *swf = s->priv_data;
744
    ByteIOContext *pb = &s->pb;
745
    int nbits, len, frame_rate, tag, v;
746
    offset_t firstTagOff;
747
    AVStream *ast = 0;
748
    AVStream *vst = 0;
749

    
750
    tag = get_be32(pb) & 0xffffff00;
751

    
752
    if (tag == MKBETAG('C', 'W', 'S', 0))
753
    {
754
        av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
755
        return AVERROR_IO;
756
    }
757
    if (tag != MKBETAG('F', 'W', 'S', 0))
758
        return AVERROR_IO;
759
    get_le32(pb);
760
    /* skip rectangle size */
761
    nbits = get_byte(pb) >> 3;
762
    len = (4 * nbits - 3 + 7) / 8;
763
    url_fskip(pb, len);
764
    frame_rate = get_le16(pb);
765
    get_le16(pb); /* frame count */
766

    
767
    /* The Flash Player converts 8.8 frame rates
768
       to milliseconds internally. Do the same to get
769
       a correct framerate */
770
    swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
771
    swf->samples_per_frame = 0;
772

    
773
    firstTagOff = url_ftell(pb);
774
    for(;;) {
775
        tag = get_swf_tag(pb, &len);
776
        if (tag < 0) {
777
            if ( ast || vst ) {
778
                if ( vst && ast ) {
779
                    vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;
780
                    vst->codec->time_base.num = 1;
781
                }
782
                break;
783
            }
784
            av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
785
            return AVERROR_IO;
786
        }
787
        if ( tag == TAG_VIDEOSTREAM && !vst) {
788
            int ch_id = get_le16(pb);
789
            get_le16(pb);
790
            get_le16(pb);
791
            get_le16(pb);
792
            get_byte(pb);
793
            /* Check for FLV1 */
794
            vst = av_new_stream(s, ch_id);
795
            av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
796
            vst->codec->codec_type = CODEC_TYPE_VIDEO;
797
            vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
798
            if (swf->samples_per_frame) {
799
                vst->codec->time_base.den = 1000. / swf->ms_per_frame;
800
                vst->codec->time_base.num = 1;
801
            }
802
        } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
803
            /* streaming found */
804
            int sample_rate_code;
805
            get_byte(pb);
806
            v = get_byte(pb);
807
            swf->samples_per_frame = get_le16(pb);
808
            ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
809
            av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
810
            swf->audio_stream_index = ast->index;
811
            ast->codec->channels = 1 + (v&1);
812
            ast->codec->codec_type = CODEC_TYPE_AUDIO;
813
            if (v & 0x20)
814
                ast->codec->codec_id = CODEC_ID_MP3;
815
            ast->need_parsing = 1;
816
            sample_rate_code= (v>>2) & 3;
817
            if (!sample_rate_code)
818
                return AVERROR_IO;
819
            ast->codec->sample_rate = 11025 << (sample_rate_code-1);
820
            if (len > 4)
821
                url_fskip(pb,len-4);
822

    
823
        } else if (tag == TAG_JPEG2 && !vst) {
824
            vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
825
            av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
826
            vst->codec->codec_type = CODEC_TYPE_VIDEO;
827
            vst->codec->codec_id = CODEC_ID_MJPEG;
828
            if (swf->samples_per_frame) {
829
                vst->codec->time_base.den = 1000. / swf->ms_per_frame;
830
                vst->codec->time_base.num = 1;
831
            }
832
            url_fskip(pb, len);
833
        } else {
834
            url_fskip(pb, len);
835
        }
836
    }
837
    url_fseek(pb, firstTagOff, SEEK_SET);
838

    
839
    return 0;
840
}
841

    
842
static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
843
{
844
    SWFContext *swf = s->priv_data;
845
    ByteIOContext *pb = &s->pb;
846
    AVStream *st = 0;
847
    int tag, len, i, frame;
848

    
849
    for(;;) {
850
        tag = get_swf_tag(pb, &len);
851
        if (tag < 0)
852
            return AVERROR_IO;
853
        if (tag == TAG_VIDEOFRAME) {
854
            int ch_id = get_le16(pb);
855
            len -= 2;
856
            for( i=0; i<s->nb_streams; i++ ) {
857
                st = s->streams[i];
858
                if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
859
                    frame = get_le16(pb);
860
                    av_get_packet(pb, pkt, len-2);
861
                    pkt->pts = frame * swf->ms_per_frame;
862
                    pkt->stream_index = st->index;
863
                    return pkt->size;
864
                }
865
            }
866
        } else if (tag == TAG_STREAMBLOCK) {
867
            st = s->streams[swf->audio_stream_index];
868
            if (st->codec->codec_id == CODEC_ID_MP3) {
869
                url_fskip(pb, 4);
870
                av_get_packet(pb, pkt, len-4);
871
                pkt->stream_index = st->index;
872
                return pkt->size;
873
            }
874
        } else if (tag == TAG_JPEG2) {
875
            for (i=0; i<s->nb_streams; i++) {
876
                st = s->streams[i];
877
                if (st->id == -2) {
878
                    get_le16(pb); /* BITMAP_ID */
879
                    av_new_packet(pkt, len-2);
880
                    get_buffer(pb, pkt->data, 4);
881
                    if (AV_RB32(pkt->data) == 0xffd8ffd9) {
882
                        /* old SWF files containing SOI/EOI as data start */
883
                        pkt->size -= 4;
884
                        get_buffer(pb, pkt->data, pkt->size);
885
                    } else {
886
                        get_buffer(pb, pkt->data + 4, pkt->size - 4);
887
                    }
888
                    pkt->stream_index = st->index;
889
                    return pkt->size;
890
                }
891
            }
892
        }
893
        url_fskip(pb, len);
894
    }
895
    return 0;
896
}
897

    
898
static int swf_read_close(AVFormatContext *s)
899
{
900
     return 0;
901
}
902

    
903
#ifdef CONFIG_SWF_DEMUXER
904
AVInputFormat swf_demuxer = {
905
    "swf",
906
    "Flash format",
907
    sizeof(SWFContext),
908
    swf_probe,
909
    swf_read_header,
910
    swf_read_packet,
911
    swf_read_close,
912
};
913
#endif
914
#ifdef CONFIG_SWF_MUXER
915
AVOutputFormat swf_muxer = {
916
    "swf",
917
    "Flash format",
918
    "application/x-shockwave-flash",
919
    "swf",
920
    sizeof(SWFContext),
921
    CODEC_ID_MP3,
922
    CODEC_ID_FLV1,
923
    swf_write_header,
924
    swf_write_packet,
925
    swf_write_trailer,
926
};
927
#endif