Statistics
| Branch: | Revision:

ffmpeg / libavformat / wc3movie.c @ 5aa0a644

History | View | Annotate | Download (13.1 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 LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
31
#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
32
                   (((uint8_t*)(x))[2] << 16) | \
33
                   (((uint8_t*)(x))[1] << 8) | \
34
                    ((uint8_t*)(x))[0])
35
#define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
36
#define BE_32(x)  ((((uint8_t*)(x))[0] << 24) | \
37
                   (((uint8_t*)(x))[1] << 16) | \
38
                   (((uint8_t*)(x))[2] << 8) | \
39
                    ((uint8_t*)(x))[3])
40

    
41
#define WC3_PREAMBLE_SIZE 8
42

    
43
#define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \
44
        ( (long)(unsigned char)(ch0) | \
45
        ( (long)(unsigned char)(ch1) << 8 ) | \
46
        ( (long)(unsigned char)(ch2) << 16 ) | \
47
        ( (long)(unsigned char)(ch3) << 24 ) )
48

    
49
#define FORM_TAG FOURCC_TAG('F', 'O', 'R', 'M')
50
#define MOVE_TAG FOURCC_TAG('M', 'O', 'V', 'E')
51
#define _PC__TAG FOURCC_TAG('_', 'P', 'C', '_')
52
#define SOND_TAG FOURCC_TAG('S', 'O', 'N', 'D')
53
#define BNAM_TAG FOURCC_TAG('B', 'N', 'A', 'M')
54
#define SIZE_TAG FOURCC_TAG('S', 'I', 'Z', 'E')
55
#define PALT_TAG FOURCC_TAG('P', 'A', 'L', 'T')
56
#define INDX_TAG FOURCC_TAG('I', 'N', 'D', 'X')
57
#define BRCH_TAG FOURCC_TAG('B', 'R', 'C', 'H')
58
#define SHOT_TAG FOURCC_TAG('S', 'H', 'O', 'T')
59
#define VGA__TAG FOURCC_TAG('V', 'G', 'A', ' ')
60
#define TEXT_TAG FOURCC_TAG('T', 'E', 'X', 'T')
61
#define AUDI_TAG FOURCC_TAG('A', 'U', 'D', 'I')
62

    
63
/* video resolution unless otherwise specified */
64
#define WC3_DEFAULT_WIDTH 320
65
#define WC3_DEFAULT_HEIGHT 165
66

    
67
/* always use the same PCM audio parameters */
68
#define WC3_SAMPLE_RATE 22050
69
#define WC3_AUDIO_CHANNELS 1
70
#define WC3_AUDIO_BITS 16
71

    
72
/* nice, constant framerate */
73
#define WC3_FRAME_PTS_INC (90000 / 15)
74

    
75
#define PALETTE_SIZE (256 * 3)
76
#define PALETTE_COUNT 256
77

    
78
typedef struct Wc3DemuxContext {
79
    int width;
80
    int height;
81
    unsigned char *palettes;
82
    int palette_count;
83
    int64_t pts;
84
    int video_stream_index;
85
    int audio_stream_index;
86

    
87
    AVPaletteControl palette_control;
88

    
89
} Wc3DemuxContext;
90

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

    
127

    
128
static int wc3_probe(AVProbeData *p)
129
{
130
    if (p->buf_size < 12)
131
        return 0;
132

    
133
    if ((LE_32(&p->buf[0]) != FORM_TAG) ||
134
        (LE_32(&p->buf[8]) != MOVE_TAG))
135
        return 0;
136

    
137
    return AVPROBE_SCORE_MAX;
138
}
139

    
140
static int wc3_read_header(AVFormatContext *s,
141
                           AVFormatParameters *ap)
142
{
143
    Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
144
    ByteIOContext *pb = &s->pb;
145
    unsigned int fourcc_tag;
146
    unsigned int size;
147
    AVStream *st;
148
    unsigned char preamble[WC3_PREAMBLE_SIZE];
149
    int ret = 0;
150
    int current_palette = 0;
151
    int bytes_to_read;
152
    int i;
153
    unsigned char rotate;
154

    
155
    /* default context members */
156
    wc3->width = WC3_DEFAULT_WIDTH;
157
    wc3->height = WC3_DEFAULT_HEIGHT;
158
    wc3->palettes = NULL;
159
    wc3->palette_count = 0;
160
    wc3->pts = 0;
161
    wc3->video_stream_index = wc3->audio_stream_index = 0;
162

    
163
    /* skip the first 3 32-bit numbers */
164
    url_fseek(pb, 12, SEEK_CUR);
165

    
166
    /* traverse through the chunks and load the header information before
167
     * the first BRCH tag */
168
    if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 
169
        WC3_PREAMBLE_SIZE)
170
        return -EIO;
171
    fourcc_tag = LE_32(&preamble[0]);
172
    size = (BE_32(&preamble[4]) + 1) & (~1);
173

    
174
    do {
175
        switch (fourcc_tag) {
176

    
177
        case SOND_TAG:
178
        case INDX_TAG:
179
            /* SOND unknown, INDX unnecessary; ignore both */
180
            url_fseek(pb, size, SEEK_CUR);
181
            break;
182

    
183
        case _PC__TAG:
184
            /* need the number of palettes */
185
            url_fseek(pb, 8, SEEK_CUR);
186
            if ((ret = get_buffer(pb, preamble, 4)) != 4)
187
                return -EIO;
188
            wc3->palette_count = LE_32(&preamble[0]);
189
            wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
190
            break;
191

    
192
        case BNAM_TAG:
193
            /* load up the name */
194
            if (size < 512)
195
                bytes_to_read = size;
196
            else
197
                bytes_to_read = 512;
198
            if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)
199
                return -EIO;
200
            break;
201

    
202
        case SIZE_TAG:
203
            /* video resolution override */
204
            if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 
205
                WC3_PREAMBLE_SIZE)
206
                return -EIO;
207
            wc3->width = LE_32(&preamble[0]);
208
            wc3->height = LE_32(&preamble[4]);
209
            break;
210

    
211
        case PALT_TAG:
212
            /* one of several palettes */
213
            if (current_palette >= wc3->palette_count)
214
                return AVERROR_INVALIDDATA;
215
            if ((ret = get_buffer(pb, 
216
                &wc3->palettes[current_palette * PALETTE_SIZE], 
217
                PALETTE_SIZE)) != PALETTE_SIZE)
218
                return -EIO;
219

    
220
            /* transform the current palette in place */
221
            for (i = current_palette * PALETTE_SIZE;
222
                 i < (current_palette + 1) * PALETTE_SIZE; i++) {
223
                /* rotate each palette component left by 2 and use the result
224
                 * as an index into the color component table */
225
                rotate = ((wc3->palettes[i] << 2) & 0xFF) | 
226
                         ((wc3->palettes[i] >> 6) & 0xFF);
227
                wc3->palettes[i] = wc3_pal_lookup[rotate];
228
            }
229
            current_palette++;
230
            break;
231

    
232
        default:
233
            printf ("  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
234
                preamble[0], preamble[1], preamble[2], preamble[3],
235
                preamble[0], preamble[1], preamble[2], preamble[3]);
236
            return AVERROR_INVALIDDATA;
237
            break;
238
        }
239

    
240
        if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) != 
241
            WC3_PREAMBLE_SIZE)
242
            return -EIO;
243
        fourcc_tag = LE_32(&preamble[0]);
244
        /* chunk sizes are 16-bit aligned */
245
        size = (BE_32(&preamble[4]) + 1) & (~1);
246

    
247
    } while (fourcc_tag != BRCH_TAG);
248

    
249
    /* initialize the decoder streams */
250
    st = av_new_stream(s, 0);
251
    if (!st)
252
        return AVERROR_NOMEM;
253
    wc3->video_stream_index = st->index;
254
    st->codec.codec_type = CODEC_TYPE_VIDEO;
255
    st->codec.codec_id = CODEC_ID_XAN_WC3;
256
    st->codec.codec_tag = 0;  /* no fourcc */
257
    st->codec.width = wc3->width;
258
    st->codec.height = wc3->height;
259

    
260
    /* palette considerations */
261
    st->codec.extradata_size = sizeof(AVPaletteControl);
262
    st->codec.extradata = &wc3->palette_control;
263

    
264
    st = av_new_stream(s, 0);
265
    if (!st)
266
        return AVERROR_NOMEM;
267
    wc3->audio_stream_index = st->index;
268
    st->codec.codec_type = CODEC_TYPE_AUDIO;
269
    st->codec.codec_id = CODEC_ID_PCM_S16LE;
270
    st->codec.codec_tag = 1;
271
    st->codec.channels = WC3_AUDIO_CHANNELS;
272
    st->codec.bits_per_sample = WC3_AUDIO_BITS;
273
    st->codec.sample_rate = WC3_SAMPLE_RATE;
