diff options
-rw-r--r-- | audio/mixer.c | 12 | ||||
-rw-r--r-- | audio/out/ao.c | 38 | ||||
-rw-r--r-- | audio/out/ao.h | 69 | ||||
-rw-r--r-- | audio/out/ao_alsa.c | 1 | ||||
-rw-r--r-- | audio/out/ao_coreaudio.c | 1 | ||||
-rw-r--r-- | audio/out/ao_coreaudio_properties.h | 2 | ||||
-rw-r--r-- | audio/out/ao_coreaudio_utils.h | 1 | ||||
-rw-r--r-- | audio/out/ao_dsound.c | 1 | ||||
-rw-r--r-- | audio/out/ao_jack.c | 1 | ||||
-rw-r--r-- | audio/out/ao_lavc.c | 1 | ||||
-rw-r--r-- | audio/out/ao_null.c | 1 | ||||
-rw-r--r-- | audio/out/ao_openal.c | 1 | ||||
-rw-r--r-- | audio/out/ao_oss.c | 1 | ||||
-rw-r--r-- | audio/out/ao_pcm.c | 1 | ||||
-rw-r--r-- | audio/out/ao_portaudio.c | 1 | ||||
-rw-r--r-- | audio/out/ao_pulse.c | 1 | ||||
-rw-r--r-- | audio/out/ao_rsound.c | 1 | ||||
-rw-r--r-- | audio/out/ao_sdl.c | 1 | ||||
-rw-r--r-- | audio/out/ao_sndio.c | 1 | ||||
-rw-r--r-- | audio/out/ao_wasapi.c | 1 | ||||
-rw-r--r-- | audio/out/internal.h | 76 | ||||
-rw-r--r-- | player/audio.c | 98 | ||||
-rw-r--r-- | player/core.h | 5 | ||||
-rw-r--r-- | player/loadfile.c | 6 | ||||
-rw-r--r-- | player/playloop.c | 11 | ||||
-rw-r--r-- | player/video.c | 2 |
26 files changed, 218 insertions, 117 deletions
diff --git a/audio/mixer.c b/audio/mixer.c index a9759976a2..34a1722c80 100644 --- a/audio/mixer.c +++ b/audio/mixer.c @@ -210,7 +210,7 @@ void mixer_setbalance(struct mixer *mixer, float val) if (af_control_any_rev(mixer->af, AF_CONTROL_SET_PAN_BALANCE, &val)) return; - if (val == 0 || mixer->ao->channels.num < 2) + if (val == 0) return; if (!(af_pan_balance = af_add(mixer->af, "pan", NULL))) { @@ -243,8 +243,9 @@ static void probe_softvol(struct mixer *mixer) { if (mixer->opts->softvol == SOFTVOL_AUTO) { // No system-wide volume => fine with AO volume control. - mixer->softvol = !(mixer->ao->per_application_mixer || - mixer->ao->no_persistent_volume); + mixer->softvol = + ao_control(mixer->ao, AOCONTROL_HAS_TEMP_VOLUME, 0) != 1 && + ao_control(mixer->ao, AOCONTROL_HAS_PER_APP_VOLUME, 0) != 1; } else { mixer->softvol = mixer->opts->softvol == SOFTVOL_YES; } @@ -275,9 +276,10 @@ static void restore_volume(struct mixer *mixer) int force_mute = -1; const char *prev_driver = mixer->driver; - mixer->driver = mixer->softvol ? "softvol" : ao->driver->name; + mixer->driver = mixer->softvol ? "softvol" : ao_get_name(ao); - bool restore = mixer->softvol || ao->no_persistent_volume; + bool restore + = mixer->softvol || ao_control(ao, AOCONTROL_HAS_TEMP_VOLUME, 0) == 1; // Restore old parameters if volume won't survive reinitialization. // But not if volume scale is possibly different. diff --git a/audio/out/ao.c b/audio/out/ao.c index 02415b0f2d..b77d401d64 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -25,7 +25,9 @@ #include "config.h" #include "ao.h" +#include "internal.h" #include "audio/format.h" +#include "audio/audio.h" #include "options/options.h" #include "options/m_config.h" @@ -231,8 +233,15 @@ int ao_play(struct ao *ao, void **data, int samples, int flags) int ao_control(struct ao *ao, enum aocontrol cmd, void *arg) { - if (ao->driver->control) - return ao->driver->control(ao, cmd, arg); + switch (cmd) { + case AOCONTROL_HAS_TEMP_VOLUME: + return !ao->no_persistent_volume; + case AOCONTROL_HAS_PER_APP_VOLUME: + return !!ao->per_application_mixer; + default: + if (ao->driver->control) + return ao->driver->control(ao, cmd, arg); + } return CONTROL_UNKNOWN; } @@ -307,3 +316,28 @@ bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, { return mp_chmap_sel_get_def(s, map, num); } + +// --- The following functions just return immutable information. + +void ao_get_format(struct ao *ao, struct mp_audio *format) +{ + *format = (struct mp_audio){0}; + mp_audio_set_format(format, ao->format); + mp_audio_set_channels(format, &ao->channels); + format->rate = ao->samplerate; +} + +const char *ao_get_name(struct ao *ao) +{ + return ao->driver->name; +} + +const char *ao_get_description(struct ao *ao) +{ + return ao->driver->description; +} + +bool ao_untimed(struct ao *ao) +{ + return ao->untimed; +} diff --git a/audio/out/ao.h b/audio/out/ao.h index 73a7cdfa61..152490aacc 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -36,6 +36,8 @@ enum aocontrol { AOCONTROL_SET_MUTE, // Has char* as argument, which contains the desired stream title. AOCONTROL_UPDATE_STREAM_TITLE, + AOCONTROL_HAS_TEMP_VOLUME, + AOCONTROL_HAS_PER_APP_VOLUME, }; // If set, then the queued audio data is the last. Note that after a while, new @@ -48,64 +50,20 @@ typedef struct ao_control_vol { } ao_control_vol_t; struct ao; - -struct ao_driver { - // If true, use with encoding only. - bool encode; - // Name used for --ao. - const char *name; - // Description shown with --ao=help. - const char *description; - // Init the device using ao->format/ao->channels/ao->samplerate. If the - // device doesn't accept these parameters, you can attempt to negotiate - // fallback parameters, and set the ao format fields accordingly. - int (*init)(struct ao *ao); - // See ao_control() etc. in ao.c - int (*control)(struct ao *ao, enum aocontrol cmd, void *arg); - void (*uninit)(struct ao *ao, bool cut_audio); - void (*reset)(struct ao*ao); - int (*get_space)(struct ao *ao); - int (*play)(struct ao *ao, void **data, int samples, int flags); - float (*get_delay)(struct ao *ao); - void (*pause)(struct ao *ao); - void (*resume)(struct ao *ao); - - // For option parsing (see vo.h) - int priv_size; - const void *priv_defaults; - const struct m_option *options; -}; - -/* global data used by mplayer and plugins */ -struct ao { - int samplerate; - struct mp_chmap channels; - int format; // one of AF_FORMAT_... - int bps; // bytes per second - int sstride; // size of a sample on each plane - // (format_size*num_channels/num_planes) - double pts; // some mplayer.c state (why is this here?) - struct mp_audio_buffer *buffer; // queued audio; passed to play() later - int buffer_playable_samples;// part of the part of the buffer the AO hasn't - // accepted yet with play() - bool probing; // if true, don't fail loudly on init - bool untimed; // don't assume realtime playback - bool no_persistent_volume; // the AO does the equivalent of af_volume - bool per_application_mixer; // like above, but volume persists (per app) - const struct ao_driver *driver; - void *priv; - struct encode_lavc_context *encode_lavc_ctx; - struct MPOpts *opts; - struct input_ctx *input_ctx; - struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix -}; - struct mpv_global; +struct input_ctx; +struct encode_lavc_context; +struct mp_audio; + struct ao *ao_init_best(struct mpv_global *global, struct input_ctx *input_ctx, struct encode_lavc_context *encode_lavc_ctx, int samplerate, int format, struct mp_chmap channels); void ao_uninit(struct ao *ao, bool cut_audio); +void ao_get_format(struct ao *ao, struct mp_audio *format); +const char *ao_get_name(struct ao *ao); +const char *ao_get_description(struct ao *ao); +bool ao_untimed(struct ao *ao); int ao_play(struct ao *ao, void **data, int samples, int flags); int ao_control(struct ao *ao, enum aocontrol cmd, void *arg); double ao_get_delay(struct ao *ao); @@ -114,11 +72,4 @@ void ao_reset(struct ao *ao); void ao_pause(struct ao *ao); void ao_resume(struct ao *ao); -int ao_play_silence(struct ao *ao, int samples); - -bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, - struct mp_chmap *map); -bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, - struct mp_chmap *map, int num); - #endif /* MPLAYER_AUDIO_OUT_H */ diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index 2237c4dd59..d50757bdfd 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -46,6 +46,7 @@ #include <alsa/asoundlib.h> #include "ao.h" +#include "internal.h" #include "audio/format.h" #include "audio/reorder_ch.h" diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index ba95fa728d..36be7c5872 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -37,6 +37,7 @@ #include "config.h" #include "ao.h" +#include "internal.h" #include "audio/format.h" #include "osdep/timer.h" #include "options/m_option.h" diff --git a/audio/out/ao_coreaudio_properties.h b/audio/out/ao_coreaudio_properties.h index ee7f83e6b7..e48b75871e 100644 --- a/audio/out/ao_coreaudio_properties.h +++ b/audio/out/ao_coreaudio_properties.h @@ -21,6 +21,8 @@ #include <AudioToolbox/AudioToolbox.h> +#include "internal.h" + // CoreAudio names are way too verbose #define ca_sel AudioObjectPropertySelector #define ca_scope AudioObjectPropertyScope diff --git a/audio/out/ao_coreaudio_utils.h b/audio/out/ao_coreaudio_utils.h index cf69248b47..0aca2f7c62 100644 --- a/audio/out/ao_coreaudio_utils.h +++ b/audio/out/ao_coreaudio_utils.h @@ -24,6 +24,7 @@ #include <stdbool.h> #include "common/msg.h" #include "audio/out/ao.h" +#include "internal.h" #define CA_CFSTR_ENCODING kCFStringEncodingASCII diff --git a/audio/out/ao_dsound.c b/audio/out/ao_dsound.c index 26c7bb83ed..ce7346fbdb 100644 --- a/audio/out/ao_dsound.c +++ b/audio/out/ao_dsound.c @@ -38,6 +38,7 @@ #include "config.h" #include "audio/format.h" #include "ao.h" +#include "internal.h" #include "audio/reorder_ch.h" #include "common/msg.h" #include "osdep/timer.h" diff --git a/audio/out/ao_jack.c b/audio/out/ao_jack.c index 72235a2d48..5b142f2d06 100644 --- a/audio/out/ao_jack.c +++ b/audio/out/ao_jack.c @@ -32,6 +32,7 @@ #include "common/msg.h" #include "ao.h" +#include "internal.h" #include "audio/format.h" #include "osdep/timer.h" #include "options/m_option.h" diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c index 9a2df7be22..7d31f63ec9 100644 --- a/audio/out/ao_lavc.c +++ b/audio/out/ao_lavc.c @@ -36,6 +36,7 @@ #include "audio/fmt-conversion.h" #include "talloc.h" #include "ao.h" +#include "internal.h" #include "common/msg.h" #include "common/encode_lavc.h" diff --git a/audio/out/ao_null.c b/audio/out/ao_null.c index 7c912d94a4..7caee039e0 100644 --- a/audio/out/ao_null.c +++ b/audio/out/ao_null.c @@ -34,6 +34,7 @@ #include "common/msg.h" #include "audio/format.h" #include "ao.h" +#include "internal.h" struct priv { bool paused; diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c index 3cb8ba5149..8cc29db689 100644 --- a/audio/out/ao_openal.c +++ b/audio/out/ao_openal.c @@ -38,6 +38,7 @@ #include "common/msg.h" #include "ao.h" +#include "internal.h" #include "audio/format.h" #include "osdep/timer.h" #include "options/m_option.h" diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c index 574fcf6beb..a1bf0feefc 100644 --- a/audio/out/ao_oss.c +++ b/audio/out/ao_oss.c @@ -49,6 +49,7 @@ #include "audio/format.h" #include "ao.h" +#include "internal.h" struct priv { int audio_fd; diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c index 14548d3be3..5824f7ce99 100644 --- a/audio/out/ao_pcm.c +++ b/audio/out/ao_pcm.c @@ -34,6 +34,7 @@ #include "audio/format.h" #include "audio/reorder_ch.h" #include "ao.h" +#include "internal.h" #include "common/msg.h" #ifdef __MINGW32__ diff --git a/audio/out/ao_portaudio.c b/audio/out/ao_portaudio.c index 8b7e3041cd..c3ba343485 100644 --- a/audio/out/ao_portaudio.c +++ b/audio/out/ao_portaudio.c @@ -31,6 +31,7 @@ #include "common/msg.h" #include "misc/ring.h" #include "ao.h" +#include "internal.h" struct priv { PaStream *stream; diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c index fc93c40871..12fca17dd6 100644 --- a/audio/out/ao_pulse.c +++ b/audio/out/ao_pulse.c @@ -31,6 +31,7 @@ #include "audio/format.h" #include "common/msg.h" #include "ao.h" +#include "internal.h" #include "input/input.h" #define PULSE_CLIENT_NAME "mpv" diff --git a/audio/out/ao_rsound.c b/audio/out/ao_rsound.c index 6bd99030a1..ef81c621da 100644 --- a/audio/out/ao_rsound.c +++ b/audio/out/ao_rsound.c @@ -33,6 +33,7 @@ #include "osdep/timer.h" #include "audio/format.h" #include "ao.h" +#include "internal.h" struct priv { rsound_t *rd; diff --git a/audio/out/ao_sdl.c b/audio/out/ao_sdl.c index ac1fd6febb..acb959b101 100644 --- a/audio/out/ao_sdl.c +++ b/audio/out/ao_sdl.c @@ -23,6 +23,7 @@ #include "audio/format.h" #include "talloc.h" #include "ao.h" +#include "internal.h" #include "common/msg.h" #include "options/m_option.h" #include "osdep/timer.h" diff --git a/audio/out/ao_sndio.c b/audio/out/ao_sndio.c index 75ea5d095b..c200b906ab 100644 --- a/audio/out/ao_sndio.c +++ b/audio/out/ao_sndio.c @@ -27,6 +27,7 @@ #include "audio/format.h" #include "ao.h" +#include "internal.h" struct priv { struct sio_hdl *hdl; diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index 39199159b3..bb00849adb 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -35,6 +35,7 @@ #include "common/msg.h" #include "misc/ring.h" #include "ao.h" +#include "internal.h" #include "compat/atomics.h" #ifndef PKEY_Device_FriendlyName diff --git a/audio/out/internal.h b/audio/out/internal.h new file mode 100644 index 0000000000..5cb12886a7 --- /dev/null +++ b/audio/out/internal.h @@ -0,0 +1,76 @@ +/* + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MP_AO_INTERNAL_H_ +#define MP_AO_INTERNAL_H_ + +/* global data used by ao.c and ao drivers */ +struct ao { + int samplerate; + struct mp_chmap channels; + int format; // one of AF_FORMAT_... + int bps; // bytes per second + int sstride; // size of a sample on each plane + // (format_size*num_channels/num_planes) + bool probing; // if true, don't fail loudly on init + bool untimed; // don't assume realtime playback + bool no_persistent_volume; // the AO does the equivalent of af_volume + bool per_application_mixer; // like above, but volume persists (per app) + const struct ao_driver *driver; + void *priv; + struct encode_lavc_context *encode_lavc_ctx; + struct MPOpts *opts; + struct input_ctx *input_ctx; + struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix +}; + +struct ao_driver { + // If true, use with encoding only. + bool encode; + // Name used for --ao. + const char *name; + // Description shown with --ao=help. + const char *description; + // Init the device using ao->format/ao->channels/ao->samplerate. If the + // device doesn't accept these parameters, you can attempt to negotiate + // fallback parameters, and set the ao format fields accordingly. + int (*init)(struct ao *ao); + // See ao_control() etc. in ao.c + int (*control)(struct ao *ao, enum aocontrol cmd, void *arg); + void (*uninit)(struct ao *ao, bool cut_audio); + void (*reset)(struct ao*ao); + int (*get_space)(struct ao *ao); + int (*play)(struct ao *ao, void **data, int samples, int flags); + float (*get_delay)(struct ao *ao); + void (*pause)(struct ao *ao); + void (*resume)(struct ao *ao); + + // For option parsing (see vo.h) + int priv_size; + const void *priv_defaults; + const struct m_option *options; +}; + +// These functions can be called by AOs. They don't lock the AO. +int ao_play_silence(struct ao *ao, int samples); +bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, + struct mp_chmap *map); +bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, + struct mp_chmap *map, int num); + +#endif diff --git a/player/audio.c b/player/audio.c index 984243b639..c6e7411e2a 100644 --- a/player/audio.c +++ b/player/audio.c @@ -45,7 +45,6 @@ static int build_afilter_chain(struct MPContext *mpctx) { struct dec_audio *d_audio = mpctx->d_audio; - struct ao *ao = mpctx->ao; struct MPOpts *opts = mpctx->opts; if (!d_audio) @@ -54,13 +53,16 @@ static int build_afilter_chain(struct MPContext *mpctx) struct mp_audio in_format; mp_audio_buffer_get_format(d_audio->decode_buffer, &in_format); + struct mp_audio out_format; + ao_get_format(mpctx->ao, &out_format); + int new_srate; if (af_control_any_rev(d_audio->afilter, AF_CONTROL_SET_PLAYBACK_SPEED, &opts->playback_speed)) new_srate = in_format.rate; else { new_srate = in_format.rate * opts->playback_speed; - if (new_srate != ao->samplerate) { + if (new_srate != out_format.rate) { // limits are taken from libaf/af_resample.c if (new_srate < 8000) new_srate = 8000; @@ -70,7 +72,7 @@ static int build_afilter_chain(struct MPContext *mpctx) } } return audio_init_filters(d_audio, new_srate, - &ao->samplerate, &ao->channels, &ao->format); + &out_format.rate, &out_format.channels, &out_format.format); } static int recreate_audio_filters(struct MPContext *mpctx) @@ -135,9 +137,11 @@ void reinit_audio_chain(struct MPContext *mpctx) int ao_format = opts->audio_output_format; struct mp_chmap ao_channels = {0}; if (mpctx->initialized_flags & INITIALIZED_AO) { - ao_srate = mpctx->ao->samplerate; - ao_format = mpctx->ao->format; - ao_channels = mpctx->ao->channels; + struct mp_audio out_format; + ao_get_format(mpctx->ao, &out_format); + ao_srate = out_format.rate; + ao_format = out_format.format; + ao_channels = out_format.channels; } else { // Automatic downmix if (mp_chmap_is_stereo(&opts->audio_output_channels) && @@ -172,14 +176,16 @@ void reinit_audio_chain(struct MPContext *mpctx) goto init_error; } - ao->buffer = mp_audio_buffer_create(ao); - mp_audio_buffer_reinit_fmt(ao->buffer, ao->format, &ao->channels, - ao->samplerate); + struct mp_audio fmt; + ao_get_format(ao, &fmt); - char *s = mp_audio_fmt_to_str(ao->samplerate, &ao->channels, ao->format); - MP_INFO(mpctx, "AO: [%s] %s\n", ao->driver->name, s); + mpctx->ao_buffer = mp_audio_buffer_create(ao); + mp_audio_buffer_reinit(mpctx->ao_buffer, &fmt); + + char *s = mp_audio_config_to_str(&fmt); + MP_INFO(mpctx, "AO: [%s] %s\n", ao_get_name(ao), s); talloc_free(s); - MP_VERBOSE(mpctx, "AO: Description: %s\n", ao->driver->description); + MP_VERBOSE(mpctx, "AO: Description: %s\n", ao_get_description(ao)); update_window_title(mpctx, true); } @@ -228,7 +234,7 @@ double written_audio_pts(struct MPContext *mpctx) // Data that was ready for ao but was buffered because ao didn't fully // accept everything to internal buffers yet - buffered_output += mp_audio_buffer_seconds(mpctx->ao->buffer); + buffered_output += mp_audio_buffer_seconds(mpctx->ao_buffer); // Filters divide audio length by playback_speed, so multiply by it // to get the length in original units without speedup or slowdown @@ -252,11 +258,13 @@ static int write_to_ao(struct MPContext *mpctx, struct mp_audio *data, int flags if (mpctx->paused) return 0; struct ao *ao = mpctx->ao; - ao->pts = pts; + struct mp_audio out_format; + ao_get_format(ao, &out_format); + mpctx->ao_pts = pts; #if HAVE_ENCODING - encode_lavc_set_audio_pts(mpctx->encode_lavc_ctx, ao->pts); + encode_lavc_set_audio_pts(mpctx->encode_lavc_ctx, mpctx->ao_pts); #endif - double real_samplerate = ao->samplerate / mpctx->opts->playback_speed; + double real_samplerate = out_format.rate / mpctx->opts->playback_speed; int played = ao_play(mpctx->ao, data->planes, data->samples, flags); assert(played <= data->samples); if (played > 0) { @@ -264,7 +272,7 @@ static int write_to_ao(struct MPContext *mpctx, struct mp_audio *data, int flags mpctx->delay += played / real_samplerate; // Keep correct pts for remaining data - could be used to flush // remaining buffer when closing ao. - ao->pts += played / real_samplerate; + mpctx->ao_pts += played / real_samplerate; return played; } return 0; @@ -274,7 +282,7 @@ static int write_silence_to_ao(struct MPContext *mpctx, int samples, int flags, double pts) { struct mp_audio tmp = {0}; - mp_audio_buffer_get_format(mpctx->ao->buffer, &tmp); + mp_audio_buffer_get_format(mpctx->ao_buffer, &tmp); tmp.samples = samples; char *p = talloc_size(NULL, tmp.samples * tmp.sstride); for (int n = 0; n < tmp.num_planes; n++) @@ -295,15 +303,18 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) assert(d_audio); + struct mp_audio out_format; + ao_get_format(ao, &out_format); + // Timing info may not be set without - res = audio_decode(d_audio, ao->buffer, 1); + res = audio_decode(d_audio, mpctx->ao_buffer, 1); if (res < 0) return res; int samples; bool did_retry = false; double written_pts; - double real_samplerate = ao->samplerate / opts->playback_speed; + double real_samplerate = out_format.rate / opts->playback_speed; bool hrseek = mpctx->hrseek_active; // audio only hrseek mpctx->hrseek_active = false; while (1) { @@ -320,7 +331,7 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) if (written_pts <= 1 && d_audio->pts == MP_NOPTS_VALUE) { if (!did_retry) { // Try to read more data to see packets that have pts - res = audio_decode(d_audio, ao->buffer, ao->samplerate); + res = audio_decode(d_audio, mpctx->ao_buffer, out_format.rate); if (res < 0) return res; did_retry = true; @@ -338,16 +349,16 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) mpctx->syncing_audio = false; int skip_samples = -samples; int a = MPMIN(skip_samples, MPMAX(playsize, 2500)); - res = audio_decode(d_audio, ao->buffer, a); - if (skip_samples <= mp_audio_buffer_samples(ao->buffer)) { - mp_audio_buffer_skip(ao->buffer, skip_samples); - ao->buffer_playable_samples = 0; + res = audio_decode(d_audio, mpctx->ao_buffer, a); + if (skip_samples <= mp_audio_buffer_samples(mpctx->ao_buffer)) { + mp_audio_buffer_skip(mpctx->ao_buffer, skip_samples); + mpctx->ao_buffer_playable_samples = 0; if (res < 0) return res; - return audio_decode(d_audio, ao->buffer, playsize); + return audio_decode(d_audio, mpctx->ao_buffer, playsize); } - mp_audio_buffer_clear(ao->buffer); - ao->buffer_playable_samples = 0; + mp_audio_buffer_clear(mpctx->ao_buffer); + mpctx->ao_buffer_playable_samples = 0; if (res < 0) return res; } @@ -357,15 +368,15 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) if (samples >= playsize) { /* This case could fall back to the one below with * samples = playsize, but then silence would keep accumulating - * in ao->buffer if the AO accepts less data than it asks for + * in ao_buffer if the AO accepts less data than it asks for * in playsize. */ write_silence_to_ao(mpctx, playsize, 0, written_pts - samples / real_samplerate); return ASYNC_PLAY_DONE; } mpctx->syncing_audio = false; - mp_audio_buffer_prepend_silence(ao->buffer, samples); - return audio_decode(d_audio, ao->buffer, playsize); + mp_audio_buffer_prepend_silence(mpctx->ao_buffer, samples); + return audio_decode(d_audio, mpctx->ao_buffer, playsize); } int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) @@ -378,8 +389,10 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) bool signal_eof = false; bool partial_fill = false; struct dec_audio *d_audio = mpctx->d_audio; + struct mp_audio out_format; + ao_get_format(ao, &out_format); // Can't adjust the start of audio with spdif pass-through. - bool modifiable_audio_format = !(ao->format & AF_FORMAT_SPECIAL_MASK); + bool modifiable_audio_format = !(out_format.format & AF_FORMAT_SPECIAL_MASK); assert(d_audio); @@ -400,7 +413,7 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) if (mpctx->syncing_audio || mpctx->hrseek_active) res = audio_start_sync(mpctx, playsize); else - res = audio_decode(d_audio, ao->buffer, playsize); + res = audio_decode(d_audio, mpctx->ao_buffer, playsize); if (res < 0) { // EOF, error or format change if (res == -2) { @@ -420,7 +433,7 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) if (endpts != MP_NOPTS_VALUE) { double samples = (endpts - written_audio_pts(mpctx) - mpctx->audio_delay) - * ao->samplerate / opts->playback_speed; + * out_format.rate / opts->playback_speed; if (playsize > samples) { playsize = MPMAX(samples, 0); audio_eof = true; @@ -428,8 +441,8 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) } } - if (playsize > mp_audio_buffer_samples(ao->buffer)) { - playsize = mp_audio_buffer_samples(ao->buffer); + if (playsize > mp_audio_buffer_samples(mpctx->ao_buffer)) { + playsize = mp_audio_buffer_samples(mpctx->ao_buffer); partial_fill = true; } if (!playsize) @@ -445,17 +458,18 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) } } - assert(ao->buffer_playable_samples <= mp_audio_buffer_samples(ao->buffer)); + assert(mpctx->ao_buffer_playable_samples <= + mp_audio_buffer_samples(mpctx->ao_buffer)); struct mp_audio data; - mp_audio_buffer_peek(ao->buffer, &data); + mp_audio_buffer_peek(mpctx->ao_buffer, &data); data.samples = MPMIN(data.samples, playsize); int played = write_to_ao(mpctx, &data, playflags, written_audio_pts(mpctx)); assert(played >= 0 && played <= data.samples); - ao->buffer_playable_samples = playsize - played; + mpctx->ao_buffer_playable_samples = playsize - played; if (played > 0) { - mp_audio_buffer_skip(ao->buffer, played); + mp_audio_buffer_skip(mpctx->ao_buffer, played); } else if (!mpctx->paused && audio_eof && ao_get_delay(ao) < .04) { // Sanity check to avoid hanging in case current ao doesn't output // partial chunks and doesn't check for AOPLAY_FINAL_CHUNK @@ -470,8 +484,8 @@ void clear_audio_output_buffers(struct MPContext *mpctx) { if (mpctx->ao) { ao_reset(mpctx->ao); - mp_audio_buffer_clear(mpctx->ao->buffer); - mpctx->ao->buffer_playable_samples = 0; + mp_audio_buffer_clear(mpctx->ao_buffer); + mpctx->ao_buffer_playable_samples = 0; } } diff --git a/player/core.h b/player/core.h index fd9be5bcd4..5e60568c97 100644 --- a/player/core.h +++ b/player/core.h @@ -223,6 +223,11 @@ typedef struct MPContext { struct mixer *mixer; struct ao *ao; + double ao_pts; + struct mp_audio_buffer *ao_buffer; // queued audio; passed to ao_play() later + int ao_buffer_playable_samples; // part of the part of the buffer the AO |