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