00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdint.h>
00023 #include "libavutil/intreadwrite.h"
00024 #include "avcodec.h"
00025
00035 static const int8_t ws_adpcm_2bit[] = { -2, -1, 0, 1};
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 static av_cold int ws_snd_decode_init(AVCodecContext * avctx)
00041 {
00042
00043
00044 if (avctx->channels != 1) {
00045 av_log_ask_for_sample(avctx, "unsupported number of channels\n");
00046 return AVERROR(EINVAL);
00047 }
00048
00049 avctx->sample_fmt = AV_SAMPLE_FMT_U8;
00050 return 0;
00051 }
00052
00053 static int ws_snd_decode_frame(AVCodecContext *avctx,
00054 void *data, int *data_size,
00055 AVPacket *avpkt)
00056 {
00057 const uint8_t *buf = avpkt->data;
00058 int buf_size = avpkt->size;
00059
00060
00061 int in_size, out_size;
00062 int sample = 128;
00063 int i;
00064 uint8_t *samples = data;
00065
00066 if (!buf_size)
00067 return 0;
00068
00069 if (buf_size < 4) {
00070 av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
00071 return AVERROR(EINVAL);
00072 }
00073
00074 out_size = AV_RL16(&buf[0]);
00075 in_size = AV_RL16(&buf[2]);
00076 buf += 4;
00077
00078 if (out_size > *data_size) {
00079 av_log(avctx, AV_LOG_ERROR, "Frame is too large to fit in buffer\n");
00080 return -1;
00081 }
00082 if (in_size > buf_size) {
00083 av_log(avctx, AV_LOG_ERROR, "Frame data is larger than input buffer\n");
00084 return -1;
00085 }
00086
00087 if (in_size == out_size) {
00088 for (i = 0; i < out_size; i++)
00089 *samples++ = *buf++;
00090 *data_size = out_size;
00091 return buf_size;
00092 }
00093
00094 while (out_size > 0 && buf - avpkt->data < buf_size) {
00095 int code, smp, size;
00096 uint8_t count;
00097 code = (*buf) >> 6;
00098 count = (*buf) & 0x3F;
00099 buf++;
00100
00101
00102 switch (code) {
00103 case 0: smp = 4*(count+1); break;
00104 case 1: smp = 2*(count+1); break;
00105 case 2: smp = (count & 0x20) ? 1 : count + 1; break;
00106 default: smp = count + 1; break;
00107 }
00108 if (out_size < smp) {
00109 out_size = 0;
00110 break;
00111 }
00112
00113
00114 size = ((code == 2 && (count & 0x20)) || code == 3) ? 0 : count + 1;
00115 if ((buf - avpkt->data) + size > buf_size)
00116 break;
00117
00118 switch(code) {
00119 case 0:
00120 for (count++; count > 0; count--) {
00121 code = *buf++;
00122 sample += ws_adpcm_2bit[code & 0x3];
00123 sample = av_clip_uint8(sample);
00124 *samples++ = sample;
00125 sample += ws_adpcm_2bit[(code >> 2) & 0x3];
00126 sample = av_clip_uint8(sample);
00127 *samples++ = sample;
00128 sample += ws_adpcm_2bit[(code >> 4) & 0x3];
00129 sample = av_clip_uint8(sample);
00130 *samples++ = sample;
00131 sample += ws_adpcm_2bit[(code >> 6) & 0x3];
00132 sample = av_clip_uint8(sample);
00133 *samples++ = sample;
00134 out_size -= 4;
00135 }
00136 break;
00137 case 1:
00138 for (count++; count > 0; count--) {
00139 code = *buf++;
00140 sample += ws_adpcm_4bit[code & 0xF];
00141 sample = av_clip_uint8(sample);
00142 *samples++ = sample;
00143 sample += ws_adpcm_4bit[code >> 4];
00144 sample = av_clip_uint8(sample);
00145 *samples++ = sample;
00146 out_size -= 2;
00147 }
00148 break;
00149 case 2:
00150 if (count & 0x20) {
00151 int8_t t;
00152 t = count;
00153 t <<= 3;
00154 sample += t >> 3;
00155 sample = av_clip_uint8(sample);
00156 *samples++ = sample;
00157 out_size--;
00158 } else {
00159 for (count++; count > 0; count--) {
00160 *samples++ = *buf++;
00161 out_size--;
00162 }
00163 sample = buf[-1];
00164 }
00165 break;
00166 default:
00167 for(count++; count > 0; count--) {
00168 *samples++ = sample;
00169 out_size--;
00170 }
00171 }
00172 }
00173
00174 *data_size = samples - (uint8_t *)data;
00175
00176 return buf_size;
00177 }
00178
00179 AVCodec ff_ws_snd1_decoder = {
00180 "ws_snd1",
00181 AVMEDIA_TYPE_AUDIO,
00182 CODEC_ID_WESTWOOD_SND1,
00183 0,
00184 ws_snd_decode_init,
00185 NULL,
00186 NULL,
00187 ws_snd_decode_frame,
00188 .long_name = NULL_IF_CONFIG_SMALL("Westwood Audio (SND1)"),
00189 };