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