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