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

Reply via email to