Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 5ce117c3

History | View | Annotate | Download (27.2 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
#include "avformat.h"
21
#include "bitstream.h"
22
#include "riff.h"    /* for CodecTag */
23

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

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

    
42
#define TAG_LONG         0x100
43

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

    
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 CodecTag swf_codec_tags[] = {
83
    {CODEC_ID_FLV1, 0x02},
84
    {CODEC_ID_VP6F, 0x04},
85
    {0, 0},
86
};
87

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

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

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

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

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

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

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

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

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

    
153
    return 1;
154
}
155

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
265
#define FRAC_BITS 16
266

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

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

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

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

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

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

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

    
314
    swf = av_malloc(sizeof(SWFContext));
315
    if (!swf)
316
        return -1;
317
    s->priv_data = swf;
318

    
319
    swf->ch_id = -1;
320
    swf->audio_in_pos = 0;
321
    swf->audio_out_pos = 0;
322
    swf->audio_size = 0;
323
    swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
324
    swf->sound_samples = 0;
325
    swf->video_samples = 0;
326
    swf->swf_frame_number = 0;
327
    swf->video_frame_number = 0;
328

    
329
    video_enc = NULL;
330
    audio_enc = NULL;
331
    for(i=0;i<s->nb_streams;i++) {
332
        enc = s->streams[i]->codec;
333
        if (enc->codec_type == CODEC_TYPE_AUDIO)
334
            audio_enc = enc;
335
        else {
336
            if ( enc->codec_id == CODEC_ID_VP6F ||
337
                 enc->codec_id == CODEC_ID_FLV1 ||
338
                 enc->codec_id == CODEC_ID_MJPEG ) {
339
                video_enc = enc;
340
            } else {
341
                av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
342
                return -1;
343
            }
344
        }
345
    }
346

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

    
362
    if (!audio_enc ) {
363
        swf->audio_type = 0;
364
        swf->samples_per_frame = ( 44100. * rate_base ) / rate;
365
    } else {
366
        swf->audio_type = audio_enc->codec_id;
367
        swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
368
    }
369

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

    
381
    put_swf_rect(pb, 0, width * 20, 0, height * 20);
382
    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
383
    swf->duration_pos = url_ftell(pb);
384
    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
385

    
386
    /* define a shape with the jpeg inside */
387
    if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
388
                       video_enc->codec_id == CODEC_ID_FLV1 )) {
389
    } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
390
        put_swf_tag(s, TAG_DEFINESHAPE);
391

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

    
404
        /* shape drawing */
405
        init_put_bits(&p, buf1, sizeof(buf1));
406
        put_bits(&p, 4, 1); /* one fill bit */
407
        put_bits(&p, 4, 0); /* zero line bit */
408

    
409
        put_bits(&p, 1, 0); /* not an edge */
410
        put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
411
        put_bits(&p, 5, 1); /* nbits */
412
        put_bits(&p, 1, 0); /* X */
413
        put_bits(&p, 1, 0); /* Y */
414
        put_bits(&p, 1, 1); /* set fill style 1 */
415

    
416
        /* draw the rectangle ! */
417
        put_swf_line_edge(&p, width, 0);
418
        put_swf_line_edge(&p, 0, height);
419
        put_swf_line_edge(&p, -width, 0);
420
        put_swf_line_edge(&p, 0, -height);
421

    
422
        /* end of shape */
423
        put_bits(&p, 1, 0); /* not an edge */
424
        put_bits(&p, 5, 0);
425

    
426
        flush_put_bits(&p);
427
        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
428

    
429
        put_swf_end_tag(s);
430
    }
431

    
432
    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
433
        int v;
434

    
435
        /* start sound */
436
        put_swf_tag(s, TAG_STREAMHEAD2);
437

    
438
        v = 0;
