Mercurial > libavcodec.hg
annotate liba52.c @ 5876:731ee5ad6bde libavcodec
Correct assignment of interlaced_frame; was being set on output frames,
in display order, based on decoding information in decoding order. Now
set properly, immediately upon completion of decode.
Based on original patch from Reinhard Nissl, rnisssl % gmx , de
Original Thread: [FFmpeg-devel] H.264 + PAFF: BBC HD recording shows
extreme interlacing artefacts, Thu, 01 Nov 2007 22:43:09
author | heydowns |
---|---|
date | Mon, 05 Nov 2007 18:16:42 +0000 |
parents | bc4791868c52 |
children | f6b691720c7d |
rev | line source |
---|---|
332 | 1 /* |
4617 | 2 * A52 decoder using liba52 |
429 | 3 * Copyright (c) 2001 Fabrice Bellard. |
332 | 4 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
429 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
332 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
332 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
429 | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Lesser General Public License for more details. | |
332 | 16 * |
429 | 17 * You should have received a copy of the GNU Lesser General Public |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
332 | 20 */ |
1106 | 21 |
22 /** | |
23 * @file a52dec.c | |
4617 | 24 * A52 decoder using liba52 |
1106 | 25 */ |
26 | |
332 | 27 #include "avcodec.h" |
4511
91872ae737b2
Remove internal liba52; external lib still works, native decoder coming up.
diego
parents:
4356
diff
changeset
|
28 #include <a52dec/a52.h> |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
29 |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
30 #ifdef CONFIG_LIBA52BIN |
332 | 31 #include <dlfcn.h> |
32 static const char* liba52name = "liba52.so.0"; | |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
33 #endif |
332 | 34 |
35 /** | |
36 * liba52 - Copyright (C) Aaron Holtzman | |
37 * released under the GPL license. | |
38 */ | |
39 typedef struct AC3DecodeState { | |
1064 | 40 uint8_t inbuf[4096]; /* input buffer */ |
41 uint8_t *inbuf_ptr; | |
332 | 42 int frame_size; |
43 int flags; | |
44 int channels; | |
45 a52_state_t* state; | |
46 sample_t* samples; | |
47 | |
48 /* | |
49 * virtual method table | |
50 * | |
51 * using this function table so the liba52 doesn't | |
52 * have to be really linked together with ffmpeg | |
53 * and might be linked in runtime - this allows binary | |
54 * distribution of ffmpeg library which doens't depend | |
55 * on liba52 library - but if user has it installed | |
56 * it will be used - user might install such library | |
57 * separately | |
58 */ | |
59 void* handle; | |
60 a52_state_t* (*a52_init)(uint32_t mm_accel); | |
61 sample_t* (*a52_samples)(a52_state_t * state); | |
62 int (*a52_syncinfo)(uint8_t * buf, int * flags, | |
2979 | 63 int * sample_rate, int * bit_rate); |
332 | 64 int (*a52_frame)(a52_state_t * state, uint8_t * buf, int * flags, |
2979 | 65 sample_t * level, sample_t bias); |
332 | 66 void (*a52_dynrng)(a52_state_t * state, |
2979 | 67 sample_t (* call) (sample_t, void *), void * data); |
332 | 68 int (*a52_block)(a52_state_t * state); |
69 void (*a52_free)(a52_state_t * state); | |
70 | |
71 } AC3DecodeState; | |
72 | |
4618
bb06df70f857
Add proper #idef to dlsymm call, also fixes an unresolved symbol on OS X 10.2.
diego
parents:
4617
diff
changeset
|
73 #ifdef CONFIG_LIBA52BIN |
332 | 74 static void* dlsymm(void* handle, const char* symbol) |
75 { | |
76 void* f = dlsym(handle, symbol); | |
77 if (!f) | |
2846
40765c51a7a9
Compilation fixes part 1 patch by (Arvind R. and Burkhard Plaum, plaum, ipf uni-stuttgart de)
michael
parents:
2028
diff
changeset
|
78 av_log( NULL, AV_LOG_ERROR, "A52 Decoder - function '%s' can't be resolved\n", symbol); |
332 | 79 return f; |
80 } | |
4618
bb06df70f857
Add proper #idef to dlsymm call, also fixes an unresolved symbol on OS X 10.2.
diego
parents:
4617
diff
changeset
|
81 #endif |
332 | 82 |
83 static int a52_decode_init(AVCodecContext *avctx) | |
84 { | |
85 AC3DecodeState *s = avctx->priv_data; | |
86 | |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
87 #ifdef CONFIG_LIBA52BIN |
332 | 88 s->handle = dlopen(liba52name, RTLD_LAZY); |
89 if (!s->handle) | |
90 { | |
2846
40765c51a7a9
Compilation fixes part 1 patch by (Arvind R. and Burkhard Plaum, plaum, ipf uni-stuttgart de)
michael
parents:
2028
diff
changeset
|
91 av_log( avctx, AV_LOG_ERROR, "A52 library %s could not be opened! \n%s\n", liba52name, dlerror()); |
332 | 92 return -1; |
93 } | |
94 s->a52_init = (a52_state_t* (*)(uint32_t)) dlsymm(s->handle, "a52_init"); | |
95 s->a52_samples = (sample_t* (*)(a52_state_t*)) dlsymm(s->handle, "a52_samples"); | |
96 s->a52_syncinfo = (int (*)(uint8_t*, int*, int*, int*)) dlsymm(s->handle, "a52_syncinfo"); | |
97 s->a52_frame = (int (*)(a52_state_t*, uint8_t*, int*, sample_t*, sample_t)) dlsymm(s->handle, "a52_frame"); | |
98 s->a52_block = (int (*)(a52_state_t*)) dlsymm(s->handle, "a52_block"); | |
99 s->a52_free = (void (*)(a52_state_t*)) dlsymm(s->handle, "a52_free"); | |
100 if (!s->a52_init || !s->a52_samples || !s->a52_syncinfo | |
101 || !s->a52_frame || !s->a52_block || !s->a52_free) | |
102 { | |
2979 | 103 dlclose(s->handle); |
332 | 104 return -1; |
105 } | |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
106 #else |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
107 s->handle = 0; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
108 s->a52_init = a52_init; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
109 s->a52_samples = a52_samples; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
110 s->a52_syncinfo = a52_syncinfo; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
111 s->a52_frame = a52_frame; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
112 s->a52_block = a52_block; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
113 s->a52_free = a52_free; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
114 #endif |
332 | 115 s->state = s->a52_init(0); /* later use CPU flags */ |
116 s->samples = s->a52_samples(s->state); | |
117 s->inbuf_ptr = s->inbuf; | |
118 s->frame_size = 0; | |
119 | |
120 return 0; | |
121 } | |
122 | |
5525
bc4791868c52
various simplifications around recent av_clip_int16() usage
aurel
parents:
5523
diff
changeset
|
123 /**** the following function comes from a52dec */ |
1064 | 124 static inline void float_to_int (float * _f, int16_t * s16, int nchannels) |
332 | 125 { |
126 int i, j, c; | |
2979 | 127 int32_t * f = (int32_t *) _f; // XXX assumes IEEE float format |
332 | 128 |
129 j = 0; | |
130 nchannels *= 256; | |
131 for (i = 0; i < 256; i++) { | |
2979 | 132 for (c = 0; c < nchannels; c += 256) |
5525
bc4791868c52
various simplifications around recent av_clip_int16() usage
aurel
parents:
5523
diff
changeset
|
133 s16[j++] = av_clip_int16(f[i + c] - 0x43c00000); |
332 | 134 } |
135 } | |
136 | |
137 /**** end */ | |
138 | |
139 #define HEADER_SIZE 7 | |
140 | |
141 static int a52_decode_frame(AVCodecContext *avctx, | |
142 void *data, int *data_size, | |
1064 | 143 uint8_t *buf, int buf_size) |
332 | 144 { |
145 AC3DecodeState *s = avctx->priv_data; | |
1064 | 146 uint8_t *buf_ptr; |
332 | 147 int flags, i, len; |
148 int sample_rate, bit_rate; | |
149 short *out_samples = data; | |
150 float level; | |
151 static const int ac3_channels[8] = { | |
2979 | 152 2, 1, 2, 3, 3, 4, 4, 5 |
332 | 153 }; |
154 | |
4356
c8bc01fee409
set data_size to 0 so that in case we return without setting it nothing funny can happen
michael
parents:
4343
diff
changeset
|
155 *data_size= 0; |
c8bc01fee409
set data_size to 0 so that in case we return without setting it nothing funny can happen
michael
parents:
4343
diff
changeset
|
156 |
332 | 157 buf_ptr = buf; |
158 while (buf_size > 0) { | |
159 len = s->inbuf_ptr - s->inbuf; | |
160 if (s->frame_size == 0) { | |
161 /* no header seen : find one. We need at least 7 bytes to parse it */ | |
162 len = HEADER_SIZE - len; | |
163 if (len > buf_size) | |
164 len = buf_size; | |
165 memcpy(s->inbuf_ptr, buf_ptr, len); | |
166 buf_ptr += len; | |
167 s->inbuf_ptr += len; | |
168 buf_size -= len; | |
169 if ((s->inbuf_ptr - s->inbuf) == HEADER_SIZE) { | |
170 len = s->a52_syncinfo(s->inbuf, &s->flags, &sample_rate, &bit_rate); | |
171 if (len == 0) { | |
172 /* no sync found : move by one byte (inefficient, but simple!) */ | |
173 memcpy(s->inbuf, s->inbuf + 1, HEADER_SIZE - 1); | |
174 s->inbuf_ptr--; | |
175 } else { | |
2979 | 176 s->frame_size = len; |
332 | 177 /* update codec info */ |
178 avctx->sample_rate = sample_rate; | |
179 s->channels = ac3_channels[s->flags & 7]; | |
180 if (s->flags & A52_LFE) | |
2979 | 181 s->channels++; |
182 if (avctx->channels == 0) | |
183 /* No specific number of channel requested */ | |
184 avctx->channels = s->channels; | |
185 else if (s->channels < avctx->channels) { | |
186 av_log(avctx, AV_LOG_ERROR, "ac3dec: AC3 Source channels are less than specified: output to %d channels.. (frmsize: %d)\n", s->channels, len); | |
187 avctx->channels = s->channels; | |
188 } | |
189 avctx->bit_rate = bit_rate; | |
332 | 190 } |
191 } | |
192 } else if (len < s->frame_size) { | |
193 len = s->frame_size - len; | |
194 if (len > buf_size) | |
195 len = buf_size; | |
196 | |
197 memcpy(s->inbuf_ptr, buf_ptr, len); | |
198 buf_ptr += len; | |
199 s->inbuf_ptr += len; | |
200 buf_size -= len; | |
201 } else { | |
202 flags = s->flags; | |
203 if (avctx->channels == 1) | |
204 flags = A52_MONO; | |
205 else if (avctx->channels == 2) | |
206 flags = A52_STEREO; | |
207 else | |
208 flags |= A52_ADJUST_LEVEL; | |
209 level = 1; | |
210 if (s->a52_frame(s->state, s->inbuf, &flags, &level, 384)) { | |
211 fail: | |
4343 | 212 av_log(avctx, AV_LOG_ERROR, "Error decoding frame\n"); |
332 | 213 s->inbuf_ptr = s->inbuf; |
214 s->frame_size = 0; | |
215 continue; | |
216 } | |
217 for (i = 0; i < 6; i++) { | |
218 if (s->a52_block(s->state)) | |
219 goto fail; | |
220 float_to_int(s->samples, out_samples + i * 256 * avctx->channels, avctx->channels); | |
221 } | |
222 s->inbuf_ptr = s->inbuf; | |
223 s->frame_size = 0; | |
1064 | 224 *data_size = 6 * avctx->channels * 256 * sizeof(int16_t); |
332 | 225 break; |
226 } | |
227 } | |
228 return buf_ptr - buf; | |
229 } | |
230 | |
231 static int a52_decode_end(AVCodecContext *avctx) | |
232 { | |
233 AC3DecodeState *s = avctx->priv_data; | |
234 s->a52_free(s->state); | |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
235 #ifdef CONFIG_LIBA52BIN |
332 | 236 dlclose(s->handle); |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
237 #endif |
332 | 238 return 0; |
239 } | |
240 | |
4513
3367310f8460
Rename ac3 decoder to liba52 to prepare for native decoder.
diego
parents:
4511
diff
changeset
|
241 AVCodec liba52_decoder = { |
5102
4323e587708d
Give names of external library decoders/encoders a lib prefix
diego
parents:
5101
diff
changeset
|
242 "liba52", |
332 | 243 CODEC_TYPE_AUDIO, |
244 CODEC_ID_AC3, | |
245 sizeof(AC3DecodeState), | |
246 a52_decode_init, | |
247 NULL, | |
248 a52_decode_end, | |
249 a52_decode_frame, | |
250 }; |