Statistics
| Branch: | Revision:

ffmpeg / libavformat / wc3movie.c @ 591944cd

History | View | Annotate | Download (12.7 KB)

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 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 "avformat.h"
31

    
32
#define WC3_PREAMBLE_SIZE 8
33

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

    
48
/* video resolution unless otherwise specified */
49
#define WC3_DEFAULT_WIDTH 320
50
#define WC3_DEFAULT_HEIGHT 165
51

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

    
57
/* nice, constant framerate */
58
#define WC3_FRAME_FPS 15
59

    
60
#define PALETTE_SIZE (256 * 3)
61
#define PALETTE_COUNT 256
62

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

    
72
    AVPaletteControl palette_control;
73

    
74
} Wc3DemuxContext;
75

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

    
112

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

    
118
    if ((AV_RL32(&p->buf[0]) != FORM_TAG) ||
119
        (AV_RL32(&p->buf[8]) != MOVE_TAG))
120
        return 0;
121

    
122
    return AVPROBE_SCORE_MAX;
123
}
124

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

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

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

    
151
    /* traverse through the chunks and load the header information before
152
     * the first BRCH tag */
153
    if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
154
        WC3_PREAMBLE_SIZE)
155
        return AVERROR(EIO);
156
    fourcc_tag = AV_RL32(&preamble[0]);
157
    size = (AV_RB32(&preamble[4]) + 1) & (~1);
158

    
159
    do {
160
        switch (fourcc_tag) {
161

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

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

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

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

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

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

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

    
229
        if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
230
            WC3_PREAMBLE_SIZE)
231
            return AVERROR(EIO);
232
        fourcc_tag = AV_RL32(&preamble[0]);
233
        /* chunk sizes are 16-bit aligned */
234
        size = (AV_RB32(&preamble[4]) + 1) & (~1);
235

    
236
    } while (fourcc_tag != BRCH_TAG);
237

    
238
    /* initialize the decoder streams */
239
    st = av_new_stream(s, 0);
240
    if (!st)
241
        return AVERROR(ENOMEM);
242
    av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
243
    wc3->video_stream_index = st->index;
244
    st->codec->codec_type = CODEC_TYPE_VIDEO;
245
    st->codec->codec_id = CODEC_ID_XAN_WC3;
246
    st->codec->codec_tag = 0;  /* no fourcc */
247
    st->codec->width = wc3->width;
248
    st->codec->height = wc3->height;
249

    
250
    /* palette considerations */
251
    st->codec->palctrl = &wc3->palette_control;
252

    
253
    st = av_new_stream(s, 0);
254
    if (!st)
255
        return AVERROR(ENOMEM);
256
    av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
257
    wc3->audio_stream_index = st->index;
258
    st->codec->codec_type = CODEC_TYPE_AUDIO;
259
    st->codec->codec_id = CODEC_ID_PCM_S16LE;
260
    st->codec->codec_tag = 1;
261
    st->codec->channels = WC3_AUDIO_CHANNELS;
262
    st->codec->bits_per_sample = WC3_AUDIO_BITS;
263
    st->codec->sample_rate = WC3_SAMPLE_RATE;
264
    st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
265
        st->codec->bits_per_sample;
266
    st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
267

    
268
    return 0;
269
}
270

    
271
static int wc3_read_packet(AVFormatContext *s,
272
                           AVPacket *pkt)
273
{
274
    Wc3DemuxContext *wc3 = s->priv_data;
275
    ByteIOContext *pb = s->pb;
276
    unsigned int fourcc_tag;
277
    unsigned int size;
278
    int packet_read = 0;
279
    int ret = 0;
280
    unsigned char preamble[WC3_PREAMBLE_SIZE];
281
    unsigned char text[1024];
282
    unsigned int palette_number;
283
    int i;
284
    unsigned char r, g, b;
285
    int base_palette_index;
286

    
287
    while (!packet_read) {
288

    
289
        /* get the next chunk preamble */
290
        if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
291
            WC3_PREAMBLE_SIZE)
292
            ret = AVERROR(EIO);
293

    
294
        fourcc_tag = AV_RL32(&preamble[0]);
295
        /* chunk sizes are 16-bit aligned */
296
        size = (AV_RB32(&preamble[4]) + 1) & (~1);
297

    
298
        switch (fourcc_tag) {
299

    
300
        case BRCH_TAG:
301
            /* no-op */
302
            break;
303

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

    
321
        case VGA__TAG:
322
            /* send out video chunk */
323
            ret= av_get_packet(pb, pkt, size);
324
            pkt->stream_index = wc3->video_stream_index;
325
            pkt->pts = wc3->pts;
326
            if (ret != size)
327
                ret = AVERROR(EIO);
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(EIO);
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
            ret= av_get_packet(pb, pkt, size);
353
            pkt->stream_index = wc3->audio_stream_index;
354
            pkt->pts = wc3->pts;
355
            if (ret != size)
356
                ret = AVERROR(EIO);
357

    
358
            /* time to advance pts */
359
            wc3->pts++;
360

    
361
            packet_read = 1;
362
            break;
363

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

    
374
    return ret;
375
}
376

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

    
381
    av_free(wc3->palettes);
382

    
383
    return 0;
384
}
385

    
386
AVInputFormat wc3_demuxer = {
387
    "wc3movie",
388
    "Wing Commander III movie format",
389
    sizeof(Wc3DemuxContext),
390
    wc3_probe,
391
    wc3_read_header,
392
    wc3_read_packet,
393
    wc3_read_close,
394
};