Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 0bc4728e

History | View | Annotate | Download (23.3 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 b78e7197 Diego Biurrun
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9 17269bdf Fabrice Bellard
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11 b78e7197 Diego Biurrun
 * version 2.1 of the License, or (at your option) any later version.
12 de6d9b64 Fabrice Bellard
 *
13 b78e7197 Diego Biurrun
 * FFmpeg is distributed in the hope that it will be useful,
14 de6d9b64 Fabrice Bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 17269bdf Fabrice Bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17 de6d9b64 Fabrice Bellard
 *
18 17269bdf Fabrice Bellard
 * You should have received a copy of the GNU Lesser General Public
19 b78e7197 Diego Biurrun
 * License along with FFmpeg; if not, write to the Free Software
20 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 de6d9b64 Fabrice Bellard
 */
22
#include "avformat.h"
23 2de7795a Michael Niedermayer
#include "bitstream.h"
24 5ce117c3 Aurelien Jacobs
#include "riff.h"    /* for CodecTag */
25 de6d9b64 Fabrice Bellard
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 98d82b22 Alex Beregszaszi
#define TAG_STREAMHEAD    18
37 de6d9b64 Fabrice Bellard
#define TAG_STREAMBLOCK   19
38
#define TAG_JPEG2         21
39 747a0554 Tinic Uro
#define TAG_PLACEOBJECT2  26
40
#define TAG_STREAMHEAD2   45
41 bb270c08 Diego Biurrun
#define TAG_VIDEOSTREAM   60
42 747a0554 Tinic Uro
#define TAG_VIDEOFRAME    61
43 dfb400a8 Paul Egan
#define TAG_FILEATTRIBUTES 69
44 de6d9b64 Fabrice Bellard
45
#define TAG_LONG         0x100
46
47
/* flags for shape definition */
48
#define FLAG_MOVETO      0x01
49
#define FLAG_SETFILL0    0x02
50
#define FLAG_SETFILL1    0x04
51
52 747a0554 Tinic Uro
#define AUDIO_FIFO_SIZE 65536
53
54 de6d9b64 Fabrice Bellard
/* character id used */
55
#define BITMAP_ID 0
56 747a0554 Tinic Uro
#define VIDEO_ID 0
57 de6d9b64 Fabrice Bellard
#define SHAPE_ID  1
58
59 14a68b89 Michael Niedermayer
#undef NDEBUG
60
#include <assert.h>
61 747a0554 Tinic Uro
62 de6d9b64 Fabrice Bellard
typedef struct {
63 5b1e5dce Baptiste Coudurier
    int audio_stream_index;
64 8be1c656 Fabrice Bellard
    offset_t duration_pos;
65
    offset_t tag_pos;
66 115329f1 Diego Biurrun
67 747a0554 Tinic Uro
    int samples_per_frame;
68
    int sound_samples;
69
    int swf_frame_number;
70
    int video_frame_number;
71 b912ef3f Baptiste Coudurier
    int frame_rate;
72 de6d9b64 Fabrice Bellard
    int tag;
73 747a0554 Tinic Uro
74 013e0a8f Baptiste Coudurier
    uint8_t audio_fifo[AUDIO_FIFO_SIZE];
75 747a0554 Tinic Uro
    int audio_in_pos;
76
77
    int video_type;
78
    int audio_type;
79 de6d9b64 Fabrice Bellard
} SWFContext;
80
81 7caf0cc6 Michael Niedermayer
static const AVCodecTag swf_codec_tags[] = {
82 5ce117c3 Aurelien Jacobs
    {CODEC_ID_FLV1, 0x02},
83
    {CODEC_ID_VP6F, 0x04},
84
    {0, 0},
85
};
86
87 dd8a46d9 Baptiste Coudurier
static const AVCodecTag swf_audio_codec_tags[] = {
88
    {CODEC_ID_PCM_S16LE,  0x00},
89
    {CODEC_ID_ADPCM_SWF,  0x01},
90
    {CODEC_ID_MP3,        0x02},
91
    {CODEC_ID_PCM_S16LE,  0x03},
92
  //{CODEC_ID_NELLYMOSER, 0x06},
93
    {0, 0},
94
};
95
96 a9e35095 Diego Biurrun
#ifdef CONFIG_MUXERS
97 de6d9b64 Fabrice Bellard
static void put_swf_tag(AVFormatContext *s, int tag)
98
{
99
    SWFContext *swf = s->priv_data;
100 899681cd Björn Axelsson
    ByteIOContext *pb = s->pb;
101 de6d9b64 Fabrice Bellard
102
    swf->tag_pos = url_ftell(pb);
103
    swf->tag = tag;
104
    /* reserve some room for the tag */
105
    if (tag & TAG_LONG) {
106
        put_le16(pb, 0);
107
        put_le32(pb, 0);
108
    } else {
109
        put_le16(pb, 0);
110
    }
111
}
112
113
static void put_swf_end_tag(AVFormatContext *s)
114
{
115
    SWFContext *swf = s->priv_data;
116 899681cd Björn Axelsson
    ByteIOContext *pb = s->pb;
117 8be1c656 Fabrice Bellard
    offset_t pos;
118 de6d9b64 Fabrice Bellard
    int tag_len, tag;
119
120
    pos = url_ftell(pb);
121
    tag_len = pos - swf->tag_pos - 2;
122
    tag = swf->tag;
123
    url_fseek(pb, swf->tag_pos, SEEK_SET);
124
    if (tag & TAG_LONG) {
125
        tag &= ~TAG_LONG;
126
        put_le16(pb, (tag << 6) | 0x3f);
127
        put_le32(pb, tag_len - 4);
128
    } else {
129
        assert(tag_len < 0x3f);
130
        put_le16(pb, (tag << 6) | tag_len);
131
    }
132
    url_fseek(pb, pos, SEEK_SET);
133
}
134
135
static inline void max_nbits(int *nbits_ptr, int val)
136
{
137
    int n;
138
139
    if (val == 0)
140
        return;
141
    val = abs(val);
142
    n = 1;
143
    while (val != 0) {
144
        n++;
145
        val >>= 1;
146
    }
147
    if (n > *nbits_ptr)
148
        *nbits_ptr = n;
149
}
150
151 115329f1 Diego Biurrun
static void put_swf_rect(ByteIOContext *pb,
152 de6d9b64 Fabrice Bellard
                         int xmin, int xmax, int ymin, int ymax)
153
{
154
    PutBitContext p;
155 0c1a9eda Zdenek Kabelac
    uint8_t buf[256];
156 de6d9b64 Fabrice Bellard
    int nbits, mask;
157
158 117a5490 Alex Beregszaszi
    init_put_bits(&p, buf, sizeof(buf));
159 115329f1 Diego Biurrun
160 de6d9b64 Fabrice Bellard
    nbits = 0;
161
    max_nbits(&nbits, xmin);
162
    max_nbits(&nbits, xmax);
163
    max_nbits(&nbits, ymin);
164
    max_nbits(&nbits, ymax);
165
    mask = (1 << nbits) - 1;
166
167
    /* rectangle info */
168
    put_bits(&p, 5, nbits);
169
    put_bits(&p, nbits, xmin & mask);
170
    put_bits(&p, nbits, xmax & mask);
171
    put_bits(&p, nbits, ymin & mask);
172
    put_bits(&p, nbits, ymax & mask);
173 115329f1 Diego Biurrun
174 de6d9b64 Fabrice Bellard
    flush_put_bits(&p);
175 17592475 Michael Niedermayer
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
176 de6d9b64 Fabrice Bellard
}
177
178
static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
179
{
180
    int nbits, mask;
181
182
    put_bits(pb, 1, 1); /* edge */
183
    put_bits(pb, 1, 1); /* line select */
184
    nbits = 2;
185
    max_nbits(&nbits, dx);
186
    max_nbits(&nbits, dy);
187
188
    mask = (1 << nbits) - 1;
189
    put_bits(pb, 4, nbits - 2); /* 16 bits precision */
190
    if (dx == 0) {
191 c78ed542 Baptiste Coudurier
        put_bits(pb, 1, 0);
192
        put_bits(pb, 1, 1);
193
        put_bits(pb, nbits, dy & mask);
194 de6d9b64 Fabrice Bellard
    } else if (dy == 0) {
195 c78ed542 Baptiste Coudurier
        put_bits(pb, 1, 0);
196
        put_bits(pb, 1, 0);
197
        put_bits(pb, nbits, dx & mask);
198 de6d9b64 Fabrice Bellard
    } else {
199 c78ed542 Baptiste Coudurier
        put_bits(pb, 1, 1);
200
        put_bits(pb, nbits, dx & mask);
201
        put_bits(pb, nbits, dy & mask);
202 de6d9b64 Fabrice Bellard
    }
203
}
204
205
#define FRAC_BITS 16
206
207 747a0554 Tinic Uro
/* put matrix */
208 de6d9b64 Fabrice Bellard
static void put_swf_matrix(ByteIOContext *pb,
209
                           int a, int b, int c, int d, int tx, int ty)
210
{
211
    PutBitContext p;
212 0c1a9eda Zdenek Kabelac
    uint8_t buf[256];
213 747a0554 Tinic Uro
    int nbits;
214 de6d9b64 Fabrice Bellard
215 117a5490 Alex Beregszaszi
    init_put_bits(&p, buf, sizeof(buf));
216 115329f1 Diego Biurrun
217 de6d9b64 Fabrice Bellard
    put_bits(&p, 1, 1); /* a, d present */
218 747a0554 Tinic Uro
    nbits = 1;
219
    max_nbits(&nbits, a);
220
    max_nbits(&nbits, d);
221
    put_bits(&p, 5, nbits); /* nb bits */
222
    put_bits(&p, nbits, a);
223
    put_bits(&p, nbits, d);
224 115329f1 Diego Biurrun
225 de6d9b64 Fabrice Bellard
    put_bits(&p, 1, 1); /* b, c present */
226 747a0554 Tinic Uro
    nbits = 1;
227
    max_nbits(&nbits, c);
228
    max_nbits(&nbits, b);
229
    put_bits(&p, 5, nbits); /* nb bits */
230
    put_bits(&p, nbits, c);
231
    put_bits(&p, nbits, b);
232
233
    nbits = 1;
234
    max_nbits(&nbits, tx);
235
    max_nbits(&nbits, ty);
236
    put_bits(&p, 5, nbits); /* nb bits */
237
    put_bits(&p, nbits, tx);
238
    put_bits(&p, nbits, ty);
239 de6d9b64 Fabrice Bellard
240
    flush_put_bits(&p);
241 17592475 Michael Niedermayer
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
242 de6d9b64 Fabrice Bellard
}
243
244 747a0554 Tinic Uro
/* */
245 de6d9b64 Fabrice Bellard
static int swf_write_header(AVFormatContext *s)
246
{
247 fed7d067 Baptiste Coudurier
    SWFContext *swf = s->priv_data;
248 899681cd Björn Axelsson
    ByteIOContext *pb = s->pb;
249 de6d9b64 Fabrice Bellard
    AVCodecContext *enc, *audio_enc, *video_enc;
250
    PutBitContext p;
251 0c1a9eda Zdenek Kabelac
    uint8_t buf1[256];
252 14bea432 Michael Niedermayer
    int i, width, height, rate, rate_base;
253 dfb400a8 Paul Egan
    int is_avm2;
254 de6d9b64 Fabrice Bellard
255 747a0554 Tinic Uro
    swf->audio_in_pos = 0;
256
    swf->sound_samples = 0;
257
    swf->swf_frame_number = 0;
258
    swf->video_frame_number = 0;
259
260 de6d9b64 Fabrice Bellard
    video_enc = NULL;
261
    audio_enc = NULL;
262
    for(i=0;i<s->nb_streams;i++) {
263 01f4895c Michael Niedermayer
        enc = s->streams[i]->codec;
264 013e0a8f Baptiste Coudurier
        if (enc->codec_type == CODEC_TYPE_AUDIO) {
265
            if (enc->codec_id == CODEC_ID_MP3) {
266
                if (!enc->frame_size) {
267
                    av_log(s, AV_LOG_ERROR, "audio frame size not set\n");
268
                    return -1;
269
                }
270
                audio_enc = enc;
271
            } else {
272 5095aaa9 Baptiste Coudurier
                av_log(s, AV_LOG_ERROR, "SWF muxer only supports MP3\n");
273 013e0a8f Baptiste Coudurier
                return -1;
274
            }
275
        } else {
276 5fcf2df3 Baptiste Coudurier
            if (enc->codec_id == CODEC_ID_VP6F ||
277
                enc->codec_id == CODEC_ID_FLV1 ||
278
                enc->codec_id == CODEC_ID_MJPEG) {
279 747a0554 Tinic Uro
                video_enc = enc;
280
            } else {
281 5095aaa9 Baptiste Coudurier
                av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n");
282 747a0554 Tinic Uro
                return -1;
283
            }
284
        }
285 de6d9b64 Fabrice Bellard
    }
286
287
    if (!video_enc) {
288 df3a80b5 Diego Biurrun
        /* currently, cannot work correctly if audio only */
289 747a0554 Tinic Uro
        swf->video_type = 0;
290 de6d9b64 Fabrice Bellard
        width = 320;
291
        height = 200;
292 14bea432 Michael Niedermayer
        rate = 10;
293
        rate_base= 1;
294 de6d9b64 Fabrice Bellard
    } else {
295 747a0554 Tinic Uro
        swf->video_type = video_enc->codec_id;
296 de6d9b64 Fabrice Bellard
        width = video_enc->width;
297
        height = video_enc->height;
298 c0df9d75 Michael Niedermayer
        rate = video_enc->time_base.den;
299
        rate_base = video_enc->time_base.num;
300 de6d9b64 Fabrice Bellard
    }
301
302 5fcf2df3 Baptiste Coudurier
    if (!audio_enc) {
303 747a0554 Tinic Uro
        swf->audio_type = 0;
304 5fcf2df3 Baptiste Coudurier
        swf->samples_per_frame = (44100. * rate_base) / rate;
305 747a0554 Tinic Uro
    } else {
306
        swf->audio_type = audio_enc->codec_id;
307 5fcf2df3 Baptiste Coudurier
        swf->samples_per_frame = (audio_enc->sample_rate * rate_base) / rate;
308 747a0554 Tinic Uro
    }
309
310 dfb400a8 Paul Egan
    is_avm2 = !strcmp("avm2", s->oformat->name);
311
312 de6d9b64 Fabrice Bellard
    put_tag(pb, "FWS");
313 dfb400a8 Paul Egan
    if (is_avm2) {
314
        put_byte(pb, 9);
315
    } else if (video_enc && video_enc->codec_id == CODEC_ID_VP6F) {
316 5ce117c3 Aurelien Jacobs
        put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
317 5fcf2df3 Baptiste Coudurier
    } else if (video_enc && video_enc->codec_id == CODEC_ID_FLV1) {
318 747a0554 Tinic Uro
        put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
319
    } else {
320
        put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
321
    }
322 115329f1 Diego Biurrun
    put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
323
                                      (will be patched if not streamed) */
324 de6d9b64 Fabrice Bellard
325 747a0554 Tinic Uro
    put_swf_rect(pb, 0, width * 20, 0, height * 20);
326 14bea432 Michael Niedermayer
    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
327 de6d9b64 Fabrice Bellard
    swf->duration_pos = url_ftell(pb);
328 14bea432 Michael Niedermayer
    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
329 115329f1 Diego Biurrun
330 dfb400a8 Paul Egan
    /* avm2/swf v9 (also v8?) files require a file attribute tag */
331
    if (is_avm2) {
332
        put_swf_tag(s, TAG_FILEATTRIBUTES);
333
        put_le32(pb, 1<<3); /* set ActionScript v3/AVM2 flag */
334
        put_swf_end_tag(s);
335
    }
336
337 de6d9b64 Fabrice Bellard
    /* define a shape with the jpeg inside */
338 5fcf2df3 Baptiste Coudurier
    if (video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
339
                       video_enc->codec_id == CODEC_ID_FLV1)) {
340
    } else if (video_enc && video_enc->codec_id == CODEC_ID_MJPEG) {
341 747a0554 Tinic Uro
        put_swf_tag(s, TAG_DEFINESHAPE);
342
343
        put_le16(pb, SHAPE_ID); /* ID of shape */
344
        /* bounding rectangle */
345
        put_swf_rect(pb, 0, width, 0, height);
346
        /* style info */
347
        put_byte(pb, 1); /* one fill style */
348
        put_byte(pb, 0x41); /* clipped bitmap fill */
349
        put_le16(pb, BITMAP_ID); /* bitmap ID */
350
        /* position of the bitmap */
351 115329f1 Diego Biurrun
        put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
352 c78ed542 Baptiste Coudurier
                       0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
353 747a0554 Tinic Uro
        put_byte(pb, 0); /* no line style */
354 115329f1 Diego Biurrun
355 747a0554 Tinic Uro
        /* shape drawing */
356
        init_put_bits(&p, buf1, sizeof(buf1));
357
        put_bits(&p, 4, 1); /* one fill bit */
358
        put_bits(&p, 4, 0); /* zero line bit */
359 115329f1 Diego Biurrun
360 747a0554 Tinic Uro
        put_bits(&p, 1, 0); /* not an edge */
361
        put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
362
        put_bits(&p, 5, 1); /* nbits */
363
        put_bits(&p, 1, 0); /* X */
364
        put_bits(&p, 1, 0); /* Y */
365
        put_bits(&p, 1, 1); /* set fill style 1 */
366 115329f1 Diego Biurrun
367 747a0554 Tinic Uro
        /* draw the rectangle ! */
368
        put_swf_line_edge(&p, width, 0);
369
        put_swf_line_edge(&p, 0, height);
370
        put_swf_line_edge(&p, -width, 0);
371
        put_swf_line_edge(&p, 0, -height);
372 115329f1 Diego Biurrun
373 747a0554 Tinic Uro
        /* end of shape */
374
        put_bits(&p, 1, 0); /* not an edge */
375
        put_bits(&p, 5, 0);
376 de6d9b64 Fabrice Bellard
377 747a0554 Tinic Uro
        flush_put_bits(&p);
378
        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
379 de6d9b64 Fabrice Bellard
380 747a0554 Tinic Uro
        put_swf_end_tag(s);
381
    }
382 115329f1 Diego Biurrun
383 5fcf2df3 Baptiste Coudurier
    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3) {
384 de6d9b64 Fabrice Bellard
        int v;
385
386
        /* start sound */
387 747a0554 Tinic Uro
        put_swf_tag(s, TAG_STREAMHEAD2);
388 de6d9b64 Fabrice Bellard
389
        v = 0;
390
        switch(audio_enc->sample_rate) {
391
        case 11025:
392
            v |= 1 << 2;
393
            break;
394
        case 22050:
395
            v |= 2 << 2;
396
            break;
397
        case 44100:
398
            v |= 3 << 2;
399
            break;
400
        default:
401
            /* not supported */
402 755bfeab Diego Biurrun
            av_log(s, AV_LOG_ERROR, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n");
403 de6d9b64 Fabrice Bellard
            return -1;
404
        }
405 747a0554 Tinic Uro
        v |= 0x02; /* 16 bit playback */
406 de6d9b64 Fabrice Bellard
        if (audio_enc->channels == 2)
407 747a0554 Tinic Uro
            v |= 0x01; /* stereo playback */
408 899681cd Björn Axelsson
        put_byte(s->pb, v);
409 de6d9b64 Fabrice Bellard
        v |= 0x20; /* mp3 compressed */
410 899681cd Björn Axelsson
        put_byte(s->pb, v);
411
        put_le16(s->pb, swf->samples_per_frame);  /* avg samples per frame */
412
        put_le16(s->pb, 0);
413 115329f1 Diego Biurrun
414 de6d9b64 Fabrice Bellard
        put_swf_end_tag(s);
415
    }
416
417 899681cd Björn Axelsson
    put_flush_packet(s->pb);
418 de6d9b64 Fabrice Bellard
    return 0;
419
}
420
421 115329f1 Diego Biurrun
static int swf_write_video(AVFormatContext *s,
422 49057904 Fabrice Bellard
                           AVCodecContext *enc, const uint8_t *buf, int size)
