Mercurial > mplayer.hg
annotate libmpcodecs/ad_dk3adpcm.c @ 36406:c918845d0d9a
mplayer: Fix a crash seeking with -chapter and -ass
When seeking to chapter on startup the mpctx->d_sub member
is not yet initialized. Do not access it in that case.
The commit r31293 that introduced that code explains that
it is for handling backward seeking correctly. So it should
not be needed on startup forward seek situation.
author | al |
---|---|
date | Fri, 08 Nov 2013 21:06:40 +0000 |
parents | a93891202051 |
children |
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" |
34174
a93891202051
Add missing mp_msg.h #includes, remove some unnecessary ones.
diego
parents:
31614
diff
changeset
|
36 #include "mp_msg.h" |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
37 #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
|
38 #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
|
39 |
30504
cc27da5d7286
Mark all ad_info_t/vd_info_t structure declarations as const.
diego
parents:
30421
diff
changeset
|
40 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
|
41 { |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
42 "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
|
43 "dk3adpcm", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
44 "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
|
45 "Mike Melanson", |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
46 "" |
5340
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 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
49 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
|
50 |
5408 | 51 #define DK3_ADPCM_PREAMBLE_SIZE 16 |
52 | |
53 // useful macros | |
54 // clamp a number between 0 and 88 | |
55 #define CLAMP_0_TO_88(x) if (x < 0) x = 0; else if (x > 88) x = 88; | |
56 // clamp a number within a signed 16-bit range | |
57 #define CLAMP_S16(x) if (x < -32768) x = -32768; \ | |
58 else if (x > 32767) x = 32767; | |
59 // clamp a number above 16 | |
60 #define CLAMP_ABOVE_16(x) if (x < 16) x = 16; | |
61 // sign extend a 16-bit value | |
62 #define SE_16BIT(x) if (x & 0x8000) x -= 0x10000; | |
63 // sign extend a 4-bit value | |
64 #define SE_4BIT(x) if (x & 0x8) x -= 0x10; | |
65 | |
66 // pertinent tables | |
67 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
|
68 { |
5408 | 69 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, |
70 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, | |
71 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, | |
72 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, | |
73 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, | |
74 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, | |
75 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, | |
76 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | |
77 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 | |
78 }; | |
79 | |
80 static int adpcm_index[16] = | |
81 { | |
82 -1, -1, -1, -1, 2, 4, 6, 8, | |
83 -1, -1, -1, -1, 2, 4, 6, 8 | |
84 }; | |
85 | |
86 static int preinit(sh_audio_t *sh_audio) | |
87 { | |
88 sh_audio->audio_out_minsize = sh_audio->wf->nBlockAlign * 6; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
89 sh_audio->ds->ss_div = |
5408 | 90 (sh_audio->wf->nBlockAlign - DK3_ADPCM_PREAMBLE_SIZE) * 8 / 3; |
5458 | 91 sh_audio->audio_in_minsize= |
5408 | 92 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
|
93 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
|
94 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
95 |
5408 | 96 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
|
97 { |
5408 | 98 sh_audio->channels = sh_audio->wf->nChannels; |
99 sh_audio->samplerate = sh_audio->wf->nSamplesPerSec; | |
100 sh_audio->i_bps = | |
101 (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
|
102 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
|
103 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
|
104 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
105 |
5408 | 106 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
|
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 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
109 |
5481 | 110 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
|
111 { |
5481 | 112 if(cmd==ADCTRL_SKIP_FRAME){ |
113 demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,sh_audio->ds->ss_mul); | |
114 return CONTROL_TRUE; | |
115 } | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
116 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
|
117 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
118 |
5408 | 119 #define DK3_GET_NEXT_NIBBLE() \ |
120 if (decode_top_nibble_next) \ | |
121 { \ | |
122 nibble = (last_byte >> 4) & 0x0F; \ | |
123 decode_top_nibble_next = 0; \ | |
124 } \ | |
125 else \ | |
126 { \ | |
127 last_byte = input[in_ptr++]; \ | |
128 nibble = last_byte & 0x0F; \ | |
129 decode_top_nibble_next = 1; \ | |
130 } | |
131 | |
132 // note: This decoder assumes the format 0x62 data always comes in | |
133 // stereo flavor | |
134 static int dk3_adpcm_decode_block(unsigned short *output, unsigned char *input, | |
135 int block_size) | |
136 { | |
137 int sum_pred; | |
138 int diff_pred; | |
139 int sum_index; | |
140 int diff_index; | |
141 int diff_channel; | |
142 int in_ptr = 0x10; | |
143 int out_ptr = 0; | |
144 | |
145 unsigned char last_byte = 0; | |
146 unsigned char nibble; | |
147 int decode_top_nibble_next = 0; | |
148 | |
149 // ADPCM work variables | |
150 int sign; | |
151 int delta; | |
152 int step; | |
153 int diff; | |
154 | |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
155 sum_pred = AV_RL16(&input[10]); |
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
156 diff_pred = AV_RL16(&input[12]); |
5408 | 157 SE_16BIT(sum_pred); |
158 SE_16BIT(diff_pred); | |
159 diff_channel = diff_pred; | |
160 sum_index = input[14]; | |
161 diff_index = input[15]; | |
162 | |
16965
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
163 while (in_ptr < block_size - !decode_top_nibble_next) |
5408 | 164 // while (in_ptr < 2048) |
165 { | |
166 // process the first predictor of the sum channel | |
167 DK3_GET_NEXT_NIBBLE(); | |
168 | |
169 step = adpcm_step[sum_index]; | |
170 | |
171 sign = nibble & 8; | |
172 delta = nibble & 7; | |
173 | |
174 diff = step >> 3; | |
175 if (delta & 4) diff += step; | |
176 if (delta & 2) diff += step >> 1; | |
177 if (delta & 1) diff += step >> 2; | |
178 | |
179 if (sign) | |
180 sum_pred -= diff; | |
181 else | |
182 sum_pred += diff; | |
183 | |
184 CLAMP_S16(sum_pred); | |
185 | |
186 sum_index += adpcm_index[nibble]; | |
187 CLAMP_0_TO_88(sum_index); | |
188 | |
189 // process the diff channel predictor | |
190 DK3_GET_NEXT_NIBBLE(); | |
191 | |
192 step = adpcm_step[diff_index]; | |
193 | |
194 sign = nibble & 8; | |
195 delta = nibble & 7; | |
196 | |
197 diff = step >> 3; | |
198 if (delta & 4) diff += step; | |
199 if (delta & 2) diff += step >> 1; | |
200 if (delta & 1) diff += step >> 2; | |
201 | |
202 if (sign) | |
203 diff_pred -= diff; | |
204 else | |
205 diff_pred += diff; | |
206 | |
207 CLAMP_S16(diff_pred); | |
208 | |
209 diff_index += adpcm_index[nibble]; | |
210 CLAMP_0_TO_88(diff_index); | |
211 | |
212 // output the first pair of stereo PCM samples | |
213 diff_channel = (diff_channel + diff_pred) / 2; | |
214 output[out_ptr++] = sum_pred + diff_channel; | |
215 output[out_ptr++] = sum_pred - diff_channel; | |
216 | |
217 // process the second predictor of the sum channel | |
218 DK3_GET_NEXT_NIBBLE(); | |
219 | |
220 step = adpcm_step[sum_index]; | |
221 | |
222 sign = nibble & 8; | |
223 delta = nibble & 7; | |
224 | |
225 diff = step >> 3; | |
226 if (delta & 4) diff += step; | |
227 if (delta & 2) diff += step >> 1; | |
228 if (delta & 1) diff += step >> 2; | |
229 | |
230 if (sign) | |
231 sum_pred -= diff; | |
232 else | |
233 sum_pred += diff; | |
234 | |
235 CLAMP_S16(sum_pred); | |
236 | |
237 sum_index += adpcm_index[nibble]; | |
238 CLAMP_0_TO_88(sum_index); | |
239 | |
240 // output the second pair of stereo PCM samples | |
241 output[out_ptr++] = sum_pred + diff_channel; | |
242 output[out_ptr++] = sum_pred - diff_channel; | |
243 } | |
244 | |
245 return out_ptr; | |
246 } | |
247 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
248 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
|
249 { |
5408 | 250 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
|
251 sh_audio->ds->ss_mul) != |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26280
diff
changeset
|
252 sh_audio->ds->ss_mul) |
5408 | 253 return -1; /* EOF */ |
254 | |
16965
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
255 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
|
256 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
|
257 return -1; |
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
258 } |
5408 | 259 return 2 * dk3_adpcm_decode_block( |
260 (unsigned short*)buf, sh_audio->a_in_buffer, | |
16965
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
261 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
|
262 } |