439
        switch(audio_enc->sample_rate) {
440
        case 11025:
441
            v |= 1 << 2;
442
            break;
443
        case 22050:
444
            v |= 2 << 2;
445
            break;
446
        case 44100:
447
            v |= 3 << 2;
448
            break;
449
        default:
450
            /* not supported */
451
            av_free(swf->audio_fifo);
452
            av_free(swf);
453
            return -1;
454
        }
455
        v |= 0x02; /* 16 bit playback */
456
        if (audio_enc->channels == 2)
457
            v |= 0x01; /* stereo playback */
458
        put_byte(&s->pb, v);
459
        v |= 0x20; /* mp3 compressed */
460
        put_byte(&s->pb, v);
461
        put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
462
        put_le16(&s->pb, 0);
463

    
464
        put_swf_end_tag(s);
465
    }
466

    
467
    put_flush_packet(&s->pb);
468
    return 0;
469
}
470

    
471
static int swf_write_video(AVFormatContext *s,
472
                           AVCodecContext *enc, const uint8_t *buf, int size)
473
{
474
    SWFContext *swf = s->priv_data;
475
    ByteIOContext *pb = &s->pb;
476
    int c = 0;
477
    int outSize = 0;
478
    int outSamples = 0;
479

    
480
    /* Flash Player limit */
481
    if ( swf->swf_frame_number == 16000 ) {
482
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
483
    }
484

    
485
    if ( swf->audio_type ) {
486
        /* Prescan audio data for this swf frame */
487
retry_swf_audio_packet:
488
        if ( ( swf->audio_size-outSize ) >= 4 ) {
489
            int mp3FrameSize = 0;
490
            int mp3SampleRate = 0;
491
            int mp3IsMono = 0;
492
            int mp3SamplesPerFrame = 0;
493

    
494
            /* copy out mp3 header from ring buffer */
495
            uint8_t header[4];
496
            for (c=0; c<4; c++) {
497
                header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
498
            }
499

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

    
519
        /* audio stream is behind video stream, bail */
520
        if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
521
            return 0;
522
        }
523
    }
524

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

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

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

    
575
                    /* free the bitmap */
576
                    put_swf_tag(s, TAG_FREECHARACTER);
577
                    put_le16(pb, BITMAP_ID);
578
                    put_swf_end_tag(s);
579
                }
580

    
581
                put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
582

    
583
                put_le16(pb, BITMAP_ID); /* ID of the image */
584

    
585
                /* a dummy jpeg header seems to be required */
586
                put_byte(pb, 0xff);
587
                put_byte(pb, 0xd8);
588
                put_byte(pb, 0xff);
589
                put_byte(pb, 0xd9);
590
                /* write the jpeg image */
591
                put_buffer(pb, buf, size);
592

    
593
                put_swf_end_tag(s);
594

    
595
                /* draw the shape */
596

    
597
                put_swf_tag(s, TAG_PLACEOBJECT);
598
                put_le16(pb, SHAPE_ID); /* shape ID */
599
                put_le16(pb, 1); /* depth */
600
                put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
601
                put_swf_end_tag(s);
602
            } else {
603
                /* invalid codec */
604
            }
605

    
606
            swf->swf_frame_number ++;
607

    
608
    swf->video_samples += swf->samples_per_frame;
609

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

    
620
        /* update FIFO */
621
        swf->sound_samples += outSamples;
622
        swf->audio_in_pos += outSize;
623
        swf->audio_size -= outSize;
624
        swf->audio_in_pos %= AUDIO_FIFO_SIZE;
625
    }
626

    
627
    /* output the frame */
628
    put_swf_tag(s, TAG_SHOWFRAME);
629
    put_swf_end_tag(s);
630

    
631
    put_flush_packet(&s->pb);
632

    
633
    return 0;
634
}
635

    
636
static int swf_write_audio(AVFormatContext *s,
637
                           AVCodecContext *enc, const uint8_t *buf, int size)
