libavcodec/adxdec.c
Go to the documentation of this file.
00001 /*
00002  * ADX ADPCM codecs
00003  * Copyright (c) 2001,2003 BERO
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * Libav is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "libavutil/intreadwrite.h"
00023 #include "avcodec.h"
00024 #include "internal.h"
00025 #include "adx.h"
00026 #include "get_bits.h"
00027 
00037 static av_cold int adx_decode_init(AVCodecContext *avctx)
00038 {
00039     ADXContext *c = avctx->priv_data;
00040     int ret, header_size;
00041 
00042     if (avctx->extradata_size >= 24) {
00043         if ((ret = avpriv_adx_decode_header(avctx, avctx->extradata,
00044                                             avctx->extradata_size, &header_size,
00045                                             c->coeff)) < 0) {
00046             av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n");
00047             return AVERROR_INVALIDDATA;
00048         }
00049         c->channels      = avctx->channels;
00050         c->header_parsed = 1;
00051     }
00052 
00053     avctx->sample_fmt = AV_SAMPLE_FMT_S16;
00054 
00055     avcodec_get_frame_defaults(&c->frame);
00056     avctx->coded_frame = &c->frame;
00057 
00058     return 0;
00059 }
00060 
00068 static int adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch)
00069 {
00070     ADXChannelState *prev = &c->prev[ch];
00071     GetBitContext gb;
00072     int scale = AV_RB16(in);
00073     int i;
00074     int s0, s1, s2, d;
00075 
00076     /* check if this is an EOF packet */
00077     if (scale & 0x8000)
00078         return -1;
00079 
00080     init_get_bits(&gb, in + 2, (BLOCK_SIZE - 2) * 8);
00081     s1 = prev->s1;
00082     s2 = prev->s2;
00083     for (i = 0; i < BLOCK_SAMPLES; i++) {
00084         d  = get_sbits(&gb, 4);
00085         s0 = ((d << COEFF_BITS) * scale + c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS;
00086         s2 = s1;
00087         s1 = av_clip_int16(s0);
00088         *out = s1;
00089         out += c->channels;
00090     }
00091     prev->s1 = s1;
00092     prev->s2 = s2;
00093 
00094     return 0;
00095 }
00096 
00097 static int adx_decode_frame(AVCodecContext *avctx, void *data,
00098                             int *got_frame_ptr, AVPacket *avpkt)
00099 {
00100     int buf_size        = avpkt->size;
00101     ADXContext *c       = avctx->priv_data;
00102     int16_t *samples;
00103     const uint8_t *buf  = avpkt->data;
00104     int num_blocks, ch, ret;
00105 
00106     if (c->eof) {
00107         *got_frame_ptr = 0;
00108         return buf_size;
00109     }
00110 
00111     if (!c->header_parsed && buf_size >= 2 && AV_RB16(buf) == 0x8000) {
00112         int header_size;
00113         if ((ret = avpriv_adx_decode_header(avctx, buf, buf_size, &header_size,
00114                                             c->coeff)) < 0) {
00115             av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n");
00116             return AVERROR_INVALIDDATA;
00117         }
00118         c->channels      = avctx->channels;
00119         c->header_parsed = 1;
00120         if (buf_size < header_size)
00121             return AVERROR_INVALIDDATA;
00122         buf      += header_size;
00123         buf_size -= header_size;
00124     }
00125     if (!c->header_parsed)
00126         return AVERROR_INVALIDDATA;
00127 
00128     /* calculate number of blocks in the packet */
00129     num_blocks = buf_size / (BLOCK_SIZE * c->channels);
00130 
00131     /* if the packet is not an even multiple of BLOCK_SIZE, check for an EOF
00132        packet */
00133     if (!num_blocks || buf_size % (BLOCK_SIZE * avctx->channels)) {
00134         if (buf_size >= 4 && (AV_RB16(buf) & 0x8000)) {
00135             c->eof = 1;
00136             *got_frame_ptr = 0;
00137             return avpkt->size;
00138         }
00139         return AVERROR_INVALIDDATA;
00140     }
00141 
00142     /* get output buffer */
00143     c->frame.nb_samples = num_blocks * BLOCK_SAMPLES;
00144     if ((ret = ff_get_buffer(avctx, &c->frame)) < 0) {
00145         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00146         return ret;
00147     }
00148     samples = (int16_t *)c->frame.data[0];
00149 
00150     while (num_blocks--) {
00151         for (ch = 0; ch < c->channels; ch++) {
00152             if (adx_decode(c, samples + ch, buf, ch)) {
00153                 c->eof = 1;
00154                 buf = avpkt->data + avpkt->size;
00155                 break;
00156             }
00157             buf_size -= BLOCK_SIZE;
00158             buf      += BLOCK_SIZE;
00159         }
00160         samples += BLOCK_SAMPLES * c->channels;
00161     }
00162 
00163     *got_frame_ptr   = 1;
00164     *(AVFrame *)data = c->frame;
00165 
00166     return buf - avpkt->data;
00167 }
00168 
00169 static void adx_decode_flush(AVCodecContext *avctx)
00170 {
00171     ADXContext *c = avctx->priv_data;
00172     memset(c->prev, 0, sizeof(c->prev));
00173     c->eof = 0;
00174 }
00175 
00176 AVCodec ff_adpcm_adx_decoder = {
00177     .name           = "adpcm_adx",
00178     .type           = AVMEDIA_TYPE_AUDIO,
00179     .id             = CODEC_ID_ADPCM_ADX,
00180     .priv_data_size = sizeof(ADXContext),
00181     .init           = adx_decode_init,
00182     .decode         = adx_decode_frame,
00183     .flush          = adx_decode_flush,
00184     .capabilities   = CODEC_CAP_DR1,
00185     .long_name      = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"),
00186 };