274
    st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
275
        st->codec.bits_per_sample;
276
    st->codec.block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
277

    
278
    /* set the pts reference (1 pts = 1/90000) */
279
    s->pts_num = 1;
280
    s->pts_den = 90000;
281

    
282
    return 0;
283
}
284

    
285
static int wc3_read_packet(AVFormatContext *s,
286
                           AVPacket *pkt)
287
{
288
    Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
289
    ByteIOContext *pb = &s->pb;
290
    unsigned int fourcc_tag;
291
    unsigned int size;
292
    int packet_read = 0;
293
    int ret = 0;
294
    unsigned char preamble[WC3_PREAMBLE_SIZE];
295
    unsigned char text[1024];
296
    unsigned int palette_number;
297

    
298
    while (!packet_read) {
299

    
300
        /* get the next chunk preamble */
301
        if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
302
            WC3_PREAMBLE_SIZE)
303
            ret = -EIO;
304

    
305
        fourcc_tag = LE_32(&preamble[0]);
306
        /* chunk sizes are 16-bit aligned */
307
        size = (BE_32(&preamble[4]) + 1) & (~1);
308

    
309
        switch (fourcc_tag) {
310

    
311
        case BRCH_TAG:
312
            /* no-op */
313
            break;
314

    
315
        case SHOT_TAG:
316
            /* load up new palette */
317
            if ((ret = get_buffer(pb, preamble, 4)) != 4)
318
                return -EIO;
319
            palette_number = LE_32(&preamble[0]);
320
            if (palette_number >= wc3->palette_count)
321
                return AVERROR_INVALIDDATA;
322
            memcpy(wc3->palette_control.palette, 
323
                &wc3->palettes[palette_number * PALETTE_COUNT * 3],
324
                PALETTE_COUNT * 3);
325
            wc3->palette_control.palette_changed = 1;
326
            break;
327

    
328
        case VGA__TAG:
329
            /* send out video chunk */
330
            if (av_new_packet(pkt, size))
331
                ret = -EIO;
332
            pkt->stream_index = wc3->video_stream_index;
333
            pkt->pts = wc3->pts;
334
            ret = get_buffer(pb, pkt->data, size);
335
            if (ret != size)
336
                ret = -EIO;
337
            packet_read = 1;
338
            break;
339

    
340
        case TEXT_TAG:
341
            /* subtitle chunk */
342
#if 0
343
            url_fseek(pb, size, SEEK_CUR);
344
#else
345
            if ((ret = get_buffer(pb, text, size)) != size)
346
                ret = -EIO;
347
            else {
348
                int i = 0;
349
                printf ("Subtitle time!\n");
350
                printf ("  inglish: %s\n", &text[i + 1]);
351
                i += text[i] + 1;
352
                printf ("  doytsch: %s\n", &text[i + 1]);
353
                i += text[i] + 1;
354
                printf ("  fronsay: %s\n", &text[i + 1]);
355
            }
356
#endif
357
            break;
358

    
359
        case AUDI_TAG:
360
            /* send out audio chunk */
361
            if (av_new_packet(pkt, size))
362
                ret = -EIO;
363
            pkt->stream_index = wc3->audio_stream_index;
364
            pkt->pts = wc3->pts;
365
            ret = get_buffer(pb, pkt->data, size);
366
            if (ret != size)
367
                ret = -EIO;
368

    
369
            /* time to advance pts */
370
            wc3->pts += WC3_FRAME_PTS_INC;
371

    
372
            packet_read = 1;
373
            break;
374

    
375
        default:
376
            printf ("  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
377
                preamble[0], preamble[1], preamble[2], preamble[3],
378
                preamble[0], preamble[1], preamble[2], preamble[3]);
379
            ret = AVERROR_INVALIDDATA;
380
            packet_read = 1;
381
            break;
382
        }
383
    }
384

    
385
    return ret;
386
}
387

    
388
static int wc3_read_close(AVFormatContext *s)
389
{
390
    Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
391

    
392
    av_free(wc3->palettes);
393

    
394
    return 0;
395
}
396

    
397
static AVInputFormat wc3_iformat = {
398
    "wc3movie",
399
    "Wing Commander III movie format",
400
    sizeof(Wc3DemuxContext),
401
    wc3_probe,
402
    wc3_read_header,
403
    wc3_read_packet,
404
    wc3_read_close,
405
};
406

    
407
int wc3_init(void)
408
{
409
    av_register_input_format(&wc3_iformat);
410
    return 0;
411
}