Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 649b918c

History | View | Annotate | Download (26.9 KB)

1 de6d9b64 Fabrice Bellard
/*
2
 * Flash Compatible Streaming Format
3 17269bdf Fabrice Bellard
 * Copyright (c) 2000 Fabrice Bellard.
4 747a0554 Tinic Uro
 * Copyright (c) 2003 Tinic Uro.
5 de6d9b64 Fabrice Bellard
 *
6 17269bdf Fabrice Bellard
 * 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 de6d9b64 Fabrice Bellard
 *
11 17269bdf Fabrice Bellard
 * This library is distributed in the hope that it will be useful,
12 de6d9b64 Fabrice Bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 17269bdf Fabrice Bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15 de6d9b64 Fabrice Bellard
 *
16 17269bdf Fabrice Bellard
 * 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 de6d9b64 Fabrice Bellard
 */
20
#include "avformat.h"
21 2de7795a Michael Niedermayer
#include "bitstream.h"
22 de6d9b64 Fabrice Bellard
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 747a0554 Tinic Uro
#define TAG_STREAMHEAD    45
34 de6d9b64 Fabrice Bellard
#define TAG_STREAMBLOCK   19
35
#define TAG_JPEG2         21
36 747a0554 Tinic Uro
#define TAG_PLACEOBJECT2  26
37
#define TAG_STREAMHEAD2   45
38
#define TAG_VIDEOSTREAM          60
39
#define TAG_VIDEOFRAME    61
40 de6d9b64 Fabrice Bellard
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 747a0554 Tinic Uro
#define SWF_VIDEO_CODEC_FLV1        0x02
49
50
#define AUDIO_FIFO_SIZE 65536
51
52 de6d9b64 Fabrice Bellard
/* character id used */
53
#define BITMAP_ID 0
54 747a0554 Tinic Uro
#define VIDEO_ID 0
55 de6d9b64 Fabrice Bellard
#define SHAPE_ID  1
56
57 14a68b89 Michael Niedermayer
#undef NDEBUG
58
#include <assert.h>
59 747a0554 Tinic Uro
60 de6d9b64 Fabrice Bellard
typedef struct {
61 747a0554 Tinic Uro
62 8be1c656 Fabrice Bellard
    offset_t duration_pos;
63
    offset_t tag_pos;
64 747a0554 Tinic Uro
    
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 de6d9b64 Fabrice Bellard
    int tag;
73 747a0554 Tinic Uro
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 de6d9b64 Fabrice Bellard
} SWFContext;
82
83 747a0554 Tinic Uro
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 764ef400 Mike Melanson
#ifdef CONFIG_ENCODERS
152 de6d9b64 Fabrice Bellard
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 8be1c656 Fabrice Bellard
    offset_t pos;
173 de6d9b64 Fabrice Bellard
    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 0c1a9eda Zdenek Kabelac
    uint8_t buf[256];
211 de6d9b64 Fabrice Bellard
    int nbits, mask;
212
213 117a5490 Alex Beregszaszi
    init_put_bits(&p, buf, sizeof(buf));
214 de6d9b64 Fabrice Bellard
    
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 17592475 Michael Niedermayer
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
231 de6d9b64 Fabrice Bellard
}
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 747a0554 Tinic Uro
/* put matrix */
263 de6d9b64 Fabrice Bellard
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 0c1a9eda Zdenek Kabelac
    uint8_t buf[256];
268 747a0554 Tinic Uro
    int nbits;
269 de6d9b64 Fabrice Bellard
270 117a5490 Alex Beregszaszi
    init_put_bits(&p, buf, sizeof(buf));
271 de6d9b64 Fabrice Bellard
    
272
    put_bits(&p, 1, 1); /* a, d present */
273 747a0554 Tinic Uro
    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 de6d9b64 Fabrice Bellard
    
280
    put_bits(&p, 1, 1); /* b, c present */
281 747a0554 Tinic Uro
    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 de6d9b64 Fabrice Bellard
295
    flush_put_bits(&p);
296 17592475 Michael Niedermayer
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
297 de6d9b64 Fabrice Bellard
}
298
299 747a0554 Tinic Uro
/* */
300 de6d9b64 Fabrice Bellard
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 0c1a9eda Zdenek Kabelac
    uint8_t buf1[256];
307 14bea432 Michael Niedermayer
    int i, width, height, rate, rate_base;
308 de6d9b64 Fabrice Bellard
309 1ea4f593 Fabrice Bellard
    swf = av_malloc(sizeof(SWFContext));
