00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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;
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));
00077 get_token(pb, token, sizeof(token));
00078 sscanf(token, "%d", &iss->packet_size);
00079 get_token(pb, token, sizeof(token));
00080 get_token(pb, token, sizeof(token));
00081 get_token(pb, token, sizeof(token));
00082 sscanf(token, "%d", &stereo);
00083 get_token(pb, token, sizeof(token));
00084 get_token(pb, token, sizeof(token));
00085 sscanf(token, "%d", &rate_divisor);
00086 get_token(pb, token, sizeof(token));
00087 get_token(pb, token, sizeof(token));
00088 get_token(pb, token, sizeof(token));
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 = CODEC_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