comparison wc3movie.c @ 4852:ecf9f13948f1 libavformat

Use get_le32/get_be32 in wc3movie demuxer instead of reading everything into a buffer first.
author reimar
date Sat, 11 Apr 2009 18:58:55 +0000
parents a9a2c60d0e84
children 74342058fc9d
comparison
equal deleted inserted replaced
4851:dcd4702bcc21 4852:ecf9f13948f1
27 * http://www.pcisys.net/~melanson/codecs/ 27 * http://www.pcisys.net/~melanson/codecs/
28 */ 28 */
29 29
30 #include "libavutil/intreadwrite.h" 30 #include "libavutil/intreadwrite.h"
31 #include "avformat.h" 31 #include "avformat.h"
32
33 #define WC3_PREAMBLE_SIZE 8
34 32
35 #define FORM_TAG MKTAG('F', 'O', 'R', 'M') 33 #define FORM_TAG MKTAG('F', 'O', 'R', 'M')
36 #define MOVE_TAG MKTAG('M', 'O', 'V', 'E') 34 #define MOVE_TAG MKTAG('M', 'O', 'V', 'E')
37 #define PC__TAG MKTAG('_', 'P', 'C', '_') 35 #define PC__TAG MKTAG('_', 'P', 'C', '_')
38 #define SOND_TAG MKTAG('S', 'O', 'N', 'D') 36 #define SOND_TAG MKTAG('S', 'O', 'N', 'D')
129 Wc3DemuxContext *wc3 = s->priv_data; 127 Wc3DemuxContext *wc3 = s->priv_data;
130 ByteIOContext *pb = s->pb; 128 ByteIOContext *pb = s->pb;
131 unsigned int fourcc_tag; 129 unsigned int fourcc_tag;
132 unsigned int size; 130 unsigned int size;
133 AVStream *st; 131 AVStream *st;
134 unsigned char preamble[WC3_PREAMBLE_SIZE];
135 char buffer[513]; 132 char buffer[513];
136 int ret = 0; 133 int ret = 0;
137 int current_palette = 0; 134 int current_palette = 0;
138 int bytes_to_read; 135 int bytes_to_read;
139 int i; 136 int i;
150 /* skip the first 3 32-bit numbers */ 147 /* skip the first 3 32-bit numbers */
151 url_fseek(pb, 12, SEEK_CUR); 148 url_fseek(pb, 12, SEEK_CUR);
152 149
153 /* traverse through the chunks and load the header information before 150 /* traverse through the chunks and load the header information before
154 * the first BRCH tag */ 151 * the first BRCH tag */
155 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 152 fourcc_tag = get_le32(pb);
156 WC3_PREAMBLE_SIZE) 153 size = (get_be32(pb) + 1) & (~1);
157 return AVERROR(EIO);
158 fourcc_tag = AV_RL32(&preamble[0]);
159 size = (AV_RB32(&preamble[4]) + 1) & (~1);
160 154
161 do { 155 do {
162 switch (fourcc_tag) { 156 switch (fourcc_tag) {
163 157
164 case SOND_TAG: 158 case SOND_TAG:
168 break; 162 break;
169 163
170 case PC__TAG: 164 case PC__TAG:
171 /* need the number of palettes */ 165 /* need the number of palettes */
172 url_fseek(pb, 8, SEEK_CUR); 166 url_fseek(pb, 8, SEEK_CUR);
173 if ((ret = get_buffer(pb, preamble, 4)) != 4) 167 wc3->palette_count = get_le32(pb);
174 return AVERROR(EIO);
175 wc3->palette_count = AV_RL32(&preamble[0]);
176 if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){ 168 if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){
177 wc3->palette_count= 0; 169 wc3->palette_count= 0;
178 return -1; 170 return -1;
179 } 171 }
180 wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE); 172 wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
192 av_metadata_set(&s->metadata, "title", buffer); 184 av_metadata_set(&s->metadata, "title", buffer);
193 break; 185 break;
194 186
195 case SIZE_TAG: 187 case SIZE_TAG:
196 /* video resolution override */ 188 /* video resolution override */
197 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 189 wc3->width = get_le32(pb);
198 WC3_PREAMBLE_SIZE) 190 wc3->height = get_le32(pb);
199 return AVERROR(EIO);
200 wc3->width = AV_RL32(&preamble[0]);
201 wc3->height = AV_RL32(&preamble[4]);
202 break; 191 break;
203 192
204 case PALT_TAG: 193 case PALT_TAG:
205 /* one of several palettes */ 194 /* one of several palettes */
206 if ((unsigned)current_palette >= wc3->palette_count) 195 if ((unsigned)current_palette >= wc3->palette_count)
222 current_palette++; 211 current_palette++;
223 break; 212 break;
224 213
225 default: 214 default:
226 av_log(s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n", 215 av_log(s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
227 preamble[0], preamble[1], preamble[2], preamble[3], 216 (char)fourcc_tag, (char)(fourcc_tag >> 8), (char)(fourcc_tag >> 16), (char)(fourcc_tag >> 24),
228 preamble[0], preamble[1], preamble[2], preamble[3]); 217 (char)fourcc_tag, (char)(fourcc_tag >> 8), (char)(fourcc_tag >> 16), (char)(fourcc_tag >> 24));
229 return AVERROR_INVALIDDATA; 218 return AVERROR_INVALIDDATA;
230 break; 219 break;
231 } 220 }
232 221
233 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 222 fourcc_tag = get_le32(pb);
234 WC3_PREAMBLE_SIZE) 223 /* chunk sizes are 16-bit aligned */
224 size = (get_be32(pb) + 1) & (~1);
225 if (url_feof(pb))
235 return AVERROR(EIO); 226 return AVERROR(EIO);
236 fourcc_tag = AV_RL32(&preamble[0]);
237 /* chunk sizes are 16-bit aligned */
238 size = (AV_RB32(&preamble[4]) + 1) & (~1);
239 227
240 } while (fourcc_tag != BRCH_TAG); 228 } while (fourcc_tag != BRCH_TAG);
241 229
242 /* initialize the decoder streams */ 230 /* initialize the decoder streams */
243 st = av_new_stream(s, 0); 231 st = av_new_stream(s, 0);
279 ByteIOContext *pb = s->pb; 267 ByteIOContext *pb = s->pb;
280 unsigned int fourcc_tag; 268 unsigned int fourcc_tag;
281 unsigned int size; 269 unsigned int size;
282 int packet_read = 0; 270 int packet_read = 0;
283 int ret = 0; 271 int ret = 0;
284 unsigned char preamble[WC3_PREAMBLE_SIZE];
285 unsigned char text[1024]; 272 unsigned char text[1024];
286 unsigned int palette_number; 273 unsigned int palette_number;
287 int i; 274 int i;
288 unsigned char r, g, b; 275 unsigned char r, g, b;
289 int base_palette_index; 276 int base_palette_index;
290 277
291 while (!packet_read) { 278 while (!packet_read) {
292 279
293 /* get the next chunk preamble */ 280 fourcc_tag = get_le32(pb);
294 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 281 /* chunk sizes are 16-bit aligned */
295 WC3_PREAMBLE_SIZE) 282 size = (get_be32(pb) + 1) & (~1);
283 if (url_feof(pb))
296 return AVERROR(EIO); 284 return AVERROR(EIO);
297
298 fourcc_tag = AV_RL32(&preamble[0]);
299 /* chunk sizes are 16-bit aligned */
300 size = (AV_RB32(&preamble[4]) + 1) & (~1);
301 285
302 switch (fourcc_tag) { 286 switch (fourcc_tag) {
303 287
304 case BRCH_TAG: 288 case BRCH_TAG:
305 /* no-op */ 289 /* no-op */
306 break; 290 break;
307 291
308 case SHOT_TAG: 292 case SHOT_TAG:
309 /* load up new palette */ 293 /* load up new palette */
310 if ((ret = get_buffer(pb, preamble, 4)) != 4) 294 palette_number = get_le32(pb);
311 return AVERROR(EIO);
312 palette_number = AV_RL32(&preamble[0]);
313 if (palette_number >= wc3->palette_count) 295 if (palette_number >= wc3->palette_count)
314 return AVERROR_INVALIDDATA; 296 return AVERROR_INVALIDDATA;
315 base_palette_index = palette_number * PALETTE_COUNT * 3; 297 base_palette_index = palette_number * PALETTE_COUNT * 3;
316 for (i = 0; i < PALETTE_COUNT; i++) { 298 for (i = 0; i < PALETTE_COUNT; i++) {
317 r = wc3->palettes[base_palette_index + i * 3 + 0]; 299 r = wc3->palettes[base_palette_index + i * 3 + 0];
365 packet_read = 1; 347 packet_read = 1;
366 break; 348 break;
367 349
368 default: 350 default:
369 av_log (s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n", 351 av_log (s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
370 preamble[0], preamble[1], preamble[2], preamble[3], 352 (char)fourcc_tag, (char)(fourcc_tag >> 8), (char)(fourcc_tag >> 16), (char)(fourcc_tag >> 24),
371 preamble[0], preamble[1], preamble[2], preamble[3]); 353 (char)fourcc_tag, (char)(fourcc_tag >> 8), (char)(fourcc_tag >> 16), (char)(fourcc_tag >> 24));
372 ret = AVERROR_INVALIDDATA; 354 ret = AVERROR_INVALIDDATA;
373 packet_read = 1; 355 packet_read = 1;
374 break; 356 break;
375 } 357 }
376 } 358 }