extended ADPCM decoder by ISS specific IMA variant Originally committed as revision 16658 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -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, \ | |||
| @@ -0,0 +1,130 @@ | |||
| /* | |||
| * 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, | |||
| }; | |||