]> git.sesse.net Git - ffmpeg/blob - libavformat/wc3movie.c
(f)printf() is disallowed in libavcodec, compilation will fail now if its used, excep...
[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 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             printf ("  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                 printf ("Subtitle time!\n");
356                 printf ("  inglish: %s\n", &text[i + 1]);
357                 i += text[i] + 1;
358                 printf ("  doytsch: %s\n", &text[i + 1]);
359                 i += text[i] + 1;
360                 printf ("  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             printf ("  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 }