]> git.sesse.net Git - ffmpeg/blob - libavformat/wc3movie.c
fix wc3movie demuxer to conform to the PTS API
[ffmpeg] / libavformat / wc3movie.c
1 /*
2  * Wing Commander III Movie (.mve) File Demuxer
3  * Copyright (c) 2003 The ffmpeg Project
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file wc3movie.c
24  * Wing Commander III Movie file demuxer
25  * by Mike Melanson (melanson@pcisys.net)
26  * for more information on the WC3 .mve file format, visit:
27  *   http://www.pcisys.net/~melanson/codecs/
28  */
29
30 #include "avformat.h"
31
32 #define WC3_PREAMBLE_SIZE 8
33
34 #define FORM_TAG MKTAG('F', 'O', 'R', 'M')
35 #define MOVE_TAG MKTAG('M', 'O', 'V', 'E')
36 #define  PC__TAG MKTAG('_', 'P', 'C', '_')
37 #define SOND_TAG MKTAG('S', 'O', 'N', 'D')
38 #define BNAM_TAG MKTAG('B', 'N', 'A', 'M')
39 #define SIZE_TAG MKTAG('S', 'I', 'Z', 'E')
40 #define PALT_TAG MKTAG('P', 'A', 'L', 'T')
41 #define INDX_TAG MKTAG('I', 'N', 'D', 'X')
42 #define BRCH_TAG MKTAG('B', 'R', 'C', 'H')
43 #define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
44 #define VGA__TAG MKTAG('V', 'G', 'A', ' ')
45 #define TEXT_TAG MKTAG('T', 'E', 'X', 'T')
46 #define AUDI_TAG MKTAG('A', 'U', 'D', 'I')
47
48 /* video resolution unless otherwise specified */
49 #define WC3_DEFAULT_WIDTH 320
50 #define WC3_DEFAULT_HEIGHT 165
51
52 /* always use the same PCM audio parameters */
53 #define WC3_SAMPLE_RATE 22050
54 #define WC3_AUDIO_CHANNELS 1
55 #define WC3_AUDIO_BITS 16
56
57 /* nice, constant framerate */
58 #define WC3_FRAME_FPS 15
59
60 #define PALETTE_SIZE (256 * 3)
61 #define PALETTE_COUNT 256
62
63 typedef struct Wc3DemuxContext {
64     int width;
65     int height;
66     unsigned char *palettes;
67     int palette_count;
68     int64_t pts;
69     int video_stream_index;
70     int audio_stream_index;
71
72     AVPaletteControl palette_control;
73
74 } Wc3DemuxContext;
75
76 /* bizarre palette lookup table */
77 static const unsigned char wc3_pal_lookup[] = {
78   0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E,
79   0x10, 0x12, 0x13, 0x15, 0x16, 0x18, 0x19, 0x1A,
80   0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25,
81   0x27, 0x28, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F,
82   0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39,
83   0x3A, 0x3B, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x42,
84   0x43, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4B,
85   0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
86   0x54, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C,
87   0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64,
88   0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
89   0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
90   0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
91   0x7D, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
92   0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B,
93   0x8C, 0x8D, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
94   0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99,
95   0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1,
96   0xA2, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
97   0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
98   0xB0, 0xB1, 0xB2, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
99   0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD,
100   0xBE, 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4,
101   0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB,
102   0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD0, 0xD1,
103   0xD2, 0xD3, 0xD4, 0xD5, 0xD5, 0xD6, 0xD7, 0xD8,
104   0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
105   0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5,
106   0xE6, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEB, 0xEC,
107   0xED, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2,
108   0xF3, 0xF4, 0xF5, 0xF6, 0xF6, 0xF7, 0xF8, 0xF9,
109   0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD
110 };
111
112
113 static int wc3_probe(AVProbeData *p)
114 {
115     if (p->buf_size < 12)
116         return 0;
117
118     if ((AV_RL32(&p->buf[0]) != FORM_TAG) ||
119         (AV_RL32(&p->buf[8]) != MOVE_TAG))
120         return 0;
121
122     return AVPROBE_SCORE_MAX;
123 }
124
125 static int wc3_read_header(AVFormatContext *s,
126                            AVFormatParameters *ap)
127 {
128     Wc3DemuxContext *wc3 = s->priv_data;
129     ByteIOContext *pb = s->pb;
130     unsigned int fourcc_tag;
131     unsigned int size;
132     AVStream *st;
133     unsigned char preamble[WC3_PREAMBLE_SIZE];
134     int ret = 0;
135     int current_palette = 0;
136     int bytes_to_read;
137     int i;
138     unsigned char rotate;
139
140     /* default context members */
141     wc3->width = WC3_DEFAULT_WIDTH;
142     wc3->height = WC3_DEFAULT_HEIGHT;
143     wc3->palettes = NULL;
144     wc3->palette_count = 0;
145     wc3->pts = 0;
146     wc3->video_stream_index = wc3->audio_stream_index = 0;
147
148     /* skip the first 3 32-bit numbers */
149     url_fseek(pb, 12, SEEK_CUR);
150
151     /* traverse through the chunks and load the header information before
152      * the first BRCH tag */
153     if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
154         WC3_PREAMBLE_SIZE)
155         return AVERROR(EIO);
156     fourcc_tag = AV_RL32(&preamble[0]);
157     size = (AV_RB32(&preamble[4]) + 1) & (~1);
158
159     do {
160         switch (fourcc_tag) {
161
162         case SOND_TAG:
163         case INDX_TAG:
164             /* SOND unknown, INDX unnecessary; ignore both */
165             url_fseek(pb, size, SEEK_CUR);
166             break;
167
168         case PC__TAG:
169             /* need the number of palettes */
170             url_fseek(pb, 8, SEEK_CUR);
171             if ((ret = get_buffer(pb, preamble, 4)) != 4)
172                 return AVERROR(EIO);
173             wc3->palette_count = AV_RL32(&preamble[0]);
174             if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){
175                 wc3->palette_count= 0;
176                 return -1;
177             }
178             wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
179             break;
180
181         case BNAM_TAG:
182             /* load up the name */
183             if ((unsigned)size < 512)
184                 bytes_to_read = size;
185             else
186                 bytes_to_read = 512;
187             if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)
188                 return AVERROR(EIO);
189             break;
190
191         case SIZE_TAG:
192             /* video resolution override */
193             if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
194                 WC3_PREAMBLE_SIZE)
195                 return AVERROR(EIO);
196             wc3->width = AV_RL32(&preamble[0]);
197             wc3->height = AV_RL32(&preamble[4]);
198             break;
199
200         case PALT_TAG:
201             /* one of several palettes */
202             if ((unsigned)current_palette >= wc3->palette_count)
203                 return AVERROR_INVALIDDATA;
204             if ((ret = get_buffer(pb,
205                 &wc3->palettes[current_palette * PALETTE_SIZE],
206                 PALETTE_SIZE)) != PALETTE_SIZE)
207                 return AVERROR(EIO);
208
209             /* transform the current palette in place */
210             for (i = current_palette * PALETTE_SIZE;
211                  i < (current_palette + 1) * PALETTE_SIZE; i++) {
212                 /* rotate each palette component left by 2 and use the result
213                  * as an index into the color component table */
214                 rotate = ((wc3->palettes[i] << 2) & 0xFF) |
215                          ((wc3->palettes[i] >> 6) & 0xFF);
216                 wc3->palettes[i] = wc3_pal_lookup[rotate];
217             }
218             current_palette++;
219             break;
220
221         default:
222             av_log(s, AV_LOG_ERROR, "  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
223                 preamble[0], preamble[1], preamble[2], preamble[3],
224                 preamble[0], preamble[1], preamble[2], preamble[3]);
225             return AVERROR_INVALIDDATA;
226             break;
227         }
228
229         if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
230             WC3_PREAMBLE_SIZE)
231             return AVERROR(EIO);
232         fourcc_tag = AV_RL32(&preamble[0]);
233         /* chunk sizes are 16-bit aligned */
234         size = (AV_RB32(&preamble[4]) + 1) & (~1);
235
236     } while (fourcc_tag != BRCH_TAG);
237
238     /* initialize the decoder streams */
239     st = av_new_stream(s, 0);
240     if (!st)
241         return AVERROR(ENOMEM);
242     av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
243     wc3->video_stream_index = st->index;
244     st->codec->codec_type = CODEC_TYPE_VIDEO;
245     st->codec->codec_id = CODEC_ID_XAN_WC3;
246     st->codec->codec_tag = 0;  /* no fourcc */
247     st->codec->width = wc3->width;
248     st->codec->height = wc3->height;
249
250     /* palette considerations */
251     st->codec->palctrl = &wc3->palette_control;
252
253     st = av_new_stream(s, 0);
254     if (!st)
255         return AVERROR(ENOMEM);
256     av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
257     wc3->audio_stream_index = st->index;
258     st->codec->codec_type = CODEC_TYPE_AUDIO;
259     st->codec->codec_id = CODEC_ID_PCM_S16LE;
260     st->codec->codec_tag = 1;
261     st->codec->channels = WC3_AUDIO_CHANNELS;
262     st->codec->bits_per_sample = WC3_AUDIO_BITS;
263     st->codec->sample_rate = WC3_SAMPLE_RATE;
264     st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
265         st->codec->bits_per_sample;
266     st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
267
268     return 0;
269 }
270
271 static int wc3_read_packet(AVFormatContext *s,
272                            AVPacket *pkt)
273 {
274     Wc3DemuxContext *wc3 = s->priv_data;
275     ByteIOContext *pb = s->pb;
276     unsigned int fourcc_tag;
277     unsigned int size;
278     int packet_read = 0;
279     int ret = 0;
280     unsigned char preamble[WC3_PREAMBLE_SIZE];
281     unsigned char text[1024];
282     unsigned int palette_number;
283     int i;
284     unsigned char r, g, b;
285     int base_palette_index;
286
287     while (!packet_read) {
288
289         /* get the next chunk preamble */
290         if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
291             WC3_PREAMBLE_SIZE)
292             ret = AVERROR(EIO);
293
294         fourcc_tag = AV_RL32(&preamble[0]);
295         /* chunk sizes are 16-bit aligned */
296         size = (AV_RB32(&preamble[4]) + 1) & (~1);
297
298         switch (fourcc_tag) {
299
300         case BRCH_TAG:
301             /* no-op */
302             break;
303
304         case SHOT_TAG:
305             /* load up new palette */
306             if ((ret = get_buffer(pb, preamble, 4)) != 4)
307                 return AVERROR(EIO);
308             palette_number = AV_RL32(&preamble[0]);
309             if (palette_number >= wc3->palette_count)
310                 return AVERROR_INVALIDDATA;
311             base_palette_index = palette_number * PALETTE_COUNT * 3;
312             for (i = 0; i < PALETTE_COUNT; i++) {
313                 r = wc3->palettes[base_palette_index + i * 3 + 0];
314                 g = wc3->palettes[base_palette_index + i * 3 + 1];
315                 b = wc3->palettes[base_palette_index + i * 3 + 2];
316                 wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
317             }
318             wc3->palette_control.palette_changed = 1;
319             break;
320
321         case VGA__TAG:
322             /* send out video chunk */
323             ret= av_get_packet(pb, pkt, size);
324             pkt->stream_index = wc3->video_stream_index;
325             pkt->pts = wc3->pts;
326             if (ret != size)
327                 ret = AVERROR(EIO);
328             packet_read = 1;
329             break;
330
331         case TEXT_TAG:
332             /* subtitle chunk */
333 #if 0
334             url_fseek(pb, size, SEEK_CUR);
335 #else
336             if ((unsigned)size > sizeof(text) || (ret = get_buffer(pb, text, size)) != size)
337                 ret = AVERROR(EIO);
338             else {
339                 int i = 0;
340                 av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
341                 av_log (s, AV_LOG_DEBUG, "  inglish: %s\n", &text[i + 1]);
342                 i += text[i] + 1;
343                 av_log (s, AV_LOG_DEBUG, "  doytsch: %s\n", &text[i + 1]);
344                 i += text[i] + 1;
345                 av_log (s, AV_LOG_DEBUG, "  fronsay: %s\n", &text[i + 1]);
346             }
347 #endif
348             break;
349
350         case AUDI_TAG:
351             /* send out audio chunk */
352             ret= av_get_packet(pb, pkt, size);
353             pkt->stream_index = wc3->audio_stream_index;
354             pkt->pts = wc3->pts;
355             if (ret != size)
356                 ret = AVERROR(EIO);
357
358             /* time to advance pts */
359             wc3->pts++;
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 = s->priv_data;
380
381     av_free(wc3->palettes);
382
383     return 0;
384 }
385
386 AVInputFormat wc3_demuxer = {
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 };