Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 764ef400

History | View | Annotate | Download (14.3 KB)

1
/*
2
 * Flash Compatible Streaming Format
3
 * Copyright (c) 2000 Fabrice Bellard.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19
#include "avformat.h"
20

    
21
/* should have a generic way to indicate probable size */
22
#define DUMMY_FILE_SIZE   (100 * 1024 * 1024)
23
#define DUMMY_DURATION    600 /* in seconds */
24

    
25
#define TAG_END           0
26
#define TAG_SHOWFRAME     1
27
#define TAG_DEFINESHAPE   2
28
#define TAG_FREECHARACTER 3
29
#define TAG_PLACEOBJECT   4
30
#define TAG_REMOVEOBJECT  5
31
#define TAG_STREAMHEAD    18
32
#define TAG_STREAMBLOCK   19
33
#define TAG_JPEG2         21
34

    
35
#define TAG_LONG         0x100
36

    
37
/* flags for shape definition */
38
#define FLAG_MOVETO      0x01
39
#define FLAG_SETFILL0    0x02
40
#define FLAG_SETFILL1    0x04
41

    
42
/* character id used */
43
#define BITMAP_ID 0
44
#define SHAPE_ID  1
45

    
46
typedef struct {
47
    offset_t duration_pos;
48
    offset_t tag_pos;
49
    int tag;
50
} SWFContext;
51

    
52
#ifdef CONFIG_ENCODERS
53
static void put_swf_tag(AVFormatContext *s, int tag)
54
{
55
    SWFContext *swf = s->priv_data;
56
    ByteIOContext *pb = &s->pb;
57

    
58
    swf->tag_pos = url_ftell(pb);
59
    swf->tag = tag;
60
    /* reserve some room for the tag */
61
    if (tag & TAG_LONG) {
62
        put_le16(pb, 0);
63
        put_le32(pb, 0);
64
    } else {
65
        put_le16(pb, 0);
66
    }
67
}
68

    
69
static void put_swf_end_tag(AVFormatContext *s)
70
{
71
    SWFContext *swf = s->priv_data;
72
    ByteIOContext *pb = &s->pb;
73
    offset_t pos;
74
    int tag_len, tag;
75

    
76
    pos = url_ftell(pb);
77
    tag_len = pos - swf->tag_pos - 2;
78
    tag = swf->tag;
79
    url_fseek(pb, swf->tag_pos, SEEK_SET);
80
    if (tag & TAG_LONG) {
81
        tag &= ~TAG_LONG;
82
        put_le16(pb, (tag << 6) | 0x3f);
83
        put_le32(pb, tag_len - 4);
84
    } else {
85
        assert(tag_len < 0x3f);
86
        put_le16(pb, (tag << 6) | tag_len);
87
    }
88
    url_fseek(pb, pos, SEEK_SET);
89
}
90

    
91
static inline void max_nbits(int *nbits_ptr, int val)
92
{
93
    int n;
94

    
95
    if (val == 0)
96
        return;
97
    val = abs(val);
98
    n = 1;
99
    while (val != 0) {
100
        n++;
101
        val >>= 1;
102
    }
103
    if (n > *nbits_ptr)
104
        *nbits_ptr = n;
105
}
106

    
107
static void put_swf_rect(ByteIOContext *pb, 
108
                         int xmin, int xmax, int ymin, int ymax)
109
{
110
    PutBitContext p;
111
    uint8_t buf[256];
112
    int nbits, mask;
113

    
114
    init_put_bits(&p, buf, sizeof(buf));
115
    
116
    nbits = 0;
117
    max_nbits(&nbits, xmin);
118
    max_nbits(&nbits, xmax);
119
    max_nbits(&nbits, ymin);
120
    max_nbits(&nbits, ymax);
121
    mask = (1 << nbits) - 1;
122

    
123
    /* rectangle info */
124
    put_bits(&p, 5, nbits);
125
    put_bits(&p, nbits, xmin & mask);
126
    put_bits(&p, nbits, xmax & mask);
127
    put_bits(&p, nbits, ymin & mask);
128
    put_bits(&p, nbits, ymax & mask);
129
    
130
    flush_put_bits(&p);
131
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
132
}
133

    
134
static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
135
{
136
    int nbits, mask;
137

    
138
    put_bits(pb, 1, 1); /* edge */
139
    put_bits(pb, 1, 1); /* line select */
140
    nbits = 2;
141
    max_nbits(&nbits, dx);
142
    max_nbits(&nbits, dy);
143

    
144
    mask = (1 << nbits) - 1;
145
    put_bits(pb, 4, nbits - 2); /* 16 bits precision */
146
    if (dx == 0) {
147
      put_bits(pb, 1, 0); 
148
      put_bits(pb, 1, 1); 
149
      put_bits(pb, nbits, dy & mask);
150
    } else if (dy == 0) {
151
      put_bits(pb, 1, 0); 
152
      put_bits(pb, 1, 0); 
153
      put_bits(pb, nbits, dx & mask);
154
    } else {
155
      put_bits(pb, 1, 1); 
156
      put_bits(pb, nbits, dx & mask);
157
      put_bits(pb, nbits, dy & mask);
158
    }
159
}
160

    
161
#define FRAC_BITS 16
162

    
163
/* put matrix (not size optimized */
164
static void put_swf_matrix(ByteIOContext *pb,
165
                           int a, int b, int c, int d, int tx, int ty)
166
{
167
    PutBitContext p;
168
    uint8_t buf[256];
169

    
170
    init_put_bits(&p, buf, sizeof(buf));
171
    
172
    put_bits(&p, 1, 1); /* a, d present */
173
    put_bits(&p, 5, 20); /* nb bits */
174
    put_bits(&p, 20, a);
175
    put_bits(&p, 20, d);
176
    
177
    put_bits(&p, 1, 1); /* b, c present */
178
    put_bits(&p, 5, 20); /* nb bits */
179
    put_bits(&p, 20, c);
180
    put_bits(&p, 20, b);
181

    
182
    put_bits(&p, 5, 20); /* nb bits */
183
    put_bits(&p, 20, tx);
184
    put_bits(&p, 20, ty);
185

    
186
    flush_put_bits(&p);
187
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
188
}
189

    
190
/* XXX: handle audio only */
191
static int swf_write_header(AVFormatContext *s)
192
{
193
    SWFContext *swf;
194
    ByteIOContext *pb = &s->pb;
195
    AVCodecContext *enc, *audio_enc, *video_enc;
196
    PutBitContext p;
197
    uint8_t buf1[256];
198
    int i, width, height, rate, rate_base;
199

    
200
    swf = av_malloc(sizeof(SWFContext));
201
    if (!swf)
202
        return -1;
203
    s->priv_data = swf;
204

    
205
    video_enc = NULL;
206
    audio_enc = NULL;
207
    for(i=0;i<s->nb_streams;i++) {
208
        enc = &s->streams[i]->codec;
209
        if (enc->codec_type == CODEC_TYPE_AUDIO)
210
            audio_enc = enc;
211
        else
212
            video_enc = enc;
213
    }
214

    
215
    if (!video_enc) {
216
        /* currenty, cannot work correctly if audio only */
217
        width = 320;
218
        height = 200;
219
        rate = 10;
220
        rate_base= 1;
221
    } else {
222
        width = video_enc->width;
223
        height = video_enc->height;
224
        rate = video_enc->frame_rate;
225
        rate_base = video_enc->frame_rate_base;
226
    }
227

    
228
    put_tag(pb, "FWS");
229
    put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
230
    put_le32(pb, DUMMY_FILE_SIZE); /* dummy size 
231
                                      (will be patched if not streamed) */ 
232

    
233
    put_swf_rect(pb, 0, width, 0, height);
234
    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
235
    swf->duration_pos = url_ftell(pb);
236
    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
237
    
238
    /* define a shape with the jpeg inside */
239

    
240
    put_swf_tag(s, TAG_DEFINESHAPE);
241

    
242
    put_le16(pb, SHAPE_ID); /* ID of shape */
243
    /* bounding rectangle */
244
    put_swf_rect(pb, 0, width, 0, height);
245
    /* style info */
246
    put_byte(pb, 1); /* one fill style */
247
    put_byte(pb, 0x41); /* clipped bitmap fill */
248
    put_le16(pb, BITMAP_ID); /* bitmap ID */
249
    /* position of the bitmap */
250
    put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0, 
251
                   0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
252
    put_byte(pb, 0); /* no line style */
253
    
254
    /* shape drawing */
255
    init_put_bits(&p, buf1, sizeof(buf1));
256
    put_bits(&p, 4, 1); /* one fill bit */
257
    put_bits(&p, 4, 0); /* zero line bit */
258
    
259
    put_bits(&p, 1, 0); /* not an edge */
260
    put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
261
    put_bits(&p, 5, 1); /* nbits */
262
    put_bits(&p, 1, 0); /* X */
263
    put_bits(&p, 1, 0); /* Y */
264
    put_bits(&p, 1, 1); /* set fill style 1 */
265
    
266
    /* draw the rectangle ! */
267
    put_swf_line_edge(&p, width, 0);
268
    put_swf_line_edge(&p, 0, height);
269
    put_swf_line_edge(&p, -width, 0);
270
    put_swf_line_edge(&p, 0, -height);
271
    
272
    /* end of shape */
273
    put_bits(&p, 1, 0); /* not an edge */
274
    put_bits(&p, 5, 0);
275

    
276
    flush_put_bits(&p);
277
    put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
278

    
279
    put_swf_end_tag(s);
280

    
281
    
282
    if (audio_enc) {
283
        int v;
284

    
285
        /* start sound */
286

    
287
        v = 0;
288
        switch(audio_enc->sample_rate) {
289
        case 11025:
290
            v |= 1 << 2;
291
            break;
292
        case 22050:
293
            v |= 2 << 2;
294
            break;
295
        case 44100:
296
            v |= 3 << 2;
297
            break;
298
        default:
299
            /* not supported */
300
            av_free(swf);
301
            return -1;
302
        }
303
        if (audio_enc->channels == 2)
304
            v |= 1;
305
        v |= 0x20; /* mp3 compressed */
306
        v |= 0x02; /* 16 bits */
307
        
308
        put_swf_tag(s, TAG_STREAMHEAD);
309
        put_byte(&s->pb, 0);
310
        put_byte(&s->pb, v);
311
        put_le16(&s->pb, (audio_enc->sample_rate * rate_base) / rate);  /* avg samples per frame */
312
        
313
        
314
        put_swf_end_tag(s);
315
    }
316

    
317
    put_flush_packet(&s->pb);
318
    return 0;
319
}
320

    
321
static int swf_write_video(AVFormatContext *s, 
322
                           AVCodecContext *enc, const uint8_t *buf, int size)
323
{
324
    ByteIOContext *pb = &s->pb;
325
    static int tag_id = 0;
326

    
327
    if (enc->frame_number > 1) {
328
        /* remove the shape */
329
        put_swf_tag(s, TAG_REMOVEOBJECT);
330
        put_le16(pb, SHAPE_ID); /* shape ID */
331
        put_le16(pb, 1); /* depth */
332
        put_swf_end_tag(s);
333
        
334
        /* free the bitmap */
335
        put_swf_tag(s, TAG_FREECHARACTER);
336
        put_le16(pb, BITMAP_ID);
337
        put_swf_end_tag(s);
338
    }
339

    
340
    put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
341

    
342
    put_le16(pb, tag_id); /* ID of the image */
343

    
344
    /* a dummy jpeg header seems to be required */
345
    put_byte(pb, 0xff); 
346
    put_byte(pb, 0xd8);
347
    put_byte(pb, 0xff);
348
    put_byte(pb, 0xd9);
349
    /* write the jpeg image */
350
    put_buffer(pb, buf, size);
351

    
352
    put_swf_end_tag(s);
353

    
354
    /* draw the shape */
355

    
356
    put_swf_tag(s, TAG_PLACEOBJECT);
357
    put_le16(pb, SHAPE_ID); /* shape ID */
358
    put_le16(pb, 1); /* depth */
359
    put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
360
    put_swf_end_tag(s);
361
    
362
    /* output the frame */
363
    put_swf_tag(s, TAG_SHOWFRAME);
364
    put_swf_end_tag(s);
365
    
366
    put_flush_packet(&s->pb);
367
    return 0;
368
}
369

    
370
static int swf_write_audio(AVFormatContext *s, const uint8_t *buf, int size)
371
{
372
    ByteIOContext *pb = &s->pb;
373

    
374
    put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
375

    
376
    put_buffer(pb, buf, size);
377
    
378
    put_swf_end_tag(s);
379
    put_flush_packet(&s->pb);
380
    return 0;
381
}
382

    
383
static int swf_write_packet(AVFormatContext *s, int stream_index, 
384
                           const uint8_t *buf, int size, int64_t pts)
