Statistics
| Branch: | Revision:

ffmpeg / libavformat / wc3movie.c @ d9640a55

History | View | Annotate | Download (12.4 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
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
};