310 de6d9b64 Fabrice Bellard
    if (!swf)
311
        return -1;
312
    s->priv_data = swf;
313
314 747a0554 Tinic Uro
    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 de6d9b64 Fabrice Bellard
    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 747a0554 Tinic Uro
        else {
331
            if ( enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == CODEC_ID_MJPEG ) {
332
                video_enc = enc;
333
            } else {
334 bc874dae Michel Bardiaux
                av_log(enc, AV_LOG_ERROR, "SWF only supports FLV1 and MJPEG\n");
335 747a0554 Tinic Uro
                return -1;
336
            }
337
        }
338 de6d9b64 Fabrice Bellard
    }
339
340
    if (!video_enc) {
341
        /* currenty, cannot work correctly if audio only */
342 747a0554 Tinic Uro
        swf->video_type = 0;
343 de6d9b64 Fabrice Bellard
        width = 320;
344
        height = 200;
345 14bea432 Michael Niedermayer
        rate = 10;
346
        rate_base= 1;
347 de6d9b64 Fabrice Bellard
    } else {
348 747a0554 Tinic Uro
        swf->video_type = video_enc->codec_id;
349 de6d9b64 Fabrice Bellard
        width = video_enc->width;
350
        height = video_enc->height;
351
        rate = video_enc->frame_rate;
352 14bea432 Michael Niedermayer
        rate_base = video_enc->frame_rate_base;
353 de6d9b64 Fabrice Bellard
    }
354
355 747a0554 Tinic Uro
    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 de6d9b64 Fabrice Bellard
    put_tag(pb, "FWS");
364 747a0554 Tinic Uro
    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 de6d9b64 Fabrice Bellard
    put_le32(pb, DUMMY_FILE_SIZE); /* dummy size 
370
                                      (will be patched if not streamed) */ 
371
372 747a0554 Tinic Uro
    put_swf_rect(pb, 0, width * 20, 0, height * 20);
373 14bea432 Michael Niedermayer
    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
374 de6d9b64 Fabrice Bellard
    swf->duration_pos = url_ftell(pb);
375 14bea432 Michael Niedermayer
    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
376 de6d9b64 Fabrice Bellard
    
377
    /* define a shape with the jpeg inside */
378 747a0554 Tinic Uro
    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 de6d9b64 Fabrice Bellard
    
394 747a0554 Tinic Uro
        /* 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 de6d9b64 Fabrice Bellard
    
406 747a0554 Tinic Uro
        /* 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 de6d9b64 Fabrice Bellard
    
412 747a0554 Tinic Uro
        /* end of shape */
413
        put_bits(&p, 1, 0); /* not an edge */
414
        put_bits(&p, 5, 0);
415 de6d9b64 Fabrice Bellard
416 747a0554 Tinic Uro
        flush_put_bits(&p);
417
        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
418 de6d9b64 Fabrice Bellard
419 747a0554 Tinic Uro
        put_swf_end_tag(s);
420
    }
421 de6d9b64 Fabrice Bellard
    
422 747a0554 Tinic Uro
    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
423 de6d9b64 Fabrice Bellard
        int v;
424
425
        /* start sound */
426 747a0554 Tinic Uro
        put_swf_tag(s, TAG_STREAMHEAD2);
427 de6d9b64 Fabrice Bellard
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 747a0554 Tinic Uro
            av_free(swf->audio_fifo);
442 1ea4f593 Fabrice Bellard
            av_free(swf);
443 de6d9b64 Fabrice Bellard
            return -1;
444
        }
445 747a0554 Tinic Uro
        v |= 0x02; /* 16 bit playback */
446 de6d9b64 Fabrice Bellard
        if (audio_enc->channels == 2)
447 747a0554 Tinic Uro
            v |= 0x01; /* stereo playback */
448
        put_byte(&s->pb, v);
449 de6d9b64 Fabrice Bellard
        v |= 0x20; /* mp3 compressed */
450
        put_byte(&s->pb, v);
451 747a0554 Tinic Uro
        put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
452
        put_le16(&s->pb, 0);
453 de6d9b64 Fabrice Bellard
        
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 49057904 Fabrice Bellard
                           AVCodecContext *enc, const uint8_t *buf, int size)
