various security fixes and precautionary checks
[libav.git] / libavformat / wc3movie.c
CommitLineData
493645eb
MM
1/*
2 * Wing Commander III Movie (.mve) File Demuxer
3 * Copyright (c) 2003 The ffmpeg Project
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/**
21 * @file wc3movie.c
22 * Wing Commander III Movie file demuxer
23 * by Mike Melanson (melanson@pcisys.net)
24 * for more information on the WC3 .mve file format, visit:
25 * http://www.pcisys.net/~melanson/codecs/
26 */
27
28#include "avformat.h"
29
493645eb
MM
30#define WC3_PREAMBLE_SIZE 8
31
3a278992
MM
32#define FORM_TAG MKTAG('F', 'O', 'R', 'M')
33#define MOVE_TAG MKTAG('M', 'O', 'V', 'E')
34#define _PC__TAG MKTAG('_', 'P', 'C', '_')
35#define SOND_TAG MKTAG('S', 'O', 'N', 'D')
36#define BNAM_TAG MKTAG('B', 'N', 'A', 'M')
37#define SIZE_TAG MKTAG('S', 'I', 'Z', 'E')
38#define PALT_TAG MKTAG('P', 'A', 'L', 'T')
39#define INDX_TAG MKTAG('I', 'N', 'D', 'X')
40#define BRCH_TAG MKTAG('B', 'R', 'C', 'H')
41#define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
42#define VGA__TAG MKTAG('V', 'G', 'A', ' ')
43#define TEXT_TAG MKTAG('T', 'E', 'X', 'T')
44#define AUDI_TAG MKTAG('A', 'U', 'D', 'I')
493645eb
MM
45
46/* video resolution unless otherwise specified */
47#define WC3_DEFAULT_WIDTH 320
48#define WC3_DEFAULT_HEIGHT 165
49
50/* always use the same PCM audio parameters */
51#define WC3_SAMPLE_RATE 22050
52#define WC3_AUDIO_CHANNELS 1
53#define WC3_AUDIO_BITS 16
54
55/* nice, constant framerate */
56#define WC3_FRAME_PTS_INC (90000 / 15)
57
58#define PALETTE_SIZE (256 * 3)
59#define PALETTE_COUNT 256
493645eb
MM
60
61typedef struct Wc3DemuxContext {
62 int width;
63 int height;
64 unsigned char *palettes;
65 int palette_count;
66 int64_t pts;
67 int video_stream_index;
68 int audio_stream_index;
69
ba118447 70 AVPaletteControl palette_control;
493645eb
MM
71
72} Wc3DemuxContext;
73
74/* bizarre palette lookup table */
7e5ef401 75static const unsigned char wc3_pal_lookup[] = {
493645eb
MM
76 0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E,
77 0x10, 0x12, 0x13, 0x15, 0x16, 0x18, 0x19, 0x1A,
78 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25,
79 0x27, 0x28, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F,
80 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39,
81 0x3A, 0x3B, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x42,
82 0x43, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4B,
83 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
84 0x54, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C,
85 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64,
86 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
87 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
88 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
89 0x7D, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
90 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B,
91 0x8C, 0x8D, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
92 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99,
93 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1,
94 0xA2, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
95 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
96 0xB0, 0xB1, 0xB2, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
97 0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD,
98 0xBE, 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4,
99 0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB,
100 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD0, 0xD1,
101 0xD2, 0xD3, 0xD4, 0xD5, 0xD5, 0xD6, 0xD7, 0xD8,
102 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
103 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5,
104 0xE6, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEB, 0xEC,
105 0xED, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2,
106 0xF3, 0xF4, 0xF5, 0xF6, 0xF6, 0xF7, 0xF8, 0xF9,
107 0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD
108};
109
110
111static int wc3_probe(AVProbeData *p)
112{
113 if (p->buf_size < 12)
114 return 0;
115
116 if ((LE_32(&p->buf[0]) != FORM_TAG) ||
117 (LE_32(&p->buf[8]) != MOVE_TAG))
118 return 0;
119
120 return AVPROBE_SCORE_MAX;
121}
122
123static int wc3_read_header(AVFormatContext *s,
124 AVFormatParameters *ap)
125{
126 Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
127 ByteIOContext *pb = &s->pb;
128 unsigned int fourcc_tag;
129 unsigned int size;
130 AVStream *st;
131 unsigned char preamble[WC3_PREAMBLE_SIZE];
132 int ret = 0;
133 int current_palette = 0;
134 int bytes_to_read;
135 int i;
7e5ef401 136 unsigned char rotate;
493645eb
MM
137
138 /* default context members */
139 wc3->width = WC3_DEFAULT_WIDTH;
140 wc3->height = WC3_DEFAULT_HEIGHT;
141 wc3->palettes = NULL;
142 wc3->palette_count = 0;
143 wc3->pts = 0;
144 wc3->video_stream_index = wc3->audio_stream_index = 0;
493645eb
MM
145
146 /* skip the first 3 32-bit numbers */
147 url_fseek(pb, 12, SEEK_CUR);
148
149 /* traverse through the chunks and load the header information before
150 * the first BRCH tag */
151 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
152 WC3_PREAMBLE_SIZE)
0bd586c5 153 return AVERROR_IO;
493645eb
MM
154 fourcc_tag = LE_32(&preamble[0]);
155 size = (BE_32(&preamble[4]) + 1) & (~1);
156
157 do {
158 switch (fourcc_tag) {
159
160 case SOND_TAG:
161 case INDX_TAG:
162 /* SOND unknown, INDX unnecessary; ignore both */
163 url_fseek(pb, size, SEEK_CUR);
164 break;
165
166 case _PC__TAG:
167 /* need the number of palettes */
168 url_fseek(pb, 8, SEEK_CUR);
169 if ((ret = get_buffer(pb, preamble, 4)) != 4)
0bd586c5 170 return AVERROR_IO;
493645eb 171 wc3->palette_count = LE_32(&preamble[0]);
0ecca7a4
MN
172 if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){
173 wc3->palette_count= 0;
568e18b1 174 return -1;
0ecca7a4 175 }
493645eb
MM
176 wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
177 break;
178
179 case BNAM_TAG:
180 /* load up the name */
0ecca7a4 181 if ((unsigned)size < 512)
493645eb
MM
182 bytes_to_read = size;
183 else
184 bytes_to_read = 512;
185 if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)
0bd586c5 186 return AVERROR_IO;
493645eb
MM
187 break;
188
189 case SIZE_TAG:
190 /* video resolution override */
191 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
192 WC3_PREAMBLE_SIZE)
0bd586c5 193 return AVERROR_IO;
493645eb
MM
194 wc3->width = LE_32(&preamble[0]);
195 wc3->height = LE_32(&preamble[4]);
196 break;
197
198 case PALT_TAG:
199 /* one of several palettes */
0ecca7a4 200 if ((unsigned)current_palette >= wc3->palette_count)
493645eb
MM
201 return AVERROR_INVALIDDATA;
202 if ((ret = get_buffer(pb,
203 &wc3->palettes[current_palette * PALETTE_SIZE],
204 PALETTE_SIZE)) != PALETTE_SIZE)
0bd586c5 205 return AVERROR_IO;
493645eb
MM
206
207 /* transform the current palette in place */
208 for (i = current_palette * PALETTE_SIZE;
209 i < (current_palette + 1) * PALETTE_SIZE; i++) {
7e5ef401
MM
210 /* rotate each palette component left by 2 and use the result
211 * as an index into the color component table */
212 rotate = ((wc3->palettes[i] << 2) & 0xFF) |
213 ((wc3->palettes[i] >> 6) & 0xFF);
214 wc3->palettes[i] = wc3_pal_lookup[rotate];
493645eb
MM
215 }
216 current_palette++;
217 break;
218
219 default:
bc874dae 220 av_log(s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
493645eb
MM
221 preamble[0], preamble[1], preamble[2], preamble[3],
222 preamble[0], preamble[1], preamble[2], preamble[3]);
223 return AVERROR_INVALIDDATA;
224 break;
225 }
226
227 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
228 WC3_PREAMBLE_SIZE)
0bd586c5 229 return AVERROR_IO;
493645eb
MM
230 fourcc_tag = LE_32(&preamble[0]);
231 /* chunk sizes are 16-bit aligned */
232 size = (BE_32(&preamble[4]) + 1) & (~1);
233
234 } while (fourcc_tag != BRCH_TAG);
235
236 /* initialize the decoder streams */
237 st = av_new_stream(s, 0);
238 if (!st)
239 return AVERROR_NOMEM;
9ee91c2f 240 av_set_pts_info(st, 33, 1, 90000);
493645eb
MM
241 wc3->video_stream_index = st->index;
242 st->codec.codec_type = CODEC_TYPE_VIDEO;
243 st->codec.codec_id = CODEC_ID_XAN_WC3;
244 st->codec.codec_tag = 0; /* no fourcc */
245 st->codec.width = wc3->width;
246 st->codec.height = wc3->height;
247
248 /* palette considerations */
2a2bbcb0 249 st->codec.palctrl = &wc3->palette_control;
493645eb
MM
250
251 st = av_new_stream(s, 0);
252 if (!st)
253 return AVERROR_NOMEM;
9ee91c2f 254 av_set_pts_info(st, 33, 1, 90000);
493645eb
MM
255 wc3->audio_stream_index = st->index;
256 st->codec.codec_type = CODEC_TYPE_AUDIO;
257 st->codec.codec_id = CODEC_ID_PCM_S16LE;
258 st->codec.codec_tag = 1;
259 st->codec.channels = WC3_AUDIO_CHANNELS;
260 st->codec.bits_per_sample = WC3_AUDIO_BITS;
261 st->codec.sample_rate = WC3_SAMPLE_RATE;
262 st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
263 st->codec.bits_per_sample;
264 st->codec.block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
265
493645eb
MM
266 return 0;
267}
268
269static int wc3_read_packet(AVFormatContext *s,
270 AVPacket *pkt)
271{
272 Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
273 ByteIOContext *pb = &s->pb;
274 unsigned int fourcc_tag;
275 unsigned int size;
276 int packet_read = 0;
277 int ret = 0;
278 unsigned char preamble[WC3_PREAMBLE_SIZE];
279 unsigned char text[1024];
280 unsigned int palette_number;
2a2bbcb0
MM
281 int i;
282 unsigned char r, g, b;
283 int base_palette_index;
493645eb
MM
284
285 while (!packet_read) {
286
287 /* get the next chunk preamble */
288 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
289 WC3_PREAMBLE_SIZE)
0bd586c5 290 ret = AVERROR_IO;
493645eb
MM
291
292 fourcc_tag = LE_32(&preamble[0]);
293 /* chunk sizes are 16-bit aligned */
294 size = (BE_32(&preamble[4]) + 1) & (~1);
295
296 switch (fourcc_tag) {
297
298 case BRCH_TAG:
299 /* no-op */
300 break;
301
302 case SHOT_TAG:
303 /* load up new palette */
304 if ((ret = get_buffer(pb, preamble, 4)) != 4)
0bd586c5 305 return AVERROR_IO;
493645eb
MM
306 palette_number = LE_32(&preamble[0]);
307 if (palette_number >= wc3->palette_count)
308 return AVERROR_INVALIDDATA;
2a2bbcb0
MM
309 base_palette_index = palette_number * PALETTE_COUNT * 3;
310 for (i = 0; i < PALETTE_COUNT; i++) {
311 r = wc3->palettes[base_palette_index + i * 3 + 0];
312 g = wc3->palettes[base_palette_index + i * 3 + 1];
313 b = wc3->palettes[base_palette_index + i * 3 + 2];
314 wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
315 }
ba118447 316 wc3->palette_control.palette_changed = 1;
493645eb
MM
317 break;
318
319 case VGA__TAG:
320 /* send out video chunk */
321 if (av_new_packet(pkt, size))
0bd586c5 322 ret = AVERROR_IO;
493645eb
MM
323 pkt->stream_index = wc3->video_stream_index;
324 pkt->pts = wc3->pts;
325 ret = get_buffer(pb, pkt->data, size);
326 if (ret != size)
0bd586c5 327 ret = AVERROR_IO;
493645eb
MM
328 packet_read = 1;
329 break;
330
331 case TEXT_TAG:
332 /* subtitle chunk */
333#if 0
334 url_fseek(pb, size, SEEK_CUR);
335#else
0ecca7a4 336 if ((unsigned)size > sizeof(text) || (ret = get_buffer(pb, text, size)) != size)
0bd586c5 337 ret = AVERROR_IO;
493645eb
MM
338 else {
339 int i = 0;
bc874dae
MB
340 av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
341 av_log (s, AV_LOG_DEBUG, " inglish: %s\n", &text[i + 1]);
493645eb 342 i += text[i] + 1;
bc874dae 343 av_log (s, AV_LOG_DEBUG, " doytsch: %s\n", &text[i + 1]);
493645eb 344 i += text[i] + 1;
bc874dae 345 av_log (s, AV_LOG_DEBUG, " fronsay: %s\n", &text[i + 1]);
493645eb
MM
346 }
347#endif
348 break;
349
350 case AUDI_TAG:
351 /* send out audio chunk */
352 if (av_new_packet(pkt, size))
0bd586c5 353 ret = AVERROR_IO;
493645eb
MM
354 pkt->stream_index = wc3->audio_stream_index;
355 pkt->pts = wc3->pts;
356 ret = get_buffer(pb, pkt->data, size);
357 if (ret != size)
0bd586c5 358 ret = AVERROR_IO;
493645eb
MM
359
360 /* time to advance pts */
361 wc3->pts += WC3_FRAME_PTS_INC;
362
363 packet_read = 1;
364 break;
365
366 default:
bc874dae 367 av_log (s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
493645eb
MM
368 preamble[0], preamble[1], preamble[2], preamble[3],
369 preamble[0], preamble[1], preamble[2], preamble[3]);
370 ret = AVERROR_INVALIDDATA;
371 packet_read = 1;
372 break;
373 }
374 }
375
376 return ret;
377}
378
379static int wc3_read_close(AVFormatContext *s)
380{
381 Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
382
383 av_free(wc3->palettes);
493645eb
MM
384
385 return 0;
386}
387
388static AVInputFormat wc3_iformat = {
389 "wc3movie",
390 "Wing Commander III movie format",
391 sizeof(Wc3DemuxContext),
392 wc3_probe,
393 wc3_read_header,
394 wc3_read_packet,
395 wc3_read_close,
396};
397
398int wc3_init(void)
399{
400 av_register_input_format(&wc3_iformat);
401 return 0;
402}