423 de6d9b64 Fabrice Bellard
{
424 747a0554 Tinic Uro
    SWFContext *swf = s->priv_data;
425 899681cd Björn Axelsson
    ByteIOContext *pb = s->pb;
426 115329f1 Diego Biurrun
427 747a0554 Tinic Uro
    /* Flash Player limit */
428 5fcf2df3 Baptiste Coudurier
    if (swf->swf_frame_number == 16000) {
429 bc874dae Michel Bardiaux
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
430 de6d9b64 Fabrice Bellard
    }
431
432 5fcf2df3 Baptiste Coudurier
    if (swf->video_type == CODEC_ID_VP6F ||
433
        swf->video_type == CODEC_ID_FLV1) {
434
        if (swf->video_frame_number == 0) {
435 c78ed542 Baptiste Coudurier
            /* create a new video object */
436
            put_swf_tag(s, TAG_VIDEOSTREAM);
437
            put_le16(pb, VIDEO_ID);
438 5fcf2df3 Baptiste Coudurier
            put_le16(pb, 15000); /* hard flash player limit */
439 c78ed542 Baptiste Coudurier
            put_le16(pb, enc->width);
440
            put_le16(pb, enc->height);
441
            put_byte(pb, 0);
442
            put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
443
            put_swf_end_tag(s);
444
445
            /* place the video object for the first time */
446
            put_swf_tag(s, TAG_PLACEOBJECT2);
447
            put_byte(pb, 0x36);
448
            put_le16(pb, 1);
449
            put_le16(pb, VIDEO_ID);
450
            put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
451 5fcf2df3 Baptiste Coudurier
            put_le16(pb, swf->video_frame_number);
452 c78ed542 Baptiste Coudurier
            put_byte(pb, 'v');
453
            put_byte(pb, 'i');
454
            put_byte(pb, 'd');
455
            put_byte(pb, 'e');
456
            put_byte(pb, 'o');
457
            put_byte(pb, 0x00);
458
            put_swf_end_tag(s);
459
        } else {
460
            /* mark the character for update */
461
            put_swf_tag(s, TAG_PLACEOBJECT2);
462
            put_byte(pb, 0x11);
463
            put_le16(pb, 1);
464 5fcf2df3 Baptiste Coudurier
            put_le16(pb, swf->video_frame_number);
465 c78ed542 Baptiste Coudurier
            put_swf_end_tag(s);
466
        }
467 115329f1 Diego Biurrun
468 c78ed542 Baptiste Coudurier
        /* set video frame data */
469
        put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
470
        put_le16(pb, VIDEO_ID);
471 5fcf2df3 Baptiste Coudurier
        put_le16(pb, swf->video_frame_number++);
472 c78ed542 Baptiste Coudurier
        put_buffer(pb, buf, size);
473
        put_swf_end_tag(s);
474 5fcf2df3 Baptiste Coudurier
    } else if (swf->video_type == CODEC_ID_MJPEG) {
475 c78ed542 Baptiste Coudurier
        if (swf->swf_frame_number > 0) {
476
            /* remove the shape */
477
            put_swf_tag(s, TAG_REMOVEOBJECT);
478
            put_le16(pb, SHAPE_ID); /* shape ID */
479
            put_le16(pb, 1); /* depth */
480
            put_swf_end_tag(s);
481
482
            /* free the bitmap */
483
            put_swf_tag(s, TAG_FREECHARACTER);
484
            put_le16(pb, BITMAP_ID);
485
            put_swf_end_tag(s);
486
        }
487 115329f1 Diego Biurrun
488 c78ed542 Baptiste Coudurier
        put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
489 115329f1 Diego Biurrun
490 c78ed542 Baptiste Coudurier
        put_le16(pb, BITMAP_ID); /* ID of the image */
491 115329f1 Diego Biurrun
492 c78ed542 Baptiste Coudurier
        /* a dummy jpeg header seems to be required */
493
        put_byte(pb, 0xff);
494
        put_byte(pb, 0xd8);
495
        put_byte(pb, 0xff);
496
        put_byte(pb, 0xd9);
497
        /* write the jpeg image */
498
        put_buffer(pb, buf, size);
499 115329f1 Diego Biurrun
500 c78ed542 Baptiste Coudurier
        put_swf_end_tag(s);
501 115329f1 Diego Biurrun
502 c78ed542 Baptiste Coudurier
        /* draw the shape */
503 115329f1 Diego Biurrun
504 c78ed542 Baptiste Coudurier
        put_swf_tag(s, TAG_PLACEOBJECT);
505
        put_le16(pb, SHAPE_ID); /* shape ID */
506
        put_le16(pb, 1); /* depth */
507
        put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
508
        put_swf_end_tag(s);
509
    } else {
510
        /* invalid codec */
511
    }
512 115329f1 Diego Biurrun
513 c78ed542 Baptiste Coudurier
    swf->swf_frame_number ++;
514 de6d9b64 Fabrice Bellard
515 747a0554 Tinic Uro
    /* streaming sound always should be placed just before showframe tags */
516 013e0a8f Baptiste Coudurier
    if (swf->audio_type && swf->audio_in_pos) {
517 747a0554 Tinic Uro
        put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
518 013e0a8f Baptiste Coudurier
        put_le16(pb, swf->sound_samples);
519
        put_le16(pb, 0); // seek samples
520
        put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
521 747a0554 Tinic Uro
        put_swf_end_tag(s);
522 115329f1 Diego Biurrun
523 747a0554 Tinic Uro
        /* update FIFO */
524 013e0a8f Baptiste Coudurier
        swf->sound_samples = 0;
525
        swf->audio_in_pos = 0;
526 747a0554 Tinic Uro
    }
527
528 de6d9b64 Fabrice Bellard
    /* output the frame */
529
    put_swf_tag(s, TAG_SHOWFRAME);
530
    put_swf_end_tag(s);
531 115329f1 Diego Biurrun
532 899681cd Björn Axelsson
    put_flush_packet(s->pb);
533 115329f1 Diego Biurrun
534 de6d9b64 Fabrice Bellard
    return 0;
535
}
536
537 115329f1 Diego Biurrun
static int swf_write_audio(AVFormatContext *s,
538 747a0554 Tinic Uro
                           AVCodecContext *enc, const uint8_t *buf, int size)