463 de6d9b64 Fabrice Bellard
{
464 747a0554 Tinic Uro
    SWFContext *swf = s->priv_data;
465 de6d9b64 Fabrice Bellard
    ByteIOContext *pb = &s->pb;
466 747a0554 Tinic Uro
    int c = 0;
467
    int outSize = 0;
468
    int outSamples = 0;
469
    
470
    /* Flash Player limit */
471 d3e18ad0 Michael Niedermayer
    if ( swf->swf_frame_number == 16000 ) {
472 bc874dae Michel Bardiaux
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
473 de6d9b64 Fabrice Bellard
    }
474
475 747a0554 Tinic Uro
    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 de6d9b64 Fabrice Bellard
515 747a0554 Tinic Uro
            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 14a68b89 Michael Niedermayer
                    put_buffer(pb, buf, size);
555 747a0554 Tinic Uro
                    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 14a68b89 Michael Niedermayer
                put_buffer(pb, buf, size);
581 747a0554 Tinic Uro
        
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 de6d9b64 Fabrice Bellard
597 747a0554 Tinic Uro
    swf->video_samples += swf->samples_per_frame;
598 de6d9b64 Fabrice Bellard
599 747a0554 Tinic Uro
    /* 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 de6d9b64 Fabrice Bellard
    
609 747a0554 Tinic Uro
        /* 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 de6d9b64 Fabrice Bellard
    /* output the frame */
617
    put_swf_tag(s, TAG_SHOWFRAME);
618
    put_swf_end_tag(s);
619
    
620
    put_flush_packet(&s->pb);
621 747a0554 Tinic Uro
    
622 de6d9b64 Fabrice Bellard
    return 0;
623
}
624
625 747a0554 Tinic Uro
static int swf_write_audio(AVFormatContext *s, 
626
                           AVCodecContext *enc, const uint8_t *buf, int size)
627 de6d9b64 Fabrice Bellard
{
628 747a0554 Tinic Uro
    SWFContext *swf = s->priv_data;
629
    int c = 0;
630 de6d9b64 Fabrice Bellard
631 747a0554 Tinic Uro
    /* Flash Player limit */
632 d3e18ad0 Michael Niedermayer
    if ( swf->swf_frame_number == 16000 ) {
633 bc874dae Michel Bardiaux
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
634 747a0554 Tinic Uro
    }
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 de6d9b64 Fabrice Bellard
650
    return 0;
651
}
652
653 e928649b Michael Niedermayer
static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
654 de6d9b64 Fabrice Bellard
{
655 e928649b Michael Niedermayer
    AVCodecContext *codec = &s->streams[pkt->stream_index]->codec;
656 de6d9b64 Fabrice Bellard
    if (codec->codec_type == CODEC_TYPE_AUDIO)
657 e928649b Michael Niedermayer
        return swf_write_audio(s, codec, pkt->data, pkt->size);
658 de6d9b64 Fabrice Bellard
    else
659 e928649b Michael Niedermayer
        return swf_write_video(s, codec, pkt->data, pkt->size);
660 de6d9b64 Fabrice Bellard
}
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 747a0554 Tinic Uro
    
690
    av_free(swf->audio_fifo);
691
692 de6d9b64 Fabrice Bellard
    return 0;
