• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavcodec/8svx.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Jaikrishnan Menon
00003  * Copyright (C) 2011 Stefano Sabatini
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00038 #include "avcodec.h"
00039 
00041 typedef struct EightSvxContext {
00042     const int8_t *table;
00043 
00044     /* buffer used to store the whole audio decoded/interleaved chunk,
00045      * which is sent with the first packet */
00046     uint8_t *samples;
00047     int64_t samples_size;
00048     int samples_idx;
00049 } EightSvxContext;
00050 
00051 static const int8_t fibonacci[16]   = { -34,  -21, -13,  -8, -5, -3, -2, -1, 0, 1, 2, 3, 5, 8,  13, 21 };
00052 static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64 };
00053 
00054 #define MAX_FRAME_SIZE 2048
00055 
00063 static void interleave_stereo(uint8_t *dst, const uint8_t *src, int size)
00064 {
00065     uint8_t *dst_end = dst + size;
00066     size = size>>1;
00067 
00068     while (dst < dst_end) {
00069         *dst++ = *src;
00070         *dst++ = *(src+size);
00071         src++;
00072     }
00073 }
00074 
00083 static int delta_decode(int8_t *dst, const uint8_t *src, int src_size,
00084                         int8_t val, const int8_t *table)
00085 {
00086     int n = src_size;
00087     int8_t *dst0 = dst;
00088 
00089     while (n--) {
00090         uint8_t d = *src++;
00091         val = av_clip(val + table[d & 0x0f], -127, 128);
00092         *dst++ = val;
00093         val = av_clip(val + table[d >> 4]  , -127, 128);
00094         *dst++ = val;
00095     }
00096 
00097     return dst-dst0;
00098 }
00099 
00100 static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
00101                                  AVPacket *avpkt)
00102 {
00103     EightSvxContext *esc = avctx->priv_data;
00104     int out_data_size, n;
00105     uint8_t *src, *dst;
00106 
00107     /* decode and interleave the first packet */
00108     if (!esc->samples && avpkt) {
00109         uint8_t *deinterleaved_samples;
00110 
00111         esc->samples_size = avctx->codec->id == CODEC_ID_8SVX_RAW ?
00112             avpkt->size : avctx->channels + (avpkt->size-avctx->channels) * 2;
00113         if (!(esc->samples = av_malloc(esc->samples_size)))
00114             return AVERROR(ENOMEM);
00115 
00116         /* decompress */
00117         if (avctx->codec->id == CODEC_ID_8SVX_FIB || avctx->codec->id == CODEC_ID_8SVX_EXP) {
00118             const uint8_t *buf = avpkt->data;
00119             int buf_size = avpkt->size;
00120             int n = esc->samples_size;
00121 
00122             if (!(deinterleaved_samples = av_mallocz(n)))
00123                 return AVERROR(ENOMEM);
00124 
00125             /* the uncompressed starting value is contained in the first byte */
00126             if (avctx->channels == 2) {
00127                 delta_decode(deinterleaved_samples      , buf+1, buf_size/2-1, buf[0], esc->table);
00128                 buf += buf_size/2;
00129                 delta_decode(deinterleaved_samples+n/2-1, buf+1, buf_size/2-1, buf[0], esc->table);
00130             } else
00131                 delta_decode(deinterleaved_samples      , buf+1, buf_size-1  , buf[0], esc->table);
00132         } else {
00133             deinterleaved_samples = avpkt->data;
00134         }
00135 
00136         if (avctx->channels == 2)
00137             interleave_stereo(esc->samples, deinterleaved_samples, esc->samples_size);
00138         else
00139             memcpy(esc->samples, deinterleaved_samples, esc->samples_size);
00140     }
00141 
00142     /* return single packed with fixed size */
00143     out_data_size = FFMIN(MAX_FRAME_SIZE, esc->samples_size - esc->samples_idx);
00144     if (*data_size < out_data_size) {
00145         av_log(avctx, AV_LOG_ERROR, "Provided buffer with size %d is too small.\n", *data_size);
00146         return AVERROR(EINVAL);
00147     }
00148 
00149     *data_size = out_data_size;
00150     dst = data;
00151     src = esc->samples + esc->samples_idx;
00152     for (n = out_data_size; n > 0; n--)
00153         *dst++ = *src++ + 128;
00154     esc->samples_idx += *data_size;
00155 
00156     return avctx->codec->id == CODEC_ID_8SVX_FIB || avctx->codec->id == CODEC_ID_8SVX_EXP ?
00157         (avctx->frame_number == 0)*2 + out_data_size / 2 :
00158         out_data_size;
00159 }
00160 
00161 static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
00162 {
00163     EightSvxContext *esc = avctx->priv_data;
00164 
00165     if (avctx->channels > 2) {
00166         av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n");
00167         return AVERROR_INVALIDDATA;
00168     }
00169 
00170     switch (avctx->codec->id) {
00171     case CODEC_ID_8SVX_FIB: esc->table = fibonacci;    break;
00172     case CODEC_ID_8SVX_EXP: esc->table = exponential;  break;
00173     case CODEC_ID_8SVX_RAW: esc->table = NULL;         break;
00174     default:
00175         av_log(avctx, AV_LOG_ERROR, "Invalid codec id %d.\n", avctx->codec->id);
00176         return AVERROR_INVALIDDATA;
00177     }
00178     avctx->sample_fmt = AV_SAMPLE_FMT_U8;
00179 
00180     return 0;
00181 }
00182 
00183 static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
00184 {
00185     EightSvxContext *esc = avctx->priv_data;
00186 
00187     av_freep(&esc->samples);
00188     esc->samples_size = 0;
00189     esc->samples_idx = 0;
00190 
00191     return 0;
00192 }
00193 
00194 AVCodec ff_eightsvx_fib_decoder = {
00195   .name           = "8svx_fib",
00196   .type           = AVMEDIA_TYPE_AUDIO,
00197   .id             = CODEC_ID_8SVX_FIB,
00198   .priv_data_size = sizeof (EightSvxContext),
00199   .init           = eightsvx_decode_init,
00200   .decode         = eightsvx_decode_frame,
00201   .close          = eightsvx_decode_close,
00202   .long_name      = NULL_IF_CONFIG_SMALL("8SVX fibonacci"),
00203 };
00204 
00205 AVCodec ff_eightsvx_exp_decoder = {
00206   .name           = "8svx_exp",
00207   .type           = AVMEDIA_TYPE_AUDIO,
00208   .id             = CODEC_ID_8SVX_EXP,
00209   .priv_data_size = sizeof (EightSvxContext),
00210   .init           = eightsvx_decode_init,
00211   .decode         = eightsvx_decode_frame,
00212   .close          = eightsvx_decode_close,
00213   .long_name      = NULL_IF_CONFIG_SMALL("8SVX exponential"),
00214 };
00215 
00216 AVCodec ff_eightsvx_raw_decoder = {
00217   .name           = "8svx_raw",
00218   .type           = AVMEDIA_TYPE_AUDIO,
00219   .id             = CODEC_ID_8SVX_RAW,
00220   .priv_data_size = sizeof(EightSvxContext),
00221   .init           = eightsvx_decode_init,
00222   .decode         = eightsvx_decode_frame,
00223   .close          = eightsvx_decode_close,
00224   .long_name      = NULL_IF_CONFIG_SMALL("8SVX rawaudio"),
00225 };

Generated on Fri Feb 22 2013 07:24:25 for FFmpeg by  doxygen 1.7.1