2 * ISS (.iss) file demuxer
3 * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net>
5 * This file is part of Libav.
7 * Libav 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.
12 * Libav 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * Funcom ISS file demuxer
25 * @author Jaikrishnan Menon
26 * @see http://wiki.multimedia.cx/index.php?title=FunCom_ISS
29 #include "libavutil/channel_layout.h"
32 #include "libavutil/avstring.h"
34 #define ISS_SIG "IMA_ADPCM_Sound"
35 #define ISS_SIG_LEN 15
36 #define MAX_TOKEN_SIZE 20
43 static void get_token(AVIOContext
*s
, char *buf
, int maxlen
)
48 while ((c
= avio_r8(s
))) {
58 buf
[i
] = 0; /* Ensure null terminated, but may be truncated */
61 static int iss_probe(AVProbeData
*p
)
63 if (strncmp(p
->buf
, ISS_SIG
, ISS_SIG_LEN
))
66 return AVPROBE_SCORE_MAX
;
69 static av_cold
int iss_read_header(AVFormatContext
*s
)
71 IssDemuxContext
*iss
= s
->priv_data
;
72 AVIOContext
*pb
= s
->pb
;
74 char token
[MAX_TOKEN_SIZE
];
75 int stereo
, rate_divisor
;
77 get_token(pb
, token
, sizeof(token
)); //"IMA_ADPCM_Sound"
78 get_token(pb
, token
, sizeof(token
)); //packet size
79 sscanf(token
, "%d", &iss
->packet_size
);
80 get_token(pb
, token
, sizeof(token
)); //File ID
81 get_token(pb
, token
, sizeof(token
)); //out size
82 get_token(pb
, token
, sizeof(token
)); //stereo
83 sscanf(token
, "%d", &stereo
);
84 get_token(pb
, token
, sizeof(token
)); //Unknown1
85 get_token(pb
, token
, sizeof(token
)); //RateDivisor
86 sscanf(token
, "%d", &rate_divisor
);
87 get_token(pb
, token
, sizeof(token
)); //Unknown2
88 get_token(pb
, token
, sizeof(token
)); //Version ID
89 get_token(pb
, token
, sizeof(token
)); //Size
91 iss
->sample_start_pos
= avio_tell(pb
);
93 st
= avformat_new_stream(s
, NULL
);
95 return AVERROR(ENOMEM
);
96 st
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
97 st
->codec
->codec_id
= AV_CODEC_ID_ADPCM_IMA_ISS
;
99 st
->codec
->channels
= 2;
100 st
->codec
->channel_layout
= AV_CH_LAYOUT_STEREO
;
102 st
->codec
->channels
= 1;
103 st
->codec
->channel_layout
= AV_CH_LAYOUT_MONO
;
105 st
->codec
->sample_rate
= 44100;
107 st
->codec
->sample_rate
/= rate_divisor
;
108 st
->codec
->bits_per_coded_sample
= 4;
109 st
->codec
->bit_rate
= st
->codec
->channels
* st
->codec
->sample_rate
110 * st
->codec
->bits_per_coded_sample
;
111 st
->codec
->block_align
= iss
->packet_size
;
112 avpriv_set_pts_info(st
, 32, 1, st
->codec
->sample_rate
);
117 static int iss_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
119 IssDemuxContext
*iss
= s
->priv_data
;
120 int ret
= av_get_packet(s
->pb
, pkt
, iss
->packet_size
);
122 if(ret
!= iss
->packet_size
)
125 pkt
->stream_index
= 0;
126 pkt
->pts
= avio_tell(s
->pb
) - iss
->sample_start_pos
;
127 if(s
->streams
[0]->codec
->channels
> 0)
128 pkt
->pts
/= s
->streams
[0]->codec
->channels
*2;
132 AVInputFormat ff_iss_demuxer
= {
134 .long_name
= NULL_IF_CONFIG_SMALL("Funcom ISS"),
135 .priv_data_size
= sizeof(IssDemuxContext
),
136 .read_probe
= iss_probe
,
137 .read_header
= iss_read_header
,
138 .read_packet
= iss_read_packet
,