693
}
694 764ef400 Mike Melanson
#endif //CONFIG_ENCODERS
695 de6d9b64 Fabrice Bellard
696 747a0554 Tinic Uro
/*********************************************/
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 de6d9b64 Fabrice Bellard
703
static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
704
{
705
    int tag, len;
706
    
707
    if (url_feof(pb))
708
        return -1;
709
710
    tag = get_le16(pb);
711
    len = tag & 0x3f;
712
    tag = tag >> 6;
713
    if (len == 0x3f) {
714
        len = get_le32(pb);
715
    }
716
    *len_ptr = len;
717
    return tag;
718
}
719
720 c9a65ca8 Fabrice Bellard
721
static int swf_probe(AVProbeData *p)
722
{
723
    /* check file header */
724
    if (p->buf_size <= 16)
725
        return 0;
726
    if (p->buf[0] == 'F' && p->buf[1] == 'W' &&
727 17269bdf Fabrice Bellard
        p->buf[2] == 'S')
728 c9a65ca8 Fabrice Bellard
        return AVPROBE_SCORE_MAX;
729
    else
730
        return 0;
731
}
732
733 de6d9b64 Fabrice Bellard
static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
734
{
735 747a0554 Tinic Uro
    SWFContext *swf = 0;
736 de6d9b64 Fabrice Bellard
    ByteIOContext *pb = &s->pb;
737
    int nbits, len, frame_rate, tag, v;
738 747a0554 Tinic Uro
    offset_t firstTagOff;
739
    AVStream *ast = 0;
740
    AVStream *vst = 0;
741
742
    swf = av_malloc(sizeof(SWFContext));
743
    if (!swf)
744
        return -1;
745
    s->priv_data = swf;
746 de6d9b64 Fabrice Bellard
747
    if ((get_be32(pb) & 0xffffff00) != MKBETAG('F', 'W', 'S', 0))
748 0bd586c5 Mike Melanson
        return AVERROR_IO;
749 de6d9b64 Fabrice Bellard
    get_le32(pb);
750
    /* skip rectangle size */
751
    nbits = get_byte(pb) >> 3;
752
    len = (4 * nbits - 3 + 7) / 8;
753
    url_fskip(pb, len);
754
    frame_rate = get_le16(pb);
755
    get_le16(pb); /* frame count */
756 747a0554 Tinic Uro
    
757
    /* The Flash Player converts 8.8 frame rates 
758
       to milliseconds internally. Do the same to get 
759
       a correct framerate */
760
    swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
761
    swf->samples_per_frame = 0;
762
    swf->ch_id = -1;
763
764
    firstTagOff = url_ftell(pb);
765 de6d9b64 Fabrice Bellard
    for(;;) {
766
        tag = get_swf_tag(pb, &len);
767
        if (tag < 0) {
768 747a0554 Tinic Uro
            if ( ast || vst ) {
769
                if ( vst && ast ) {
770
                    vst->codec.frame_rate = ast->codec.sample_rate / swf->samples_per_frame;
771
                    vst->codec.frame_rate_base = 1;
772
                }
773
                break;
774
            }
775 bc874dae Michel Bardiaux
            av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
776 0bd586c5 Mike Melanson
            return AVERROR_IO;
777 de6d9b64 Fabrice Bellard
        }
778 747a0554 Tinic Uro
        if ( tag == TAG_VIDEOSTREAM && !vst) {
779
            swf->ch_id = get_le16(pb);
780
            get_le16(pb);
781
            get_le16(pb);
782
            get_le16(pb);
783
            get_byte(pb);
784
            /* Check for FLV1 */
785
            if ( get_byte(pb) == SWF_VIDEO_CODEC_FLV1 ) {
786
                vst = av_new_stream(s, 0);
787 9ee91c2f Michael Niedermayer
                av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
788
    
789 747a0554 Tinic Uro
                vst->codec.codec_type = CODEC_TYPE_VIDEO;
790
                vst->codec.codec_id = CODEC_ID_FLV1;
791
                if ( swf->samples_per_frame ) {
792
                    vst->codec.frame_rate = 1000. / swf->ms_per_frame;
793
                    vst->codec.frame_rate_base = 1;
794
                }
795
            }
796
        } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
797 de6d9b64 Fabrice Bellard
            /* streaming found */
798
            get_byte(pb);
799
            v = get_byte(pb);
800 747a0554 Tinic Uro
            swf->samples_per_frame = get_le16(pb);
801 647b7762 Glyn Kennington
            if (len!=4)
802
                url_fskip(pb,len-4);
803 de6d9b64 Fabrice Bellard
            /* if mp3 streaming found, OK */
804
            if ((v & 0x20) != 0) {
805 747a0554 Tinic Uro
                if ( tag == TAG_STREAMHEAD2 ) {
806
                    get_le16(pb);
807
                }
808
                ast = av_new_stream(s, 1);
809 9ee91c2f Michael Niedermayer
                av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
810 747a0554 Tinic Uro
                if (!ast)
811 de6d9b64 Fabrice Bellard
                    return -ENOMEM;
812 1e491e29 Michael Niedermayer
813 de6d9b64 Fabrice Bellard
                if (v & 0x01)
814 747a0554 Tinic Uro
                    ast->codec.channels = 2;
815 de6d9b64 Fabrice Bellard
                else
816 747a0554 Tinic Uro
                    ast->codec.channels = 1;
817 de6d9b64 Fabrice Bellard
818
                switch((v>> 2) & 0x03) {
819
                case 1:
820 747a0554 Tinic Uro
                    ast->codec.sample_rate = 11025;
821 de6d9b64 Fabrice Bellard
                    break;
822
                case 2:
823 747a0554 Tinic Uro
                    ast->codec.sample_rate = 22050;
824 de6d9b64 Fabrice Bellard
                    break;
825
                case 3:
826 747a0554 Tinic Uro
                    ast->codec.sample_rate = 44100;
827 de6d9b64 Fabrice Bellard
                    break;
828
                default:
829 747a0554 Tinic Uro
                    av_free(ast);
830 0bd586c5 Mike Melanson
                    return AVERROR_IO;
831 de6d9b64 Fabrice Bellard
                }
832 747a0554 Tinic Uro
                ast->codec.codec_type = CODEC_TYPE_AUDIO;
833
                ast->codec.codec_id = CODEC_ID_MP3;
834 de6d9b64 Fabrice Bellard
            }
835
        } else {
836
            url_fskip(pb, len);
837
        }
838
    }