539 de6d9b64 Fabrice Bellard
{
540 747a0554 Tinic Uro
    SWFContext *swf = s->priv_data;
541 de6d9b64 Fabrice Bellard
542 747a0554 Tinic Uro
    /* Flash Player limit */
543 5fcf2df3 Baptiste Coudurier
    if (swf->swf_frame_number == 16000) {
544 bc874dae Michel Bardiaux
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
545 747a0554 Tinic Uro
    }
546
547 013e0a8f Baptiste Coudurier
    if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
548
        av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
549
        return -1;
550 747a0554 Tinic Uro
    }
551
552 013e0a8f Baptiste Coudurier
    memcpy(swf->audio_fifo +  swf->audio_in_pos, buf, size);
553
    swf->audio_in_pos += size;
554
    swf->sound_samples += enc->frame_size;
555
556 747a0554 Tinic Uro
    /* if audio only stream make sure we add swf frames */
557 5fcf2df3 Baptiste Coudurier
    if (swf->video_type == 0) {
558 747a0554 Tinic Uro
        swf_write_video(s, enc, 0, 0);
559
    }
560 de6d9b64 Fabrice Bellard
561
    return 0;
562
}
563
564 e928649b Michael Niedermayer
static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
565 de6d9b64 Fabrice Bellard
{
566 01f4895c Michael Niedermayer
    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
567 de6d9b64 Fabrice Bellard
    if (codec->codec_type == CODEC_TYPE_AUDIO)
568 e928649b Michael Niedermayer
        return swf_write_audio(s, codec, pkt->data, pkt->size);
569 de6d9b64 Fabrice Bellard
    else
570 e928649b Michael Niedermayer
        return swf_write_video(s, codec, pkt->data, pkt->size);
571 de6d9b64 Fabrice Bellard
}
572
573
static int swf_write_trailer(AVFormatContext *s)
574
{
575
    SWFContext *swf = s->priv_data;
576 899681cd Björn Axelsson
    ByteIOContext *pb = s->pb;
577 de6d9b64 Fabrice Bellard
    AVCodecContext *enc, *video_enc;
578
    int file_size, i;
579
580
    video_enc = NULL;
581
    for(i=0;i<s->nb_streams;i++) {
582 01f4895c Michael Niedermayer
        enc = s->streams[i]->codec;
583 de6d9b64 Fabrice Bellard
        if (enc->codec_type == CODEC_TYPE_VIDEO)
584
            video_enc = enc;
585
    }
586
587
    put_swf_tag(s, TAG_END);
588
    put_swf_end_tag(s);
589 115329f1 Diego Biurrun
590 899681cd Björn Axelsson
    put_flush_packet(s->pb);
591 de6d9b64 Fabrice Bellard
592
    /* patch file size and number of frames if not streamed */
593 899681cd Björn Axelsson
    if (!url_is_streamed(s->pb) && video_enc) {
594 de6d9b64 Fabrice Bellard
        file_size = url_ftell(pb);
595
        url_fseek(pb, 4, SEEK_SET);
596
        put_le32(pb, file_size);
597
        url_fseek(pb, swf->duration_pos, SEEK_SET);
598
        put_le16(pb, video_enc->frame_number);
599 3439dc95 Baptiste Coudurier
        url_fseek(pb, file_size, SEEK_SET);
600 de6d9b64 Fabrice Bellard
    }
601
    return 0;
602
}
603 a9e35095 Diego Biurrun
#endif //CONFIG_MUXERS
604 de6d9b64 Fabrice Bellard
605 747a0554 Tinic Uro
/*********************************************/
606
/* Extract FLV encoded frame and MP3 from swf
607
   Note that the detection of the real frame
608
   is inaccurate at this point as it can be
609 115329f1 Diego Biurrun
   quite tricky to determine, you almost certainly
610 747a0554 Tinic Uro
   will get a bad audio/video sync */
