00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #include "avformat.h"
00030 #include "internal.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(AVIOContext *s, char *buf, int maxlen)
00043 {
00044 int i = 0;
00045 char c;
00046
00047 while ((c = avio_r8(s))) {
00048 if(c == ' ')
00049 break;
00050 if (i < maxlen-1)
00051 buf[i++] = c;
00052 }
00053
00054 if(!c)
00055 avio_r8(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 AVIOContext *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 if (iss->packet_size <= 0) {
00091 av_log(s, AV_LOG_ERROR, "packet_size %d is invalid\n", iss->packet_size);
00092 return AVERROR_INVALIDDATA;
00093 }
00094
00095 iss->sample_start_pos = avio_tell(pb);
00096
00097 st = avformat_new_stream(s, NULL);
00098 if (!st)
00099 return AVERROR(ENOMEM);
00100 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00101 st->codec->codec_id = CODEC_ID_ADPCM_IMA_ISS;
00102 st->codec->channels = stereo ? 2 : 1;
00103 st->codec->sample_rate = 44100;
00104 if(rate_divisor > 0)
00105 st->codec->sample_rate /= rate_divisor;
00106 st->codec->bits_per_coded_sample = 4;
00107 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate
00108 * st->codec->bits_per_coded_sample;
00109 st->codec->block_align = iss->packet_size;
00110 avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
00111
00112 return 0;
00113 }
00114
00115 static int iss_read_packet(AVFormatContext *s, AVPacket *pkt)
00116 {
00117 IssDemuxContext *iss = s->priv_data;
00118 int ret = av_get_packet(s->pb, pkt, iss->packet_size);
00119
00120 if(ret != iss->packet_size)
00121 return AVERROR(EIO);
00122
00123 pkt->stream_index = 0;
00124 pkt->pts = avio_tell(s->pb) - iss->sample_start_pos;
00125 if(s->streams[0]->codec->channels > 0)
00126 pkt->pts /= s->streams[0]->codec->channels*2;
00127 return 0;
00128 }
00129
00130 AVInputFormat ff_iss_demuxer = {
00131 .name = "ISS",
00132 .long_name = NULL_IF_CONFIG_SMALL("Funcom ISS format"),
00133 .priv_data_size = sizeof(IssDemuxContext),
00134 .read_probe = iss_probe,
00135 .read_header = iss_read_header,
00136 .read_packet = iss_read_packet,
00137 };
00138