diff options
Diffstat (limited to 'audio')
-rw-r--r-- | audio/out/ao.c | 2 | ||||
-rw-r--r-- | audio/out/ao.h | 3 | ||||
-rw-r--r-- | audio/out/ao_lavc.c | 10 | ||||
-rw-r--r-- | audio/out/internal.h | 4 | ||||
-rw-r--r-- | audio/out/push.c | 17 |
5 files changed, 33 insertions, 3 deletions
diff --git a/audio/out/ao.c b/audio/out/ao.c index 8f6fc8ea3c..8fd24c2439 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -422,7 +422,7 @@ int ao_query_and_reset_events(struct ao *ao, int events) return atomic_fetch_and(&ao->events_, ~(unsigned)events) & events; } -static void ao_add_events(struct ao *ao, int events) +void ao_add_events(struct ao *ao, int events) { atomic_fetch_or(&ao->events_, events); ao->wakeup_cb(ao->wakeup_ctx); diff --git a/audio/out/ao.h b/audio/out/ao.h index b9df4ebb00..99a3d0fae0 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -48,6 +48,7 @@ enum aocontrol { enum { AO_EVENT_RELOAD = 1, AO_EVENT_HOTPLUG = 2, + AO_EVENT_INITIAL_UNBLOCK = 4, }; enum { @@ -104,6 +105,8 @@ void ao_resume(struct ao *ao); void ao_drain(struct ao *ao); bool ao_eof_reached(struct ao *ao); int ao_query_and_reset_events(struct ao *ao, int events); +void ao_add_events(struct ao *ao, int events); +void ao_unblock(struct ao *ao); void ao_request_reload(struct ao *ao); void ao_hotplug_event(struct ao *ao); diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c index bb86224229..974d9d0b63 100644 --- a/audio/out/ao_lavc.c +++ b/audio/out/ao_lavc.c @@ -84,6 +84,13 @@ static void select_format(struct ao *ao, const AVCodec *codec) } } +static void on_ready(void *ptr) +{ + struct ao *ao = ptr; + + ao_add_events(ao, AO_EVENT_INITIAL_UNBLOCK); +} + // open & setup audio device static int init(struct ao *ao) { @@ -123,7 +130,7 @@ static int init(struct ao *ao) encoder->sample_fmt = af_to_avformat(ao->format); encoder->bits_per_raw_sample = ac->sample_size * 8; - if (!encoder_init_codec_and_muxer(ac->enc)) + if (!encoder_init_codec_and_muxer(ac->enc, on_ready, ao)) goto fail; ac->pcmhack = 0; @@ -342,6 +349,7 @@ const struct ao_driver audio_out_lavc = { .encode = true, .description = "audio encoding using libavcodec", .name = "lavc", + .initially_blocked = true, .priv_size = sizeof(struct priv), .init = init, .uninit = uninit, diff --git a/audio/out/internal.h b/audio/out/internal.h index 33e8a8c6a9..bf769d7e1c 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -130,6 +130,10 @@ struct ao_driver { const char *name; // Description shown with --ao=help. const char *description; + // This requires waiting for a AO_EVENT_INITIAL_UNBLOCK event before the + // first play() call is done. Encode mode uses this, and push mode + // respects it automatically (don't use with pull mode). + bool initially_blocked; // 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. diff --git a/audio/out/push.c b/audio/out/push.c index b198afef91..470f521c68 100644 --- a/audio/out/push.c +++ b/audio/out/push.c @@ -56,6 +56,7 @@ struct ao_push_state { bool still_playing; bool need_wakeup; bool paused; + bool initial_unblocked; // Whether the current buffer contains the complete audio. bool final_chunk; @@ -357,7 +358,8 @@ static void *playthread(void *arg) mpthread_set_name("ao"); pthread_mutex_lock(&p->lock); while (!p->terminate) { - bool playing = !p->paused || ao->stream_silence; + bool blocked = ao->driver->initially_blocked && !p->initial_unblocked; + bool playing = (!p->paused || ao->stream_silence) && !blocked; if (playing) ao_play_data(ao); @@ -502,6 +504,19 @@ int ao_play_silence(struct ao *ao, int samples) return ao->driver->play(ao, (void **)p->silence, samples, 0); } +void ao_unblock(struct ao *ao) +{ + if (ao->api == &ao_api_push) { + struct ao_push_state *p = ao->api_priv; + pthread_mutex_lock(&p->lock); + p->need_wakeup = true; + p->initial_unblocked = true; + wakeup_playthread(ao); + pthread_cond_signal(&p->wakeup); + pthread_mutex_unlock(&p->lock); + } +} + #ifndef __MINGW32__ #include <poll.h> |