summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2018-04-29 19:42:18 +0200
committerJan Ekström <jeebjp@gmail.com>2018-05-03 01:08:44 +0300
commit0ab3184526e7b9b95c06a3ec7a6674283a5922d0 (patch)
tree4c05b192e65b51c68f3024b4b7946dcb79caf404 /audio
parent958053ff56109a38e9f8e0a0aa8786a5f47adb7c (diff)
downloadmpv-0ab3184526e7b9b95c06a3ec7a6674283a5922d0.tar.bz2
mpv-0ab3184526e7b9b95c06a3ec7a6674283a5922d0.tar.xz
encode: get rid of the output packet queue
Until recently, ao_lavc and vo_lavc started encoding whenever the core happened to send them data. Since audio and video are not initialized at the same time, and the muxer was not necessarily opened when the first encoder started to produce data, the resulting packets were put into a queue. As soon as the muxer was opened, the queue was flushed. Change this to make the core wait with sending data until all encoders are initialized. This has the advantage that we don't need to queue up the packets.
Diffstat (limited to 'audio')
-rw-r--r--audio/out/ao.c2
-rw-r--r--audio/out/ao.h3
-rw-r--r--audio/out/ao_lavc.c10
-rw-r--r--audio/out/internal.h4
-rw-r--r--audio/out/push.c17
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>