Statistics
| Branch: | Revision:

ffmpeg / libavformat / wc3movie.c @ 7be806f3

History | View | Annotate | Download (13 KB)

1
/*
2
 * Wing Commander III Movie (.mve) File Demuxer
3
 * Copyright (c) 2003 The ffmpeg Project
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19

    
20
/**
21
 * @file wc3movie.c
22
 * Wing Commander III Movie file demuxer
23
 * by Mike Melanson (melanson@pcisys.net)
24
 * for more information on the WC3 .mve file format, visit:
25
 *   http://www.pcisys.net/~melanson/codecs/
26
 */
27

    
28
#include "avformat.h"
29

    
30
#define WC3_PREAMBLE_SIZE 8
31

    
32
#define FORM_TAG MKTAG('F', 'O', 'R', 'M')
33
#define MOVE_TAG MKTAG('M', 'O', 'V', 'E')
34
#define _PC__TAG MKTAG('_', 'P', 'C', '_')
35
#define SOND_TAG MKTAG('S', 'O', 'N', 'D')
36
#define BNAM_TAG MKTAG('B', 'N', 'A', 'M')
37
#define SIZE_TAG MKTAG('S', 'I', 'Z', 'E')
38
#define PALT_TAG MKTAG('P', 'A', 'L', 'T')
39
#define INDX_TAG MKTAG('I', 'N', 'D', 'X')
40
#define BRCH_TAG MKTAG('B', 'R', 'C', 'H')
41
#define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
42
#define VGA__TAG MKTAG('V', 'G', 'A', ' ')
43
#define TEXT_TAG MKTAG('T', 'E', 'X', 'T')
44
#define AUDI_TAG MKTAG('A', 'U', 'D', 'I')
45

    
46
/* video resolution unless otherwise specified */
47
#define WC3_DEFAULT_WIDTH 320
48
#define WC3_DEFAULT_HEIGHT 165
49

    
50
/* always use the same PCM audio parameters */
51
#define WC3_SAMPLE_RATE 22050
52
#define WC3_AUDIO_CHANNELS 1
53
#define WC3_AUDIO_BITS 16
54

    
55
/* nice, constant framerate */
56
#define WC3_FRAME_PTS_INC (90000 / 15)
57

    
58
#define PALETTE_SIZE (256 * 3)
59
#define PALETTE_COUNT 256
60

    
61
typedef struct Wc3DemuxContext {
62
    int width;
63
    int height;
64
    unsigned char *palettes;
65
    int palette_count;
66
    int64_t pts;
67
    int video_stream_index;
68
    int audio_stream_index;
69

    
70
    AVPaletteControl palette_control;
71

    
72
} Wc3DemuxContext;
73

    
74
/* bizarre palette lookup table */
75
static const unsigned char wc3_pal_lookup[] = {
76
  0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 
77
  0x10, 0x12, 0x13, 0x15, 0x16, 0x18, 0x19, 0x1A,
78
  0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25, 
79
  0x27, 0x28, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F,
80
  0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39, 
81
  0x3A, 0x3B, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x42,
82
  0x43, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4B, 
83
  0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
84
  0x54, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 
85
  0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64,
86
  0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 
87
  0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
88
  0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 
89
  0x7D, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
90
  0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 
91
  0x8C, 0x8D, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
92
  0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99, 
93
  0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1,
94
  0xA2, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 
95
  0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
96
  0xB0, 0xB1, 0xB2, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 
97
  0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD,
98
  0xBE, 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 
99
  0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB,
100
  0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD0, 0xD1, 
101
  0xD2, 0xD3, 0xD4, 0xD5, 0xD5, 0xD6, 0xD7, 0xD8,
102
  0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
103
  0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5,
104
  0xE6, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEB, 0xEC, 
105
  0xED, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2,
106
  0xF3, 0xF4, 0xF5, 0xF6, 0xF6, 0xF7, 0xF8, 0xF9, 
107
  0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD
108
};
109

    
110

    
111
static int wc3_probe(AVProbeData *p)
112
{
113
    if (p->buf_size < 12)
114
        return 0;
115

    
116
    if ((LE_32(&p->buf[0]) != FORM_TAG) ||
117
        (LE_32(&p->buf[8]) != MOVE_TAG))
118
        return 0;
119

    
120
    return AVPROBE_SCORE_MAX;
121
}
122

    
123
static int wc3_read_header(AVFormatContext *s,
124
                           AVFormatParameters *ap)
