Libav
|
00001 /* 00002 * ISS (.iss) file demuxer 00003 * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net> 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00030 #include "avformat.h" 00031 #include "libavutil/avstring.h" 00032 00033 #define ISS_SIG "IMA_ADPCM_Sound" 00034 #define ISS_SIG_LEN 15 00035 #define MAX_TOKEN_SIZE 20 00036 00037 typedef struct { 00038 int packet_size; 00039 int sample_start_pos; 00040 } IssDemuxContext; 00041 00042 static void get_token(ByteIOContext *s, char *buf, int maxlen) 00043 { 00044 int i = 0; 00045 char c; 00046 00047 while ((c = get_byte(s))) { 00048 if(c == ' ') 00049 break; 00050 if (i < maxlen-1) 00051 buf[i++] = c; 00052 } 00053 00054 if(!c) 00055 get_byte(s); 00056 00057 buf[i] = 0; /* Ensure null terminated, but may be truncated */ 00058 } 00059 00060 static int iss_probe(AVProbeData *p) 00061 { 00062 if (strncmp(p->buf, ISS_SIG, ISS_SIG_LEN)) 00063 return 0; 00064 00065 return AVPROBE_SCORE_MAX; 00066 } 00067 00068 static av_cold int iss_read_header(AVFormatContext *s, AVFormatParameters *ap) 00069 { 00070 IssDemuxContext *iss = s->priv_data; 00071 ByteIOContext *pb = s->pb; 00072 AVStream *st; 00073 char token[MAX_TOKEN_SIZE]; 00074 int stereo, rate_divisor; 00075 00076 get_token(pb, token, sizeof(token)); //"IMA_ADPCM_Sound" 00077 get_token(pb, token, sizeof(token)); //packet size 00078 sscanf(token, "%d", &iss->packet_size); 00079 get_token(pb, token, sizeof(token)); //File ID 00080 get_token(pb, token, sizeof(token)); //out size 00081 get_token(pb, token, sizeof(token)); //stereo 00082 sscanf(token, "%d", &stereo); 00083 get_token(pb, token, sizeof(token)); //Unknown1 00084 get_token(pb, token, sizeof(token)); //RateDivisor 00085 sscanf(token, "%d", &rate_divisor); 00086 get_token(pb, token, sizeof(token)); //Unknown2 00087 get_token(pb, token, sizeof(token)); //Version ID 00088 get_token(pb, token, sizeof(token)); //Size 00089 00090 iss->sample_start_pos = url_ftell(pb); 00091 00092 st = av_new_stream(s, 0); 00093 if (!st) 00094 return AVERROR(ENOMEM); 00095 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00096 st->codec->codec_id = CODEC_ID_ADPCM_IMA_ISS; 00097 st->codec->channels = stereo ? 2 : 1; 00098 st->codec->sample_rate = 44100; 00099 if(rate_divisor > 0) 00100 st->codec->sample_rate /= rate_divisor; 00101 st->codec->bits_per_coded_sample = 4; 00102 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate 00103 * st->codec->bits_per_coded_sample; 00104 st->codec->block_align = iss->packet_size; 00105 av_set_pts_info(st, 32, 1, st->codec->sample_rate); 00106 00107 return 0; 00108 } 00109 00110 static int iss_read_packet(AVFormatContext *s, AVPacket *pkt) 00111 { 00112 IssDemuxContext *iss = s->priv_data; 00113 int ret = av_get_packet(s->pb, pkt, iss->packet_size); 00114 00115 if(ret != iss->packet_size) 00116 return AVERROR(EIO); 00117 00118 pkt->stream_index = 0; 00119 pkt->pts = url_ftell(s->pb) - iss->sample_start_pos; 00120 if(s->streams[0]->codec->channels > 0) 00121 pkt->pts /= s->streams[0]->codec->channels*2; 00122 return 0; 00123 } 00124 00125 AVInputFormat iss_demuxer = { 00126 "ISS", 00127 NULL_IF_CONFIG_SMALL("Funcom ISS format"), 00128 sizeof(IssDemuxContext), 00129 iss_probe, 00130 iss_read_header, 00131 iss_read_packet, 00132 }; 00133