Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 20b02bc6

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

    
22
/* should have a generic way to indicate probable size */
23
#define DUMMY_FILE_SIZE   (100 * 1024 * 1024)
24
#define DUMMY_DURATION    600 /* in seconds */
25

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

    
40
#define TAG_LONG         0x100
41

    
42
/* flags for shape definition */
43
#define FLAG_MOVETO      0x01
44
#define FLAG_SETFILL0    0x02
45
#define FLAG_SETFILL1    0x04
46

    
47
#define SWF_VIDEO_CODEC_FLV1        0x02
48

    
49
#define AUDIO_FIFO_SIZE 65536
50

    
51
/* character id used */
52
#define BITMAP_ID 0
53
#define VIDEO_ID 0
54
#define SHAPE_ID  1
55

    
56
#undef NDEBUG
57
#include <assert.h>
58

    
59
typedef struct {
60

    
61
    offset_t duration_pos;
62
    offset_t tag_pos;
63
    
64
    int samples_per_frame;
65
    int sound_samples;
66
    int video_samples;
67
    int swf_frame_number;
68
    int video_frame_number;
69
    int ms_per_frame;
70
    int ch_id;
71
    int tag;
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;
80
} SWFContext;
81

    
82
static const int sSampleRates[3][4] = {
83
    {44100, 48000, 32000, 0},
84
    {22050, 24000, 16000, 0},
85
    {11025, 12000,  8000, 0},
86
};
87

    
88
static const int sBitRates[2][3][15] = {
89
    {   {  0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
90
        {  0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
91
        {  0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
92
    },
93
    {   {  0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
94
        {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
95
        {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
96
    },
97
};
98

    
99
static const int sSamplesPerFrame[3][3] =
100
{
101
    {  384,     1152,    1152 },
102
    {  384,     1152,     576 },
103
    {  384,     1152,     576 }
104
};
105

    
106
static const int sBitsPerSlot[3] = {
107
    32,
108
    8,
109
    8
110
};
111

    
112
static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
113
{
114
    uint8_t *dataTmp = (uint8_t *)data;
115
    uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
116
    int layerID = 3 - ((header >> 17) & 0x03);
117
    int bitRateID = ((header >> 12) & 0x0f);
118
    int sampleRateID = ((header >> 10) & 0x03);
119
    int bitRate = 0;
120
    int bitsPerSlot = sBitsPerSlot[layerID];
121
    int isPadded = ((header >> 9) & 0x01);
122
    
123
    if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
124
        return 0;
125
    }
126

    
127
    *isMono = ((header >>  6) & 0x03) == 0x03;
128

    
129
    if ( (header >> 19 ) & 0x01 ) {
130
        *sampleRate = sSampleRates[0][sampleRateID];
131
        bitRate = sBitRates[0][layerID][bitRateID] * 1000;
132
        *samplesPerFrame = sSamplesPerFrame[0][layerID];
133
    } else {
134
        if ( (header >> 20) & 0x01 ) {
135
            *sampleRate = sSampleRates[1][sampleRateID];
136
            bitRate = sBitRates[1][layerID][bitRateID] * 1000;
137
            *samplesPerFrame = sSamplesPerFrame[1][layerID];
138
        } else {
139
            *sampleRate = sSampleRates[2][sampleRateID];
140
            bitRate = sBitRates[1][layerID][bitRateID] * 1000;
141
            *samplesPerFrame = sSamplesPerFrame[2][layerID];
142
        }
143
    }
144

    
145
    *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
146

    
147
    return 1;
148
}
149

    
150
#ifdef CONFIG_ENCODERS
151
static void put_swf_tag(AVFormatContext *s, int tag)
152
{
153
    SWFContext *swf = s->priv_data;
154
    ByteIOContext *pb = &s->pb;
155

    
156
    swf->tag_pos = url_ftell(pb);
157
    swf->tag = tag;
158
    /* reserve some room for the tag */
159
    if (tag & TAG_LONG) {
160
        put_le16(pb, 0);
161
        put_le32(pb, 0);
162
    } else {
163
        put_le16(pb, 0);
164
    }
165
}
166

    
167
static void put_swf_end_tag(AVFormatContext *s)
168
{
169
    SWFContext *swf = s->priv_data;
170
    ByteIOContext *pb = &s->pb;
171
    offset_t pos;
172
    int tag_len, tag;
173

    
174
    pos = url_ftell(pb);
175
    tag_len = pos - swf->tag_pos - 2;
176
    tag = swf->tag;
177
    url_fseek(pb, swf->tag_pos, SEEK_SET);
178
    if (tag & TAG_LONG) {
179
        tag &= ~TAG_LONG;
180
        put_le16(pb, (tag << 6) | 0x3f);
181
        put_le32(pb, tag_len - 4);
182
    } else {
183
        assert(tag_len < 0x3f);
184
        put_le16(pb, (tag << 6) | tag_len);
185
    }
186
    url_fseek(pb, pos, SEEK_SET);
187
}
188

    
189
static inline void max_nbits(int *nbits_ptr, int val)
190
{
191
    int n;
192

    
193
    if (val == 0)
194
        return;
195
    val = abs(val);
196
    n = 1;
197
    while (val != 0) {
198
        n++;
199
        val >>= 1;
200
    }
201
    if (n > *nbits_ptr)
202
        *nbits_ptr = n;
203
}
204

    
205
static void put_swf_rect(ByteIOContext *pb, 
206
                         int xmin, int xmax, int ymin, int ymax)
207
{
208
    PutBitContext p;
209
    uint8_t buf[256];
210
    int nbits, mask;
211

    
212
    init_put_bits(&p, buf, sizeof(buf));
213
    
214
    nbits = 0;
215
    max_nbits(&nbits, xmin);
216
    max_nbits(&nbits, xmax);
217
    max_nbits(&nbits, ymin);
218
    max_nbits(&nbits, ymax);
219
    mask = (1 << nbits) - 1;
220

    
221
    /* rectangle info */
222
    put_bits(&p, 5, nbits);
223
    put_bits(&p, nbits, xmin & mask);
224
    put_bits(&p, nbits, xmax & mask);
225
    put_bits(&p, nbits, ymin & mask);
226
    put_bits(&p, nbits, ymax & mask);
227
    
228
    flush_put_bits(&p);
229
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
230
}
231

    
232
static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
233
{
234
    int nbits, mask;
235

    
236
    put_bits(pb, 1, 1); /* edge */
237
    put_bits(pb, 1, 1); /* line select */
238
    nbits = 2;
239
    max_nbits(&nbits, dx);
240
    max_nbits(&nbits, dy);
241

    
242
    mask = (1 << nbits) - 1;
243
    put_bits(pb, 4, nbits - 2); /* 16 bits precision */
244
    if (dx == 0) {
245
      put_bits(pb, 1, 0); 
246
      put_bits(pb, 1, 1); 
247
      put_bits(pb, nbits, dy & mask);
248
    } else if (dy == 0) {
249
      put_bits(pb, 1, 0); 
250
      put_bits(pb, 1, 0); 
251
      put_bits(pb, nbits, dx & mask);
252
    } else {
253
      put_bits(pb, 1, 1); 
254
      put_bits(pb, nbits, dx & mask);
255
      put_bits(pb, nbits, dy & mask);
256
    }
257
}
258

    
259
#define FRAC_BITS 16
260

    
261
/* put matrix */
262
static void put_swf_matrix(ByteIOContext *pb,
263
                           int a, int b, int c, int d, int tx, int ty)
264
{
265
    PutBitContext p;
266
    uint8_t buf[256];
267
    int nbits;
268

    
269
    init_put_bits(&p, buf, sizeof(buf));
270
    
271
    put_bits(&p, 1, 1); /* a, d present */
272
    nbits = 1;
273
    max_nbits(&nbits, a);
274
    max_nbits(&nbits, d);
275
    put_bits(&p, 5, nbits); /* nb bits */
276
    put_bits(&p, nbits, a);
277
    put_bits(&p, nbits, d);
278
    
279
    put_bits(&p, 1, 1); /* b, c present */
280
    nbits = 1;
281
    max_nbits(&nbits, c);
282
    max_nbits(&nbits, b);
283
    put_bits(&p, 5, nbits); /* nb bits */
284
    put_bits(&p, nbits, c);
285
    put_bits(&p, nbits, b);
286

    
287
    nbits = 1;
288
    max_nbits(&nbits, tx);
289
    max_nbits(&nbits, ty);
290
    put_bits(&p, 5, nbits); /* nb bits */
291
    put_bits(&p, nbits, tx);
292
    put_bits(&p, nbits, ty);
293

    
294
    flush_put_bits(&p);
295
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
296
}
297

    
298
/* */
299
static int swf_write_header(AVFormatContext *s)
300
{
301
    SWFContext *swf;
302
    ByteIOContext *pb = &s->pb;
303
    AVCodecContext *enc, *audio_enc, *video_enc;
304
    PutBitContext p;
305
    uint8_t buf1[256];
306
    int i, width, height, rate, rate_base;
307

    
308
    swf = av_malloc(sizeof(SWFContext));
309
    if (!swf)
310
        return -1;
311
    s->priv_data = swf;
312

    
313
    swf->ch_id = -1;
314
    swf->audio_in_pos = 0;
315
    swf->audio_out_pos = 0;
316
    swf->audio_size = 0;
317
    swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
318
    swf->sound_samples = 0;
319
    swf->video_samples = 0;
320
    swf->swf_frame_number = 0;
321
    swf->video_frame_number = 0;
322

    
323
    video_enc = NULL;
324
    audio_enc = NULL;
325
    for(i=0;i<s->nb_streams;i++) {
326
        enc = &s->streams[i]->codec;
327
        if (enc->codec_type == CODEC_TYPE_AUDIO)
328
            audio_enc = enc;
329
        else {
330
            if ( enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == CODEC_ID_MJPEG ) {
331
                video_enc = enc;
332
            } else {
333
                av_log(enc, AV_LOG_ERROR, "SWF only supports FLV1 and MJPEG\n");
334
                return -1;
335
            }
336
        }
337
    }
338

    
339
    if (!video_enc) {
340
        /* currenty, cannot work correctly if audio only */
341
        swf->video_type = 0;
342
        width = 320;
343
        height = 200;
344
        rate = 10;
345
        rate_base= 1;
346
    } else {
347
        swf->video_type = video_enc->codec_id;
348
        width = video_enc->width;
349
        height = video_enc->height;
350
        rate = video_enc->frame_rate;
351
        rate_base = video_enc->frame_rate_base;
352
    }
353

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

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

    
371
    put_swf_rect(pb, 0, width * 20, 0, height * 20);
372
    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
373
    swf->duration_pos = url_ftell(pb);
374
    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
375
    
376
    /* define a shape with the jpeg inside */
377
    if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
378
    } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
379
        put_swf_tag(s, TAG_DEFINESHAPE);
380

    
381
        put_le16(pb, SHAPE_ID); /* ID of shape */
382
        /* bounding rectangle */
383
        put_swf_rect(pb, 0, width, 0, height);
384
        /* style info */
385
        put_byte(pb, 1); /* one fill style */
386
        put_byte(pb, 0x41); /* clipped bitmap fill */
387
        put_le16(pb, BITMAP_ID); /* bitmap ID */
388
        /* position of the bitmap */
389
        put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0, 
390
                        0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
391
        put_byte(pb, 0); /* no line style */
392
    
393
        /* shape drawing */
394
        init_put_bits(&p, buf1, sizeof(buf1));
395
        put_bits(&p, 4, 1); /* one fill bit */
396
        put_bits(&p, 4, 0); /* zero line bit */
397
     
398
        put_bits(&p, 1, 0); /* not an edge */
399
        put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
400
        put_bits(&p, 5, 1); /* nbits */
401
        put_bits(&p, 1, 0); /* X */
402
        put_bits(&p, 1, 0); /* Y */
403
        put_bits(&p, 1, 1); /* set fill style 1 */
404
    
405
        /* draw the rectangle ! */
406
        put_swf_line_edge(&p, width, 0);
407
        put_swf_line_edge(&p, 0, height);
408
        put_swf_line_edge(&p, -width, 0);
409
        put_swf_line_edge(&p, 0, -height);
410
    
411
        /* end of shape */
412
        put_bits(&p, 1, 0); /* not an edge */
413
        put_bits(&p, 5, 0);
414

    
415
        flush_put_bits(&p);
416
        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
417

    
418
        put_swf_end_tag(s);
419
    }
420
    
421
    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
422
        int v;
423

    
424
        /* start sound */
425
        put_swf_tag(s, TAG_STREAMHEAD2);
426

    
427
        v = 0;
428
        switch(audio_enc->sample_rate) {
429
        case 11025:
430
            v |= 1 << 2;
431
            break;
432
        case 22050:
433
            v |= 2 << 2;
434
            break;
435
        case 44100:
436
            v |= 3 << 2;
437
            break;
438
        default:
439
            /* not supported */
440
            av_free(swf->audio_fifo);
441
            av_free(swf);
442
            return -1;
443
        }
444
        v |= 0x02; /* 16 bit playback */
445
        if (audio_enc->channels == 2)
446
            v |= 0x01; /* stereo playback */
447
        put_byte(&s->pb, v);
448
        v |= 0x20; /* mp3 compressed */
449
        put_byte(&s->pb, v);
450
        put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
451
        put_le16(&s->pb, 0);
452
        
453
        put_swf_end_tag(s);
454
    }
455

    
456
    put_flush_packet(&s->pb);
457
    return 0;
458
}
459

    
460
static int swf_write_video(AVFormatContext *s, 
461
                           AVCodecContext *enc, const uint8_t *buf, int size)
462
{
463
    SWFContext *swf = s->priv_data;
464
    ByteIOContext *pb = &s->pb;
465
    int c = 0;
466
    int outSize = 0;
467
    int outSamples = 0;
468
    
469
    /* Flash Player limit */
470
    if ( swf->swf_frame_number == 16000 ) {
471
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
472
    }
473

    
474
    if ( swf->audio_type ) {
475
        /* Prescan audio data for this swf frame */
476
retry_swf_audio_packet:
477
        if ( ( swf->audio_size-outSize ) >= 4 ) {
478
            int mp3FrameSize = 0;
479
            int mp3SampleRate = 0;
480
            int mp3IsMono = 0;
481
            int mp3SamplesPerFrame = 0;
482
            
483
            /* copy out mp3 header from ring buffer */
484
            uint8_t header[4];
485
            for (c=0; c<4; c++) {
486
                header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
487
            }
488
            
489
            if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
490
                if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
491
                    outSize += mp3FrameSize;
492
                    outSamples += mp3SamplesPerFrame;
493
                    if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
494
                        goto retry_swf_audio_packet;
495
                    }
496
                }
497
            } else {
498
                /* invalid mp3 data, skip forward
499
                we need to do this since the Flash Player 
500
                does not like custom headers */
501
                swf->audio_in_pos ++;
502
                swf->audio_size --;
503
                swf->audio_in_pos %= AUDIO_FIFO_SIZE;
504
                goto retry_swf_audio_packet;
505
            }
506
        }
507
        
508
        /* audio stream is behind video stream, bail */
509
        if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
510
            return 0;
511
        }
