1/* 2 * ISS (.iss) file demuxer 3 * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net> 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 * Funcom ISS file demuxer 25 * @author Jaikrishnan Menon 26 * for more information on the .iss file format, visit: 27 * http://wiki.multimedia.cx/index.php?title=FunCom_ISS 28 */ 29 30#include "avformat.h" 31#include "libavutil/avstring.h" 32 33#define ISS_SIG "IMA_ADPCM_Sound" 34#define ISS_SIG_LEN 15 35#define MAX_TOKEN_SIZE 20 36 37typedef struct { 38 int packet_size; 39 int sample_start_pos; 40} IssDemuxContext; 41 42static void get_token(ByteIOContext *s, char *buf, int maxlen) 43{ 44 int i = 0; 45 char c; 46 47 while ((c = get_byte(s))) { 48 if(c == ' ') 49 break; 50 if (i < maxlen-1) 51 buf[i++] = c; 52 } 53 54 if(!c) 55 get_byte(s); 56 57 buf[i] = 0; /* Ensure null terminated, but may be truncated */ 58} 59 60static int iss_probe(AVProbeData *p) 61{ 62 if (strncmp(p->buf, ISS_SIG, ISS_SIG_LEN)) 63 return 0; 64 65 return AVPROBE_SCORE_MAX; 66} 67 68static av_cold int iss_read_header(AVFormatContext *s, AVFormatParameters *ap) 69{ 70 IssDemuxContext *iss = s->priv_data; 71 ByteIOContext *pb = s->pb; 72 AVStream *st; 73 char token[MAX_TOKEN_SIZE]; 74 int stereo, rate_divisor; 75 76 get_token(pb, token, sizeof(token)); //"IMA_ADPCM_Sound" 77 get_token(pb, token, sizeof(token)); //packet size 78 sscanf(token, "%d", &iss->packet_size); 79 get_token(pb, token, sizeof(token)); //File ID 80 get_token(pb, token, sizeof(token)); //out size 81 get_token(pb, token, sizeof(token)); //stereo 82 sscanf(token, "%d", &stereo); 83 get_token(pb, token, sizeof(token)); //Unknown1 84 get_token(pb, token, sizeof(token)); //RateDivisor 85 sscanf(token, "%d", &rate_divisor); 86 get_token(pb, token, sizeof(token)); //Unknown2 87 get_token(pb, token, sizeof(token)); //Version ID 88 get_token(pb, token, sizeof(token)); //Size 89 90 iss->sample_start_pos = url_ftell(pb); 91 92 st = av_new_stream(s, 0); 93 if (!st) 94 return AVERROR(ENOMEM); 95 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 96 st->codec->codec_id = CODEC_ID_ADPCM_IMA_ISS; 97 st->codec->channels = stereo ? 2 : 1; 98 st->codec->sample_rate = 44100; 99 if(rate_divisor > 0) 100 st->codec->sample_rate /= rate_divisor; 101 st->codec->bits_per_coded_sample = 4; 102 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate 103 * st->codec->bits_per_coded_sample; 104 st->codec->block_align = iss->packet_size; 105 av_set_pts_info(st, 32, 1, st->codec->sample_rate); 106 107 return 0; 108} 109 110static int iss_read_packet(AVFormatContext *s, AVPacket *pkt) 111{ 112 IssDemuxContext *iss = s->priv_data; 113 int ret = av_get_packet(s->pb, pkt, iss->packet_size); 114 115 if(ret != iss->packet_size) 116 return AVERROR(EIO); 117 118 pkt->stream_index = 0; 119 pkt->pts = url_ftell(s->pb) - iss->sample_start_pos; 120 if(s->streams[0]->codec->channels > 0) 121 pkt->pts /= s->streams[0]->codec->channels*2; 122 return 0; 123} 124 125AVInputFormat iss_demuxer = { 126 "ISS", 127 NULL_IF_CONFIG_SMALL("Funcom ISS format"), 128 sizeof(IssDemuxContext), 129 iss_probe, 130 iss_read_header, 131 iss_read_packet, 132}; 133 134