summaryrefslogtreecommitdiffstats
path: root/video
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 /video
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 'video')
-rw-r--r--video/out/vo.c4
-rw-r--r--video/out/vo.h11
-rw-r--r--video/out/vo_lavc.c10
3 files changed, 22 insertions, 3 deletions
diff --git a/video/out/vo.c b/video/out/vo.c
index 624136bd47..acae4f2acb 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -750,7 +750,9 @@ bool vo_is_ready_for_frame(struct vo *vo, int64_t next_pts)
{
struct vo_internal *in = vo->in;
pthread_mutex_lock(&in->lock);
- bool r = vo->config_ok && !in->frame_queued &&
+ bool blocked = vo->driver->initially_blocked &&
+ !(in->internal_events & VO_EVENT_INITIAL_UNBLOCK);
+ bool r = vo->config_ok && !in->frame_queued && !blocked &&
(!in->current_frame || in->current_frame->num_vsyncs < 1);
if (r && next_pts >= 0) {
// Don't show the frame too early - it would basically freeze the
diff --git a/video/out/vo.h b/video/out/vo.h
index 17cb692356..3c00bb988e 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -45,10 +45,13 @@ enum {
VO_EVENT_LIVE_RESIZING = 1 << 5,
// Window fullscreen state changed via external influence.
VO_EVENT_FULLSCREEN_STATE = 1 << 6,
+ // Special thing for encode mode (vo_driver.initially_blocked).
+ // Part of VO_EVENTS_USER to make vo_is_ready_for_frame() work properly.
+ VO_EVENT_INITIAL_UNBLOCK = 1 << 7,
// Set of events the player core may be interested in.
VO_EVENTS_USER = VO_EVENT_RESIZE | VO_EVENT_WIN_STATE |
- VO_EVENT_FULLSCREEN_STATE,
+ VO_EVENT_FULLSCREEN_STATE | VO_EVENT_INITIAL_UNBLOCK,
};
enum mp_voctrl {
@@ -264,6 +267,12 @@ struct vo_driver {
// Encoding functionality, which can be invoked via --o only.
bool encode;
+ // This requires waiting for a VO_EVENT_INITIAL_UNBLOCK event before the
+ // first frame can be sent. Doing vo_reconfig*() calls is allowed though.
+ // Encode mode uses this, the core uses vo_is_ready_for_frame() to
+ // implicitly check for this.
+ bool initially_blocked;
+
// VO_CAP_* bits
int caps;
diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c
index 2f48e3f750..e817b530e0 100644
--- a/video/out/vo_lavc.c
+++ b/video/out/vo_lavc.c
@@ -60,6 +60,13 @@ static void uninit(struct vo *vo)
encoder_encode(enc, NULL); // finish encoding
}
+static void on_ready(void *ptr)
+{
+ struct vo *vo = ptr;
+
+ vo_event(vo, VO_EVENT_INITIAL_UNBLOCK);
+}
+
static int reconfig2(struct vo *vo, struct mp_image *img)
{
struct priv *vc = vo->priv;
@@ -127,7 +134,7 @@ static int reconfig2(struct vo *vo, struct mp_image *img)
encoder->time_base = av_inv_q(tb);
- if (!encoder_init_codec_and_muxer(vc->enc))
+ if (!encoder_init_codec_and_muxer(vc->enc, on_ready, vo))
goto error;
return 0;
@@ -233,6 +240,7 @@ const struct vo_driver video_out_lavc = {
.encode = true,
.description = "video encoding using libavcodec",
.name = "lavc",
+ .initially_blocked = true,
.untimed = true,
.priv_size = sizeof(struct priv),
.preinit = preinit,