Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 649b918c

History | View | Annotate | Download (26.9 KB)

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
}