From 80f74137438df2cfe911907242ec96593642f64b Mon Sep 17 00:00:00 2001
From: John Cox <jc@kynesim.co.uk>
Date: Thu, 18 Jan 2024 15:57:30 +0000
Subject: [PATCH 03/14] v4l2_m2m_dec: Fix cma allocated s/w output

---
 libavcodec/v4l2_buffers.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index e412636a7a..b3ef74bcd4 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -486,6 +486,11 @@ static void v4l2_free_bufref(void *opaque, uint8_t *data)
         // Buffer still attached to context
         V4L2m2mContext *s = buf_to_m2mctx(avbuf);
 
+        if (!s->output_drm && avbuf->dmabuf[0] != NULL) {
+            for (unsigned int i = 0; i != avbuf->num_planes; ++i)
+                dmabuf_read_end(avbuf->dmabuf[i]);
+        }
+
         ff_mutex_lock(&ctx->lock);
 
         ff_v4l2_buffer_set_avail(avbuf);
@@ -533,6 +538,9 @@ static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
                 avbuf->buf.m.planes[i].m.fd = dma_fd;
             else
                 avbuf->buf.m.fd = dma_fd;
+
+            if (!s->output_drm)
+                avbuf->plane_info[i].mm_addr = dmabuf_map(avbuf->dmabuf[i]);
         }
         else {
             struct v4l2_exportbuffer expbuf;
@@ -647,6 +655,11 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf)
         break;
     }
 
+    if (avbuf->dmabuf[0] != NULL) {
+        for (unsigned int i = 0; i != avbuf->num_planes; ++i)
+            dmabuf_read_start(avbuf->dmabuf[i]);
+    }
+
     return 0;
 }
 
@@ -947,6 +960,7 @@ int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ct
     V4L2Buffer * const avbuf = av_mallocz(sizeof(*avbuf));
     AVBufferRef * bufref;
     V4L2m2mContext * const s = ctx_to_m2mctx(ctx);
+    int want_mmap;
 
     *pbufref = NULL;
     if (avbuf == NULL)
@@ -988,10 +1002,10 @@ int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ct
     } else
         avbuf->num_planes = 1;
 
-    for (i = 0; i < avbuf->num_planes; i++) {
-        const int want_mmap = avbuf->buf.memory == V4L2_MEMORY_MMAP &&
-            (V4L2_TYPE_IS_OUTPUT(ctx->type) || !buf_to_m2mctx(avbuf)->output_drm);
+    want_mmap = avbuf->buf.memory == V4L2_MEMORY_MMAP &&
+        (V4L2_TYPE_IS_OUTPUT(ctx->type) || !buf_to_m2mctx(avbuf)->output_drm);
 
+    for (i = 0; i < avbuf->num_planes; i++) {
         avbuf->plane_info[i].bytesperline = V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ?
             ctx->format.fmt.pix_mp.plane_fmt[i].bytesperline :
             ctx->format.fmt.pix.bytesperline;
@@ -1032,13 +1046,12 @@ int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ct
         avbuf->buf.length    = avbuf->planes[0].length;
     }
 
-    if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) {
-        if (s->output_drm) {
-            ret = v4l2_buffer_export_drm(avbuf);
-            if (ret) {
-                av_log(logger(avbuf), AV_LOG_ERROR, "Failed to get exported drm handles\n");
-                goto fail;
-            }
+    if (!want_mmap) {
+        // export_drm does dmabuf alloc if we aren't using v4l2 alloc
+        ret = v4l2_buffer_export_drm(avbuf);
+        if (ret) {
+            av_log(logger(avbuf), AV_LOG_ERROR, "Failed to get exported drm handles\n");
+            goto fail;
         }
     }
 
-- 
2.34.1

