Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 27d5f18f

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
22
/* should have a generic way to indicate probable size */
23
#define DUMMY_FILE_SIZE   (100 * 1024 * 1024)
24
#define DUMMY_DURATION    600 /* in seconds */
25
26
#define TAG_END           0
27
#define TAG_SHOWFRAME     1
28
#define TAG_DEFINESHAPE   2
29
#define TAG_FREECHARACTER 3
30
#define TAG_PLACEOBJECT   4
31
#define TAG_REMOVEOBJECT  5
32 747a0554 Tinic Uro
#define TAG_STREAMHEAD    45
33 de6d9b64 Fabrice Bellard
#define TAG_STREAMBLOCK   19
34
#define TAG_JPEG2         21
35 747a0554 Tinic Uro
#define TAG_PLACEOBJECT2  26
36
#define TAG_STREAMHEAD2   45
37
#define TAG_VIDEOSTREAM          60
38
#define TAG_VIDEOFRAME    61
39 de6d9b64 Fabrice Bellard
40
#define TAG_LONG         0x100
41
42
/* flags for shape definition */
43
#define FLAG_MOVETO      0x01
44
#define FLAG_SETFILL0    0x02
45
#define FLAG_SETFILL1    0x04
46
47 747a0554 Tinic Uro
#define SWF_VIDEO_CODEC_FLV1        0x02
48
49
#define AUDIO_FIFO_SIZE 65536
50
51 de6d9b64 Fabrice Bellard
/* character id used */
52
#define BITMAP_ID 0
53 747a0554 Tinic Uro
#define VIDEO_ID 0
54 de6d9b64 Fabrice Bellard
#define SHAPE_ID  1
55
56 14a68b89 Michael Niedermayer
#undef NDEBUG
57
#include <assert.h>
58 747a0554 Tinic Uro
59 de6d9b64 Fabrice Bellard
typedef struct {
60 747a0554 Tinic Uro
61 8be1c656 Fabrice Bellard
    offset_t duration_pos;
62
    offset_t tag_pos;
63 747a0554 Tinic Uro
    
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 de6d9b64 Fabrice Bellard
    int tag;
72 747a0554 Tinic Uro
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 de6d9b64 Fabrice Bellard
} SWFContext;
81
82 747a0554 Tinic Uro
static const int sSampleRates[3][4] = {
83
    {44100, 48000, 32000, 0},
84
    {22050, 24000, 16000, 0},
85
    {11025, 12000,  8000, 0},
86
};
87
88
static const int sBitRates[2][3][15] = {
89
    {   {  0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
90
        {  0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
91
        {  0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
92
    },
93
    {   {  0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
94
        {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
95
        {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
96
    },
97
};
98
99
static const int sSamplesPerFrame[3][3] =
100
{
101
    {  384,     1152,    1152 },
102
    {  384,     1152,     576 },
103
    {  384,     1152,     576 }
104
};
105
106
static const int sBitsPerSlot[3] = {
107
    32,
108
    8,
109
    8
110
};
111
112
static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
113
{
114
    uint8_t *dataTmp = (uint8_t *)data;
115
    uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
116
    int layerID = 3 - ((header >> 17) & 0x03);
117
    int bitRateID = ((header >> 12) & 0x0f);
118
    int sampleRateID = ((header >> 10) & 0x03);
119
    int bitRate = 0;
120
    int bitsPerSlot = sBitsPerSlot[layerID];
121
    int isPadded = ((header >> 9) & 0x01);
122
    
123
    if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
124
        return 0;
125
    }
126
127
    *isMono = ((header >>  6) & 0x03) == 0x03;
128
129
    if ( (header >> 19 ) & 0x01 ) {
130
        *sampleRate = sSampleRates[0][sampleRateID];
131
        bitRate = sBitRates[0][layerID][bitRateID] * 1000;
132
        *samplesPerFrame = sSamplesPerFrame[0][layerID];
133
    } else {
134
        if ( (header >> 20) & 0x01 ) {
135
            *sampleRate = sSampleRates[1][sampleRateID];
136
            bitRate = sBitRates[1][layerID][bitRateID] * 1000;
137
            *samplesPerFrame = sSamplesPerFrame[1][layerID];
138
        } else {
139
            *sampleRate = sSampleRates[2][sampleRateID];
140
            bitRate = sBitRates[1][layerID][bitRateID] * 1000;
141
            *samplesPerFrame = sSamplesPerFrame[2][layerID];
142
        }
143
    }
144
145
    *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
146
147
    return 1;
148
}
149
150 764ef400 Mike Melanson
#ifdef CONFIG_ENCODERS
151 de6d9b64 Fabrice Bellard
static void put_swf_tag(AVFormatContext *s, int tag)
152
{
153
    SWFContext *swf = s->priv_data;
154
    ByteIOContext *pb = &s->pb;
155
156
    swf->tag_pos = url_ftell(pb);
157
    swf->tag = tag;
158
    /* reserve some room for the tag */
159
    if (tag & TAG_LONG) {
160
        put_le16(pb, 0);
161
        put_le32(pb, 0);
162
    } else {
163
        put_le16(pb, 0);
164
    }
165
}
166
167
static void put_swf_end_tag(AVFormatContext *s)
168
{
169
    SWFContext *swf = s->priv_data;
170
    ByteIOContext *pb = &s->pb;
171 8be1c656 Fabrice Bellard
    offset_t pos;
172 de6d9b64 Fabrice Bellard
    int tag_len, tag;
173
174
    pos = url_ftell(pb);
175
    tag_len = pos - swf->tag_pos - 2;
176
    tag = swf->tag;
177
    url_fseek(pb, swf->tag_pos, SEEK_SET);
178
    if (tag & TAG_LONG) {
179
        tag &= ~TAG_LONG;
180
        put_le16(pb, (tag << 6) | 0x3f);
181
        put_le32(pb, tag_len - 4);
182
    } else {
183
        assert(tag_len < 0x3f);
184
        put_le16(pb, (tag << 6) | tag_len);
185
    }
186
    url_fseek(pb, pos, SEEK_SET);
187
}
188
189
static inline void max_nbits(int *nbits_ptr, int val)
190
{
191
    int n;
192
193
    if (val == 0)
194
        return;
195
    val = abs(val);
196
    n = 1;
197
    while (val != 0) {
198
        n++;
199
        val >>= 1;
200
    }
201
    if (n > *nbits_ptr)
202
        *nbits_ptr = n;
203
}
204
205
static void put_swf_rect(ByteIOContext *pb, 
206
                         int xmin, int xmax, int ymin, int ymax)
207
{
208
    PutBitContext p;
209 0c1a9eda Zdenek Kabelac
    uint8_t buf[256];
210 de6d9b64 Fabrice Bellard
    int nbits, mask;
211
212 117a5490 Alex Beregszaszi
    init_put_bits(&p, buf, sizeof(buf));
213 de6d9b64 Fabrice Bellard
    
214
    nbits = 0;
215
    max_nbits(&nbits, xmin);
216
    max_nbits(&nbits, xmax);
217
    max_nbits(&nbits, ymin);
218
    max_nbits(&nbits, ymax);
219
    mask = (1 << nbits) - 1;
220
221
    /* rectangle info */
222
    put_bits(&p, 5, nbits);
223
    put_bits(&p, nbits, xmin & mask);
224
    put_bits(&p, nbits, xmax & mask);
225
    put_bits(&p, nbits, ymin & mask);
226
    put_bits(&p, nbits, ymax & mask);
227
    
228
    flush_put_bits(&p);
229 17592475 Michael Niedermayer
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
230 de6d9b64 Fabrice Bellard
}
231
232
static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
233
{
234
    int nbits, mask;
235
236
    put_bits(pb, 1, 1); /* edge */
237
    put_bits(pb, 1, 1); /* line select */
238
    nbits = 2;
239
    max_nbits(&nbits, dx);
240
    max_nbits(&nbits, dy);
241
242
    mask = (1 << nbits) - 1;
243
    put_bits(pb, 4, nbits - 2); /* 16 bits precision */
244
    if (dx == 0) {
245
      put_bits(pb, 1, 0); 
246
      put_bits(pb, 1, 1); 
247
      put_bits(pb, nbits, dy & mask);
248
    } else if (dy == 0) {
249
      put_bits(pb, 1, 0); 
250
      put_bits(pb, 1, 0); 
251
      put_bits(pb, nbits, dx & mask);
252
    } else {
253
      put_bits(pb, 1, 1); 
254
      put_bits(pb, nbits, dx & mask);
255
      put_bits(pb, nbits, dy & mask);
256
    }
257
}
258
259
#define FRAC_BITS 16
260
261 747a0554 Tinic Uro
/* put matrix */
262 de6d9b64 Fabrice Bellard
static void put_swf_matrix(ByteIOContext *pb,
263
                           int a, int b, int c, int d, int tx, int ty)
264
{
265
    PutBitContext p;
266 0c1a9eda Zdenek Kabelac
    uint8_t buf[256];
267 747a0554 Tinic Uro
    int nbits;
268 de6d9b64 Fabrice Bellard
269 117a5490 Alex Beregszaszi
    init_put_bits(&p, buf, sizeof(buf));
270 de6d9b64 Fabrice Bellard
    
271
    put_bits(&p, 1, 1); /* a, d present */
272 747a0554 Tinic Uro
    nbits = 1;
273
    max_nbits(&nbits, a);
274
    max_nbits(&nbits, d);
275
    put_bits(&p, 5, nbits); /* nb bits */
276
    put_bits(&p, nbits, a);
277
    put_bits(&p, nbits, d);
278 de6d9b64 Fabrice Bellard
    
279
    put_bits(&p, 1, 1); /* b, c present */
280 747a0554 Tinic Uro
    nbits = 1;
281
    max_nbits(&nbits, c);
282
    max_nbits(&nbits, b);
283
    put_bits(&p, 5, nbits); /* nb bits */
284
    put_bits(&p, nbits, c);
285
    put_bits(&p, nbits, b);
286
287
    nbits = 1;
288
    max_nbits(&nbits, tx);
289
    max_nbits(&nbits, ty);
290
    put_bits(&p, 5, nbits); /* nb bits */
291
    put_bits(&p, nbits, tx);
292
    put_bits(&p, nbits, ty);
293 de6d9b64 Fabrice Bellard
294
    flush_put_bits(&p);
295 17592475 Michael Niedermayer
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
296 de6d9b64 Fabrice Bellard
}
297
298 747a0554 Tinic Uro
/* */
299 de6d9b64 Fabrice Bellard
static int swf_write_header(AVFormatContext *s)
300
{
301
    SWFContext *swf;
302
    ByteIOContext *pb = &s->pb;
303
    AVCodecContext *enc, *audio_enc, *video_enc;
304
    PutBitContext p;
305 0c1a9eda Zdenek Kabelac
    uint8_t buf1[256];
306 14bea432 Michael Niedermayer
    int i, width, height, rate, rate_base;
307 de6d9b64 Fabrice Bellard
308 1ea4f593 Fabrice Bellard
    swf = av_malloc(sizeof(SWFContext));
309 de6d9b64 Fabrice Bellard
    if (!swf)
310
        return -1;
311
    s->priv_data = swf;
312
313 747a0554 Tinic Uro
    swf->ch_id = -1;
314
    swf->audio_in_pos = 0;
315
    swf->audio_out_pos = 0;
316
    swf->audio_size = 0;
317
    swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
318
    swf->sound_samples = 0;
319
    swf->video_samples = 0;
320
    swf->swf_frame_number = 0;
321
    swf->video_frame_number = 0;
322
323 de6d9b64 Fabrice Bellard
    video_enc = NULL;
324
    audio_enc = NULL;
325
    for(i=0;i<s->nb_streams;i++) {
326
        enc = &s->streams[i]->codec;
327
        if (enc->codec_type == CODEC_TYPE_AUDIO)
328
            audio_enc = enc;
329 747a0554 Tinic Uro
        else {
330
            if ( enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == CODEC_ID_MJPEG ) {
331
                video_enc = enc;
332
            } else {
333 bc874dae Michel Bardiaux
                av_log(enc, AV_LOG_ERROR, "SWF only supports FLV1 and MJPEG\n");
334 747a0554 Tinic Uro
                return -1;
335
            }
336
        }
337 de6d9b64 Fabrice Bellard
    }
338
339
    if (!video_enc) {
340
        /* currenty, cannot work correctly if audio only */
341 747a0554 Tinic Uro
        swf->video_type = 0;
342 de6d9b64 Fabrice Bellard
        width = 320;
343
        height = 200;
344 14bea432 Michael Niedermayer
        rate = 10;
345
        rate_base= 1;
346 de6d9b64 Fabrice Bellard
    } else {
347 747a0554 Tinic Uro
        swf->video_type = video_enc->codec_id;
348 de6d9b64 Fabrice Bellard
        width = video_enc->width;
349
        height = video_enc->height;
350
        rate = video_enc->frame_rate;
351 14bea432 Michael Niedermayer
        rate_base = video_enc->frame_rate_base;
352 de6d9b64 Fabrice Bellard
    }
353
354 747a0554 Tinic Uro
    if (!audio_enc ) {
355
        swf->audio_type = 0;
356
        swf->samples_per_frame = ( 44100. * rate_base ) / rate;
357
    } else {
358
        swf->audio_type = audio_enc->codec_id;
359
        swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
360
    }
361
362 de6d9b64 Fabrice Bellard
    put_tag(pb, "FWS");
363 747a0554 Tinic Uro
    if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
364
        put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
365
    } else {
366
        put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
367
    }
368 de6d9b64 Fabrice Bellard
    put_le32(pb, DUMMY_FILE_SIZE); /* dummy size 
369
                                      (will be patched if not streamed) */ 
370
371 747a0554 Tinic Uro
    put_swf_rect(pb, 0, width * 20, 0, height * 20);
372 14bea432 Michael Niedermayer
    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
373 de6d9b64 Fabrice Bellard
    swf->duration_pos = url_ftell(pb);
374 14bea432 Michael Niedermayer
    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
375 de6d9b64 Fabrice Bellard
    
376
    /* define a shape with the jpeg inside */
377 747a0554 Tinic Uro
    if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
378
    } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
379
        put_swf_tag(s, TAG_DEFINESHAPE);
380
381
        put_le16(pb, SHAPE_ID); /* ID of shape */
382
        /* bounding rectangle */
383
        put_swf_rect(pb, 0, width, 0, height);
384
        /* style info */
385
        put_byte(pb, 1); /* one fill style */
386
        put_byte(pb, 0x41); /* clipped bitmap fill */
387
        put_le16(pb, BITMAP_ID); /* bitmap ID */
388
        /* position of the bitmap */
389
        put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0, 
390
                        0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
391
        put_byte(pb, 0); /* no line style */
392 de6d9b64 Fabrice Bellard
    
393 747a0554 Tinic Uro
        /* shape drawing */
394
        init_put_bits(&p, buf1, sizeof(buf1));
395
        put_bits(&p, 4, 1); /* one fill bit */
396
        put_bits(&p, 4, 0); /* zero line bit */
397
     
398
        put_bits(&p, 1, 0); /* not an edge */
399
        put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
400
        put_bits(&p, 5, 1); /* nbits */
401
        put_bits(&p, 1, 0); /* X */
402
        put_bits(&p, 1, 0); /* Y */
403
        put_bits(&p, 1, 1); /* set fill style 1 */
404 de6d9b64 Fabrice Bellard
    
405 747a0554 Tinic Uro
        /* draw the rectangle ! */
406
        put_swf_line_edge(&p, width, 0);
407
        put_swf_line_edge(&p, 0, height);
408
        put_swf_line_edge(&p, -width, 0);
409
        put_swf_line_edge(&p, 0, -height);
410 de6d9b64 Fabrice Bellard
    
411 747a0554 Tinic Uro
        /* end of shape */
412
        put_bits(&p, 1, 0); /* not an edge */
413
        put_bits(&p, 5, 0);
414 de6d9b64 Fabrice Bellard
415 747a0554 Tinic Uro
        flush_put_bits(&p);
416
        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
417 de6d9b64 Fabrice Bellard
418 747a0554 Tinic Uro
        put_swf_end_tag(s);
419
    }
420 de6d9b64 Fabrice Bellard
    
421 747a0554 Tinic Uro
    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
422 de6d9b64 Fabrice Bellard
        int v;
423
424
        /* start sound */
425 747a0554 Tinic Uro
        put_swf_tag(s, TAG_STREAMHEAD2);
426 de6d9b64 Fabrice Bellard
427
        v = 0;
428
        switch(audio_enc->sample_rate) {
429
        case 11025:
430
            v |= 1 << 2;
431
            break;
432
        case 22050:
433
            v |= 2 << 2;
434
            break;
435
        case 44100:
436
            v |= 3 << 2;
437
            break;
438
        default:
439
            /* not supported */
440 747a0554 Tinic Uro
            av_free(swf->audio_fifo);
441 1ea4f593 Fabrice Bellard
            av_free(swf);
442 de6d9b64 Fabrice Bellard
            return -1;
443
        }
444 747a0554 Tinic Uro
        v |= 0x02; /* 16 bit playback */
445 de6d9b64 Fabrice Bellard
        if (audio_enc->channels == 2)
446 747a0554 Tinic Uro
            v |= 0x01; /* stereo playback */
447
        put_byte(&s->pb, v);
448 de6d9b64 Fabrice Bellard
        v |= 0x20; /* mp3 compressed */
449
        put_byte(&s->pb, v);
450 747a0554 Tinic Uro
        put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
451
        put_le16(&s->pb, 0);
452 de6d9b64 Fabrice Bellard
        
453
        put_swf_end_tag(s);
454
    }
455
456
    put_flush_packet(&s->pb);
457
    return 0;
458
}
459
460
static int swf_write_video(AVFormatContext *s, 
461 49057904 Fabrice Bellard
                           AVCodecContext *enc, const uint8_t *buf, int size)
462 de6d9b64 Fabrice Bellard
{
463 747a0554 Tinic Uro
    SWFContext *swf = s->priv_data;
464 de6d9b64 Fabrice Bellard
    ByteIOContext *pb = &s->pb;
465 747a0554 Tinic Uro
    int c = 0;
466
    int outSize = 0;
467
    int outSamples = 0;
468
    
469
    /* Flash Player limit */
470 d3e18ad0 Michael Niedermayer
    if ( swf->swf_frame_number == 16000 ) {
471 bc874dae Michel Bardiaux
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
472 de6d9b64 Fabrice Bellard
    }
473
474 747a0554 Tinic Uro
    if ( swf->audio_type ) {
475
        /* Prescan audio data for this swf frame */
476
retry_swf_audio_packet:
477
        if ( ( swf->audio_size-outSize ) >= 4 ) {
478
            int mp3FrameSize = 0;
479
            int mp3SampleRate = 0;
480
            int mp3IsMono = 0;
481
            int mp3SamplesPerFrame = 0;
482
            
483
            /* copy out mp3 header from ring buffer */
484
            uint8_t header[4];
485
            for (c=0; c<4; c++) {
486
                header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
487
            }
488
            
489
            if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
490
                if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
491
                    outSize += mp3FrameSize;
492
                    outSamples += mp3SamplesPerFrame;
493
                    if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
494
                        goto retry_swf_audio_packet;
495
                    }
496
                }
497
            } else {
498
                /* invalid mp3 data, skip forward
499
                we need to do this since the Flash Player 
500
                does not like custom headers */
501
                swf->audio_in_pos ++;
502
                swf->audio_size --;
503
                swf->audio_in_pos %= AUDIO_FIFO_SIZE;
504
                goto retry_swf_audio_packet;
505
            }
506
        }