638
{
639
    SWFContext *swf = s->priv_data;
640
    int c = 0;
641

    
642
    /* Flash Player limit */
643
    if ( swf->swf_frame_number == 16000 ) {
644
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
645
    }
646

    
647
    if (enc->codec_id == CODEC_ID_MP3 ) {
648
        for (c=0; c<size; c++) {
649
            swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
650
        }
651
        swf->audio_size += size;
652
        swf->audio_out_pos += size;
653
        swf->audio_out_pos %= AUDIO_FIFO_SIZE;
654
    }
655

    
656
    /* if audio only stream make sure we add swf frames */
657
    if ( swf->video_type == 0 ) {
658
        swf_write_video(s, enc, 0, 0);
659
    }
660

    
661
    return 0;
662
}
663

    
664
static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
665
{
666
    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
667
    if (codec->codec_type == CODEC_TYPE_AUDIO)
668
        return swf_write_audio(s, codec, pkt->data, pkt->size);
669
    else
670
        return swf_write_video(s, codec, pkt->data, pkt->size);
671
}
672

    
673
static int swf_write_trailer(AVFormatContext *s)
674
{
675
    SWFContext *swf = s->priv_data;
676
    ByteIOContext *pb = &s->pb;
677
    AVCodecContext *enc, *video_enc;
678
    int file_size, i;
679

    
680
    video_enc = NULL;
681
    for(i=0;i<s->nb_streams;i++) {
682
        enc = s->streams[i]->codec;
683
        if (enc->codec_type == CODEC_TYPE_VIDEO)
684
            video_enc = enc;
685
    }
686

    
687
    put_swf_tag(s, TAG_END);
688
    put_swf_end_tag(s);
689

    
690
    put_flush_packet(&s->pb);
691

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

    
701
    av_free(swf->audio_fifo);
702

    
703
    return 0;
704
}
705
#endif //CONFIG_MUXERS
706

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

    
714
static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
715
{
716
    int tag, len;
717

    
718
    if (url_feof(pb))
719
        return -1;
720

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

    
732

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

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

    
754
    swf = av_malloc(sizeof(SWFContext));
755
    if (!swf)
756
        return -1;
757
    s->priv_data = swf;
758

    
759
    tag = get_be32(pb) & 0xffffff00;
760

    
761
    if (tag == MKBETAG('C', 'W', 'S', 0))
762
    {
763
        av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
764
        return AVERROR_IO;
765
    }
766
    if (tag != MKBETAG('F', 'W', 'S', 0))
767
        return AVERROR_IO;
768
    get_le32(pb);
769
    /* skip rectangle size */
770
    nbits = get_byte(pb) >> 3;
771
    len = (4 * nbits - 3 + 7) / 8;
772
    url_fskip(pb, len);
773
    frame_rate = get_le16(pb);
774
    get_le16(pb); /* frame count */
775

    
776
    /* The Flash Player converts 8.8 frame rates
777
       to milliseconds internally. Do the same to get
778
       a correct framerate */
779
    swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
780
    swf->samples_per_frame = 0;
781
    swf->ch_id = -1;
782

    
783
    firstTagOff = url_ftell(pb);
784
    for(;;) {
785
        tag = get_swf_tag(pb, &len);
786
        if (tag < 0) {
787
            if ( ast || vst ) {
788
                if ( vst && ast ) {
789
                    vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;
790
                    vst->codec->time_base.num = 1;
791
                }
792
                break;
793
            }
794
            av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
795
            return AVERROR_IO;
796
        }
797
        if ( tag == TAG_VIDEOSTREAM && !vst) {
798
            int codec_id;
799
            swf->ch_id = get_le16(pb);
800
            get_le16(pb);
801
            get_le16(pb);
802
            get_le16(pb);
803
            get_byte(pb);
804
            /* Check for FLV1 */
805
            codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
806
            if ( codec_id ) {
807
                vst = av_new_stream(s, 0);
808
                av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
809

    
810
                vst->codec->codec_type = CODEC_TYPE_VIDEO;
811
                vst->codec->codec_id = codec_id;
812
                if ( swf->samples_per_frame ) {
813
                    vst->codec->time_base.den = 1000. / swf->ms_per_frame;
814
                    vst->codec->time_base.num = 1;
815
                }
816
            }
817
        } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
818
            /* streaming found */
819
            get_byte(pb);
820
            v = get_byte(pb);
821
            swf->samples_per_frame = get_le16(pb);
822
            if (len!=4)
823
                url_fskip(pb,len-4);
824
            /* if mp3 streaming found, OK */
825
            if ((v & 0x20) != 0) {
826
                if ( tag == TAG_STREAMHEAD2 ) {
827
                    get_le16(pb);
828
                }
829
                ast = av_new_stream(s, 1);
830
                av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
831
                if (!ast)
832
                    return -ENOMEM;
833

    
834
                if (v & 0x01)
835
                    ast->codec->channels = 2;
836
                else
837
                    ast->codec->channels = 1;
838

    
839
                switch((v>> 2) & 0x03) {
840
                case 1:
841
                    ast->codec->sample_rate = 11025;
842
                    break;
843
                case 2:
844
                    ast->codec->sample_rate = 22050;
845
                    break;
846
                case 3:
847
                    ast->codec->sample_rate = 44100;
848
                    break;
849
                default:
850
                    av_free(ast);
851
                    return AVERROR_IO;
852
                }
853
                ast->codec->codec_type = CODEC_TYPE_AUDIO;
854
                ast->codec->codec_id = CODEC_ID_MP3;
855
            }
856
        } else {
857
            url_fskip(pb, len);
858
        }
859
    }
