Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ b973f9ad

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