Mercurial > mplayer.hg
annotate libmpcodecs/ad_libdca.c @ 30051:605c84da5b2c
sync w/r29731
author | gpoirier |
---|---|
date | Sun, 20 Dec 2009 20:57:44 +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 } |