Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ afecbec2

History | View | Annotate | Download (23.3 KB)

1
/*
2
 * Flash Compatible Streaming Format
3
 * Copyright (c) 2000 Fabrice Bellard.
4
 * Copyright (c) 2003 Tinic Uro.
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
#include "avformat.h"
23
#include "bitstream.h"
24
#include "riff.h"    /* for CodecTag */
25

    
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
#define TAG_STREAMHEAD    18
37
#define TAG_STREAMBLOCK   19
38
#define TAG_JPEG2         21
39
#define TAG_PLACEOBJECT2  26
40
#define TAG_STREAMHEAD2   45
41
#define TAG_VIDEOSTREAM   60
42
#define TAG_VIDEOFRAME    61
43
#define TAG_FILEATTRIBUTES 69
44

    
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
#define AUDIO_FIFO_SIZE 65536
53

    
54
/* character id used */
55
#define BITMAP_ID 0
56
#define VIDEO_ID 0
57
#define SHAPE_ID  1
58

    
59
#undef NDEBUG
60
#include <assert.h>
61

    
62
typedef struct {
63
    int audio_stream_index;
64
    offset_t duration_pos;
65
    offset_t tag_pos;
66

    
67
    int samples_per_frame;
68
    int sound_samples;
69
    int swf_frame_number;
70
    int video_frame_number;
71
    int frame_rate;
72
    int tag;
73

    
74
    uint8_t audio_fifo[AUDIO_FIFO_SIZE];
75
    int audio_in_pos;
76

    
77
    int video_type;
78
    int audio_type;
79
} SWFContext;
80

    
81
static const AVCodecTag swf_codec_tags[] = {
82
    {CODEC_ID_FLV1, 0x02},
83
    {CODEC_ID_VP6F, 0x04},
84
    {0, 0},
85
};
86

    
87
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
#ifdef CONFIG_MUXERS
97
static void put_swf_tag(AVFormatContext *s, int tag)
98
{
99
    SWFContext *swf = s->priv_data;
100
    ByteIOContext *pb = s->pb;
101

    
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
    ByteIOContext *pb = s->pb;
117
    offset_t pos;
118
    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
static void put_swf_rect(ByteIOContext *pb,
152
                         int xmin, int xmax, int ymin, int ymax)
153
{
154
    PutBitContext p;
155
    uint8_t buf[256];
156
    int nbits, mask;
157

    
158
    init_put_bits(&p, buf, sizeof(buf));
159

    
160
    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

    
174
    flush_put_bits(&p);
175
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
176
}
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
        put_bits(pb, 1, 0);
192
        put_bits(pb, 1, 1);
193
        put_bits(pb, nbits, dy & mask);
194
    } else if (dy == 0) {
195
        put_bits(pb, 1, 0);
196
        put_bits(pb, 1, 0);
197
        put_bits(pb, nbits, dx & mask);
198
    } else {
199
        put_bits(pb, 1, 1);
200
        put_bits(pb, nbits, dx & mask);
201
        put_bits(pb, nbits, dy & mask);
202
    }
203
}
204

    
205
#define FRAC_BITS 16
206

    
207
/* put matrix */
208
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
    uint8_t buf[256];
213
    int nbits;
214

    
215
    init_put_bits(&p, buf, sizeof(buf));
216

    
217
    put_bits(&p, 1, 1); /* a, d present */
218
    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

    
225
    put_bits(&p, 1, 1); /* b, c present */
226
    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

    
240
    flush_put_bits(&p);
241
    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
242
}
243

    
244
/* */
245
static int swf_write_header(AVFormatContext *s)
246
{
247
    SWFContext *swf = s->priv_data;
248
    ByteIOContext *pb = s->pb;
249
    AVCodecContext *enc, *audio_enc, *video_enc;
250
    PutBitContext p;
251
    uint8_t buf1[256];
252
    int i, width, height, rate, rate_base;
253
    int is_avm2;
254

    
255
    swf->audio_in_pos = 0;
256
    swf->sound_samples = 0;
257
    swf->swf_frame_number = 0;
258
    swf->video_frame_number = 0;
259

    
260
    video_enc = NULL;
261
    audio_enc = NULL;
262
    for(i=0;i<s->nb_streams;i++) {
263
        enc = s->streams[i]->codec;
264
        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
                av_log(s, AV_LOG_ERROR, "SWF muxer only supports MP3\n");
273
                return -1;
274
            }
275
        } else {
276
            if (enc->codec_id == CODEC_ID_VP6F ||
277
                enc->codec_id == CODEC_ID_FLV1 ||
278
                enc->codec_id == CODEC_ID_MJPEG) {
279
                video_enc = enc;
280
            } else {
281
                av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n");
282
                return -1;
283
            }
284
        }
