wipe buttons 2nd try :)
[libdreamdvd.git] / a52_dec.c
1 /* 
2  * DreamDVD V0.9 - DVD-Player for Dreambox
3  * Copyright (C) 2007 by Seddi
4  * 
5  * This DVD Player is based upon the great work from the libdvdnav project,
6  * a52dec library, ffmpeg and the knowledge from all the people who made 
7  * watching DVD within linux possible.
8  * 
9  * DreamDVD 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  * DreamDVD 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 this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
22  *
23  * part of libdreamdvd
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <errno.h>
31 #include <getopt.h>
32 #include <math.h>
33 #include <inttypes.h>
34 #include <dlfcn.h>
35
36
37 #include "a52dec.h"
38
39
40 // try to dynamically load and wrap liba52.so.0
41
42 int ddvd_load_liba52()
43 {
44         a52_handle = dlopen("liba52.so.0",RTLD_LAZY);
45         
46         if (a52_handle)
47         {
48                 a52_init = (a52_state_t* (*)(uint32_t)) dlsym(a52_handle, "a52_init");
49                 a52_samples = (sample_t* (*)(a52_state_t*)) dlsym(a52_handle, "a52_samples");
50                 a52_syncinfo = (int (*)(uint8_t*, int*, int*, int*)) dlsym(a52_handle, "a52_syncinfo");
51                 a52_frame = (int (*)(a52_state_t* ,uint8_t* ,int* ,level_t* ,sample_t)) dlsym(a52_handle, "a52_frame");
52                 a52_block = (int (*)(a52_state_t*)) dlsym(a52_handle, "a52_block");
53                 a52_free = (void (*)(a52_state_t*)) dlsym(a52_handle, "a52_free");
54
55                 printf("libdreamdvd: soft ac3 decoding is available, liba52.so.0 loaded !\n");
56                 return 1;
57         }
58         else
59         {
60                 printf("libdreamdvd: soft ac3 decoding is not available, liba52.so.0 not found !\n");
61                 return 0;
62         }
63 }
64
65 // close dynamically loaded liba52.so.0
66
67 void ddvd_close_liba52()
68 {
69         dlclose(a52_handle);
70 }
71
72 // convert 32bit samples to 16bit
73
74 static inline int16_t a52_convert (int32_t i)
75 {
76     i >>= 15;
77     return (i > 32767) ? 32767 : ((i < -32768) ? -32768 : i);
78 }
79
80 // liba52 gives us 256 samples left - 256 samples right
81 // we need 1 left - 1 right so lets sort them
82
83 static void a52_convert2s16_2 (sample_t * _f, int16_t * s16)
84 {
85     int i;
86     int32_t * f = (int32_t *) _f;
87
88     for (i = 0; i < 256; i++) {
89         s16[2*i] = a52_convert (f[i]);
90         s16[2*i+1] = a52_convert (f[i+256]);
91     }
92 }
93
94 // a52 decode function (needs liba52)
95
96 int ddvd_ac3_decode(const uint8_t *input, unsigned int len, int16_t *output)
97 {
98         static int sample_rate;
99     static int flags;
100     int bit_rate;
101         int out_len=0;
102         const uint8_t *end; 
103         end=input+len;
104         
105     static uint8_t buf[3840];
106     static uint8_t * bufptr = buf;
107     static uint8_t * bufpos = buf + 7;
108
109     while (1) {
110         len = end - input;
111         if (!len)
112             break;
113         if (len > bufpos - bufptr)
114             len = bufpos - bufptr;
115         
116         memcpy (bufptr, input, len);
117         bufptr += len;
118         input += len;
119
120         if (bufptr == bufpos) {
121             if (bufpos == buf + 7) {
122                 int length;
123
124                 length = a52_syncinfo (buf, &flags, &sample_rate, &bit_rate);
125                 if (!length) {
126                     for (bufptr = buf; bufptr < buf + 6; bufptr++)
127                         bufptr[0] = bufptr[1];
128                     continue;
129                 }
130                 bufpos = buf + length;
131             } else {
132                 level_t level;
133                 sample_t bias;
134                 int i;
135
136                 flags=A52_DOLBY|A52_ADJUST_LEVEL;
137                         
138                 bias=0;
139                 level=(1 << 26);
140
141                 if (a52_frame (state, buf, &flags, &level, bias))
142                     goto error;
143
144                 for (i = 0; i < 6; i++) {
145                     if (a52_block (state))
146                         goto error;
147                         a52_convert2s16_2(a52_samples(state),output);
148                         output+=512;
149                         out_len+=1024;
150                 }
151                 bufptr = buf;
152                 bufpos = buf + 7;
153                 continue;
154             error:
155                 bufptr = buf;
156                 bufpos = buf + 7;
157             }
158         }
159     }
160         return out_len;
161 }