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