285
    }
286

    
287
    if (!video_enc) {
288
        /* currently, cannot work correctly if audio only */
289
        swf->video_type = 0;
290
        width = 320;
291
        height = 200;
292
        rate = 10;
293
        rate_base= 1;
294
    } else {
295
        swf->video_type = video_enc->codec_id;
296
        width = video_enc->width;
297
        height = video_enc->height;
298
        rate = video_enc->time_base.den;
299
        rate_base = video_enc->time_base.num;
300
    }
301

    
302
    if (!audio_enc) {
303
        swf->audio_type = 0;
304
        swf->samples_per_frame = (44100. * rate_base) / rate;
305
    } else {
306
        swf->audio_type = audio_enc->codec_id;
307
        swf->samples_per_frame = (audio_enc->sample_rate * rate_base) / rate;
308
    }
309

    
310
    is_avm2 = !strcmp("avm2", s->oformat->name);
311

    
312
    put_tag(pb, "FWS");
313
    if (is_avm2) {
314
        put_byte(pb, 9);
315
    } else if (video_enc && video_enc->codec_id == CODEC_ID_VP6F) {
316
        put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
317
    } else if (video_enc && video_enc->codec_id == CODEC_ID_FLV1) {
318
        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
    put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
323
                                      (will be patched if not streamed) */
324

    
325
    put_swf_rect(pb, 0, width * 20, 0, height * 20);
326
    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
327
    swf->duration_pos = url_ftell(pb);
328
    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
329

    
330
    /* 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
    /* define a shape with the jpeg inside */
338
    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
        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
        put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
352
                       0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
353
        put_byte(pb, 0); /* no line style */
354

    
355
        /* 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

    
360
        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

    
367
        /* 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

    
373
        /* end of shape */
374
        put_bits(&p, 1, 0); /* not an edge */
375
        put_bits(&p, 5, 0);
376

    
377
        flush_put_bits(&p);
378
        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
379

    
380
        put_swf_end_tag(s);
381
    }
382

    
383
    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3) {
384
        int v;
385

    
386
        /* start sound */
387
        put_swf_tag(s, TAG_STREAMHEAD2);
388

    
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
            av_log(s, AV_LOG_ERROR, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n");
403
            return -1;
404
        }
405
        v |= 0x02; /* 16 bit playback */
406
        if (audio_enc->channels == 2)
407
            v |= 0x01; /* stereo playback */
408
        put_byte(s->pb, v);
409
        v |= 0x20; /* mp3 compressed */
410
        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

    
414
        put_swf_end_tag(s);
415
    }
416

    
417
    put_flush_packet(s->pb);
418
    return 0;
419
}
420

    
421
static int swf_write_video(AVFormatContext *s,
422
                           AVCodecContext *enc, const uint8_t *buf, int size)
