Mercurial > mplayer.hg
annotate libmpcodecs/ad_imaadpcm.c @ 34757:da38eb1e2069
subassconvert: handle "\r\n" line ends
Previously the code converting text subtitles to ASS format converted newline
characters, and only those, to ASS "new line" markup. If the subtitles
contained "\r\n", the "\r" was thus left in the text. In previous libass
versions the "\r" was not visible, but in the current one it produces an empty
box. Improve the conversion to remove the "\r" in that case. Also treat a lone
"\r" as a newline.
Picked from mplayer2/3e0a2705
author | cboesch |
---|---|
date | Sat, 07 Apr 2012 11:17:09 +0000 |
parents | b40d593a463f |
children |
rev | line source |
---|---|
5408 | 1 /* |
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
2 * IMA ADPCM decoder |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
3 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
4 * This file is in charge of decoding all of the various IMA ADPCM data |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
5 * formats that various entities have created. Details about the data |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
6 * formats can be found here: |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
7 * http://www.pcisys.net/~melanson/codecs/ |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
8 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
9 * So far, this file handles these formats: |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
10 * 'ima4': IMA ADPCM found in QT files |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
11 * 0x11: IMA ADPCM found in MS AVI/ASF/WAV files |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
12 * 0x61: DK4 ADPCM found in certain AVI files on Sega Saturn CD-ROMs; |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
13 * note that this is a 'rogue' format number in that it was |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
14 * never officially registered with Microsoft |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
15 * 0x1100736d: IMA ADPCM coded like in MS AVI/ASF/WAV found in QT files |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
16 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
17 * Copyright (c) 2002 Mike Melanson |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
18 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
19 * This file is part of MPlayer. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
20 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
21 * 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:
29297
diff
changeset
|
22 * 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:
29297
diff
changeset
|
23 * 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:
29297
diff
changeset
|
24 * (at your option) any later version. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
25 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
26 * 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:
29297
diff
changeset
|
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
29 * GNU General Public License for more details. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
30 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
31 * 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:
29297
diff
changeset
|
32 * 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:
29297
diff
changeset
|
33 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29297
diff
changeset
|
34 */ |
5408 | 35 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
36 #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
|
37 #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
|
38 #include <unistd.h> |
27220 | 39 #include <inttypes.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
|
40 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
41 #include "config.h" |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
42 #include "libavutil/intreadwrite.h" |
21507
fa99b3d31d13
Hack around libavutil/bswap.h compilation problems due to always_inline undefined.
reimar
parents:
21372
diff
changeset
|
43 #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
|
44 #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
|
45 |
5408 | 46 #define MS_IMA_ADPCM_PREAMBLE_SIZE 4 |
47 | |
48 #define QT_IMA_ADPCM_PREAMBLE_SIZE 2 | |
49 #define QT_IMA_ADPCM_BLOCK_SIZE 0x22 | |
50 #define QT_IMA_ADPCM_SAMPLES_PER_BLOCK 64 | |
51 | |
52 // pertinent tables for IMA ADPCM | |
27116 | 53 static const int16_t adpcm_step[89] = |
5408 | 54 { |
55 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, | |
56 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, | |
57 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, | |
58 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, | |
59 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, | |
60 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, | |
61 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, | |
62 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | |
63 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 | |
64 }; | |
65 | |
27121 | 66 static const int8_t adpcm_index[8] = |
5408 | 67 { |
68 -1, -1, -1, -1, 2, 4, 6, 8, | |
69 }; | |
70 | |
71 // useful macros | |
72 // clamp a number between 0 and 88 | |
27118 | 73 #define CLAMP_0_TO_88(x) x = av_clip(x, 0, 88); |
5408 | 74 // clamp a number within a signed 16-bit range |
27118 | 75 #define CLAMP_S16(x) x = av_clip_int16(x); |
5408 | 76 // clamp a number above 16 |
77 #define CLAMP_ABOVE_16(x) if (x < 16) x = 16; | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
78 |
30504
cc27da5d7286
Mark all ad_info_t/vd_info_t structure declarations as const.
diego
parents:
30421
diff
changeset
|
79 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
|
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 "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
|
82 "imaadpcm", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
83 "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
|
84 "Mike Melanson", |
5408 | 85 "" |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
86 }; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
87 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
88 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
|
89 |
5408 | 90 static int preinit(sh_audio_t *sh_audio) |
91 { | |
92 // not exactly sure what this field is for | |
93 sh_audio->audio_out_minsize = 8192; | |
94 | |
95 // if format is "ima4", assume the audio is coming from a QT file which | |
96 // indicates constant block size, whereas an AVI/ASF/WAV file will fill | |
97 // in this field with 0x11 | |
8103 | 98 if ((sh_audio->format == 0x11) || (sh_audio->format == 0x61) || |
99 (sh_audio->format == 0x1100736d)) | |
5408 | 100 { |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
27230
diff
changeset
|
101 sh_audio->ds->ss_div = (sh_audio->wf->nBlockAlign - |
5408 | 102 (MS_IMA_ADPCM_PREAMBLE_SIZE * sh_audio->wf->nChannels)) * 2; |
103 sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign; | |
104 } | |
105 else | |
106 { | |
107 sh_audio->ds->ss_div = QT_IMA_ADPCM_SAMPLES_PER_BLOCK; | |
108 sh_audio->ds->ss_mul = QT_IMA_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels; | |
109 } | |
5458 | 110 sh_audio->audio_in_minsize=sh_audio->ds->ss_mul; |
5408 | 111 return 1; |
112 } | |
113 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
114 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
|
115 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
116 /* 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
|
117 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
|
118 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
|
119 /* decodes 34 byte -> 64 short*/ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
27230
diff
changeset
|
120 sh_audio->i_bps = |
5408 | 121 (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
|
122 sh_audio->samplesize=2; |
5408 | 123 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
124 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
|
125 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
126 |
5408 | 127 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
|
128 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
129 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
130 |
5481 | 131 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
|
132 { |
5481 | 133 if(cmd==ADCTRL_SKIP_FRAME){ |
134 demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,sh_audio->ds->ss_mul); | |
135 return CONTROL_TRUE; | |
136 } | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
137 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
|
138 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
139 |
5408 | 140 static void decode_nibbles(unsigned short *output, |
141 int output_size, int channels, | |
27117 | 142 int predictor[2], int index[2]) |
5408 | 143 { |
144 int step[2]; | |
145 int i; | |
146 int sign; | |
147 int delta; | |
148 int channel_number = 0; | |
149 | |
27117 | 150 step[0] = adpcm_step[index[0]]; |
151 step[1] = adpcm_step[index[1]]; | |
5408 | 152 |
153 for (i = 0; i < output_size; i++) | |
154 { | |
155 delta = output[i]; | |
27121 | 156 sign = delta & 8; |
157 delta = delta & 7; | |
5408 | 158 |
159 index[channel_number] += adpcm_index[delta]; | |
160 CLAMP_0_TO_88(index[channel_number]); | |
161 | |
27120 | 162 delta = 2 * delta + 1; |
163 if (sign) delta = -delta; | |
5408 | 164 |
27120 | 165 predictor[channel_number] += (delta * step[channel_number]) >> 3; |
5408 | 166 |
167 CLAMP_S16(predictor[channel_number]); | |
168 output[i] = predictor[channel_number]; | |
169 step[channel_number] = adpcm_step[index[channel_number]]; | |
170 | |
171 // toggle channel | |
172 channel_number ^= channels - 1; | |
173 | |
174 } | |
175 } | |
176 | |
177 static int qt_ima_adpcm_decode_block(unsigned short *output, | |
27112 | 178 unsigned char *input, int channels, int block_size) |
5408 | 179 { |
29297
dbc412fcde45
Initialize local variable, avoids a possible crash due to using an
reimar
parents:
29263
diff
changeset
|
180 int initial_predictor[2] = {0}; |
dbc412fcde45
Initialize local variable, avoids a possible crash due to using an
reimar
parents:
29263
diff
changeset
|
181 int initial_index[2] = {0}; |
5408 | 182 int i; |
183 | |
27230
48b793612e37
Make really sure channels can only be 1 or 2 for imaadpcm
reimar
parents:
27229
diff
changeset
|
184 if (channels != 1) channels = 2; |
27113
680301b96149
Add a few size checks to IMA decoder. The code is still a mess though,
reimar
parents:
27112
diff
changeset
|
185 if (block_size < channels * QT_IMA_ADPCM_BLOCK_SIZE) |
680301b96149
Add a few size checks to IMA decoder. The code is still a mess though,
reimar
parents:
27112
diff
changeset
|
186 return -1; |
680301b96149
Add a few size checks to IMA decoder. The code is still a mess though,
reimar
parents:
27112
diff
changeset
|
187 |
27114 | 188 for (i = 0; i < channels; i++) { |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
189 initial_index[i] = initial_predictor[i] = (int16_t)AV_RB16(&input[i * QT_IMA_ADPCM_BLOCK_SIZE]); |
5408 | 190 |
191 // mask, sign-extend, and clamp the predictor portion | |
27119 | 192 initial_predictor[i] &= ~0x7F; |
27114 | 193 CLAMP_S16(initial_predictor[i]); |
5408 | 194 |
195 // mask and clamp the index portion | |
27114 | 196 initial_index[i] &= 0x7F; |
197 CLAMP_0_TO_88(initial_index[i]); | |
5408 | 198 } |
199 | |
200 // break apart all of the nibbles in the block | |
201 if (channels == 1) | |
202 for (i = 0; i < QT_IMA_ADPCM_SAMPLES_PER_BLOCK / 2; i++) | |
203 { | |
204 output[i * 2 + 0] = input[2 + i] & 0x0F; | |
205 output[i * 2 + 1] = input[2 + i] >> 4; | |
206 } | |
207 else | |
15786 | 208 for (i = 0; i < QT_IMA_ADPCM_SAMPLES_PER_BLOCK / 2; i++) |
5408 | 209 { |
210 output[i * 4 + 0] = input[2 + i] & 0x0F; | |
211 output[i * 4 + 1] = input[2 + QT_IMA_ADPCM_BLOCK_SIZE + i] & 0x0F; | |
212 output[i * 4 + 2] = input[2 + i] >> 4; | |
213 output[i * 4 + 3] = input[2 + QT_IMA_ADPCM_BLOCK_SIZE + i] >> 4; | |
214 } | |
215 | |
216 decode_nibbles(output, | |
217 QT_IMA_ADPCM_SAMPLES_PER_BLOCK * channels, channels, | |
27117 | 218 initial_predictor, initial_index); |
5408 | 219 |
220 return QT_IMA_ADPCM_SAMPLES_PER_BLOCK * channels; | |
221 } | |
222 | |
223 static int ms_ima_adpcm_decode_block(unsigned short *output, | |
224 unsigned char *input, int channels, int block_size) | |
225 { | |
27114 | 226 int predictor[2]; |
227 int index[2]; | |
5408 | 228 int i; |
229 int channel_counter; | |
230 int channel_index; | |
231 int channel_index_l; | |
232 int channel_index_r; | |
233 | |
27230
48b793612e37
Make really sure channels can only be 1 or 2 for imaadpcm
reimar
parents:
27229
diff
changeset
|
234 if (channels != 1) channels = 2; |
27113
680301b96149
Add a few size checks to IMA decoder. The code is still a mess though,
reimar
parents:
27112
diff
changeset
|
235 if (block_size < MS_IMA_ADPCM_PREAMBLE_SIZE * channels) |
680301b96149
Add a few size checks to IMA decoder. The code is still a mess though,
reimar
parents:
27112
diff
changeset
|
236 return -1; |
680301b96149
Add a few size checks to IMA decoder. The code is still a mess though,
reimar
parents:
27112
diff
changeset
|
237 |
27114 | 238 for (i = 0; i < channels; i++) { |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
239 predictor[i] = (int16_t)AV_RL16(&input[i * 4]); |
27114 | 240 index[i] = input[i * 4 + 2]; |
5408 | 241 } |
242 | |
243 if (channels == 1) | |
244 for (i = 0; | |
10808
9883dfced49c
100l: you have 2 nibbles per byte, don't divide byte count by 2
rtognimp
parents:
8103
diff
changeset
|
245 i < (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels); i++) |
5408 | 246 { |
247 output[i * 2 + 0] = input[MS_IMA_ADPCM_PREAMBLE_SIZE + i] & 0x0F; | |
248 output[i * 2 + 1] = input[MS_IMA_ADPCM_PREAMBLE_SIZE + i] >> 4; | |
249 } | |
250 else | |
251 { | |
252 // encoded as 8 nibbles (4 bytes) per channel; switch channel every | |
253 // 4th byte | |
254 channel_counter = 0; | |
255 channel_index_l = 0; | |
256 channel_index_r = 1; | |
257 channel_index = channel_index_l; | |
258 for (i = 0; | |
259 i < (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels); i++) | |
260 { | |
261 output[channel_index + 0] = | |
262 input[MS_IMA_ADPCM_PREAMBLE_SIZE * 2 + i] & 0x0F; | |
263 output[channel_index + 2] = | |
264 input[MS_IMA_ADPCM_PREAMBLE_SIZE * 2 + i] >> 4; | |
265 channel_index += 4; | |
266 channel_counter++; | |
267 if (channel_counter == 4) | |
268 { | |
269 channel_index_l = channel_index; | |
270 channel_index = channel_index_r; | |
271 } | |
272 else if (channel_counter == 8) | |
273 { | |
274 channel_index_r = channel_index; | |
275 channel_index = channel_index_l; | |
276 channel_counter = 0; | |
277 } | |
278 } | |
279 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
27230
diff
changeset
|
280 |
5408 | 281 decode_nibbles(output, |
282 (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels) * 2, | |
283 channels, | |
27117 | 284 predictor, index); |
5408 | 285 |
286 return (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels) * 2; | |
287 } | |
288 | |
289 static int dk4_ima_adpcm_decode_block(unsigned short *output, | |
290 unsigned char *input, int channels, int block_size) | |
291 { | |
292 int i; | |
293 int output_ptr; | |
27114 | 294 int predictor[2]; |
295 int index[2]; | |
5408 | 296 |
27230
48b793612e37
Make really sure channels can only be 1 or 2 for imaadpcm
reimar
parents:
27229
diff
changeset
|
297 if (channels != 1) channels = 2; |
27113
680301b96149
Add a few size checks to IMA decoder. The code is still a mess though,
reimar
parents:
27112
diff
changeset
|
298 if (block_size < MS_IMA_ADPCM_PREAMBLE_SIZE * channels) |
680301b96149
Add a few size checks to IMA decoder. The code is still a mess though,
reimar
parents:
27112
diff
changeset
|
299 return -1; |
680301b96149
Add a few size checks to IMA decoder. The code is still a mess though,
reimar
parents:
27112
diff
changeset
|
300 |
27114 | 301 for (i = 0; i < channels; i++) { |
302 // the first predictor value goes straight to the output | |
31614
b40d593a463f
Use AV_RL* macros instead of typecasts where appropriate.
reimar
parents:
30504
diff
changeset
|
303 predictor[i] = output[i] = (int16_t)AV_RL16(&input[i * 4]); |
27114 | 304 index[i] = input[i * 4 + 2]; |
5408 | 305 } |
306 | |
307 output_ptr = channels; | |
308 for (i = MS_IMA_ADPCM_PREAMBLE_SIZE * channels; i < block_size; i++) | |
309 { | |
310 output[output_ptr++] = input[i] >> 4; | |
311 output[output_ptr++] = input[i] & 0x0F; | |
312 } | |
313 | |
314 decode_nibbles(&output[channels], | |
315 (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels) * 2 - channels, | |
316 channels, | |
27117 | 317 predictor, index); |
5408 | 318 |
319 return (block_size - MS_IMA_ADPCM_PREAMBLE_SIZE * channels) * 2 - channels; | |
320 } | |
321 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
322 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
|
323 { |
27112 | 324 int res = -1; |
325 int (*decode_func)(unsigned short *output, unsigned char *input, int channels, int block_size) = qt_ima_adpcm_decode_block; | |
5408 | 326 if (demux_read_data(sh_audio->ds, sh_audio->a_in_buffer, |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
27230
diff
changeset
|
327 sh_audio->ds->ss_mul) != |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
27230
diff
changeset
|
328 sh_audio->ds->ss_mul) |
5408 | 329 return -1; |
330 | |
8103 | 331 if ((sh_audio->format == 0x11) || (sh_audio->format == 0x1100736d)) |
27112 | 332 decode_func = ms_ima_adpcm_decode_block; |
5408 | 333 else if (sh_audio->format == 0x61) |
27112 | 334 decode_func = dk4_ima_adpcm_decode_block; |
335 | |
336 res = decode_func((unsigned short*)buf, sh_audio->a_in_buffer, | |
337 sh_audio->wf->nChannels, sh_audio->ds->ss_mul); | |
27229 | 338 return res < 0 ? res : 2 * res; |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
339 } |