Mercurial > mplayer.hg
annotate libmpcodecs/dec_audio.c @ 31246:cc6ee3017097
Limit buffered PTS only when we actually got a frame from the decoder.
This avoids some issues with H.264 PAFF due to dropping PTS values too
early because only every second packet actually produced output.
Just keeping up to one additional pts value would have avoided this
particular issue as well, but this is more generic.
author | reimar |
---|---|
date | Thu, 03 Jun 2010 20:59:40 +0000 |
parents | bbb6ebec87a0 |
children | 7f1c8212e3cf |
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) { | |
154 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 |
24893 | 364 sh_audio->a_out_buffer_len = 0; |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
365 |
24883 | 366 // ok! |
367 sh_audio->afilter = (void *) afs; | |
368 return 1; | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
369 } |
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
370 |
24892 | 371 static int filter_n_bytes(sh_audio_t *sh, int len) |
5342 | 372 { |
25252 | 373 int error = 0; |
25253 | 374 // Filter |
375 af_data_t filter_input = { | |
376 .audio = sh->a_buffer, | |
377 .rate = sh->samplerate, | |
378 .nch = sh->channels, | |
379 .format = sh->sample_format | |
380 }; | |
381 af_data_t *filter_output; | |
24892 | 382 |
25252 | 383 assert(len-1 + sh->audio_out_minsize <= sh->a_buffer_size); |
24892 | 384 |
385 // Decode more bytes if needed | |
386 while (sh->a_buffer_len < len) { | |
387 unsigned char *buf = sh->a_buffer + sh->a_buffer_len; | |
388 int minlen = len - sh->a_buffer_len; | |
389 int maxlen = sh->a_buffer_size - sh->a_buffer_len; | |
390 int ret = sh->ad_driver->decode_audio(sh, buf, minlen, maxlen); | |
391 if (ret <= 0) { | |
392 error = -1; | |
393 len = sh->a_buffer_len; | |
394 break; | |
395 } | |
396 sh->a_buffer_len += ret; | |
397 } | |
24883 | 398 |
25254 | 399 filter_input.len = len; |
24892 | 400 af_fix_parameters(&filter_input); |
25253 | 401 filter_output = af_play(sh->afilter, &filter_input); |
24892 | 402 if (!filter_output) |
403 return -1; | |
404 if (sh->a_out_buffer_size < sh->a_out_buffer_len + filter_output->len) { | |
405 int newlen = sh->a_out_buffer_len + filter_output->len; | |
406 mp_msg(MSGT_DECAUDIO, MSGL_V, "Increasing filtered audio buffer size " | |
407 "from %d to %d\n", sh->a_out_buffer_size, newlen); | |
408 sh->a_out_buffer = realloc(sh->a_out_buffer, newlen); | |
409 sh->a_out_buffer_size = newlen; | |
410 } | |
411 memcpy(sh->a_out_buffer + sh->a_out_buffer_len, filter_output->audio, | |
412 filter_output->len); | |
413 sh->a_out_buffer_len += filter_output->len; | |
414 | |
415 // remove processed data from decoder buffer: | |
416 sh->a_buffer_len -= len; | |
417 memmove(sh->a_buffer, sh->a_buffer + len, sh->a_buffer_len); | |
418 | |
419 return error; | |
420 } | |
421 | |
422 /* Try to get at least minlen decoded+filtered bytes in sh_audio->a_out_buffer | |
423 * (total length including possible existing data). | |
424 * Return 0 on success, -1 on error/EOF (not distinguished). | |
425 * In the former case sh_audio->a_out_buffer_len is always >= minlen | |
426 * on return. In case of EOF/error it might or might not be. | |
427 * Can reallocate sh_audio->a_out_buffer if needed to fit all filter output. */ | |
428 int decode_audio(sh_audio_t *sh_audio, int minlen) | |
429 { | |
24961 | 430 // Indicates that a filter seems to be buffering large amounts of data |
431 int huge_filter_buffer = 0; | |
24892 | 432 // Decoded audio must be cut at boundaries of this many bytes |
27249 | 433 int unitsize = sh_audio->channels * sh_audio->samplesize * 16; |
24892 | 434 |
435 /* Filter output size will be about filter_multiplier times input size. | |
436 * If some filter buffers audio in big blocks this might only hold | |
437 * as average over time. */ | |
438 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
|
439 |
24892 | 440 /* If the decoder set audio_out_minsize then it can do the equivalent of |
441 * "while (output_len < target_len) output_len += audio_out_minsize;", | |
442 * so we must guarantee there is at least audio_out_minsize-1 bytes | |
443 * more space in the output buffer than the minimum length we try to | |
444 * decode. */ | |
445 int max_decode_len = sh_audio->a_buffer_size - sh_audio->audio_out_minsize; | |
446 max_decode_len -= max_decode_len % unitsize; | |
7604
32efb806436e
aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
arpi
parents:
7561
diff
changeset
|
447 |
24892 | 448 while (sh_audio->a_out_buffer_len < minlen) { |
449 int declen = (minlen - sh_audio->a_out_buffer_len) / filter_multiplier | |
450 + (unitsize << 5); // some extra for possible filter buffering | |
24961 | 451 if (huge_filter_buffer) |
24892 | 452 /* Some filter must be doing significant buffering if the estimated |
453 * input length didn't produce enough output from filters. | |
454 * Feed the filters 2k bytes at a time until we have enough output. | |
455 * Very small amounts could make filtering inefficient while large | |
456 * amounts can make MPlayer demux the file unnecessarily far ahead | |
457 * to get audio data and buffer video frames in memory while doing | |
458 * so. However the performance impact of either is probably not too | |
459 * significant as long as the value is not completely insane. */ | |
24961 | 460 declen = 2000; |
24892 | 461 declen -= declen % unitsize; |
24961 | 462 if (declen > max_decode_len) |
463 declen = max_decode_len; | |
464 else | |
465 /* if this iteration does not fill buffer, we must have lots | |
466 * of buffering in filters */ | |
467 huge_filter_buffer = 1; | |
468 if (filter_n_bytes(sh_audio, declen) < 0) | |
469 return -1; | |
24883 | 470 } |
24892 | 471 return 0; |
5342 | 472 } |
473 | |
474 void resync_audio_stream(sh_audio_t *sh_audio) | |
475 { | |
30378
8339bca8e4b4
Move the resync-related code into more consistent places instead of having it
reimar
parents:
29168
diff
changeset
|
476 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
|
477 sh_audio->a_out_buffer_len = 0; |
24883 | 478 sh_audio->a_in_buffer_len = 0; // clear audio input buffer |
25962 | 479 if (!sh_audio->initialized) |
24883 | 480 return; |
481 sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL); | |
5342 | 482 } |
483 | |
484 void skip_audio_frame(sh_audio_t *sh_audio) | |
485 { | |
25962 | 486 if (!sh_audio->initialized) |
24883 | 487 return; |
488 if (sh_audio->ad_driver->control(sh_audio, ADCTRL_SKIP_FRAME, NULL) == | |
489 CONTROL_TRUE) | |
490 return; | |
491 // default skip code: | |
492 ds_fill_buffer(sh_audio->ds); // skip block | |
5342 | 493 } |