Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 01f4895c

History | View | Annotate | Download (27.1 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    18
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->time_base.den;
352
        rate_base = video_enc->time_base.num;
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
//    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
717
    *len_ptr = len;
718
    return tag;
719
}
720

    
721

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

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

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

    
748
    tag = get_be32(pb) & 0xffffff00;
749

    
750
    if (tag == MKBETAG('C', 'W', 'S', 0))
751
    {
752
        av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
753
        return AVERROR_IO;
754
    }
755
    if (tag != MKBETAG('F', 'W', 'S', 0))
756
        return AVERROR_IO;
757
    get_le32(pb);
758
    /* skip rectangle size */
759
    nbits = get_byte(pb) >> 3;
760
    len = (4 * nbits - 3 + 7) / 8;
761
    url_fskip(pb, len);
762
    frame_rate = get_le16(pb);
763
    get_le16(pb); /* frame count */
764
    
765
    /* The Flash Player converts 8.8 frame rates 
766
       to milliseconds internally. Do the same to get 
767
       a correct framerate */
768
    swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
769
    swf->samples_per_frame = 0;
770
    swf->ch_id = -1;
771

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

    
821
                if (v & 0x01)
822
                    ast->codec->channels = 2;
823
                else
824
                    ast->codec->channels = 1;
825

    
826
                switch((v>> 2) & 0x03) {
827
                case 1:
828
                    ast->codec->sample_rate = 11025;
829
                    break;
830
                case 2:
831
                    ast->codec->sample_rate = 22050;
832
                    break;
833
                case 3:
834
                    ast->codec->sample_rate = 44100;
835
                    break;
836
                default:
837
                    av_free(ast);
838
                    return AVERROR_IO;
839
                }
840
                ast->codec->codec_type = CODEC_TYPE_AUDIO;
841
                ast->codec->codec_id = CODEC_ID_MP3;
842
            }
843
        } else {
844
            url_fskip(pb, len);
845
        }
846
    }
847
    url_fseek(pb, firstTagOff, SEEK_SET);
848
    
849
    return 0;
850
}
851

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

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

    
902
static AVInputFormat swf_iformat = {
903
    "swf",
904
    "Flash format",
905
    sizeof(SWFContext),
906
    swf_probe,
907
    swf_read_header,
908
    swf_read_packet,
909
    swf_read_close,
910
};
911

    
912
#ifdef CONFIG_ENCODERS
913
static AVOutputFormat swf_oformat = {
914
    "swf",
915
    "Flash format",
916
    "application/x-shockwave-flash",
917
    "swf",
918
    sizeof(SWFContext),
919
    CODEC_ID_MP3,
920
    CODEC_ID_FLV1,
921
    swf_write_header,
922
    swf_write_packet,
923
    swf_write_trailer,
924
};
925
#endif //CONFIG_ENCODERS
926

    
927
int swf_init(void)
928
{
929
    av_register_input_format(&swf_iformat);
930
#ifdef CONFIG_ENCODERS
931
    av_register_output_format(&swf_oformat);
932
#endif //CONFIG_ENCODERS
933
    return 0;
934
}