507
        
508
        /* audio stream is behind video stream, bail */
509
        if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
510
            return 0;
511
        }
512
    }
513 de6d9b64 Fabrice Bellard
514 747a0554 Tinic Uro
            if ( swf->video_type == CODEC_ID_FLV1 ) {
515
                if ( swf->video_frame_number == 0 ) {
516
                    /* create a new video object */
517
                    put_swf_tag(s, TAG_VIDEOSTREAM);
518
                    put_le16(pb, VIDEO_ID);
519
                    put_le16(pb, 15000 ); /* hard flash player limit */
520
                    put_le16(pb, enc->width);
521
                    put_le16(pb, enc->height);
522
                    put_byte(pb, 0);
523
                    put_byte(pb, SWF_VIDEO_CODEC_FLV1);
524
                    put_swf_end_tag(s);
525
                    
526
                    /* place the video object for the first time */
527
                    put_swf_tag(s, TAG_PLACEOBJECT2);
528
                    put_byte(pb, 0x36);
529
                    put_le16(pb, 1);
530
                    put_le16(pb, VIDEO_ID);
531
                    put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
532
                    put_le16(pb, swf->video_frame_number );
533
                    put_byte(pb, 'v');
534
                    put_byte(pb, 'i');
535
                    put_byte(pb, 'd');
536
                    put_byte(pb, 'e');
537
                    put_byte(pb, 'o');
538
                    put_byte(pb, 0x00);
539
                    put_swf_end_tag(s);
540
                } else {
541
                    /* mark the character for update */
542
                    put_swf_tag(s, TAG_PLACEOBJECT2);
543
                    put_byte(pb, 0x11);
544
                    put_le16(pb, 1);
545
                    put_le16(pb, swf->video_frame_number );
546
                    put_swf_end_tag(s);
547
                }
548
    
549
                    /* set video frame data */
550
                    put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
551
                    put_le16(pb, VIDEO_ID); 
552
                    put_le16(pb, swf->video_frame_number++ );
553 14a68b89 Michael Niedermayer
                    put_buffer(pb, buf, size);
554 747a0554 Tinic Uro
                    put_swf_end_tag(s);
555
            } else if ( swf->video_type == CODEC_ID_MJPEG ) {
556
                if (swf->swf_frame_number > 0) {
557
                    /* remove the shape */
558
                    put_swf_tag(s, TAG_REMOVEOBJECT);
559
                    put_le16(pb, SHAPE_ID); /* shape ID */
560
                    put_le16(pb, 1); /* depth */
561
                    put_swf_end_tag(s);
562
                
563
                    /* free the bitmap */
564
                    put_swf_tag(s, TAG_FREECHARACTER);
565
                    put_le16(pb, BITMAP_ID);
566
                    put_swf_end_tag(s);
567
                }
568
        
569
                put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
570
        
571
                put_le16(pb, BITMAP_ID); /* ID of the image */
572
        
573
                /* a dummy jpeg header seems to be required */
574
                put_byte(pb, 0xff); 
575
                put_byte(pb, 0xd8);
576
                put_byte(pb, 0xff);
577
                put_byte(pb, 0xd9);
578
                /* write the jpeg image */
579 14a68b89 Michael Niedermayer
                put_buffer(pb, buf, size);
580 747a0554 Tinic Uro
        
581
                put_swf_end_tag(s);
582
        
583
                /* draw the shape */
584
        
585
                put_swf_tag(s, TAG_PLACEOBJECT);
586
                put_le16(pb, SHAPE_ID); /* shape ID */
587
                put_le16(pb, 1); /* depth */
588
                put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
589
                put_swf_end_tag(s);
590
            } else {
591
                /* invalid codec */
592
            }
