Libav 0.7.1
|
00001 /* 00002 * Sega FILM Format (CPK) Demuxer 00003 * Copyright (c) 2003 The ffmpeg Project 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00030 #include "libavutil/intreadwrite.h" 00031 #include "avformat.h" 00032 00033 #define FILM_TAG MKBETAG('F', 'I', 'L', 'M') 00034 #define FDSC_TAG MKBETAG('F', 'D', 'S', 'C') 00035 #define STAB_TAG MKBETAG('S', 'T', 'A', 'B') 00036 #define CVID_TAG MKBETAG('c', 'v', 'i', 'd') 00037 00038 typedef struct { 00039 int stream; 00040 int64_t sample_offset; 00041 unsigned int sample_size; 00042 int64_t pts; 00043 int keyframe; 00044 } film_sample; 00045 00046 typedef struct FilmDemuxContext { 00047 int video_stream_index; 00048 int audio_stream_index; 00049 00050 enum CodecID audio_type; 00051 unsigned int audio_samplerate; 00052 unsigned int audio_bits; 00053 unsigned int audio_channels; 00054 00055 enum CodecID video_type; 00056 unsigned int sample_count; 00057 film_sample *sample_table; 00058 unsigned int current_sample; 00059 00060 unsigned int base_clock; 00061 unsigned int version; 00062 00063 /* buffer used for interleaving stereo PCM data */ 00064 unsigned char *stereo_buffer; 00065 int stereo_buffer_size; 00066 } FilmDemuxContext; 00067 00068 static int film_probe(AVProbeData *p) 00069 { 00070 if (AV_RB32(&p->buf[0]) != FILM_TAG) 00071 return 0; 00072 00073 return AVPROBE_SCORE_MAX; 00074 } 00075 00076 static int film_read_header(AVFormatContext *s, 00077 AVFormatParameters *ap) 00078 { 00079 FilmDemuxContext *film = s->priv_data; 00080 AVIOContext *pb = s->pb; 00081 AVStream *st; 00082 unsigned char scratch[256]; 00083 int i; 00084 unsigned int data_offset; 00085 unsigned int audio_frame_counter; 00086 00087 film->sample_table = NULL; 00088 film->stereo_buffer = NULL; 00089 film->stereo_buffer_size = 0; 00090 00091 /* load the main FILM header */ 00092 if (avio_read(pb, scratch, 16) != 16) 00093 return AVERROR(EIO); 00094 data_offset = AV_RB32(&scratch[4]); 00095 film->version = AV_RB32(&scratch[8]); 00096 00097 /* load the FDSC chunk */ 00098 if (film->version == 0) { 00099 /* special case for Lemmings .film files; 20-byte header */ 00100 if (avio_read(pb, scratch, 20) != 20) 00101 return AVERROR(EIO); 00102 /* make some assumptions about the audio parameters */ 00103 film->audio_type = CODEC_ID_PCM_S8; 00104 film->audio_samplerate = 22050; 00105 film->audio_channels = 1; 00106 film->audio_bits = 8; 00107 } else { 00108 /* normal Saturn .cpk files; 32-byte header */ 00109 if (avio_read(pb, scratch, 32) != 32) 00110 return AVERROR(EIO); 00111 film->audio_samplerate = AV_RB16(&scratch[24]); 00112 film->audio_channels = scratch[21]; 00113 film->audio_bits = scratch[22]; 00114 if (film->audio_bits == 8) 00115 film->audio_type = CODEC_ID_PCM_S8; 00116 else if (film->audio_bits == 16) 00117 film->audio_type = CODEC_ID_PCM_S16BE; 00118 else 00119 film->audio_type = CODEC_ID_NONE; 00120 } 00121 00122 if (AV_RB32(&scratch[0]) != FDSC_TAG) 00123 return AVERROR_INVALIDDATA; 00124 00125 if (AV_RB32(&scratch[8]) == CVID_TAG) { 00126 film->video_type = CODEC_ID_CINEPAK; 00127 } else 00128 film->video_type = CODEC_ID_NONE; 00129 00130 /* initialize the decoder streams */ 00131 if (film->video_type) { 00132 st = av_new_stream(s, 0); 00133 if (!st) 00134 return AVERROR(ENOMEM); 00135 film->video_stream_index = st->index; 00136 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00137 st->codec->codec_id = film->video_type; 00138 st->codec->codec_tag = 0; /* no fourcc */ 00139 st->codec->width = AV_RB32(&scratch[16]); 00140 st->codec->height = AV_RB32(&scratch[12]); 00141 } 00142 00143 if (film->audio_type) { 00144 st = av_new_stream(s, 0); 00145 if (!st) 00146 return AVERROR(ENOMEM); 00147 film->audio_stream_index = st->index; 00148 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00149 st->codec->codec_id = film->audio_type; 00150 st->codec->codec_tag = 1; 00151 st->codec->channels = film->audio_channels; 00152 st->codec->bits_per_coded_sample = film->audio_bits; 00153 st->codec->sample_rate = film->audio_samplerate; 00154 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 00155 st->codec->bits_per_coded_sample; 00156 st->codec->block_align = st->codec->channels * 00157 st->codec->bits_per_coded_sample / 8; 00158 } 00159 00160 /* load the sample table */ 00161 if (avio_read(pb, scratch, 16) != 16) 00162 return AVERROR(EIO); 00163 if (AV_RB32(&scratch[0]) != STAB_TAG) 00164 return AVERROR_INVALIDDATA; 00165 film->base_clock = AV_RB32(&scratch[8]); 00166 film->sample_count = AV_RB32(&scratch[12]); 00167 if(film->sample_count >= UINT_MAX / sizeof(film_sample)) 00168 return -1; 00169 film->sample_table = av_malloc(film->sample_count * sizeof(film_sample)); 00170 00171 for(i=0; i<s->nb_streams; i++) 00172 av_set_pts_info(s->streams[i], 33, 1, film->base_clock); 00173 00174 audio_frame_counter = 0; 00175 for (i = 0; i < film->sample_count; i++) { 00176 /* load the next sample record and transfer it to an internal struct */ 00177 if (avio_read(pb, scratch, 16) != 16) { 00178 av_free(film->sample_table); 00179 return AVERROR(EIO); 00180 } 00181 film->sample_table[i].sample_offset = 00182 data_offset + AV_RB32(&scratch[0]); 00183 film->sample_table[i].sample_size = AV_RB32(&scratch[4]); 00184 if (AV_RB32(&scratch[8]) == 0xFFFFFFFF) { 00185 film->sample_table[i].stream = film->audio_stream_index; 00186 film->sample_table[i].pts = audio_frame_counter; 00187 film->sample_table[i].pts *= film->base_clock; 00188 film->sample_table[i].pts /= film->audio_samplerate; 00189 00190 audio_frame_counter += (film->sample_table[i].sample_size / 00191 (film->audio_channels * film->audio_bits / 8)); 00192 } else { 00193 film->sample_table[i].stream = film->video_stream_index; 00194 film->sample_table[i].pts = AV_RB32(&scratch[8]) & 0x7FFFFFFF; 00195 film->sample_table[i].keyframe = (scratch[8] & 0x80) ? 0 : 1; 00196 } 00197 } 00198 00199 film->current_sample = 0; 00200 00201 return 0; 00202 } 00203 00204 static int film_read_packet(AVFormatContext *s, 00205 AVPacket *pkt) 00206 { 00207 FilmDemuxContext *film = s->priv_data; 00208 AVIOContext *pb = s->pb; 00209 film_sample *sample; 00210 int ret = 0; 00211 int i; 00212 int left, right; 00213 00214 if (film->current_sample >= film->sample_count) 00215 return AVERROR(EIO); 00216 00217 sample = &film->sample_table[film->current_sample]; 00218 00219 /* position the stream (will probably be there anyway) */ 00220 avio_seek(pb, sample->sample_offset, SEEK_SET); 00221 00222 /* do a special song and dance when loading FILM Cinepak chunks */ 00223 if ((sample->stream == film->video_stream_index) && 00224 (film->video_type == CODEC_ID_CINEPAK)) { 00225 pkt->pos= avio_tell(pb); 00226 if (av_new_packet(pkt, sample->sample_size)) 00227 return AVERROR(ENOMEM); 00228 avio_read(pb, pkt->data, sample->sample_size); 00229 } else if ((sample->stream == film->audio_stream_index) && 00230 (film->audio_channels == 2)) { 00231 /* stereo PCM needs to be interleaved */ 00232 00233 if (av_new_packet(pkt, sample->sample_size)) 00234 return AVERROR(ENOMEM); 00235 00236 /* make sure the interleave buffer is large enough */ 00237 if (sample->sample_size > film->stereo_buffer_size) { 00238 av_free(film->stereo_buffer); 00239 film->stereo_buffer_size = sample->sample_size; 00240 film->stereo_buffer = av_malloc(film->stereo_buffer_size); 00241 if (!film->stereo_buffer) { 00242 film->stereo_buffer_size = 0; 00243 return AVERROR(ENOMEM); 00244 } 00245 } 00246 00247 pkt->pos= avio_tell(pb); 00248 ret = avio_read(pb, film->stereo_buffer, sample->sample_size); 00249 if (ret != sample->sample_size) 00250 ret = AVERROR(EIO); 00251 00252 left = 0; 00253 right = sample->sample_size / 2; 00254 for (i = 0; i < sample->sample_size; ) { 00255 if (film->audio_bits == 8) { 00256 pkt->data[i++] = film->stereo_buffer[left++]; 00257 pkt->data[i++] = film->stereo_buffer[right++]; 00258 } else { 00259 pkt->data[i++] = film->stereo_buffer[left++]; 00260 pkt->data[i++] = film->stereo_buffer[left++]; 00261 pkt->data[i++] = film->stereo_buffer[right++]; 00262 pkt->data[i++] = film->stereo_buffer[right++]; 00263 } 00264 } 00265 } else { 00266 ret= av_get_packet(pb, pkt, sample->sample_size); 00267 if (ret != sample->sample_size) 00268 ret = AVERROR(EIO); 00269 } 00270 00271 pkt->stream_index = sample->stream; 00272 pkt->pts = sample->pts; 00273 00274 film->current_sample++; 00275 00276 return ret; 00277 } 00278 00279 static int film_read_close(AVFormatContext *s) 00280 { 00281 FilmDemuxContext *film = s->priv_data; 00282 00283 av_free(film->sample_table); 00284 av_free(film->stereo_buffer); 00285 00286 return 0; 00287 } 00288 00289 AVInputFormat ff_segafilm_demuxer = { 00290 "film_cpk", 00291 NULL_IF_CONFIG_SMALL("Sega FILM/CPK format"), 00292 sizeof(FilmDemuxContext), 00293 film_probe, 00294 film_read_header, 00295 film_read_packet, 00296 film_read_close, 00297 };