125
{
126
    Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
127
    ByteIOContext *pb = &s->pb;
128
    unsigned int fourcc_tag;
129
    unsigned int size;
130
    AVStream *st;
131
    unsigned char preamble[WC3_PREAMBLE_SIZE];
132
    int ret = 0;
133
    int current_palette = 0;
134
    int bytes_to_read;
135
    int i;
136
    unsigned char rotate;
137

    
138
    /* default context members */
139
    wc3->width = WC3_DEFAULT_WIDTH;
140
    wc3->height = WC3_DEFAULT_HEIGHT;
141
    wc3->palettes = NULL;
142
    wc3->palette_count = 0;
143
    wc3->pts = 0;
144
    wc3->video_stream_index = wc3->audio_stream_index = 0;
145

    
146
    /* skip the first 3 32-bit numbers */
147
    url_fseek(pb, 12, SEEK_CUR);
148

    
149
    /* traverse through the chunks and load the header information before
150
     * the first BRCH tag */
151
    if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 
152
        WC3_PREAMBLE_SIZE)
153
        return AVERROR_IO;
154
    fourcc_tag = LE_32(&preamble[0]);
155
    size = (BE_32(&preamble[4]) + 1) & (~1);
156

    
157
    do {
158
        switch (fourcc_tag) {
159

    
160
        case SOND_TAG:
161
        case INDX_TAG:
162
            /* SOND unknown, INDX unnecessary; ignore both */
163
            url_fseek(pb, size, SEEK_CUR);
164
            break;
165

    
166
        case _PC__TAG:
167
            /* need the number of palettes */
168
            url_fseek(pb, 8, SEEK_CUR);
169
            if ((ret = get_buffer(pb, preamble, 4)) != 4)
170
                return AVERROR_IO;
171
            wc3->palette_count = LE_32(&preamble[0]);
172
            if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){
173
                wc3->palette_count= 0;
174
                return -1;
175
            }
176
            wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
177
            break;
178

    
179
        case BNAM_TAG:
180
            /* load up the name */
181
            if ((unsigned)size < 512)
182
                bytes_to_read = size;
183
            else
184
                bytes_to_read = 512;
185
            if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)
186
                return AVERROR_IO;
187
            break;
188

    
189
        case SIZE_TAG:
190
            /* video resolution override */
191
            if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 
192
                WC3_PREAMBLE_SIZE)
193
                return AVERROR_IO;
194
            wc3->width = LE_32(&preamble[0]);
195
            wc3->height = LE_32(&preamble[4]);
196
            break;
197

    
198
        case PALT_TAG:
199
            /* one of several palettes */
200
            if ((unsigned)current_palette >= wc3->palette_count)
201
                return AVERROR_INVALIDDATA;
202
            if ((ret = get_buffer(pb, 
203
                &wc3->palettes[current_palette * PALETTE_SIZE], 
204
                PALETTE_SIZE)) != PALETTE_SIZE)
205
                return AVERROR_IO;
206

    
207
            /* transform the current palette in place */
208
            for (i = current_palette * PALETTE_SIZE;
209
                 i < (current_palette + 1) * PALETTE_SIZE; i++) {
210
                /* rotate each palette component left by 2 and use the result
211
                 * as an index into the color component table */
212
                rotate = ((wc3->palettes[i] << 2) & 0xFF) | 
213
                         ((wc3->palettes[i] >> 6) & 0xFF);
214
                wc3->palettes[i] = wc3_pal_lookup[rotate];
215
            }
216
            current_palette++;
217
            break;
218

    
219
        default:
220
            av_log(s, AV_LOG_ERROR, "  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
221
                preamble[0], preamble[1], preamble[2], preamble[3],
222
                preamble[0], preamble[1], preamble[2], preamble[3]);
223
            return AVERROR_INVALIDDATA;
224
            break;
225
        }
226

    
227
        if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 