611 de6d9b64 Fabrice Bellard
612
static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
613
{
614
    int tag, len;
615 115329f1 Diego Biurrun
616 de6d9b64 Fabrice Bellard
    if (url_feof(pb))
617
        return -1;
618
619
    tag = get_le16(pb);
620
    len = tag & 0x3f;
621
    tag = tag >> 6;
622
    if (len == 0x3f) {
623
        len = get_le32(pb);
624
    }
625 e227d197 Alex Beregszaszi
//    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
626 de6d9b64 Fabrice Bellard
    *len_ptr = len;
627
    return tag;
628
}
629
630 c9a65ca8 Fabrice Bellard
631
static int swf_probe(AVProbeData *p)
632
{
633
    /* check file header */
634 e227d197 Alex Beregszaszi
    if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
635 17269bdf Fabrice Bellard
        p->buf[2] == 'S')
636 c9a65ca8 Fabrice Bellard
        return AVPROBE_SCORE_MAX;
637
    else
638
        return 0;
639
}
640
641 de6d9b64 Fabrice Bellard
static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
642
{
643 2ab573cd Baptiste Coudurier
    SWFContext *swf = s->priv_data;
644 899681cd Björn Axelsson
    ByteIOContext *pb = s->pb;
645 4f0a9956 Baptiste Coudurier
    int nbits, len, tag;
646 747a0554 Tinic Uro
647 e227d197 Alex Beregszaszi
    tag = get_be32(pb) & 0xffffff00;
648
649 5fcf2df3 Baptiste Coudurier
    if (tag == MKBETAG('C', 'W', 'S', 0)) {
650 bb270c08 Diego Biurrun
        av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
651 6f3e0b21 Panagiotis Issaris
        return AVERROR(EIO);
652 e227d197 Alex Beregszaszi
    }
653
    if (tag != MKBETAG('F', 'W', 'S', 0))
654 6f3e0b21 Panagiotis Issaris
        return AVERROR(EIO);
655 de6d9b64 Fabrice Bellard
    get_le32(pb);
656
    /* skip rectangle size */
657
    nbits = get_byte(pb) >> 3;
658
    len = (4 * nbits - 3 + 7) / 8;
659
    url_fskip(pb, len);
660 b912ef3f Baptiste Coudurier
    swf->frame_rate = get_le16(pb); /* 8.8 fixed */
661 de6d9b64 Fabrice Bellard
    get_le16(pb); /* frame count */
662 115329f1 Diego Biurrun
663 747a0554 Tinic Uro
    swf->samples_per_frame = 0;
664 c6f05d81 Baptiste Coudurier
    s->ctx_flags |= AVFMTCTX_NOHEADER;
665
    return 0;
666
}
667
668
static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
669
{
670
    SWFContext *swf = s->priv_data;
671 899681cd Björn Axelsson
    ByteIOContext *pb = s->pb;
672 c6f05d81 Baptiste Coudurier
    AVStream *vst = NULL, *ast = NULL, *st = 0;
673
    int tag, len, i, frame, v;
674 747a0554 Tinic Uro
675 de6d9b64 Fabrice Bellard
    for(;;) {
676
        tag = get_swf_tag(pb, &len);
677 c6f05d81 Baptiste Coudurier
        if (tag < 0)
678
            return AVERROR(EIO);
679 5fcf2df3 Baptiste Coudurier
        if (tag == TAG_VIDEOSTREAM && !vst) {
680 432cef76 Baptiste Coudurier
            int ch_id = get_le16(pb);
681 747a0554 Tinic Uro
            get_le16(pb);
682
            get_le16(pb);
683
            get_le16(pb);
684
            get_byte(pb);
685
            /* Check for FLV1 */
686 432cef76 Baptiste Coudurier
            vst = av_new_stream(s, ch_id);
687 e55a4dd3 Baptiste Coudurier
            if (!vst)
688
                return -1;
689 b4bcf810 Baptiste Coudurier
            vst->codec->codec_type = CODEC_TYPE_VIDEO;
690
            vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
691 c6f05d81 Baptiste Coudurier
            av_set_pts_info(vst, 64, 256, swf->frame_rate);
692
            vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
693
            len -= 10;
694 5fcf2df3 Baptiste Coudurier
        } else if ((tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) && !ast) {
695 de6d9b64 Fabrice Bellard
            /* streaming found */
696 8f36d4ba Baptiste Coudurier
            int sample_rate_code;
697 de6d9b64 Fabrice Bellard
            get_byte(pb);
698
            v = get_byte(pb);
699 747a0554 Tinic Uro
            swf->samples_per_frame = get_le16(pb);
700 5b1e5dce Baptiste Coudurier
            ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
701 e55a4dd3 Baptiste Coudurier
            if (!ast)
702
                return -1;
703 5b1e5dce Baptiste Coudurier
            swf->audio_stream_index = ast->index;
704 ec54839a Baptiste Coudurier
            ast->codec->channels = 1 + (v&1);
705
            ast->codec->codec_type = CODEC_TYPE_AUDIO;
706 dd8a46d9 Baptiste Coudurier
            ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
707 57004ff1 Aurelien Jacobs
            ast->need_parsing = AVSTREAM_PARSE_FULL;
708 8f36d4ba Baptiste Coudurier
            sample_rate_code= (v>>2) & 3;
709
            if (!sample_rate_code)
710 6f3e0b21 Panagiotis Issaris
                return AVERROR(EIO);
711 8f36d4ba Baptiste Coudurier
            ast->codec->sample_rate = 11025 << (sample_rate_code-1);
712 dc13d0b5 Baptiste Coudurier
            av_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
713 c6f05d81 Baptiste Coudurier
            len -= 4;
714 c78ed542 Baptiste Coudurier
        } else if (tag == TAG_VIDEOFRAME) {
715 432cef76 Baptiste Coudurier
            int ch_id = get_le16(pb);
716 655254f0 Baptiste Coudurier
            len -= 2;
717 5fcf2df3 Baptiste Coudurier
            for(i=0; i<s->nb_streams; i++) {
718 bb270c08 Diego Biurrun
                st = s->streams[i];
719 432cef76 Baptiste Coudurier
                if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
720
                    frame = get_le16(pb);
721 655254f0 Baptiste Coudurier
                    av_get_packet(pb, pkt, len-2);
722 b912ef3f Baptiste Coudurier
                    pkt->pts = frame;
723 432cef76 Baptiste Coudurier
                    pkt->stream_index = st->index;
724
                    return pkt->size;
725 747a0554 Tinic Uro
                }
726 115329f1 Diego Biurrun
            }
727 747a0554 Tinic Uro
        } else if (tag == TAG_STREAMBLOCK) {
728 5b1e5dce Baptiste Coudurier
            st = s->streams[swf->audio_stream_index];
729
            if (st->codec->codec_id == CODEC_ID_MP3) {
730
                url_fskip(pb, 4);
731
                av_get_packet(pb, pkt, len-4);
732 dd8a46d9 Baptiste Coudurier
            } else { // ADPCM, PCM
733
                av_get_packet(pb, pkt, len);
734 747a0554 Tinic Uro
            }
735 dd8a46d9 Baptiste Coudurier
            pkt->stream_index = st->index;
736
            return pkt->size;
737 a0dc1ccd Baptiste Coudurier
        } else if (tag == TAG_JPEG2) {
738
            for (i=0; i<s->nb_streams; i++) {
739
                st = s->streams[i];
740 c6f05d81 Baptiste Coudurier
                if (st->id == -2)
741
                    break;
742
            }
743
            if (i == s->nb_streams) {
744
                vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
745 e55a4dd3 Baptiste Coudurier
                if (!vst)
746
                    return -1;
747 c6f05d81 Baptiste Coudurier
                vst->codec->codec_type = CODEC_TYPE_VIDEO;
748
                vst->codec->codec_id = CODEC_ID_MJPEG;
749
                av_set_pts_info(vst, 64, 256, swf->frame_rate);
750
                vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
751
                st = vst;
752
            }
753 c78ed542 Baptiste Coudurier
            get_le16(pb); /* BITMAP_ID */
754
            av_new_packet(pkt, len-2);
755
            get_buffer(pb, pkt->data, 4);
756 1f794d69 Baptiste Coudurier
            if (AV_RB32(pkt->data) == 0xffd8ffd9 ||
757
                AV_RB32(pkt->data) == 0xffd9ffd8) {
758 c78ed542 Baptiste Coudurier
                /* old SWF files containing SOI/EOI as data start */
759 1f794d69 Baptiste Coudurier
                /* files created by swink have reversed tag */
760 c78ed542 Baptiste Coudurier
                pkt->size -= 4;
761
                get_buffer(pb, pkt->data, pkt->size);
762
            } else {
763
                get_buffer(pb, pkt->data + 4, pkt->size - 4);
764
            }
765
            pkt->stream_index = st->index;
766
            return pkt->size;
767 de6d9b64 Fabrice Bellard
        }
768 655254f0 Baptiste Coudurier
        url_fskip(pb, len);
769 de6d9b64 Fabrice Bellard
    }
