Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 5095aaa9

History | View | Annotate | Download (23.7 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

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

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

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

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

    
66
    int samples_per_frame;
67
    int sound_samples;
68
    int swf_frame_number;
69
    int video_frame_number;
70
    int ms_per_frame;
71
    int tag;
72

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

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

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

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

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

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

    
159
    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

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

    
204
#define FRAC_BITS 16
205

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

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

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

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

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

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

    
253
    swf->audio_in_pos = 0;
254
    swf->sound_samples = 0;
255
    swf->swf_frame_number = 0;
256
    swf->video_frame_number = 0;
257

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

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

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

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

    
319
    put_swf_rect(pb, 0, width * 20, 0, height * 20);
320
    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
321
    swf->duration_pos = url_ftell(pb);
322
    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
323

    
324
    /* define a shape with the jpeg inside */
325
    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
        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
        put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
339
                        0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
340
        put_byte(pb, 0); /* no line style */
341

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

    
347
        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

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

    
360
        /* end of shape */
361
        put_bits(&p, 1, 0); /* not an edge */
362
        put_bits(&p, 5, 0);
363

    
364
        flush_put_bits(&p);
365
        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
366

    
367
        put_swf_end_tag(s);
368
    }
369

    
370
    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
371
        int v;
372

    
373
        /* start sound */
374
        put_swf_tag(s, TAG_STREAMHEAD2);
375

    
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
            av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
390
            av_free(swf->audio_fifo);
391
            return -1;
392
        }
393
        v |= 0x02; /* 16 bit playback */
394
        if (audio_enc->channels == 2)
395
            v |= 0x01; /* stereo playback */
396
        put_byte(&s->pb, v);
397
        v |= 0x20; /* mp3 compressed */
398
        put_byte(&s->pb, v);
399
        put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
400
        put_le16(&s->pb, 0);
401

    
402
        put_swf_end_tag(s);
403
    }
404

    
405
    put_flush_packet(&s->pb);
406
    return 0;
407
}
408

    
409
static int swf_write_video(AVFormatContext *s,
410
                           AVCodecContext *enc, const uint8_t *buf, int size)
