0
0
mirror of https://github.com/libretro/Lakka-LibreELEC.git synced 2025-01-31 10:41:48 +00:00
Lakka-LibreELEC/projects/Amlogic/patches/ffmpeg/ffmpeg-0007-v4l2_m2m-Rework-use-of-ctx-lock-to-avoid-use-while-u.patch
Christian Hewitt 23942f808a ffmpeg: update Amlogic patches with recent commits from test/5.1.4/main
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
2024-03-24 14:58:21 +00:00

167 lines
5.5 KiB
Diff

From 4f458f6ef9d74a44029dab3c0416f630c96a968b Mon Sep 17 00:00:00 2001
From: John Cox <jc@kynesim.co.uk>
Date: Tue, 30 Jan 2024 16:25:53 +0000
Subject: [PATCH 07/14] v4l2_m2m: Rework use of ctx->lock to avoid use while
uninit
---
libavcodec/v4l2_buffers.c | 9 ++--
libavcodec/v4l2_context.c | 86 +++++++++++++++++++++++++++------------
2 files changed, 63 insertions(+), 32 deletions(-)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index b3ef74bcd4..e844a1a0b6 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -484,7 +484,7 @@ static void v4l2_free_bufref(void *opaque, uint8_t *data)
if (ctx != NULL) {
// Buffer still attached to context
- V4L2m2mContext *s = buf_to_m2mctx(avbuf);
+ V4L2m2mContext * const s = ctx_to_m2mctx(ctx);
if (!s->output_drm && avbuf->dmabuf[0] != NULL) {
for (unsigned int i = 0; i != avbuf->num_planes; ++i)
@@ -494,15 +494,14 @@ static void v4l2_free_bufref(void *opaque, uint8_t *data)
ff_mutex_lock(&ctx->lock);
ff_v4l2_buffer_set_avail(avbuf);
+ avbuf->buf.timestamp.tv_sec = 0;
+ avbuf->buf.timestamp.tv_usec = 0;
- if (s->draining && V4L2_TYPE_IS_OUTPUT(ctx->type)) {
+ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) {
av_log(logger(avbuf), AV_LOG_DEBUG, "%s: Buffer avail\n", ctx->name);
- /* no need to queue more buffers to the driver */
}
else if (ctx->streamon) {
av_log(logger(avbuf), AV_LOG_DEBUG, "%s: Buffer requeue\n", ctx->name);
- avbuf->buf.timestamp.tv_sec = 0;
- avbuf->buf.timestamp.tv_usec = 0;
ff_v4l2_buffer_enqueue(avbuf); // will set to IN_DRIVER
}
else {
diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index a01a105892..0d61a432c3 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -906,56 +906,88 @@ static int stuff_all_buffers(AVCodecContext * avctx, V4L2Context* ctx)
}
}
+ ff_mutex_lock(&ctx->lock);
for (i = 0; i < ctx->num_buffers; ++i) {
struct V4L2Buffer * const buf = (struct V4L2Buffer *)ctx->bufrefs[i]->data;
if (buf->status == V4L2BUF_AVAILABLE) {
rv = ff_v4l2_buffer_enqueue(buf);
if (rv < 0)
- return rv;
+ break;
}
}
- return 0;
+ ff_mutex_unlock(&ctx->lock);
+ return rv;
}
-int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd)
+static int set_streamon(AVCodecContext * const avctx, V4L2Context*const ctx)
{
int type = ctx->type;
int ret = 0;
- AVCodecContext * const avctx = logger(ctx);
+
+ if (!V4L2_TYPE_IS_OUTPUT(ctx->type))
+ stuff_all_buffers(avctx, ctx);
+
+ if (ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_STREAMON, &type) < 0) {
+ ret = AVERROR(errno);
+ av_log(avctx, AV_LOG_ERROR, "%s set status ON failed: err=%s\n", ctx->name,
+ av_err2str(ret));
+ return ret;
+ }
+
+ ctx->first_buf = 1;
+ ctx->streamon = 1;
+ ctx->flag_last = 0;
+ av_log(avctx, AV_LOG_DEBUG, "%s set status ON OK\n", ctx->name);
+ return ret;
+}
+
+static int set_streamoff(AVCodecContext * const avctx, V4L2Context*const ctx)
+{
+ int type = ctx->type;
+ int ret = 0;
+ const int has_bufs = ctx_buffers_alloced(ctx);
// Avoid doing anything if there is nothing we can do
- if (cmd == VIDIOC_STREAMOFF && !ctx_buffers_alloced(ctx) && !ctx->streamon)
+ if (!has_bufs && !ctx->streamon)
return 0;
- ff_mutex_lock(&ctx->lock);
-
- if (cmd == VIDIOC_STREAMON && !V4L2_TYPE_IS_OUTPUT(ctx->type))
- stuff_all_buffers(avctx, ctx);
+ if (has_bufs)
+ ff_mutex_lock(&ctx->lock);
- if (ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type) < 0) {
- const int err = errno;
- av_log(avctx, AV_LOG_ERROR, "%s set status %d (%s) failed: err=%d\n", ctx->name,
- cmd, (cmd == VIDIOC_STREAMON) ? "ON" : "OFF", err);
- ret = AVERROR(err);
+ if (ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_STREAMOFF, &type) < 0) {
+ ret = AVERROR(errno);
+ av_log(avctx, AV_LOG_ERROR, "%s set status ON failed: err=%s\n", ctx->name,
+ av_err2str(ret));
}
- else
- {
- if (cmd == VIDIOC_STREAMOFF)
- flush_all_buffers_status(ctx);
- else
- ctx->first_buf = 1;
+ else {
+ flush_all_buffers_status(ctx);
- ctx->streamon = (cmd == VIDIOC_STREAMON);
- av_log(avctx, AV_LOG_DEBUG, "%s set status %d (%s) OK\n", ctx->name,
- cmd, (cmd == VIDIOC_STREAMON) ? "ON" : "OFF");
+ ctx->streamon = 0;
+ ctx->flag_last = 0;
+
+ av_log(avctx, AV_LOG_DEBUG, "%s set status OFF OK\n", ctx->name);
}
- // Both stream off & on effectively clear flag_last
- ctx->flag_last = 0;
+ if (has_bufs)
+ ff_mutex_unlock(&ctx->lock);
+ return ret;
+}
- ff_mutex_unlock(&ctx->lock);
- return ret;
+int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd)
+{
+ AVCodecContext * const avctx = logger(ctx);
+
+ switch (cmd) {
+ case VIDIOC_STREAMOFF:
+ return set_streamoff(avctx, ctx);
+ case VIDIOC_STREAMON:
+ return set_streamon(avctx, ctx);
+ default:
+ av_log(avctx, AV_LOG_ERROR, "%s: Unexpected cmd: %d\n", __func__, cmd);
+ break;
+ }
+ return AVERROR_BUG;
}
int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame)
--
2.34.1