LCOV - code coverage report
Current view: top level - src/libavcodec - 8svx.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 50 69 72.5 %
Date: 2017-04-28 19:02:26 Functions: 4 4 100.0 %

          Line data    Source code
       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          40 : static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
      70             :                          uint8_t *state, const int8_t *table)
      71             : {
      72          40 :     uint8_t val = *state;
      73             : 
      74       80208 :     while (src_size--) {
      75       80128 :         uint8_t d = *src++;
      76       80128 :         val = av_clip_uint8(val + table[d & 0xF]);
      77       80128 :         *dst++ = val;
      78       80128 :         val = av_clip_uint8(val + table[d >> 4]);
      79       80128 :         *dst++ = val;
      80             :     }
      81             : 
      82          40 :     *state = val;
      83          40 : }
      84             : 
      85             : /** decode a frame */
      86          40 : static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
      87             :                                  int *got_frame_ptr, AVPacket *avpkt)
      88             : {
      89          40 :     EightSvxContext *esc = avctx->priv_data;
      90          40 :     AVFrame *frame       = data;
      91             :     int buf_size;
      92             :     int ch, ret;
      93          40 :     int hdr_size = 2;
      94             : 
      95             :     /* decode and interleave the first packet */
      96          40 :     if (!esc->data[0] && avpkt) {
      97           1 :         int chan_size = avpkt->size / avctx->channels - hdr_size;
      98             : 
      99           1 :         if (avpkt->size % avctx->channels) {
     100           0 :             av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n");
     101             :         }
     102           1 :         if (avpkt->size < (hdr_size + 1) * avctx->channels) {
     103           0 :             av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
     104           0 :             return AVERROR_INVALIDDATA;
     105             :         }
     106             : 
     107           1 :         esc->fib_acc[0] = avpkt->data[1] + 128;
     108           1 :         if (avctx->channels == 2)
     109           0 :             esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
     110             : 
     111           1 :         esc->data_idx  = 0;
     112           1 :         esc->data_size = chan_size;
     113           1 :         if (!(esc->data[0] = av_malloc(chan_size)))
     114           0 :             return AVERROR(ENOMEM);
     115           1 :         if (avctx->channels == 2) {
     116           0 :             if (!(esc->data[1] = av_malloc(chan_size))) {
     117           0 :                 av_freep(&esc->data[0]);
     118           0 :                 return AVERROR(ENOMEM);
     119             :             }
     120             :         }
     121           1 :         memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size);
     122           1 :         if (avctx->channels == 2)
     123           0 :             memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size);
     124             :     }
     125          40 :     if (!esc->data[0]) {
     126           0 :         av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n");
     127           0 :         return AVERROR_INVALIDDATA;
     128             :     }
     129             : 
     130             :     /* decode next piece of data from the buffer */
     131          40 :     buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx);
     132          40 :     if (buf_size <= 0) {
     133           0 :         *got_frame_ptr = 0;
     134           0 :         return avpkt->size;
     135             :     }
     136             : 
     137             :     /* get output buffer */
     138          40 :     frame->nb_samples = buf_size * 2;
     139          40 :     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
     140           0 :         return ret;
     141             : 
     142          80 :     for (ch = 0; ch < avctx->channels; ch++) {
     143          40 :         delta_decode(frame->data[ch], &esc->data[ch][esc->data_idx],
     144             :                      buf_size, &esc->fib_acc[ch], esc->table);
     145             :     }
     146             : 
     147          40 :     esc->data_idx += buf_size;
     148             : 
     149          40 :     *got_frame_ptr = 1;
     150             : 
     151          40 :     return ((avctx->frame_number == 0)*hdr_size + buf_size)*avctx->channels;
     152             : }
     153             : 
     154           2 : static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
     155             : {
     156           2 :     EightSvxContext *esc = avctx->priv_data;
     157             : 
     158           2 :     if (avctx->channels < 1 || avctx->channels > 2) {
     159           0 :         av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n");
     160           0 :         return AVERROR_INVALIDDATA;
     161             :     }
     162             : 
     163           2 :     switch (avctx->codec->id) {
     164           2 :     case AV_CODEC_ID_8SVX_FIB: esc->table = fibonacci;    break;
     165           0 :     case AV_CODEC_ID_8SVX_EXP: esc->table = exponential;  break;
     166             :     default:
     167           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid codec id %d.\n", avctx->codec->id);
     168           0 :         return AVERROR_INVALIDDATA;
     169             :     }
     170           2 :     avctx->sample_fmt = AV_SAMPLE_FMT_U8P;
     171             : 
     172           2 :     return 0;
     173             : }
     174             : 
     175           2 : static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
     176             : {
     177           2 :     EightSvxContext *esc = avctx->priv_data;
     178             : 
     179           2 :     av_freep(&esc->data[0]);
     180           2 :     av_freep(&esc->data[1]);
     181           2 :     esc->data_size = 0;
     182           2 :     esc->data_idx = 0;
     183             : 
     184           2 :     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

Generated by: LCOV version 1.13