"Fossies" - the Fresh Open Source Software Archive

Member "ffmpeg-3.4.2/libavcodec/8svx.c" (31 Dec 2017, 6911 Bytes) of package /linux/misc/ffmpeg-3.4.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "8svx.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) 2008 Jaikrishnan Menon
    3  * Copyright (C) 2011 Stefano Sabatini
    4  *
    5  * This file is part of FFmpeg.
    6  *
    7  * FFmpeg is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU Lesser General Public
    9  * License as published by the Free Software Foundation; either
   10  * version 2.1 of the License, or (at your option) any later version.
   11  *
   12  * FFmpeg is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15  * Lesser General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU Lesser General Public
   18  * License along with FFmpeg; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   20  */
   21 
   22 /**
   23  * @file
   24  * 8svx audio decoder
   25  * @author Jaikrishnan Menon
   26  *
   27  * supports: fibonacci delta encoding
   28  *         : exponential encoding
   29  *
   30  * For more information about the 8SVX format:
   31  * http://netghost.narod.ru/gff/vendspec/iff/iff.txt
   32  * http://sox.sourceforge.net/AudioFormats-11.html
   33  * http://aminet.net/package/mus/misc/wavepak
   34  * http://amigan.1emu.net/reg/8SVX.txt
   35  *
   36  * Samples can be found here:
   37  * http://aminet.net/mods/smpl/
   38  */
   39 
   40 #include "libavutil/avassert.h"
   41 #include "avcodec.h"
   42 #include "internal.h"
   43 #include "libavutil/common.h"
   44 
   45 /** decoder context */
   46 typedef struct EightSvxContext {
   47     uint8_t fib_acc[2];
   48     const int8_t *table;
   49 
   50     /* buffer used to store the whole first packet.
   51        data is only sent as one large packet */
   52     uint8_t *data[2];
   53     int data_size;
   54     int data_idx;
   55 } EightSvxContext;
   56 
   57 static const int8_t fibonacci[16]   = { -34,  -21, -13,  -8, -5, -3, -2, -1, 0, 1, 2, 3, 5, 8,  13, 21 };
   58 static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64 };
   59 
   60 #define MAX_FRAME_SIZE 2048
   61 
   62 /**
   63  * Delta decode the compressed values in src, and put the resulting
   64  * decoded samples in dst.
   65  *
   66  * @param[in,out] state starting value. it is saved for use in the next call.
   67  * @param table delta sequence table
   68  */
   69 static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
   70                          uint8_t *state, const int8_t *table)
   71 {
   72     uint8_t val = *state;
   73 
   74     while (src_size--) {
   75         uint8_t d = *src++;
   76         val = av_clip_uint8(val + table[d & 0xF]);
   77         *dst++ = val;
   78         val = av_clip_uint8(val + table[d >> 4]);
   79         *dst++ = val;
   80     }
   81 
   82     *state = val;
   83 }
   84 
   85 /** decode a frame */
   86 static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
   87                                  int *got_frame_ptr, AVPacket *avpkt)
   88 {
   89     EightSvxContext *esc = avctx->priv_data;
   90     AVFrame *frame       = data;
   91     int buf_size;
   92     int ch, ret;
   93     int hdr_size = 2;
   94 
   95     /* decode and interleave the first packet */
   96     if (!esc->data[0] && avpkt) {
   97         int chan_size = avpkt->size / avctx->channels - hdr_size;
   98 
   99         if (avpkt->size % avctx->channels) {
  100             av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n");
  101         }
  102         if (avpkt->size < (hdr_size + 1) * avctx->channels) {
  103             av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
  104             return AVERROR_INVALIDDATA;
  105         }
  106 
  107         esc->fib_acc[0] = avpkt->data[1] + 128;
  108         if (avctx->channels == 2)
  109             esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
  110 
  111         esc->data_idx  = 0;
  112         esc->data_size = chan_size;
  113         if (!(esc->data[0] = av_malloc(chan_size)))
  114             return AVERROR(ENOMEM);
  115         if (avctx->channels == 2) {
  116             if (!(esc->data[1] = av_malloc(chan_size))) {
  117                 av_freep(&esc->data[0]);
  118                 return AVERROR(ENOMEM);
  119             }
  120         }
  121         memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size);
  122         if (avctx->channels == 2)
  123             memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size);
  124     }
  125     if (!esc->data[0]) {
  126         av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n");
  127         return AVERROR_INVALIDDATA;
  128     }
  129 
  130     /* decode next piece of data from the buffer */
  131     buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx);
  132     if (buf_size <= 0) {
  133         *got_frame_ptr = 0;
  134         return avpkt->size;
  135     }
  136 
  137     /* get output buffer */
  138     frame->nb_samples = buf_size * 2;
  139     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
  140         return ret;
  141 
  142     for (ch = 0; ch < avctx->channels; ch++) {
  143         delta_decode(frame->data[ch], &esc->data[ch][esc->data_idx],
  144                      buf_size, &esc->fib_acc[ch], esc->table);
  145     }
  146 
  147     esc->data_idx += buf_size;
  148 
  149     *got_frame_ptr = 1;
  150 
  151     return ((avctx->frame_number == 0)*hdr_size + buf_size)*avctx->channels;
  152 }
  153 
  154 static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
  155 {
  156     EightSvxContext *esc = avctx->priv_data;
  157 
  158     if (avctx->channels < 1 || avctx->channels > 2) {
  159         av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n");
  160         return AVERROR_INVALIDDATA;
  161     }
  162 
  163     switch (avctx->codec->id) {
  164     case AV_CODEC_ID_8SVX_FIB: esc->table = fibonacci;    break;
  165     case AV_CODEC_ID_8SVX_EXP: esc->table = exponential;  break;
  166     default:
  167         av_log(avctx, AV_LOG_ERROR, "Invalid codec id %d.\n", avctx->codec->id);
  168         return AVERROR_INVALIDDATA;
  169     }
  170     avctx->sample_fmt = AV_SAMPLE_FMT_U8P;
  171 
  172     return 0;
  173 }
  174 
  175 static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
  176 {
  177     EightSvxContext *esc = avctx->priv_data;
  178 
  179     av_freep(&esc->data[0]);
  180     av_freep(&esc->data[1]);
  181     esc->data_size = 0;
  182     esc->data_idx = 0;
  183 
  184     return 0;
  185 }
  186 
  187 #if CONFIG_EIGHTSVX_FIB_DECODER
  188 AVCodec ff_eightsvx_fib_decoder = {
  189   .name           = "8svx_fib",
  190   .long_name      = NULL_IF_CONFIG_SMALL("8SVX fibonacci"),
  191   .type           = AVMEDIA_TYPE_AUDIO,
  192   .id             = AV_CODEC_ID_8SVX_FIB,
  193   .priv_data_size = sizeof (EightSvxContext),
  194   .init           = eightsvx_decode_init,
  195   .decode         = eightsvx_decode_frame,
  196   .close          = eightsvx_decode_close,
  197   .capabilities   = AV_CODEC_CAP_DR1,
  198   .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P,
  199                                                     AV_SAMPLE_FMT_NONE },
  200 };
  201 #endif
  202 #if CONFIG_EIGHTSVX_EXP_DECODER
  203 AVCodec ff_eightsvx_exp_decoder = {
  204   .name           = "8svx_exp",
  205   .long_name      = NULL_IF_CONFIG_SMALL("8SVX exponential"),
  206   .type           = AVMEDIA_TYPE_AUDIO,
  207   .id             = AV_CODEC_ID_8SVX_EXP,
  208   .priv_data_size = sizeof (EightSvxContext),
  209   .init           = eightsvx_decode_init,
  210   .decode         = eightsvx_decode_frame,
  211   .close          = eightsvx_decode_close,
  212   .capabilities   = AV_CODEC_CAP_DR1,
  213   .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P,
  214                                                     AV_SAMPLE_FMT_NONE },
  215 };
  216 #endif