Statistics
| Branch: | Revision:

ffmpeg / libavformat / flic.c @ a7eb3c8d

History | View | Annotate | Download (6.74 KB)

1
/*
2
 * FLI/FLC Animation 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 flic.c
22
 * FLI/FLC file demuxer
23
 * by Mike Melanson (melanson@pcisys.net)
24
 * for more information on the .fli/.flc file format and all of its many
25
 * variations, visit:
26
 *   http://www.compuphase.com/flic.htm
27
 *
28
 * This demuxer handles standard 0xAF11- and 0xAF12-type FLIs. It also
29
 * handles special FLIs from the PC game "Magic Carpet".
30
 */
31

    
32
#include "avformat.h"
33

    
34
#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
35
#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
36
                   (((uint8_t*)(x))[2] << 16) | \
37
                   (((uint8_t*)(x))[1] << 8) | \
38
                    ((uint8_t*)(x))[0])
39

    
40
#define FLIC_FILE_MAGIC_1 0xAF11
41
#define FLIC_FILE_MAGIC_2 0xAF12
42
#define FLIC_CHUNK_MAGIC_1 0xF1FA
43
#define FLIC_CHUNK_MAGIC_2 0xF5FA
44
#define FLIC_MC_PTS_INC 6000  /* pts increment for Magic Carpet game FLIs */
45
#define FLIC_DEFAULT_PTS_INC 6000  /* for FLIs that have 0 speed */
46

    
47
#define FLIC_HEADER_SIZE 128
48
#define FLIC_PREAMBLE_SIZE 6
49

    
50
typedef struct FlicDemuxContext {
51
    int frame_pts_inc;
52
    int64_t pts;
53
    int video_stream_index;
54
} FlicDemuxContext;
55

    
56
static int flic_probe(AVProbeData *p)
57
{
58
    int magic_number;
59

    
60
    if (p->buf_size < 6)
61
        return 0;
62

    
63
    magic_number = LE_16(&p->buf[4]);
64
    if ((magic_number != FLIC_FILE_MAGIC_1) &&
65
        (magic_number != FLIC_FILE_MAGIC_2))
66
        return 0;
67

    
68
    return AVPROBE_SCORE_MAX;
69
}
70

    
71
static int flic_read_header(AVFormatContext *s,
72
                            AVFormatParameters *ap)
