dpcm: Fix invalid writes
[libav.git] / libavcodec / dpcm.c
CommitLineData
3ef8be2b
MM
1/*
2 * Assorted DPCM codecs
406792e7 3 * Copyright (c) 2003 The ffmpeg Project
3ef8be2b 4 *
2912e87a 5 * This file is part of Libav.
b78e7197 6 *
2912e87a 7 * Libav is free software; you can redistribute it and/or
3ef8be2b
MM
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
b78e7197 10 * version 2.1 of the License, or (at your option) any later version.
3ef8be2b 11 *
2912e87a 12 * Libav is distributed in the hope that it will be useful,
3ef8be2b
MM
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
2912e87a 18 * License along with Libav; if not, write to the Free Software
5509bffa 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3ef8be2b
MM
20 */
21
22/**
33edd31f 23 * @file
3ef8be2b
MM
24 * Assorted DPCM (differential pulse code modulation) audio codecs
25 * by Mike Melanson (melanson@pcisys.net)
9937e686 26 * Xan DPCM decoder by Mario Brito (mbrito@student.dei.uc.pt)
3ef8be2b
MM
27 * for more information on the specific data formats, visit:
28 * http://www.pcisys.net/~melanson/codecs/simpleaudio.html
d08d7142 29 * SOL DPCMs implemented by Konstantin Shishkov
9937e686
MM
30 *
31 * Note about using the Xan DPCM decoder: Xan DPCM is used in AVI files
32 * found in the Wing Commander IV computer game. These AVI files contain
33 * WAVEFORMAT headers which report the audio format as 0x01: raw PCM.
34 * Clearly incorrect. To detect Xan DPCM, you will probably have to
35 * special-case your AVI demuxer to use Xan DPCM if the file uses 'Xxan'
36 * (Xan video) for its video codec. Alternately, such AVI files also contain
37 * the fourcc 'Axan' in the 'auds' chunk of the AVI header.
3ef8be2b
MM
38 */
39
6a5d31ac 40#include "libavutil/intreadwrite.h"
3ef8be2b 41#include "avcodec.h"
1de8401c 42#include "bytestream.h"
3ef8be2b
MM
43
44typedef struct DPCMContext {
0eea2129 45 AVFrame frame;
3ef8be2b 46 int channels;
f47f7efd 47 int16_t roq_square_array[256];
04b24cf9 48 int sample[2]; ///< previous sample (for SOL_DPCM)
0354fb7e 49 const int8_t *sol_table; ///< delta table for SOL_DPCM
3ef8be2b
MM
50} DPCMContext;
51
0354fb7e 52static const int16_t interplay_delta_table[] = {
3ef8be2b
MM
53 0, 1, 2, 3, 4, 5, 6, 7,
54 8, 9, 10, 11, 12, 13, 14, 15,
55 16, 17, 18, 19, 20, 21, 22, 23,
56 24, 25, 26, 27, 28, 29, 30, 31,
57 32, 33, 34, 35, 36, 37, 38, 39,
58 40, 41, 42, 43, 47, 51, 56, 61,
59 66, 72, 79, 86, 94, 102, 112, 122,
60 133, 145, 158, 173, 189, 206, 225, 245,
61 267, 292, 318, 348, 379, 414, 452, 493,
62 538, 587, 640, 699, 763, 832, 908, 991,
63 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993,
64 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008,
65 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059,
66 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206,
67 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589,
68 -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1,
69 1, 1, 5481, 10503, 15105, 19322, 23186, 26728,
70 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298,
71 -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597,
72 -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772,
73 -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373,
74 -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180,
75 -1081, -991, -908, -832, -763, -699, -640, -587,
76 -538, -493, -452, -414, -379, -348, -318, -292,
77 -267, -245, -225, -206, -189, -173, -158, -145,
78 -133, -122, -112, -102, -94, -86, -79, -72,
79 -66, -61, -56, -51, -47, -43, -42, -41,
80 -40, -39, -38, -37, -36, -35, -34, -33,
81 -32, -31, -30, -29, -28, -27, -26, -25,
82 -24, -23, -22, -21, -20, -19, -18, -17,
83 -16, -15, -14, -13, -12, -11, -10, -9,
84 -8, -7, -6, -5, -4, -3, -2, -1
85
86};
87
0354fb7e 88static const int8_t sol_table_old[16] = {
4bad464e
JR
89 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15,
90 -0x15, -0xF, -0xA, -0x6, -0x3, -0x2, -0x1, 0x0
91};
d08d7142 92
0354fb7e 93static const int8_t sol_table_new[16] = {
4bad464e
JR
94 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15,
95 0x0, -0x1, -0x2, -0x3, -0x6, -0xA, -0xF, -0x15
96};
115329f1 97
0354fb7e 98static const int16_t sol_table_16[128] = {
d08d7142
MM
99 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
100 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
101 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
102 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
103 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
104 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
105 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
106 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
107 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
108 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
109 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
110 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
111 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
112};
113
114
98a6fff9 115static av_cold int dpcm_decode_init(AVCodecContext *avctx)
3ef8be2b
MM
116{
117 DPCMContext *s = avctx->priv_data;
118 int i;
3ef8be2b 119
8d77d12a
JR
120 if (avctx->channels < 1 || avctx->channels > 2) {
121 av_log(avctx, AV_LOG_INFO, "invalid number of channels\n");
122 return AVERROR(EINVAL);
123 }
124
3ef8be2b 125 s->channels = avctx->channels;
d08d7142 126 s->sample[0] = s->sample[1] = 0;
3ef8be2b
MM
127
128 switch(avctx->codec->id) {
129
130 case CODEC_ID_ROQ_DPCM:
131 /* initialize square table */
132 for (i = 0; i < 128; i++) {
f47f7efd 133 int16_t square = i * i;
4bad464e 134 s->roq_square_array[i ] = square;
3ef8be2b
MM
135 s->roq_square_array[i + 128] = -square;
136 }
137 break;
138
d08d7142
MM
139 case CODEC_ID_SOL_DPCM:
140 switch(avctx->codec_tag){
141 case 1:
4bad464e 142 s->sol_table = sol_table_old;
d08d7142
MM
143 s->sample[0] = s->sample[1] = 0x80;
144 break;
145 case 2:
4bad464e 146 s->sol_table = sol_table_new;
d08d7142
MM
147 s->sample[0] = s->sample[1] = 0x80;
148 break;
149 case 3:
d08d7142
MM
150 break;
151 default:
152 av_log(avctx, AV_LOG_ERROR, "Unknown SOL subcodec\n");
153 return -1;
154 }
155 break;
115329f1 156
3ef8be2b
MM
157 default:
158 break;
159 }
160
04b24cf9
JR
161 if (avctx->codec->id == CODEC_ID_SOL_DPCM && avctx->codec_tag != 3)
162 avctx->sample_fmt = AV_SAMPLE_FMT_U8;
163 else
164 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
165
0eea2129
JR
166 avcodec_get_frame_defaults(&s->frame);
167 avctx->coded_frame = &s->frame;
168
3ef8be2b
MM
169 return 0;
170}
171
4bad464e 172
0eea2129
JR
173static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
174 int *got_frame_ptr, AVPacket *avpkt)
3ef8be2b 175{
7a00bbad
TB
176 const uint8_t *buf = avpkt->data;
177 int buf_size = avpkt->size;
1de8401c 178 const uint8_t *buf_end = buf + buf_size;
3ef8be2b 179 DPCMContext *s = avctx->priv_data;
0eea2129 180 int out = 0, ret;
3ef8be2b 181 int predictor[2];
b09c7eef 182 int ch = 0;
3db8db40 183 int stereo = s->channels - 1;
0eea2129 184 int16_t *output_samples;
3ef8be2b 185
76db17dc
JR
186 /* calculate output size */
187 switch(avctx->codec->id) {
188 case CODEC_ID_ROQ_DPCM:
189 out = buf_size - 8;
190 break;
191 case CODEC_ID_INTERPLAY_DPCM:
192 out = buf_size - 6 - s->channels;
193 break;
194 case CODEC_ID_XAN_DPCM:
195 out = buf_size - 2 * s->channels;
196 break;
197 case CODEC_ID_SOL_DPCM:
198 if (avctx->codec_tag != 3)
199 out = buf_size * 2;
200 else
201 out = buf_size;
202 break;
203 }
8dbc6d03 204 if (out <= 0) {
08bd22a6
JR
205 av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
206 return AVERROR(EINVAL);
207 }
0eea2129
JR
208
209 /* get output buffer */
210 s->frame.nb_samples = out / s->channels;
211 if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
212 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
213 return ret;
76db17dc 214 }
0eea2129 215 output_samples = (int16_t *)s->frame.data[0];
a2085a7e 216
3ef8be2b
MM
217 switch(avctx->codec->id) {
218
219 case CODEC_ID_ROQ_DPCM:
1de8401c
JR
220 buf += 6;
221
3db8db40 222 if (stereo) {
1de8401c
JR
223 predictor[1] = (int16_t)(bytestream_get_byte(&buf) << 8);
224 predictor[0] = (int16_t)(bytestream_get_byte(&buf) << 8);
3db8db40 225 } else {
1de8401c 226 predictor[0] = (int16_t)bytestream_get_le16(&buf);
3ef8be2b 227 }
3ef8be2b
MM
228
229 /* decode the samples */
1de8401c
JR
230 while (buf < buf_end) {
231 predictor[ch] += s->roq_square_array[*buf++];
4bad464e 232 predictor[ch] = av_clip_int16(predictor[ch]);
76db17dc 233 *output_samples++ = predictor[ch];
3ef8be2b
MM
234
235 /* toggle channel */
3db8db40 236 ch ^= stereo;
3ef8be2b
MM
237 }
238 break;
239
240 case CODEC_ID_INTERPLAY_DPCM:
1de8401c
JR
241 buf += 6; /* skip over the stream mask and stream length */
242
243 for (ch = 0; ch < s->channels; ch++) {
244 predictor[ch] = (int16_t)bytestream_get_le16(&buf);
245 *output_samples++ = predictor[ch];
3ef8be2b
MM
246 }
247
1de8401c
JR
248 ch = 0;
249 while (buf < buf_end) {
250 predictor[ch] += interplay_delta_table[*buf++];
4bad464e 251 predictor[ch] = av_clip_int16(predictor[ch]);
76db17dc 252 *output_samples++ = predictor[ch];
3ef8be2b
MM
253
254 /* toggle channel */
3db8db40 255 ch ^= stereo;
3ef8be2b 256 }
3ef8be2b 257 break;
9937e686
MM
258
259 case CODEC_ID_XAN_DPCM:
fc6faee0
JR
260 {
261 int shift[2] = { 4, 4 };
9937e686 262
1de8401c
JR
263 for (ch = 0; ch < s->channels; ch++)
264 predictor[ch] = (int16_t)bytestream_get_le16(&buf);
265
266 ch = 0;
267 while (buf < buf_end) {
268 uint8_t n = *buf++;
fc6faee0 269 int16_t diff = (n & 0xFC) << 8;
989bb7bd 270 if ((n & 0x03) == 3)
b09c7eef 271 shift[ch]++;
9937e686 272 else
989bb7bd 273 shift[ch] -= (2 * (n & 3));
9937e686 274 /* saturate the shifter to a lower limit of 0 */
b09c7eef
JR
275 if (shift[ch] < 0)
276 shift[ch] = 0;
9937e686 277
b09c7eef
JR
278 diff >>= shift[ch];
279 predictor[ch] += diff;
9937e686 280
b09c7eef 281 predictor[ch] = av_clip_int16(predictor[ch]);
76db17dc 282 *output_samples++ = predictor[ch];
9937e686
MM
283
284 /* toggle channel */
3db8db40 285 ch ^= stereo;
9937e686
MM
286 }
287 break;
fc6faee0 288 }
d08d7142 289 case CODEC_ID_SOL_DPCM:
d08d7142 290 if (avctx->codec_tag != 3) {
529a25d6 291 uint8_t *output_samples_u8 = s->frame.data[0];
1de8401c
JR
292 while (buf < buf_end) {
293 uint8_t n = *buf++;
04b24cf9
JR
294
295 s->sample[0] += s->sol_table[n >> 4];
296 s->sample[0] = av_clip_uint8(s->sample[0]);
297 *output_samples_u8++ = s->sample[0];
298
299 s->sample[stereo] += s->sol_table[n & 0x0F];
300 s->sample[stereo] = av_clip_uint8(s->sample[stereo]);
301 *output_samples_u8++ = s->sample[stereo];
d08d7142
MM
302 }
303 } else {
1de8401c
JR
304 while (buf < buf_end) {
305 uint8_t n = *buf++;
5a54d510
JR
306 if (n & 0x80) s->sample[ch] -= sol_table_16[n & 0x7F];
307 else s->sample[ch] += sol_table_16[n & 0x7F];
b09c7eef 308 s->sample[ch] = av_clip_int16(s->sample[ch]);
76db17dc 309 *output_samples++ = s->sample[ch];
d08d7142 310 /* toggle channel */
3db8db40 311 ch ^= stereo;
d08d7142
MM
312 }
313 }
314 break;
3ef8be2b
MM
315 }
316
0eea2129
JR
317 *got_frame_ptr = 1;
318 *(AVFrame *)data = s->frame;
319
3ef8be2b
MM
320 return buf_size;
321}
322
86714887
DB
323#define DPCM_DECODER(id_, name_, long_name_) \
324AVCodec ff_ ## name_ ## _decoder = { \
325 .name = #name_, \
326 .type = AVMEDIA_TYPE_AUDIO, \
327 .id = id_, \
328 .priv_data_size = sizeof(DPCMContext), \
329 .init = dpcm_decode_init, \
330 .decode = dpcm_decode_frame, \
0eea2129 331 .capabilities = CODEC_CAP_DR1, \
86714887 332 .long_name = NULL_IF_CONFIG_SMALL(long_name_), \
44adbebe 333}
3ef8be2b 334
12dd57fd 335DPCM_DECODER(CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay");
4bad464e
JR
336DPCM_DECODER(CODEC_ID_ROQ_DPCM, roq_dpcm, "DPCM id RoQ");
337DPCM_DECODER(CODEC_ID_SOL_DPCM, sol_dpcm, "DPCM Sol");
338DPCM_DECODER(CODEC_ID_XAN_DPCM, xan_dpcm, "DPCM Xan");