839 747a0554 Tinic Uro
    url_fseek(pb, firstTagOff, SEEK_SET);
840
    
841 de6d9b64 Fabrice Bellard
    return 0;
842
}
843
844
static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
845
{
846 747a0554 Tinic Uro
    SWFContext *swf = s->priv_data;
847 de6d9b64 Fabrice Bellard
    ByteIOContext *pb = &s->pb;
848 747a0554 Tinic Uro
    AVStream *st = 0;
849
    int tag, len, i, frame;
850 de6d9b64 Fabrice Bellard
    
851
    for(;;) {
852
        tag = get_swf_tag(pb, &len);
853
        if (tag < 0) 
854 0bd586c5 Mike Melanson
            return AVERROR_IO;
855 747a0554 Tinic Uro
        if (tag == TAG_VIDEOFRAME) {
856
            for( i=0; i<s->nb_streams; i++ ) {
857
                st = s->streams[i];
858
                if (st->id == 0) {
859
                    if ( get_le16(pb) == swf->ch_id ) {
860
                        frame = get_le16(pb);
861
                        av_new_packet(pkt, len-4);
862
                        pkt->pts = frame * swf->ms_per_frame;
863
                        pkt->stream_index = st->index;
864
                        get_buffer(pb, pkt->data, pkt->size);
865
                        return pkt->size;
866
                    } else {
867
                        url_fskip(pb, len-2);
868
                        continue;
869
                    }
870
                }
871
            }    
872
            url_fskip(pb, len);
873
        } else if (tag == TAG_STREAMBLOCK) {
874
            for( i=0; i<s->nb_streams; i++ ) {
875
                st = s->streams[i];
876
                if (st->id == 1) {
877
                    av_new_packet(pkt, len);
878
                    pkt->stream_index = st->index;
879
                    get_buffer(pb, pkt->data, pkt->size);
880
                    return pkt->size;
881
                }
882
            }
883
            url_fskip(pb, len);
884 de6d9b64 Fabrice Bellard
        } else {
885
            url_fskip(pb, len);
886
        }
887
    }
888
    return 0;
889
}
890
891
static int swf_read_close(AVFormatContext *s)
892
{
893
     return 0;
894
}
895
896 c9a65ca8 Fabrice Bellard
static AVInputFormat swf_iformat = {
897
    "swf",
898
    "Flash format",
899 747a0554 Tinic Uro
    sizeof(SWFContext),
900 c9a65ca8 Fabrice Bellard
    swf_probe,
901
    swf_read_header,
902
    swf_read_packet,
903
    swf_read_close,
904
};
905
906 764ef400 Mike Melanson
#ifdef CONFIG_ENCODERS
907 c9a65ca8 Fabrice Bellard
static AVOutputFormat swf_oformat = {
908 de6d9b64 Fabrice Bellard
    "swf",
909
    "Flash format",
910
    "application/x-shockwave-flash",
911
    "swf",
912 c9a65ca8 Fabrice Bellard
    sizeof(SWFContext),
913 747a0554 Tinic Uro
    CODEC_ID_MP3,
914
    CODEC_ID_FLV1,
915 de6d9b64 Fabrice Bellard
    swf_write_header,
916
    swf_write_packet,
917
    swf_write_trailer,
918
};
919 764ef400 Mike Melanson
#endif //CONFIG_ENCODERS
920 c9a65ca8 Fabrice Bellard
921
int swf_init(void)
922
{
923
    av_register_input_format(&swf_iformat);
924 764ef400 Mike Melanson
#ifdef CONFIG_ENCODERS
925 c9a65ca8 Fabrice Bellard
    av_register_output_format(&swf_oformat);
926 764ef400 Mike Melanson
#endif //CONFIG_ENCODERS
927 c9a65ca8 Fabrice Bellard
    return 0;
928
}