411
{
412
    SWFContext *swf = s->priv_data;
413
    ByteIOContext *pb = &s->pb;
414

    
415
    /* Flash Player limit */
416
    if ( swf->swf_frame_number == 16000 ) {
417
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
418
    }
419

    
420
            if ( swf->video_type == CODEC_ID_VP6F ||
421
                 swf->video_type == CODEC_ID_FLV1 ) {
422
                if ( swf->video_frame_number == 0 ) {
423
                    /* create a new video object */
424
                    put_swf_tag(s, TAG_VIDEOSTREAM);
425
                    put_le16(pb, VIDEO_ID);
426
                    put_le16(pb, 15000 ); /* hard flash player limit */
427
                    put_le16(pb, enc->width);
428
                    put_le16(pb, enc->height);
429
                    put_byte(pb, 0);
430
                    put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
431
                    put_swf_end_tag(s);
432

    
433
                    /* place the video object for the first time */
434
                    put_swf_tag(s, TAG_PLACEOBJECT2);
435
                    put_byte(pb, 0x36);
436
                    put_le16(pb, 1);
437
                    put_le16(pb, VIDEO_ID);
438
                    put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
439
                    put_le16(pb, swf->video_frame_number );
440
                    put_byte(pb, 'v');
441
                    put_byte(pb, 'i');
442
                    put_byte(pb, 'd');
443
                    put_byte(pb, 'e');
444
                    put_byte(pb, 'o');
445
                    put_byte(pb, 0x00);
446
                    put_swf_end_tag(s);
447
                } else {
448
                    /* mark the character for update */
449
                    put_swf_tag(s, TAG_PLACEOBJECT2);
450
                    put_byte(pb, 0x11);
451
                    put_le16(pb, 1);
452
                    put_le16(pb, swf->video_frame_number );
453
                    put_swf_end_tag(s);
454
                }
455

    
456
                    /* set video frame data */
457
                    put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
458
                    put_le16(pb, VIDEO_ID);
459
                    put_le16(pb, swf->video_frame_number++ );
460
                    put_buffer(pb, buf, size);
461
                    put_swf_end_tag(s);
462
            } else if ( swf->video_type == CODEC_ID_MJPEG ) {
463
                if (swf->swf_frame_number > 0) {
464
                    /* remove the shape */
465
                    put_swf_tag(s, TAG_REMOVEOBJECT);
466
                    put_le16(pb, SHAPE_ID); /* shape ID */
467
                    put_le16(pb, 1); /* depth */
468
                    put_swf_end_tag(s);
469

    
470
                    /* free the bitmap */
471
                    put_swf_tag(s, TAG_FREECHARACTER);
472
                    put_le16(pb, BITMAP_ID);
473
                    put_swf_end_tag(s);
474
                }
475

    
476
                put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
477

    
478
                put_le16(pb, BITMAP_ID); /* ID of the image */
479

    
480
                /* a dummy jpeg header seems to be required */
481
                put_byte(pb, 0xff);
482
                put_byte(pb, 0xd8);
483
                put_byte(pb, 0xff);
484
                put_byte(pb, 0xd9);
485
                /* write the jpeg image */
486
                put_buffer(pb, buf, size);
487

    
488
                put_swf_end_tag(s);
489

    
490
                /* draw the shape */
491

    
492
                put_swf_tag(s, TAG_PLACEOBJECT);
493
                put_le16(pb, SHAPE_ID); /* shape ID */
494
                put_le16(pb, 1); /* depth */
495
                put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
496
                put_swf_end_tag(s);
497
            } else {
498
                /* invalid codec */
499
            }
500

    
501
            swf->swf_frame_number ++;
502

    
503
    /* streaming sound always should be placed just before showframe tags */
504
    if (swf->audio_type && swf->audio_in_pos) {
505
        put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
506
        put_le16(pb, swf->sound_samples);
507
        put_le16(pb, 0); // seek samples
508
        put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
509
        put_swf_end_tag(s);
510

    
511
        /* update FIFO */
512
        swf->sound_samples = 0;
513
        swf->audio_in_pos = 0;
514
    }
515

    
516
    /* output the frame */
517
    put_swf_tag(s, TAG_SHOWFRAME);
518
    put_swf_end_tag(s);
519

    
520
    put_flush_packet(&s->pb);
521

    
522
    return 0;
523
}
524

    
525
static int swf_write_audio(AVFormatContext *s,
526
                           AVCodecContext *enc, const uint8_t *buf, int size)
527
{
528
    SWFContext *swf = s->priv_data;
529

    
530
    /* Flash Player limit */
531
    if ( swf->swf_frame_number == 16000 ) {
532
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
533
    }
534

    
535
    if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
536
        av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
537
        return -1;
538
    }
539

    
540
    memcpy(swf->audio_fifo +  swf->audio_in_pos, buf, size);
541
    swf->audio_in_pos += size;
542
    swf->sound_samples += enc->frame_size;
543

    
544
    /* if audio only stream make sure we add swf frames */
545
    if ( swf->video_type == 0 ) {
546
        swf_write_video(s, enc, 0, 0);
547
    }
548

    
549
    return 0;
550
}
551

    
552
static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
553
{
554
    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
555
    if (codec->codec_type == CODEC_TYPE_AUDIO)
556
        return swf_write_audio(s, codec, pkt->data, pkt->size);
557
    else
558
        return swf_write_video(s, codec, pkt->data, pkt->size);
559
}
560

    
561
static int swf_write_trailer(AVFormatContext *s)
562
{
563
    SWFContext *swf = s->priv_data;
564
    ByteIOContext *pb = &s->pb;
565
    AVCodecContext *enc, *video_enc;
566
    int file_size, i;
567

    
568
    video_enc = NULL;
569
    for(i=0;i<s->nb_streams;i++) {
570
        enc = s->streams[i]->codec;
571
        if (enc->codec_type == CODEC_TYPE_VIDEO)
572
            video_enc = enc;
573
    }
574

    
575
    put_swf_tag(s, TAG_END);
576
    put_swf_end_tag(s);
577

    
578
    put_flush_packet(&s->pb);
579

    
580
    /* patch file size and number of frames if not streamed */
581
    if (!url_is_streamed(&s->pb) && video_enc) {
582
        file_size = url_ftell(pb);
583
        url_fseek(pb, 4, SEEK_SET);
584
        put_le32(pb, file_size);
585
        url_fseek(pb, swf->duration_pos, SEEK_SET);
586
        put_le16(pb, video_enc->frame_number);
587
        url_fseek(pb, file_size, SEEK_SET);
588
    }
589
    return 0;
590
}
591
#endif //CONFIG_MUXERS
592

    
593
/*********************************************/
594
/* Extract FLV encoded frame and MP3 from swf
595
   Note that the detection of the real frame
596
   is inaccurate at this point as it can be
597
   quite tricky to determine, you almost certainly
598
   will get a bad audio/video sync */