512
    }
513

    
514
            if ( swf->video_type == CODEC_ID_FLV1 ) {
515
                if ( swf->video_frame_number == 0 ) {
516
                    /* create a new video object */
517
                    put_swf_tag(s, TAG_VIDEOSTREAM);
518
                    put_le16(pb, VIDEO_ID);
519
                    put_le16(pb, 15000 ); /* hard flash player limit */
520
                    put_le16(pb, enc->width);
521
                    put_le16(pb, enc->height);
522
                    put_byte(pb, 0);
523
                    put_byte(pb, SWF_VIDEO_CODEC_FLV1);
524
                    put_swf_end_tag(s);
525
                    
526
                    /* place the video object for the first time */
527
                    put_swf_tag(s, TAG_PLACEOBJECT2);
528
                    put_byte(pb, 0x36);
529
                    put_le16(pb, 1);
530
                    put_le16(pb, VIDEO_ID);
531
                    put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
532
                    put_le16(pb, swf->video_frame_number );
533
                    put_byte(pb, 'v');
534
                    put_byte(pb, 'i');
535
                    put_byte(pb, 'd');
536
                    put_byte(pb, 'e');
537
                    put_byte(pb, 'o');
538
                    put_byte(pb, 0x00);
539
                    put_swf_end_tag(s);
540
                } else {
541
                    /* mark the character for update */
542
                    put_swf_tag(s, TAG_PLACEOBJECT2);
543
                    put_byte(pb, 0x11);
544
                    put_le16(pb, 1);
545
                    put_le16(pb, swf->video_frame_number );
546
                    put_swf_end_tag(s);
547
                }
548
    
549
                    /* set video frame data */
550
                    put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
551
                    put_le16(pb, VIDEO_ID); 
552
                    put_le16(pb, swf->video_frame_number++ );
553
                    put_buffer(pb, buf, size);
554
                    put_swf_end_tag(s);
555
            } else if ( swf->video_type == CODEC_ID_MJPEG ) {
556
                if (swf->swf_frame_number > 0) {
557
                    /* remove the shape */
558
                    put_swf_tag(s, TAG_REMOVEOBJECT);
559
                    put_le16(pb, SHAPE_ID); /* shape ID */
560
                    put_le16(pb, 1); /* depth */
561
                    put_swf_end_tag(s);
562
                
563
                    /* free the bitmap */
564
                    put_swf_tag(s, TAG_FREECHARACTER);
565
                    put_le16(pb, BITMAP_ID);
566
                    put_swf_end_tag(s);
567
                }
568
        
569
                put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
570
        
571
                put_le16(pb, BITMAP_ID); /* ID of the image */
572
        
573
                /* a dummy jpeg header seems to be required */
574
                put_byte(pb, 0xff); 
575
                put_byte(pb, 0xd8);
576
                put_byte(pb, 0xff);
577
                put_byte(pb, 0xd9);
578
                /* write the jpeg image */
579
                put_buffer(pb, buf, size);
580
        
581
                put_swf_end_tag(s);
582
        
583
                /* draw the shape */
584
        
585
                put_swf_tag(s, TAG_PLACEOBJECT);
586
                put_le16(pb, SHAPE_ID); /* shape ID */
587
                put_le16(pb, 1); /* depth */
588
                put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
589
                put_swf_end_tag(s);
590
            } else {
591
                /* invalid codec */
592
            }
