From fcba41e2e4752d6391c76ef4e2c9f0c8c5734159 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 21 Nov 2016 18:31:32 +0100 Subject: audio: fix --audio-stream-silence with ao_alsa ao_alsa.c calls this before the common code sets ao->sstride. Other than this, I'm still not sure whether this works. Seems like no, or depends. --- audio/out/push.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'audio') diff --git a/audio/out/push.c b/audio/out/push.c index 68606386f2..555a7867da 100644 --- a/audio/out/push.c +++ b/audio/out/push.c @@ -453,8 +453,9 @@ int ao_play_silence(struct ao *ao, int samples) assert(ao->api == &ao_api_push); if (samples <= 0 || !af_fmt_is_pcm(ao->format) || !ao->driver->play) return 0; - char *p = talloc_size(NULL, samples * ao->sstride); - af_fill_silence(p, samples * ao->sstride, ao->format); + int bytes = af_fmt_to_bytes(ao->format) * samples * ao->channels.num; + char *p = talloc_size(NULL, bytes); + af_fill_silence(p, bytes, ao->format); void *tmp[MP_NUM_CHANNELS]; for (int n = 0; n < MP_NUM_CHANNELS; n++) tmp[n] = p; -- cgit v1.2.3 From de37c5b1cbdc8a8c1fd6a4e3494396fb9608fd8b Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 21 Nov 2016 19:33:31 +0100 Subject: audio: fix --audio-stream-silence with ao_wasapi Seems like wasapi will restart the HDMI stream if resume is called during playback. --- audio/out/pull.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'audio') diff --git a/audio/out/pull.c b/audio/out/pull.c index 44f6ab3355..a656de6fdd 100644 --- a/audio/out/pull.c +++ b/audio/out/pull.c @@ -101,7 +101,8 @@ static int play(struct ao *ao, void **data, int samples, int flags) int state = atomic_load(&p->state); if (!IS_PLAYING(state)) { set_state(ao, AO_STATE_PLAY); - ao->driver->resume(ao); + if (!ao->stream_silence) + ao->driver->resume(ao); } return write_samples; @@ -203,7 +204,8 @@ static void pause(struct ao *ao) static void resume(struct ao *ao) { set_state(ao, AO_STATE_PLAY); - ao->driver->resume(ao); + if (!ao->stream_silence) + ao->driver->resume(ao); } static bool get_eof(struct ao *ao) -- cgit v1.2.3 From c03a67c37c149134a25d400a62b7706386136379 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 24 Nov 2016 20:50:09 +0100 Subject: audio/out/push: play silence on --audio-stream-silence Until now, this was only implemented for ao_alsa and AOs not using push.c. ao_alsa.c relied on enabling funny underrun semantics for avoiding resets on lower levels, while other AOs using push.c didn't do anything. Change this and at least make push.c copy silent data to the AO. This still isn't perfect as keeping track of how much silence was played when seems complex, so we don't do it. The consequence is that frame-stepping will essentially randomize the A/V offset (it'll recover immediately when unpausing, but still ugly). Also, in order to empty the currently buffered audio on seeks etc., we still call ao_driver->reset and so on, so the AO driver will still need to handle this specially. The intent is to make behavior with ALSA less weird (for one we can remove the code in ao_alsa.c that tries to trigger an initial underflow). Also might help with #3754. --- audio/out/ao_alsa.c | 6 ------ audio/out/push.c | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 13 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index 201557697d..91c8e2d3fc 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -845,12 +845,6 @@ static int init_device(struct ao *ao, int mode) ao->device_buffer = p->buffersize; - // ao_alsa implements this by relying on underrun behavior (no data means - // underrun, during which silence is played). Trigger by playing some - // initial silence. - if (ao->stream_silence) - ao_play_silence(ao, p->outburst); - return 0; alsa_error: diff --git a/audio/out/push.c b/audio/out/push.c index 555a7867da..a4a6808d7f 100644 --- a/audio/out/push.c +++ b/audio/out/push.c @@ -49,6 +49,8 @@ struct ao_push_state { struct mp_audio_buffer *buffer; + struct mp_audio *silence; + bool terminate; bool wait_on_ao; bool still_playing; @@ -259,15 +261,38 @@ static int play(struct ao *ao, void **data, int samples, int flags) return write_samples; } +static void ao_get_silence(struct ao *ao, struct mp_audio *data, int size) +{ + struct ao_push_state *p = ao->api_priv; + if (!p->silence) { + p->silence = talloc_zero(p, struct mp_audio); + mp_audio_set_format(p->silence, ao->format); + mp_audio_set_channels(p->silence, &ao->channels); + p->silence->rate = ao->samplerate; + } + if (p->silence->samples < size) { + mp_audio_realloc_min(p->silence, size); + p->silence->samples = size; + mp_audio_fill_silence(p->silence, 0, size); + } + *data = *p->silence; + data->samples = size; +} + // called locked static void ao_play_data(struct ao *ao) { struct ao_push_state *p = ao->api_priv; - struct mp_audio data; - mp_audio_buffer_peek(p->buffer, &data); - int max = data.samples; int space = ao->driver->get_space(ao); + bool play_silence = p->paused || (ao->stream_silence && !p->still_playing); space = MPMAX(space, 0); + struct mp_audio data; + if (play_silence) { + ao_get_silence(ao, &data, space); + } else { + mp_audio_buffer_peek(p->buffer, &data); + } + int max = data.samples; if (data.samples > space) data.samples = space; int flags = 0; @@ -289,7 +314,8 @@ static void ao_play_data(struct ao *ao) MP_ERR(ao, "Audio output driver seems to ignore AOPLAY_FINAL_CHUNK.\n"); r = max; } - mp_audio_buffer_skip(p->buffer, r); + if (!play_silence) + mp_audio_buffer_skip(p->buffer, r); if (r > 0) p->expected_end_time = 0; // Nothing written, but more input data than space - this must mean the @@ -300,7 +326,7 @@ static void ao_play_data(struct ao *ao) // Wait until space becomes available. Also wait if we actually wrote data, // so the AO wakes us up properly if it needs more data. p->wait_on_ao = space == 0 || r > 0 || stuck; - p->still_playing |= r > 0; + p->still_playing |= r > 0 && !play_silence; // If we just filled the AO completely (r == space), don't refill for a // while. Prevents wakeup feedback with byte-granular AOs. int needed = unlocked_get_space(ao); @@ -319,12 +345,13 @@ static void *playthread(void *arg) mpthread_set_name("ao"); pthread_mutex_lock(&p->lock); while (!p->terminate) { - if (!p->paused) + bool playing = !p->paused || ao->stream_silence; + if (playing) ao_play_data(ao); if (!p->need_wakeup) { MP_STATS(ao, "start audio wait"); - if (!p->wait_on_ao || p->paused) { + if (!p->wait_on_ao || !playing) { // Avoid busy waiting, because the audio API will still report // that it needs new data, even if we're not ready yet, or if // get_space() decides that the amount of audio buffered in the -- cgit v1.2.3 From 1a2319f3e4cc42c680e2fd3ba30022c7a9adf3fe Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 25 Nov 2016 21:00:39 +0100 Subject: options: remove deprecated sub-option handling for --vo and --ao Long planned. Leads to some sanity. There still are some rather gross things. Especially g_groups is ugly, and a hack that can hopefully be removed. (There is a plan for it, but whether it's implemented depends on how much energy is left.) --- audio/out/ao.c | 23 ++++++++++------------- audio/out/ao_alsa.c | 10 ---------- audio/out/ao_audiounit.m | 3 --- audio/out/ao_coreaudio.c | 9 ++------- audio/out/ao_jack.c | 8 -------- audio/out/ao_null.c | 2 +- audio/out/ao_openal.c | 2 +- audio/out/ao_opensles.c | 2 +- audio/out/ao_oss.c | 2 +- audio/out/ao_pcm.c | 2 +- audio/out/ao_pulse.c | 2 +- audio/out/ao_rsound.c | 2 +- audio/out/ao_sdl.c | 2 +- audio/out/ao_sndio.c | 2 +- audio/out/ao_wasapi.c | 7 ------- audio/out/ao_wasapi.h | 2 -- audio/out/ao_wasapi_utils.c | 5 +---- audio/out/internal.h | 2 +- 18 files changed, 23 insertions(+), 64 deletions(-) (limited to 'audio') diff --git a/audio/out/ao.c b/audio/out/ao.c index b624f4196c..6cf8de2d88 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -112,8 +112,8 @@ static bool get_desc(struct m_obj_desc *dst, int index) .priv_size = ao->priv_size, .priv_defaults = ao->priv_defaults, .options = ao->options, + .options_prefix = ao->options_prefix, .global_opts = ao->global_opts, - .legacy_prefix = ao->legacy_prefix, .hidden = ao->encode, .p = ao, }; @@ -127,11 +127,12 @@ const struct m_obj_list ao_obj_list = { .allow_unknown_entries = true, .allow_trailer = true, .disallow_positional_parameters = true, + .use_global_options = true, }; static struct ao *ao_alloc(bool probing, struct mpv_global *global, void (*wakeup_cb)(void *ctx), void *wakeup_ctx, - char *name, char **args) + char *name) { assert(wakeup_cb); @@ -155,12 +156,9 @@ static struct ao *ao_alloc(bool probing, struct mpv_global *global, .def_buffer = opts->audio_buffer, .client_name = talloc_strdup(ao, opts->audio_client_name), }; - struct m_config *config = - m_config_from_obj_desc_and_args(ao, ao->log, global, &desc, - name, opts->ao_defs, args); - if (!config) + ao->priv = m_config_group_from_desc(ao, ao->log, global, &desc, name); + if (!ao->priv) goto error; - ao->priv = config->optstruct; return ao; error: talloc_free(ao); @@ -171,9 +169,9 @@ static struct ao *ao_init(bool probing, struct mpv_global *global, void (*wakeup_cb)(void *ctx), void *wakeup_ctx, struct encode_lavc_context *encode_lavc_ctx, int flags, int samplerate, int format, struct mp_chmap channels, - char *dev, char *name, char **args) + char *dev, char *name) { - struct ao *ao = ao_alloc(probing, global, wakeup_cb, wakeup_ctx, name, args); + struct ao *ao = ao_alloc(probing, global, wakeup_cb, wakeup_ctx, name); if (!ao) return NULL; ao->samplerate = samplerate; @@ -206,7 +204,7 @@ static struct ao *ao_init(bool probing, struct mpv_global *global, talloc_free(ao); return ao_init(probing, global, wakeup_cb, wakeup_ctx, encode_lavc_ctx, flags, samplerate, format, channels, - rdevice, redirect, NULL); + rdevice, redirect); } goto fail; } @@ -313,8 +311,7 @@ struct ao *ao_init_best(struct mpv_global *global, mp_verbose(log, "Using preferred device '%s'\n", dev); } ao = ao_init(probing, global, wakeup_cb, wakeup_ctx, encode_lavc_ctx, - init_flags, samplerate, format, channels, dev, - entry->name, entry->attribs); + init_flags, samplerate, format, channels, dev, entry->name); if (ao) break; if (!probing) @@ -571,7 +568,7 @@ struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp) break; // don't add unsafe/special entries struct ao *ao = ao_alloc(true, hp->global, hp->wakeup_cb, hp->wakeup_ctx, - (char *)d->name, NULL); + (char *)d->name); if (!ao) continue; diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index 91c8e2d3fc..d63a760d73 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -1196,15 +1196,5 @@ const struct ao_driver audio_out_alsa = { .wakeup = ao_wakeup_poll, .list_devs = list_devs, .priv_size = sizeof(struct priv), - .options = (const struct m_option[]) { - OPT_SUBOPT_LEGACY("device", "alsa-device"), - OPT_SUBOPT_LEGACY("resample", "alsa-resample"), - OPT_SUBOPT_LEGACY("mixer-device", "alsa-mixer-device"), - OPT_SUBOPT_LEGACY("mixer-name", "alsa-mixer-name"), - OPT_SUBOPT_LEGACY("mixer-index", "alsa-mixer-index"), - OPT_SUBOPT_LEGACY("non-interleaved", "alsa-non-interleaved"), - OPT_SUBOPT_LEGACY("ignore-chmap", "alsa-ignore-chmap"), - {0} - }, .global_opts = &ao_alsa_conf, }; diff --git a/audio/out/ao_audiounit.m b/audio/out/ao_audiounit.m index 7411a1a1dd..31703525a9 100644 --- a/audio/out/ao_audiounit.m +++ b/audio/out/ao_audiounit.m @@ -195,7 +195,4 @@ const struct ao_driver audio_out_audiounit = { .pause = stop, .resume = start, .priv_size = sizeof(struct priv), - .options = (const struct m_option[]){ - {0} - }, }; diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index 3a7aa2eac1..ba0dd9b0ba 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -39,7 +39,6 @@ struct priv { AudioStreamID original_asbd_stream; int change_physical_format; - int exclusive; }; static int64_t ca_get_hardware_latency(struct ao *ao) { @@ -143,9 +142,7 @@ static int init(struct ao *ao) { struct priv *p = ao->priv; - p->exclusive |= ao->init_flags & AO_INIT_EXCLUSIVE; - - if (!af_fmt_is_pcm(ao->format) || p->exclusive) { + if (!af_fmt_is_pcm(ao->format) || (ao->init_flags & AO_INIT_EXCLUSIVE)) { MP_VERBOSE(ao, "redirecting to coreaudio_exclusive\n"); ao->redirect = "coreaudio_exclusive"; return CONTROL_ERROR; @@ -429,9 +426,7 @@ const struct ao_driver audio_out_coreaudio = { .priv_size = sizeof(struct priv), .options = (const struct m_option[]){ OPT_FLAG("change-physical-format", change_physical_format, 0), - OPT_FLAG("exclusive", exclusive, 0, - .deprecation_message = "use --audio-exclusive"), {0} }, - .legacy_prefix = "coreaudio", + .options_prefix = "coreaudio", }; diff --git a/audio/out/ao_jack.c b/audio/out/ao_jack.c index 56c7e28544..2ad3cad586 100644 --- a/audio/out/ao_jack.c +++ b/audio/out/ao_jack.c @@ -246,13 +246,5 @@ const struct ao_driver audio_out_jack = { .uninit = uninit, .resume = resume, .priv_size = sizeof(struct priv), - .options = (const struct m_option[]) { - OPT_SUBOPT_LEGACY("port", "jack-port"), - OPT_SUBOPT_LEGACY("name", "jack-name"), - OPT_SUBOPT_LEGACY("autostart", "jack-autostart"), - OPT_SUBOPT_LEGACY("connect", "jack-connect"), - OPT_SUBOPT_LEGACY("std-channel-layout", "jack-std-channel-layout"), - {0} - }, .global_opts = &ao_jack_conf, }; diff --git a/audio/out/ao_null.c b/audio/out/ao_null.c index 7c0c745b12..7b288a8245 100644 --- a/audio/out/ao_null.c +++ b/audio/out/ao_null.c @@ -241,5 +241,5 @@ const struct ao_driver audio_out_null = { OPT_CHANNELS("channel-layouts", channel_layouts, 0), {0} }, - .legacy_prefix = "ao-null", + .options_prefix = "ao-null", }; diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c index aba049445d..a1fd95ab18 100644 --- a/audio/out/ao_openal.c +++ b/audio/out/ao_openal.c @@ -374,5 +374,5 @@ const struct ao_driver audio_out_openal = { DEVICE_OPT_DEPRECATION), {0} }, - .legacy_prefix = "ao-openal", + .options_prefix = "ao-openal", }; diff --git a/audio/out/ao_opensles.c b/audio/out/ao_opensles.c index dd20dbf1d0..5357ab4920 100644 --- a/audio/out/ao_opensles.c +++ b/audio/out/ao_opensles.c @@ -246,5 +246,5 @@ const struct ao_driver audio_out_opensles = { OPT_INTRANGE("sample-rate", cfg_sample_rate, 0, 1000, 100000), {0} }, - .legacy_prefix = "opensles", + .options_prefix = "opensles", }; diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c index 5bf5fec29b..c0446eb2aa 100644 --- a/audio/out/ao_oss.c +++ b/audio/out/ao_oss.c @@ -653,5 +653,5 @@ const struct ao_driver audio_out_oss = { OPT_STRING("mixer-channel", cfg_oss_mixer_channel, 0), {0} }, - .legacy_prefix = "oss", + .options_prefix = "oss", }; diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c index 169a1b94a1..4e5ec0a319 100644 --- a/audio/out/ao_pcm.c +++ b/audio/out/ao_pcm.c @@ -224,5 +224,5 @@ const struct ao_driver audio_out_pcm = { OPT_FLAG("append", append, 0), {0} }, - .legacy_prefix = "ao-pcm", + .options_prefix = "ao-pcm", }; diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c index 5a68553e88..6c6a517f2a 100644 --- a/audio/out/ao_pulse.c +++ b/audio/out/ao_pulse.c @@ -841,5 +841,5 @@ const struct ao_driver audio_out_pulse = { OPT_FLAG("latency-hacks", cfg_latency_hacks, 0), {0} }, - .legacy_prefix = "pulse", + .options_prefix = "pulse", }; diff --git a/audio/out/ao_rsound.c b/audio/out/ao_rsound.c index 5ecb39b9d3..9689a9e0b8 100644 --- a/audio/out/ao_rsound.c +++ b/audio/out/ao_rsound.c @@ -162,6 +162,6 @@ const struct ao_driver audio_out_rsound = { .deprecation_message = "request --audio-device support on issue tracker"), {0} }, - .legacy_prefix = "rsound", + .options_prefix = "rsound", }; diff --git a/audio/out/ao_sdl.c b/audio/out/ao_sdl.c index d9d00628b6..1564e26120 100644 --- a/audio/out/ao_sdl.c +++ b/audio/out/ao_sdl.c @@ -212,5 +212,5 @@ const struct ao_driver audio_out_sdl = { OPT_FLOAT("buflen", buflen, 0), {0} }, - .legacy_prefix = "sdl", + .options_prefix = "sdl", }; diff --git a/audio/out/ao_sndio.c b/audio/out/ao_sndio.c index f60fa303e5..e0fd9f0296 100644 --- a/audio/out/ao_sndio.c +++ b/audio/out/ao_sndio.c @@ -324,5 +324,5 @@ const struct ao_driver audio_out_sndio = { DEVICE_OPT_DEPRECATION), {0} }, - .legacy_prefix = "ao-sndio", + .options_prefix = "ao-sndio", }; diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index 17f3e98653..b2e035d3dc 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -496,11 +496,4 @@ const struct ao_driver audio_out_wasapi = { .hotplug_init = hotplug_init, .hotplug_uninit = hotplug_uninit, .priv_size = sizeof(wasapi_state), - .options = (const struct m_option[]) { - OPT_FLAG("exclusive", opt_exclusive, 0, - .deprecation_message = "use --audio-exclusive"), - OPT_STRING("device", opt_device, 0, DEVICE_OPT_DEPRECATION), - {NULL}, - }, - .legacy_prefix = "ao-wasapi", }; diff --git a/audio/out/ao_wasapi.h b/audio/out/ao_wasapi.h index 6dd130b50f..ea9f5c2bad 100644 --- a/audio/out/ao_wasapi.h +++ b/audio/out/ao_wasapi.h @@ -92,8 +92,6 @@ typedef struct wasapi_state { // ao options int opt_exclusive; - int opt_list; - char *opt_device; // format info WAVEFORMATEXTENSIBLE format; diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c index 320bb6767b..8b12ef4d5c 100644 --- a/audio/out/ao_wasapi_utils.c +++ b/audio/out/ao_wasapi_utils.c @@ -858,10 +858,7 @@ static LPWSTR select_device(struct mp_log *l, struct device_desc *d) bstr wasapi_get_specified_device_string(struct ao *ao) { struct wasapi_state *state = ao->priv; - bstr device = bstr_strip(bstr0(state->opt_device)); - if (!device.len) - device = bstr_strip(bstr0(ao->device)); - return device; + return bstr_strip(bstr0(ao->device)); } LPWSTR wasapi_find_deviceID(struct ao *ao) diff --git a/audio/out/internal.h b/audio/out/internal.h index 3ddc1becb9..b35f20fba2 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -182,8 +182,8 @@ struct ao_driver { int priv_size; const void *priv_defaults; const struct m_option *options; + const char *options_prefix; const struct m_sub_options *global_opts; - const char *legacy_prefix; }; // These functions can be called by AOs. -- cgit v1.2.3 From 3203d6003c8e308b2ba4e277a64e717696b1b8b7 Mon Sep 17 00:00:00 2001 From: pavelxdd Date: Sun, 27 Nov 2016 07:31:33 +0300 Subject: ao_wasapi_utils: remove unused variable Introduced in 1a2319f3e4cc42c680e2fd3ba30022c7a9adf3fe Produced a warning during compilation on Windows. --- audio/out/ao_wasapi_utils.c | 1 - 1 file changed, 1 deletion(-) (limited to 'audio') diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c index 8b12ef4d5c..ce3f5da887 100644 --- a/audio/out/ao_wasapi_utils.c +++ b/audio/out/ao_wasapi_utils.c @@ -857,7 +857,6 @@ static LPWSTR select_device(struct mp_log *l, struct device_desc *d) bstr wasapi_get_specified_device_string(struct ao *ao) { - struct wasapi_state *state = ao->priv; return bstr_strip(bstr0(ao->device)); } -- cgit v1.2.3 From ec74a79e1240eeda7b0bb195b484420052ea0ad8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 30 Nov 2016 17:44:59 +0100 Subject: ao_wasapi: log return code when probing audio formats We log a large number of formats, but we rarely log the result of the probing. Change this. The logic in try_format_exclusive() changes slightly, but should be equivalent. EXIT_ON_ERROR() checks for FAILED(), which should be exclusive to SUCCEEDED(). --- audio/out/ao_wasapi.h | 4 ++++ audio/out/ao_wasapi_utils.c | 18 +++++------------- 2 files changed, 9 insertions(+), 13 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_wasapi.h b/audio/out/ao_wasapi.h index ea9f5c2bad..65f16d11c1 100644 --- a/audio/out/ao_wasapi.h +++ b/audio/out/ao_wasapi.h @@ -50,6 +50,10 @@ void wasapi_change_uninit(struct ao* ao); #define SAFE_RELEASE(unk, release) \ do { if ((unk) != NULL) { release; (unk) = NULL; } } while(0) +#define mp_format_res_str(hres) \ + (SUCCEEDED(hres) ? "ok" : ((hres) == AUDCLNT_E_UNSUPPORTED_FORMAT) \ + ? "unsupported" : mp_HRESULT_to_str(hres)) + enum wasapi_thread_state { WASAPI_THREAD_FEED = 0, WASAPI_THREAD_RESUME, diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c index ce3f5da887..4667b57ae8 100644 --- a/audio/out/ao_wasapi_utils.c +++ b/audio/out/ao_wasapi_utils.c @@ -289,18 +289,12 @@ static bool set_ao_format(struct ao *ao, WAVEFORMATEX *wf, static bool try_format_exclusive(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat) { struct wasapi_state *state = ao->priv; - MP_VERBOSE(ao, "Trying %s (exclusive)\n", - waveformat_to_str(&wformat->Format)); HRESULT hr = IAudioClient_IsFormatSupported(state->pAudioClient, AUDCLNT_SHAREMODE_EXCLUSIVE, &wformat->Format, NULL); - if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT) - EXIT_ON_ERROR(hr); - + MP_VERBOSE(ao, "Trying %s (exclusive) -> %s\n", + waveformat_to_str(&wformat->Format), mp_format_res_str(hr)); return SUCCEEDED(hr); -exit_label: - MP_ERR(state, "Error testing exclusive format: %s\n", mp_HRESULT_to_str(hr)); - return false; } // This works like try_format_exclusive(), but will try to fallback to the AC3 @@ -393,11 +387,8 @@ static bool search_channels(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat) for (int j = 0; channel_layouts[j]; j++) { mp_chmap_from_str(&entry, bstr0(channel_layouts[j])); if (!wformat->Format.nSamplesPerSec) { - if (search_samplerates(ao, wformat, &entry)) { + if (search_samplerates(ao, wformat, &entry)) mp_chmap_sel_add_map(&chmap_sel, &entry); - MP_VERBOSE(ao, "%s is supported\n", - waveformat_to_str(&wformat->Format)); - } } else { change_waveformat_channels(wformat, &entry); if (try_format_exclusive(ao, wformat)) @@ -442,11 +433,12 @@ static bool find_formats_shared(struct ao *ao) WAVEFORMATEXTENSIBLE wformat; set_waveformat_with_ao(&wformat, ao); - MP_VERBOSE(ao, "Trying %s (shared)\n", waveformat_to_str(&wformat.Format)); WAVEFORMATEX *closestMatch; HRESULT hr = IAudioClient_IsFormatSupported(state->pAudioClient, AUDCLNT_SHAREMODE_SHARED, &wformat.Format, &closestMatch); + MP_VERBOSE(ao, "Trying %s (shared) -> %s\n", + waveformat_to_str(&wformat.Format), mp_format_res_str(hr)); if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT) EXIT_ON_ERROR(hr); -- cgit v1.2.3 From 42799005dc8397fbe4ad56659a00542fbe2a15cb Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 7 Dec 2016 12:51:17 +0100 Subject: ao_alsa: print certain ALSA errors as string instead as number --- audio/out/ao_alsa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index d63a760d73..ac29905f5a 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -603,8 +603,8 @@ static int try_open_device(struct ao *ao, const char *device, int mode) const char *const fallbacks[] = {"hdmi", "iec958", NULL}; for (int n = 0; fallbacks[n]; n++) { char *ndev = append_params(tmp, fallbacks[n], params); - MP_VERBOSE(ao, "got error %d; opening iec fallback " - "device '%s'\n", err, ndev); + MP_VERBOSE(ao, "got error '%s'; opening iec fallback " + "device '%s'\n", snd_strerror(err), ndev); err = snd_pcm_open (&p->alsa, ndev, SND_PCM_STREAM_PLAYBACK, mode); if (err >= 0) -- cgit v1.2.3 From 3eceac2eab0b42ee082a0b615ebf40a21f0fb915 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 7 Dec 2016 19:44:29 +0100 Subject: Remove compatibility things Possible with bumped FFmpeg/Libav. These are just the simple cases. --- audio/decode/ad_lavc.c | 22 +--------------------- audio/decode/ad_spdif.c | 10 ---------- audio/filter/af_lavcac3enc.c | 16 ---------------- audio/filter/af_lavrresample.c | 5 ----- audio/out/ao_lavc.c | 23 ----------------------- 5 files changed, 1 insertion(+), 75 deletions(-) (limited to 'audio') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index e28558414d..276ce69739 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -207,7 +207,6 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, if (priv->needs_reset) control(da, ADCTRL_RESET, NULL); -#if HAVE_AVCODEC_NEW_CODEC_API int ret = avcodec_send_packet(avctx, &pkt); if (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { if (ret >= 0 && mpkt) @@ -220,24 +219,6 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) ret = 0; } -#else - int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt); - if (mpkt) { - // At least "shorten" decodes sub-frames, instead of the whole packet. - // At least "mpc8" can return 0 and wants the packet again next time. - if (ret >= 0) { - ret = FFMIN(ret, mpkt->len); // sanity check against decoder overreads - mpkt->buffer += ret; - mpkt->len -= ret; - mpkt->pts = MP_NOPTS_VALUE; // don't reset PTS next time - } - // LATM may need many packets to find mux info - if (ret == AVERROR(EAGAIN)) { - mpkt->len = 0; - return 0; - } - } -#endif if (ret < 0) { MP_ERR(da, "Error decoding audio.\n"); return -1; @@ -245,8 +226,7 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, if (!got_frame) return 0; - double out_pts = mp_pts_from_av(MP_AVFRAME_DEC_PTS(priv->avframe), - &priv->codec_timebase); + double out_pts = mp_pts_from_av(priv->avframe->pts, &priv->codec_timebase); struct mp_audio *mpframe = mp_audio_from_avframe(priv->avframe); if (!mpframe) diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 56e4a8102d..e15aca5c53 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -116,16 +116,10 @@ static int determine_codec_profile(struct dec_audio *da, AVPacket *pkt) goto done; } -#if HAVE_AVCODEC_NEW_CODEC_API if (avcodec_send_packet(ctx, pkt) < 0) goto done; if (avcodec_receive_frame(ctx, frame) < 0) goto done; -#else - int got_frame = 0; - if (avcodec_decode_audio4(ctx, frame, &got_frame, pkt) < 1 || !got_frame) - goto done; -#endif profile = ctx->profile; @@ -178,11 +172,7 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt) if (!stream) goto fail; -#if HAVE_AVCODEC_HAS_CODECPAR stream->codecpar->codec_id = spdif_ctx->codec_id; -#else - stream->codec->codec_id = spdif_ctx->codec_id; -#endif AVDictionary *format_opts = NULL; diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c index 0a7c5d4440..9df5adb96f 100644 --- a/audio/filter/af_lavcac3enc.c +++ b/audio/filter/af_lavcac3enc.c @@ -280,7 +280,6 @@ static int filter_out(struct af_instance *af) AVPacket pkt = {0}; av_init_packet(&pkt); -#if HAVE_AVCODEC_NEW_CODEC_API // Send input as long as it wants. while (1) { err = read_input_frame(af, frame); @@ -310,21 +309,6 @@ static int filter_out(struct af_instance *af) MP_FATAL(af, "Encode failed.\n"); goto done; } -#else - err = read_input_frame(af, frame); - if (err < 0) - goto done; - if (err == 0) - goto done; - err = -1; - int ok; - int lavc_ret = avcodec_encode_audio2(s->lavc_actx, &pkt, frame, &ok); - s->input->samples = 0; - if (lavc_ret < 0 || !ok) { - MP_FATAL(af, "Encode failed.\n"); - goto done; - } -#endif MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n", pkt.size, s->pending->samples + s->input->samples); diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c index dc5d1a0d23..828be66247 100644 --- a/audio/filter/af_lavrresample.c +++ b/audio/filter/af_lavrresample.c @@ -111,12 +111,7 @@ static double get_delay(struct af_resample *s) } static int get_out_samples(struct af_resample *s, int in_samples) { -#if LIBSWRESAMPLE_VERSION_MAJOR > 1 || LIBSWRESAMPLE_VERSION_MINOR >= 2 return swr_get_out_samples(s->avrctx, in_samples); -#else - return av_rescale_rnd(in_samples, s->out_rate, s->in_rate, AV_ROUND_UP) - + swr_get_delay(s->avrctx, s->out_rate); -#endif } #endif diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c index 8ae1317407..4dbc55a369 100644 --- a/audio/out/ao_lavc.c +++ b/audio/out/ao_lavc.c @@ -258,7 +258,6 @@ static void encode_audio_and_write(struct ao *ao, AVFrame *frame) struct priv *ac = ao->priv; AVPacket packet = {0}; -#if HAVE_AVCODEC_NEW_CODEC_API int status = avcodec_send_frame(ac->codec, frame); if (status < 0) { MP_ERR(ao, "error encoding at %d %d/%d\n", @@ -297,28 +296,6 @@ static void encode_audio_and_write(struct ao *ao, AVFrame *frame) write_packet(ao, &packet); av_packet_unref(&packet); } -#else - av_init_packet(&packet); - int got_packet = 0; - int status = avcodec_encode_audio2(ac->codec, &packet, frame, &got_packet); - if (status < 0) { - MP_ERR(ao, "error encoding at %d %d/%d\n", - frame ? (int) frame->pts : -1, - ac->codec->time_base.num, - ac->codec->time_base.den); - return; - } - if (!got_packet) { - return; - } - if (frame) { - if (ac->savepts == AV_NOPTS_VALUE) - ac->savepts = frame->pts; - } - encode_lavc_write_stats(ao->encode_lavc_ctx, ac->codec); - write_packet(ao, &packet); - av_packet_unref(&packet); -#endif } // must get exactly ac->aframesize amount of data -- cgit v1.2.3 From 2d9b6ff7cd51c352533e13bb24624c387415dbfb Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sun, 3 Jul 2016 17:41:45 -0700 Subject: ad_spdif: Fix crash when spdif muxer is not available Currently, if init_filter fails after lavf_ctx is allocated, uninit is called which frees lavf_ctx, but doesn't clear the pointer in spdif_ctx. So, on the next call of decode_packet, it thinks it is already initialized and uses it, resulting in a crash on my system. --- audio/decode/ad_spdif.c | 1 + 1 file changed, 1 insertion(+) (limited to 'audio') diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index e15aca5c53..60aef3b18f 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -71,6 +71,7 @@ static void uninit(struct dec_audio *da) av_freep(&lavf_ctx->pb->buffer); av_freep(&lavf_ctx->pb); avformat_free_context(lavf_ctx); + spdif_ctx->lavf_ctx = NULL; } } -- cgit v1.2.3 From e57037dc952def5c2b2d2be7535052f94dfb9294 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 18 Dec 2016 12:27:47 +0100 Subject: ad_lavc, vd_lavc: don't set AVCodecContext.refcounted_frames This field is (or should be) deprecated, and there's no need to set it with the new API. --- audio/decode/ad_lavc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'audio') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 276ce69739..c4d3a2ae7b 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -100,7 +100,6 @@ static int init(struct dec_audio *da, const char *decoder) lavc_context = avcodec_alloc_context3(lavc_codec); ctx->avctx = lavc_context; ctx->avframe = av_frame_alloc(); - lavc_context->refcounted_frames = 1; lavc_context->codec_type = AVMEDIA_TYPE_AUDIO; lavc_context->codec_id = lavc_codec->id; -- cgit v1.2.3 From c560f6ff0ab9aec70e53a268e2ff388a85ec3ca0 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 23 Dec 2016 18:03:16 +0100 Subject: audio: change how spdif codecs are selected Remove ad_spdif from the normal codec list, and select it explicitly. One goal was to decouple this from the normal codec selection, so they're less entangled and the decoder selection code can be simplified in the far future. This means spdif codec selection is now done explicitly via select_spdif_codec(). We can also remove the weird requirements on "dts" and "dts-hd" for the --audio-spdif option, and it can just do the right thing. Now both video and audio codecs consist of a single codec family each, vd_lavc and ad_lavc. --- audio/decode/ad_spdif.c | 49 ++++++++++++++++++++++++++++++++++++++---------- audio/decode/dec_audio.c | 9 ++++++--- audio/decode/dec_audio.h | 3 +++ 3 files changed, 48 insertions(+), 13 deletions(-) (limited to 'audio') diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 60aef3b18f..30c7883bf4 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -83,12 +83,10 @@ static int init(struct dec_audio *da, const char *decoder) spdif_ctx->use_dts_hd = da->opts->dtshd; spdif_ctx->pool = mp_audio_pool_create(spdif_ctx); - if (strcmp(decoder, "dts-hd") == 0) { - decoder = "dts"; + if (strcmp(decoder, "spdif_dts_hd") == 0) spdif_ctx->use_dts_hd = true; - } - spdif_ctx->codec_id = mp_codec_to_av_codec_id(decoder); + spdif_ctx->codec_id = mp_codec_to_av_codec_id(da->codec->codec); return spdif_ctx->codec_id != AV_CODEC_ID_NONE; } @@ -296,22 +294,53 @@ static const int codecs[] = { AV_CODEC_ID_NONE }; -static void add_decoders(struct mp_decoder_list *list) +static bool find_codec(const char *name) { for (int n = 0; codecs[n] != AV_CODEC_ID_NONE; n++) { const char *format = mp_codec_from_av_codec_id(codecs[n]); - if (format) { - mp_add_decoder(list, "spdif", format, format, - "libavformat/spdifenc audio pass-through decoder"); + if (format && name && strcmp(format, name) == 0) + return true; + } + return false; +} + +// codec is the libavcodec name of the source audio codec. +// pref is a ","-separated list of names, some of them which do not match with +// libavcodec names (like dts-hd). +struct mp_decoder_list *select_spdif_codec(const char *codec, const char *pref) +{ + struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); + + if (!find_codec(codec)) + return list; + + bool spdif_allowed = false, dts_hd_allowed = false; + bstr sel = bstr0(pref); + while (sel.len) { + bstr decoder; + bstr_split_tok(sel, ",", &decoder, &sel); + if (decoder.len) { + if (bstr_equals0(decoder, codec)) + spdif_allowed = true; + if (bstr_equals0(decoder, "dts-hd") && strcmp(codec, "dts") == 0) + spdif_allowed = dts_hd_allowed = true; } } - mp_add_decoder(list, "spdif", "dts", "dts-hd", + + if (!spdif_allowed) + return list; + + const char *suffix_name = dts_hd_allowed ? "dts_hd" : codec; + char name[80]; + snprintf(name, sizeof(name), "spdif_%s", suffix_name); + mp_add_decoder(list, "spdif", codec, name, "libavformat/spdifenc audio pass-through decoder"); + return list; } const struct ad_functions ad_spdif = { .name = "spdif", - .add_decoders = add_decoders, + .add_decoders = NULL, .init = init, .uninit = uninit, .control = control, diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 39e867cf42..c98d42f556 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -43,11 +43,12 @@ #include "audio/filter/af.h" extern const struct ad_functions ad_lavc; + +// Not a real codec - specially treated. extern const struct ad_functions ad_spdif; static const struct ad_functions * const ad_drivers[] = { &ad_lavc, - &ad_spdif, NULL }; @@ -91,9 +92,9 @@ static struct mp_decoder_list *audio_select_decoders(struct dec_audio *d_audio) struct mp_decoder_list *list = audio_decoder_list(); struct mp_decoder_list *new = mp_select_decoders(list, codec, opts->audio_decoders); - if (d_audio->try_spdif) { + if (d_audio->try_spdif && codec) { struct mp_decoder_list *spdif = - mp_select_decoder_list(list, codec, "spdif", opts->audio_spdif); + select_spdif_codec(codec, opts->audio_spdif); mp_append_decoders(spdif, new); talloc_free(new); new = spdif; @@ -108,6 +109,8 @@ static const struct ad_functions *find_driver(const char *name) if (strcmp(ad_drivers[i]->name, name) == 0) return ad_drivers[i]; } + if (strcmp(name, "spdif") == 0) + return &ad_spdif; return NULL; } diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h index 7bc8b00b0f..ebe7c8ae5b 100644 --- a/audio/decode/dec_audio.h +++ b/audio/decode/dec_audio.h @@ -59,4 +59,7 @@ int audio_get_frame(struct dec_audio *d_audio, struct mp_audio **out_frame); void audio_reset_decoding(struct dec_audio *d_audio); +// ad_spdif.c +struct mp_decoder_list *select_spdif_codec(const char *codec, const char *pref); + #endif /* MPLAYER_DEC_AUDIO_H */ -- cgit v1.2.3 From 9d21f2503f28a7be0e493ab18a4acbaae02c3d0a Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 23 Dec 2016 18:12:29 +0100 Subject: options: deprecate codec family selection in --vd/--ad Useless now, so get rid of it. Also affects some user-visible display things (like reported codec in use). --- audio/decode/dec_audio.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'audio') diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index c98d42f556..9f28302bd5 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -91,7 +91,7 @@ static struct mp_decoder_list *audio_select_decoders(struct dec_audio *d_audio) struct mp_decoder_list *list = audio_decoder_list(); struct mp_decoder_list *new = - mp_select_decoders(list, codec, opts->audio_decoders); + mp_select_decoders(d_audio->log, list, codec, opts->audio_decoders); if (d_audio->try_spdif && codec) { struct mp_decoder_list *spdif = select_spdif_codec(codec, opts->audio_spdif); @@ -129,21 +129,18 @@ int audio_init_best_codec(struct dec_audio *d_audio) const struct ad_functions *driver = find_driver(sel->family); if (!driver) continue; - MP_VERBOSE(d_audio, "Opening audio decoder %s:%s\n", - sel->family, sel->decoder); + MP_VERBOSE(d_audio, "Opening audio decoder %s\n", sel->decoder); d_audio->ad_driver = driver; if (init_audio_codec(d_audio, sel->decoder)) { decoder = sel; break; } - MP_WARN(d_audio, "Audio decoder init failed for " - "%s:%s\n", sel->family, sel->decoder); + MP_WARN(d_audio, "Audio decoder init failed for %s\n", sel->decoder); } if (d_audio->ad_driver) { d_audio->decoder_desc = - talloc_asprintf(d_audio, "%s [%s:%s]", decoder->desc, decoder->family, - decoder->decoder); + talloc_asprintf(d_audio, "%s (%s)", decoder->decoder, decoder->desc); MP_VERBOSE(d_audio, "Selected audio codec: %s\n", d_audio->decoder_desc); } else { MP_ERR(d_audio, "Failed to initialize an audio decoder for codec '%s'.\n", -- cgit v1.2.3