mirror of
https://github.com/libretro/Lakka-LibreELEC.git
synced 2025-01-31 10:41:48 +00:00
23942f808a
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
167 lines
5.5 KiB
Diff
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
|
|
|