Mercurial > mplayer.hg
annotate libmpcodecs/ad_libdca.c @ 27559:21590d0bb4e6
The yuv->rgb tables are too small for clipping to be avoidable,
thus revert the respective optimization. The table generator code
has to be rewritten anyway one day by some volunteer because it is
not LGPL, fixing the GPL table generator thus seems like wasted time.
author | michael |
---|---|
date | Fri, 12 Sep 2008 21:25:42 +0000 |
parents | 82601a38e2a7 |
children | cc27da5d7286 |
rev | line source |
---|---|
23821 | 1 /* |
26727 | 2 * DTS Coherent Acoustics stream decoder using libdca |
23821 | 3 * This file is partially based on dtsdec.c r9036 from FFmpeg and ad_liba52.c |
26727 | 4 * |
23821 | 5 * Copyright (C) 2007 Roberto Togni |
6 * | |
7 * This file is part of MPlayer. | |
8 * | |
9 * MPlayer is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU General Public License as published by | |
11 * the Free Software Foundation; either version 2 of the License, or | |
12 * (at your option) any later version. | |
13 * | |
14 * MPlayer is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 * GNU General Public License for more details. | |
18 * | |
26727 | 19 * You should have received a copy of the GNU General Public License along |
20 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
23821 | 22 */ |
23 | |
24 #include <stdio.h> | |
25 #include <stdlib.h> | |
26 #include <unistd.h> | |
27 #include <assert.h> | |
28 #include "config.h" | |
29 | |
30 #include "mp_msg.h" | |
31 #include "ad_internal.h" | |
32 | |
33 #include <dts.h> | |
34 | |
35 static ad_info_t info = | |
36 { | |
37 "DTS decoding with libdca", | |
38 "libdca", | |
39 "Roberto Togni", | |
40 "", | |
41 "" | |
42 }; | |
43 | |
44 LIBAD_EXTERN(libdca) | |
45 | |
46 #define DTSBUFFER_SIZE 18726 | |
47 #define HEADER_SIZE 14 | |
48 | |
49 #define CONVERT_LEVEL 1 | |
50 #define CONVERT_BIAS 0 | |
51 | |
52 static const char ch2flags[6] = { | |
53 DTS_MONO, | |
54 DTS_STEREO, | |
24701 | 55 DTS_3F, |
23821 | 56 DTS_2F2R, |
57 DTS_3F2R, | |
58 DTS_3F2R | DTS_LFE | |
59 }; | |
60 | |
61 static inline int16_t convert(sample_t s) | |
62 { | |
63 int i = s * 0x7fff; | |
64 | |
65 return (i > 32767) ? 32767 : ((i < -32768) ? -32768 : i); | |
66 } | |
67 | |
68 static void convert2s16_multi(sample_t *f, int16_t *s16, int flags, int ch_out) | |
69 { | |
70 int i; | |
71 | |
72 switch(flags & (DTS_CHANNEL_MASK | DTS_LFE)){ | |
73 case DTS_MONO: | |
74 if (ch_out == 1) | |
75 for(i = 0; i < 256; i++) | |
76 s16[i] = convert(f[i]); | |
77 else | |
78 for(i = 0; i < 256; i++){ | |
79 s16[5*i] = s16[5*i+1] = s16[5*i+2] = s16[5*i+3] = 0; | |
80 s16[5*i+4] = convert(f[i]); | |
81 } | |
82 break; | |
83 case DTS_CHANNEL: | |
84 case DTS_STEREO: | |
85 case DTS_DOLBY: | |
86 for(i = 0; i < 256; i++){ | |
87 s16[2*i] = convert(f[i]); | |
88 s16[2*i+1] = convert(f[i+256]); | |
89 } | |
90 break; | |
91 case DTS_3F: | |
92 for(i = 0; i < 256; i++){ | |
24701 | 93 s16[3*i] = convert(f[i+256]); |
94 s16[3*i+1] = convert(f[i+512]); | |
95 s16[3*i+2] = convert(f[i]); | |
23821 | 96 } |
97 break; | |
98 case DTS_2F2R: | |
99 for(i = 0; i < 256; i++){ | |
100 s16[4*i] = convert(f[i]); | |
101 s16[4*i+1] = convert(f[i+256]); | |
102 s16[4*i+2] = convert(f[i+512]); | |
103 s16[4*i+3] = convert(f[i+768]); | |
104 } | |
105 break; | |
106 case DTS_3F2R: | |
107 for(i = 0; i < 256; i++){ | |
24701 | 108 s16[5*i] = convert(f[i+256]); |
23821 | 109 s16[5*i+1] = convert(f[i+512]); |
110 s16[5*i+2] = convert(f[i+768]); | |
111 s16[5*i+3] = convert(f[i+1024]); | |
24701 | 112 s16[5*i+4] = convert(f[i]); |
23821 | 113 } |
114 break; | |
115 case DTS_MONO | DTS_LFE: | |
116 for(i = 0; i < 256; i++){ | |
117 s16[6*i] = s16[6*i+1] = s16[6*i+2] = s16[6*i+3] = 0; | |
24701 | 118 s16[6*i+4] = convert(f[i]); |
119 s16[6*i+5] = convert(f[i+256]); | |
23821 | 120 } |
121 break; | |
122 case DTS_CHANNEL | DTS_LFE: | |
123 case DTS_STEREO | DTS_LFE: | |
124 case DTS_DOLBY | DTS_LFE: | |
125 for(i = 0; i < 256; i++){ | |
24701 | 126 s16[6*i] = convert(f[i]); |
127 s16[6*i+1] = convert(f[i+256]); | |
23821 | 128 s16[6*i+2] = s16[6*i+3] = s16[6*i+4] = 0; |
24701 | 129 s16[6*i+5] = convert(f[i+512]); |
23821 | 130 } |
131 break; | |
132 case DTS_3F | DTS_LFE: | |
133 for(i = 0; i < 256; i++){ | |
134 s16[6*i] = convert(f[i+256]); | |
24701 | 135 s16[6*i+1] = convert(f[i+512]); |
23821 | 136 s16[6*i+2] = s16[6*i+3] = 0; |
24701 | 137 s16[6*i+4] = convert(f[i]); |
138 s16[6*i+5] = convert(f[i+768]); | |
23821 | 139 } |
140 break; | |
141 case DTS_2F2R | DTS_LFE: | |
142 for(i = 0; i < 256; i++){ | |
24701 | 143 s16[6*i] = convert(f[i]); |
144 s16[6*i+1] = convert(f[i+256]); | |
145 s16[6*i+2] = convert(f[i+512]); | |
146 s16[6*i+3] = convert(f[i+768]); | |
147 s16[6*i+4] = 0; | |
148 s16[6*i+5] = convert(f[1024]); | |
149 } | |
150 break; | |
151 case DTS_3F2R | DTS_LFE: | |
152 for(i = 0; i < 256; i++){ | |
23821 | 153 s16[6*i] = convert(f[i+256]); |
154 s16[6*i+1] = convert(f[i+512]); | |
155 s16[6*i+2] = convert(f[i+768]); | |
156 s16[6*i+3] = convert(f[i+1024]); | |
24701 | 157 s16[6*i+4] = convert(f[i]); |
158 s16[6*i+5] = convert(f[i+1280]); | |
23821 | 159 } |
160 break; | |
161 } | |
162 } | |
163 | |
164 static void channels_info(int flags) | |
165 { | |
166 int lfe = 0; | |
167 char lfestr[5] = ""; | |
168 | |
169 if (flags & DTS_LFE) { | |
170 lfe = 1; | |
171 strcpy(lfestr, "+lfe"); | |
172 } | |
173 mp_msg(MSGT_DECAUDIO, MSGL_V, "DTS: "); | |
174 switch(flags & DTS_CHANNEL_MASK){ | |
175 case DTS_MONO: | |
176 mp_msg(MSGT_DECAUDIO, MSGL_V, "1.%d (mono%s)", lfe, lfestr); | |
177 break; | |
178 case DTS_CHANNEL: | |
179 mp_msg(MSGT_DECAUDIO, MSGL_V, "2.%d (channel%s)", lfe, lfestr); | |
180 break; | |
181 case DTS_STEREO: | |
182 mp_msg(MSGT_DECAUDIO, MSGL_V, "2.%d (stereo%s)", lfe, lfestr); | |
183 break; | |
184 case DTS_3F: | |
24693 | 185 mp_msg(MSGT_DECAUDIO, MSGL_V, "3.%d (3f%s)", lfe, lfestr); |
23821 | 186 break; |
187 case DTS_2F2R: | |
188 mp_msg(MSGT_DECAUDIO, MSGL_V, "4.%d (2f+2r%s)", lfe, lfestr); | |
189 break; | |
190 case DTS_3F2R: | |
191 mp_msg(MSGT_DECAUDIO, MSGL_V, "5.%d (3f+2r%s)", lfe, lfestr); | |
192 break; | |
193 default: | |
194 mp_msg(MSGT_DECAUDIO, MSGL_V, "x.%d (unknown%s)", lfe, lfestr); | |
195 } | |
196 mp_msg(MSGT_DECAUDIO, MSGL_V, "\n"); | |
197 } | |
198 | |
199 static int dts_sync(sh_audio_t *sh, int *flags) | |
200 { | |
201 dts_state_t *s = sh->context; | |
202 int length; | |
203 int sample_rate; | |
204 int frame_length; | |
205 int bit_rate; | |
206 | |
207 sh->a_in_buffer_len=0; | |
208 | |
209 while(1) { | |
210 while(sh->a_in_buffer_len < HEADER_SIZE) { | |
211 int c = demux_getc(sh->ds); | |
212 | |
213 if(c < 0) | |
214 return -1; | |
215 sh->a_in_buffer[sh->a_in_buffer_len++] = c; | |
216 } | |
217 | |
218 length = dts_syncinfo(s, sh->a_in_buffer, flags, &sample_rate, | |
219 &bit_rate, &frame_length); | |
220 | |
221 if(length >= HEADER_SIZE) | |
222 break; | |
223 | |
25278
b037a816be70
Prevent from outputing mass of 'skip' log messages in verbose level.
ulion
parents:
24701
diff
changeset
|
224 // mp_msg(MSGT_DECAUDIO, MSGL_V, "skip\n"); |
23821 | 225 memmove(sh->a_in_buffer, sh->a_in_buffer+1, HEADER_SIZE-1); |
226 --sh->a_in_buffer_len; | |
227 } | |
228 | |
229 demux_read_data(sh->ds, sh->a_in_buffer + HEADER_SIZE, length - HEADER_SIZE); | |
230 | |
231 sh->samplerate = sample_rate; | |
232 sh->i_bps = bit_rate/8; | |
233 | |
234 return length; | |
235 } | |
236 | |
237 static int decode_audio(sh_audio_t *sh, unsigned char *buf, int minlen, int maxlen) | |
238 { | |
239 dts_state_t *s = sh->context; | |
240 int16_t *out_samples = (int16_t*)buf; | |
241 int flags; | |
242 level_t level; | |
243 sample_t bias; | |
244 int nblocks; | |
245 int i; | |
246 int data_size = 0; | |
247 | |
248 if(!sh->a_in_buffer_len) | |
249 if(dts_sync(sh, &flags) < 0) return -1; /* EOF */ | |
250 sh->a_in_buffer_len=0; | |
251 | |
252 flags &= ~(DTS_CHANNEL_MASK | DTS_LFE); | |
253 flags |= ch2flags[sh->channels - 1]; | |
254 | |
255 level = CONVERT_LEVEL; | |
256 bias = CONVERT_BIAS; | |
257 flags |= DTS_ADJUST_LEVEL; | |
258 if(dts_frame(s, sh->a_in_buffer, &flags, &level, bias)) { | |
259 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "dts_frame() failed\n"); | |
260 goto end; | |
261 } | |
262 | |
263 nblocks = dts_blocks_num(s); | |
264 | |
265 for(i = 0; i < nblocks; i++) { | |
266 if(dts_block(s)) { | |
267 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "dts_block() failed\n"); | |
268 goto end; | |
269 } | |
270 | |
271 convert2s16_multi(dts_samples(s), out_samples, flags, sh->channels); | |
272 | |
273 out_samples += 256 * sh->channels; | |
274 data_size += 256 * sizeof(int16_t) * sh->channels; | |
275 } | |
276 | |
277 end: | |
278 return data_size; | |
279 } | |
280 | |
281 static int preinit(sh_audio_t *sh) | |
282 { | |
283 /* 256 = samples per block, 16 = max number of blocks */ | |
284 sh->audio_out_minsize = audio_output_channels * sizeof(int16_t) * 256 * 16; | |
285 sh->audio_in_minsize = DTSBUFFER_SIZE; | |
286 sh->samplesize=2; | |
287 | |
288 return 1; | |
289 } | |
290 | |
291 static int init(sh_audio_t *sh) | |
292 { | |
293 dts_state_t *s; | |
294 int flags; | |
295 int decoded_bytes; | |
296 | |
297 s = dts_init(0); | |
298 if(s == NULL) { | |
299 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "dts_init() failed\n"); | |
300 return 0; | |
301 } | |
302 sh->context = s; | |
303 | |
304 if(dts_sync(sh, &flags) < 0) { | |
305 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "dts sync failed\n"); | |
306 dts_free(s); | |
307 return 0; | |
308 } | |
309 channels_info(flags); | |
310 | |
311 assert(audio_output_channels >= 1 && audio_output_channels <= 6); | |
312 sh->channels = audio_output_channels; | |
313 | |
314 decoded_bytes = decode_audio(sh, sh->a_buffer, 1, sh->a_buffer_size); | |
315 if(decoded_bytes > 0) | |
316 sh->a_buffer_len = decoded_bytes; | |
317 else { | |
318 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "dts decode failed on first frame (up/downmix problem?)\n"); | |
319 dts_free(s); | |
320 return 0; | |
321 } | |
322 | |
323 return 1; | |
324 } | |
325 | |
326 static void uninit(sh_audio_t *sh) | |
327 { | |
328 dts_state_t *s = sh->context; | |
329 | |
330 dts_free(s); | |
331 } | |
332 | |
333 static int control(sh_audio_t *sh,int cmd,void* arg, ...) | |
334 { | |
335 int flags; | |
336 | |
337 switch(cmd){ | |
338 case ADCTRL_RESYNC_STREAM: | |
339 dts_sync(sh, &flags); | |
340 return CONTROL_TRUE; | |
341 } | |
342 return CONTROL_UNKNOWN; | |
343 } |