libavcodec/ws-snd1.c
Go to the documentation of this file.
00001 /*
00002  * Westwood SNDx codecs
00003  * Copyright (c) 2005 Konstantin Shishkov
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include <stdint.h>
00023 #include "libavutil/intreadwrite.h"
00024 #include "avcodec.h"
00025 #include "internal.h"
00026 
00036 static const int8_t ws_adpcm_4bit[] = {
00037     -9, -8, -6, -5, -4, -3, -2, -1,
00038      0,  1,  2,  3,  4,  5,  6,  8
00039 };
00040 
00041 typedef struct WSSndContext {
00042     AVFrame frame;
00043 } WSSndContext;
00044 
00045 static av_cold int ws_snd_decode_init(AVCodecContext *avctx)
00046 {
00047     WSSndContext *s = avctx->priv_data;
00048 
00049     if (avctx->channels != 1) {
00050         av_log_ask_for_sample(avctx, "unsupported number of channels\n");
00051         return AVERROR(EINVAL);
00052     }
00053 
00054     avctx->sample_fmt = AV_SAMPLE_FMT_U8;
00055 
00056     avcodec_get_frame_defaults(&s->frame);
00057     avctx->coded_frame = &s->frame;
00058 
00059     return 0;
00060 }
00061 
00062 static int ws_snd_decode_frame(AVCodecContext *avctx, void *data,
00063                                int *got_frame_ptr, AVPacket *avpkt)
00064 {
00065     WSSndContext *s = avctx->priv_data;
00066     const uint8_t *buf = avpkt->data;
00067     int buf_size       = avpkt->size;
00068 
00069     int in_size, out_size, ret;
00070     int sample = 128;
00071     uint8_t *samples;
00072     uint8_t *samples_end;
00073 
00074     if (!buf_size)
00075         return 0;
00076 
00077     if (buf_size < 4) {
00078         av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
00079         return AVERROR(EINVAL);
00080     }
00081 
00082     out_size = AV_RL16(&buf[0]);
00083     in_size  = AV_RL16(&buf[2]);
00084     buf += 4;
00085 
00086     if (in_size > buf_size) {
00087         av_log(avctx, AV_LOG_ERROR, "Frame data is larger than input buffer\n");
00088         return -1;
00089     }
00090 
00091     /* get output buffer */
00092     s->frame.nb_samples = out_size;
00093     if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) {
00094         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00095         return ret;
00096     }
00097     samples     = s->frame.data[0];
00098     samples_end = samples + out_size;
00099 
00100     if (in_size == out_size) {
00101         memcpy(samples, buf, out_size);
00102         *got_frame_ptr   = 1;
00103         *(AVFrame *)data = s->frame;
00104         return buf_size;
00105     }
00106 
00107     while (samples < samples_end && buf - avpkt->data < buf_size) {
00108         int code, smp, size;
00109         uint8_t count;
00110         code  = *buf >> 6;
00111         count = *buf & 0x3F;
00112         buf++;
00113 
00114         /* make sure we don't write past the output buffer */
00115         switch (code) {
00116         case 0:  smp = 4*(count+1);                    break;
00117         case 1:  smp = 2*(count+1);                    break;
00118         case 2:  smp = (count & 0x20) ? 1 : count + 1; break;
00119         default: smp = count + 1;                      break;
00120         }
00121         if (samples_end - samples < smp)
00122             break;
00123 
00124         /* make sure we don't read past the input buffer */
00125         size = ((code == 2 && (count & 0x20)) || code == 3) ? 0 : count + 1;
00126         if ((buf - avpkt->data) + size > buf_size)
00127             break;
00128 
00129         switch (code) {
00130         case 0: /* ADPCM 2-bit */
00131             for (count++; count > 0; count--) {
00132                 code = *buf++;
00133                 sample += ( code       & 0x3) - 2;
00134                 sample = av_clip_uint8(sample);
00135                 *samples++ = sample;
00136                 sample += ((code >> 2) & 0x3) - 2;
00137                 sample = av_clip_uint8(sample);
00138                 *samples++ = sample;
00139                 sample += ((code >> 4) & 0x3) - 2;
00140                 sample = av_clip_uint8(sample);
00141                 *samples++ = sample;
00142                 sample +=  (code >> 6)        - 2;
00143                 sample = av_clip_uint8(sample);
00144                 *samples++ = sample;
00145             }
00146             break;
00147         case 1: /* ADPCM 4-bit */
00148             for (count++; count > 0; count--) {
00149                 code = *buf++;
00150                 sample += ws_adpcm_4bit[code & 0xF];
00151                 sample = av_clip_uint8(sample);
00152                 *samples++ = sample;
00153                 sample += ws_adpcm_4bit[code >> 4];
00154                 sample = av_clip_uint8(sample);
00155                 *samples++ = sample;
00156             }
00157             break;
00158         case 2: /* no compression */
00159             if (count & 0x20) { /* big delta */
00160                 int8_t t;
00161                 t = count;
00162                 t <<= 3;
00163                 sample += t >> 3;
00164                 sample = av_clip_uint8(sample);
00165                 *samples++ = sample;
00166             } else { /* copy */
00167                 memcpy(samples, buf, smp);
00168                 samples += smp;
00169                 buf     += smp;
00170                 sample = buf[-1];
00171             }
00172             break;
00173         default: /* run */
00174             memset(samples, sample, smp);
00175             samples += smp;
00176         }
00177     }
00178 
00179     s->frame.nb_samples = samples - s->frame.data[0];
00180     *got_frame_ptr   = 1;
00181     *(AVFrame *)data = s->frame;
00182 
00183     return buf_size;
00184 }
00185 
00186 AVCodec ff_ws_snd1_decoder = {
00187     .name           = "ws_snd1",
00188     .type           = AVMEDIA_TYPE_AUDIO,
00189     .id             = CODEC_ID_WESTWOOD_SND1,
00190     .priv_data_size = sizeof(WSSndContext),
00191     .init           = ws_snd_decode_init,
00192     .decode         = ws_snd_decode_frame,
00193     .capabilities   = CODEC_CAP_DR1,
00194     .long_name = NULL_IF_CONFIG_SMALL("Westwood Audio (SND1)"),
00195 };