2 * Wing Commander III Movie (.mve) File Demuxer
3 * Copyright (c) 2003 The ffmpeg Project
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.
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.
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
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/
30 #define WC3_PREAMBLE_SIZE 8
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')
46 /* video resolution unless otherwise specified */
47 #define WC3_DEFAULT_WIDTH 320
48 #define WC3_DEFAULT_HEIGHT 165
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
55 /* nice, constant framerate */
56 #define WC3_FRAME_PTS_INC (90000 / 15)
58 #define PALETTE_SIZE (256 * 3)
59 #define PALETTE_COUNT 256
61 typedef struct Wc3DemuxContext {
64 unsigned char *palettes;
67 int video_stream_index;
68 int audio_stream_index;
70 AVPaletteControl palette_control;
74 /* bizarre palette lookup table */
75 static const unsigned char wc3_pal_lookup[] = {
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
111 static int wc3_probe(AVProbeData *p)
113 if (p->buf_size < 12)
116 if ((LE_32(&p->buf[0]) != FORM_TAG) ||
117 (LE_32(&p->buf[8]) != MOVE_TAG))
120 return AVPROBE_SCORE_MAX;
123 static int wc3_read_header(AVFormatContext *s,
124 AVFormatParameters *ap)
126 Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
127 ByteIOContext *pb = &s->pb;
128 unsigned int fourcc_tag;
131 unsigned char preamble[WC3_PREAMBLE_SIZE];
133 int current_palette = 0;
136 unsigned char rotate;
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;
144 wc3->video_stream_index = wc3->audio_stream_index = 0;
146 /* skip the first 3 32-bit numbers */
147 url_fseek(pb, 12, SEEK_CUR);
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)) !=
154 fourcc_tag = LE_32(&preamble[0]);
155 size = (BE_32(&preamble[4]) + 1) & (~1);
158 switch (fourcc_tag) {
162 /* SOND unknown, INDX unnecessary; ignore both */
163 url_fseek(pb, size, SEEK_CUR);
167 /* need the number of palettes */
168 url_fseek(pb, 8, SEEK_CUR);
169 if ((ret = get_buffer(pb, preamble, 4)) != 4)
171 wc3->palette_count = LE_32(&preamble[0]);
172 wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
176 /* load up the name */
178 bytes_to_read = size;
181 if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)
186 /* video resolution override */
187 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
190 wc3->width = LE_32(&preamble[0]);
191 wc3->height = LE_32(&preamble[4]);
195 /* one of several palettes */
196 if (current_palette >= wc3->palette_count)
197 return AVERROR_INVALIDDATA;
198 if ((ret = get_buffer(pb,
199 &wc3->palettes[current_palette * PALETTE_SIZE],
200 PALETTE_SIZE)) != PALETTE_SIZE)
203 /* transform the current palette in place */
204 for (i = current_palette * PALETTE_SIZE;
205 i < (current_palette + 1) * PALETTE_SIZE; i++) {
206 /* rotate each palette component left by 2 and use the result
207 * as an index into the color component table */
208 rotate = ((wc3->palettes[i] << 2) & 0xFF) |
209 ((wc3->palettes[i] >> 6) & 0xFF);
210 wc3->palettes[i] = wc3_pal_lookup[rotate];
216 av_log(s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
217 preamble[0], preamble[1], preamble[2], preamble[3],
218 preamble[0], preamble[1], preamble[2], preamble[3]);
219 return AVERROR_INVALIDDATA;
223 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
226 fourcc_tag = LE_32(&preamble[0]);
227 /* chunk sizes are 16-bit aligned */
228 size = (BE_32(&preamble[4]) + 1) & (~1);
230 } while (fourcc_tag != BRCH_TAG);
232 /* initialize the decoder streams */
233 st = av_new_stream(s, 0);
235 return AVERROR_NOMEM;
236 av_set_pts_info(st, 33, 1, 90000);
237 wc3->video_stream_index = st->index;
238 st->codec.codec_type = CODEC_TYPE_VIDEO;
239 st->codec.codec_id = CODEC_ID_XAN_WC3;
240 st->codec.codec_tag = 0; /* no fourcc */
241 st->codec.width = wc3->width;
242 st->codec.height = wc3->height;
244 /* palette considerations */
245 st->codec.palctrl = &wc3->palette_control;
247 st = av_new_stream(s, 0);
249 return AVERROR_NOMEM;
250 av_set_pts_info(st, 33, 1, 90000);
251 wc3->audio_stream_index = st->index;
252 st->codec.codec_type = CODEC_TYPE_AUDIO;
253 st->codec.codec_id = CODEC_ID_PCM_S16LE;
254 st->codec.codec_tag = 1;
255 st->codec.channels = WC3_AUDIO_CHANNELS;
256 st->codec.bits_per_sample = WC3_AUDIO_BITS;
257 st->codec.sample_rate = WC3_SAMPLE_RATE;
258 st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
259 st->codec.bits_per_sample;
260 st->codec.block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
265 static int wc3_read_packet(AVFormatContext *s,
268 Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
269 ByteIOContext *pb = &s->pb;
270 unsigned int fourcc_tag;
274 unsigned char preamble[WC3_PREAMBLE_SIZE];
275 unsigned char text[1024];
276 unsigned int palette_number;
278 unsigned char r, g, b;
279 int base_palette_index;
281 while (!packet_read) {
283 /* get the next chunk preamble */
284 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
288 fourcc_tag = LE_32(&preamble[0]);
289 /* chunk sizes are 16-bit aligned */
290 size = (BE_32(&preamble[4]) + 1) & (~1);
292 switch (fourcc_tag) {
299 /* load up new palette */
300 if ((ret = get_buffer(pb, preamble, 4)) != 4)
302 palette_number = LE_32(&preamble[0]);
303 if (palette_number >= wc3->palette_count)
304 return AVERROR_INVALIDDATA;
305 base_palette_index = palette_number * PALETTE_COUNT * 3;
306 for (i = 0; i < PALETTE_COUNT; i++) {
307 r = wc3->palettes[base_palette_index + i * 3 + 0];
308 g = wc3->palettes[base_palette_index + i * 3 + 1];
309 b = wc3->palettes[base_palette_index + i * 3 + 2];
310 wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
312 wc3->palette_control.palette_changed = 1;
316 /* send out video chunk */
317 if (av_new_packet(pkt, size))
319 pkt->stream_index = wc3->video_stream_index;
321 ret = get_buffer(pb, pkt->data, size);
330 url_fseek(pb, size, SEEK_CUR);
332 if ((ret = get_buffer(pb, text, size)) != size)
336 av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
337 av_log (s, AV_LOG_DEBUG, " inglish: %s\n", &text[i + 1]);
339 av_log (s, AV_LOG_DEBUG, " doytsch: %s\n", &text[i + 1]);
341 av_log (s, AV_LOG_DEBUG, " fronsay: %s\n", &text[i + 1]);
347 /* send out audio chunk */
348 if (av_new_packet(pkt, size))
350 pkt->stream_index = wc3->audio_stream_index;
352 ret = get_buffer(pb, pkt->data, size);
356 /* time to advance pts */
357 wc3->pts += WC3_FRAME_PTS_INC;
363 av_log (s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
364 preamble[0], preamble[1], preamble[2], preamble[3],
365 preamble[0], preamble[1], preamble[2], preamble[3]);
366 ret = AVERROR_INVALIDDATA;
375 static int wc3_read_close(AVFormatContext *s)
377 Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
379 av_free(wc3->palettes);
384 static AVInputFormat wc3_iformat = {
386 "Wing Commander III movie format",
387 sizeof(Wc3DemuxContext),
396 av_register_input_format(&wc3_iformat);