comparison libmpcodecs/ad_libdca.c @ 23821:46b21d6fb61d

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