Mercurial > mplayer.hg
annotate libmpcodecs/dec_audio.c @ 33307:552f1f7731c8
Set GUI initialization flag earlier.
So far, the flag is set after the call of guiInit(), but there are calls
to GUI functions (like reading the GUI config) before that. As MPlayer
(when exiting) only calls GUI's cleanup function guiDone() if the flag
is set, it neglects calling guiDone() on any error between the first GUI
function call and execution of guiInit(). Now the flag is set before the
first GUI function call.
As a result, GUI's own exit function (also used for fatal GUI errors, and
thus also for errors occurring before guiInit() properly finishes) doesn't
have to handle cleanup any longer. The code can be moved to guiDone().
author | ib |
---|---|
date | Sat, 07 May 2011 15:30:14 +0000 |
parents | 470867f7e1df |
children | 277ec491a8a7 |
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; | |
89 mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_AllocatingBytesForInputBuffer, | |
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 |
24883 | 97 mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_AllocatingBytesForOutputBuffer, |
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 } | |
224 // it's available, let's try to init! | |
225 // init() | |
24883 | 226 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_OpeningAudioDecoder, |
227 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
|
228 sh_audio->ad_driver = mpadec; |
24883 | 229 if (!init_audio_codec(sh_audio)) { |
230 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_ADecoderInitFailed); | |
231 continue; // try next... | |
7522 | 232 } |
233 // Yeah! We got it! | |
234 return 1; | |
235 } | |
236 return 0; | |
237 } | |
238 | |
24883 | 239 int init_best_audio_codec(sh_audio_t *sh_audio, char **audio_codec_list, |
240 char **audio_fm_list) | |
241 { | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
242 stringset_t selected; |
24883 | 243 char *ac_l_default[2] = { "", (char *) NULL }; |
244 // hack: | |
245 if (!audio_codec_list) | |
246 audio_codec_list = ac_l_default; | |
247 // Go through the codec.conf and find the best codec... | |
25962 | 248 sh_audio->initialized = 0; |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
249 stringset_init(&selected); |
25962 | 250 while (!sh_audio->initialized && *audio_codec_list) { |
24883 | 251 char *audio_codec = *(audio_codec_list++); |
252 if (audio_codec[0]) { | |
253 if (audio_codec[0] == '-') { | |
254 // disable this codec: | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
255 stringset_add(&selected, audio_codec + 1); |
24883 | 256 } else { |
257 // forced codec by name: | |
258 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_ForcedAudioCodec, | |
259 audio_codec); | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
260 init_audio(sh_audio, audio_codec, NULL, -1, &selected); |
24883 | 261 } |
262 } else { | |
263 int status; | |
264 // try in stability order: UNTESTED, WORKING, BUGGY. | |
265 // never try CRASHING. | |
266 if (audio_fm_list) { | |
267 char **fmlist = audio_fm_list; | |
268 // try first the preferred codec families: | |
25962 | 269 while (!sh_audio->initialized && *fmlist) { |
24883 | 270 char *audio_fm = *(fmlist++); |
271 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_TryForceAudioFmtStr, | |
272 audio_fm); | |
273 for (status = CODECS_STATUS__MAX; | |
274 status >= CODECS_STATUS__MIN; --status) | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
275 if (init_audio(sh_audio, NULL, audio_fm, status, &selected)) |
24883 | 276 break; |
277 } | |
278 } | |
25962 | 279 if (!sh_audio->initialized) |
24883 | 280 for (status = CODECS_STATUS__MAX; status >= CODECS_STATUS__MIN; |
281 --status) | |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
282 if (init_audio(sh_audio, NULL, NULL, status, &selected)) |
24883 | 283 break; |
284 } | |
7522 | 285 } |
25661
293aeec83153
Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with
reimar
parents:
25254
diff
changeset
|
286 stringset_free(&selected); |
24883 | 287 |
25962 | 288 if (!sh_audio->initialized) { |
24883 | 289 mp_msg(MSGT_DECAUDIO, MSGL_ERR, MSGTR_CantFindAudioCodec, |
290 sh_audio->format); | |
291 return 0; // failed | |
7522 | 292 } |
293 | |
24883 | 294 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_SelectedAudioCodec, |
295 sh_audio->codec->name, sh_audio->codec->drv, sh_audio->codec->info); | |
296 return 1; // success | |
7522 | 297 } |
298 | |
5342 | 299 void uninit_audio(sh_audio_t *sh_audio) |
300 { | |
24883 | 301 if (sh_audio->afilter) { |
302 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
|
303 af_uninit(sh_audio->afilter); |
10803 | 304 free(sh_audio->afilter); |
24883 | 305 sh_audio->afilter = NULL; |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
306 } |
25962 | 307 if (sh_audio->initialized) { |
24883 | 308 mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_UninitAudioStr, |
309 sh_audio->codec->drv); | |
14819
601e2c8a2922
Remove file-global mpadec, add ad_driver member to sh_audio_t instead.
hzoli
parents:
14818
diff
changeset
|
310 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
|
311 #ifdef CONFIG_DYNAMIC_PLUGINS |
8152 | 312 if (sh_audio->dec_handle) |
313 dlclose(sh_audio->dec_handle); | |
314 #endif | |
25962 | 315 sh_audio->initialized = 0; |
7240 | 316 } |
24884 | 317 free(sh_audio->a_out_buffer); |
24883 | 318 sh_audio->a_out_buffer = NULL; |
319 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
|
320 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
|
321 av_freep(&sh_audio->a_in_buffer); |
5342 | 322 } |
323 | |
24883 | 324 |
325 int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, | |
24894 | 326 int *out_samplerate, int *out_channels, int *out_format) |
24883 | 327 { |
328 af_stream_t *afs = sh_audio->afilter; | |
329 if (!afs) { | |
330 afs = malloc(sizeof(af_stream_t)); | |
331 memset(afs, 0, sizeof(af_stream_t)); | |
332 } | |
333 // input format: same as codec's output format: | |
334 afs->input.rate = in_samplerate; | |
24894 | 335 afs->input.nch = sh_audio->channels; |
336 afs->input.format = sh_audio->sample_format; | |
24883 | 337 af_fix_parameters(&(afs->input)); |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
338 |
24883 | 339 // output format: same as ao driver's input format (if missing, fallback to input) |
340 afs->output.rate = *out_samplerate; | |
341 afs->output.nch = *out_channels; | |
342 afs->output.format = *out_format; | |
343 af_fix_parameters(&(afs->output)); | |
344 | |
345 // filter config: | |
346 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
|
347 |
24883 | 348 mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_BuildingAudioFilterChain, |
349 afs->input.rate, afs->input.nch, | |
350 af_fmt2str_short(afs->input.format), afs->output.rate, | |
351 afs->output.nch, af_fmt2str_short(afs->output.format)); | |
352 | |
353 // let's autoprobe it! | |
354 if (0 != af_init(afs)) { | |
355 sh_audio->afilter = NULL; | |
356 free(afs); | |
357 return 0; // failed :( | |
358 } | |
359 | |
360 *out_samplerate = afs->output.rate; | |
361 *out_channels = afs->output.nch; | |
362 *out_format = afs->output.format; | |
15811
9b4bbb6098f6
make -srate work again, unify audio filter init and preinit.
reimar
parents:
15789
diff
changeset
|
363 |
32727
470867f7e1df
Remove resetting of a_out_buffer_len in init_audio_filters.
reimar
parents:
31977
diff
changeset
|
364 // 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
|
365 // 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
|
366 // 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
|
367 |
24883 | 368 // ok! |
369 sh_audio->afilter = (void *) afs; | |
370 return 1; | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
371 } |
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
372 |
24892 | 373 static int filter_n_bytes(sh_audio_t *sh, int len) |
5342 | 374 { |
25252 | 375 int error = 0; |
25253 | 376 // Filter |
377 af_data_t filter_input = { | |
378 .audio = sh->a_buffer, | |
379 .rate = sh->samplerate, | |
380 .nch = sh->channels, | |
381 .format = sh->sample_format | |
382 }; | |
383 af_data_t *filter_output; | |
24892 | 384 |
25252 | 385 assert(len-1 + sh->audio_out_minsize <= sh->a_buffer_size); |
24892 | 386 |
387 // Decode more bytes if needed | |
388 while (sh->a_buffer_len < len) { | |
389 unsigned char *buf = sh->a_buffer + sh->a_buffer_len; | |
390 int minlen = len - sh->a_buffer_len; | |
391 int maxlen = sh->a_buffer_size - sh->a_buffer_len; | |
392 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
|
393 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
|
394 sh->channels != filter_input.nch || |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
395 sh->sample_format != filter_input.format; |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
396 if (ret <= 0 || format_change) { |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
397 error = format_change ? -2 : -1; |
24892 | 398 len = sh->a_buffer_len; |
399 break; | |
400 } | |
401 sh->a_buffer_len += ret; | |
402 } | |
24883 | 403 |
25254 | 404 filter_input.len = len; |
24892 | 405 af_fix_parameters(&filter_input); |
25253 | 406 filter_output = af_play(sh->afilter, &filter_input); |
24892 | 407 if (!filter_output) |
408 return -1; | |
409 if (sh->a_out_buffer_size < sh->a_out_buffer_len + filter_output->len) { | |
410 int newlen = sh->a_out_buffer_len + filter_output->len; | |
411 mp_msg(MSGT_DECAUDIO, MSGL_V, "Increasing filtered audio buffer size " | |
412 "from %d to %d\n", sh->a_out_buffer_size, newlen); | |
413 sh->a_out_buffer = realloc(sh->a_out_buffer, newlen); | |
414 sh->a_out_buffer_size = newlen; | |
415 } | |
416 memcpy(sh->a_out_buffer + sh->a_out_buffer_len, filter_output->audio, | |
417 filter_output->len); | |
418 sh->a_out_buffer_len += filter_output->len; | |
419 | |
420 // remove processed data from decoder buffer: | |
421 sh->a_buffer_len -= len; | |
422 memmove(sh->a_buffer, sh->a_buffer + len, sh->a_buffer_len); | |
423 | |
424 return error; | |
425 } | |
426 | |
427 /* Try to get at least minlen decoded+filtered bytes in sh_audio->a_out_buffer | |
428 * (total length including possible existing data). | |
429 * Return 0 on success, -1 on error/EOF (not distinguished). | |
430 * In the former case sh_audio->a_out_buffer_len is always >= minlen | |
431 * on return. In case of EOF/error it might or might not be. | |
432 * Can reallocate sh_audio->a_out_buffer if needed to fit all filter output. */ | |
31977 | 433 int mp_decode_audio(sh_audio_t *sh_audio, int minlen) |
24892 | 434 { |
24961 | 435 // Indicates that a filter seems to be buffering large amounts of data |
436 int huge_filter_buffer = 0; | |
24892 | 437 // Decoded audio must be cut at boundaries of this many bytes |
27249 | 438 int unitsize = sh_audio->channels * sh_audio->samplesize * 16; |
24892 | 439 |
440 /* Filter output size will be about filter_multiplier times input size. | |
441 * If some filter buffers audio in big blocks this might only hold | |
442 * as average over time. */ | |
443 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
|
444 |
24892 | 445 /* If the decoder set audio_out_minsize then it can do the equivalent of |
446 * "while (output_len < target_len) output_len += audio_out_minsize;", | |
447 * so we must guarantee there is at least audio_out_minsize-1 bytes | |
448 * more space in the output buffer than the minimum length we try to | |
449 * decode. */ | |
450 int max_decode_len = sh_audio->a_buffer_size - sh_audio->audio_out_minsize; | |
451 max_decode_len -= max_decode_len % unitsize; | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
452 |
24892 | 453 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
|
454 int res; |
24892 | 455 int declen = (minlen - sh_audio->a_out_buffer_len) / filter_multiplier |
456 + (unitsize << 5); // some extra for possible filter buffering | |
24961 | 457 if (huge_filter_buffer) |
24892 | 458 /* Some filter must be doing significant buffering if the estimated |
459 * input length didn't produce enough output from filters. | |
460 * Feed the filters 2k bytes at a time until we have enough output. | |
461 * Very small amounts could make filtering inefficient while large | |
462 * amounts can make MPlayer demux the file unnecessarily far ahead | |
463 * to get audio data and buffer video frames in memory while doing | |
464 * so. However the performance impact of either is probably not too | |
465 * significant as long as the value is not completely insane. */ | |
24961 | 466 declen = 2000; |
24892 | 467 declen -= declen % unitsize; |
24961 | 468 if (declen > max_decode_len) |
469 declen = max_decode_len; | |
470 else | |
471 /* if this iteration does not fill buffer, we must have lots | |
472 * of buffering in filters */ | |
473 huge_filter_buffer = 1; | |
31671
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
474 res = filter_n_bytes(sh_audio, declen); |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
475 if (res < 0) |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
476 return res; |
24883 | 477 } |
24892 | 478 return 0; |
5342 | 479 } |
480 | |
481 void resync_audio_stream(sh_audio_t *sh_audio) | |
482 { | |
30378
8339bca8e4b4
Move the resync-related code into more consistent places instead of having it
reimar
parents:
29168
diff
changeset
|
483 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
|
484 sh_audio->a_out_buffer_len = 0; |
24883 | 485 sh_audio->a_in_buffer_len = 0; // clear audio input buffer |
25962 | 486 if (!sh_audio->initialized) |
24883 | 487 return; |
488 sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL); | |
5342 | 489 } |
490 | |
491 void skip_audio_frame(sh_audio_t *sh_audio) | |
492 { | |
25962 | 493 if (!sh_audio->initialized) |
24883 | 494 return; |
495 if (sh_audio->ad_driver->control(sh_audio, ADCTRL_SKIP_FRAME, NULL) == | |
496 CONTROL_TRUE) | |
497 return; | |
498 // default skip code: | |
499 ds_fill_buffer(sh_audio->ds); // skip block | |
5342 | 500 } |