228
            WC3_PREAMBLE_SIZE)
229
            return AVERROR_IO;
230
        fourcc_tag = LE_32(&preamble[0]);
231
        /* chunk sizes are 16-bit aligned */
232
        size = (BE_32(&preamble[4]) + 1) & (~1);
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_NOMEM;
240
    av_set_pts_info(st, 33, 1, 90000);
241
    wc3->video_stream_index = st->index;
242
    st->codec.codec_type = CODEC_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_NOMEM;
254
    av_set_pts_info(st, 33, 1, 90000);
255
    wc3->audio_stream_index = st->index;
256
    st->codec.codec_type = CODEC_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_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_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 = (Wc3DemuxContext *)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 preamble[WC3_PREAMBLE_SIZE];
279
    unsigned char text[1024];
280
    unsigned int palette_number;
281
    int i;
282
    unsigned char r, g, b;
283
    int base_palette_index;
284

    
285
    while (!packet_read) {
286

    
287
        /* get the next chunk preamble */
288
        if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
289
            WC3_PREAMBLE_SIZE)
290
            ret = AVERROR_IO;
291

    
292
        fourcc_tag = LE_32(&preamble[0]);
293
        /* chunk sizes are 16-bit aligned */
294
        size = (BE_32(&preamble[4]) + 1) & (~1);
295

    
296
        switch (fourcc_tag) {
297

    
298
        case BRCH_TAG:
299
            /* no-op */
300
            break;
301

    
302
        case SHOT_TAG:
303
            /* load up new palette */
304
            if ((ret = get_buffer(pb, preamble, 4)) != 4)
305
                return AVERROR_IO;
306
            palette_number = LE_32(&preamble[0]);
307
            if (palette_number >= wc3->palette_count)
308
                return AVERROR_INVALIDDATA;
309
            base_palette_index = palette_number * PALETTE_COUNT * 3;
310
            for (i = 0; i < PALETTE_COUNT; i++) {
311
                r = wc3->palettes[base_palette_index + i * 3 + 0];
312
                g = wc3->palettes[base_palette_index + i * 3 + 1];
313
                b = wc3->palettes[base_palette_index + i * 3 + 2];
314
                wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
315
            }
316
            wc3->palette_control.palette_changed = 1;
317
            break;
318

    
319
        case VGA__TAG:
320
            /* send out video chunk */
321
            if (av_new_packet(pkt, size))
322
                ret = AVERROR_IO;
323
            pkt->stream_index = wc3->video_stream_index;
324
            pkt->pts = wc3->pts;
325
            ret = get_buffer(pb, pkt->data, size);
326
            if (ret != size)
327
                ret = AVERROR_IO;
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_IO;
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
            if (av_new_packet(pkt, size))
353
                ret = AVERROR_IO;
354
            pkt->stream_index = wc3->audio_stream_index;
355
            pkt->pts = wc3->pts;
356
            ret = get_buffer(pb, pkt->data, size);
357
            if (ret != size)
358
                ret = AVERROR_IO;
359

    
360
            /* time to advance pts */
361
            wc3->pts += WC3_FRAME_PTS_INC;
362

    
363
            packet_read = 1;
364
            break;
365

    
366
        default:
367
            av_log (s, AV_LOG_ERROR, "  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
368
                preamble[0], preamble[1], preamble[2], preamble[3],
369
                preamble[0], preamble[1], preamble[2], preamble[3]);
370
            ret = AVERROR_INVALIDDATA;
371
            packet_read = 1;
372
            break;
373
        }
374
    }
375

    
376
    return ret;
377
}
378

    
379
static int wc3_read_close(AVFormatContext *s)
380
{
381
    Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
382

    
383
    av_free(wc3->palettes);
384

    
385
    return 0;
386
}
387

    
388
static AVInputFormat wc3_iformat = {
389
    "wc3movie",
390
    "Wing Commander III movie format",
391
    sizeof(Wc3DemuxContext),
392
    wc3_probe,
393
    wc3_read_header,
394
    wc3_read_packet,
395
    wc3_read_close,
396
};
397

    
398
int wc3_init(void)
399
{
400
    av_register_input_format(&wc3_iformat);
401
    return 0;
402
}