Mercurial > mplayer.hg
annotate libmpcodecs/dec_audio.c @ 36963:e539d330c7be
Remove unnecessary bounds checks in Win32 GUI.
The checks that the rendered potmeter button
doesn't exceed the bounds is not necessary as
the item value is already limited within the
range of 0 to 100.
Patch by Hans-Dieter Kosch, hdkosch kabelbw de.
author | ib |
---|---|
date | Mon, 24 Mar 2014 12:52:01 +0000 |
parents | d29d116c0818 |
children |
rev | line source |
---|---|
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
1 /* |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
2 * This file is part of MPlayer. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
3 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
4 * MPlayer is free software; you can redistribute it and/or modify |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
5 * it under the terms of the GNU General Public License as published by |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
6 * the Free Software Foundation; either version 2 of the License, or |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
7 * (at your option) any later version. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
8 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
9 * MPlayer is distributed in the hope that it will be useful, |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
12 * GNU General Public License for more details. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
13 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
14 * You should have received a copy of the GNU General Public License along |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
15 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
17 */ |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30378
diff
changeset
|
18 |
5342 | 19 #include <stdio.h> |
20 #include <stdlib.h> | |
21 #include <unistd.h> | |
24892 | 22 #include <assert.h> |
5342 | 23 |
24 #include "config.h" | |
25 #include "mp_msg.h" | |
26 #include "help_mp.h" | |
27 | |
22599
4faee1254928
Add explicit location for headers from the stream/ directory.
diego
parents:
22180
diff
changeset
|
28 #include "stream/stream.h" |
22601
ed8f90096c65
Add explicit location for headers from the libmpdemux/ directory.
diego
parents:
22599
diff
changeset
|
29 #include "libmpdemux/demuxer.h" |
5342 | 30 |
31 #include "codec-cfg.h" | |
22601
ed8f90096c65
Add explicit location for headers from the libmpdemux/ directory.
diego
parents:
22599
diff
changeset
|
32 #include "libmpdemux/stheader.h" |
5342 | 33 |
34 #include "dec_audio.h" | |
35 #include "ad.h" | |
17012 | 36 #include "libaf/af_format.h" |
5342 | 37 |
17012 | 38 #include "libaf/af.h" |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
39 |
27397
d47744b95b78
Give a CONFIG_ prefix to preprocessor directives that lacked one and
diego
parents:
27341
diff
changeset
|
40 #ifdef CONFIG_DYNAMIC_PLUGINS |
8152 | 41 #include <dlfcn.h> |
42 #endif | |
43 | |
27341
e7c989f7a7c9
Start unifying names of internal preprocessor directives.
diego
parents:
27249
diff
changeset
|
44 #ifdef CONFIG_FAKE_MONO |
24883 | 45 int fakemono = 0; |
5342 | 46 #endif |
24883 | 47 |
5342 | 48 /* used for ac3surround decoder - set using -channels option */ |
49 int audio_output_channels = 2; | |
24883 | 50 af_cfg_t af_cfg = { 1, NULL }; // Configuration for audio filters |
5342 | 51 |
24883 | 52 void afm_help(void) |
53 { | |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
54 int i; |
24883 | 55 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
|
56 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_DRIVERS\n"); |
24883 | 57 mp_msg(MSGT_DECAUDIO, MSGL_INFO, " afm: info: (comment)\n"); |
58 for (i = 0; mpcodecs_ad_drivers[i] != NULL; i++) | |
59 if (mpcodecs_ad_drivers[i]->info->comment | |
60 && mpcodecs_ad_drivers[i]->info->comment[0]) | |
61 mp_msg(MSGT_DECAUDIO, MSGL_INFO, "%9s %s (%s)\n", | |
62 mpcodecs_ad_drivers[i]->info->short_name, | |
63 mpcodecs_ad_drivers[i]->info->name, | |
64 mpcodecs_ad_drivers[i]->info->comment); | |
65 else | |
66 mp_msg(MSGT_DECAUDIO, MSGL_INFO, "%9s %s\n", | |
67 mpcodecs_ad_drivers[i]->info->short_name, | |
68 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
|
69 } |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
70 |
24885 | 71 static int init_audio_codec(sh_audio_t *sh_audio) |
5342 | 72 { |
24883 | 73 if ((af_cfg.force & AF_INIT_FORMAT_MASK) == AF_INIT_FLOAT) { |
74 int fmt = AF_FORMAT_FLOAT_NE; | |
75 if (sh_audio->ad_driver->control(sh_audio, ADCTRL_QUERY_FORMAT, | |
76 &fmt) == CONTROL_TRUE) { | |
77 sh_audio->sample_format = fmt; | |
78 sh_audio->samplesize = 4; | |
79 } | |
80 } | |
81 if (!sh_audio->ad_driver->preinit(sh_audio)) { | |
82 mp_msg(MSGT_DECAUDIO, MSGL_ERR, MSGTR_ADecoderPreinitFailed); | |
83 return 0; | |
84 } | |
5342 | 85 |
24883 | 86 /* allocate audio in buffer: */ |
87 if (sh_audio->audio_in_minsize > 0) { | |
88 sh_audio->a_in_buffer_size = sh_audio->audio_in_minsize; | |
33827
277ec491a8a7
Do not translate console messages of verbosity level MSGL_V and above.
diego
parents:
32727
diff
changeset
|
89 mp_msg(MSGT_DECAUDIO, MSGL_V, "dec_audio: Allocating %d bytes for input buffer.\n", |
24883 | 90 sh_audio->a_in_buffer_size); |
27765
03bb6c3945ff
Use av_malloc/av_free for audio-related buffers to avoid crashes due to
reimar
parents:
27397
diff
changeset
|
91 sh_audio->a_in_buffer = av_mallocz(sh_audio->a_in_buffer_size); |
24883 | 92 sh_audio->a_in_buffer_len = 0; |
93 } | |
5458 | 94 |
24883 | 95 sh_audio->a_buffer_size = sh_audio->audio_out_minsize + MAX_OUTBURST; |
5342 | 96 |
33827
277ec491a8a7
Do not translate console messages of verbosity level MSGL_V and above.
diego
parents:
32727
diff
changeset
|
97 mp_msg(MSGT_DECAUDIO, MSGL_V, "dec_audio: Allocating %d + %d = %d bytes for output buffer.\n", |
24883 | 98 sh_audio->audio_out_minsize, MAX_OUTBURST, sh_audio->a_buffer_size); |
5342 | 99 |
27765
03bb6c3945ff
Use av_malloc/av_free for audio-related buffers to avoid crashes due to
reimar
parents:
27397
diff
changeset
|
100 sh_audio->a_buffer = av_mallocz(sh_audio->a_buffer_size); |
24883 | 101 if (!sh_audio->a_buffer) { |
102 mp_msg(MSGT_DECAUDIO, MSGL_ERR, MSGTR_CantAllocAudioBuf); | |
103 return 0; | |
104 } | |
105 sh_audio->a_buffer_len = 0; | |
5342 | 106 |
24883 | 107 if (!sh_audio->ad_driver->init(sh_audio)) { |
108 mp_msg(MSGT_DECAUDIO, MSGL_WARN, MSGTR_ADecoderInitFailed); | |
109 uninit_audio(sh_audio); // free buffers | |
110 return 0; | |
111 } | |
112 | |
25962 | 113 sh_audio->initialized = 1; |
5458 | 114 |
24883 | 115 if (!sh_audio->channels || !sh_audio->samplerate) { |
116 mp_msg(MSGT_DECAUDIO, MSGL_WARN, MSGTR_UnknownAudio); | |
117 uninit_audio(sh_audio); // free buffers | |
118 return 0; | |
119 } | |
5342 | 120 |
24883 | 121 if (!sh_audio->o_bps) |
122 sh_audio->o_bps = sh_audio->channels * sh_audio->samplerate | |
123 * sh_audio->samplesize; | |
7522 | 124 |
24883 | 125 mp_msg(MSGT_DECAUDIO, MSGL_INFO, |
126 "AUDIO: %d Hz, %d ch, %s, %3.1f kbit/%3.2f%% (ratio: %d->%d)\n", | |
127 sh_audio->samplerate, sh_audio->channels, | |
128 af_fmt2str_short(sh_audio->sample_format), | |
129 sh_audio->i_bps * 8 * 0.001, | |
130 ((float) sh_audio->i_bps / sh_audio->o_bps) * 100.0, | |
131 sh_audio->i_bps, sh_audio->o_bps); | |
132 mp_msg(MSGT_IDENTIFY, MSGL_INFO, | |
133 "ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n", | |
134 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
|
135 |
24884 | 136 sh_audio->a_out_buffer_size = 0; |
137 sh_audio->a_out_buffer = NULL; | |
138 sh_audio->a_out_buffer_len = 0; | |
24883 | 139 |
140 return 1; | |
5342 | 141 } |
142 | |
24885 | 143 static int init_audio(sh_audio_t *sh_audio, char *codecname, char *afm, |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
144 int status, stringset_t *selected) |
24883 | 145 { |
146 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
|
147 int force = 0; |
efbfac98cab1
Allow forcing of demuxers and codecs by prepending '+'
reimar
parents:
16306
diff
changeset
|
148 if (codecname && codecname[0] == '+') { |
24883 | 149 codecname = &codecname[1]; |
150 force = 1; | |
16321
efbfac98cab1
Allow forcing of demuxers and codecs by prepending '+'
reimar
parents:
16306
diff
changeset
|
151 } |
24883 | 152 sh_audio->codec = NULL; |
153 while (1) { | |
31540
7f1c8212e3cf
Add some const, the ad_functions structs are in rodata.
reimar
parents:
30421
diff
changeset
|
154 const ad_functions_t *mpadec; |
7522 | 155 int i; |
14819
601e2c8a2922
Remove file-global mpadec, add ad_driver member to sh_audio_t instead.
hzoli
parents:
14818
diff
changeset
|
156 sh_audio->ad_driver = 0; |
7522 | 157 // restore original fourcc: |
24883 | 158 if (sh_audio->wf) |
159 sh_audio->wf->wFormatTag = i = orig_fourcc; | |
160 if (!(sh_audio->codec = find_audio_codec(sh_audio->format, | |
161 sh_audio->wf ? (&i) : NULL, | |
162 sh_audio->codec, force))) | |
163 break; | |
164 if (sh_audio->wf) | |
165 sh_audio->wf->wFormatTag = i; | |
7522 | 166 // ok we found one codec |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
167 if (stringset_test(selected, sh_audio->codec->name)) |
24883 | 168 continue; // already tried & failed |
169 if (codecname && strcmp(sh_audio->codec->name, codecname)) | |
170 continue; // -ac | |
171 if (afm && strcmp(sh_audio->codec->drv, afm)) | |
172 continue; // afm doesn't match | |
173 if (!force && sh_audio->codec->status < status) | |
174 continue; // too unstable | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
175 stringset_add(selected, sh_audio->codec->name); // tagging it |
7522 | 176 // ok, it matches all rules, let's find the driver! |
24883 | 177 for (i = 0; mpcodecs_ad_drivers[i] != NULL; i++) |
178 if (!strcmp(mpcodecs_ad_drivers[i]->info->short_name, | |
179 sh_audio->codec->drv)) | |
180 break; | |
181 mpadec = mpcodecs_ad_drivers[i]; | |
27397
d47744b95b78
Give a CONFIG_ prefix to preprocessor directives that lacked one and
diego
parents:
27341
diff
changeset
|
182 #ifdef CONFIG_DYNAMIC_PLUGINS |
24883 | 183 if (!mpadec) { |
8152 | 184 /* try to open shared decoder plugin */ |
185 int buf_len; | |
186 char *buf; | |
187 ad_functions_t *funcs_sym; | |
188 ad_info_t *info_sym; | |
24883 | 189 |
190 buf_len = | |
191 strlen(MPLAYER_LIBDIR) + strlen(sh_audio->codec->drv) + 16; | |
8152 | 192 buf = malloc(buf_len); |
193 if (!buf) | |
194 break; | |
24883 | 195 snprintf(buf, buf_len, "%s/mplayer/ad_%s.so", MPLAYER_LIBDIR, |
196 sh_audio->codec->drv); | |
197 mp_msg(MSGT_DECAUDIO, MSGL_DBG2, | |
198 "Trying to open external plugin: %s\n", buf); | |
8152 | 199 sh_audio->dec_handle = dlopen(buf, RTLD_LAZY); |
200 if (!sh_audio->dec_handle) | |
201 break; | |
202 snprintf(buf, buf_len, "mpcodecs_ad_%s", sh_audio->codec->drv); | |
203 funcs_sym = dlsym(sh_audio->dec_handle, buf); | |
24883 | 204 if (!funcs_sym || !funcs_sym->info || !funcs_sym->preinit |
205 || !funcs_sym->init || !funcs_sym->uninit | |
206 || !funcs_sym->control || !funcs_sym->decode_audio) | |
8152 | 207 break; |
208 info_sym = funcs_sym->info; | |
209 if (strcmp(info_sym->short_name, sh_audio->codec->drv)) | |
210 break; | |
211 free(buf); | |
212 mpadec = funcs_sym; | |
24883 | 213 mp_msg(MSGT_DECAUDIO, MSGL_V, |
214 "Using external decoder plugin (%s/mplayer/ad_%s.so)!\n", | |
215 MPLAYER_LIBDIR, sh_audio->codec->drv); | |
8152 | 216 } |
217 #endif | |
24883 | 218 if (!mpadec) { // driver not available (==compiled in) |
219 mp_msg(MSGT_DECAUDIO, MSGL_ERR, | |
220 MSGTR_AudioCodecFamilyNotAvailableStr, | |
221 sh_audio->codec->name, sh_audio->codec->drv); | |
7522 | 222 continue; |
223 } | |
35304 | 224 /* only allow dummy codecs if specified via -ac */ |
225 if (sh_audio->codec->flags & CODECS_FLAG_DUMMY && !codecname) { | |
226 continue; | |
227 } | |
228 | |
7522 | 229 // it's available, let's try to init! |
230 // init() | |
24883 | 231 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_OpeningAudioDecoder, |
232 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
|
233 sh_audio->ad_driver = mpadec; |
24883 | 234 if (!init_audio_codec(sh_audio)) { |
235 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_ADecoderInitFailed); | |
236 continue; // try next... | |
7522 | 237 } |
238 // Yeah! We got it! | |
239 return 1; | |
240 } | |
241 return 0; | |
242 } | |
243 | |
24883 | 244 int init_best_audio_codec(sh_audio_t *sh_audio, char **audio_codec_list, |
245 char **audio_fm_list) | |
246 { | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
247 stringset_t selected; |
24883 | 248 char *ac_l_default[2] = { "", (char *) NULL }; |
249 // hack: | |
250 if (!audio_codec_list) | |
251 audio_codec_list = ac_l_default; | |
252 // Go through the codec.conf and find the best codec... | |
25962 | 253 sh_audio->initialized = 0; |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
254 stringset_init(&selected); |
25962 | 255 while (!sh_audio->initialized && *audio_codec_list) { |
24883 | 256 char *audio_codec = *(audio_codec_list++); |
257 if (audio_codec[0]) { | |
258 if (audio_codec[0] == '-') { | |
259 // disable this codec: | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
260 stringset_add(&selected, audio_codec + 1); |
24883 | 261 } else { |
262 // forced codec by name: | |
263 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_ForcedAudioCodec, | |
264 audio_codec); | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
265 init_audio(sh_audio, audio_codec, NULL, -1, &selected); |
24883 | 266 } |
267 } else { | |
268 int status; | |
269 // try in stability order: UNTESTED, WORKING, BUGGY. | |
270 // never try CRASHING. | |
271 if (audio_fm_list) { | |
272 char **fmlist = audio_fm_list; | |
273 // try first the preferred codec families: | |
25962 | 274 while (!sh_audio->initialized && *fmlist) { |
24883 | 275 char *audio_fm = *(fmlist++); |
276 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_TryForceAudioFmtStr, | |
277 audio_fm); | |
278 for (status = CODECS_STATUS__MAX; | |
279 status >= CODECS_STATUS__MIN; --status) | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
280 if (init_audio(sh_audio, NULL, audio_fm, status, &selected)) |
24883 | 281 break; |
282 } | |
283 } | |
25962 | 284 if (!sh_audio->initialized) |
24883 | 285 for (status = CODECS_STATUS__MAX; status >= CODECS_STATUS__MIN; |
286 --status) | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
287 if (init_audio(sh_audio, NULL, NULL, status, &selected)) |
24883 | 288 break; |
289 } | |
7522 | 290 } |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
291 stringset_free(&selected); |
24883 | 292 |
25962 | 293 if (!sh_audio->initialized) { |
24883 | 294 mp_msg(MSGT_DECAUDIO, MSGL_ERR, MSGTR_CantFindAudioCodec, |
295 sh_audio->format); | |
296 return 0; // failed | |
7522 | 297 } |
298 | |
24883 | 299 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_SelectedAudioCodec, |
300 sh_audio->codec->name, sh_audio->codec->drv, sh_audio->codec->info); | |
301 return 1; // success | |
7522 | 302 } |
303 | |
5342 | 304 void uninit_audio(sh_audio_t *sh_audio) |
305 { | |
24883 | 306 if (sh_audio->afilter) { |
307 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
|
308 af_uninit(sh_audio->afilter); |
10803 | 309 free(sh_audio->afilter); |
24883 | 310 sh_audio->afilter = NULL; |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
311 } |
25962 | 312 if (sh_audio->initialized) { |
33827
277ec491a8a7
Do not translate console messages of verbosity level MSGL_V and above.
diego
parents:
32727
diff
changeset
|
313 mp_msg(MSGT_DECAUDIO, MSGL_V, "Uninit audio: %s\n", |
24883 | 314 sh_audio->codec->drv); |
14819
601e2c8a2922
Remove file-global mpadec, add ad_driver member to sh_audio_t instead.
hzoli
parents:
14818
diff
changeset
|
315 sh_audio->ad_driver->uninit(sh_audio); |
27397
d47744b95b78
Give a CONFIG_ prefix to preprocessor directives that lacked one and
diego
parents:
27341
diff
changeset
|
316 #ifdef CONFIG_DYNAMIC_PLUGINS |
8152 | 317 if (sh_audio->dec_handle) |
318 dlclose(sh_audio->dec_handle); | |
319 #endif | |
25962 | 320 sh_audio->initialized = 0; |
7240 | 321 } |
24884 | 322 free(sh_audio->a_out_buffer); |
24883 | 323 sh_audio->a_out_buffer = NULL; |
324 sh_audio->a_out_buffer_size = 0; | |
27765
03bb6c3945ff
Use av_malloc/av_free for audio-related buffers to avoid crashes due to
reimar
parents:
27397
diff
changeset
|
325 av_freep(&sh_audio->a_buffer); |
03bb6c3945ff
Use av_malloc/av_free for audio-related buffers to avoid crashes due to
reimar
parents:
27397
diff
changeset
|
326 av_freep(&sh_audio->a_in_buffer); |
5342 | 327 } |
328 | |
24883 | 329 |
330 int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, | |
24894 | 331 int *out_samplerate, int *out_channels, int *out_format) |
24883 | 332 { |
333 af_stream_t *afs = sh_audio->afilter; | |
334 if (!afs) { | |
335 afs = malloc(sizeof(af_stream_t)); | |
336 memset(afs, 0, sizeof(af_stream_t)); | |
337 } | |
338 // input format: same as codec's output format: | |
339 afs->input.rate = in_samplerate; | |
24894 | 340 afs->input.nch = sh_audio->channels; |
341 afs->input.format = sh_audio->sample_format; | |
24883 | 342 af_fix_parameters(&(afs->input)); |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
343 |
24883 | 344 // output format: same as ao driver's input format (if missing, fallback to input) |
345 afs->output.rate = *out_samplerate; | |
346 afs->output.nch = *out_channels; | |
347 afs->output.format = *out_format; | |
348 af_fix_parameters(&(afs->output)); | |
349 | |
350 // filter config: | |
351 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
|
352 |
33827
277ec491a8a7
Do not translate console messages of verbosity level MSGL_V and above.
diego
parents:
32727
diff
changeset
|
353 mp_msg(MSGT_DECAUDIO, MSGL_V, |
277ec491a8a7
Do not translate console messages of verbosity level MSGL_V and above.
diego
parents:
32727
diff
changeset
|
354 "Building audio filter chain for %dHz/%dch/%s -> %dHz/%dch/%s...\n", |
24883 | 355 afs->input.rate, afs->input.nch, |
356 af_fmt2str_short(afs->input.format), afs->output.rate, | |
357 afs->output.nch, af_fmt2str_short(afs->output.format)); | |
358 | |
359 // let's autoprobe it! | |
360 if (0 != af_init(afs)) { | |
361 sh_audio->afilter = NULL; | |
362 free(afs); | |
363 return 0; // failed :( | |
364 } | |
365 | |
366 *out_samplerate = afs->output.rate; | |
367 *out_channels = afs->output.nch; | |
368 *out_format = afs->output.format; | |
15811
9b4bbb6098f6
make -srate work again, unify audio filter init and preinit.
reimar
parents:
15789
diff
changeset
|
369 |
32727
470867f7e1df
Remove resetting of a_out_buffer_len in init_audio_filters.
reimar
parents:
31977
diff
changeset
|
370 // Do not reset a_out_buffer_len. This may cause some |
470867f7e1df
Remove resetting of a_out_buffer_len in init_audio_filters.
reimar
parents:
31977
diff
changeset
|
371 // glitches/slow adaption of changes but it is better than |
470867f7e1df
Remove resetting of a_out_buffer_len in init_audio_filters.
reimar
parents:
31977
diff
changeset
|
372 // losing audio even for minor adjustments and avoids sync issues. |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
373 |
24883 | 374 // ok! |
375 sh_audio->afilter = (void *) afs; | |
376 return 1; | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
377 } |
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
378 |
24892 | 379 static int filter_n_bytes(sh_audio_t *sh, int len) |
5342 | 380 { |
25252 | 381 int error = 0; |
25253 | 382 // Filter |
383 af_data_t filter_input = { | |
384 .audio = sh->a_buffer, | |
385 .rate = sh->samplerate, | |
386 .nch = sh->channels, | |
387 .format = sh->sample_format | |
388 }; | |
389 af_data_t *filter_output; | |
24892 | 390 |
25252 | 391 assert(len-1 + sh->audio_out_minsize <= sh->a_buffer_size); |
24892 | 392 |
393 // Decode more bytes if needed | |
394 while (sh->a_buffer_len < len) { | |
395 unsigned char *buf = sh->a_buffer + sh->a_buffer_len; | |
396 int minlen = len - sh->a_buffer_len; | |
397 int maxlen = sh->a_buffer_size - sh->a_buffer_len; | |
398 int ret = sh->ad_driver->decode_audio(sh, buf, minlen, maxlen); | |
31671
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
399 int format_change = sh->samplerate != filter_input.rate || |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
400 sh->channels != filter_input.nch || |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
401 sh->sample_format != filter_input.format; |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
402 if (ret <= 0 || format_change) { |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
403 error = format_change ? -2 : -1; |
24892 | 404 len = sh->a_buffer_len; |
405 break; | |
406 } | |
407 sh->a_buffer_len += ret; | |
408 } | |
24883 | 409 |
25254 | 410 filter_input.len = len; |
24892 | 411 af_fix_parameters(&filter_input); |
25253 | 412 filter_output = af_play(sh->afilter, &filter_input); |
24892 | 413 if (!filter_output) |
414 return -1; | |
415 if (sh->a_out_buffer_size < sh->a_out_buffer_len + filter_output->len) { | |
416 int newlen = sh->a_out_buffer_len + filter_output->len; | |
417 mp_msg(MSGT_DECAUDIO, MSGL_V, "Increasing filtered audio buffer size " | |
418 "from %d to %d\n", sh->a_out_buffer_size, newlen); | |
419 sh->a_out_buffer = realloc(sh->a_out_buffer, newlen); | |
420 sh->a_out_buffer_size = newlen; | |
421 } | |
422 memcpy(sh->a_out_buffer + sh->a_out_buffer_len, filter_output->audio, | |
423 filter_output->len); | |
424 sh->a_out_buffer_len += filter_output->len; | |
425 | |
426 // remove processed data from decoder buffer: | |
427 sh->a_buffer_len -= len; | |
428 memmove(sh->a_buffer, sh->a_buffer + len, sh->a_buffer_len); | |
429 | |
430 return error; | |
431 } | |
432 | |
433 /* Try to get at least minlen decoded+filtered bytes in sh_audio->a_out_buffer | |
434 * (total length including possible existing data). | |
435 * Return 0 on success, -1 on error/EOF (not distinguished). | |
436 * In the former case sh_audio->a_out_buffer_len is always >= minlen | |
437 * on return. In case of EOF/error it might or might not be. | |
438 * Can reallocate sh_audio->a_out_buffer if needed to fit all filter output. */ | |
31977 | 439 int mp_decode_audio(sh_audio_t *sh_audio, int minlen) |
24892 | 440 { |
24961 | 441 // Indicates that a filter seems to be buffering large amounts of data |
442 int huge_filter_buffer = 0; | |
24892 | 443 // Decoded audio must be cut at boundaries of this many bytes |
27249 | 444 int unitsize = sh_audio->channels * sh_audio->samplesize * 16; |
24892 | 445 |
446 /* Filter output size will be about filter_multiplier times input size. | |
447 * If some filter buffers audio in big blocks this might only hold | |
448 * as average over time. */ | |
449 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
|
450 |
24892 | 451 /* If the decoder set audio_out_minsize then it can do the equivalent of |
452 * "while (output_len < target_len) output_len += audio_out_minsize;", | |
453 * so we must guarantee there is at least audio_out_minsize-1 bytes | |
454 * more space in the output buffer than the minimum length we try to | |
455 * decode. */ | |
456 int max_decode_len = sh_audio->a_buffer_size - sh_audio->audio_out_minsize; | |
34650
dc78fbe1f17f
Add a safeguard to avoid crash if the decoder e.g. claims 0 channels.
reimar
parents:
33827
diff
changeset
|
457 if (!unitsize) |
dc78fbe1f17f
Add a safeguard to avoid crash if the decoder e.g. claims 0 channels.
reimar
parents:
33827
diff
changeset
|
458 return -1; |
24892 | 459 max_decode_len -= max_decode_len % unitsize; |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
460 |
24892 | 461 while (sh_audio->a_out_buffer_len < minlen) { |
31671
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
462 int res; |
24892 | 463 int declen = (minlen - sh_audio->a_out_buffer_len) / filter_multiplier |
464 + (unitsize << 5); // some extra for possible filter buffering | |
24961 | 465 if (huge_filter_buffer) |
24892 | 466 /* Some filter must be doing significant buffering if the estimated |
467 * input length didn't produce enough output from filters. | |
468 * Feed the filters 2k bytes at a time until we have enough output. | |
469 * Very small amounts could make filtering inefficient while large | |
470 * amounts can make MPlayer demux the file unnecessarily far ahead | |
471 * to get audio data and buffer video frames in memory while doing | |
472 * so. However the performance impact of either is probably not too | |
473 * significant as long as the value is not completely insane. */ | |
24961 | 474 declen = 2000; |
24892 | 475 declen -= declen % unitsize; |
24961 | 476 if (declen > max_decode_len) |
477 declen = max_decode_len; | |
478 else | |
479 /* if this iteration does not fill buffer, we must have lots | |
480 * of buffering in filters */ | |
481 huge_filter_buffer = 1; | |
31671
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
482 res = filter_n_bytes(sh_audio, declen); |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
483 if (res < 0) |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
484 return res; |
24883 | 485 } |
24892 | 486 return 0; |
5342 | 487 } |
488 | |
489 void resync_audio_stream(sh_audio_t *sh_audio) | |
490 { | |
30378
8339bca8e4b4
Move the resync-related code into more consistent places instead of having it
reimar
parents:
29168
diff
changeset
|
491 sh_audio->a_buffer_len = 0; |
8339bca8e4b4
Move the resync-related code into more consistent places instead of having it
reimar
parents:
29168
diff
changeset
|
492 sh_audio->a_out_buffer_len = 0; |
24883 | 493 sh_audio->a_in_buffer_len = 0; // clear audio input buffer |
25962 | 494 if (!sh_audio->initialized) |
24883 | 495 return; |
496 sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL); | |
5342 | 497 } |
498 | |
499 void skip_audio_frame(sh_audio_t *sh_audio) | |
500 { | |
25962 | 501 if (!sh_audio->initialized) |
24883 | 502 return; |
503 if (sh_audio->ad_driver->control(sh_audio, ADCTRL_SKIP_FRAME, NULL) == | |
504 CONTROL_TRUE) | |
505 return; | |
506 // default skip code: | |
507 ds_fill_buffer(sh_audio->ds); // skip block | |
5342 | 508 } |