593
    
594
            swf->swf_frame_number ++;
595 de6d9b64 Fabrice Bellard
596 747a0554 Tinic Uro
    swf->video_samples += swf->samples_per_frame;
597 de6d9b64 Fabrice Bellard
598 747a0554 Tinic Uro
    /* streaming sound always should be placed just before showframe tags */
599
    if ( outSize > 0 ) {
600
        put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
601
        put_le16(pb, outSamples);
602
        put_le16(pb, 0);
603
        for (c=0; c<outSize; c++) {
604
            put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
605
        }
606
        put_swf_end_tag(s);
607 de6d9b64 Fabrice Bellard
    
608 747a0554 Tinic Uro
        /* update FIFO */
609
        swf->sound_samples += outSamples;
610
        swf->audio_in_pos += outSize;
611
        swf->audio_size -= outSize;
612
        swf->audio_in_pos %= AUDIO_FIFO_SIZE;
613
    }
614
615 de6d9b64 Fabrice Bellard
    /* output the frame */
616
    put_swf_tag(s, TAG_SHOWFRAME);
617
    put_swf_end_tag(s);
618
    
619
    put_flush_packet(&s->pb);
620 747a0554 Tinic Uro
    
621 de6d9b64 Fabrice Bellard
    return 0;
622
}
623
624 747a0554 Tinic Uro
static int swf_write_audio(AVFormatContext *s, 
625
                           AVCodecContext *enc, const uint8_t *buf, int size)
