]> git.sesse.net Git - ffmpeg/blob - libavformat/wc3movie.c
sweeping change from -EIO -> AVERROR_IO
[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 AVERROR_IO;
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 AVERROR_IO;
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 AVERROR_IO;
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 AVERROR_IO;
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 AVERROR_IO;
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 AVERROR_IO;
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     av_set_pts_info(st, 33, 1, 90000);
237     wc3->video_stream_index = st->index;
238     st->codec.codec_type = CODEC_TYPE_VIDEO;
239     st->codec.codec_id = CODEC_ID_XAN_WC3;
240     st->codec.codec_tag = 0;  /* no fourcc */
241     st->codec.width = wc3->width;
242     st->codec.height = wc3->height;
243
244     /* palette considerations */
245     st->codec.palctrl = &wc3->palette_control;
246
247     st = av_new_stream(s, 0);
248     if (!st)
249         return AVERROR_NOMEM;
250     av_set_pts_info(st, 33, 1, 90000);
251     wc3->audio_stream_index = st->index;
252     st->codec.codec_type = CODEC_TYPE_AUDIO;
253     st->codec.codec_id = CODEC_ID_PCM_S16LE;
254     st->codec.codec_tag = 1;
255     st->codec.channels = WC3_AUDIO_CHANNELS;
256     st->codec.bits_per_sample = WC3_AUDIO_BITS;
257     st->codec.sample_rate = WC3_SAMPLE_RATE;
258     st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
259         st->codec.bits_per_sample;
260     st->codec.block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
261
262     return 0;
263 }
264
265 static int wc3_read_packet(AVFormatContext *s,
266                            AVPacket *pkt)
267 {
268     Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
269     ByteIOContext *pb = &s->pb;
270     unsigned int fourcc_tag;
271     unsigned int size;
272     int packet_read = 0;
273     int ret = 0;
274     unsigned char preamble[WC3_PREAMBLE_SIZE];
275     unsigned char text[1024];
276     unsigned int palette_number;
277     int i;
278     unsigned char r, g, b;
279     int base_palette_index;
280
281     while (!packet_read) {
282
283         /* get the next chunk preamble */
284         if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
285             WC3_PREAMBLE_SIZE)
286             ret = AVERROR_IO;
287
288         fourcc_tag = LE_32(&preamble[0]);
289         /* chunk sizes are 16-bit aligned */
290         size = (BE_32(&preamble[4]) + 1) & (~1);
291
292         switch (fourcc_tag) {
293
294         case BRCH_TAG:
295             /* no-op */
296             break;
297
298         case SHOT_TAG:
299             /* load up new palette */
300             if ((ret = get_buffer(pb, preamble, 4)) != 4)
301                 return AVERROR_IO;
302             palette_number = LE_32(&preamble[0]);
303             if (palette_number >= wc3->palette_count)
304                 return AVERROR_INVALIDDATA;
305             base_palette_index = palette_number * PALETTE_COUNT * 3;
306             for (i = 0; i < PALETTE_COUNT; i++) {
307                 r = wc3->palettes[base_palette_index + i * 3 + 0];
308                 g = wc3->palettes[base_palette_index + i * 3 + 1];
309                 b = wc3->palettes[base_palette_index + i * 3 + 2];
310                 wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
311             }
312             wc3->palette_control.palette_changed = 1;
313             break;
314
315         case VGA__TAG:
316             /* send out video chunk */
317             if (av_new_packet(pkt, size))
318                 ret = AVERROR_IO;
319             pkt->stream_index = wc3->video_stream_index;
320             pkt->pts = wc3->pts;
321             ret = get_buffer(pb, pkt->data, size);
322             if (ret != size)
323                 ret = AVERROR_IO;
324             packet_read = 1;
325             break;
326
327         case TEXT_TAG:
328             /* subtitle chunk */
329 #if 0
330             url_fseek(pb, size, SEEK_CUR);
331 #else
332             if ((ret = get_buffer(pb, text, size)) != size)
333                 ret = AVERROR_IO;
334             else {
335                 int i = 0;
336                 av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
337                 av_log (s, AV_LOG_DEBUG, "  inglish: %s\n", &text[i + 1]);
338                 i += text[i] + 1;
339                 av_log (s, AV_LOG_DEBUG, "  doytsch: %s\n", &text[i + 1]);
340                 i += text[i] + 1;
341                 av_log (s, AV_LOG_DEBUG, "  fronsay: %s\n", &text[i + 1]);
342             }
343 #endif
344             break;
345
346         case AUDI_TAG:
347             /* send out audio chunk */
348             if (av_new_packet(pkt, size))
349                 ret = AVERROR_IO;
350             pkt->stream_index = wc3->audio_stream_index;
351             pkt->pts = wc3->pts;
352             ret = get_buffer(pb, pkt->data, size);
353             if (ret != size)
354                 ret = AVERROR_IO;
355
356             /* time to advance pts */
357             wc3->pts += WC3_FRAME_PTS_INC;
358
359             packet_read = 1;
360             break;
361
362         default:
363             av_log (s, AV_LOG_ERROR, "  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
364                 preamble[0], preamble[1], preamble[2], preamble[3],
365                 preamble[0], preamble[1], preamble[2], preamble[3]);
366             ret = AVERROR_INVALIDDATA;
367             packet_read = 1;
368             break;
369         }
370     }
371
372     return ret;
373 }
374
375 static int wc3_read_close(AVFormatContext *s)
376 {
377     Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
378
379     av_free(wc3->palettes);
380
381     return 0;
382 }
383
384 static AVInputFormat wc3_iformat = {
385     "wc3movie",
386     "Wing Commander III movie format",
387     sizeof(Wc3DemuxContext),
388     wc3_probe,
389     wc3_read_header,
390     wc3_read_packet,
391     wc3_read_close,
392 };
393
394 int wc3_init(void)
395 {
396     av_register_input_format(&wc3_iformat);
397     return 0;
398 }