Mercurial > mplayer.hg
annotate libmpcodecs/dec_audio.c @ 25194:e816d546c4fe
ao_null: Make duration of "buffered" audio constant
Choose the "buffer size" for the amount of audio the driver accepts so
that it corresponds to about 0.2 seconds of playback based on the
number of channels, sample size and samplerate.
author | uau |
---|---|
date | Sat, 01 Dec 2007 01:39:39 +0000 |
parents | de251a0b5228 |
children | ca7e863c97bb |
rev | line source |
---|---|
5342 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 #include <unistd.h> | |
24892 | 4 #include <assert.h> |
5342 | 5 |
6 #include "config.h" | |
7 #include "mp_msg.h" | |
8 #include "help_mp.h" | |
9 | |
22599
4faee1254928
Add explicit location for headers from the stream/ directory.
diego
parents:
22180
diff
changeset
|
10 #include "stream/stream.h" |
22601
ed8f90096c65
Add explicit location for headers from the libmpdemux/ directory.
diego
parents:
22599
diff
changeset
|
11 #include "libmpdemux/demuxer.h" |
5342 | 12 |
13 #include "codec-cfg.h" | |
22601
ed8f90096c65
Add explicit location for headers from the libmpdemux/ directory.
diego
parents:
22599
diff
changeset
|
14 #include "libmpdemux/stheader.h" |
5342 | 15 |
16 #include "dec_audio.h" | |
17 #include "ad.h" | |
17012 | 18 #include "libaf/af_format.h" |
5342 | 19 |
17012 | 20 #include "libaf/af.h" |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
21 |
17635
db13b7295651
memalign segfaults when used without declaration on amd64 (default function return type is int so the pointer was trunctated to 32bits)
aurel
parents:
17625
diff
changeset
|
22 #ifdef HAVE_MALLOC_H |
db13b7295651
memalign segfaults when used without declaration on amd64 (default function return type is int so the pointer was trunctated to 32bits)
aurel
parents:
17625
diff
changeset
|
23 #include <malloc.h> |
db13b7295651
memalign segfaults when used without declaration on amd64 (default function return type is int so the pointer was trunctated to 32bits)
aurel
parents:
17625
diff
changeset
|
24 #endif |
db13b7295651
memalign segfaults when used without declaration on amd64 (default function return type is int so the pointer was trunctated to 32bits)
aurel
parents:
17625
diff
changeset
|
25 |
8152 | 26 #ifdef DYNAMIC_PLUGINS |
27 #include <dlfcn.h> | |
28 #endif | |
29 | |
5342 | 30 #ifdef USE_FAKE_MONO |
24883 | 31 int fakemono = 0; |
5342 | 32 #endif |
24883 | 33 |
5342 | 34 /* used for ac3surround decoder - set using -channels option */ |
35 int audio_output_channels = 2; | |
24883 | 36 af_cfg_t af_cfg = { 1, NULL }; // Configuration for audio filters |
5342 | 37 |
24883 | 38 void afm_help(void) |
39 { | |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
40 int i; |
24883 | 41 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_AvailableAudioFm); |
18237
4231482179b6
Get ride of the several if(identify) messy lines and rearangment of some of the output, both patches by Kiriuja mplayer-patches AT en-directo_net, his changes are barely unrelated, nevertheless Im commiting them thogeter just for the sake of my mental healt, I had both patches already applied on my local three
reynaldo
parents:
17635
diff
changeset
|
42 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_DRIVERS\n"); |
24883 | 43 mp_msg(MSGT_DECAUDIO, MSGL_INFO, " afm: info: (comment)\n"); |
44 for (i = 0; mpcodecs_ad_drivers[i] != NULL; i++) | |
45 if (mpcodecs_ad_drivers[i]->info->comment | |
46 && mpcodecs_ad_drivers[i]->info->comment[0]) | |
47 mp_msg(MSGT_DECAUDIO, MSGL_INFO, "%9s %s (%s)\n", | |
48 mpcodecs_ad_drivers[i]->info->short_name, | |
49 mpcodecs_ad_drivers[i]->info->name, | |
50 mpcodecs_ad_drivers[i]->info->comment); | |
51 else | |
52 mp_msg(MSGT_DECAUDIO, MSGL_INFO, "%9s %s\n", | |
53 mpcodecs_ad_drivers[i]->info->short_name, | |
54 mpcodecs_ad_drivers[i]->info->name); | |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
55 } |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
56 |
24885 | 57 static int init_audio_codec(sh_audio_t *sh_audio) |
5342 | 58 { |
24883 | 59 if ((af_cfg.force & AF_INIT_FORMAT_MASK) == AF_INIT_FLOAT) { |
60 int fmt = AF_FORMAT_FLOAT_NE; | |
61 if (sh_audio->ad_driver->control(sh_audio, ADCTRL_QUERY_FORMAT, | |
62 &fmt) == CONTROL_TRUE) { | |
63 sh_audio->sample_format = fmt; | |
64 sh_audio->samplesize = 4; | |
65 } | |
66 } | |
67 if (!sh_audio->ad_driver->preinit(sh_audio)) { | |
68 mp_msg(MSGT_DECAUDIO, MSGL_ERR, MSGTR_ADecoderPreinitFailed); | |
69 return 0; | |
70 } | |
5342 | 71 |
24883 | 72 /* allocate audio in buffer: */ |
73 if (sh_audio->audio_in_minsize > 0) { | |
74 sh_audio->a_in_buffer_size = sh_audio->audio_in_minsize; | |
75 mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_AllocatingBytesForInputBuffer, | |
76 sh_audio->a_in_buffer_size); | |
77 sh_audio->a_in_buffer = memalign(16, sh_audio->a_in_buffer_size); | |
78 memset(sh_audio->a_in_buffer, 0, sh_audio->a_in_buffer_size); | |
79 sh_audio->a_in_buffer_len = 0; | |
80 } | |
5458 | 81 |
24883 | 82 sh_audio->a_buffer_size = sh_audio->audio_out_minsize + MAX_OUTBURST; |
5342 | 83 |
24883 | 84 mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_AllocatingBytesForOutputBuffer, |
85 sh_audio->audio_out_minsize, MAX_OUTBURST, sh_audio->a_buffer_size); | |
5342 | 86 |
24883 | 87 sh_audio->a_buffer = memalign(16, sh_audio->a_buffer_size); |
88 if (!sh_audio->a_buffer) { | |
89 mp_msg(MSGT_DECAUDIO, MSGL_ERR, MSGTR_CantAllocAudioBuf); | |
90 return 0; | |
91 } | |
92 memset(sh_audio->a_buffer, 0, sh_audio->a_buffer_size); | |
93 sh_audio->a_buffer_len = 0; | |
5342 | 94 |
24883 | 95 if (!sh_audio->ad_driver->init(sh_audio)) { |
96 mp_msg(MSGT_DECAUDIO, MSGL_WARN, MSGTR_ADecoderInitFailed); | |
97 uninit_audio(sh_audio); // free buffers | |
98 return 0; | |
99 } | |
100 | |
101 sh_audio->inited = 1; | |
5458 | 102 |
24883 | 103 if (!sh_audio->channels || !sh_audio->samplerate) { |
104 mp_msg(MSGT_DECAUDIO, MSGL_WARN, MSGTR_UnknownAudio); | |
105 uninit_audio(sh_audio); // free buffers | |
106 return 0; | |
107 } | |
5342 | 108 |
24883 | 109 if (!sh_audio->o_bps) |
110 sh_audio->o_bps = sh_audio->channels * sh_audio->samplerate | |
111 * sh_audio->samplesize; | |
7522 | 112 |
24883 | 113 mp_msg(MSGT_DECAUDIO, MSGL_INFO, |
114 "AUDIO: %d Hz, %d ch, %s, %3.1f kbit/%3.2f%% (ratio: %d->%d)\n", | |
115 sh_audio->samplerate, sh_audio->channels, | |
116 af_fmt2str_short(sh_audio->sample_format), | |
117 sh_audio->i_bps * 8 * 0.001, | |
118 ((float) sh_audio->i_bps / sh_audio->o_bps) * 100.0, | |
119 sh_audio->i_bps, sh_audio->o_bps); | |
120 mp_msg(MSGT_IDENTIFY, MSGL_INFO, | |
121 "ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n", | |
122 sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels); | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
123 |
24884 | 124 sh_audio->a_out_buffer_size = 0; |
125 sh_audio->a_out_buffer = NULL; | |
126 sh_audio->a_out_buffer_len = 0; | |
24883 | 127 |
128 return 1; | |
5342 | 129 } |
130 | |
24885 | 131 static int init_audio(sh_audio_t *sh_audio, char *codecname, char *afm, |
132 int status) | |
24883 | 133 { |
134 unsigned int orig_fourcc = sh_audio->wf ? sh_audio->wf->wFormatTag : 0; | |
16321
efbfac98cab1
Allow forcing of demuxers and codecs by prepending '+'
reimar
parents:
16306
diff
changeset
|
135 int force = 0; |
efbfac98cab1
Allow forcing of demuxers and codecs by prepending '+'
reimar
parents:
16306
diff
changeset
|
136 if (codecname && codecname[0] == '+') { |
24883 | 137 codecname = &codecname[1]; |
138 force = 1; | |
16321
efbfac98cab1
Allow forcing of demuxers and codecs by prepending '+'
reimar
parents:
16306
diff
changeset
|
139 } |
24883 | 140 sh_audio->codec = NULL; |
141 while (1) { | |
142 ad_functions_t *mpadec; | |
7522 | 143 int i; |
14819
601e2c8a2922
Remove file-global mpadec, add ad_driver member to sh_audio_t instead.
hzoli
parents:
14818
diff
changeset
|
144 sh_audio->ad_driver = 0; |
7522 | 145 // restore original fourcc: |
24883 | 146 if (sh_audio->wf) |
147 sh_audio->wf->wFormatTag = i = orig_fourcc; | |
148 if (!(sh_audio->codec = find_audio_codec(sh_audio->format, | |
149 sh_audio->wf ? (&i) : NULL, | |
150 sh_audio->codec, force))) | |
151 break; | |
152 if (sh_audio->wf) | |
153 sh_audio->wf->wFormatTag = i; | |
7522 | 154 // ok we found one codec |
24883 | 155 if (sh_audio->codec->flags & CODECS_FLAG_SELECTED) |
156 continue; // already tried & failed | |
157 if (codecname && strcmp(sh_audio->codec->name, codecname)) | |
158 continue; // -ac | |
159 if (afm && strcmp(sh_audio->codec->drv, afm)) | |
160 continue; // afm doesn't match | |
161 if (!force && sh_audio->codec->status < status) | |
162 continue; // too unstable | |
163 sh_audio->codec->flags |= CODECS_FLAG_SELECTED; // tagging it | |
7522 | 164 // ok, it matches all rules, let's find the driver! |
24883 | 165 for (i = 0; mpcodecs_ad_drivers[i] != NULL; i++) |
166 if (!strcmp(mpcodecs_ad_drivers[i]->info->short_name, | |
167 sh_audio->codec->drv)) | |
168 break; | |
169 mpadec = mpcodecs_ad_drivers[i]; | |
8152 | 170 #ifdef DYNAMIC_PLUGINS |
24883 | 171 if (!mpadec) { |
8152 | 172 /* try to open shared decoder plugin */ |
173 int buf_len; | |
174 char *buf; | |
175 ad_functions_t *funcs_sym; | |
176 ad_info_t *info_sym; | |
24883 | 177 |
178 buf_len = | |
179 strlen(MPLAYER_LIBDIR) + strlen(sh_audio->codec->drv) + 16; | |
8152 | 180 buf = malloc(buf_len); |
181 if (!buf) | |
182 break; | |
24883 | 183 snprintf(buf, buf_len, "%s/mplayer/ad_%s.so", MPLAYER_LIBDIR, |
184 sh_audio->codec->drv); | |
185 mp_msg(MSGT_DECAUDIO, MSGL_DBG2, | |
186 "Trying to open external plugin: %s\n", buf); | |
8152 | 187 sh_audio->dec_handle = dlopen(buf, RTLD_LAZY); |
188 if (!sh_audio->dec_handle) | |
189 break; | |
190 snprintf(buf, buf_len, "mpcodecs_ad_%s", sh_audio->codec->drv); | |
191 funcs_sym = dlsym(sh_audio->dec_handle, buf); | |
24883 | 192 if (!funcs_sym || !funcs_sym->info || !funcs_sym->preinit |
193 || !funcs_sym->init || !funcs_sym->uninit | |
194 || !funcs_sym->control || !funcs_sym->decode_audio) | |
8152 | 195 break; |
196 info_sym = funcs_sym->info; | |
197 if (strcmp(info_sym->short_name, sh_audio->codec->drv)) | |
198 break; | |
199 free(buf); | |
200 mpadec = funcs_sym; | |
24883 | 201 mp_msg(MSGT_DECAUDIO, MSGL_V, |
202 "Using external decoder plugin (%s/mplayer/ad_%s.so)!\n", | |
203 MPLAYER_LIBDIR, sh_audio->codec->drv); | |
8152 | 204 } |
205 #endif | |
24883 | 206 if (!mpadec) { // driver not available (==compiled in) |
207 mp_msg(MSGT_DECAUDIO, MSGL_ERR, | |
208 MSGTR_AudioCodecFamilyNotAvailableStr, | |
209 sh_audio->codec->name, sh_audio->codec->drv); | |
7522 | 210 continue; |
211 } | |
212 // it's available, let's try to init! | |
213 // init() | |
24883 | 214 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_OpeningAudioDecoder, |
215 mpadec->info->short_name, mpadec->info->name); | |
14819
601e2c8a2922
Remove file-global mpadec, add ad_driver member to sh_audio_t instead.
hzoli
parents:
14818
diff
changeset
|
216 sh_audio->ad_driver = mpadec; |
24883 | 217 if (!init_audio_codec(sh_audio)) { |
218 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_ADecoderInitFailed); | |
219 continue; // try next... | |
7522 | 220 } |
221 // Yeah! We got it! | |
222 return 1; | |
223 } | |
224 return 0; | |
225 } | |
226 | |
24883 | 227 int init_best_audio_codec(sh_audio_t *sh_audio, char **audio_codec_list, |
228 char **audio_fm_list) | |
229 { | |
230 char *ac_l_default[2] = { "", (char *) NULL }; | |
231 // hack: | |
232 if (!audio_codec_list) | |
233 audio_codec_list = ac_l_default; | |
234 // Go through the codec.conf and find the best codec... | |
235 sh_audio->inited = 0; | |
236 codecs_reset_selection(1); | |
237 while (!sh_audio->inited && *audio_codec_list) { | |
238 char *audio_codec = *(audio_codec_list++); | |
239 if (audio_codec[0]) { | |
240 if (audio_codec[0] == '-') { | |
241 // disable this codec: | |
242 select_codec(audio_codec + 1, 1); | |
243 } else { | |
244 // forced codec by name: | |
245 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_ForcedAudioCodec, | |
246 audio_codec); | |
247 init_audio(sh_audio, audio_codec, NULL, -1); | |
248 } | |
249 } else { | |
250 int status; | |
251 // try in stability order: UNTESTED, WORKING, BUGGY. | |
252 // never try CRASHING. | |
253 if (audio_fm_list) { | |
254 char **fmlist = audio_fm_list; | |
255 // try first the preferred codec families: | |
256 while (!sh_audio->inited && *fmlist) { | |
257 char *audio_fm = *(fmlist++); | |
258 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_TryForceAudioFmtStr, | |
259 audio_fm); | |
260 for (status = CODECS_STATUS__MAX; | |
261 status >= CODECS_STATUS__MIN; --status) | |
262 if (init_audio(sh_audio, NULL, audio_fm, status)) | |
263 break; | |
264 } | |
265 } | |
266 if (!sh_audio->inited) | |
267 for (status = CODECS_STATUS__MAX; status >= CODECS_STATUS__MIN; | |
268 --status) | |
269 if (init_audio(sh_audio, NULL, NULL, status)) | |
270 break; | |
271 } | |
7522 | 272 } |
24883 | 273 |
274 if (!sh_audio->inited) { | |
275 mp_msg(MSGT_DECAUDIO, MSGL_ERR, MSGTR_CantFindAudioCodec, | |
276 sh_audio->format); | |
277 mp_msg(MSGT_DECAUDIO, MSGL_HINT, MSGTR_RTFMCodecs); | |
278 return 0; // failed | |
7522 | 279 } |
280 | |
24883 | 281 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_SelectedAudioCodec, |
282 sh_audio->codec->name, sh_audio->codec->drv, sh_audio->codec->info); | |
283 return 1; // success | |
7522 | 284 } |
285 | |
5342 | 286 void uninit_audio(sh_audio_t *sh_audio) |
287 { | |
24883 | 288 if (sh_audio->afilter) { |
289 mp_msg(MSGT_DECAUDIO, MSGL_V, "Uninit audio filters...\n"); | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
290 af_uninit(sh_audio->afilter); |
10803 | 291 free(sh_audio->afilter); |
24883 | 292 sh_audio->afilter = NULL; |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
293 } |
24883 | 294 if (sh_audio->inited) { |
295 mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_UninitAudioStr, | |
296 sh_audio->codec->drv); | |
14819
601e2c8a2922
Remove file-global mpadec, add ad_driver member to sh_audio_t instead.
hzoli
parents:
14818
diff
changeset
|
297 sh_audio->ad_driver->uninit(sh_audio); |
8152 | 298 #ifdef DYNAMIC_PLUGINS |
299 if (sh_audio->dec_handle) | |
300 dlclose(sh_audio->dec_handle); | |
301 #endif | |
24883 | 302 sh_audio->inited = 0; |
7240 | 303 } |
24884 | 304 free(sh_audio->a_out_buffer); |
24883 | 305 sh_audio->a_out_buffer = NULL; |
306 sh_audio->a_out_buffer_size = 0; | |
307 if (sh_audio->a_buffer) | |
308 free(sh_audio->a_buffer); | |
309 sh_audio->a_buffer = NULL; | |
310 if (sh_audio->a_in_buffer) | |
311 free(sh_audio->a_in_buffer); | |
312 sh_audio->a_in_buffer = NULL; | |
5342 | 313 } |
314 | |
24883 | 315 |
316 int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, | |
24894 | 317 int *out_samplerate, int *out_channels, int *out_format) |
24883 | 318 { |
319 af_stream_t *afs = sh_audio->afilter; | |
320 if (!afs) { | |
321 afs = malloc(sizeof(af_stream_t)); | |
322 memset(afs, 0, sizeof(af_stream_t)); | |
323 } | |
324 // input format: same as codec's output format: | |
325 afs->input.rate = in_samplerate; | |
24894 | 326 afs->input.nch = sh_audio->channels; |
327 afs->input.format = sh_audio->sample_format; | |
24883 | 328 af_fix_parameters(&(afs->input)); |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
329 |
24883 | 330 // output format: same as ao driver's input format (if missing, fallback to input) |
331 afs->output.rate = *out_samplerate; | |
332 afs->output.nch = *out_channels; | |
333 afs->output.format = *out_format; | |
334 af_fix_parameters(&(afs->output)); | |
335 | |
336 // filter config: | |
337 memcpy(&afs->cfg, &af_cfg, sizeof(af_cfg_t)); | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
338 |
24883 | 339 mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_BuildingAudioFilterChain, |
340 afs->input.rate, afs->input.nch, | |
341 af_fmt2str_short(afs->input.format), afs->output.rate, | |
342 afs->output.nch, af_fmt2str_short(afs->output.format)); | |
343 | |
344 // let's autoprobe it! | |
345 if (0 != af_init(afs)) { | |
346 sh_audio->afilter = NULL; | |
347 free(afs); | |
348 return 0; // failed :( | |
349 } | |
350 | |
351 *out_samplerate = afs->output.rate; | |
352 *out_channels = afs->output.nch; | |
353 *out_format = afs->output.format; | |
15811
9b4bbb6098f6
make -srate work again, unify audio filter init and preinit.
reimar
parents:
15789
diff
changeset
|
354 |
24893 | 355 sh_audio->a_out_buffer_len = 0; |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
356 |
24883 | 357 // ok! |
358 sh_audio->afilter = (void *) afs; | |
359 return 1; | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
360 } |
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
361 |
24892 | 362 static int filter_n_bytes(sh_audio_t *sh, int len) |
5342 | 363 { |
24892 | 364 assert(len-1 + sh->audio_out_minsize <= sh->a_buffer_size); |
365 | |
366 int error = 0; | |
367 | |
368 // Decode more bytes if needed | |
369 while (sh->a_buffer_len < len) { | |
370 unsigned char *buf = sh->a_buffer + sh->a_buffer_len; | |
371 int minlen = len - sh->a_buffer_len; | |
372 int maxlen = sh->a_buffer_size - sh->a_buffer_len; | |
373 int ret = sh->ad_driver->decode_audio(sh, buf, minlen, maxlen); | |
374 if (ret <= 0) { | |
375 error = -1; | |
376 len = sh->a_buffer_len; | |
377 break; | |
378 } | |
379 sh->a_buffer_len += ret; | |
380 } | |
24883 | 381 |
24892 | 382 // Filter |
383 af_data_t filter_input = { | |
384 .audio = sh->a_buffer, | |
385 .len = len, | |
386 .rate = sh->samplerate, | |
387 .nch = sh->channels, | |
388 .format = sh->sample_format | |
389 }; | |
390 af_fix_parameters(&filter_input); | |
391 af_data_t *filter_output = af_play(sh->afilter, &filter_input); | |
392 if (!filter_output) | |
393 return -1; | |
394 if (sh->a_out_buffer_size < sh->a_out_buffer_len + filter_output->len) { | |
395 int newlen = sh->a_out_buffer_len + filter_output->len; | |
396 mp_msg(MSGT_DECAUDIO, MSGL_V, "Increasing filtered audio buffer size " | |
397 "from %d to %d\n", sh->a_out_buffer_size, newlen); | |
398 sh->a_out_buffer = realloc(sh->a_out_buffer, newlen); | |
399 sh->a_out_buffer_size = newlen; | |
400 } | |
401 memcpy(sh->a_out_buffer + sh->a_out_buffer_len, filter_output->audio, | |
402 filter_output->len); | |
403 sh->a_out_buffer_len += filter_output->len; | |
404 | |
405 // remove processed data from decoder buffer: | |
406 sh->a_buffer_len -= len; | |
407 memmove(sh->a_buffer, sh->a_buffer + len, sh->a_buffer_len); | |
408 | |
409 return error; | |
410 } | |
411 | |
412 /* Try to get at least minlen decoded+filtered bytes in sh_audio->a_out_buffer | |
413 * (total length including possible existing data). | |
414 * Return 0 on success, -1 on error/EOF (not distinguished). | |
415 * In the former case sh_audio->a_out_buffer_len is always >= minlen | |
416 * on return. In case of EOF/error it might or might not be. | |
417 * Can reallocate sh_audio->a_out_buffer if needed to fit all filter output. */ | |
418 int decode_audio(sh_audio_t *sh_audio, int minlen) | |
419 { | |
24961 | 420 // Indicates that a filter seems to be buffering large amounts of data |
421 int huge_filter_buffer = 0; | |
24892 | 422 // Decoded audio must be cut at boundaries of this many bytes |
423 int unitsize = sh_audio->channels * sh_audio->samplesize; | |
424 | |
425 /* Filter output size will be about filter_multiplier times input size. | |
426 * If some filter buffers audio in big blocks this might only hold | |
427 * as average over time. */ | |
428 double filter_multiplier = af_calc_filter_multiplier(sh_audio->afilter); | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
429 |
24892 | 430 /* If the decoder set audio_out_minsize then it can do the equivalent of |
431 * "while (output_len < target_len) output_len += audio_out_minsize;", | |
432 * so we must guarantee there is at least audio_out_minsize-1 bytes | |
433 * more space in the output buffer than the minimum length we try to | |
434 * decode. */ | |
435 int max_decode_len = sh_audio->a_buffer_size - sh_audio->audio_out_minsize; | |
436 max_decode_len -= max_decode_len % unitsize; | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
437 |
24892 | 438 while (sh_audio->a_out_buffer_len < minlen) { |
439 int declen = (minlen - sh_audio->a_out_buffer_len) / filter_multiplier | |
440 + (unitsize << 5); // some extra for possible filter buffering | |
24961 | 441 if (huge_filter_buffer) |
24892 | 442 /* Some filter must be doing significant buffering if the estimated |
443 * input length didn't produce enough output from filters. | |
444 * Feed the filters 2k bytes at a time until we have enough output. | |
445 * Very small amounts could make filtering inefficient while large | |
446 * amounts can make MPlayer demux the file unnecessarily far ahead | |
447 * to get audio data and buffer video frames in memory while doing | |
448 * so. However the performance impact of either is probably not too | |
449 * significant as long as the value is not completely insane. */ | |
24961 | 450 declen = 2000; |
24892 | 451 declen -= declen % unitsize; |
24961 | 452 if (declen > max_decode_len) |
453 declen = max_decode_len; | |
454 else | |
455 /* if this iteration does not fill buffer, we must have lots | |
456 * of buffering in filters */ | |
457 huge_filter_buffer = 1; | |
458 if (filter_n_bytes(sh_audio, declen) < 0) | |
459 return -1; | |
24883 | 460 } |
24892 | 461 return 0; |
5342 | 462 } |
463 | |
464 void resync_audio_stream(sh_audio_t *sh_audio) | |
465 { | |
24883 | 466 sh_audio->a_in_buffer_len = 0; // clear audio input buffer |
467 if (!sh_audio->inited) | |
468 return; | |
469 sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL); | |
5342 | 470 } |
471 | |
472 void skip_audio_frame(sh_audio_t *sh_audio) | |
473 { | |
24883 | 474 if (!sh_audio->inited) |
475 return; | |
476 if (sh_audio->ad_driver->control(sh_audio, ADCTRL_SKIP_FRAME, NULL) == | |
477 CONTROL_TRUE) | |
478 return; | |
479 // default skip code: | |
480 ds_fill_buffer(sh_audio->ds); // skip block | |
5342 | 481 } |