]> git.sesse.net Git - ffmpeg/blob - libavformat/wc3movie.c
fix rounding errors with NTSC patch by (Luca Abeni <lucabe72 at email dot it>)
[ffmpeg] / 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 WC3_PREAMBLE_SIZE 8
31
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')
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
60
61 typedef 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
70     AVPaletteControl palette_control;
71
72 } Wc3DemuxContext;
73
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
108 };
109
110
111 static 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
123 static 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;
136     unsigned char rotate;
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;
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)
153         return -EIO;
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)
170                 return -EIO;
171             wc3->palette_count = LE_32(&preamble[0]);
172             wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
173             break;
174
175         case BNAM_TAG:
176             /* load up the name */
177             if (size < 512)
178                 bytes_to_read = size;
179             else
180                 bytes_to_read = 512;
181             if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)
182                 return -EIO;
183             break;
184
185         case SIZE_TAG:
186             /* video resolution override */
187             if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 
188                 WC3_PREAMBLE_SIZE)
189                 return -EIO;
190             wc3->width = LE_32(&preamble[0]);
191             wc3->height = LE_32(&preamble[4]);
192             break;
193
194         case PALT_TAG:
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)
201                 return -EIO;
202
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];
211             }
212             current_palette++;
213             break;
214
215         default:
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;
220             break;
221         }
222
223         if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 
224             WC3_PREAMBLE_SIZE)
225             return -EIO;
226         fourcc_tag = LE_32(&preamble[0]);
227         /* chunk sizes are 16-bit aligned */
228         size = (BE_32(&preamble[4]) + 1) & (~1);
229
230     } while (fourcc_tag != BRCH_TAG);
231
232     /* initialize the decoder streams */
233     st = av_new_stream(s, 0);
234     if (!st)
235         return AVERROR_NOMEM;
236     wc3->video_stream_index = st->index;
237     st->codec.codec_type = CODEC_TYPE_VIDEO;
238     st->codec.codec_id = CODEC_ID_XAN_WC3;
239     st->codec.codec_tag = 0;  /* no fourcc */
240     st->codec.width = wc3->width;
241     st->codec.height = wc3->height;
242
243     /* palette considerations */
244     st->codec.palctrl = &wc3->palette_control;
245
246     st = av_new_stream(s, 0);
247     if (!st)
248         return AVERROR_NOMEM;
249     wc3->audio_stream_index = st->index;
250     st->codec.codec_type = CODEC_TYPE_AUDIO;
251     st->codec.codec_id = CODEC_ID_PCM_S16LE;
252     st->codec.codec_tag = 1;
253     st->codec.channels = WC3_AUDIO_CHANNELS;
254     st->codec.bits_per_sample = WC3_AUDIO_BITS;
255     st->codec.sample_rate = WC3_SAMPLE_RATE;
256     st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
257         st->codec.bits_per_sample;
258     st->codec.block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
259
260     /* set the pts reference (1 pts = 1/90000) */
261     s->pts_num = 1;
262     s->pts_den = 90000;
263
264     return 0;
265 }
266
267 static int wc3_read_packet(AVFormatContext *s,
268                            AVPacket *pkt)
269 {
270     Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
271     ByteIOContext *pb = &s->pb;
272     unsigned int fourcc_tag;
273     unsigned int size;
274     int packet_read = 0;
275     int ret = 0;
276     unsigned char preamble[WC3_PREAMBLE_SIZE];
277     unsigned char text[1024];
278     unsigned int palette_number;
279     int i;
280     unsigned char r, g, b;
281     int base_palette_index;
282
283     while (!packet_read) {
284
285         /* get the next chunk preamble */
286         if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
287             WC3_PREAMBLE_SIZE)
288             ret = -EIO;
289
290         fourcc_tag = LE_32(&preamble[0]);
291         /* chunk sizes are 16-bit aligned */
292         size = (BE_32(&preamble[4]) + 1) & (~1);
293
294         switch (fourcc_tag) {
295
296         case BRCH_TAG:
297             /* no-op */
298             break;
299
300         case SHOT_TAG:
301             /* load up new palette */
302             if ((ret = get_buffer(pb, preamble, 4)) != 4)
303                 return -EIO;
304             palette_number = LE_32(&preamble[0]);
305             if (palette_number >= wc3->palette_count)
306                 return AVERROR_INVALIDDATA;
307             base_palette_index = palette_number * PALETTE_COUNT * 3;
308             for (i = 0; i < PALETTE_COUNT; i++) {
309                 r = wc3->palettes[base_palette_index + i * 3 + 0];
310                 g = wc3->palettes[base_palette_index + i * 3 + 1];
311                 b = wc3->palettes[base_palette_index + i * 3 + 2];
312                 wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
313             }
314             wc3->palette_control.palette_changed = 1;
315             break;
316
317         case VGA__TAG:
318             /* send out video chunk */
319             if (av_new_packet(pkt, size))
320                 ret = -EIO;
321             pkt->stream_index = wc3->video_stream_index;
322             pkt->pts = wc3->pts;
323             ret = get_buffer(pb, pkt->data, size);
324             if (ret != size)
325                 ret = -EIO;
326             packet_read = 1;
327             break;
328
329         case TEXT_TAG:
330             /* subtitle chunk */
331 #if 0
332             url_fseek(pb, size, SEEK_CUR);
333 #else
334             if ((ret = get_buffer(pb, text, size)) != size)
335                 ret = -EIO;
336             else {
337                 int i = 0;
338                 av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
339                 av_log (s, AV_LOG_DEBUG, "  inglish: %s\n", &text[i + 1]);
340                 i += text[i] + 1;
341                 av_log (s, AV_LOG_DEBUG, "  doytsch: %s\n", &text[i + 1]);
342                 i += text[i] + 1;
343                 av_log (s, AV_LOG_DEBUG, "  fronsay: %s\n", &text[i + 1]);
344             }
345 #endif
346             break;
347
348         case AUDI_TAG:
349             /* send out audio chunk */
350             if (av_new_packet(pkt, size))
351                 ret = -EIO;
352             pkt->stream_index = wc3->audio_stream_index;
353             pkt->pts = wc3->pts;
354             ret = get_buffer(pb, pkt->data, size);
355             if (ret != size)
356                 ret = -EIO;
357
358             /* time to advance pts */
359             wc3->pts += WC3_FRAME_PTS_INC;
360
361             packet_read = 1;
362             break;
363
364         default:
365             av_log (s, AV_LOG_ERROR, "  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
366                 preamble[0], preamble[1], preamble[2], preamble[3],
367                 preamble[0], preamble[1], preamble[2], preamble[3]);
368             ret = AVERROR_INVALIDDATA;
369             packet_read = 1;
370             break;
371         }
372     }
373
374     return ret;
375 }
376
377 static int wc3_read_close(AVFormatContext *s)
378 {
379     Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
380
381     av_free(wc3->palettes);
382
383     return 0;
384 }
385
386 static AVInputFormat wc3_iformat = {
387     "wc3movie",
388     "Wing Commander III movie format",
389     sizeof(Wc3DemuxContext),
390     wc3_probe,
391     wc3_read_header,
392     wc3_read_packet,
393     wc3_read_close,
394 };
395
396 int wc3_init(void)
397 {
398     av_register_input_format(&wc3_iformat);
399     return 0;
400 }