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