599

    
600
static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
601
{
602
    int tag, len;
603

    
604
    if (url_feof(pb))
605
        return -1;
606

    
607
    tag = get_le16(pb);
608
    len = tag & 0x3f;
609
    tag = tag >> 6;
610
    if (len == 0x3f) {
611
        len = get_le32(pb);
612
    }
613
//    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
614
    *len_ptr = len;
615
    return tag;
616
}
617

    
618

    
619
static int swf_probe(AVProbeData *p)
620
{
621
    /* check file header */
622
    if (p->buf_size <= 16)
623
        return 0;
624
    if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
625
        p->buf[2] == 'S')
626
        return AVPROBE_SCORE_MAX;
627
    else
628
        return 0;
629
}
630

    
631
static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
632
{
633
    SWFContext *swf = s->priv_data;
634
    ByteIOContext *pb = &s->pb;
635
    int nbits, len, frame_rate, tag, v;
636
    offset_t frame_offset = -1;
637
    AVStream *ast = 0;
638
    AVStream *vst = 0;
639

    
640
    tag = get_be32(pb) & 0xffffff00;
641

    
642
    if (tag == MKBETAG('C', 'W', 'S', 0))
643
    {
644
        av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
645
        return AVERROR_IO;
646
    }
647
    if (tag != MKBETAG('F', 'W', 'S', 0))
648
        return AVERROR_IO;
649
    get_le32(pb);
650
    /* skip rectangle size */
651
    nbits = get_byte(pb) >> 3;
652
    len = (4 * nbits - 3 + 7) / 8;
653
    url_fskip(pb, len);
654
    frame_rate = get_le16(pb);
655
    get_le16(pb); /* frame count */
656

    
657
    /* The Flash Player converts 8.8 frame rates
658
       to milliseconds internally. Do the same to get
659
       a correct framerate */
660
    swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
661
    swf->samples_per_frame = 0;
662

    
663
    for(;;) {
664
        offset_t tag_offset = url_ftell(pb);
665
        tag = get_swf_tag(pb, &len);
666
        if (tag < 0 || tag == TAG_VIDEOFRAME || tag == TAG_STREAMBLOCK) {
667
            url_fseek(pb, frame_offset == -1 ? tag_offset : frame_offset, SEEK_SET);
668
            break;
669
        }
670
        if ( tag == TAG_VIDEOSTREAM && !vst) {
671
            int ch_id = get_le16(pb);
672
            get_le16(pb);
673
            get_le16(pb);
674
            get_le16(pb);
675
            get_byte(pb);
676
            /* Check for FLV1 */
677
            vst = av_new_stream(s, ch_id);
678
            vst->codec->codec_type = CODEC_TYPE_VIDEO;
679
            vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
680
        } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
681
            /* streaming found */
682
            int sample_rate_code;
683
            get_byte(pb);
684
            v = get_byte(pb);
685
            swf->samples_per_frame = get_le16(pb);
686
            ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
687
            av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
688
            swf->audio_stream_index = ast->index;
689
            ast->codec->channels = 1 + (v&1);
690
            ast->codec->codec_type = CODEC_TYPE_AUDIO;
691
            ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
692
            ast->need_parsing = 1;
693
            sample_rate_code= (v>>2) & 3;
694
            if (!sample_rate_code)
695
                return AVERROR_IO;
696
            ast->codec->sample_rate = 11025 << (sample_rate_code-1);
697
            if (len > 4)
698
                url_fskip(pb,len-4);
699

    
700
        } else if (tag == TAG_JPEG2 && !vst) {
701
            vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
702
            vst->codec->codec_type = CODEC_TYPE_VIDEO;
703
            vst->codec->codec_id = CODEC_ID_MJPEG;
704
            url_fskip(pb, len);
705
            frame_offset = tag_offset;
706
        } else {
707
            url_fskip(pb, len);
708
        }
709
    }
