1/*
2 * Flash Compatible Streaming Format demuxer
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
23#include "libavutil/avassert.h"
24#include "libavutil/channel_layout.h"
25#include "libavutil/imgutils.h"
26#include "libavutil/intreadwrite.h"
27#include "swf.h"
28
29static const AVCodecTag swf_audio_codec_tags[] = {
30    { AV_CODEC_ID_PCM_S16LE,  0x00 },
31    { AV_CODEC_ID_ADPCM_SWF,  0x01 },
32    { AV_CODEC_ID_MP3,        0x02 },
33    { AV_CODEC_ID_PCM_S16LE,  0x03 },
34//  { AV_CODEC_ID_NELLYMOSER, 0x06 },
35    { AV_CODEC_ID_NONE,          0 },
36};
37
38static int get_swf_tag(AVIOContext *pb, int *len_ptr)
39{
40    int tag, len;
41
42    if (url_feof(pb))
43        return AVERROR_EOF;
44
45    tag = avio_rl16(pb);
46    len = tag & 0x3f;
47    tag = tag >> 6;
48    if (len == 0x3f) {
49        len = avio_rl32(pb);
50    }
51    *len_ptr = len;
52    return tag;
53}
54
55
56static int swf_probe(AVProbeData *p)
57{
58    if(p->buf_size < 15)
59        return 0;
60
61    /* check file header */
62    if (   AV_RB24(p->buf) != AV_RB24("CWS")
63        && AV_RB24(p->buf) != AV_RB24("FWS"))
64        return 0;
65
66    if (p->buf[3] >= 20)
67        return AVPROBE_SCORE_MAX / 4;
68
69    return AVPROBE_SCORE_MAX;
70}
71
72#if CONFIG_ZLIB
73static int zlib_refill(void *opaque, uint8_t *buf, int buf_size)
74{
75    AVFormatContext *s = opaque;
76    SWFContext *swf = s->priv_data;
77    z_stream *z = &swf->zstream;
78    int ret;
79
80retry:
81    if (!z->avail_in) {
82        int n = avio_read(s->pb, swf->zbuf_in, ZBUF_SIZE);
83        if (n < 0)
84            return n;
85        z->next_in  = swf->zbuf_in;
86        z->avail_in = n;
87    }
88
89    z->next_out  = buf;
90    z->avail_out = buf_size;
91
92    ret = inflate(z, Z_NO_FLUSH);
93    if (ret < 0)
94        return AVERROR(EINVAL);
95    if (ret == Z_STREAM_END)
96        return AVERROR_EOF;
97
98    if (buf_size - z->avail_out == 0)
99        goto retry;
100
101    return buf_size - z->avail_out;
102}
103#endif
104
105static int swf_read_header(AVFormatContext *s)
106{
107    SWFContext *swf = s->priv_data;
108    AVIOContext *pb = s->pb;
109    int nbits, len, tag;
110
111    tag = avio_rb32(pb) & 0xffffff00;
112    avio_rl32(pb);
113
114    if (tag == MKBETAG('C', 'W', 'S', 0)) {
115        av_log(s, AV_LOG_INFO, "SWF compressed file detected\n");
116#if CONFIG_ZLIB
117        swf->zbuf_in  = av_malloc(ZBUF_SIZE);
118        swf->zbuf_out = av_malloc(ZBUF_SIZE);
119        swf->zpb = avio_alloc_context(swf->zbuf_out, ZBUF_SIZE, 0, s,
120                                      zlib_refill, NULL, NULL);
121        if (!swf->zbuf_in || !swf->zbuf_out || !swf->zpb)
122            return AVERROR(ENOMEM);
123        swf->zpb->seekable = 0;
124        if (inflateInit(&swf->zstream) != Z_OK) {
125            av_log(s, AV_LOG_ERROR, "Unable to init zlib context\n");
126            return AVERROR(EINVAL);
127        }
128        pb = swf->zpb;
129#else
130        av_log(s, AV_LOG_ERROR, "zlib support is required to read SWF compressed files\n");
131        return AVERROR(EIO);
132#endif
133    } else if (tag != MKBETAG('F', 'W', 'S', 0))
134        return AVERROR(EIO);
135    /* skip rectangle size */
136    nbits = avio_r8(pb) >> 3;
137    len = (4 * nbits - 3 + 7) / 8;
138    avio_skip(pb, len);
139    swf->frame_rate = avio_rl16(pb); /* 8.8 fixed */
140    avio_rl16(pb); /* frame count */
141
142    swf->samples_per_frame = 0;
143    s->ctx_flags |= AVFMTCTX_NOHEADER;
144    return 0;
145}
146
147static AVStream *create_new_audio_stream(AVFormatContext *s, int id, int info)
148{
149    int sample_rate_code, sample_size_code;
150    AVStream *ast = avformat_new_stream(s, NULL);
151    if (!ast)
152        return NULL;
153    ast->id = id;
154    if (info & 1) {
155        ast->codec->channels       = 2;
156        ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
157    } else {
158        ast->codec->channels       = 1;
159        ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
160    }
161    ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
162    ast->codec->codec_id   = ff_codec_get_id(swf_audio_codec_tags, info>>4 & 15);
163    ast->need_parsing = AVSTREAM_PARSE_FULL;
164    sample_rate_code = info>>2 & 3;
165    sample_size_code = info>>1 & 1;
166    if (!sample_size_code && ast->codec->codec_id == AV_CODEC_ID_PCM_S16LE)
167        ast->codec->codec_id = AV_CODEC_ID_PCM_U8;
168    ast->codec->sample_rate = 44100 >> (3 - sample_rate_code);
169    avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
170    return ast;
171}
172
173static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
174{
175    SWFContext *swf = s->priv_data;
176    AVIOContext *pb = s->pb;
177    AVStream *vst = NULL, *ast = NULL, *st = 0;
178    int tag, len, i, frame, v, res;
179
180#if CONFIG_ZLIB
181    if (swf->zpb)
182        pb = swf->zpb;
183#endif
184
185    for(;;) {
186        uint64_t pos = avio_tell(pb);
187        tag = get_swf_tag(pb, &len);
188        if (tag < 0)
189            return tag;
190        if (len < 0) {
191            av_log(s, AV_LOG_ERROR, "invalid tag length: %d\n", len);
192            return AVERROR_INVALIDDATA;
193        }
194        if (tag == TAG_VIDEOSTREAM) {
195            int ch_id = avio_rl16(pb);
196            len -= 2;
197
198            for (i=0; i<s->nb_streams; i++) {
199                st = s->streams[i];
200                if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id)
201                    goto skip;
202            }
203
204            avio_rl16(pb);
205            avio_rl16(pb);
206            avio_rl16(pb);
207            avio_r8(pb);
208            /* Check for FLV1 */
209            vst = avformat_new_stream(s, NULL);
210            if (!vst)
211                return AVERROR(ENOMEM);
212            vst->id = ch_id;
213            vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
214            vst->codec->codec_id = ff_codec_get_id(ff_swf_codec_tags, avio_r8(pb));
215            avpriv_set_pts_info(vst, 16, 256, swf->frame_rate);
216            len -= 8;
217        } else if (tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) {
218            /* streaming found */
219
220            for (i=0; i<s->nb_streams; i++) {
221                st = s->streams[i];
222                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1)
223                    goto skip;
224            }
225
226            avio_r8(pb);
227            v = avio_r8(pb);
228            swf->samples_per_frame = avio_rl16(pb);
229            ast = create_new_audio_stream(s, -1, v); /* -1 to avoid clash with video stream ch_id */
230            if (!ast)
231                return AVERROR(ENOMEM);
232            len -= 4;
233        } else if (tag == TAG_DEFINESOUND) {
234            /* audio stream */
235            int ch_id = avio_rl16(pb);
236
237            for (i=0; i<s->nb_streams; i++) {
238                st = s->streams[i];
239                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == ch_id)
240                    goto skip;
241            }
242
243            // FIXME: The entire audio stream is stored in a single chunk/tag. Normally,
244            // these are smaller audio streams in DEFINESOUND tags, but it's technically
245            // possible they could be huge. Break it up into multiple packets if it's big.
246            v = avio_r8(pb);
247            ast = create_new_audio_stream(s, ch_id, v);
248            if (!ast)
249                return AVERROR(ENOMEM);
250            ast->duration = avio_rl32(pb); // number of samples
251            if (((v>>4) & 15) == 2) { // MP3 sound data record
252                ast->skip_samples = avio_rl16(pb);
253                len -= 2;
254            }
255            len -= 7;
256            if ((res = av_get_packet(pb, pkt, len)) < 0)
257                return res;
258            pkt->pos = pos;
259            pkt->stream_index = ast->index;
260            return pkt->size;
261        } else if (tag == TAG_VIDEOFRAME) {
262            int ch_id = avio_rl16(pb);
263            len -= 2;
264            for(i=0; i<s->nb_streams; i++) {
265                st = s->streams[i];
266                if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) {
267                    frame = avio_rl16(pb);
268                    len -= 2;
269                    if (len <= 0)
270                        goto skip;
271                    if ((res = av_get_packet(pb, pkt, len)) < 0)
272                        return res;
273                    pkt->pos = pos;
274                    pkt->pts = frame;
275                    pkt->stream_index = st->index;
276                    return pkt->size;
277                }
278            }
279        } else if (tag == TAG_DEFINEBITSLOSSLESS || tag == TAG_DEFINEBITSLOSSLESS2) {
280#if CONFIG_ZLIB
281            long out_len;
282            uint8_t *buf = NULL, *zbuf = NULL, *pal;
283            uint32_t colormap[AVPALETTE_COUNT] = {0};
284            const int alpha_bmp = tag == TAG_DEFINEBITSLOSSLESS2;
285            const int colormapbpp = 3 + alpha_bmp;
286            int linesize, colormapsize = 0;
287
288            const int ch_id   = avio_rl16(pb);
289            const int bmp_fmt = avio_r8(pb);
290            const int width   = avio_rl16(pb);
291            const int height  = avio_rl16(pb);
292            int pix_fmt;
293
294            len -= 2+1+2+2;
295
296            switch (bmp_fmt) {
297            case 3: // PAL-8
298                linesize = width;
299                colormapsize = avio_r8(pb) + 1;
300                len--;
301                break;
302            case 4: // RGB15
303                linesize = width * 2;
304                break;
305            case 5: // RGB24 (0RGB)
306                linesize = width * 4;
307                break;
308            default:
309                av_log(s, AV_LOG_ERROR, "invalid bitmap format %d, skipped\n", bmp_fmt);
310                goto bitmap_end_skip;
311            }
312
313            linesize = FFALIGN(linesize, 4);
314
315            if (av_image_check_size(width, height, 0, s) < 0 ||
316                linesize >= INT_MAX / height ||
317                linesize * height >= INT_MAX - colormapsize * colormapbpp) {
318                av_log(s, AV_LOG_ERROR, "invalid frame size %dx%d\n", width, height);
319                goto bitmap_end_skip;
320            }
321
322            out_len = colormapsize * colormapbpp + linesize * height;
323
324            av_dlog(s, "bitmap: ch=%d fmt=%d %dx%d (linesize=%d) len=%d->%ld pal=%d\n",
325                    ch_id, bmp_fmt, width, height, linesize, len, out_len, colormapsize);
326
327            zbuf = av_malloc(len);
328            buf  = av_malloc(out_len);
329            if (!zbuf || !buf) {
330                res = AVERROR(ENOMEM);
331                goto bitmap_end;
332            }
333
334            len = avio_read(pb, zbuf, len);
335            if (len < 0 || (res = uncompress(buf, &out_len, zbuf, len)) != Z_OK) {
336                av_log(s, AV_LOG_WARNING, "Failed to uncompress one bitmap\n");
337                goto bitmap_end_skip;
338            }
339
340            for (i = 0; i < s->nb_streams; i++) {
341                st = s->streams[i];
342                if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && st->id == -3)
343                    break;
344            }
345            if (i == s->nb_streams) {
346                vst = avformat_new_stream(s, NULL);
347                if (!vst) {
348                    res = AVERROR(ENOMEM);
349                    goto bitmap_end;
350                }
351                vst->id = -3; /* -3 to avoid clash with video stream and audio stream */
352                vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
353                vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
354                avpriv_set_pts_info(vst, 64, 256, swf->frame_rate);
355                st = vst;
356            }
357
358            if ((res = av_new_packet(pkt, out_len - colormapsize * colormapbpp)) < 0)
359                goto bitmap_end;
360            if (!st->codec->width && !st->codec->height) {
361                st->codec->width  = width;
362                st->codec->height = height;
363            } else {
364                ff_add_param_change(pkt, 0, 0, 0, width, height);
365            }
366            pkt->pos = pos;
367            pkt->stream_index = st->index;
368
369            switch (bmp_fmt) {
370            case 3:
371                pix_fmt = AV_PIX_FMT_PAL8;
372                for (i = 0; i < colormapsize; i++)
373                    if (alpha_bmp)  colormap[i] = buf[3]<<24 | AV_RB24(buf + 4*i);
374                    else            colormap[i] = 0xffU <<24 | AV_RB24(buf + 3*i);
375                pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
376                if (!pal) {
377                    res = AVERROR(ENOMEM);
378                    goto bitmap_end;
379                }
380                memcpy(pal, colormap, AVPALETTE_SIZE);
381                break;
382            case 4:
383                pix_fmt = AV_PIX_FMT_RGB555;
384                break;
385            case 5:
386                pix_fmt = alpha_bmp ? AV_PIX_FMT_ARGB : AV_PIX_FMT_0RGB;
387                break;
388            default:
389                av_assert0(0);
390            }
391            if (st->codec->pix_fmt != AV_PIX_FMT_NONE && st->codec->pix_fmt != pix_fmt) {
392                av_log(s, AV_LOG_ERROR, "pixel format change unsupported\n");
393                res = AVERROR_PATCHWELCOME;
394                goto bitmap_end;
395            }
396            st->codec->pix_fmt = pix_fmt;
397
398            if (linesize * height > pkt->size) {
399                res = AVERROR_INVALIDDATA;
400                goto bitmap_end;
401            }
402            memcpy(pkt->data, buf + colormapsize*colormapbpp, linesize * height);
403
404            res = pkt->size;
405
406bitmap_end:
407            av_freep(&zbuf);
408            av_freep(&buf);
409            return res;
410bitmap_end_skip:
411            av_freep(&zbuf);
412            av_freep(&buf);
413#else
414            av_log(s, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
415#endif
416        } else if (tag == TAG_STREAMBLOCK) {
417            for (i = 0; i < s->nb_streams; i++) {
418                st = s->streams[i];
419                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) {
420                    if (st->codec->codec_id == AV_CODEC_ID_MP3) {
421                        avio_skip(pb, 4);
422                        len -= 4;
423                        if (len <= 0)
424                            goto skip;
425                        if ((res = av_get_packet(pb, pkt, len)) < 0)
426                            return res;
427                    } else { // ADPCM, PCM
428                        if (len <= 0)
429                            goto skip;
430                        if ((res = av_get_packet(pb, pkt, len)) < 0)
431                            return res;
432                    }
433                    pkt->pos          = pos;
434                    pkt->stream_index = st->index;
435                    return pkt->size;
436                }
437            }
438        } else if (tag == TAG_JPEG2) {
439            for (i=0; i<s->nb_streams; i++) {
440                st = s->streams[i];
441                if (st->codec->codec_id == AV_CODEC_ID_MJPEG && st->id == -2)
442                    break;
443            }
444            if (i == s->nb_streams) {
445                vst = avformat_new_stream(s, NULL);
446                if (!vst)
447                    return AVERROR(ENOMEM);
448                vst->id = -2; /* -2 to avoid clash with video stream and audio stream */
449                vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
450                vst->codec->codec_id = AV_CODEC_ID_MJPEG;
451                avpriv_set_pts_info(vst, 64, 256, swf->frame_rate);
452                st = vst;
453            }
454            avio_rl16(pb); /* BITMAP_ID */
455            len -= 2;
456            if (len < 4)
457                goto skip;
458            if ((res = av_new_packet(pkt, len)) < 0)
459                return res;
460            if (avio_read(pb, pkt->data, 4) != 4) {
461                av_free_packet(pkt);
462                return AVERROR_INVALIDDATA;
463            }
464            if (AV_RB32(pkt->data) == 0xffd8ffd9 ||
465                AV_RB32(pkt->data) == 0xffd9ffd8) {
466                /* old SWF files containing SOI/EOI as data start */
467                /* files created by swink have reversed tag */
468                pkt->size -= 4;
469                memset(pkt->data+pkt->size, 0, 4);
470                res = avio_read(pb, pkt->data, pkt->size);
471            } else {
472                res = avio_read(pb, pkt->data + 4, pkt->size - 4);
473                if (res >= 0)
474                    res += 4;
475            }
476            if (res != pkt->size) {
477                if (res < 0) {
478                    av_free_packet(pkt);
479                    return res;
480                }
481                av_shrink_packet(pkt, res);
482            }
483
484            pkt->pos = pos;
485            pkt->stream_index = st->index;
486            return pkt->size;
487        } else {
488            av_log(s, AV_LOG_DEBUG, "Unknown tag: %d\n", tag);
489        }
490    skip:
491        if(len<0)
492            av_log(s, AV_LOG_WARNING, "Cliping len %d\n", len);
493        len = FFMAX(0, len);
494        avio_skip(pb, len);
495    }
496}
497
498#if CONFIG_ZLIB
499static av_cold int swf_read_close(AVFormatContext *avctx)
500{
501    SWFContext *s = avctx->priv_data;
502    inflateEnd(&s->zstream);
503    av_freep(&s->zbuf_in);
504    av_freep(&s->zbuf_out);
505    av_freep(&s->zpb);
506    return 0;
507}
508#endif
509
510AVInputFormat ff_swf_demuxer = {
511    .name           = "swf",
512    .long_name      = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
513    .priv_data_size = sizeof(SWFContext),
514    .read_probe     = swf_probe,
515    .read_header    = swf_read_header,
516    .read_packet    = swf_read_packet,
517#if CONFIG_ZLIB
518    .read_close     = swf_read_close,
519#endif
520};
521