00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #include "libavutil/channel_layout.h"
00030 #include "avformat.h"
00031 #include "internal.h"
00032 #include "libavutil/avstring.h"
00033
00034 #define ISS_SIG "IMA_ADPCM_Sound"
00035 #define ISS_SIG_LEN 15
00036 #define MAX_TOKEN_SIZE 20
00037
00038 typedef struct {
00039 int packet_size;
00040 int sample_start_pos;
00041 } IssDemuxContext;
00042
00043 static void get_token(AVIOContext *s, char *buf, int maxlen)
00044 {
00045 int i = 0;
00046 char c;
00047
00048 while ((c = avio_r8(s))) {
00049 if(c == ' ')
00050 break;
00051 if (i < maxlen-1)
00052 buf[i++] = c;
00053 }
00054
00055 if(!c)
00056 avio_r8(s);
00057
00058 buf[i] = 0;
00059 }
00060
00061 static int iss_probe(AVProbeData *p)
00062 {
00063 if (strncmp(p->buf, ISS_SIG, ISS_SIG_LEN))
00064 return 0;
00065
00066 return AVPROBE_SCORE_MAX;
00067 }
00068
00069 static av_cold int iss_read_header(AVFormatContext *s)
00070 {
00071 IssDemuxContext *iss = s->priv_data;
00072 AVIOContext *pb = s->pb;
00073 AVStream *st;
00074 char token[MAX_TOKEN_SIZE];
00075 int stereo, rate_divisor;
00076
00077 get_token(pb, token, sizeof(token));
00078 get_token(pb, token, sizeof(token));
00079 sscanf(token, "%d", &iss->packet_size);
00080 get_token(pb, token, sizeof(token));
00081 get_token(pb, token, sizeof(token));
00082 get_token(pb, token, sizeof(token));
00083 sscanf(token, "%d", &stereo);
00084 get_token(pb, token, sizeof(token));
00085 get_token(pb, token, sizeof(token));
00086 sscanf(token, "%d", &rate_divisor);
00087 get_token(pb, token, sizeof(token));
00088 get_token(pb, token, sizeof(token));
00089 get_token(pb, token, sizeof(token));
00090
00091 if (iss->packet_size <= 0) {
00092 av_log(s, AV_LOG_ERROR, "packet_size %d is invalid\n", iss->packet_size);
00093 return AVERROR_INVALIDDATA;
00094 }
00095
00096 iss->sample_start_pos = avio_tell(pb);
00097
00098 st = avformat_new_stream(s, NULL);
00099 if (!st)
00100 return AVERROR(ENOMEM);
00101 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00102 st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_ISS;
00103 if (stereo) {
00104 st->codec->channels = 2;
00105 st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
00106 } else {
00107 st->codec->channels = 1;
00108 st->codec->channel_layout = AV_CH_LAYOUT_MONO;
00109 }
00110 st->codec->sample_rate = 44100;
00111 if(rate_divisor > 0)
00112 st->codec->sample_rate /= rate_divisor;
00113 st->codec->bits_per_coded_sample = 4;
00114 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate
00115 * st->codec->bits_per_coded_sample;
00116 st->codec->block_align = iss->packet_size;
00117 avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
00118
00119 return 0;
00120 }
00121
00122 static int iss_read_packet(AVFormatContext *s, AVPacket *pkt)
00123 {
00124 IssDemuxContext *iss = s->priv_data;
00125 int ret = av_get_packet(s->pb, pkt, iss->packet_size);
00126
00127 if(ret != iss->packet_size)
00128 return AVERROR(EIO);
00129
00130 pkt->stream_index = 0;
00131 pkt->pts = avio_tell(s->pb) - iss->sample_start_pos;
00132 if(s->streams[0]->codec->channels > 0)
00133 pkt->pts /= s->streams[0]->codec->channels*2;
00134 return 0;
00135 }
00136
00137 AVInputFormat ff_iss_demuxer = {
00138 .name = "iss",
00139 .long_name = NULL_IF_CONFIG_SMALL("Funcom ISS"),
00140 .priv_data_size = sizeof(IssDemuxContext),
00141 .read_probe = iss_probe,
00142 .read_header = iss_read_header,
00143 .read_packet = iss_read_packet,
00144 };