mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
ao_lavc, vo_lavc: Fix crashes in case of multiple init attempts.
When initialization failed, vo_lavc may cause an irrecoverable state in the ffmpeg-related structs. Therefore, we reject additional initialization attempts at least until we know a better way to clean up the mess. ao_lavc currently cannot be initialized more than once, yet it's good to do consistent changes there as well. Also, clean up uninit-after-failure handling to be less spammy.
This commit is contained in:
@@ -56,6 +56,8 @@ struct priv {
|
||||
|
||||
AVRational worst_time_base;
|
||||
int worst_time_base_is_stream;
|
||||
|
||||
bool shutdown;
|
||||
};
|
||||
|
||||
static void select_format(struct ao *ao, AVCodec *codec)
|
||||
@@ -174,6 +176,7 @@ static int init(struct ao *ao)
|
||||
|
||||
fail:
|
||||
pthread_mutex_unlock(&ao->encode_lavc_ctx->lock);
|
||||
ac->shutdown = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -184,6 +187,9 @@ static void uninit(struct ao *ao)
|
||||
struct priv *ac = ao->priv;
|
||||
struct encode_lavc_context *ectx = ao->encode_lavc_ctx;
|
||||
|
||||
if (!ac || ac->shutdown)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&ectx->lock);
|
||||
|
||||
if (!encode_lavc_start(ectx)) {
|
||||
@@ -201,6 +207,8 @@ static void uninit(struct ao *ao)
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&ectx->lock);
|
||||
|
||||
ac->shutdown = true;
|
||||
}
|
||||
|
||||
// return: how many bytes can be played without blocking
|
||||
|
||||
@@ -56,6 +56,8 @@ struct priv {
|
||||
int worst_time_base_is_stream;
|
||||
|
||||
struct mp_image_params real_colorspace;
|
||||
|
||||
bool shutdown;
|
||||
};
|
||||
|
||||
static int preinit(struct vo *vo)
|
||||
@@ -75,7 +77,7 @@ static void draw_image_unlocked(struct vo *vo, mp_image_t *mpi);
|
||||
static void uninit(struct vo *vo)
|
||||
{
|
||||
struct priv *vc = vo->priv;
|
||||
if (!vc)
|
||||
if (!vc || vc->shutdown)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&vo->encode_lavc_ctx->lock);
|
||||
@@ -86,6 +88,8 @@ static void uninit(struct vo *vo)
|
||||
mp_image_unrefp(&vc->lastimg);
|
||||
|
||||
pthread_mutex_unlock(&vo->encode_lavc_ctx->lock);
|
||||
|
||||
vc->shutdown = true;
|
||||
}
|
||||
|
||||
static int reconfig(struct vo *vo, struct mp_image_params *params, int flags)
|
||||
@@ -97,7 +101,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params, int flags)
|
||||
uint32_t width = params->w;
|
||||
uint32_t height = params->h;
|
||||
|
||||
if (!vc)
|
||||
if (!vc || vc->shutdown)
|
||||
return -1;
|
||||
|
||||
pthread_mutex_lock(&vo->encode_lavc_ctx->lock);
|
||||
@@ -132,6 +136,14 @@ static int reconfig(struct vo *vo, struct mp_image_params *params, int flags)
|
||||
goto error;
|
||||
}
|
||||
|
||||
// When we get here, this must be the first call to reconfigure(). Thus, we
|
||||
// can rely on no existing data in vc having been allocated yet.
|
||||
// Reason:
|
||||
// - Second calls after reconfigure() already failed once fail (due to the
|
||||
// vc->shutdown check above).
|
||||
// - Second calls after reconfigure() already succeeded once return early
|
||||
// (due to the vc->stream check above).
|
||||
|
||||
vc->lastipts = AV_NOPTS_VALUE;
|
||||
vc->lastframeipts = AV_NOPTS_VALUE;
|
||||
vc->lastencodedipts = AV_NOPTS_VALUE;
|
||||
@@ -169,15 +181,13 @@ static int reconfig(struct vo *vo, struct mp_image_params *params, int flags)
|
||||
|
||||
vc->buffer = talloc_size(vc, vc->buffer_size);
|
||||
|
||||
mp_image_unrefp(&vc->lastimg);
|
||||
|
||||
done:
|
||||
pthread_mutex_unlock(&vo->encode_lavc_ctx->lock);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
pthread_mutex_unlock(&vo->encode_lavc_ctx->lock);
|
||||
uninit(vo);
|
||||
vc->shutdown = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -288,7 +298,7 @@ static void draw_image_unlocked(struct vo *vo, mp_image_t *mpi)
|
||||
|
||||
double pts = mpi ? mpi->pts : MP_NOPTS_VALUE;
|
||||
|
||||
if (!vc)
|
||||
if (!vc || vc->shutdown)
|
||||
goto done;
|
||||
if (!encode_lavc_start(ectx)) {
|
||||
MP_WARN(vo, "NOTE: skipped initial video frame (probably because audio is not there yet)\n");
|
||||
|
||||
Reference in New Issue
Block a user