770
    return 0;
771
}
772
773
static int swf_read_close(AVFormatContext *s)
774
{
775 c78ed542 Baptiste Coudurier
    return 0;
776 de6d9b64 Fabrice Bellard
}
777
778 ff70e601 Måns Rullgård
#ifdef CONFIG_SWF_DEMUXER
779
AVInputFormat swf_demuxer = {
780 c9a65ca8 Fabrice Bellard
    "swf",
781
    "Flash format",
782 747a0554 Tinic Uro
    sizeof(SWFContext),
783 c9a65ca8 Fabrice Bellard
    swf_probe,
784
    swf_read_header,
785
    swf_read_packet,
786
    swf_read_close,
787
};
788 ff70e601 Måns Rullgård
#endif
789
#ifdef CONFIG_SWF_MUXER
790
AVOutputFormat swf_muxer = {
791 de6d9b64 Fabrice Bellard
    "swf",
792
    "Flash format",
793
    "application/x-shockwave-flash",
794
    "swf",
795 c9a65ca8 Fabrice Bellard
    sizeof(SWFContext),
796 747a0554 Tinic Uro
    CODEC_ID_MP3,
797
    CODEC_ID_FLV1,
798 de6d9b64 Fabrice Bellard
    swf_write_header,
799
    swf_write_packet,
800
    swf_write_trailer,
801
};
802 ff70e601 Måns Rullgård
#endif
803 dfb400a8 Paul Egan
#ifdef CONFIG_AVM2_MUXER
804
AVOutputFormat avm2_muxer = {
805
    "avm2",
806
    "Flash 9 (AVM2) format",
807
    "application/x-shockwave-flash",
808 afecbec2 Baptiste Coudurier
    NULL,
809 dfb400a8 Paul Egan
    sizeof(SWFContext),
810
    CODEC_ID_MP3,
811
    CODEC_ID_FLV1,
812
    swf_write_header,
813
    swf_write_packet,
814
    swf_write_trailer,
815
};
816
#endif