860
    url_fseek(pb, firstTagOff, SEEK_SET);
861

    
862
    return 0;
863
}
864

    
865
static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
866
{
867
    SWFContext *swf = s->priv_data;
868
    ByteIOContext *pb = &s->pb;
869
    AVStream *st = 0;
870
    int tag, len, i, frame;
871

    
872
    for(;;) {
873
        tag = get_swf_tag(pb, &len);
874
        if (tag < 0)
875
            return AVERROR_IO;
876
        if (tag == TAG_VIDEOFRAME) {
877
            for( i=0; i<s->nb_streams; i++ ) {
878
                st = s->streams[i];
879
                if (st->id == 0) {
880
                    if ( get_le16(pb) == swf->ch_id ) {
881
                        frame = get_le16(pb);
882
                        av_get_packet(pb, pkt, len-4);
883
                        pkt->pts = frame * swf->ms_per_frame;
884
                        pkt->stream_index = st->index;
885
                        return pkt->size;
886
                    } else {
887
                        url_fskip(pb, len-2);
888
                        continue;
889
                    }
890
                }
891
            }
892
            url_fskip(pb, len);
893
        } else if (tag == TAG_STREAMBLOCK) {
894
            for( i=0; i<s->nb_streams; i++ ) {
895
                st = s->streams[i];
896
                if (st->id == 1) {
897
                    av_get_packet(pb, pkt, len);
898
                    pkt->stream_index = st->index;
899
                    return pkt->size;
900
                }
901
            }
902
            url_fskip(pb, len);
903
        } else {
904
            url_fskip(pb, len);
905
        }
906
    }
907
    return 0;
908
}
909

    
910
static int swf_read_close(AVFormatContext *s)
911
{
912
     return 0;
913
}
914

    
915
#ifdef CONFIG_SWF_DEMUXER
916
AVInputFormat swf_demuxer = {
917
    "swf",
918
    "Flash format",
919
    sizeof(SWFContext),
920
    swf_probe,
921
    swf_read_header,
922
    swf_read_packet,
923
    swf_read_close,
924
};
925
#endif
926
#ifdef CONFIG_SWF_MUXER
927
AVOutputFormat swf_muxer = {
928
    "swf",
929
    "Flash format",
930
    "application/x-shockwave-flash",
931
    "swf",
932
    sizeof(SWFContext),
933
    CODEC_ID_MP3,
934
    CODEC_ID_FLV1,
935
    swf_write_header,
936
    swf_write_packet,
937
    swf_write_trailer,
938
};
939
#endif