2 * ISS (.iss) file demuxer
3 * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net>
5 * This file is part of FFmpeg.
7 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 if (sscanf(token
, "%d", &iss
->packet_size
) != 1) {
80 av_log(s
, AV_LOG_ERROR
, "Failed parsing packet size\n");
81 return AVERROR_INVALIDDATA
;
83 get_token(pb
, token
, sizeof(token
)); //File ID
84 get_token(pb
, token
, sizeof(token
)); //out size
85 get_token(pb
, token
, sizeof(token
)); //stereo
86 if (sscanf(token
, "%d", &stereo
) != 1) {
87 av_log(s
, AV_LOG_ERROR
, "Failed parsing stereo flag\n");
88 return AVERROR_INVALIDDATA
;
90 get_token(pb
, token
, sizeof(token
)); //Unknown1
91 get_token(pb
, token
, sizeof(token
)); //RateDivisor
92 if (sscanf(token
, "%d", &rate_divisor
) != 1) {
93 av_log(s
, AV_LOG_ERROR
, "Failed parsing rate_divisor\n");
94 return AVERROR_INVALIDDATA
;
96 get_token(pb
, token
, sizeof(token
)); //Unknown2
97 get_token(pb
, token
, sizeof(token
)); //Version ID
98 get_token(pb
, token
, sizeof(token
)); //Size
100 if (iss
->packet_size
<= 0) {
101 av_log(s
, AV_LOG_ERROR
, "packet_size %d is invalid\n", iss
->packet_size
);
102 return AVERROR_INVALIDDATA
;
105 iss
->sample_start_pos
= avio_tell(pb
);
107 st
= avformat_new_stream(s
, NULL
);
109 return AVERROR(ENOMEM
);
110 st
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
111 st
->codec
->codec_id
= AV_CODEC_ID_ADPCM_IMA_ISS
;
113 st
->codec
->channels
= 2;
114 st
->codec
->channel_layout
= AV_CH_LAYOUT_STEREO
;
116 st
->codec
->channels
= 1;
117 st
->codec
->channel_layout
= AV_CH_LAYOUT_MONO
;
119 st
->codec
->sample_rate
= 44100;
121 st
->codec
->sample_rate
/= rate_divisor
;
122 st
->codec
->bits_per_coded_sample
= 4;
123 st
->codec
->bit_rate
= st
->codec
->channels
* st
->codec
->sample_rate
124 * st
->codec
->bits_per_coded_sample
;
125 st
->codec
->block_align
= iss
->packet_size
;
126 avpriv_set_pts_info(st
, 32, 1, st
->codec
->sample_rate
);
131 static int iss_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
133 IssDemuxContext
*iss
= s
->priv_data
;
134 int ret
= av_get_packet(s
->pb
, pkt
, iss
->packet_size
);
136 if(ret
!= iss
->packet_size
)
139 pkt
->stream_index
= 0;
140 pkt
->pts
= avio_tell(s
->pb
) - iss
->sample_start_pos
;
141 if(s
->streams
[0]->codec
->channels
> 0)
142 pkt
->pts
/= s
->streams
[0]->codec
->channels
*2;
146 AVInputFormat ff_iss_demuxer
= {
148 .long_name
= NULL_IF_CONFIG_SMALL("Funcom ISS"),
149 .priv_data_size
= sizeof(IssDemuxContext
),
150 .read_probe
= iss_probe
,
151 .read_header
= iss_read_header
,
152 .read_packet
= iss_read_packet
,