Mercurial > libavformat.hg
annotate swfdec.c @ 5854:3dc78fb78b2a libavformat
Fix erroneous behaviour when format probe hits end of file
If the format probe hits end of file, do not add the error code
to the buffer position. This is obviously wrong, and with a
small input file would cause a negative buffer overflow.
Fixes issue 1818.
author | mru |
---|---|
date | Tue, 16 Mar 2010 21:45:30 +0000 |
parents | 33a244b7ca65 |
children | 536e5527c1e0 |
rev | line source |
---|---|
0 | 1 /* |
3357 | 2 * Flash Compatible Streaming Format demuxer |
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4201
diff
changeset
|
3 * Copyright (c) 2000 Fabrice Bellard |
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4201
diff
changeset
|
4 * Copyright (c) 2003 Tinic Uro |
0 | 5 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
6 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
7 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
8 * FFmpeg is free software; you can redistribute it and/or |
0 | 9 * modify it under the terms of the GNU Lesser General Public |
10 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
11 * version 2.1 of the License, or (at your option) any later version. |
0 | 12 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
13 * FFmpeg is distributed in the hope that it will be useful, |
0 | 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 | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
19 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
887
diff
changeset
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 21 */ |
3286 | 22 |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
3424
diff
changeset
|
23 #include "libavutil/intreadwrite.h" |
3302 | 24 #include "swf.h" |
0 | 25 |
26 static int get_swf_tag(ByteIOContext *pb, int *len_ptr) | |
27 { | |
28 int tag, len; | |
885 | 29 |
0 | 30 if (url_feof(pb)) |
31 return -1; | |
32 | |
33 tag = get_le16(pb); | |
34 len = tag & 0x3f; | |
35 tag = tag >> 6; | |
36 if (len == 0x3f) { | |
37 len = get_le32(pb); | |
38 } | |
806 | 39 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len); |
0 | 40 *len_ptr = len; |
41 return tag; | |
42 } | |
43 | |
44 | |
45 static int swf_probe(AVProbeData *p) | |
46 { | |
47 /* check file header */ | |
806 | 48 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' && |
0 | 49 p->buf[2] == 'S') |
50 return AVPROBE_SCORE_MAX; | |
51 else | |
52 return 0; | |
53 } | |
54 | |
55 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
56 { | |
1641 | 57 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
58 ByteIOContext *pb = s->pb; |
2310 | 59 int nbits, len, tag; |
359 | 60 |
806 | 61 tag = get_be32(pb) & 0xffffff00; |
62 | |
2309 | 63 if (tag == MKBETAG('C', 'W', 'S', 0)) { |
887 | 64 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n"); |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
65 return AVERROR(EIO); |
806 | 66 } |
67 if (tag != MKBETAG('F', 'W', 'S', 0)) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
68 return AVERROR(EIO); |
0 | 69 get_le32(pb); |
70 /* skip rectangle size */ | |
71 nbits = get_byte(pb) >> 3; | |
72 len = (4 * nbits - 3 + 7) / 8; | |
73 url_fskip(pb, len); | |
1889 | 74 swf->frame_rate = get_le16(pb); /* 8.8 fixed */ |
0 | 75 get_le16(pb); /* frame count */ |
885 | 76 |
359 | 77 swf->samples_per_frame = 0; |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
78 s->ctx_flags |= AVFMTCTX_NOHEADER; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
79 return 0; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
80 } |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
81 |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
82 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
83 { |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
84 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
85 ByteIOContext *pb = s->pb; |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
86 AVStream *vst = NULL, *ast = NULL, *st = 0; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
87 int tag, len, i, frame, v; |
0 | 88 |
89 for(;;) { | |
4707
f153437e1ac0
Set pkt->pos correctly (to the start of header of the packet) in swfdec.
reimar
parents:
4706
diff
changeset
|
90 uint64_t pos = url_ftell(pb); |
0 | 91 tag = get_swf_tag(pb, &len); |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
92 if (tag < 0) |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
93 return AVERROR(EIO); |
4706 | 94 if (tag == TAG_VIDEOSTREAM) { |
1637 | 95 int ch_id = get_le16(pb); |
4706 | 96 len -= 2; |
97 | |
98 for (i=0; i<s->nb_streams; i++) { | |
99 st = s->streams[i]; | |
100 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) | |
101 goto skip; | |
102 } | |
103 | |
359 | 104 get_le16(pb); |
105 get_le16(pb); | |
106 get_le16(pb); | |
107 get_byte(pb); | |
108 /* Check for FLV1 */ | |
1637 | 109 vst = av_new_stream(s, ch_id); |
2913 | 110 if (!vst) |
111 return -1; | |
1635 | 112 vst->codec->codec_type = CODEC_TYPE_VIDEO; |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4715
diff
changeset
|
113 vst->codec->codec_id = ff_codec_get_id(swf_codec_tags, get_byte(pb)); |
4715 | 114 av_set_pts_info(vst, 16, 256, swf->frame_rate); |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
115 vst->codec->time_base = (AVRational){ 256, swf->frame_rate }; |
4706 | 116 len -= 8; |
117 } else if (tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) { | |
0 | 118 /* streaming found */ |
1642 | 119 int sample_rate_code; |
4706 | 120 |
121 for (i=0; i<s->nb_streams; i++) { | |
122 st = s->streams[i]; | |
123 if (st->codec->codec_type == CODEC_TYPE_AUDIO && st->id == -1) | |
124 goto skip; | |
125 } | |
126 | |
0 | 127 get_byte(pb); |
128 v = get_byte(pb); | |
359 | 129 swf->samples_per_frame = get_le16(pb); |
1638 | 130 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */ |
2913 | 131 if (!ast) |
132 return -1; | |
1636 | 133 ast->codec->channels = 1 + (v&1); |
134 ast->codec->codec_type = CODEC_TYPE_AUDIO; | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4715
diff
changeset
|
135 ast->codec->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15); |
2023 | 136 ast->need_parsing = AVSTREAM_PARSE_FULL; |
1642 | 137 sample_rate_code= (v>>2) & 3; |
138 if (!sample_rate_code) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
139 return AVERROR(EIO); |
1642 | 140 ast->codec->sample_rate = 11025 << (sample_rate_code-1); |
1890
04f9a3ae30af
seems safer to set pts timebase to sample rate, fix some mp3
bcoudurier
parents:
1889
diff
changeset
|
141 av_set_pts_info(ast, 64, 1, ast->codec->sample_rate); |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
142 len -= 4; |
2308 | 143 } else if (tag == TAG_VIDEOFRAME) { |
1637 | 144 int ch_id = get_le16(pb); |
1639 | 145 len -= 2; |
2309 | 146 for(i=0; i<s->nb_streams; i++) { |
887 | 147 st = s->streams[i]; |
1637 | 148 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) { |
149 frame = get_le16(pb); | |
1639 | 150 av_get_packet(pb, pkt, len-2); |
4707
f153437e1ac0
Set pkt->pos correctly (to the start of header of the packet) in swfdec.
reimar
parents:
4706
diff
changeset
|
151 pkt->pos = pos; |
1889 | 152 pkt->pts = frame; |
1637 | 153 pkt->stream_index = st->index; |
154 return pkt->size; | |
359 | 155 } |
885 | 156 } |
359 | 157 } else if (tag == TAG_STREAMBLOCK) { |
4706 | 158 for (i = 0; i < s->nb_streams; i++) { |
159 st = s->streams[i]; | |
160 if (st->codec->codec_type == CODEC_TYPE_AUDIO && st->id == -1) { | |
1638 | 161 if (st->codec->codec_id == CODEC_ID_MP3) { |
162 url_fskip(pb, 4); | |
163 av_get_packet(pb, pkt, len-4); | |
1833 | 164 } else { // ADPCM, PCM |
165 av_get_packet(pb, pkt, len); | |
359 | 166 } |
4707
f153437e1ac0
Set pkt->pos correctly (to the start of header of the packet) in swfdec.
reimar
parents:
4706
diff
changeset
|
167 pkt->pos = pos; |
1833 | 168 pkt->stream_index = st->index; |
169 return pkt->size; | |
4706 | 170 } |
171 } | |
1640 | 172 } else if (tag == TAG_JPEG2) { |
173 for (i=0; i<s->nb_streams; i++) { | |
174 st = s->streams[i]; | |
4706 | 175 if (st->codec->codec_id == CODEC_ID_MJPEG && st->id == -2) |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
176 break; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
177 } |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
178 if (i == s->nb_streams) { |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
179 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */ |
2913 | 180 if (!vst) |
181 return -1; | |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
182 vst->codec->codec_type = CODEC_TYPE_VIDEO; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
183 vst->codec->codec_id = CODEC_ID_MJPEG; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
184 av_set_pts_info(vst, 64, 256, swf->frame_rate); |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
185 vst->codec->time_base = (AVRational){ 256, swf->frame_rate }; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
186 st = vst; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
187 } |
2308 | 188 get_le16(pb); /* BITMAP_ID */ |
189 av_new_packet(pkt, len-2); | |
190 get_buffer(pb, pkt->data, 4); | |
2402
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
191 if (AV_RB32(pkt->data) == 0xffd8ffd9 || |
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
192 AV_RB32(pkt->data) == 0xffd9ffd8) { |
2308 | 193 /* old SWF files containing SOI/EOI as data start */ |
2402
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
194 /* files created by swink have reversed tag */ |
2308 | 195 pkt->size -= 4; |
196 get_buffer(pb, pkt->data, pkt->size); | |
197 } else { | |
198 get_buffer(pb, pkt->data + 4, pkt->size - 4); | |
199 } | |
4707
f153437e1ac0
Set pkt->pos correctly (to the start of header of the packet) in swfdec.
reimar
parents:
4706
diff
changeset
|
200 pkt->pos = pos; |
2308 | 201 pkt->stream_index = st->index; |
202 return pkt->size; | |
0 | 203 } |
4706 | 204 skip: |
1639 | 205 url_fskip(pb, len); |
0 | 206 } |
207 return 0; | |
208 } | |
209 | |
1169 | 210 AVInputFormat swf_demuxer = { |
0 | 211 "swf", |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3357
diff
changeset
|
212 NULL_IF_CONFIG_SMALL("Flash format"), |
359 | 213 sizeof(SWFContext), |
0 | 214 swf_probe, |
215 swf_read_header, | |
216 swf_read_packet, | |
217 }; |