Mercurial > mplayer.hg
annotate libmpcodecs/ad_dk3adpcm.c @ 32972:fbaae7fe1a13
Fix several issues with Translate().
1. The "Unsafe!" comment has been removed, because the strings passed
to the function are strcpy'd.
2. The needless memsets (one of which with wrong size) have been removed
in favor of a sufficiently simple initialization of trbuf.
3. The array indices are unsigned now, and the manual optimization of
having strlen() outside the for loop has been removed in favor of
optimization performed by the compiler.
4. There is a check now to prevent an out-of-bounds array access.
author | ib |
---|---|
date | Tue, 08 Mar 2011 20:56:51 +0000 |
parents | b40d593a463f |
children | a93891202051 |
rev | line source |
---|---|
5408 | 1 /* |
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
2 * DK3 ADPCM decoder |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
3 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
4 * "This format number was used by Duck Corp. but not officially |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
5 * registered with Microsoft" |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
6 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
7 * This file is responsible for decoding audio data encoded with |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
8 * Duck Corp's DK3 ADPCM algorithm. Details about the data format |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
9 * can be found here: |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
10 * http://www.pcisys.net/~melanson/codecs/ |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
11 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
12 * Copyright (c) 2002 Mike Melanson |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
13 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
14 * This file is part of MPlayer. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
15 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
16 * MPlayer is free software; you can redistribute it and/or modify |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
17 * it under the terms of the GNU General Public License as published by |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
18 * the Free Software Foundation; either version 2 of the License, or |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
19 * (at your option) any later version. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
20 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
21 * MPlayer is distributed in the hope that it will be useful, |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
24 * GNU General Public License for more details. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
25 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
26 * You should have received a copy of the GNU General Public License along |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
27 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
28 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
29 */ |
5408 | 30 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
31 #include <stdio.h> |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
32 #include <stdlib.h> |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
33 #include <unistd.h> |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
34 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
35 #include "config.h" |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
36 #include "libavutil/intreadwrite.h" |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
37 #include "ad_internal.h" |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
38 |
30504
cc27da5d7286
Mark all ad_info_t/vd_info_t structure declarations as const.
diego
parents:
30421
diff
changeset
|
39 static const ad_info_t info = |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
40 { |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
41 "Duck Corp. DK3 ADPCM decoder", |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
42 "dk3adpcm", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
43 "Nick Kurshev", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
44 "Mike Melanson", |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
45 "" |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
46 }; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
47 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
48 LIBAD_EXTERN(dk3adpcm) |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
49 |
5408 | 50 #define DK3_ADPCM_PREAMBLE_SIZE 16 |
51 | |
52 // useful macros | |
53 // clamp a number between 0 and 88 | |
54 #define CLAMP_0_TO_88(x) if (x < 0) x = 0; else if (x > 88) x = 88; | |
55 // clamp a number within a signed 16-bit range | |
56 #define CLAMP_S16(x) if (x < -32768) x = -32768; \ | |
57 else if (x > 32767) x = 32767; | |
58 // clamp a number above 16 | |
59 #define CLAMP_ABOVE_16(x) if (x < 16) x = 16; | |
60 // sign extend a 16-bit value | |
61 #define SE_16BIT(x) if (x & 0x8000) x -= 0x10000; | |
62 // sign extend a 4-bit value | |
63 #define SE_4BIT(x) if (x & 0x8) x -= 0x10; | |
64 | |
65 // pertinent tables | |
66 static int adpcm_step[89] = | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
67 { |
5408 | 68 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, |
69 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, | |
70 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, | |
71 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, | |
72 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, | |
73 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, | |
74 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, | |
75 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | |
76 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 | |
77 }; | |
78 | |
79 static int adpcm_index[16] = | |
80 { | |
81 -1, -1, -1, -1, 2, 4, 6, 8, | |
82 -1, -1, -1, -1, 2, 4, 6, 8 | |
83 }; | |
84 | |
85 static int preinit(sh_audio_t *sh_audio) | |
86 { | |
87 sh_audio->audio_out_minsize = sh_audio->wf->nBlockAlign * 6; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
88 sh_audio->ds->ss_div = |
5408 | 89 (sh_audio->wf->nBlockAlign - DK3_ADPCM_PREAMBLE_SIZE) * 8 / 3; |
5458 | 90 sh_audio->audio_in_minsize= |
5408 | 91 sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign; |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
92 return 1; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
93 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
94 |
5408 | 95 static int init(sh_audio_t *sh_audio) |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
96 { |
5408 | 97 sh_audio->channels = sh_audio->wf->nChannels; |
98 sh_audio->samplerate = sh_audio->wf->nSamplesPerSec; | |
99 sh_audio->i_bps = | |
100 (sh_audio->ds->ss_mul * sh_audio->samplerate) / sh_audio->ds->ss_div; | |
13427
9d0b052c4f74
setting samplesize to 2 in decoders where neccessary.
reimar
parents:
7191
diff
changeset
|
101 sh_audio->samplesize=2; |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
102 return 1; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
103 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
104 |
5408 | 105 static void uninit(sh_audio_t *sh_audio) |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
106 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
107 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
108 |
5481 | 109 static int control(sh_audio_t *sh_audio,int cmd,void* arg, ...) |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
110 { |
5481 | 111 if(cmd==ADCTRL_SKIP_FRAME){ |
112 demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,sh_audio->ds->ss_mul); | |
113 return CONTROL_TRUE; | |
114 } | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
115 return CONTROL_UNKNOWN; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
116 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
117 |
5408 | 118 #define DK3_GET_NEXT_NIBBLE() \ |
119 if (decode_top_nibble_next) \ | |
120 { \ | |
121 nibble = (last_byte >> 4) & 0x0F; \ | |
122 decode_top_nibble_next = 0; \ | |
123 } \ | |
124 else \ | |
125 { \ | |
126 last_byte = input[in_ptr++]; \ | |
127 nibble = last_byte & 0x0F; \ | |
128 decode_top_nibble_next = 1; \ | |
129 } | |
130 | |
131 // note: This decoder assumes the format 0x62 data always comes in | |
132 // stereo flavor | |
133 static int dk3_adpcm_decode_block(unsigned short *output, unsigned char *input, | |
134 int block_size) | |
135 { | |
136 int sum_pred; | |
137 int diff_pred; | |
138 int sum_index; | |
139 int diff_index; | |
140 int diff_channel; | |
141 int in_ptr = 0x10; | |
142 int out_ptr = 0; | |
143 | |
144 unsigned char last_byte = 0; | |
145 unsigned char nibble; | |
146 int decode_top_nibble_next = 0; | |
147 | |
148 // ADPCM work variables | |
149 int sign; | |
150 int delta; | |
151 int step; | |
152 int diff; | |
153 | |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
154 sum_pred = AV_RL16(&input[10]); |
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
155 diff_pred = AV_RL16(&input[12]); |
5408 | 156 SE_16BIT(sum_pred); |
157 SE_16BIT(diff_pred); | |
158 diff_channel = diff_pred; | |
159 sum_index = input[14]; | |
160 diff_index = input[15]; | |
161 | |
16965
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
162 while (in_ptr < block_size - !decode_top_nibble_next) |
5408 | 163 // while (in_ptr < 2048) |
164 { | |
165 // process the first predictor of the sum channel | |
166 DK3_GET_NEXT_NIBBLE(); | |
167 | |
168 step = adpcm_step[sum_index]; | |
169 | |
170 sign = nibble & 8; | |
171 delta = nibble & 7; | |
172 | |
173 diff = step >> 3; | |
174 if (delta & 4) diff += step; | |
175 if (delta & 2) diff += step >> 1; | |
176 if (delta & 1) diff += step >> 2; | |
177 | |
178 if (sign) | |
179 sum_pred -= diff; | |
180 else | |
181 sum_pred += diff; | |
182 | |
183 CLAMP_S16(sum_pred); | |
184 | |
185 sum_index += adpcm_index[nibble]; | |
186 CLAMP_0_TO_88(sum_index); | |
187 | |
188 // process the diff channel predictor | |
189 DK3_GET_NEXT_NIBBLE(); | |
190 | |
191 step = adpcm_step[diff_index]; | |
192 | |
193 sign = nibble & 8; | |
194 delta = nibble & 7; | |
195 | |
196 diff = step >> 3; | |
197 if (delta & 4) diff += step; | |
198 if (delta & 2) diff += step >> 1; | |
199 if (delta & 1) diff += step >> 2; | |
200 | |
201 if (sign) | |
202 diff_pred -= diff; | |
203 else | |
204 diff_pred += diff; | |
205 | |
206 CLAMP_S16(diff_pred); | |
207 | |
208 diff_index += adpcm_index[nibble]; | |
209 CLAMP_0_TO_88(diff_index); | |
210 | |
211 // output the first pair of stereo PCM samples | |
212 diff_channel = (diff_channel + diff_pred) / 2; | |
213 output[out_ptr++] = sum_pred + diff_channel; | |
214 output[out_ptr++] = sum_pred - diff_channel; | |
215 | |
216 // process the second predictor of the sum channel | |
217 DK3_GET_NEXT_NIBBLE(); | |
218 | |
219 step = adpcm_step[sum_index]; | |
220 | |
221 sign = nibble & 8; | |
222 delta = nibble & 7; | |
223 | |
224 diff = step >> 3; | |
225 if (delta & 4) diff += step; | |
226 if (delta & 2) diff += step >> 1; | |
227 if (delta & 1) diff += step >> 2; | |
228 | |
229 if (sign) | |
230 sum_pred -= diff; | |
231 else | |
232 sum_pred += diff; | |
233 | |
234 CLAMP_S16(sum_pred); | |
235 | |
236 sum_index += adpcm_index[nibble]; | |
237 CLAMP_0_TO_88(sum_index); | |
238 | |
239 // output the second pair of stereo PCM samples | |
240 output[out_ptr++] = sum_pred + diff_channel; | |
241 output[out_ptr++] = sum_pred - diff_channel; | |
242 } | |
243 | |
244 return out_ptr; | |
245 } | |
246 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
247 static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen) |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
248 { |
5408 | 249 if (demux_read_data(sh_audio->ds, sh_audio->a_in_buffer, |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
250 sh_audio->ds->ss_mul) != |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
251 sh_audio->ds->ss_mul) |
5408 | 252 return -1; /* EOF */ |
253 | |
16965
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
254 if (maxlen < 2 * 4 * sh_audio->wf->nBlockAlign * 2 / 3) { |
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
255 mp_msg(MSGT_DECAUDIO, MSGL_V, "dk3adpcm: maxlen too small in decode_audio\n"); |
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
256 return -1; |
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
257 } |
5408 | 258 return 2 * dk3_adpcm_decode_block( |
259 (unsigned short*)buf, sh_audio->a_in_buffer, | |
16965
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
260 sh_audio->ds->ss_mul); |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
261 } |