710
    if (vst) {
711
        av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
712
        if (swf->ms_per_frame) {
713
            vst->codec->time_base.den = 1000. / swf->ms_per_frame;
714
            vst->codec->time_base.num = 1;
715
        }
716
    }
717
    return 0;
718
}
719

    
720
static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
721
{
722
    SWFContext *swf = s->priv_data;
723
    ByteIOContext *pb = &s->pb;
724
    AVStream *st = 0;
725
    int tag, len, i, frame;
726

    
727
    for(;;) {
728
        tag = get_swf_tag(pb, &len);
729
        if (tag < 0)
730
            return AVERROR_IO;
731
        if (tag == TAG_VIDEOFRAME) {
732
            int ch_id = get_le16(pb);
733
            len -= 2;
734
            for( i=0; i<s->nb_streams; i++ ) {
735
                st = s->streams[i];
736
                if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
737
                    frame = get_le16(pb);
738
                    av_get_packet(pb, pkt, len-2);
739
                    pkt->pts = frame * swf->ms_per_frame;
740
                    pkt->stream_index = st->index;
741
                    return pkt->size;
742
                }
743
            }
744
        } else if (tag == TAG_STREAMBLOCK) {
745
            st = s->streams[swf->audio_stream_index];
746
            if (st->codec->codec_id == CODEC_ID_MP3) {
747
                url_fskip(pb, 4);
748
                av_get_packet(pb, pkt, len-4);
749
            } else { // ADPCM, PCM
750
                av_get_packet(pb, pkt, len);
751
            }
752
            pkt->stream_index = st->index;
753
            return pkt->size;
754
        } else if (tag == TAG_JPEG2) {
755
            for (i=0; i<s->nb_streams; i++) {
756
                st = s->streams[i];
757
                if (st->id == -2) {
758
                    get_le16(pb); /* BITMAP_ID */
759
                    av_new_packet(pkt, len-2);
760
                    get_buffer(pb, pkt->data, 4);
761
                    if (AV_RB32(pkt->data) == 0xffd8ffd9) {
762
                        /* old SWF files containing SOI/EOI as data start */
763
                        pkt->size -= 4;
764
                        get_buffer(pb, pkt->data, pkt->size);
765
                    } else {
766
                        get_buffer(pb, pkt->data + 4, pkt->size - 4);
767
                    }
768
                    pkt->stream_index = st->index;
769
                    return pkt->size;
770
                }
771
            }
772
        }
773
        url_fskip(pb, len);
774
    }
775
    return 0;
776
}
777

    
778
static int swf_read_close(AVFormatContext *s)
779
{
780
     return 0;
781
}
782

    
783
#ifdef CONFIG_SWF_DEMUXER
784
AVInputFormat swf_demuxer = {
785
    "swf",
786
    "Flash format",
787
    sizeof(SWFContext),
788
    swf_probe,
789
    swf_read_header,
790
    swf_read_packet,
791
    swf_read_close,
792
};
793
#endif
794
#ifdef CONFIG_SWF_MUXER
795
AVOutputFormat swf_muxer = {
796
    "swf",
797
    "Flash format",
798
    "application/x-shockwave-flash",
799
    "swf",
800
    sizeof(SWFContext),
801
    CODEC_ID_MP3,
802
    CODEC_ID_FLV1,
803
    swf_write_header,
804
    swf_write_packet,
805
    swf_write_trailer,
806
};
807
#endif