Mercurial > mplayer.hg
annotate libmpcodecs/ad_msadpcm.c @ 21548:bf65ffcf0cdb
Set AVFMT_FLAG_GENPTS if -correct-pts is used.
This should allow using -correct-pts (and thus filters which adjust pts
or add frames) with dvd or other mpeg container files by specifying
"-correct-pts -demuxer lavf -vc ffmpeg12". Might work with libmpeg2
decoder too but certainly not with internal demuxer.
Using this flag isn't quite optimal as it can cause extra buffering of
demuxed frames, but at least it's better than just failing until a more
complex solution is implemented.
author | uau |
---|---|
date | Sun, 10 Dec 2006 00:50:38 +0000 |
parents | fa99b3d31d13 |
children | b21e1506e50b |
rev | line source |
---|---|
5408 | 1 /* |
2 MS ADPCM Decoder for MPlayer | |
3 by Mike Melanson | |
4 | |
5 This file is responsible for decoding Microsoft ADPCM data. | |
6 Details about the data format can be found here: | |
7 http://www.pcisys.net/~melanson/codecs/ | |
8 */ | |
9 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
10 #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
|
11 #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
|
12 #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
|
13 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
14 #include "config.h" |
21372 | 15 #include "libavutil/common.h" |
21507
fa99b3d31d13
Hack around libavutil/bswap.h compilation problems due to always_inline undefined.
reimar
parents:
21372
diff
changeset
|
16 #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
|
17 #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
|
18 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
19 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
|
20 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
21 "MS 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
|
22 "msadpcm", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
23 "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
|
24 "Mike Melanson", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
25 "" |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
26 }; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
27 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
28 LIBAD_EXTERN(msadpcm) |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
29 |
5408 | 30 static int ms_adapt_table[] = |
31 { | |
32 230, 230, 230, 230, 307, 409, 512, 614, | |
33 768, 614, 512, 409, 307, 230, 230, 230 | |
34 }; | |
35 | |
36 static int ms_adapt_coeff1[] = | |
37 { | |
38 256, 512, 0, 192, 240, 460, 392 | |
39 }; | |
40 | |
41 static int ms_adapt_coeff2[] = | |
42 { | |
43 0, -256, 0, 64, 0, -208, -232 | |
44 }; | |
45 | |
6609 | 46 #define MS_ADPCM_PREAMBLE_SIZE 6 |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
47 |
7893 | 48 #define LE_16(x) ((x)[0]+(256*((x)[1]))) |
7890 | 49 //#define LE_16(x) (le2me_16((x)[1]+(256*((x)[0])))) |
7888 | 50 //#define LE_16(x) (le2me_16(*(unsigned short *)(x))) |
51 //#define LE_32(x) (le2me_32(*(unsigned int *)(x))) | |
5408 | 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 | |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
66 static int preinit(sh_audio_t *sh_audio) |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
67 { |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
68 sh_audio->audio_out_minsize = sh_audio->wf->nBlockAlign * 4; |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
69 sh_audio->ds->ss_div = |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
70 (sh_audio->wf->nBlockAlign - MS_ADPCM_PREAMBLE_SIZE) * 2; |
5458 | 71 sh_audio->audio_in_minsize = |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
72 sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign; |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
73 return 1; |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
74 } |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
75 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
76 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
|
77 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
78 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
|
79 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
|
80 sh_audio->i_bps = sh_audio->wf->nBlockAlign * |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
81 (sh_audio->channels*sh_audio->samplerate) / sh_audio->ds->ss_div; |
13427
9d0b052c4f74
setting samplesize to 2 in decoders where neccessary.
reimar
parents:
7893
diff
changeset
|
82 sh_audio->samplesize=2; |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
83 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
84 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
|
85 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
86 |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
87 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
|
88 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
89 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
90 |
5481 | 91 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
|
92 { |
5481 | 93 if(cmd==ADCTRL_SKIP_FRAME){ |
94 demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,sh_audio->ds->ss_mul); | |
95 return CONTROL_TRUE; | |
96 } | |
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 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
|
98 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
99 |
5408 | 100 static int ms_adpcm_decode_block(unsigned short *output, unsigned char *input, |
101 int channels, int block_size) | |
102 { | |
103 int current_channel = 0; | |
104 int idelta[2]; | |
105 int sample1[2]; | |
106 int sample2[2]; | |
107 int coeff1[2]; | |
108 int coeff2[2]; | |
109 int stream_ptr = 0; | |
110 int out_ptr = 0; | |
111 int upper_nibble = 1; | |
112 int nibble; | |
113 int snibble; // signed nibble | |
114 int predictor; | |
115 | |
116 // fetch the header information, in stereo if both channels are present | |
117 if (input[stream_ptr] > 6) | |
118 mp_msg(MSGT_DECAUDIO, MSGL_WARN, | |
119 "MS ADPCM: coefficient (%d) out of range (should be [0..6])\n", | |
120 input[stream_ptr]); | |
121 coeff1[0] = ms_adapt_coeff1[input[stream_ptr]]; | |
122 coeff2[0] = ms_adapt_coeff2[input[stream_ptr]]; | |
123 stream_ptr++; | |
124 if (channels == 2) | |
125 { | |
126 if (input[stream_ptr] > 6) | |
127 mp_msg(MSGT_DECAUDIO, MSGL_WARN, | |
128 "MS ADPCM: coefficient (%d) out of range (should be [0..6])\n", | |
129 input[stream_ptr]); | |
130 coeff1[1] = ms_adapt_coeff1[input[stream_ptr]]; | |
131 coeff2[1] = ms_adapt_coeff2[input[stream_ptr]]; | |
132 stream_ptr++; | |
133 } | |
134 | |
135 idelta[0] = LE_16(&input[stream_ptr]); | |
136 stream_ptr += 2; | |
137 SE_16BIT(idelta[0]); | |
138 if (channels == 2) | |
139 { | |
140 idelta[1] = LE_16(&input[stream_ptr]); | |
141 stream_ptr += 2; | |
142 SE_16BIT(idelta[1]); | |
143 } | |
144 | |
145 sample1[0] = LE_16(&input[stream_ptr]); | |
146 stream_ptr += 2; | |
147 SE_16BIT(sample1[0]); | |
148 if (channels == 2) | |
149 { | |
150 sample1[1] = LE_16(&input[stream_ptr]); | |
151 stream_ptr += 2; | |
152 SE_16BIT(sample1[1]); | |
153 } | |
154 | |
155 sample2[0] = LE_16(&input[stream_ptr]); | |
156 stream_ptr += 2; | |
157 SE_16BIT(sample2[0]); | |
158 if (channels == 2) | |
159 { | |
160 sample2[1] = LE_16(&input[stream_ptr]); | |
161 stream_ptr += 2; | |
162 SE_16BIT(sample2[1]); | |
163 } | |
164 | |
6609 | 165 if (channels == 1) |
166 { | |
167 output[out_ptr++] = sample2[0]; | |
168 output[out_ptr++] = sample1[0]; | |
169 } else { | |
170 output[out_ptr++] = sample2[0]; | |
171 output[out_ptr++] = sample2[1]; | |
172 output[out_ptr++] = sample1[0]; | |
173 output[out_ptr++] = sample1[1]; | |
174 } | |
175 | |
5408 | 176 while (stream_ptr < block_size) |
177 { | |
178 // get the next nibble | |
179 if (upper_nibble) | |
180 nibble = snibble = input[stream_ptr] >> 4; | |
181 else | |
182 nibble = snibble = input[stream_ptr++] & 0x0F; | |
183 upper_nibble ^= 1; | |
184 SE_4BIT(snibble); | |
185 | |
186 predictor = ( | |
187 ((sample1[current_channel] * coeff1[current_channel]) + | |
188 (sample2[current_channel] * coeff2[current_channel])) / 256) + | |
189 (snibble * idelta[current_channel]); | |
190 CLAMP_S16(predictor); | |
191 sample2[current_channel] = sample1[current_channel]; | |
192 sample1[current_channel] = predictor; | |
193 output[out_ptr++] = predictor; | |
194 | |
195 // compute the next adaptive scale factor (a.k.a. the variable idelta) | |
196 idelta[current_channel] = | |
197 (ms_adapt_table[nibble] * idelta[current_channel]) / 256; | |
198 CLAMP_ABOVE_16(idelta[current_channel]); | |
199 | |
200 // toggle the channel | |
201 current_channel ^= channels - 1; | |
202 } | |
203 | |
204 return (block_size - (MS_ADPCM_PREAMBLE_SIZE * channels)) * 2; | |
205 } | |
206 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
207 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
|
208 { |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
209 if (demux_read_data(sh_audio->ds, sh_audio->a_in_buffer, |
5408 | 210 sh_audio->ds->ss_mul) != |
211 sh_audio->ds->ss_mul) | |
212 return -1; /* EOF */ | |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
213 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
214 return 2 * ms_adpcm_decode_block( |
5408 | 215 (unsigned short*)buf, sh_audio->a_in_buffer, |
216 sh_audio->wf->nChannels, 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
|
217 } |