1 /*
2 * a52_decore.c
3 *
4 * Copyright (C) Thomas Oestreich - June 2001
5 * changes by Joerg Sauer <js-mail@gmx.net> for liba52-0.7.3
6 *
7 * This file is part of transcode, a video stream processing tool
8 *
9 * transcode 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, or (at your option)
12 * any later version.
13 *
14 * transcode 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 *
19 * You should have received a copy of the GNU General Public License
20 * along with GNU Make; see the file COPYING. If not, write to
21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25 #include "transcode.h"
26 #include "tcinfo.h"
27 #include "libtc/libtc.h"
28
29 #include <limits.h>
30
31 #ifdef HAVE_DLFCN_H
32 #include <dlfcn.h>
33 #else
34 # ifdef OS_DARWIN
35 # include "libdldarwin/dlfcn.h"
36 # endif
37 #endif
38
39 #include <a52dec/a52.h>
40 #include <a52dec/mm_accel.h>
41 #include "magic.h"
42
43 #define FRAME_SIZE 3840
44 #define HEADER_LEN 8
45 #define A52_BLOCKS 6
46
convert(int32_t i)47 static inline int16_t convert (int32_t i)
48 {
49
50 if (i > 0x43c07fff)
51 return 32767;
52 else if (i < 0x43bf8000)
53 return -32768;
54 else
55 return i - 0x43c00000;
56 }
57
float2s16_2(float * _f,int16_t * s16)58 static void float2s16_2 (float * _f, int16_t * s16)
59 {
60 int i;
61 int32_t * f = (int32_t *) _f;
62
63 //interleave l/r channels
64
65 for (i = 0; i < 256; i++) {
66 s16[2*i] = convert (f[i]);
67 s16[2*i+1] = convert (f[i+256]);
68 }
69 }
70
float2s16(float * _f,int16_t * s16)71 static void float2s16 (float * _f, int16_t * s16)
72 {
73 int i;
74 int32_t * f = (int32_t *) _f;
75
76 for (i = 0; i < 256*A52_BLOCKS; i++) s16[i] = convert (f[i]);
77 }
78
79 static unsigned char buf[FRAME_SIZE];
80
81 int a52_decore(decode_t *decode); /* avoid a missing-prototype warning */
82
a52_decore(decode_t * decode)83 int a52_decore(decode_t *decode) {
84
85 int i, s=0, pcm_size, frame_size;
86 int k, n, bytes_read, bytes_wrote, sample_rate, bit_rate, flags;
87 unsigned short sync_word = 0;
88 int pass_through = decode->format==TC_CODEC_RAW?1:0;
89 a52_state_t *state;
90 sample_t level=1, bias=384;
91 sample_t *samples;
92 int chans = -1;
93 int16_t pcm_buf[256 * A52_BLOCKS];
94 uint32_t accel = MM_ACCEL_DJBFFT;
95
96
97 #ifdef HAVE_ASM_MMX
98 if (ac_cpuinfo() & AC_MMX)
99 accel |= MM_ACCEL_X86_MMX;
100 #endif
101
102 #ifdef HAVE_ASM_3DNOW
103 if (ac_cpuinfo() & AC_3DNOW)
104 accel |= MM_ACCEL_X86_3DNOW;
105 #endif
106
107 state = a52_init(accel);
108
109 n=0;
110
111 for (;;) {
112
113 // check for next AC3 sync bytes
114
115 k=0;
116 memset(buf, 0, HEADER_LEN);
117 s=0;
118 sync_word = 0;
119 bytes_read = 0;
120 bytes_wrote = 0;
121
122 for (;;) {
123
124 if (tc_pread(decode->fd_in, &buf[s], 1) !=1) {
125 //ac3 sync frame scan failed
126 return(-1);
127 }
128
129 sync_word = (sync_word << 8) + (unsigned char) buf[s];
130
131 s = (s+1)%2;
132
133 ++k;
134
135 if(sync_word == 0x0b77) break;
136
137 if(k>(1<<20)) {
138 tc_log_error(__FILE__, "no AC3 sync frame found within 1024 kB of stream");
139 return(-1);
140 }
141 }
142
143 // found, read rest of frame header
144
145 buf[0] = (sync_word >> 8) & 0xff;
146 buf[1] = (sync_word) & 0xff;
147
148 bytes_read=tc_pread(decode->fd_in, &buf[2], HEADER_LEN-2);
149
150 if(bytes_read< HEADER_LEN-2) {
151 if(decode->verbose & TC_DEBUG)
152 tc_log_msg(__FILE__, "read error (%d/%d)", bytes_read, HEADER_LEN-2);
153 return(-1);
154 }
155
156 // FIXME:
157 // save header
158 // ac_memcpy(header, &buf[2], 5);
159
160 // valid AC3 frame?
161
162 frame_size = a52_syncinfo(buf, &flags, &sample_rate, &bit_rate);
163
164 if(frame_size==0 || frame_size>= FRAME_SIZE) {
165 tc_log_msg(__FILE__, "frame size = %d (%d %d)", frame_size, sample_rate, bit_rate);
166 goto skip_frame;
167 }
168
169 // read the rest of the frame
170 if((bytes_read=tc_pread(decode->fd_in, &buf[HEADER_LEN], frame_size-HEADER_LEN)) < frame_size-HEADER_LEN) {
171 if(decode->verbose & TC_DEBUG)
172 tc_log_msg(__FILE__, "read error (%d/%d)", bytes_read, frame_size-HEADER_LEN);
173 return(-1);
174 }
175
176 // decoder start
177 flags = (decode->a52_mode & TC_A52_DOLBY_OFF) ? A52_STEREO:A52_DOLBY;
178 flags = (decode->a52_mode & TC_A52_DEMUX) ? (A52_3F2R | A52_LFE) : flags;
179
180 a52_frame(state, buf, &flags, &level, bias);
181 if(decode->a52_mode & TC_A52_DRC_OFF) a52_dynrng (state, NULL, NULL);
182
183 flags &= A52_CHANNEL_MASK | A52_LFE;
184
185 if (flags & A52_LFE)
186 chans = 6;
187 else if (flags & 1) /* center channel */
188 chans = 5;
189 else switch (flags) {
190 case A52_2F2R:
191 chans = 4;
192 break;
193 case A52_CHANNEL:
194 case A52_STEREO:
195 case A52_DOLBY:
196 chans = 2;
197 break;
198 default:
199 return 1;
200 }
201
202 // decode frame
203 if (!pass_through) {
204 for(i=0; i<A52_BLOCKS; ++i) {
205
206 a52_block(state);
207
208 // output pcm data
209
210 samples = a52_samples(state);
211
212 pcm_size = 256 * sizeof (int16_t)*chans;
213
214 //tc_log_msg(__FILE__, "write (%d) bytes", pcm_size);
215 (decode->a52_mode & TC_A52_DEMUX) ? float2s16((float *)samples, (int16_t *)&pcm_buf) : float2s16_2((float *)samples, (int16_t *)&pcm_buf);
216
217 if((bytes_wrote=tc_pwrite(decode->fd_out, (char*) pcm_buf, pcm_size)) < pcm_size) {
218 if(decode->verbose & TC_DEBUG)
219 tc_log_error(__FILE__, "write error (%d/%d)", bytes_wrote, pcm_size);
220 return(-1);
221 }
222 } //end pcm data output
223 } else {
224 // pass through
225 for(i=0; i<A52_BLOCKS; ++i) {
226
227 a52_block(state);
228
229 // output pcm data
230
231 samples = a52_samples(state);
232
233 pcm_size = 256 * sizeof (int16_t)*chans;
234
235 //tc_log_msg(__FILE__, "write (%d) bytes", pcm_size);
236 (decode->a52_mode & TC_A52_DEMUX) ? float2s16((float *)samples, (int16_t *)&pcm_buf) : float2s16_2((float *)samples, (int16_t *)&pcm_buf);
237 } //end pcm data output
238 if((bytes_wrote=tc_pwrite(decode->fd_out, buf, bytes_read+HEADER_LEN)) < bytes_read+HEADER_LEN) {
239 if(decode->verbose & TC_DEBUG)
240 tc_log_error(__FILE__, "write error (%d/%d)", bytes_wrote, bytes_read+HEADER_LEN);
241 return(-1);
242 }
243 }
244
245 skip_frame:
246 continue;
247
248 } //end frame processing
249
250 // should not get here
251 return 0;
252 }
253