626 de6d9b64 Fabrice Bellard
{
627 747a0554 Tinic Uro
    SWFContext *swf = s->priv_data;
628
    int c = 0;
629 de6d9b64 Fabrice Bellard
630 747a0554 Tinic Uro
    /* Flash Player limit */
631 d3e18ad0 Michael Niedermayer
    if ( swf->swf_frame_number == 16000 ) {
632 bc874dae Michel Bardiaux
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
633 747a0554 Tinic Uro
    }
634
635
    if (enc->codec_id == CODEC_ID_MP3 ) {
636
        for (c=0; c<size; c++) {
637
            swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
638
        }
639
        swf->audio_size += size;
640
        swf->audio_out_pos += size;
641
        swf->audio_out_pos %= AUDIO_FIFO_SIZE;
642
    }
643
644
    /* if audio only stream make sure we add swf frames */
645
    if ( swf->video_type == 0 ) {
646
        swf_write_video(s, enc, 0, 0);
647
    }
648 de6d9b64 Fabrice Bellard
649
    return 0;
650
}
651
652 e928649b Michael Niedermayer
static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
653 de6d9b64 Fabrice Bellard
{
654 e928649b Michael Niedermayer
    AVCodecContext *codec = &s->streams[pkt->stream_index]->codec;
655 de6d9b64 Fabrice Bellard
    if (codec->codec_type == CODEC_TYPE_AUDIO)
656 e928649b Michael Niedermayer
        return swf_write_audio(s, codec, pkt->data, pkt->size);
657 de6d9b64 Fabrice Bellard
    else
658 e928649b Michael Niedermayer
        return swf_write_video(s, codec, pkt->data, pkt->size);
659 de6d9b64 Fabrice Bellard
}
660
661
static int swf_write_trailer(AVFormatContext *s)
662
{
663
    SWFContext *swf = s->priv_data;
664
    ByteIOContext *pb = &s->pb;
665
    AVCodecContext *enc, *video_enc;
666
    int file_size, i;
667
668
    video_enc = NULL;
669
    for(i=0;i<s->nb_streams;i++) {
670
        enc = &s->streams[i]->codec;
671
        if (enc->codec_type == CODEC_TYPE_VIDEO)
672
            video_enc = enc;
673
    }
674
675
    put_swf_tag(s, TAG_END);
676
    put_swf_end_tag(s);
677
    
678
    put_flush_packet(&s->pb);
679
680
    /* patch file size and number of frames if not streamed */
681
    if (!url_is_streamed(&s->pb) && video_enc) {
682
        file_size = url_ftell(pb);
683
        url_fseek(pb, 4, SEEK_SET);
684
        put_le32(pb, file_size);
685
        url_fseek(pb, swf->duration_pos, SEEK_SET);
686
        put_le16(pb, video_enc->frame_number);
687
    }
688 747a0554 Tinic Uro
    
689
    av_free(swf->audio_fifo);
690
691 de6d9b64 Fabrice Bellard
    return 0;
692
}
693 764ef400 Mike Melanson
#endif //CONFIG_ENCODERS
694 de6d9b64 Fabrice Bellard
695 747a0554 Tinic Uro
/*********************************************/
696
/* Extract FLV encoded frame and MP3 from swf
697
   Note that the detection of the real frame
698
   is inaccurate at this point as it can be
699
   quite tricky to determine, you almost certainly 
700
   will get a bad audio/video sync */
