Commit 055dc116 authored by Stefan Gehrer's avatar Stefan Gehrer

added demuxer for FunCom ISS audio files,

extended ADPCM decoder by ISS specific IMA variant

Originally committed as revision 16658 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 8a569fee
......@@ -226,6 +226,7 @@ version 0.4.9-pre1:
- more accurate deblock filter
- padding support
- many optimizations and bugfixes
- FunCom ISS audio file demuxer and according ADPCM decoding
version 0.4.8:
......
......@@ -74,6 +74,8 @@ library:
@tab .fli/.flc files
@item FLV @tab X @tab X
@tab Macromedia Flash video files
@item FunCom ISS @tab @tab X
@tab Audio format used in various games from FunCom like The Longest Journey.
@item GXF @tab X @tab X
@tab General eXchange Format SMPTE 360M, used by Thomson Grass Valley
playout servers.
......@@ -385,6 +387,8 @@ following image formats are supported:
@item Intel Music Coder @tab @tab X
@item Interplay MVE DPCM @tab @tab X
@tab Used in various Interplay computer games.
@item ISS IMA ADPCM @tab @tab X
@tab Used in FunCom games.
@item MAXIS EA ADPCM @tab @tab X
@tab Used in Sim City 3000.
@item Microsoft ADPCM @tab X @tab X
......
......@@ -1131,6 +1131,33 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
*samples++ = c->status[0].predictor - c->status[1].predictor;
}
break;
case CODEC_ID_ADPCM_IMA_ISS:
c->status[0].predictor = (int16_t)AV_RL16(src + 0);
c->status[0].step_index = src[2];
src += 4;
if(st) {
c->status[1].predictor = (int16_t)AV_RL16(src + 0);
c->status[1].step_index = src[2];
src += 4;
}
while (src < buf + buf_size) {
if (st) {
*samples++ = adpcm_ima_expand_nibble(&c->status[0],
src[0] >> 4 , 3);
*samples++ = adpcm_ima_expand_nibble(&c->status[1],
src[0] & 0x0F, 3);
} else {
*samples++ = adpcm_ima_expand_nibble(&c->status[0],
src[0] & 0x0F, 3);
*samples++ = adpcm_ima_expand_nibble(&c->status[0],
src[0] >> 4 , 3);
}
src++;
}
break;
case CODEC_ID_ADPCM_IMA_WS:
/* no per-block initialization; just start decoding the data */
while (src < buf + buf_size) {
......@@ -1641,6 +1668,7 @@ ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3, "IMA Duck DK3 ADPCM");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4, "IMA Duck DK4 ADPCM");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs, "IMA Electronic Arts EACS ADPCM");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead, "IMA Electronic Arts SEAD ADPCM");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_ISS, adpcm_ima_iss, "IMA Funcom ISS ADPCM");
ADPCM_CODEC (CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, "IMA QuickTime ADPCM");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg, "IMA Loki SDL MJPEG ADPCM");
ADPCM_CODEC (CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, "IMA Wav ADPCM");
......
......@@ -264,6 +264,7 @@ void avcodec_register_all(void)
REGISTER_DECODER (ADPCM_IMA_DK4, adpcm_ima_dk4);
REGISTER_DECODER (ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs);
REGISTER_DECODER (ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead);
REGISTER_DECODER (ADPCM_IMA_ISS, adpcm_ima_iss);
REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt);
REGISTER_DECODER (ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav);
......
......@@ -30,7 +30,7 @@
#include "libavutil/avutil.h"
#define LIBAVCODEC_VERSION_MAJOR 52
#define LIBAVCODEC_VERSION_MINOR 10
#define LIBAVCODEC_VERSION_MINOR 11
#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
......@@ -245,6 +245,7 @@ enum CodecID {
CODEC_ID_ADPCM_IMA_EA_EACS,
CODEC_ID_ADPCM_EA_XAS,
CODEC_ID_ADPCM_EA_MAXIS_XA,
CODEC_ID_ADPCM_IMA_ISS,
/* AMR */
CODEC_ID_AMR_NB= 0x12000,
......
......@@ -78,6 +78,7 @@ OBJS-$(CONFIG_IMAGE2PIPE_MUXER) += img2.o
OBJS-$(CONFIG_INGENIENT_DEMUXER) += raw.o
OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o
OBJS-$(CONFIG_IPOD_MUXER) += movenc.o riff.o isom.o avc.o
OBJS-$(CONFIG_ISS_DEMUXER) += iss.o
OBJS-$(CONFIG_LMLM4_DEMUXER) += lmlm4.o
OBJS-$(CONFIG_M4V_DEMUXER) += raw.o
OBJS-$(CONFIG_M4V_MUXER) += raw.o
......
......@@ -101,6 +101,7 @@ void av_register_all(void)
REGISTER_DEMUXER (INGENIENT, ingenient);
REGISTER_DEMUXER (IPMOVIE, ipmovie);
REGISTER_MUXER (IPOD, ipod);
REGISTER_DEMUXER (ISS, iss);
REGISTER_DEMUXER (LMLM4, lmlm4);
REGISTER_MUXDEMUX (M4V, m4v);
REGISTER_MUXDEMUX (MATROSKA, matroska);
......
......@@ -22,7 +22,7 @@
#define AVFORMAT_AVFORMAT_H
#define LIBAVFORMAT_VERSION_MAJOR 52
#define LIBAVFORMAT_VERSION_MINOR 23
#define LIBAVFORMAT_VERSION_MINOR 24
#define LIBAVFORMAT_VERSION_MICRO 1
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
......
/*
* ISS (.iss) file demuxer
* Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file iss.c
* Funcom ISS file demuxer
* @author Jaikrishnan Menon
* for more information on the .iss file format, visit:
* http://wiki.multimedia.cx/index.php?title=FunCom_ISS
*/
#include "avformat.h"
#include "libavutil/avstring.h"
#define ISS_SIG "IMA_ADPCM_Sound"
#define ISS_SIG_LEN 15
#define MAX_TOKEN_SIZE 20
typedef struct {
int packet_size;
int sample_start_pos;
} IssDemuxContext;
static void get_token(ByteIOContext *s, char *buf, int maxlen)
{
int i = 0;
char c;
while ((c = get_byte(s))) {
if(c == ' ')
break;
if (i < maxlen-1)
buf[i++] = c;
}
buf[i] = 0; /* Ensure null terminated, but may be truncated */
}
static int iss_probe(AVProbeData *p)
{
if (strncmp(p->buf, ISS_SIG, ISS_SIG_LEN))
return 0;
return AVPROBE_SCORE_MAX;
}
static av_cold int iss_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
IssDemuxContext *iss = s->priv_data;
ByteIOContext *pb = s->pb;
AVStream *st;
char token[MAX_TOKEN_SIZE];
int stereo, rate_divisor;
get_token(pb, token, sizeof(token)); //"IMA_ADPCM_Sound"
get_token(pb, token, sizeof(token)); //packet size
sscanf(token, "%d", &iss->packet_size);
get_token(pb, token, sizeof(token)); //File ID
get_token(pb, token, sizeof(token)); //out size
get_token(pb, token, sizeof(token)); //stereo
sscanf(token, "%d", &stereo);
get_token(pb, token, sizeof(token)); //Unknown1
get_token(pb, token, sizeof(token)); //RateDivisor
sscanf(token, "%d", &rate_divisor);
get_token(pb, token, sizeof(token)); //Unknown2
get_token(pb, token, sizeof(token)); //Version ID
get_token(pb, token, sizeof(token)); //Size
iss->sample_start_pos = url_ftell(pb);
st = av_new_stream(s, 0);
if (!st)
return AVERROR(ENOMEM);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_ADPCM_IMA_ISS;
st->codec->channels = stereo ? 2 : 1;
st->codec->sample_rate = 44100;
if(rate_divisor > 0)
st->codec->sample_rate /= rate_divisor;
st->codec->bits_per_coded_sample = 4;
st->codec->bit_rate = st->codec->channels * st->codec->sample_rate
* st->codec->bits_per_coded_sample;
st->codec->block_align = iss->packet_size;
av_set_pts_info(st, 32, 1, st->codec->sample_rate);
return 0;
}
static int iss_read_packet(AVFormatContext *s, AVPacket *pkt)
{
IssDemuxContext *iss = s->priv_data;
int ret = av_get_packet(s->pb, pkt, iss->packet_size);
if(ret < 0)
return ret;
pkt->stream_index = 0;
pkt->pts = url_ftell(s->pb) - iss->sample_start_pos;
if(s->streams[0]->codec->channels > 0)
pkt->pts /= s->streams[0]->codec->channels*2;
return 0;
}
AVInputFormat iss_demuxer = {
"ISS",
NULL_IF_CONFIG_SMALL("Funcom ISS format"),
sizeof(IssDemuxContext),
iss_probe,
iss_read_header,
iss_read_packet,
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment