Statistics
| Branch: | Revision:

ffmpeg / libavformat / swf.c @ 755bfeab

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

    
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 frame_rate;
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 does not support that sample rate, choose from (44100, 22050, 11025).\n");
390
            return -1;
391
        }
392
        v |= 0x02; /* 16 bit playback */
393
        if (audio_enc->channels == 2)
394
            v |= 0x01; /* stereo playback */
395
        put_byte(&s->pb, v);
396
        v |= 0x20; /* mp3 compressed */
397
        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

    
401
        put_swf_end_tag(s);
402
    }
403

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

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

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

    
419
            if ( swf->video_type == CODEC_ID_VP6F ||
420
                 swf->video_type == CODEC_ID_FLV1 ) {
421
                if ( swf->video_frame_number == 0 ) {
422
                    /* create a new video object */
423
                    put_swf_tag(s, TAG_VIDEOSTREAM);
424
                    put_le16(pb, VIDEO_ID);
425
                    put_le16(pb, 15000 ); /* hard flash player limit */
426
                    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
                    put_le16(pb, swf->video_frame_number );
439
                    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
                    put_le16(pb, swf->video_frame_number );
452
                    put_swf_end_tag(s);
453
                }
454

    
455
                    /* set video frame data */
456
                    put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
457
                    put_le16(pb, VIDEO_ID);
458
                    put_le16(pb, swf->video_frame_number++ );
459
                    put_buffer(pb, buf, size);
460
                    put_swf_end_tag(s);
461
            } else if ( swf->video_type == CODEC_ID_MJPEG ) {
462
                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

    
475
                put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
476

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

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

    
487
                put_swf_end_tag(s);
488

    
489
                /* draw the shape */
490

    
491
                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

    
500
            swf->swf_frame_number ++;
501

    
502
    /* streaming sound always should be placed just before showframe tags */
503
    if (swf->audio_type && swf->audio_in_pos) {
504
        put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
505
        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
        put_swf_end_tag(s);
509

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

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

    
519
    put_flush_packet(&s->pb);
520

    
521
    return 0;
522
}
523

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

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

    
534
    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
    }
538

    
539
    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
    /* if audio only stream make sure we add swf frames */
544
    if ( swf->video_type == 0 ) {
545
        swf_write_video(s, enc, 0, 0);
546
    }
547

    
548
    return 0;
549
}
550

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

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

    
567
    video_enc = NULL;
568
    for(i=0;i<s->nb_streams;i++) {
569
        enc = s->streams[i]->codec;
570
        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

    
577
    put_flush_packet(&s->pb);
578

    
579
    /* patch file size and number of frames if not streamed */
580
    if (!url_is_streamed(&s->pb) && video_enc) {
581
        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
        url_fseek(pb, file_size, SEEK_SET);
587
    }
588
    return 0;
589
}
590
#endif //CONFIG_MUXERS
591

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

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

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

    
617

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

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

    
637
    tag = get_be32(pb) & 0xffffff00;
638

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

    
654
    swf->samples_per_frame = 0;
655

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

    
693
        } else if (tag == TAG_JPEG2 && !vst) {
694
            vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
695
            vst->codec->codec_type = CODEC_TYPE_VIDEO;
696
            vst->codec->codec_id = CODEC_ID_MJPEG;
697
            url_fskip(pb, len);
698
            frame_offset = tag_offset;
699
        } else {
700
            url_fskip(pb, len);
701
        }
702
    }
703
    if (vst)
704
        av_set_pts_info(vst, 64, 256, swf->frame_rate);
705
    return 0;
706
}
707

    
708
static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
709
{
710
    SWFContext *swf = s->priv_data;
711
    ByteIOContext *pb = &s->pb;
712
    AVStream *st = 0;
713
    int tag, len, i, frame;
714

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

    
766
static int swf_read_close(AVFormatContext *s)
767
{
768
     return 0;
769
}
770

    
771
#ifdef CONFIG_SWF_DEMUXER
772
AVInputFormat swf_demuxer = {
773
    "swf",
774
    "Flash format",
775
    sizeof(SWFContext),
776
    swf_probe,
777
    swf_read_header,
778
    swf_read_packet,
779
    swf_read_close,
780
};
781
#endif
782
#ifdef CONFIG_SWF_MUXER
783
AVOutputFormat swf_muxer = {
784
    "swf",
785
    "Flash format",
786
    "application/x-shockwave-flash",
787
    "swf",
788
    sizeof(SWFContext),
789
    CODEC_ID_MP3,
790
    CODEC_ID_FLV1,
791
    swf_write_header,
792
    swf_write_packet,
793
    swf_write_trailer,
794
};
795
#endif