701 de6d9b64 Fabrice Bellard
702
static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
703
{
704
    int tag, len;
705
    
706
    if (url_feof(pb))
707
        return -1;
708
709
    tag = get_le16(pb);
710
    len = tag & 0x3f;
711
    tag = tag >> 6;
712
    if (len == 0x3f) {
713
        len = get_le32(pb);
714
    }
715
    *len_ptr = len;
716
    return tag;
717
}
718
719 c9a65ca8 Fabrice Bellard
720
static int swf_probe(AVProbeData *p)
721
{
722
    /* check file header */
723
    if (p->buf_size <= 16)
724
        return 0;
725
    if (p->buf[0] == 'F' && p->buf[1] == 'W' &&
726 17269bdf Fabrice Bellard
        p->buf[2] == 'S')
727 c9a65ca8 Fabrice Bellard
        return AVPROBE_SCORE_MAX;
728
    else
729
        return 0;
730
}
731
732 de6d9b64 Fabrice Bellard
static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
733
{
734 747a0554 Tinic Uro
    SWFContext *swf = 0;
735 de6d9b64 Fabrice Bellard
    ByteIOContext *pb = &s->pb;
736
    int nbits, len, frame_rate, tag, v;
737 747a0554 Tinic Uro
    offset_t firstTagOff;
738
    AVStream *ast = 0;
739
    AVStream *vst = 0;
740
741
    swf = av_malloc(sizeof(SWFContext));
742
    if (!swf)
743
        return -1;
744
    s->priv_data = swf;
745 de6d9b64 Fabrice Bellard
746
    if ((get_be32(pb) & 0xffffff00) != MKBETAG('F', 'W', 'S', 0))
747 0bd586c5 Mike Melanson
        return AVERROR_IO;
748 de6d9b64 Fabrice Bellard
    get_le32(pb);
749
    /* skip rectangle size */
750
    nbits = get_byte(pb) >> 3;
751
    len = (4 * nbits - 3 + 7) / 8;
752
    url_fskip(pb, len);
753
    frame_rate = get_le16(pb);
754
    get_le16(pb); /* frame count */
755 747a0554 Tinic Uro
    
756
    /* The Flash Player converts 8.8 frame rates 
757
       to milliseconds internally. Do the same to get 
758
       a correct framerate */
759
    swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
760
    swf->samples_per_frame = 0;
761
    swf->ch_id = -1;
762
763
    firstTagOff = url_ftell(pb);
764 de6d9b64 Fabrice Bellard
    for(;;) {
765
        tag = get_swf_tag(pb, &len);
766
        if (tag < 0) {
767 747a0554 Tinic Uro
            if ( ast || vst ) {
768
                if ( vst && ast ) {
769
                    vst->codec.frame_rate = ast->codec.sample_rate / swf->samples_per_frame;
770
                    vst->codec.frame_rate_base = 1;
771
                }
772
                break;
773
            }
774 bc874dae Michel Bardiaux
            av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
775 0bd586c5 Mike Melanson
            return AVERROR_IO;
776 de6d9b64 Fabrice Bellard
        }
777 747a0554 Tinic Uro
        if ( tag == TAG_VIDEOSTREAM && !vst) {
778
            swf->ch_id = get_le16(pb);
779
            get_le16(pb);
780
            get_le16(pb);
781
            get_le16(pb);
782
            get_byte(pb);
783
            /* Check for FLV1 */
784
            if ( get_byte(pb) == SWF_VIDEO_CODEC_FLV1 ) {
785
                vst = av_new_stream(s, 0);
786 9ee91c2f Michael Niedermayer
                av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
787
    
788 747a0554 Tinic Uro
                vst->codec.codec_type = CODEC_TYPE_VIDEO;
789
                vst->codec.codec_id = CODEC_ID_FLV1;
790
                if ( swf->samples_per_frame ) {
791
                    vst->codec.frame_rate = 1000. / swf->ms_per_frame;
792
                    vst->codec.frame_rate_base = 1;
793
                }
794
            }
795
        } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
796 de6d9b64 Fabrice Bellard
            /* streaming found */
797
            get_byte(pb);
798
            v = get_byte(pb);
799 747a0554 Tinic Uro
            swf->samples_per_frame = get_le16(pb);
800 647b7762 Glyn Kennington
            if (len!=4)
801
                url_fskip(pb,len-4);
802 de6d9b64 Fabrice Bellard
            /* if mp3 streaming found, OK */
803
            if ((v & 0x20) != 0) {
804 747a0554 Tinic Uro
                if ( tag == TAG_STREAMHEAD2 ) {
805
                    get_le16(pb);
806
                }
807
                ast = av_new_stream(s, 1);
808 9ee91c2f Michael Niedermayer
                av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
809 747a0554 Tinic Uro
                if (!ast)
810 de6d9b64 Fabrice Bellard
                    return -ENOMEM;
811 1e491e29 Michael Niedermayer
812 de6d9b64 Fabrice Bellard
                if (v & 0x01)
813 747a0554 Tinic Uro
                    ast->codec.channels = 2;
814 de6d9b64 Fabrice Bellard
                else
815 747a0554 Tinic Uro
                    ast->codec.channels = 1;
816 de6d9b64 Fabrice Bellard
817
                switch((v>> 2) & 0x03) {
818
                case 1:
819 747a0554 Tinic Uro
                    ast->codec.sample_rate = 11025;
820 de6d9b64 Fabrice Bellard
                    break;
821
                case 2:
822 747a0554 Tinic Uro
                    ast->codec.sample_rate = 22050;
823 de6d9b64 Fabrice Bellard
                    break;
824
                case 3:
825 747a0554 Tinic Uro
                    ast->codec.sample_rate = 44100;
826 de6d9b64 Fabrice Bellard
                    break;
827
                default:
828 747a0554 Tinic Uro
                    av_free(ast);
829 0bd586c5 Mike Melanson
                    return AVERROR_IO;
830 de6d9b64 Fabrice Bellard
                }
831 747a0554 Tinic Uro
                ast->codec.codec_type = CODEC_TYPE_AUDIO;
832
                ast->codec.codec_id = CODEC_ID_MP3;
833 de6d9b64 Fabrice Bellard
            }
834
        } else {
835
            url_fskip(pb, len);
836
        }
837
    }
