Mercurial > mplayer.hg
annotate libmpcodecs/dec_audio.c @ 34757:da38eb1e2069
subassconvert: handle "\r\n" line ends
Previously the code converting text subtitles to ASS format converted newline
characters, and only those, to ASS "new line" markup. If the subtitles
contained "\r\n", the "\r" was thus left in the text. In previous libass
versions the "\r" was not visible, but in the current one it produces an empty
box. Improve the conversion to remove the "\r" in that case. Also treat a lone
"\r" as a newline.
Picked from mplayer2/3e0a2705
author | cboesch |
---|---|
date | Sat, 07 Apr 2012 11:17:09 +0000 |
parents | dc78fbe1f17f |
children | d29d116c0818 |
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 } | |
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) { |
33827
277ec491a8a7
Do not translate console messages of verbosity level MSGL_V and above.
diego
parents:
32727
diff
changeset
|
308 mp_msg(MSGT_DECAUDIO, MSGL_V, "Uninit audio: %s\n", |
24883 | 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 |
33827
277ec491a8a7
Do not translate console messages of verbosity level MSGL_V and above.
diego
parents:
32727
diff
changeset
|
348 mp_msg(MSGT_DECAUDIO, MSGL_V, |
277ec491a8a7
Do not translate console messages of verbosity level MSGL_V and above.
diego
parents:
32727
diff
changeset
|
349 "Building audio filter chain for %dHz/%dch/%s -> %dHz/%dch/%s...\n", |
24883 | 350 afs->input.rate, afs->input.nch, |
351 af_fmt2str_short(afs->input.format), afs->output.rate, | |
352 afs->output.nch, af_fmt2str_short(afs->output.format)); | |
353 | |
354 // let's autoprobe it! | |
355 if (0 != af_init(afs)) { | |
356 sh_audio->afilter = NULL; | |
357 free(afs); | |
358 return 0; // failed :( | |
359 } | |
360 | |
361 *out_samplerate = afs->output.rate; | |
362 *out_channels = afs->output.nch; | |
363 *out_format = afs->output.format; | |
15811
9b4bbb6098f6
make -srate work again, unify audio filter init and preinit.
reimar
parents:
15789
diff
changeset
|
364 |
32727
470867f7e1df
Remove resetting of a_out_buffer_len in init_audio_filters.
reimar
parents:
31977
diff
changeset
|
365 // 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
|
366 // 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
|
367 // 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
|
368 |
24883 | 369 // ok! |
370 sh_audio->afilter = (void *) afs; | |
371 return 1; | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
372 } |
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
373 |
24892 | 374 static int filter_n_bytes(sh_audio_t *sh, int len) |
5342 | 375 { |
25252 | 376 int error = 0; |
25253 | 377 // Filter |
378 af_data_t filter_input = { | |
379 .audio = sh->a_buffer, | |
380 .rate = sh->samplerate, | |
381 .nch = sh->channels, | |
382 .format = sh->sample_format | |
383 }; | |
384 af_data_t *filter_output; | |
24892 | 385 |
25252 | 386 assert(len-1 + sh->audio_out_minsize <= sh->a_buffer_size); |
24892 | 387 |
388 // Decode more bytes if needed | |
389 while (sh->a_buffer_len < len) { | |
390 unsigned char *buf = sh->a_buffer + sh->a_buffer_len; | |
391 int minlen = len - sh->a_buffer_len; | |
392 int maxlen = sh->a_buffer_size - sh->a_buffer_len; | |
393 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
|
394 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
|
395 sh->channels != filter_input.nch || |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
396 sh->sample_format != filter_input.format; |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
397 if (ret <= 0 || format_change) { |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
398 error = format_change ? -2 : -1; |
24892 | 399 len = sh->a_buffer_len; |
400 break; | |
401 } | |
402 sh->a_buffer_len += ret; | |
403 } | |
24883 | 404 |
25254 | 405 filter_input.len = len; |
24892 | 406 af_fix_parameters(&filter_input); |
25253 | 407 filter_output = af_play(sh->afilter, &filter_input); |
24892 | 408 if (!filter_output) |
409 return -1; | |
410 if (sh->a_out_buffer_size < sh->a_out_buffer_len + filter_output->len) { | |
411 int newlen = sh->a_out_buffer_len + filter_output->len; | |
412 mp_msg(MSGT_DECAUDIO, MSGL_V, "Increasing filtered audio buffer size " | |
413 "from %d to %d\n", sh->a_out_buffer_size, newlen); | |
414 sh->a_out_buffer = realloc(sh->a_out_buffer, newlen); | |
415 sh->a_out_buffer_size = newlen; | |
416 } | |
417 memcpy(sh->a_out_buffer + sh->a_out_buffer_len, filter_output->audio, | |
418 filter_output->len); | |
419 sh->a_out_buffer_len += filter_output->len; | |
420 | |
421 // remove processed data from decoder buffer: | |
422 sh->a_buffer_len -= len; | |
423 memmove(sh->a_buffer, sh->a_buffer + len, sh->a_buffer_len); | |
424 | |
425 return error; | |
426 } | |
427 | |
428 /* Try to get at least minlen decoded+filtered bytes in sh_audio->a_out_buffer | |
429 * (total length including possible existing data). | |
430 * Return 0 on success, -1 on error/EOF (not distinguished). | |
431 * In the former case sh_audio->a_out_buffer_len is always >= minlen | |
432 * on return. In case of EOF/error it might or might not be. | |
433 * Can reallocate sh_audio->a_out_buffer if needed to fit all filter output. */ | |
31977 | 434 int mp_decode_audio(sh_audio_t *sh_audio, int minlen) |
24892 | 435 { |
24961 | 436 // Indicates that a filter seems to be buffering large amounts of data |
437 int huge_filter_buffer = 0; | |
24892 | 438 // Decoded audio must be cut at boundaries of this many bytes |
27249 | 439 int unitsize = sh_audio->channels * sh_audio->samplesize * 16; |
24892 | 440 |
441 /* Filter output size will be about filter_multiplier times input size. | |
442 * If some filter buffers audio in big blocks this might only hold | |
443 * as average over time. */ | |
444 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
|
445 |
24892 | 446 /* If the decoder set audio_out_minsize then it can do the equivalent of |
447 * "while (output_len < target_len) output_len += audio_out_minsize;", | |
448 * so we must guarantee there is at least audio_out_minsize-1 bytes | |
449 * more space in the output buffer than the minimum length we try to | |
450 * decode. */ | |
451 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
|
452 if (!unitsize) |
dc78fbe1f17f
Add a safeguard to avoid crash if the decoder e.g. claims 0 channels.
reimar
parents:
33827
diff
changeset
|
453 return -1; |
24892 | 454 max_decode_len -= max_decode_len % unitsize; |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
455 |
24892 | 456 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
|
457 int res; |
24892 | 458 int declen = (minlen - sh_audio->a_out_buffer_len) / filter_multiplier |
459 + (unitsize << 5); // some extra for possible filter buffering | |
24961 | 460 if (huge_filter_buffer) |
24892 | 461 /* Some filter must be doing significant buffering if the estimated |
462 * input length didn't produce enough output from filters. | |
463 * Feed the filters 2k bytes at a time until we have enough output. | |
464 * Very small amounts could make filtering inefficient while large | |
465 * amounts can make MPlayer demux the file unnecessarily far ahead | |
466 * to get audio data and buffer video frames in memory while doing | |
467 * so. However the performance impact of either is probably not too | |
468 * significant as long as the value is not completely insane. */ | |
24961 | 469 declen = 2000; |
24892 | 470 declen -= declen % unitsize; |
24961 | 471 if (declen > max_decode_len) |
472 declen = max_decode_len; | |
473 else | |
474 /* if this iteration does not fill buffer, we must have lots | |
475 * of buffering in filters */ | |
476 huge_filter_buffer = 1; | |
31671
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
477 res = filter_n_bytes(sh_audio, declen); |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
478 if (res < 0) |
4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
reimar
parents:
31540
diff
changeset
|
479 return res; |
24883 | 480 } |
24892 | 481 return 0; |
5342 | 482 } |
483 | |
484 void resync_audio_stream(sh_audio_t *sh_audio) | |
485 { | |
30378
8339bca8e4b4
Move the resync-related code into more consistent places instead of having it
reimar
parents:
29168
diff
changeset
|
486 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
|
487 sh_audio->a_out_buffer_len = 0; |
24883 | 488 sh_audio->a_in_buffer_len = 0; // clear audio input buffer |
25962 | 489 if (!sh_audio->initialized) |
24883 | 490 return; |
491 sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL); | |
5342 | 492 } |
493 | |
494 void skip_audio_frame(sh_audio_t *sh_audio) | |
495 { | |
25962 | 496 if (!sh_audio->initialized) |
24883 | 497 return; |
498 if (sh_audio->ad_driver->control(sh_audio, ADCTRL_SKIP_FRAME, NULL) == | |
499 CONTROL_TRUE) | |
500 return; | |
501 // default skip code: | |
502 ds_fill_buffer(sh_audio->ds); // skip block | |
5342 | 503 } |