593
    
594
            swf->swf_frame_number ++;
595

    
596
    swf->video_samples += swf->samples_per_frame;
597

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

    
615
    /* output the frame */
616
    put_swf_tag(s, TAG_SHOWFRAME);
617
    put_swf_end_tag(s);
618
    
619
    put_flush_packet(&s->pb);
620
    
621
    return 0;
622
}
623

    
624
static int swf_write_audio(AVFormatContext *s, 
625
                           AVCodecContext *enc, const uint8_t *buf, int size)
626
{
627
    SWFContext *swf = s->priv_data;
628
    int c = 0;
629

    
630
    /* Flash Player limit */
631
    if ( swf->swf_frame_number == 16000 ) {
632
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
633
    }
634

    
635
    if (enc->codec_id == CODEC_ID_MP3 ) {
636
        for (c=0; c<size; c++) {
637
            swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
638
        }
639
        swf->audio_size += size;
640
        swf->audio_out_pos += size;
641
        swf->audio_out_pos %= AUDIO_FIFO_SIZE;
642
    }
643

    
644
    /* if audio only stream make sure we add swf frames */
645
    if ( swf->video_type == 0 ) {
646
        swf_write_video(s, enc, 0, 0);
647
    }
648

    
649
    return 0;
650
}
651

    
652
static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
653
{
654
    AVCodecContext *codec = &s->streams[pkt->stream_index]->codec;
655
    if (codec->codec_type == CODEC_TYPE_AUDIO)
656
        return swf_write_audio(s, codec, pkt->data, pkt->size);
657
    else
658
        return swf_write_video(s, codec, pkt->data, pkt->size);
659
}
660

    
661
static int swf_write_trailer(AVFormatContext *s)
662
{
663
    SWFContext *swf = s->priv_data;
664
    ByteIOContext *pb = &s->pb;
665
    AVCodecContext *enc, *video_enc;
666
    int file_size, i;
667

    
668
    video_enc = NULL;
669
    for(i=0;i<s->nb_streams;i++) {
670
        enc = &s->streams[i]->codec;
671
        if (enc->codec_type == CODEC_TYPE_VIDEO)
672
            video_enc = enc;
673
    }
674

    
675
    put_swf_tag(s, TAG_END);
676
    put_swf_end_tag(s);
677
    
678
    put_flush_packet(&s->pb);
679

    
680
    /* patch file size and number of frames if not streamed */
681
    if (!url_is_streamed(&s->pb) && video_enc) {
682
        file_size = url_ftell(pb);
683
        url_fseek(pb, 4, SEEK_SET);
684
        put_le32(pb, file_size);
685
        url_fseek(pb, swf->duration_pos, SEEK_SET);
686
        put_le16(pb, video_enc->frame_number);
687
    }
688
    
689
    av_free(swf->audio_fifo);
690

    
691
    return 0;
692
}
693
#endif //CONFIG_ENCODERS
694

    
695
/*********************************************/
696
/* Extract FLV encoded frame and MP3 from swf
697
   Note that the detection of the real frame
698
   is inaccurate at this point as it can be
699
   quite tricky to determine, you almost certainly 
700
   will get a bad audio/video sync */
