From eab92cec60d92e0de2ea53d4d01052f4d7acc5d5 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 9 Aug 2016 16:22:06 +0200 Subject: player: add --audio-stream-silence Completely insane that this has to be done. Crap for compensating HDMI crap. --- DOCS/man/options.rst | 11 +++++++++++ audio/out/ao.c | 2 ++ audio/out/ao.h | 2 ++ audio/out/internal.h | 1 + audio/out/pull.c | 8 ++++++-- options/options.c | 1 + options/options.h | 1 + player/audio.c | 3 +++ 8 files changed, 27 insertions(+), 2 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 456c3c3f94..344b77bf3a 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -1341,6 +1341,17 @@ Audio Default: 0.2 (200 ms). +``--audio-stream-silence=`` + Cash-grab consumer audio hardware (such as A/V receivers) often ignore + initial audio sent over HDMI. This can happen every time audio over HDMI + is stopped and resumed. In order to compensate for this, you can enable + this option to not to stop and restart audio on seeks, and fill the gaps + with silence. Likewise, when pausing playback, audio is not stopped, and + silence is played while paused. Note that if no audio track is selected, + the audio device will still be closed immediately. + + Not all AOs support this. + Subtitles --------- diff --git a/audio/out/ao.c b/audio/out/ao.c index 0647067e50..cf66e0c64b 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -183,6 +183,8 @@ static struct ao *ao_init(bool probing, struct mpv_global *global, ao->api_priv = talloc_zero_size(ao, ao->api->priv_size); assert(!ao->api->priv_defaults && !ao->api->options); + ao->stream_silence = flags & AO_INIT_STREAM_SILENCE; + int r = ao->driver->init(ao); if (r < 0) { // Silly exception for coreaudio spdif redirection diff --git a/audio/out/ao.h b/audio/out/ao.h index 3c16cef0e5..3b187e7355 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -56,6 +56,8 @@ enum { // Only accept multichannel configurations that are guaranteed to work // (i.e. not sending arbitrary layouts over HDMI). AO_INIT_SAFE_MULTICHANNEL_ONLY = 1 << 1, + // Stream silence as long as no audio is playing. + AO_INIT_STREAM_SILENCE = 1 << 2, }; typedef struct ao_control_vol { diff --git a/audio/out/internal.h b/audio/out/internal.h index 88160bbeb6..518661c2bd 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -44,6 +44,7 @@ struct ao { struct input_ctx *input_ctx; struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix int init_flags; // AO_INIT_* flags + bool stream_silence; // if audio inactive, just play silence // The device as selected by the user, usually using ao_device_desc.name // from an entry from the list returned by driver->list_devices. If the diff --git a/audio/out/pull.c b/audio/out/pull.c index 89805809b7..2175a58db0 100644 --- a/audio/out/pull.c +++ b/audio/out/pull.c @@ -185,7 +185,7 @@ static double get_delay(struct ao *ao) static void reset(struct ao *ao) { struct ao_pull_state *p = ao->api_priv; - if (ao->driver->reset) + if (!ao->stream_silence && ao->driver->reset) ao->driver->reset(ao); // assumes the audio callback thread is stopped set_state(ao, AO_STATE_NONE); for (int n = 0; n < ao->num_planes; n++) @@ -195,7 +195,7 @@ static void reset(struct ao *ao) static void pause(struct ao *ao) { - if (ao->driver->reset) + if (!ao->stream_silence && ao->driver->reset) ao->driver->reset(ao); set_state(ao, AO_STATE_NONE); } @@ -244,6 +244,10 @@ static int init(struct ao *ao) p->buffers[n] = mp_ring_new(ao, ao->buffer * ao->sstride); atomic_store(&p->state, AO_STATE_NONE); assert(ao->driver->resume); + + if (ao->stream_silence) + ao->driver->resume(ao); + return 0; } diff --git a/options/options.c b/options/options.c index 9fd853ffda..833568659f 100644 --- a/options/options.c +++ b/options/options.c @@ -396,6 +396,7 @@ const m_option_t mp_opts[] = { OPT_STRING("audio-device", audio_device, 0), OPT_STRING("audio-client-name", audio_client_name, 0), OPT_FLAG("audio-fallback-to-null", ao_null_fallback, 0), + OPT_FLAG("audio-stream-silence", audio_stream_silence, 0), OPT_CHOICE("force-window", force_vo, 0, ({"no", 0}, {"yes", 1}, {"immediate", 2})), OPT_FLAG("taskbar-progress", vo.taskbar_progress, 0), diff --git a/options/options.h b/options/options.h index ef72865f56..2aff254fbd 100644 --- a/options/options.h +++ b/options/options.h @@ -87,6 +87,7 @@ typedef struct MPOpts { char *audio_device; char *audio_client_name; int ao_null_fallback; + int audio_stream_silence; int force_vo; int softvol; float softvol_volume; diff --git a/player/audio.c b/player/audio.c index e186a375b6..1f0fe9d0a0 100644 --- a/player/audio.c +++ b/player/audio.c @@ -382,6 +382,9 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx) if (!opts->audio_output_channels.set || opts->audio_output_channels.auto_safe) ao_flags |= AO_INIT_SAFE_MULTICHANNEL_ONLY; + if (opts->audio_stream_silence) + ao_flags |= AO_INIT_STREAM_SILENCE; + mp_chmap_sel_list(&afs->output.channels, opts->audio_output_channels.chmaps, opts->audio_output_channels.num_chmaps); -- cgit v1.2.3