LCOV - code coverage report
Current view: top level - libavcodec - ws-snd1.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 78 89 87.6 %
Date: 2017-12-10 21:22:29 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Westwood SNDx codecs
       3             :  * Copyright (c) 2005 Konstantin Shishkov
       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             : #include <stdint.h>
      23             : 
      24             : #include "libavutil/channel_layout.h"
      25             : #include "libavutil/common.h"
      26             : #include "libavutil/intreadwrite.h"
      27             : #include "avcodec.h"
      28             : #include "internal.h"
      29             : 
      30             : /**
      31             :  * @file
      32             :  * Westwood SNDx codecs
      33             :  *
      34             :  * Reference documents about VQA format and its audio codecs
      35             :  * can be found here:
      36             :  * http://www.multimedia.cx
      37             :  */
      38             : 
      39             : static const int8_t ws_adpcm_4bit[] = {
      40             :     -9, -8, -6, -5, -4, -3, -2, -1,
      41             :      0,  1,  2,  3,  4,  5,  6,  8
      42             : };
      43             : 
      44           2 : static av_cold int ws_snd_decode_init(AVCodecContext *avctx)
      45             : {
      46           2 :     avctx->channels       = 1;
      47           2 :     avctx->channel_layout = AV_CH_LAYOUT_MONO;
      48           2 :     avctx->sample_fmt     = AV_SAMPLE_FMT_U8;
      49             : 
      50           2 :     return 0;
      51             : }
      52             : 
      53          11 : static int ws_snd_decode_frame(AVCodecContext *avctx, void *data,
      54             :                                int *got_frame_ptr, AVPacket *avpkt)
      55             : {
      56          11 :     AVFrame *frame     = data;
      57          11 :     const uint8_t *buf = avpkt->data;
      58          11 :     int buf_size       = avpkt->size;
      59             : 
      60             :     int in_size, out_size, ret;
      61          11 :     int sample = 128;
      62             :     uint8_t *samples;
      63             :     uint8_t *samples_end;
      64             : 
      65          11 :     if (!buf_size)
      66           0 :         return 0;
      67             : 
      68          11 :     if (buf_size < 4) {
      69           0 :         av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
      70           0 :         return AVERROR(EINVAL);
      71             :     }
      72             : 
      73          11 :     out_size = AV_RL16(&buf[0]);
      74          11 :     in_size  = AV_RL16(&buf[2]);
      75          11 :     buf += 4;
      76             : 
      77          11 :     if (in_size > buf_size) {
      78           0 :         av_log(avctx, AV_LOG_ERROR, "Frame data is larger than input buffer\n");
      79           0 :         return AVERROR_INVALIDDATA;
      80             :     }
      81             : 
      82             :     /* get output buffer */
      83          11 :     frame->nb_samples = out_size;
      84          11 :     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
      85           0 :         return ret;
      86          11 :     samples     = frame->data[0];
      87          11 :     samples_end = samples + out_size;
      88             : 
      89          11 :     if (in_size == out_size) {
      90           0 :         memcpy(samples, buf, out_size);
      91           0 :         *got_frame_ptr = 1;
      92           0 :         return buf_size;
      93             :     }
      94             : 
      95        8551 :     while (samples < samples_end && buf - avpkt->data < buf_size) {
      96             :         int code, smp, size;
      97             :         uint8_t count;
      98        8529 :         code  = *buf >> 6;
      99        8529 :         count = *buf & 0x3F;
     100        8529 :         buf++;
     101             : 
     102             :         /* make sure we don't write past the output buffer */
     103        8529 :         switch (code) {
     104          21 :         case 0:  smp = 4 * (count + 1);                break;
     105        2919 :         case 1:  smp = 2 * (count + 1);                break;
     106        5585 :         case 2:  smp = (count & 0x20) ? 1 : count + 1; break;
     107           4 :         default: smp = count + 1;                      break;
     108             :         }
     109        8529 :         if (samples_end - samples < smp)
     110           0 :             break;
     111             : 
     112             :         /* make sure we don't read past the input buffer */
     113        8529 :         size = ((code == 2 && (count & 0x20)) || code == 3) ? 0 : count + 1;
     114        8529 :         if ((buf - avpkt->data) + size > buf_size)
     115           0 :             break;
     116             : 
     117        8529 :         switch (code) {
     118          21 :         case 0: /* ADPCM 2-bit */
     119          42 :             for (count++; count > 0; count--) {
     120          21 :                 code = *buf++;
     121          21 :                 sample += ( code       & 0x3) - 2;
     122          21 :                 sample = av_clip_uint8(sample);
     123          21 :                 *samples++ = sample;
     124          21 :                 sample += ((code >> 2) & 0x3) - 2;
     125          21 :                 sample = av_clip_uint8(sample);
     126          21 :                 *samples++ = sample;
     127          21 :                 sample += ((code >> 4) & 0x3) - 2;
     128          21 :                 sample = av_clip_uint8(sample);
     129          21 :                 *samples++ = sample;
     130          21 :                 sample +=  (code >> 6)        - 2;
     131          21 :                 sample = av_clip_uint8(sample);
     132          21 :                 *samples++ = sample;
     133             :             }
     134          21 :             break;
     135        2919 :         case 1: /* ADPCM 4-bit */
     136       20207 :             for (count++; count > 0; count--) {
     137       17288 :                 code = *buf++;
     138       17288 :                 sample += ws_adpcm_4bit[code & 0xF];
     139       17288 :                 sample = av_clip_uint8(sample);
     140       17288 :                 *samples++ = sample;
     141       17288 :                 sample += ws_adpcm_4bit[code >> 4];
     142       17288 :                 sample = av_clip_uint8(sample);
     143       17288 :                 *samples++ = sample;
     144             :             }
     145        2919 :             break;
     146        5585 :         case 2: /* no compression */
     147        5585 :             if (count & 0x20) { /* big delta */
     148             :                 int8_t t;
     149        5292 :                 t = count;
     150        5292 :                 t <<= 3;
     151        5292 :                 sample += t >> 3;
     152        5292 :                 sample = av_clip_uint8(sample);
     153        5292 :                 *samples++ = sample;
     154             :             } else { /* copy */
     155         293 :                 memcpy(samples, buf, smp);
     156         293 :                 samples += smp;
     157         293 :                 buf     += smp;
     158         293 :                 sample = buf[-1];
     159             :             }
     160        5585 :             break;
     161           4 :         default: /* run */
     162           4 :             memset(samples, sample, smp);
     163           4 :             samples += smp;
     164             :         }
     165             :     }
     166             : 
     167          11 :     frame->nb_samples = samples - frame->data[0];
     168          11 :     *got_frame_ptr    = 1;
     169             : 
     170          11 :     return buf_size;
     171             : }
     172             : 
     173             : AVCodec ff_ws_snd1_decoder = {
     174             :     .name           = "ws_snd1",
     175             :     .long_name      = NULL_IF_CONFIG_SMALL("Westwood Audio (SND1)"),
     176             :     .type           = AVMEDIA_TYPE_AUDIO,
     177             :     .id             = AV_CODEC_ID_WESTWOOD_SND1,
     178             :     .init           = ws_snd_decode_init,
     179             :     .decode         = ws_snd_decode_frame,
     180             :     .capabilities   = AV_CODEC_CAP_DR1,
     181             : };

Generated by: LCOV version 1.13