385
{
386
    AVCodecContext *codec = &s->streams[stream_index]->codec;
387
    if (codec->codec_type == CODEC_TYPE_AUDIO)
388
        return swf_write_audio(s, buf, size);
389
    else
390
        return swf_write_video(s, codec, buf, size);
391
}
392

    
393
static int swf_write_trailer(AVFormatContext *s)
394
{
395
    SWFContext *swf = s->priv_data;
396
    ByteIOContext *pb = &s->pb;
397
    AVCodecContext *enc, *video_enc;
398
    int file_size, i;
399

    
400
    video_enc = NULL;
401
    for(i=0;i<s->nb_streams;i++) {
402
        enc = &s->streams[i]->codec;
403
        if (enc->codec_type == CODEC_TYPE_VIDEO)
404
            video_enc = enc;
405
    }
406

    
407
    put_swf_tag(s, TAG_END);
408
    put_swf_end_tag(s);
409
    
410
    put_flush_packet(&s->pb);
411

    
412
    /* patch file size and number of frames if not streamed */
413
    if (!url_is_streamed(&s->pb) && video_enc) {
414
        file_size = url_ftell(pb);
415
        url_fseek(pb, 4, SEEK_SET);
416
        put_le32(pb, file_size);
417
        url_fseek(pb, swf->duration_pos, SEEK_SET);
418
        put_le16(pb, video_enc->frame_number);
419
    }
420
    return 0;
421
}
422
#endif //CONFIG_ENCODERS
423

    
424
/***********************************/
425
/* just to extract MP3 from swf */
426

    
427
static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
428
{
429
    int tag, len;
430
    
431
    if (url_feof(pb))
432
        return -1;
433

    
434
    tag = get_le16(pb);
435
    len = tag & 0x3f;
436
    tag = tag >> 6;
437
    if (len == 0x3f) {
438
        len = get_le32(pb);
439
    }
440
    *len_ptr = len;
441
    return tag;
442
}
443

    
444

    
445
static int swf_probe(AVProbeData *p)
446
{
447
    /* check file header */
448
    if (p->buf_size <= 16)
449
        return 0;
450
    if (p->buf[0] == 'F' && p->buf[1] == 'W' &&
451
        p->buf[2] == 'S')
452
        return AVPROBE_SCORE_MAX;
453
    else
454
        return 0;
455
}
456

    
457
static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
458
{
459
    ByteIOContext *pb = &s->pb;
460
    int nbits, len, frame_rate, tag, v;
461
    AVStream *st;
462

    
463
    if ((get_be32(pb) & 0xffffff00) != MKBETAG('F', 'W', 'S', 0))
464
        return -EIO;
465
    get_le32(pb);
466
    /* skip rectangle size */
467
    nbits = get_byte(pb) >> 3;
468
    len = (4 * nbits - 3 + 7) / 8;
469
    url_fskip(pb, len);
470
    frame_rate = get_le16(pb);
471
    get_le16(pb); /* frame count */
472

    
473
    for(;;) {
474
        tag = get_swf_tag(pb, &len);
475
        if (tag < 0) {
476
            fprintf(stderr, "No streaming found in SWF\n");
477
            return -EIO;
478
        }
479
        if (tag == TAG_STREAMHEAD) {
480
            /* streaming found */
481
            get_byte(pb);
482
            v = get_byte(pb);
483
            get_le16(pb);
484
            /* if mp3 streaming found, OK */
485
            if ((v & 0x20) != 0) {
486
                st = av_new_stream(s, 0);
487
                if (!st)
488
                    return -ENOMEM;
489

    
490
                if (v & 0x01)
491
                    st->codec.channels = 2;
492
                else
493
                    st->codec.channels = 1;
494

    
495
                switch((v>> 2) & 0x03) {
496
                case 1:
497
                    st->codec.sample_rate = 11025;
498
                    break;
499
                case 2:
500
                    st->codec.sample_rate = 22050;
501
                    break;
502
                case 3:
503
                    st->codec.sample_rate = 44100;
504
                    break;
505
                default:
506
                    av_free(st);
507
                    return -EIO;
508
                }
509
                st->codec.codec_type = CODEC_TYPE_AUDIO;
510
                st->codec.codec_id = CODEC_ID_MP2;
511
                break;
512
            }
513
        } else {
514
            url_fskip(pb, len);
515
        }
516
    }
517

    
518
    return 0;
519
}
520

    
521
static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
522
{
523
    ByteIOContext *pb = &s->pb;
524
    int tag, len;
525
    
526
    for(;;) {
527
        tag = get_swf_tag(pb, &len);
528
        if (tag < 0) 
529
            return -EIO;
530
        if (tag == TAG_STREAMBLOCK) {
531
            av_new_packet(pkt, len);
532
            get_buffer(pb, pkt->data, pkt->size);
533
            break;
534
        } else {
535
            url_fskip(pb, len);
536
        }
537
    }
538
    return 0;
539
}
540

    
541
static int swf_read_close(AVFormatContext *s)
542
{
543
     return 0;
544
}
545

    
546
static AVInputFormat swf_iformat = {
547
    "swf",
548
    "Flash format",
549
    0,
550
    swf_probe,
551
    swf_read_header,
552
    swf_read_packet,
553
    swf_read_close,
554
};
555

    
556
#ifdef CONFIG_ENCODERS
557
static AVOutputFormat swf_oformat = {
558
    "swf",
559
    "Flash format",
560
    "application/x-shockwave-flash",
561
    "swf",
562
    sizeof(SWFContext),
563
    CODEC_ID_MP2,
564
    CODEC_ID_MJPEG,
565
    swf_write_header,
566
    swf_write_packet,
567
    swf_write_trailer,
568
};
569
#endif //CONFIG_ENCODERS
570

    
571
int swf_init(void)
572
{
573
    av_register_input_format(&swf_iformat);
574
#ifdef CONFIG_ENCODERS
575
    av_register_output_format(&swf_oformat);
576
#endif //CONFIG_ENCODERS
577
    return 0;
578
}