]> git.sesse.net Git - ffmpeg/blob - libavformat/wc3movie.c
use new metadata API in nut muxer
[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 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     char buffer[513];
136     int ret = 0;
137     int current_palette = 0;
138     int bytes_to_read;
139     int i;
140     unsigned char rotate;
141
142     /* default context members */
143     wc3->width = WC3_DEFAULT_WIDTH;
144     wc3->height = WC3_DEFAULT_HEIGHT;
145     wc3->palettes = NULL;
146     wc3->palette_count = 0;
147     wc3->pts = 0;
148     wc3->video_stream_index = wc3->audio_stream_index = 0;
149
150     /* skip the first 3 32-bit numbers */
151     url_fseek(pb, 12, SEEK_CUR);
152
153     /* traverse through the chunks and load the header information before
154      * the first BRCH tag */
155     if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
156         WC3_PREAMBLE_SIZE)
157         return AVERROR(EIO);
158     fourcc_tag = AV_RL32(&preamble[0]);
159     size = (AV_RB32(&preamble[4]) + 1) & (~1);
160
161     do {
162         switch (fourcc_tag) {
163
164         case SOND_TAG:
165         case INDX_TAG:
166             /* SOND unknown, INDX unnecessary; ignore both */
167             url_fseek(pb, size, SEEK_CUR);
168             break;
169
170         case PC__TAG:
171             /* need the number of palettes */
172             url_fseek(pb, 8, SEEK_CUR);
173             if ((ret = get_buffer(pb, preamble, 4)) != 4)
174                 return AVERROR(EIO);
175             wc3->palette_count = AV_RL32(&preamble[0]);
176             if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){
177                 wc3->palette_count= 0;
178                 return -1;
179             }
180             wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
181             break;
182
183         case BNAM_TAG:
184             /* load up the name */
185             if ((unsigned)size < 512)
186                 bytes_to_read = size;
187             else
188                 bytes_to_read = 512;
189             if ((ret = get_buffer(pb, buffer, bytes_to_read)) != bytes_to_read)
190                 return AVERROR(EIO);
191             buffer[bytes_to_read] = 0;
192             av_metadata_set(&s->metadata, "title", buffer);
193             break;
194
195         case SIZE_TAG:
196             /* video resolution override */
197             if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
198                 WC3_PREAMBLE_SIZE)
199                 return AVERROR(EIO);
200             wc3->width = AV_RL32(&preamble[0]);
201             wc3->height = AV_RL32(&preamble[4]);
202             break;
203
204         case PALT_TAG:
205             /* one of several palettes */
206             if ((unsigned)current_palette >= wc3->palette_count)
207                 return AVERROR_INVALIDDATA;
208             if ((ret = get_buffer(pb,
209                 &wc3->palettes[current_palette * PALETTE_SIZE],
210                 PALETTE_SIZE)) != PALETTE_SIZE)
211                 return AVERROR(EIO);
212
213             /* transform the current palette in place */
214             for (i = current_palette * PALETTE_SIZE;
215                  i < (current_palette + 1) * PALETTE_SIZE; i++) {
216                 /* rotate each palette component left by 2 and use the result
217                  * as an index into the color component table */
218                 rotate = ((wc3->palettes[i] << 2) & 0xFF) |
219                          ((wc3->palettes[i] >> 6) & 0xFF);
220                 wc3->palettes[i] = wc3_pal_lookup[rotate];
221             }
222             current_palette++;
223             break;
224
225         default:
226             av_log(s, AV_LOG_ERROR, "  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
227                 preamble[0], preamble[1], preamble[2], preamble[3],
228                 preamble[0], preamble[1], preamble[2], preamble[3]);
229             return AVERROR_INVALIDDATA;
230             break;
231         }
232
233         if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
234             WC3_PREAMBLE_SIZE)
235             return AVERROR(EIO);
236         fourcc_tag = AV_RL32(&preamble[0]);
237         /* chunk sizes are 16-bit aligned */
238         size = (AV_RB32(&preamble[4]) + 1) & (~1);
239
240     } while (fourcc_tag != BRCH_TAG);
241
242     /* initialize the decoder streams */
243     st = av_new_stream(s, 0);
244     if (!st)
245         return AVERROR(ENOMEM);
246     av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
247     wc3->video_stream_index = st->index;
248     st->codec->codec_type = CODEC_TYPE_VIDEO;
249     st->codec->codec_id = CODEC_ID_XAN_WC3;
250     st->codec->codec_tag = 0;  /* no fourcc */
251     st->codec->width = wc3->width;
252     st->codec->height = wc3->height;
253
254     /* palette considerations */
255     st->codec->palctrl = &wc3->palette_control;
256
257     st = av_new_stream(s, 0);
258     if (!st)
259         return AVERROR(ENOMEM);
260     av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
261     wc3->audio_stream_index = st->index;
262     st->codec->codec_type = CODEC_TYPE_AUDIO;
263     st->codec->codec_id = CODEC_ID_PCM_S16LE;
264     st->codec->codec_tag = 1;
265     st->codec->channels = WC3_AUDIO_CHANNELS;
266     st->codec->bits_per_coded_sample = WC3_AUDIO_BITS;
267     st->codec->sample_rate = WC3_SAMPLE_RATE;
268     st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
269         st->codec->bits_per_coded_sample;
270     st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
271
272     return 0;
273 }
274
275 static int wc3_read_packet(AVFormatContext *s,
276                            AVPacket *pkt)
277 {
278     Wc3DemuxContext *wc3 = s->priv_data;
279     ByteIOContext *pb = s->pb;
280     unsigned int fourcc_tag;
281     unsigned int size;
282     int packet_read = 0;
283     int ret = 0;
284     unsigned char preamble[WC3_PREAMBLE_SIZE];
285     unsigned char text[1024];
286     unsigned int palette_number;
287     int i;
288     unsigned char r, g, b;
289     int base_palette_index;
290
291     while (!packet_read) {
292
293         /* get the next chunk preamble */
294         if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
295             WC3_PREAMBLE_SIZE)
296             ret = AVERROR(EIO);
297
298         fourcc_tag = AV_RL32(&preamble[0]);
299         /* chunk sizes are 16-bit aligned */
300         size = (AV_RB32(&preamble[4]) + 1) & (~1);
301
302         switch (fourcc_tag) {
303
304         case BRCH_TAG:
305             /* no-op */
306             break;
307
308         case SHOT_TAG:
309             /* load up new palette */
310             if ((ret = get_buffer(pb, preamble, 4)) != 4)
311                 return AVERROR(EIO);
312             palette_number = AV_RL32(&preamble[0]);
313             if (palette_number >= wc3->palette_count)
314                 return AVERROR_INVALIDDATA;
315             base_palette_index = palette_number * PALETTE_COUNT * 3;
316             for (i = 0; i < PALETTE_COUNT; i++) {
317                 r = wc3->palettes[base_palette_index + i * 3 + 0];
318                 g = wc3->palettes[base_palette_index + i * 3 + 1];
319                 b = wc3->palettes[base_palette_index + i * 3 + 2];
320                 wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
321             }
322             wc3->palette_control.palette_changed = 1;
323             break;
324
325         case VGA__TAG:
326             /* send out video chunk */
327             ret= av_get_packet(pb, pkt, size);
328             pkt->stream_index = wc3->video_stream_index;
329             pkt->pts = wc3->pts;
330             if (ret != size)
331                 ret = AVERROR(EIO);
332             packet_read = 1;
333             break;
334
335         case TEXT_TAG:
336             /* subtitle chunk */
337 #if 0
338             url_fseek(pb, size, SEEK_CUR);
339 #else
340             if ((unsigned)size > sizeof(text) || (ret = get_buffer(pb, text, size)) != size)
341                 ret = AVERROR(EIO);
342             else {
343                 int i = 0;
344                 av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
345                 av_log (s, AV_LOG_DEBUG, "  inglish: %s\n", &text[i + 1]);
346                 i += text[i] + 1;
347                 av_log (s, AV_LOG_DEBUG, "  doytsch: %s\n", &text[i + 1]);
348                 i += text[i] + 1;
349                 av_log (s, AV_LOG_DEBUG, "  fronsay: %s\n", &text[i + 1]);
350             }
351 #endif
352             break;
353
354         case AUDI_TAG:
355             /* send out audio chunk */
356             ret= av_get_packet(pb, pkt, size);
357             pkt->stream_index = wc3->audio_stream_index;
358             pkt->pts = wc3->pts;
359             if (ret != size)
360                 ret = AVERROR(EIO);
361
362             /* time to advance pts */
363             wc3->pts++;
364
365             packet_read = 1;
366             break;
367
368         default:
369             av_log (s, AV_LOG_ERROR, "  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
370                 preamble[0], preamble[1], preamble[2], preamble[3],
371                 preamble[0], preamble[1], preamble[2], preamble[3]);
372             ret = AVERROR_INVALIDDATA;
373             packet_read = 1;
374             break;
375         }
376     }
377
378     return ret;
379 }
380
381 static int wc3_read_close(AVFormatContext *s)
382 {
383     Wc3DemuxContext *wc3 = s->priv_data;
384
385     av_free(wc3->palettes);
386
387     return 0;
388 }
389
390 AVInputFormat wc3_demuxer = {
391     "wc3movie",
392     NULL_IF_CONFIG_SMALL("Wing Commander III movie format"),
393     sizeof(Wc3DemuxContext),
394     wc3_probe,
395     wc3_read_header,
396     wc3_read_packet,
397     wc3_read_close,
398 };