423
{
424
    SWFContext *swf = s->priv_data;
425
    ByteIOContext *pb = s->pb;
426

    
427
    /* Flash Player limit */
428
    if (swf->swf_frame_number == 16000) {
429
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
430
    }
431

    
432
    if (swf->video_type == CODEC_ID_VP6F ||
433
        swf->video_type == CODEC_ID_FLV1) {
434
        if (swf->video_frame_number == 0) {
435
            /* create a new video object */
436
            put_swf_tag(s, TAG_VIDEOSTREAM);
437
            put_le16(pb, VIDEO_ID);
438
            put_le16(pb, 15000); /* hard flash player limit */
439
            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
            put_le16(pb, swf->video_frame_number);
452
            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
            put_le16(pb, swf->video_frame_number);
465
            put_swf_end_tag(s);
466
        }
467

    
468
        /* set video frame data */
469
        put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
470
        put_le16(pb, VIDEO_ID);
471
        put_le16(pb, swf->video_frame_number++);
472
        put_buffer(pb, buf, size);
473
        put_swf_end_tag(s);
474
    } else if (swf->video_type == CODEC_ID_MJPEG) {
475
        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

    
488
        put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
489

    
490
        put_le16(pb, BITMAP_ID); /* ID of the image */
491

    
492
        /* 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

    
500
        put_swf_end_tag(s);
501

    
502
        /* draw the shape */
503

    
504
        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

    
513
    swf->swf_frame_number ++;
514

    
515
    /* streaming sound always should be placed just before showframe tags */
516
    if (swf->audio_type && swf->audio_in_pos) {
517
        put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
518
        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
        put_swf_end_tag(s);
522

    
523
        /* update FIFO */
524
        swf->sound_samples = 0;
525
        swf->audio_in_pos = 0;
526
    }
527

    
528
    /* output the frame */
529
    put_swf_tag(s, TAG_SHOWFRAME);
530
    put_swf_end_tag(s);
531

    
532
    put_flush_packet(s->pb);
533

    
534
    return 0;
535
}
536

    
537
static int swf_write_audio(AVFormatContext *s,
538
                           AVCodecContext *enc, const uint8_t *buf, int size)
539
{
540
    SWFContext *swf = s->priv_data;
541

    
542
    /* Flash Player limit */
543
    if (swf->swf_frame_number == 16000) {
544
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
545
    }
546

    
547
    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
    }
551

    
552
    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
    /* if audio only stream make sure we add swf frames */
557
    if (swf->video_type == 0) {
558
        swf_write_video(s, enc, 0, 0);
559
    }
560

    
561
    return 0;
562
}
563

    
564
static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
565
{
566
    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
567
    if (codec->codec_type == CODEC_TYPE_AUDIO)
568
        return swf_write_audio(s, codec, pkt->data, pkt->size);
569
    else
570
        return swf_write_video(s, codec, pkt->data, pkt->size);
571
}
572

    
573
static int swf_write_trailer(AVFormatContext *s)
574
{
575
    SWFContext *swf = s->priv_data;
576
    ByteIOContext *pb = s->pb;
577
    AVCodecContext *enc, *video_enc;
578
    int file_size, i;
579

    
580
    video_enc = NULL;
581
    for(i=0;i<s->nb_streams;i++) {
582
        enc = s->streams[i]->codec;
583
        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

    
590
    put_flush_packet(s->pb);
591

    
592
    /* patch file size and number of frames if not streamed */
593
    if (!url_is_streamed(s->pb) && video_enc) {
594
        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
        url_fseek(pb, file_size, SEEK_SET);
600
    }
601
    return 0;
602
}
603
#endif //CONFIG_MUXERS
604

    
605
/*********************************************/
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
   quite tricky to determine, you almost certainly
610
   will get a bad audio/video sync */
611

    
612
static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
613
{
614
    int tag, len;
615

    
616
    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
//    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
626
    *len_ptr = len;
627
    return tag;
628
}
629

    
630

    
631
static int swf_probe(AVProbeData *p)
632
{
633
    /* check file header */
634
    if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
635
        p->buf[2] == 'S')
636
        return AVPROBE_SCORE_MAX;
637
    else
638
        return 0;
639
}
640

    
641
static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
642
{
643
    SWFContext *swf = s->priv_data;
644
    ByteIOContext *pb = s->pb;
645
    int nbits, len, tag;
646

    
647
    tag = get_be32(pb) & 0xffffff00;
648

    
649
    if (tag == MKBETAG('C', 'W', 'S', 0)) {
650
        av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
651
        return AVERROR(EIO);
652
    }
653
    if (tag != MKBETAG('F', 'W', 'S', 0))
654
        return AVERROR(EIO);
655
    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
    swf->frame_rate = get_le16(pb); /* 8.8 fixed */
661
    get_le16(pb); /* frame count */
662

    
663
    swf->samples_per_frame = 0;
664
    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
    ByteIOContext *pb = s->pb;
672
    AVStream *vst = NULL, *ast = NULL, *st = 0;
673
    int tag, len, i, frame, v;
674

    
675
    for(;;) {
676
        tag = get_swf_tag(pb, &len);
677
        if (tag < 0)
678
            return AVERROR(EIO);
679
        if (tag == TAG_VIDEOSTREAM && !vst) {
680
            int ch_id = get_le16(pb);
681
            get_le16(pb);
682
            get_le16(pb);
683
            get_le16(pb);
684
            get_byte(pb);
685
            /* Check for FLV1 */
686
            vst = av_new_stream(s, ch_id);
687
            if (!vst)
688
                return -1;
689
            vst->codec->codec_type = CODEC_TYPE_VIDEO;
690
            vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
691
            av_set_pts_info(vst, 64, 256, swf->frame_rate);
692
            vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
693
            len -= 10;
694
        } else if ((tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) && !ast) {
695
            /* streaming found */
696
            int sample_rate_code;
697
            get_byte(pb);
698
            v = get_byte(pb);
699
            swf->samples_per_frame = get_le16(pb);
700
            ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
701
            if (!ast)
702
                return -1;
703
            swf->audio_stream_index = ast->index;
704
            ast->codec->channels = 1 + (v&1);
705
            ast->codec->codec_type = CODEC_TYPE_AUDIO;
706
            ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
707
            ast->need_parsing = AVSTREAM_PARSE_FULL;
708
            sample_rate_code= (v>>2) & 3;
709
            if (!sample_rate_code)
710
                return AVERROR(EIO);
711
            ast->codec->sample_rate = 11025 << (sample_rate_code-1);
712
            av_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
713
            len -= 4;
714
        } else if (tag == TAG_VIDEOFRAME) {
715
            int ch_id = get_le16(pb);
716
            len -= 2;
717
            for(i=0; i<s->nb_streams; i++) {
718
                st = s->streams[i];
719
                if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
720
                    frame = get_le16(pb);
721
                    av_get_packet(pb, pkt, len-2);
722
                    pkt->pts = frame;
723
                    pkt->stream_index = st->index;
724
                    return pkt->size;
725
                }
726
            }
727
        } else if (tag == TAG_STREAMBLOCK) {
728
            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
            } else { // ADPCM, PCM
733
                av_get_packet(pb, pkt, len);
734
            }
735
            pkt->stream_index = st->index;
736
            return pkt->size;
737
        } else if (tag == TAG_JPEG2) {
738
            for (i=0; i<s->nb_streams; i++) {
739
                st = s->streams[i];
740
                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
                if (!vst)
746
                    return -1;
747
                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
            get_le16(pb); /* BITMAP_ID */
754
            av_new_packet(pkt, len-2);
755
            get_buffer(pb, pkt->data, 4);
756
            if (AV_RB32(pkt->data) == 0xffd8ffd9 ||
757
                AV_RB32(pkt->data) == 0xffd9ffd8) {
758
                /* old SWF files containing SOI/EOI as data start */
759
                /* files created by swink have reversed tag */
760
                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
        }
768
        url_fskip(pb, len);
769
    }
770
    return 0;
771
}
772

    
773
static int swf_read_close(AVFormatContext *s)
774
{
775
    return 0;
776
}
777

    
778
#ifdef CONFIG_SWF_DEMUXER
779
AVInputFormat swf_demuxer = {
780
    "swf",
781
    "Flash format",
782
    sizeof(SWFContext),
783
    swf_probe,
784
    swf_read_header,
785
    swf_read_packet,
786
    swf_read_close,
787
};
788
#endif
789
#ifdef CONFIG_SWF_MUXER
790
AVOutputFormat swf_muxer = {
791
    "swf",
792
    "Flash format",
793
    "application/x-shockwave-flash",
794
    "swf",
795
    sizeof(SWFContext),
796
    CODEC_ID_MP3,
797
    CODEC_ID_FLV1,
798
    swf_write_header,
799
    swf_write_packet,
800
    swf_write_trailer,
801
};
802
#endif
803
#ifdef CONFIG_AVM2_MUXER
804
AVOutputFormat avm2_muxer = {
805
    "avm2",
806
    "Flash 9 (AVM2) format",
807
    "application/x-shockwave-flash",
808
    NULL,
809
    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