comparison wc3movie.c @ 225:d0332f4362b6 libavformat

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