Initial Stable Commit
[synfig.git] / synfig-core / trunk / src / modules / mod_libavcodec / 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.extradata_size = sizeof(AVPaletteControl);
262     st->codec.extradata = &wc3->palette_control;
263
264     st = av_new_stream(s, 0);
265     if (!st)
266         return AVERROR_NOMEM;
267     wc3->audio_stream_index = st->index;
268     st->codec.codec_type = CODEC_TYPE_AUDIO;
269     st->codec.codec_id = CODEC_ID_PCM_S16LE;
270     st->codec.codec_tag = 1;
271     st->codec.channels = WC3_AUDIO_CHANNELS;
272     st->codec.bits_per_sample = WC3_AUDIO_BITS;
273     st->codec.sample_rate = WC3_SAMPLE_RATE;
274     st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
275         st->codec.bits_per_sample;
276     st->codec.block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
277
278     /* set the pts reference (1 pts = 1/90000) */
279     s->pts_num = 1;
280     s->pts_den = 90000;
281
282     return 0;
283 }
284
285 static int wc3_read_packet(AVFormatContext *s,
286                            AVPacket *pkt)
287 {
288     Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
289     ByteIOContext *pb = &s->pb;
290     unsigned int fourcc_tag;
291     unsigned int size;
292     int packet_read = 0;
293     int ret = 0;
294     unsigned char preamble[WC3_PREAMBLE_SIZE];
295     unsigned char text[1024];
296     unsigned int palette_number;
297
298     while (!packet_read) {
299
300         /* get the next chunk preamble */
301         if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
302             WC3_PREAMBLE_SIZE)
303             ret = -EIO;
304
305         fourcc_tag = LE_32(&preamble[0]);
306         /* chunk sizes are 16-bit aligned */
307         size = (BE_32(&preamble[4]) + 1) & (~1);
308
309         switch (fourcc_tag) {
310
311         case BRCH_TAG:
312             /* no-op */
313             break;
314
315         case SHOT_TAG:
316             /* load up new palette */
317             if ((ret = get_buffer(pb, preamble, 4)) != 4)
318                 return -EIO;
319             palette_number = LE_32(&preamble[0]);
320             if (palette_number >= wc3->palette_count)
321                 return AVERROR_INVALIDDATA;
322             memcpy(wc3->palette_control.palette, 
323                 &wc3->palettes[palette_number * PALETTE_COUNT * 3],
324                 PALETTE_COUNT * 3);
325             wc3->palette_control.palette_changed = 1;
326             break;
327
328         case VGA__TAG:
329             /* send out video chunk */
330             if (av_new_packet(pkt, size))
331                 ret = -EIO;
332             pkt->stream_index = wc3->video_stream_index;
333             pkt->pts = wc3->pts;
334             ret = get_buffer(pb, pkt->data, size);
335             if (ret != size)
336                 ret = -EIO;
337             packet_read = 1;
338             break;
339
340         case TEXT_TAG:
341             /* subtitle chunk */
342 #if 0
343             url_fseek(pb, size, SEEK_CUR);
344 #else
345             if ((ret = get_buffer(pb, text, size)) != size)
346                 ret = -EIO;
347             else {
348                 int i = 0;
349                 printf ("Subtitle time!\n");
350                 printf ("  inglish: %s\n", &text[i + 1]);
351                 i += text[i] + 1;
352                 printf ("  doytsch: %s\n", &text[i + 1]);
353                 i += text[i] + 1;
354                 printf ("  fronsay: %s\n", &text[i + 1]);
355             }
356 #endif
357             break;
358
359         case AUDI_TAG:
360             /* send out audio chunk */
361             if (av_new_packet(pkt, size))
362                 ret = -EIO;
363             pkt->stream_index = wc3->audio_stream_index;
364             pkt->pts = wc3->pts;
365             ret = get_buffer(pb, pkt->data, size);
366             if (ret != size)
367                 ret = -EIO;
368
369             /* time to advance pts */
370             wc3->pts += WC3_FRAME_PTS_INC;
371
372             packet_read = 1;
373             break;
374
375         default:
376             printf ("  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
377                 preamble[0], preamble[1], preamble[2], preamble[3],
378                 preamble[0], preamble[1], preamble[2], preamble[3]);
379             ret = AVERROR_INVALIDDATA;
380             packet_read = 1;
381             break;
382         }
383     }
384
385     return ret;
386 }
387
388 static int wc3_read_close(AVFormatContext *s)
389 {
390     Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
391
392     av_free(wc3->palettes);
393
394     return 0;
395 }
396
397 static AVInputFormat wc3_iformat = {
398     "wc3movie",
399     "Wing Commander III movie format",
400     sizeof(Wc3DemuxContext),
401     wc3_probe,
402     wc3_read_header,
403     wc3_read_packet,
404     wc3_read_close,
405 };
406
407 int wc3_init(void)
408 {
409     av_register_input_format(&wc3_iformat);
410     return 0;
411 }