701

    
702
static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
703
{
704
    int tag, len;
705
    
706
    if (url_feof(pb))
707
        return -1;
708

    
709
    tag = get_le16(pb);
710
    len = tag & 0x3f;
711
    tag = tag >> 6;
712
    if (len == 0x3f) {
713
        len = get_le32(pb);
714
    }
715
    *len_ptr = len;
716
    return tag;
717
}
718

    
719

    
720
static int swf_probe(AVProbeData *p)
721
{
722
    /* check file header */
723
    if (p->buf_size <= 16)
724
        return 0;
725
    if (p->buf[0] == 'F' && p->buf[1] == 'W' &&
726
        p->buf[2] == 'S')
727
        return AVPROBE_SCORE_MAX;
728
    else
729
        return 0;
730
}
731

    
732
static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
733
{
734
    SWFContext *swf = 0;
735
    ByteIOContext *pb = &s->pb;
736
    int nbits, len, frame_rate, tag, v;
737
    offset_t firstTagOff;
738
    AVStream *ast = 0;
739
    AVStream *vst = 0;
740

    
741
    swf = av_malloc(sizeof(SWFContext));
742
    if (!swf)
743
        return -1;
744
    s->priv_data = swf;
745

    
746
    if ((get_be32(pb) & 0xffffff00) != MKBETAG('F', 'W', 'S', 0))
747
        return AVERROR_IO;
748
    get_le32(pb);
749
    /* skip rectangle size */
750
    nbits = get_byte(pb) >> 3;
751
    len = (4 * nbits - 3 + 7) / 8;
752
    url_fskip(pb, len);
753
    frame_rate = get_le16(pb);
754
    get_le16(pb); /* frame count */
755
    
756
    /* The Flash Player converts 8.8 frame rates 
757
       to milliseconds internally. Do the same to get 
758
       a correct framerate */
759
    swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
760
    swf->samples_per_frame = 0;
761
    swf->ch_id = -1;
762

    
763
    firstTagOff = url_ftell(pb);
764
    for(;;) {
765
        tag = get_swf_tag(pb, &len);
766
        if (tag < 0) {
767
            if ( ast || vst ) {
768
                if ( vst && ast ) {
769
                    vst->codec.frame_rate = ast->codec.sample_rate / swf->samples_per_frame;
770
                    vst->codec.frame_rate_base = 1;
771
                }
772
                break;
773
            }
774
            av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
775
            return AVERROR_IO;
776
        }
777
        if ( tag == TAG_VIDEOSTREAM && !vst) {
778
            swf->ch_id = get_le16(pb);
779
            get_le16(pb);
780
            get_le16(pb);
781
            get_le16(pb);
782
            get_byte(pb);
783
            /* Check for FLV1 */
784
            if ( get_byte(pb) == SWF_VIDEO_CODEC_FLV1 ) {
785
                vst = av_new_stream(s, 0);
786
                av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
787
    
788
                vst->codec.codec_type = CODEC_TYPE_VIDEO;
789
                vst->codec.codec_id = CODEC_ID_FLV1;
790
                if ( swf->samples_per_frame ) {
791
                    vst->codec.frame_rate = 1000. / swf->ms_per_frame;
792
                    vst->codec.frame_rate_base = 1;
793
                }
794
            }
795
        } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
796
            /* streaming found */
797
            get_byte(pb);
798
            v = get_byte(pb);
799
            swf->samples_per_frame = get_le16(pb);
800
            if (len!=4)
801
                url_fskip(pb,len-4);
802
            /* if mp3 streaming found, OK */
803
            if ((v & 0x20) != 0) {
804
                if ( tag == TAG_STREAMHEAD2 ) {
805
                    get_le16(pb);
806
                }
807
                ast = av_new_stream(s, 1);
808
                av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
809
                if (!ast)
810
                    return -ENOMEM;
811

    
812
                if (v & 0x01)
813
                    ast->codec.channels = 2;
814
                else
815
                    ast->codec.channels = 1;
816

    
817
                switch((v>> 2) & 0x03) {
818
                case 1:
819
                    ast->codec.sample_rate = 11025;
820
                    break;
821
                case 2:
822
                    ast->codec.sample_rate = 22050;
823
                    break;
824
                case 3:
825
                    ast->codec.sample_rate = 44100;
826
                    break;
827
                default:
828
                    av_free(ast);
829
                    return AVERROR_IO;
830
                }
831
                ast->codec.codec_type = CODEC_TYPE_AUDIO;
832
                ast->codec.codec_id = CODEC_ID_MP3;
833
            }
834
        } else {
835
            url_fskip(pb, len);
836
        }
837
    }
