1/*
2 * Sega FILM Format (CPK) Demuxer
3 * Copyright (c) 2003 The ffmpeg Project
4 *
5 * This file is part of Libav.
6 *
7 * Libav 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 * Libav 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 Libav; 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 * Sega FILM (.cpk) file demuxer
25 * by Mike Melanson (melanson@pcisys.net)
26 * For more information regarding the Sega FILM file format, visit:
27 *   http://www.pcisys.net/~melanson/codecs/
28 */
29
30#include "libavutil/intreadwrite.h"
31#include "avformat.h"
32#include "internal.h"
33
34#define FILM_TAG MKBETAG('F', 'I', 'L', 'M')
35#define FDSC_TAG MKBETAG('F', 'D', 'S', 'C')
36#define STAB_TAG MKBETAG('S', 'T', 'A', 'B')
37#define CVID_TAG MKBETAG('c', 'v', 'i', 'd')
38#define RAW_TAG  MKBETAG('r', 'a', 'w', ' ')
39
40typedef struct {
41  int stream;
42  int64_t sample_offset;
43  unsigned int sample_size;
44  int64_t pts;
45  int keyframe;
46} film_sample;
47
48typedef struct FilmDemuxContext {
49    int video_stream_index;
50    int audio_stream_index;
51
52    enum CodecID audio_type;
53    unsigned int audio_samplerate;
54    unsigned int audio_bits;
55    unsigned int audio_channels;
56
57    enum CodecID video_type;
58    unsigned int sample_count;
59    film_sample *sample_table;
60    unsigned int current_sample;
61
62    unsigned int base_clock;
63    unsigned int version;
64
65    /* buffer used for interleaving stereo PCM data */
66    unsigned char *stereo_buffer;
67    int stereo_buffer_size;
68} FilmDemuxContext;
69
70static int film_probe(AVProbeData *p)
71{
72    if (AV_RB32(&p->buf[0]) != FILM_TAG)
73        return 0;
74
75    return AVPROBE_SCORE_MAX;
76}
77
78static int film_read_header(AVFormatContext *s,
79                            AVFormatParameters *ap)
80{
81    FilmDemuxContext *film = s->priv_data;
82    AVIOContext *pb = s->pb;
83    AVStream *st;
84    unsigned char scratch[256];
85    int i;
86    unsigned int data_offset;
87    unsigned int audio_frame_counter;
88
89    film->sample_table = NULL;
90    film->stereo_buffer = NULL;
91    film->stereo_buffer_size = 0;
92
93    /* load the main FILM header */
94    if (avio_read(pb, scratch, 16) != 16)
95        return AVERROR(EIO);
96    data_offset = AV_RB32(&scratch[4]);
97    film->version = AV_RB32(&scratch[8]);
98
99    /* load the FDSC chunk */
100    if (film->version == 0) {
101        /* special case for Lemmings .film files; 20-byte header */
102        if (avio_read(pb, scratch, 20) != 20)
103            return AVERROR(EIO);
104        /* make some assumptions about the audio parameters */
105        film->audio_type = CODEC_ID_PCM_S8;
106        film->audio_samplerate = 22050;
107        film->audio_channels = 1;
108        film->audio_bits = 8;
109    } else {
110        /* normal Saturn .cpk files; 32-byte header */
111        if (avio_read(pb, scratch, 32) != 32)
112            return AVERROR(EIO);
113        film->audio_samplerate = AV_RB16(&scratch[24]);
114        film->audio_channels = scratch[21];
115        film->audio_bits = scratch[22];
116        if (scratch[23] == 2)
117            film->audio_type = CODEC_ID_ADPCM_ADX;
118        else if (film->audio_channels > 0) {
119            if (film->audio_bits == 8)
120                film->audio_type = CODEC_ID_PCM_S8;
121            else if (film->audio_bits == 16)
122                film->audio_type = CODEC_ID_PCM_S16BE;
123            else
124                film->audio_type = CODEC_ID_NONE;
125        } else
126            film->audio_type = CODEC_ID_NONE;
127    }
128
129    if (AV_RB32(&scratch[0]) != FDSC_TAG)
130        return AVERROR_INVALIDDATA;
131
132    if (AV_RB32(&scratch[8]) == CVID_TAG) {
133        film->video_type = CODEC_ID_CINEPAK;
134    } else if (AV_RB32(&scratch[8]) == RAW_TAG) {
135        film->video_type = CODEC_ID_RAWVIDEO;
136    } else {
137        film->video_type = CODEC_ID_NONE;
138    }
139
140    /* initialize the decoder streams */
141    if (film->video_type) {
142        st = avformat_new_stream(s, NULL);
143        if (!st)
144            return AVERROR(ENOMEM);
145        film->video_stream_index = st->index;
146        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
147        st->codec->codec_id = film->video_type;
148        st->codec->codec_tag = 0;  /* no fourcc */
149        st->codec->width = AV_RB32(&scratch[16]);
150        st->codec->height = AV_RB32(&scratch[12]);
151
152        if (film->video_type == CODEC_ID_RAWVIDEO) {
153            if (scratch[20] == 24) {
154                st->codec->pix_fmt = PIX_FMT_RGB24;
155            } else {
156                av_log(s, AV_LOG_ERROR, "raw video is using unhandled %dbpp\n", scratch[20]);
157                return -1;
158            }
159        }
160    }
161
162    if (film->audio_type) {
163        st = avformat_new_stream(s, NULL);
164        if (!st)
165            return AVERROR(ENOMEM);
166        film->audio_stream_index = st->index;
167        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
168        st->codec->codec_id = film->audio_type;
169        st->codec->codec_tag = 1;
170        st->codec->channels = film->audio_channels;
171        st->codec->sample_rate = film->audio_samplerate;
172
173        if (film->audio_type == CODEC_ID_ADPCM_ADX) {
174            st->codec->bits_per_coded_sample = 18 * 8 / 32;
175            st->codec->block_align = st->codec->channels * 18;
176            st->need_parsing = AVSTREAM_PARSE_FULL;
177        } else {
178            st->codec->bits_per_coded_sample = film->audio_bits;
179            st->codec->block_align = st->codec->channels *
180                st->codec->bits_per_coded_sample / 8;
181        }
182
183        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
184            st->codec->bits_per_coded_sample;
185    }
186
187    /* load the sample table */
188    if (avio_read(pb, scratch, 16) != 16)
189        return AVERROR(EIO);
190    if (AV_RB32(&scratch[0]) != STAB_TAG)
191        return AVERROR_INVALIDDATA;
192    film->base_clock = AV_RB32(&scratch[8]);
193    film->sample_count = AV_RB32(&scratch[12]);
194    if(film->sample_count >= UINT_MAX / sizeof(film_sample))
195        return -1;
196    film->sample_table = av_malloc(film->sample_count * sizeof(film_sample));
197    if (!film->sample_table)
198        return AVERROR(ENOMEM);
199
200    for(i=0; i<s->nb_streams; i++)
201        avpriv_set_pts_info(s->streams[i], 33, 1, film->base_clock);
202
203    audio_frame_counter = 0;
204    for (i = 0; i < film->sample_count; i++) {
205        /* load the next sample record and transfer it to an internal struct */
206        if (avio_read(pb, scratch, 16) != 16) {
207            av_free(film->sample_table);
208            return AVERROR(EIO);
209        }
210        film->sample_table[i].sample_offset =
211            data_offset + AV_RB32(&scratch[0]);
212        film->sample_table[i].sample_size = AV_RB32(&scratch[4]);
213        if (AV_RB32(&scratch[8]) == 0xFFFFFFFF) {
214            film->sample_table[i].stream = film->audio_stream_index;
215            film->sample_table[i].pts = audio_frame_counter;
216            film->sample_table[i].pts *= film->base_clock;
217            film->sample_table[i].pts /= film->audio_samplerate;
218
219            if (film->audio_type == CODEC_ID_ADPCM_ADX)
220                audio_frame_counter += (film->sample_table[i].sample_size * 32 /
221                    (18 * film->audio_channels));
222            else if (film->audio_type != CODEC_ID_NONE)
223                audio_frame_counter += (film->sample_table[i].sample_size /
224                    (film->audio_channels * film->audio_bits / 8));
225        } else {
226            film->sample_table[i].stream = film->video_stream_index;
227            film->sample_table[i].pts = AV_RB32(&scratch[8]) & 0x7FFFFFFF;
228            film->sample_table[i].keyframe = (scratch[8] & 0x80) ? 0 : 1;
229        }
230    }
231
232    film->current_sample = 0;
233
234    return 0;
235}
236
237static int film_read_packet(AVFormatContext *s,
238                            AVPacket *pkt)
239{
240    FilmDemuxContext *film = s->priv_data;
241    AVIOContext *pb = s->pb;
242    film_sample *sample;
243    int ret = 0;
244    int i;
245    int left, right;
246
247    if (film->current_sample >= film->sample_count)
248        return AVERROR(EIO);
249
250    sample = &film->sample_table[film->current_sample];
251
252    /* position the stream (will probably be there anyway) */
253    avio_seek(pb, sample->sample_offset, SEEK_SET);
254
255    /* do a special song and dance when loading FILM Cinepak chunks */
256    if ((sample->stream == film->video_stream_index) &&
257        (film->video_type == CODEC_ID_CINEPAK)) {
258        pkt->pos= avio_tell(pb);
259        if (av_new_packet(pkt, sample->sample_size))
260            return AVERROR(ENOMEM);
261        avio_read(pb, pkt->data, sample->sample_size);
262    } else if ((sample->stream == film->audio_stream_index) &&
263        (film->audio_channels == 2) &&
264        (film->audio_type != CODEC_ID_ADPCM_ADX)) {
265        /* stereo PCM needs to be interleaved */
266
267        if (av_new_packet(pkt, sample->sample_size))
268            return AVERROR(ENOMEM);
269
270        /* make sure the interleave buffer is large enough */
271        if (sample->sample_size > film->stereo_buffer_size) {
272            av_free(film->stereo_buffer);
273            film->stereo_buffer_size = sample->sample_size;
274            film->stereo_buffer = av_malloc(film->stereo_buffer_size);
275            if (!film->stereo_buffer) {
276                film->stereo_buffer_size = 0;
277                return AVERROR(ENOMEM);
278            }
279        }
280
281        pkt->pos= avio_tell(pb);
282        ret = avio_read(pb, film->stereo_buffer, sample->sample_size);
283        if (ret != sample->sample_size)
284            ret = AVERROR(EIO);
285
286        left = 0;
287        right = sample->sample_size / 2;
288        for (i = 0; i < sample->sample_size; ) {
289            if (film->audio_bits == 8) {
290                pkt->data[i++] = film->stereo_buffer[left++];
291                pkt->data[i++] = film->stereo_buffer[right++];
292            } else {
293                pkt->data[i++] = film->stereo_buffer[left++];
294                pkt->data[i++] = film->stereo_buffer[left++];
295                pkt->data[i++] = film->stereo_buffer[right++];
296                pkt->data[i++] = film->stereo_buffer[right++];
297            }
298        }
299    } else {
300        ret= av_get_packet(pb, pkt, sample->sample_size);
301        if (ret != sample->sample_size)
302            ret = AVERROR(EIO);
303    }
304
305    pkt->stream_index = sample->stream;
306    pkt->pts = sample->pts;
307
308    film->current_sample++;
309
310    return ret;
311}
312
313static int film_read_close(AVFormatContext *s)
314{
315    FilmDemuxContext *film = s->priv_data;
316
317    av_free(film->sample_table);
318    av_free(film->stereo_buffer);
319
320    return 0;
321}
322
323AVInputFormat ff_segafilm_demuxer = {
324    .name           = "film_cpk",
325    .long_name      = NULL_IF_CONFIG_SMALL("Sega FILM/CPK format"),
326    .priv_data_size = sizeof(FilmDemuxContext),
327    .read_probe     = film_probe,
328    .read_header    = film_read_header,
329    .read_packet    = film_read_packet,
330    .read_close     = film_read_close,
331};
332