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