73
{
74
    FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
75
    ByteIOContext *pb = &s->pb;
76
    unsigned char header[FLIC_HEADER_SIZE];
77
    AVStream *st;
78
    int speed;
79
    int magic_number;
80

    
81
    flic->pts = 0;
82

    
83
    /* load the whole header and pull out the width and height */
84
    if (get_buffer(pb, header, FLIC_HEADER_SIZE) != FLIC_HEADER_SIZE)
85
        return -EIO;
86

    
87
    magic_number = LE_16(&header[4]);
88
    speed = LE_32(&header[0x10]);
89

    
90
    /* initialize the decoder streams */
91
    st = av_new_stream(s, 0);
92
    if (!st)
93
        return AVERROR_NOMEM;
94
    flic->video_stream_index = st->index;
95
    st->codec.codec_type = CODEC_TYPE_VIDEO;
96
    st->codec.codec_id = CODEC_ID_FLIC;
97
    st->codec.codec_tag = 0;  /* no fourcc */
98
    st->codec.width = LE_16(&header[0x08]);
99
    st->codec.height = LE_16(&header[0x0A]);
100

    
101
    if (!st->codec.width || !st->codec.height)
102
        return AVERROR_INVALIDDATA;
103

    
104
    /* send over the whole 128-byte FLIC header */
105
    st->codec.extradata_size = FLIC_HEADER_SIZE;
106
    st->codec.extradata = av_malloc(FLIC_HEADER_SIZE);
107
    memcpy(st->codec.extradata, header, FLIC_HEADER_SIZE);
108

    
109
    /* set the pts reference (1 pts = 1/90000) */
110
    s->pts_num = 1;
111
    s->pts_den = 90000;
112

    
113
    /* Time to figure out the framerate: If there is a FLIC chunk magic
114
     * number at offset 0x10, assume this is from the Bullfrog game,
115
     * Magic Carpet. */
116
    if (LE_16(&header[0x10]) == FLIC_CHUNK_MAGIC_1) {
117

    
118
        flic->frame_pts_inc = FLIC_MC_PTS_INC;
119

    
120
        /* rewind the stream since the first chunk is at offset 12 */
121
        url_fseek(pb, 12, SEEK_SET);
122

    
123
        /* send over abbreviated FLIC header chunk */
124
        av_free(st->codec.extradata);
125
        st->codec.extradata_size = 12;
126
        st->codec.extradata = av_malloc(12);
127
        memcpy(st->codec.extradata, header, 12);
128

    
129
    } else if (magic_number == FLIC_FILE_MAGIC_1) {
130
        /*
131
         * in this case, the speed (n) is number of 1/70s ticks between frames:
132
         *
133
         *    pts        n * frame #
134
         *  --------  =  -----------  => pts = n * (90000/70) * frame #
135
         *   90000           70
136
         *
137
         *  therefore, the frame pts increment = n * 1285.7
138
         */
139
        flic->frame_pts_inc = speed * 1285.7;
140
    } else if (magic_number == FLIC_FILE_MAGIC_2) {
141
        /*
142
         * in this case, the speed (n) is number of milliseconds between frames:
143
         *
144
         *    pts        n * frame #
145
         *  --------  =  -----------  => pts = n * 90 * frame #
146
         *   90000          1000
147
         *
148
         *  therefore, the frame pts increment = n * 90
149
         */
150
        flic->frame_pts_inc = speed * 90;
151
    } else
152
        return AVERROR_INVALIDDATA;
153

    
154
    if (flic->frame_pts_inc == 0)
155
        flic->frame_pts_inc = FLIC_DEFAULT_PTS_INC;
156

    
157
    return 0;
158
}
159

    
160
static int flic_read_packet(AVFormatContext *s,
161
                            AVPacket *pkt)
162
{
163
    FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
164
    ByteIOContext *pb = &s->pb;
165
    int packet_read = 0;
166
    unsigned int size;
167
    int magic;
168
    int ret = 0;
169
    unsigned char preamble[FLIC_PREAMBLE_SIZE];
170

    
171
    while (!packet_read) {
172

    
173
        if ((ret = get_buffer(pb, preamble, FLIC_PREAMBLE_SIZE)) !=
174
            FLIC_PREAMBLE_SIZE) {
175
            ret = -EIO;
176
            break;
177
        }
178

    
179
        size = LE_32(&preamble[0]);
180
        magic = LE_16(&preamble[4]);
181

    
182
        if ((magic == FLIC_CHUNK_MAGIC_1) || (magic == FLIC_CHUNK_MAGIC_2)) {
183
            if (av_new_packet(pkt, size)) {
184
                ret = -EIO;
185
                break;
186
            }
187
            pkt->stream_index = flic->video_stream_index;
188
            pkt->pts = flic->pts;
189
            memcpy(pkt->data, preamble, FLIC_PREAMBLE_SIZE);
190
            ret = get_buffer(pb, pkt->data + FLIC_PREAMBLE_SIZE, 
191
                size - FLIC_PREAMBLE_SIZE);
192
            if (ret != size - FLIC_PREAMBLE_SIZE) {
193
                av_free_packet(pkt);
194
                ret = -EIO;
195
            }
196
            flic->pts += flic->frame_pts_inc;
197
            packet_read = 1;
198
        } else {
199
            /* not interested in this chunk */
200
            url_fseek(pb, size - 6, SEEK_CUR);
201
        }
202
    }
203

    
204
    return ret;
205
}
206

    
207
static int flic_read_close(AVFormatContext *s)
208
{
209
//    FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
210

    
211
    return 0;
212
}
213

    
214
static AVInputFormat flic_iformat = {
215
    "flic",
216
    "FLI/FLC animation format",
217
    sizeof(FlicDemuxContext),
218
    flic_probe,
219
    flic_read_header,
220
    flic_read_packet,
221
    flic_read_close,
222
};
223

    
224
int flic_init(void)
225
{
226
    av_register_input_format(&flic_iformat);
227
    return 0;
228
}