summaryrefslogtreecommitdiffstats
path: root/common/encode_lavc.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-03-08 23:38:53 +0100
committerwm4 <wm4@nowhere>2014-03-09 00:19:35 +0100
commit5ffd6a9e9b7a0d894d7513ad20c24c2727426ecd (patch)
treef87a9c927774d8829ab2a920dcd857d2ee54a4e2 /common/encode_lavc.c
parentb48d09a89dd14616e5ae4e9d017b921486d5f541 (diff)
downloadmpv-5ffd6a9e9b7a0d894d7513ad20c24c2727426ecd.tar.bz2
mpv-5ffd6a9e9b7a0d894d7513ad20c24c2727426ecd.tar.xz
encode: add locking
Since the AO will run in a thread, and there's lots of shared state with encoding, we have to add locking. One case this doesn't handle correctly are the encode_lavc_available() calls in ao_lavc.c and vo_lavc.c. They don't do much (and usually only to protect against doing --ao=lavc with normal playback), and changing it would be a bit messy. So just leave them.
Diffstat (limited to 'common/encode_lavc.c')
-rw-r--r--common/encode_lavc.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/common/encode_lavc.c b/common/encode_lavc.c
index 5f9e2a0390..5d9853673b 100644
--- a/common/encode_lavc.c
+++ b/common/encode_lavc.c
@@ -103,6 +103,15 @@ static bool value_has_flag(const char *value, const char *flag)
return val; \
}
+#define CHECK_FAIL_UNLOCK(ctx, val) \
+ if (ctx && (ctx->failed || ctx->finished)) { \
+ MP_ERR(ctx, \
+ "Called a function on a %s encoding context. Bailing out.\n", \
+ ctx->failed ? "failed" : "finished"); \
+ pthread_mutex_unlock(&ctx->lock); \
+ return val; \
+ }
+
int encode_lavc_available(struct encode_lavc_context *ctx)
{
CHECK_FAIL(ctx, 0);
@@ -134,6 +143,7 @@ struct encode_lavc_context *encode_lavc_init(struct encode_output_conf *options,
mp_msg_force_stderr(global, true);
ctx = talloc_zero(NULL, struct encode_lavc_context);
+ pthread_mutex_init(&ctx->lock, NULL);
ctx->log = mp_log_new(ctx, global->log, "encode-lavc");
ctx->global = global;
encode_lavc_discontinuity(ctx);
@@ -309,6 +319,7 @@ void encode_lavc_free(struct encode_lavc_context *ctx)
encode_lavc_fail(ctx,
"called encode_lavc_free without encode_lavc_finish\n");
+ pthread_mutex_destroy(&ctx->lock);
talloc_free(ctx);
}
@@ -383,14 +394,18 @@ void encode_lavc_finish(struct encode_lavc_context *ctx)
void encode_lavc_set_video_fps(struct encode_lavc_context *ctx, float fps)
{
+ pthread_mutex_lock(&ctx->lock);
ctx->vo_fps = fps;
+ pthread_mutex_unlock(&ctx->lock);
}
void encode_lavc_set_audio_pts(struct encode_lavc_context *ctx, double pts)
{
if (ctx) {
+ pthread_mutex_lock(&ctx->lock);
ctx->last_audio_in_pts = pts;
ctx->samples_since_last_pts = 0;
+ pthread_mutex_unlock(&ctx->lock);
}
}
@@ -780,11 +795,15 @@ void encode_lavc_discontinuity(struct encode_lavc_context *ctx)
if (!ctx)
return;
- CHECK_FAIL(ctx, );
+ pthread_mutex_lock(&ctx->lock);
+
+ CHECK_FAIL_UNLOCK(ctx, );
ctx->audio_pts_offset = MP_NOPTS_VALUE;
ctx->last_video_in_pts = MP_NOPTS_VALUE;
ctx->discontinuity_pts_offset = MP_NOPTS_VALUE;
+
+ pthread_mutex_unlock(&ctx->lock);
}
static void encode_lavc_printoptions(struct mp_log *log, void *obj,
@@ -1013,7 +1032,9 @@ int encode_lavc_getstatus(struct encode_lavc_context *ctx,
if (!ctx)
return -1;
- CHECK_FAIL(ctx, -1);
+ pthread_mutex_lock(&ctx->lock);
+
+ CHECK_FAIL_UNLOCK(ctx, -1);
minutes = (now - ctx->t0) / 60.0 * (1 - f) / f;
megabytes = ctx->avc->pb ? (avio_size(ctx->avc->pb) / 1048576.0 / f) : 0;
@@ -1029,12 +1050,16 @@ int encode_lavc_getstatus(struct encode_lavc_context *ctx,
snprintf(buf, bufsize, "{%.1fmin %.1fMB}",
minutes, megabytes);
buf[bufsize - 1] = 0;
+
+ pthread_mutex_unlock(&ctx->lock);
return 0;
}
void encode_lavc_expect_stream(struct encode_lavc_context *ctx, int mt)
{
- CHECK_FAIL(ctx, );
+ pthread_mutex_lock(&ctx->lock);
+
+ CHECK_FAIL_UNLOCK(ctx, );
switch (mt) {
case AVMEDIA_TYPE_VIDEO:
@@ -1044,11 +1069,18 @@ void encode_lavc_expect_stream(struct encode_lavc_context *ctx, int mt)
ctx->expect_audio = true;
break;
}
+
+ pthread_mutex_unlock(&ctx->lock);
}
bool encode_lavc_didfail(struct encode_lavc_context *ctx)
{
- return ctx && ctx->failed;
+ if (!ctx)
+ return false;
+ pthread_mutex_lock(&ctx->lock);
+ bool fail = ctx && ctx->failed;
+ pthread_mutex_unlock(&ctx->lock);
+ return fail;
}
void encode_lavc_fail(struct encode_lavc_context *ctx, const char *format, ...)