Mercurial > libavcodec.hg
annotate a52dec.c @ 2071:41d30bae5019 libavcodec
attempt to create some separation in the FLAC system with respect to
demuxer and decoder layers by enabling the FLAC decoder to decode data
without needing the entire file, from start to finish
author | melanson |
---|---|
date | Thu, 10 Jun 2004 04:13:43 +0000 |
parents | 141a9539e270 |
children | 40765c51a7a9 |
rev | line source |
---|---|
332 | 1 /* |
2 * A52 decoder | |
429 | 3 * Copyright (c) 2001 Fabrice Bellard. |
332 | 4 * |
429 | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
332 | 9 * |
429 | 10 * This library is distributed in the hope that it will be useful, |
332 | 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
429 | 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 * Lesser General Public License for more details. | |
332 | 14 * |
429 | 15 * You should have received a copy of the GNU Lesser General Public |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
332 | 18 */ |
1106 | 19 |
20 /** | |
21 * @file a52dec.c | |
22 * A52 decoder. | |
23 */ | |
24 | |
332 | 25 #include "avcodec.h" |
26 #include "liba52/a52.h" | |
27 | |
338 | 28 #ifdef CONFIG_A52BIN |
332 | 29 #include <dlfcn.h> |
30 static const char* liba52name = "liba52.so.0"; | |
31 #endif | |
32 | |
33 /** | |
34 * liba52 - Copyright (C) Aaron Holtzman | |
35 * released under the GPL license. | |
36 */ | |
37 typedef struct AC3DecodeState { | |
1064 | 38 uint8_t inbuf[4096]; /* input buffer */ |
39 uint8_t *inbuf_ptr; | |
332 | 40 int frame_size; |
41 int flags; | |
42 int channels; | |
43 a52_state_t* state; | |
44 sample_t* samples; | |
45 | |
46 /* | |
47 * virtual method table | |
48 * | |
49 * using this function table so the liba52 doesn't | |
50 * have to be really linked together with ffmpeg | |
51 * and might be linked in runtime - this allows binary | |
52 * distribution of ffmpeg library which doens't depend | |
53 * on liba52 library - but if user has it installed | |
54 * it will be used - user might install such library | |
55 * separately | |
56 */ | |
57 void* handle; | |
58 a52_state_t* (*a52_init)(uint32_t mm_accel); | |
59 sample_t* (*a52_samples)(a52_state_t * state); | |
60 int (*a52_syncinfo)(uint8_t * buf, int * flags, | |
61 int * sample_rate, int * bit_rate); | |
62 int (*a52_frame)(a52_state_t * state, uint8_t * buf, int * flags, | |
63 sample_t * level, sample_t bias); | |
64 void (*a52_dynrng)(a52_state_t * state, | |
65 sample_t (* call) (sample_t, void *), void * data); | |
66 int (*a52_block)(a52_state_t * state); | |
67 void (*a52_free)(a52_state_t * state); | |
68 | |
69 } AC3DecodeState; | |
70 | |
338 | 71 #ifdef CONFIG_A52BIN |
332 | 72 static void* dlsymm(void* handle, const char* symbol) |
73 { | |
74 void* f = dlsym(handle, symbol); | |
75 if (!f) | |
76 fprintf(stderr, "A52 Decoder - function '%s' can't be resolved\n", symbol); | |
77 return f; | |
78 } | |
79 #endif | |
80 | |
81 static int a52_decode_init(AVCodecContext *avctx) | |
82 { | |
83 AC3DecodeState *s = avctx->priv_data; | |
84 | |
338 | 85 #ifdef CONFIG_A52BIN |
332 | 86 s->handle = dlopen(liba52name, RTLD_LAZY); |
87 if (!s->handle) | |
88 { | |
368
1db6950d81ea
- Segfault fixed when liba52 dynamic library isn't found.
pulento
parents:
338
diff
changeset
|
89 fprintf(stderr, "A52 library %s could not be opened! \n%s\n", liba52name, dlerror()); |
332 | 90 return -1; |
91 } | |
92 s->a52_init = (a52_state_t* (*)(uint32_t)) dlsymm(s->handle, "a52_init"); | |
93 s->a52_samples = (sample_t* (*)(a52_state_t*)) dlsymm(s->handle, "a52_samples"); | |
94 s->a52_syncinfo = (int (*)(uint8_t*, int*, int*, int*)) dlsymm(s->handle, "a52_syncinfo"); | |
95 s->a52_frame = (int (*)(a52_state_t*, uint8_t*, int*, sample_t*, sample_t)) dlsymm(s->handle, "a52_frame"); | |
96 s->a52_block = (int (*)(a52_state_t*)) dlsymm(s->handle, "a52_block"); | |
97 s->a52_free = (void (*)(a52_state_t*)) dlsymm(s->handle, "a52_free"); | |
98 if (!s->a52_init || !s->a52_samples || !s->a52_syncinfo | |
99 || !s->a52_frame || !s->a52_block || !s->a52_free) | |
100 { | |
101 dlclose(s->handle); | |
102 return -1; | |
103 } | |
104 #else | |
105 /* static linked version */ | |
106 s->handle = 0; | |
1018 | 107 s->a52_init = a52_init; |
108 s->a52_samples = a52_samples; | |
109 s->a52_syncinfo = a52_syncinfo; | |
110 s->a52_frame = a52_frame; | |
111 s->a52_block = a52_block; | |
112 s->a52_free = a52_free; | |
332 | 113 #endif |
114 s->state = s->a52_init(0); /* later use CPU flags */ | |
115 s->samples = s->a52_samples(s->state); | |
116 s->inbuf_ptr = s->inbuf; | |
117 s->frame_size = 0; | |
118 | |
119 return 0; | |
120 } | |
121 | |
122 /**** the following two functions comes from a52dec */ | |
123 static inline int blah (int32_t i) | |
124 { | |
125 if (i > 0x43c07fff) | |
126 return 32767; | |
127 else if (i < 0x43bf8000) | |
128 return -32768; | |
129 return i - 0x43c00000; | |
130 } | |
131 | |
1064 | 132 static inline void float_to_int (float * _f, int16_t * s16, int nchannels) |
332 | 133 { |
134 int i, j, c; | |
135 int32_t * f = (int32_t *) _f; // XXX assumes IEEE float format | |
136 | |
137 j = 0; | |
138 nchannels *= 256; | |
139 for (i = 0; i < 256; i++) { | |
140 for (c = 0; c < nchannels; c += 256) | |
141 s16[j++] = blah (f[i + c]); | |
142 } | |
143 } | |
144 | |
145 /**** end */ | |
146 | |
147 #define HEADER_SIZE 7 | |
148 | |
149 static int a52_decode_frame(AVCodecContext *avctx, | |
150 void *data, int *data_size, | |
1064 | 151 uint8_t *buf, int buf_size) |
332 | 152 { |
153 AC3DecodeState *s = avctx->priv_data; | |
1064 | 154 uint8_t *buf_ptr; |
332 | 155 int flags, i, len; |
156 int sample_rate, bit_rate; | |
157 short *out_samples = data; | |
158 float level; | |
159 static const int ac3_channels[8] = { | |
160 2, 1, 2, 3, 3, 4, 4, 5 | |
161 }; | |
162 | |
163 buf_ptr = buf; | |
164 while (buf_size > 0) { | |
165 len = s->inbuf_ptr - s->inbuf; | |
166 if (s->frame_size == 0) { | |
167 /* no header seen : find one. We need at least 7 bytes to parse it */ | |
168 len = HEADER_SIZE - len; | |
169 if (len > buf_size) | |
170 len = buf_size; | |
171 memcpy(s->inbuf_ptr, buf_ptr, len); | |
172 buf_ptr += len; | |
173 s->inbuf_ptr += len; | |
174 buf_size -= len; | |
175 if ((s->inbuf_ptr - s->inbuf) == HEADER_SIZE) { | |
176 len = s->a52_syncinfo(s->inbuf, &s->flags, &sample_rate, &bit_rate); | |
177 if (len == 0) { | |
178 /* no sync found : move by one byte (inefficient, but simple!) */ | |
179 memcpy(s->inbuf, s->inbuf + 1, HEADER_SIZE - 1); | |
180 s->inbuf_ptr--; | |
181 } else { | |
182 s->frame_size = len; | |
183 /* update codec info */ | |
184 avctx->sample_rate = sample_rate; | |
185 s->channels = ac3_channels[s->flags & 7]; | |
186 if (s->flags & A52_LFE) | |
187 s->channels++; | |
188 if (avctx->channels == 0) | |
189 /* No specific number of channel requested */ | |
190 avctx->channels = s->channels; | |
191 else if (s->channels < avctx->channels) { | |
1602
fdb8244da1e5
av_log patch(2 of ?) by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1106
diff
changeset
|
192 av_log(avctx, AV_LOG_ERROR, "ac3dec: AC3 Source channels are less than specified: output to %d channels.. (frmsize: %d)\n", s->channels, len); |
332 | 193 avctx->channels = s->channels; |
194 } | |
195 avctx->bit_rate = bit_rate; | |
196 } | |
197 } | |
198 } else if (len < s->frame_size) { | |
199 len = s->frame_size - len; | |
200 if (len > buf_size) | |
201 len = buf_size; | |
202 | |
203 memcpy(s->inbuf_ptr, buf_ptr, len); | |
204 buf_ptr += len; | |
205 s->inbuf_ptr += len; | |
206 buf_size -= len; | |
207 } else { | |
208 flags = s->flags; | |
209 if (avctx->channels == 1) | |
210 flags = A52_MONO; | |
211 else if (avctx->channels == 2) | |
212 flags = A52_STEREO; | |
213 else | |
214 flags |= A52_ADJUST_LEVEL; | |
215 level = 1; | |
216 if (s->a52_frame(s->state, s->inbuf, &flags, &level, 384)) { | |
217 fail: | |
218 s->inbuf_ptr = s->inbuf; | |
219 s->frame_size = 0; | |
220 continue; | |
221 } | |
222 for (i = 0; i < 6; i++) { | |
223 if (s->a52_block(s->state)) | |
224 goto fail; | |
225 float_to_int(s->samples, out_samples + i * 256 * avctx->channels, avctx->channels); | |
226 } | |
227 s->inbuf_ptr = s->inbuf; | |
228 s->frame_size = 0; | |
1064 | 229 *data_size = 6 * avctx->channels * 256 * sizeof(int16_t); |
332 | 230 break; |
231 } | |
232 } | |
233 return buf_ptr - buf; | |
234 } | |
235 | |
236 static int a52_decode_end(AVCodecContext *avctx) | |
237 { | |
238 AC3DecodeState *s = avctx->priv_data; | |
239 s->a52_free(s->state); | |
338 | 240 #ifdef CONFIG_A52BIN |
332 | 241 dlclose(s->handle); |
242 #endif | |
243 return 0; | |
244 } | |
245 | |
246 AVCodec ac3_decoder = { | |
247 "ac3", | |
248 CODEC_TYPE_AUDIO, | |
249 CODEC_ID_AC3, | |
250 sizeof(AC3DecodeState), | |
251 a52_decode_init, | |
252 NULL, | |
253 a52_decode_end, | |
254 a52_decode_frame, | |
255 }; |