838 747a0554 Tinic Uro
    url_fseek(pb, firstTagOff, SEEK_SET);
839
    
840 de6d9b64 Fabrice Bellard
    return 0;
841
}
842
843
static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
844
{
845 747a0554 Tinic Uro
    SWFContext *swf = s->priv_data;
846 de6d9b64 Fabrice Bellard
    ByteIOContext *pb = &s->pb;
847 747a0554 Tinic Uro
    AVStream *st = 0;
848
    int tag, len, i, frame;
849 de6d9b64 Fabrice Bellard
    
850
    for(;;) {
851
        tag = get_swf_tag(pb, &len);
852
        if (tag < 0) 
853 0bd586c5 Mike Melanson
            return AVERROR_IO;
854 747a0554 Tinic Uro
        if (tag == TAG_VIDEOFRAME) {
855
            for( i=0; i<s->nb_streams; i++ ) {
856
                st = s->streams[i];
857
                if (st->id == 0) {
858
                    if ( get_le16(pb) == swf->ch_id ) {
859
                        frame = get_le16(pb);
860
                        av_new_packet(pkt, len-4);
861
                        pkt->pts = frame * swf->ms_per_frame;
862
                        pkt->stream_index = st->index;
863
                        get_buffer(pb, pkt->data, pkt->size);
864
                        return pkt->size;
865
                    } else {
866
                        url_fskip(pb, len-2);
867
                        continue;
868
                    }
869
                }
870
            }    
871
            url_fskip(pb, len);
872
        } else if (tag == TAG_STREAMBLOCK) {
873
            for( i=0; i<s->nb_streams; i++ ) {
874
                st = s->streams[i];
875
                if (st->id == 1) {
876
                    av_new_packet(pkt, len);
877
                    pkt->stream_index = st->index;
878
                    get_buffer(pb, pkt->data, pkt->size);
879
                    return pkt->size;
880
                }
881
            }
882
            url_fskip(pb, len);
883 de6d9b64 Fabrice Bellard
        } else {
884
            url_fskip(pb, len);
885
        }
886
    }
887
    return 0;
888
}
889
890
static int swf_read_close(AVFormatContext *s)
891
{
892
     return 0;
893
}
894
895 c9a65ca8 Fabrice Bellard
static AVInputFormat swf_iformat = {
896
    "swf",
897
    "Flash format",
898 747a0554 Tinic Uro
    sizeof(SWFContext),
899 c9a65ca8 Fabrice Bellard
    swf_probe,
900
    swf_read_header,
901
    swf_read_packet,
902
    swf_read_close,
903
};
904
905 764ef400 Mike Melanson
#ifdef CONFIG_ENCODERS
906 c9a65ca8 Fabrice Bellard
static AVOutputFormat swf_oformat = {
907 de6d9b64 Fabrice Bellard
    "swf",
908
    "Flash format",
909
    "application/x-shockwave-flash",
910
    "swf",
911 c9a65ca8 Fabrice Bellard
    sizeof(SWFContext),
912 747a0554 Tinic Uro
    CODEC_ID_MP3,
913
    CODEC_ID_FLV1,
914 de6d9b64 Fabrice Bellard
    swf_write_header,
915
    swf_write_packet,
916
    swf_write_trailer,
917
};
918 764ef400 Mike Melanson
#endif //CONFIG_ENCODERS
919 c9a65ca8 Fabrice Bellard
920
int swf_init(void)
921
{
922
    av_register_input_format(&swf_iformat);
923 764ef400 Mike Melanson
#ifdef CONFIG_ENCODERS
924 c9a65ca8 Fabrice Bellard
    av_register_output_format(&swf_oformat);
925 764ef400 Mike Melanson
#endif //CONFIG_ENCODERS
926 c9a65ca8 Fabrice Bellard
    return 0;
927
}