LCOV - code coverage report
Current view: top level - libavcodec - vmdaudio.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 54 88 61.4 %
Date: 2017-12-15 11:05:35 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /*
       2             :  * Sierra VMD audio decoder
       3             :  * Copyright (c) 2004 The FFmpeg Project
       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             :  * Sierra VMD audio decoder
      25             :  * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
      26             :  * for more information on the Sierra VMD format, visit:
      27             :  *   http://www.pcisys.net/~melanson/codecs/
      28             :  *
      29             :  * The audio decoder, expects each encoded data
      30             :  * chunk to be prepended with the appropriate 16-byte frame information
      31             :  * record from the VMD file. It does not require the 0x330-byte VMD file
      32             :  * header, but it does need the audio setup parameters passed in through
      33             :  * normal libavcodec API means.
      34             :  */
      35             : 
      36             : #include <string.h>
      37             : 
      38             : #include "libavutil/avassert.h"
      39             : #include "libavutil/channel_layout.h"
      40             : #include "libavutil/common.h"
      41             : #include "libavutil/intreadwrite.h"
      42             : 
      43             : #include "avcodec.h"
      44             : #include "internal.h"
      45             : 
      46             : #define BLOCK_TYPE_AUDIO    1
      47             : #define BLOCK_TYPE_INITIAL  2
      48             : #define BLOCK_TYPE_SILENCE  3
      49             : 
      50             : typedef struct VmdAudioContext {
      51             :     int out_bps;
      52             :     int chunk_size;
      53             : } VmdAudioContext;
      54             : 
      55             : static const uint16_t vmdaudio_table[128] = {
      56             :     0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
      57             :     0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
      58             :     0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
      59             :     0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
      60             :     0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
      61             :     0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
      62             :     0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
      63             :     0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
      64             :     0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
      65             :     0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
      66             :     0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
      67             :     0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
      68             :     0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
      69             : };
      70             : 
      71           4 : static av_cold int vmdaudio_decode_init(AVCodecContext *avctx)
      72             : {
      73           4 :     VmdAudioContext *s = avctx->priv_data;
      74             : 
      75           4 :     if (avctx->channels < 1 || avctx->channels > 2) {
      76           0 :         av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
      77           0 :         return AVERROR(EINVAL);
      78             :     }
      79           4 :     if (avctx->block_align < 1 || avctx->block_align % avctx->channels) {
      80           0 :         av_log(avctx, AV_LOG_ERROR, "invalid block align\n");
      81           0 :         return AVERROR(EINVAL);
      82             :     }
      83             : 
      84           4 :     avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO :
      85             :                                                    AV_CH_LAYOUT_STEREO;
      86             : 
      87           4 :     if (avctx->bits_per_coded_sample == 16)
      88           0 :         avctx->sample_fmt = AV_SAMPLE_FMT_S16;
      89             :     else
      90           4 :         avctx->sample_fmt = AV_SAMPLE_FMT_U8;
      91           4 :     s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt);
      92             : 
      93           4 :     s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2);
      94             : 
      95           4 :     av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, "
      96             :            "block align = %d, sample rate = %d\n",
      97             :            avctx->channels, avctx->bits_per_coded_sample, avctx->block_align,
      98             :            avctx->sample_rate);
      99             : 
     100           4 :     return 0;
     101             : }
     102             : 
     103           0 : static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size,
     104             :                              int channels)
     105             : {
     106             :     int ch;
     107           0 :     const uint8_t *buf_end = buf + buf_size;
     108             :     int predictor[2];
     109           0 :     int st = channels - 1;
     110             : 
     111             :     /* decode initial raw sample */
     112           0 :     for (ch = 0; ch < channels; ch++) {
     113           0 :         predictor[ch] = (int16_t)AV_RL16(buf);
     114           0 :         buf += 2;
     115           0 :         *out++ = predictor[ch];
     116             :     }
     117             : 
     118             :     /* decode DPCM samples */
     119           0 :     ch = 0;
     120           0 :     while (buf < buf_end) {
     121           0 :         uint8_t b = *buf++;
     122           0 :         if (b & 0x80)
     123           0 :             predictor[ch] -= vmdaudio_table[b & 0x7F];
     124             :         else
     125           0 :             predictor[ch] += vmdaudio_table[b];
     126           0 :         predictor[ch] = av_clip_int16(predictor[ch]);
     127           0 :         *out++ = predictor[ch];
     128           0 :         ch ^= st;
     129             :     }
     130           0 : }
     131             : 
     132         215 : static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data,
     133             :                                  int *got_frame_ptr, AVPacket *avpkt)
     134             : {
     135         215 :     AVFrame *frame     = data;
     136         215 :     const uint8_t *buf = avpkt->data;
     137             :     const uint8_t *buf_end;
     138         215 :     int buf_size = avpkt->size;
     139         215 :     VmdAudioContext *s = avctx->priv_data;
     140             :     int block_type, silent_chunks, audio_chunks;
     141             :     int ret;
     142             :     uint8_t *output_samples_u8;
     143             :     int16_t *output_samples_s16;
     144             : 
     145         215 :     if (buf_size < 16) {
     146           0 :         av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n");
     147           0 :         *got_frame_ptr = 0;
     148           0 :         return buf_size;
     149             :     }
     150             : 
     151         215 :     block_type = buf[6];
     152         215 :     if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) {
     153           0 :         av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type);
     154           0 :         return AVERROR(EINVAL);
     155             :     }
     156         215 :     buf      += 16;
     157         215 :     buf_size -= 16;
     158             : 
     159             :     /* get number of silent chunks */
     160         215 :     silent_chunks = 0;
     161         215 :     if (block_type == BLOCK_TYPE_INITIAL) {
     162             :         uint32_t flags;
     163           1 :         if (buf_size < 4) {
     164           0 :             av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
     165           0 :             return AVERROR(EINVAL);
     166             :         }
     167           1 :         flags         = AV_RB32(buf);
     168           1 :         silent_chunks = av_popcount(flags);
     169           1 :         buf      += 4;
     170           1 :         buf_size -= 4;
     171         214 :     } else if (block_type == BLOCK_TYPE_SILENCE) {
     172          29 :         silent_chunks = 1;
     173          29 :         buf_size = 0; // should already be zero but set it just to be sure
     174             :     }
     175             : 
     176             :     /* ensure output buffer is large enough */
     177         215 :     audio_chunks = buf_size / s->chunk_size;
     178             : 
     179             :     /* drop incomplete chunks */
     180         215 :     buf_size     = audio_chunks * s->chunk_size;
     181             : 
     182             :     /* get output buffer */
     183         430 :     frame->nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) /
     184         215 :                         avctx->channels;
     185         215 :     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
     186           0 :         return ret;
     187         215 :     output_samples_u8  =            frame->data[0];
     188         215 :     output_samples_s16 = (int16_t *)frame->data[0];
     189             : 
     190             :     /* decode silent chunks */
     191         215 :     if (silent_chunks > 0) {
     192          29 :         int silent_size = avctx->block_align * silent_chunks;
     193          29 :         av_assert0(avctx->block_align * silent_chunks <= frame->nb_samples * avctx->channels);
     194             : 
     195          29 :         if (s->out_bps == 2) {
     196           0 :             memset(output_samples_s16, 0x00, silent_size * 2);
     197           0 :             output_samples_s16 += silent_size;
     198             :         } else {
     199          29 :             memset(output_samples_u8,  0x80, silent_size);
     200          29 :             output_samples_u8 += silent_size;
     201             :         }
     202             :     }
     203             : 
     204             :     /* decode audio chunks */
     205         215 :     if (audio_chunks > 0) {
     206         186 :         buf_end = buf + buf_size;
     207         186 :         av_assert0((buf_size & (avctx->channels > 1)) == 0);
     208         585 :         while (buf_end - buf >= s->chunk_size) {
     209         213 :             if (s->out_bps == 2) {
     210           0 :                 decode_audio_s16(output_samples_s16, buf, s->chunk_size,
     211             :                                  avctx->channels);
     212           0 :                 output_samples_s16 += avctx->block_align;
     213             :             } else {
     214         213 :                 memcpy(output_samples_u8, buf, s->chunk_size);
     215         213 :                 output_samples_u8  += avctx->block_align;
     216             :             }
     217         213 :             buf += s->chunk_size;
     218             :         }
     219             :     }
     220             : 
     221         215 :     *got_frame_ptr = 1;
     222             : 
     223         215 :     return avpkt->size;
     224             : }
     225             : 
     226             : AVCodec ff_vmdaudio_decoder = {
     227             :     .name           = "vmdaudio",
     228             :     .long_name      = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
     229             :     .type           = AVMEDIA_TYPE_AUDIO,
     230             :     .id             = AV_CODEC_ID_VMDAUDIO,
     231             :     .priv_data_size = sizeof(VmdAudioContext),
     232             :     .init           = vmdaudio_decode_init,
     233             :     .decode         = vmdaudio_decode_frame,
     234             :     .capabilities   = AV_CODEC_CAP_DR1,
     235             : };

Generated by: LCOV version 1.13