Mercurial > mplayer.hg
annotate libmpcodecs/ad_imaadpcm.c @ 24678:9aab9d7b51f0
Fix missing subtitles after seeking back
Subtitle packets that had been demuxed but whose start time had not
yet been reached were left in the demuxer stream after seeking.
When using the default (non-libass) subtitle rendering this could
block subtitles from appearing as long as the playback position stayed
below the original one before seek. External subtitle files were not
affected.
Fixed by making seek code free all packets from the subtitle stream.
author | uau |
---|---|
date | Thu, 04 Oct 2007 02:35:34 +0000 |
parents | fa99b3d31d13 |
children | cd61e85bb657 |
rev | line source |
---|---|
5408 | 1 /* |
2 IMA ADPCM Decoder for MPlayer | |
3 by Mike Melanson | |
4 | |
5 This file is in charge of decoding all of the various IMA ADPCM data | |
6 formats that various entities have created. Details about the data | |
7 formats can be found here: | |
8 http://www.pcisys.net/~melanson/codecs/ | |
9 | |
10 So far, this file handles these formats: | |
11 'ima4': IMA ADPCM found in QT files | |
12 0x11: IMA ADPCM found in MS AVI/ASF/WAV files | |
13 0x61: DK4 ADPCM found in certain AVI files on Sega Saturn CD-ROMs; | |
14 note that this is a 'rogue' format number in that it was | |
15 never officially registered with Microsoft | |
8103 | 16 0x1100736d: IMA ADPCM coded like in MS AVI/ASF/WAV found in QT files |
5408 | 17 */ |
18 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
19 #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
|
20 #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
|
21 #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
|
22 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
23 #include "config.h" |
21372 | 24 #include "libavutil/common.h" |
21507
fa99b3d31d13
Hack around libavutil/bswap.h compilation problems due to always_inline undefined.
reimar
parents:
21372
diff
changeset
|
25 #include "mpbswap.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
|
26 #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
|
27 |
5408 | 28 #define MS_IMA_ADPCM_PREAMBLE_SIZE 4 |
29 | |
30 #define QT_IMA_ADPCM_PREAMBLE_SIZE 2 | |
31 #define QT_IMA_ADPCM_BLOCK_SIZE 0x22 | |
32 #define QT_IMA_ADPCM_SAMPLES_PER_BLOCK 64 | |
33 | |
34 #define BE_16(x) (be2me_16(*(unsigned short *)(x))) | |
35 #define BE_32(x) (be2me_32(*(unsigned int *)(x))) | |
36 #define LE_16(x) (le2me_16(*(unsigned short *)(x))) | |
37 #define LE_32(x) (le2me_32(*(unsigned int *)(x))) | |
38 | |
39 // pertinent tables for IMA ADPCM | |
40 static int adpcm_step[89] = | |
41 { | |
42 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, | |
43 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, | |
44 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, | |
45 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, | |
46 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, | |
47 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, | |
48 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, | |
49 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | |
50 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 | |
51 }; | |
52 | |
53 static int adpcm_index[16] = | |
54 { | |
55 -1, -1, -1, -1, 2, 4, 6, 8, | |
56 -1, -1, -1, -1, 2, 4, 6, 8 | |
57 }; | |
58 | |
59 // useful macros | |
60 // clamp a number between 0 and 88 | |
61 #define CLAMP_0_TO_88(x) if (x < 0) x = 0; else if (x > 88) x = 88; | |
62 // clamp a number within a signed 16-bit range | |
63 #define CLAMP_S16(x) if (x < -32768) x = -32768; \ | |
64 else if (x > 32767) x = 32767; | |
65 // clamp a number above 16 | |
66 #define CLAMP_ABOVE_16(x) if (x < 16) x = 16; | |
67 // sign extend a 16-bit value | |
68 #define SE_16BIT(x) if (x & 0x8000) x -= 0x10000; | |
69 // sign extend a 4-bit value | |
70 #define SE_4BIT(x) if (x & 0x8) x -= 0x10; | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
71 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
72 static ad_info_t info = |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
73 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
74 "IMA ADPCM audio decoder", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
75 "imaadpcm", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
76 "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
|
77 "Mike Melanson", |
5408 | 78 "" |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
79 }; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
80 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
81 LIBAD_EXTERN(imaadpcm) |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
82 |
5408 | 83 static int preinit(sh_audio_t *sh_audio) |
84 { | |
85 // not exactly sure what this field is for | |
86 sh_audio->audio_out_minsize = 8192; | |
87 | |
88 // if format is "ima4", assume the audio is coming from a QT file which | |
89 // indicates constant block size, whereas an AVI/ASF/WAV file will fill | |
90 // in this field with 0x11 | |
8103 | 91 if ((sh_audio->format == 0x11) || (sh_audio->format == 0x61) || |
92 (sh_audio->format == 0x1100736d)) | |
5408 | 93 { |
94 sh_audio->ds->ss_div = (sh_audio->wf->nBlockAlign - | |
95 (MS_IMA_ADPCM_PREAMBLE_SIZE * sh_audio->wf->nChannels)) * 2; | |
96 sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign; | |
97 } | |
98 else | |
99 { | |
100 sh_audio->ds->ss_div = QT_IMA_ADPCM_SAMPLES_PER_BLOCK; | |
101 sh_audio->ds->ss_mul = QT_IMA_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels; | |
102 } | |
5458 | 103 sh_audio->audio_in_minsize=sh_audio->ds->ss_mul; |
5408 | 104 return 1; |
105 } | |
106 | |
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 static int init(sh_audio_t *sh_audio) |
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 /* IMA-ADPCM 4:1 audio codec:*/ |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
110 sh_audio->channels=sh_audio->wf->nChannels; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
111 sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
112 /* decodes 34 byte -> 64 short*/ |
5408 | 113 sh_audio->i_bps = |
114 (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:
10808
diff
changeset
|
115 sh_audio->samplesize=2; |
5408 | 116 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
117 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
|
118 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
119 |
5408 | 120 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
|
121 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
122 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
123 |
5481 | 124 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
|
125 { |
5481 | 126 if(cmd==ADCTRL_SKIP_FRAME){ |
127 demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,sh_audio->ds->ss_mul); | |
128 return CONTROL_TRUE; | |
129 } | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
130 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
|
131 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
132 |
5408 | 133 static void decode_nibbles(unsigned short *output, |
134 int output_size, int channels, | |
135 int predictor_l, int index_l, | |
136 int predictor_r, int index_r) | |
137 { | |
138 int step[2]; | |
139 int predictor[2]; | |
140 int index[2]; | |
141 int diff; | |
142 int i; | |
143 int sign; | |
144 int delta; | |
145 int channel_number = 0; | |
146 | |
147 step[0] = adpcm_step[index_l]; | |
148 step[1] = adpcm_step[index_r]; | |
149 predictor[0] = predictor_l; | |
150 predictor[1] = predictor_r; | |
151 index[0] = index_l; | |
152 index[1] = index_r; | |
153 | |
154 for (i = 0; i < output_size; i++) | |
155 { | |
156 delta = output[i]; | |
157 | |
158 index[channel_number] += adpcm_index[delta]; | |
159 CLAMP_0_TO_88(index[channel_number]); | |
160 | |
161 sign = delta & 8; | |
162 delta = delta & 7; | |
163 | |
164 diff = step[channel_number] >> 3; | |
165 if (delta & 4) diff += step[channel_number]; | |
166 if (delta & 2) diff += step[channel_number] >> 1; | |
167 if (delta & 1) diff += step[channel_number] >> 2; | |
168 | |
169 if (sign) | |
170 predictor[channel_number] -= diff; | |
171 else | |
172 predictor[channel_number] += diff; | |
173 | |
174 CLAMP_S16(predictor[channel_number]); | |
175 output[i] = predictor[channel_number]; | |
176 step[channel_number] = adpcm_step[index[channel_number]]; | |
177 | |
178 // toggle channel | |
179 channel_number ^= channels - 1; | |
180 | |
181 } | |
182 } | |
183 | |
184 static int qt_ima_adpcm_decode_block(unsigned short *output, | |
185 unsigned char *input, int channels) | |
186 { | |
187 int initial_predictor_l = 0; | |
188 int initial_predictor_r = 0; | |
189 int initial_index_l = 0; | |
190 int initial_index_r = 0; | |
191 int i; | |
192 | |
193 initial_predictor_l = BE_16(&input[0]); | |
194 initial_index_l = initial_predictor_l; | |
195 | |
196 // mask, sign-extend, and clamp the predictor portion | |
197 initial_predictor_l &= 0xFF80; | |
198 SE_16BIT(initial_predictor_l); | |
199 CLAMP_S16(initial_predictor_l); | |
200 | |
201 // mask and clamp the index portion | |
202 initial_index_l &= 0x7F; | |
203 CLAMP_0_TO_88(initial_index_l); | |
204 | |
205 // handle stereo | |
206 if (channels > 1) | |
207 { | |
208 initial_predictor_r = BE_16(&input[QT_IMA_ADPCM_BLOCK_SIZE]); | |
209 initial_index_r = initial_predictor_r; | |
210 | |
211 // mask, sign-extend, and clamp the predictor portion | |
212 initial_predictor_r &= 0xFF80; | |
213 SE_16BIT(initial_predictor_r); | |
214 CLAMP_S16(initial_predictor_r); | |
215 | |
216 // mask and clamp the index portion | |
217 initial_index_r &= 0x7F; | |
218 CLAMP_0_TO_88(initial_index_r); | |
219 } | |
220 | |
221 // break apart all of the nibbles in the block | |
222 if (channels == 1) | |
223 for (i = 0; i < QT_IMA_ADPCM_SAMPLES_PER_BLOCK / 2; i++) | |
224 { | |
225 output[i * 2 + 0] = input[2 + i] & 0x0F; | |
226 output[i * 2 + 1] = input[2 + i] >> 4; | |
227 } | |
228 else | |
15786 | 229 for (i = 0; i < QT_IMA_ADPCM_SAMPLES_PER_BLOCK / 2; i++) |
5408 | 230 { |
231 output[i * 4 + 0] = input[2 + i] & 0x0F; | |
232 output[i * 4 + 1] = input[2 + QT_IMA_ADPCM_BLOCK_SIZE + i] & 0x0F; | |
233 output[i * 4 + 2] = input[2 + i] >> 4; | |
234 output[i * 4 + 3] = input[2 + QT_IMA_ADPCM_BLOCK_SIZE + i] >> 4; | |
235 } | |
236 | |
237 decode_nibbles(output, | |
238 QT_IMA_ADPCM_SAMPLES_PER_BLOCK * channels, channels, | |
239 initial_predictor_l, initial_index_l, | |
240 initial_predictor_r, initial_index_r); | |
241 | |
242 return QT_IMA_ADPCM_SAMPLES_PER_BLOCK * channels; | |
243 } | |
244 | |
245 static int ms_ima_adpcm_decode_block(unsigned short *output, | |
246 unsigned char *input, int channels, int block_size) | |
247 { | |
248 int predictor_l = 0; | |
249 int predictor_r = 0; | |
250 int index_l = 0; | |
251 int index_r = 0; | |
252 int i; | |
253 int channel_counter; | |
254 int channel_index; | |
255 int channel_index_l; | |
256 int channel_index_r; | |
257 | |
258 predictor_l = LE_16(&input[0]); | |
259 SE_16BIT(predictor_l); | |
260 index_l = input[2]; | |
261 if (channels == 2) | |
262 { | |
263 predictor_r = LE_16(&input[4]); | |
264 SE_16BIT(predictor_r); | |
265 index_r = input[6]; | |
266 } | |
267 | |
268 if (channels == 1) | |
269 for (i = 0; | |
10808
9883dfced49c
100l: you have 2 nibbles per byte, don't divide byte count by 2
rtognimp
parents:
8103
diff
changeset
|
270 i < (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels); i++) |
5408 | 271 { |
272 output[i * 2 + 0] = input[MS_IMA_ADPCM_PREAMBLE_SIZE + i] & 0x0F; | |
273 output[i * 2 + 1] = input[MS_IMA_ADPCM_PREAMBLE_SIZE + i] >> 4; | |
274 } | |
275 else | |
276 { | |
277 // encoded as 8 nibbles (4 bytes) per channel; switch channel every | |
278 // 4th byte | |
279 channel_counter = 0; | |
280 channel_index_l = 0; | |
281 channel_index_r = 1; | |
282 channel_index = channel_index_l; | |
283 for (i = 0; | |
284 i < (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels); i++) | |
285 { | |
286 output[channel_index + 0] = | |
287 input[MS_IMA_ADPCM_PREAMBLE_SIZE * 2 + i] & 0x0F; | |
288 output[channel_index + 2] = | |
289 input[MS_IMA_ADPCM_PREAMBLE_SIZE * 2 + i] >> 4; | |
290 channel_index += 4; | |
291 channel_counter++; | |
292 if (channel_counter == 4) | |
293 { | |
294 channel_index_l = channel_index; | |
295 channel_index = channel_index_r; | |
296 } | |
297 else if (channel_counter == 8) | |
298 { | |
299 channel_index_r = channel_index; | |
300 channel_index = channel_index_l; | |
301 channel_counter = 0; | |
302 } | |
303 } | |
304 } | |
305 | |
306 decode_nibbles(output, | |
307 (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels) * 2, | |
308 channels, | |
309 predictor_l, index_l, | |
310 predictor_r, index_r); | |
311 | |
312 return (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels) * 2; | |
313 } | |
314 | |
315 static int dk4_ima_adpcm_decode_block(unsigned short *output, | |
316 unsigned char *input, int channels, int block_size) | |
317 { | |
318 int i; | |
319 int output_ptr; | |
320 int predictor_l = 0; | |
321 int predictor_r = 0; | |
322 int index_l = 0; | |
323 int index_r = 0; | |
324 | |
325 // the first predictor value goes straight to the output | |
326 predictor_l = output[0] = LE_16(&input[0]); | |
327 SE_16BIT(predictor_l); | |
328 index_l = input[2]; | |
329 if (channels == 2) | |
330 { | |
331 predictor_r = output[1] = LE_16(&input[4]); | |
332 SE_16BIT(predictor_r); | |
333 index_r = input[6]; | |
334 } | |
335 | |
336 output_ptr = channels; | |
337 for (i = MS_IMA_ADPCM_PREAMBLE_SIZE * channels; i < block_size; i++) | |
338 { | |
339 output[output_ptr++] = input[i] >> 4; | |
340 output[output_ptr++] = input[i] & 0x0F; | |
341 } | |
342 | |
343 decode_nibbles(&output[channels], | |
344 (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels) * 2 - channels, | |
345 channels, | |
346 predictor_l, index_l, | |
347 predictor_r, index_r); | |
348 | |
349 return (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels) * 2 - channels; | |
350 } | |
351 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
352 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
|
353 { |
5408 | 354 if (demux_read_data(sh_audio->ds, sh_audio->a_in_buffer, |
355 sh_audio->ds->ss_mul) != | |
356 sh_audio->ds->ss_mul) | |
357 return -1; | |
358 | |
8103 | 359 if ((sh_audio->format == 0x11) || (sh_audio->format == 0x1100736d)) |
5408 | 360 { |
361 return 2 * ms_ima_adpcm_decode_block( | |
362 (unsigned short*)buf, sh_audio->a_in_buffer, sh_audio->wf->nChannels, | |
363 sh_audio->ds->ss_mul); | |
364 } | |
365 else if (sh_audio->format == 0x61) | |
366 { | |
367 return 2 * dk4_ima_adpcm_decode_block( | |
368 (unsigned short*)buf, sh_audio->a_in_buffer, sh_audio->wf->nChannels, | |
369 sh_audio->ds->ss_mul); | |
370 } | |
371 else | |
372 { | |
373 return 2 * qt_ima_adpcm_decode_block( | |
374 (unsigned short*)buf, sh_audio->a_in_buffer, sh_audio->wf->nChannels); | |
375 } | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
376 } |