Hi
Attached are the patches for Maxis EA .XA file decoding. Was out of
town for the weekend hence the late submission.
Please comment on any improvements/errors?
Regards
Robert Marston
--- ../../ffmpeg/libavcodec/adpcm.c 2008-03-31 12:15:57.000000000 +0200
+++ libavcodec/adpcm.c 2008-04-08 01:21:08.000000000 +0200
@@ -34,6 +34,7 @@
* EA IMA EACS decoder by Peter Ross ([EMAIL PROTECTED])
* EA IMA SEAD decoder by Peter Ross ([EMAIL PROTECTED])
* EA ADPCM XAS decoder by Peter Ross ([EMAIL PROTECTED])
+ * MAXIS EA ADPCM decoder by Robert Marston ([EMAIL PROTECTED])
* THP ADPCM decoder by Marco Gerards ([EMAIL PROTECTED])
*
* Features and limitations:
@@ -149,6 +150,10 @@
typedef struct ADPCMContext {
int channel; /* for stereo MOVs, decode left, then decode right, then tell
it's decoded */
ADPCMChannelStatus status[6];
+ int32_t mxa_current_left_sample; /*Needed to keep track of left and right
samples for Maxis EA XA */
+ int32_t mxa_previous_left_sample;
+ int32_t mxa_current_right_sample;
+ int32_t mxa_previous_right_sample;
} ADPCMContext;
/* XXX: implement encoding */
@@ -669,6 +674,12 @@
unsigned int max_channels = 2;
switch(avctx->codec->id) {
+ case CODEC_ID_ADPCM_EA_MAXIS_XA://EDITED!!
+ c->mxa_current_left_sample = 0;
+ c->mxa_previous_left_sample = 0;
+ c->mxa_current_right_sample = 0;
+ c->mxa_previous_right_sample = 0;
+ break;
case CODEC_ID_ADPCM_EA_R1:
case CODEC_ID_ADPCM_EA_R2:
case CODEC_ID_ADPCM_EA_R3:
@@ -1235,6 +1246,68 @@
}
}
break;
+ case CODEC_ID_ADPCM_EA_MAXIS_XA:
+ channel = avctx->channels;
+
+ if(channel > 2) {
+ av_log(avctx, AV_LOG_ERROR, "Only 1 or 2 channels supported");
+ return -1;
+ }
+
+ coeff1l = ea_adpcm_table[(*src >> 4) & 0x0F];
+ coeff2l = ea_adpcm_table[((*src >> 4) & 0x0F) + 4];
+ shift_left = (*src & 0x0F) + 8;
+ src++;
+
+ if(st) {
+ coeff1r = ea_adpcm_table[(*src >> 4) & 0x0F];
+ coeff2r = ea_adpcm_table[((*src >> 4) & 0x0F) + 4];
+ shift_right = (*src & 0x0F) + 8;
+ src++;
+ }
+
+ for (count1 = 0; count1 < 14 ; count1++) {
+ next_left_sample = ((((*src >> 4) & 0x0F) << 0x1C) >> shift_left);
+ next_left_sample = (next_left_sample +
+ (c->mxa_current_left_sample * coeff1l) +
+ (c->mxa_previous_left_sample * coeff2l) + 0x80) >> 8;
+ c->mxa_previous_left_sample = c->mxa_current_left_sample;
+ c->mxa_current_left_sample = av_clip_int16(next_left_sample);
+ *samples++ = (unsigned short)c->mxa_current_left_sample;
+
+ next_left_sample = (((*src & 0x0F) << 0x1C) >> shift_left);
+ next_left_sample = (next_left_sample +
+ (c->mxa_current_left_sample * coeff1l) +
+ (c->mxa_previous_left_sample * coeff2l) + 0x80) >> 8;
+ c->mxa_previous_left_sample = c->mxa_current_left_sample;
+ c->mxa_current_left_sample = av_clip_int16(next_left_sample);
+
+ if(st) {
+ src++;
+ next_right_sample = ((((*src >> 4) & 0x0F) << 0x1C) >>
shift_right);
+ next_right_sample = (next_right_sample +
+ (c->mxa_current_right_sample * coeff1r) +
+ (c->mxa_previous_right_sample * coeff2r) + 0x80) >> 8;
+ c->mxa_previous_right_sample = c->mxa_current_right_sample;
+ c->mxa_current_right_sample = av_clip_int16(next_right_sample);
+ *samples++ = (unsigned short)c->mxa_current_right_sample;
+
+ *samples++ = (unsigned short)c->mxa_current_left_sample;
+
+ next_right_sample = (((*src & 0x0F) << 0x1C) >> shift_right);
+ next_right_sample = (next_right_sample +
+ (c->mxa_current_right_sample * coeff1r) +
+ (c->mxa_previous_right_sample * coeff2r) + 0x80) >> 8;
+ c->mxa_previous_right_sample = c->mxa_current_right_sample;
+ c->mxa_current_right_sample = av_clip_int16(next_right_sample);
+ *samples++ = (unsigned short)c->mxa_current_right_sample;
+ }
+ else {
+ *samples++ = (unsigned short)c->mxa_current_left_sample;
+ }
+ src++;
+ }
+ break;
case CODEC_ID_ADPCM_EA_R1:
case CODEC_ID_ADPCM_EA_R2:
case CODEC_ID_ADPCM_EA_R3: {
@@ -1613,6 +1686,7 @@
ADPCM_DECODER(CODEC_ID_ADPCM_4XM, adpcm_4xm);
ADPCM_DECODER(CODEC_ID_ADPCM_CT, adpcm_ct);
ADPCM_DECODER(CODEC_ID_ADPCM_EA, adpcm_ea);
+ADPCM_DECODER(CODEC_ID_ADPCM_EA_MAXIS_XA, adpcm_ea_maxis_xa);
ADPCM_DECODER(CODEC_ID_ADPCM_EA_R1, adpcm_ea_r1);
ADPCM_DECODER(CODEC_ID_ADPCM_EA_R2, adpcm_ea_r2);
ADPCM_DECODER(CODEC_ID_ADPCM_EA_R3, adpcm_ea_r3);
--- ../../ffmpeg/libavcodec/allcodecs.c 2008-03-31 12:15:57.000000000 +0200
+++ libavcodec/allcodecs.c 2008-04-07 11:32:38.000000000 +0200
@@ -243,6 +243,7 @@
REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx);
REGISTER_DECODER (ADPCM_CT, adpcm_ct);
REGISTER_DECODER (ADPCM_EA, adpcm_ea);
+ REGISTER_DECODER (ADPCM_EA_MAXIS_XA, adpcm_ea_maxis_xa);
REGISTER_DECODER (ADPCM_EA_R1, adpcm_ea_r1);
REGISTER_DECODER (ADPCM_EA_R2, adpcm_ea_r2);
REGISTER_DECODER (ADPCM_EA_R3, adpcm_ea_r3);
--- ../../ffmpeg/libavformat/allformats.c 2008-03-31 13:10:18.000000000
+0200
+++ libavformat/allformats.c 2008-04-03 21:44:16.000000000 +0200
@@ -168,6 +168,7 @@
REGISTER_DEMUXER (WSAUD, wsaud);
REGISTER_DEMUXER (WSVQA, wsvqa);
REGISTER_DEMUXER (WV, wv);
+ REGISTER_DEMUXER (XA, xa);
REGISTER_MUXDEMUX (YUV4MPEGPIPE, yuv4mpegpipe);
/* external libraries */
--- ../../ffmpeg/libavcodec/avcodec.h 2008-03-31 12:15:57.000000000 +0200
+++ libavcodec/avcodec.h 2008-04-07 11:30:30.000000000 +0200
@@ -230,6 +230,7 @@
CODEC_ID_ADPCM_IMA_EA_SEAD,
CODEC_ID_ADPCM_IMA_EA_EACS,
CODEC_ID_ADPCM_EA_XAS,
+ CODEC_ID_ADPCM_EA_MAXIS_XA,
/* AMR */
CODEC_ID_AMR_NB= 0x12000,
--- ../../ffmpeg/libavformat/Makefile 2008-03-31 13:10:18.000000000 +0200
+++ libavformat/Makefile 2008-04-03 14:02:06.000000000 +0200
@@ -178,6 +178,7 @@
OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood.o
OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood.o
OBJS-$(CONFIG_WV_DEMUXER) += wv.o
+OBJS-$(CONFIG_XA_DEMUXER) += xa.o
OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg.o
OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpeg.o
/*
* Maxis XA (.xa) File Demuxer
* Copyright (c) 2008 The ffmpeg Project
*
* 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 xa.c
* Maxis XA Audio Demuxer
* by Robert Marston ([EMAIL PROTECTED])
* for more information on the XA audio format visit
* http://wiki.multimedia.cx/index.php?title=Maxis_XA
*/
#include "avformat.h"
#define XA00_TAG MKTAG('X', 'A', 0, 0)
#define XAI0_TAG MKTAG('X', 'A', 'I', 0)
#define XAJ0_TAG MKTAG('X', 'A', 'J', 0)
typedef struct MaxisXADemuxContext {
uint32_t xaId;
uint32_t outSize;
int tag;
int channels;
uint32_t sampleRate;
uint32_t avgByteRate;
int align;
int bits;
int audio_stream_index;
int64_t audio_frame_counter;
} MaxisXADemuxContext;
static int xa_probe(AVProbeData *p)
{
switch(AV_RL32(&p->buf[0])) {
case XA00_TAG:
case XAI0_TAG:
case XAJ0_TAG:
return AVPROBE_SCORE_MAX;
}
return 0;
}
static int xa_extract_header_info(AVFormatContext *s)
{
MaxisXADemuxContext *xa = s->priv_data;
ByteIOContext *pb = s->pb;
xa->xaId = get_le32(pb);
xa->outSize = get_le32(pb);
xa->tag = get_le16(pb);
xa->channels = get_le16(pb);
xa->sampleRate = get_le32(pb);
xa->avgByteRate = get_le32(pb);
xa->align = get_le16(pb);
xa->bits = get_le16(pb);
return 1;
}
static int xa_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
MaxisXADemuxContext *xa = s->priv_data;
AVStream *st;
/* Extract Header Information from xa file */
if (!xa_extract_header_info(s))
return AVERROR(EIO);
/*Set up the XA Audio Decoder*/
st = av_new_stream(s, 0);
if (!st)
return AVERROR(ENOMEM);
av_set_pts_info(st, 33, 1, xa->sampleRate);
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_ADPCM_EA_MAXIS_XA;
st->codec->codec_tag = xa->tag;
st->codec->channels = xa->channels;
st->codec->sample_rate = xa->sampleRate;
st->codec->bits_per_sample = xa->bits;
st->codec->bit_rate = xa->avgByteRate * 8;
st->codec->block_align = xa->align;
xa->audio_stream_index = st->index;
xa->audio_frame_counter = 0;
return 0;
}
static int xa_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
MaxisXADemuxContext *xa = s->priv_data;
ByteIOContext *pb = s->pb;
int ret;
unsigned int packet_size;
packet_size = 15*xa->channels;/* 1 byte header and 14 byte samples * number channels per block */
ret = av_get_packet(pb, pkt, packet_size);
if (ret != packet_size) {
av_log(s, AV_LOG_WARNING, "Size mismatch");
return AVERROR(EIO);
}
else {
pkt->stream_index = xa->audio_stream_index;
pkt->pts = 90000;
pkt->pts *= xa->audio_frame_counter;
pkt->pts /= xa->sampleRate;
xa->audio_frame_counter += 2/xa->channels;
}
return 0;
}
AVInputFormat xa_demuxer = {
"xa",
"Maxis XA Audio Format",
sizeof(MaxisXADemuxContext),
xa_probe,
xa_read_header,
xa_read_packet,
};
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc