Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 20cd83e2

History | View | Annotate | Download (27.3 KB)

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

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

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

    
44
#define TAG_LONG         0x100
45

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

    
51
#define AUDIO_FIFO_SIZE 65536
52

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

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

    
61
typedef struct {
62

    
63
    offset_t duration_pos;
64
    offset_t tag_pos;
65

    
66
    int samples_per_frame;
67
    int sound_samples;
68
    int video_samples;
69
    int swf_frame_number;
70
    int video_frame_number;
71
    int ms_per_frame;
72
    int ch_id;
73
    int tag;
74

    
75
    uint8_t *audio_fifo;
76
    int audio_in_pos;
77
    int audio_out_pos;
78
    int audio_size;
79

    
80
    int video_type;
81
    int audio_type;
82
} SWFContext;
83

    
84
static const CodecTag swf_codec_tags[] = {
85
    {CODEC_ID_FLV1, 0x02},
86
    {CODEC_ID_VP6F, 0x04},
87
    {0, 0},
88
};
89

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

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

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

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

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

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

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

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

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

    
155
    return 1;
156
}
157

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
267
#define FRAC_BITS 16
268

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
428
        flush_put_bits(&p);
429
        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
430

    
431
        put_swf_end_tag(s);
432
    }
433

    
434
    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
435
        int v;
436

    
437
        /* start sound */
438
        put_swf_tag(s, TAG_STREAMHEAD2);
439

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

    
466
        put_swf_end_tag(s);
467
    }
468

    
469
    put_flush_packet(&s->pb);
470
    return 0;
471
}
472

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

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

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

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

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

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

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

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

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

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

    
583
                put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
584

    
585
                put_le16(pb, BITMAP_ID); /* ID of the image */
586

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

    
595
                put_swf_end_tag(s);
596

    
597
                /* draw the shape */
598

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

    
608
            swf->swf_frame_number ++;
609

    
610
    swf->video_samples += swf->samples_per_frame;
611

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

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

    
629
    /* output the frame */
630
    put_swf_tag(s, TAG_SHOWFRAME);
631
    put_swf_end_tag(s);
632

    
633
    put_flush_packet(&s->pb);
634

    
635
    return 0;
636
}
637

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

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

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

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

    
663
    return 0;
664
}
665

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

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

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

    
689
    put_swf_tag(s, TAG_END);
690
    put_swf_end_tag(s);
691

    
692
    put_flush_packet(&s->pb);
693

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

    
703
    av_free(swf->audio_fifo);
704

    
705
    return 0;
706
}
707
#endif //CONFIG_MUXERS
708

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

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

    
720
    if (url_feof(pb))
721
        return -1;
722

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

    
734

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

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

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

    
761
    tag = get_be32(pb) & 0xffffff00;
762

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

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

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

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

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

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

    
865
    return 0;
866
}
867

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

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

    
914
static int swf_read_close(AVFormatContext *s)
915
{
916
     return 0;
917
}
918

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