838
    url_fseek(pb, firstTagOff, SEEK_SET);
839
    
840
    return 0;
841
}
842

    
843
static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
844
{
845
    SWFContext *swf = s->priv_data;
846
    ByteIOContext *pb = &s->pb;
847
    AVStream *st = 0;
848
    int tag, len, i, frame;
849
    
850
    for(;;) {
851
        tag = get_swf_tag(pb, &len);
852
        if (tag < 0) 
853
            return AVERROR_IO;
854
        if (tag == TAG_VIDEOFRAME) {
855
            for( i=0; i<s->nb_streams; i++ ) {
856
                st = s->streams[i];
857
                if (st->id == 0) {
858
                    if ( get_le16(pb) == swf->ch_id ) {
859
                        frame = get_le16(pb);
860
                        av_new_packet(pkt, len-4);
861
                        pkt->pts = frame * swf->ms_per_frame;
862
                        pkt->stream_index = st->index;
863
                        get_buffer(pb, pkt->data, pkt->size);
864
                        return pkt->size;
865
                    } else {
866
                        url_fskip(pb, len-2);
867
                        continue;
868
                    }
869
                }
870
            }    
871
            url_fskip(pb, len);
872
        } else if (tag == TAG_STREAMBLOCK) {
873
            for( i=0; i<s->nb_streams; i++ ) {
874
                st = s->streams[i];
875
                if (st->id == 1) {
876
                    av_new_packet(pkt, len);
877
                    pkt->stream_index = st->index;
878
                    get_buffer(pb, pkt->data, pkt->size);
879
                    return pkt->size;
880
                }
881
            }
882
            url_fskip(pb, len);
883
        } else {
884
            url_fskip(pb, len);
885
        }
886
    }
887
    return 0;
888
}
889

    
890
static int swf_read_close(AVFormatContext *s)
891
{
892
     return 0;
893
}
894

    
895
static AVInputFormat swf_iformat = {
896
    "swf",
897
    "Flash format",
898
    sizeof(SWFContext),
899
    swf_probe,
900
    swf_read_header,
901
    swf_read_packet,
902
    swf_read_close,
903
};
904

    
905
#ifdef CONFIG_ENCODERS
906
static AVOutputFormat swf_oformat = {
907
    "swf",
908
    "Flash format",
909
    "application/x-shockwave-flash",
910
    "swf",
911
    sizeof(SWFContext),
912
    CODEC_ID_MP3,
913
    CODEC_ID_FLV1,
914
    swf_write_header,
915
    swf_write_packet,
916
    swf_write_trailer,
917
};
918
#endif //CONFIG_ENCODERS
919

    
920
int swf_init(void)
921
{
922
    av_register_input_format(&swf_iformat);
923
#ifdef CONFIG_ENCODERS
924
    av_register_output_format(&swf_oformat);
925
#endif //CONFIG_ENCODERS
926
    return 0;
927
}