Skip to content

Commit

Permalink
ffmpeg: update Amlogic patches with recent commits from test/5.1.4/main
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
  • Loading branch information
chewitt committed Mar 24, 2024
1 parent 353213e commit 23942f8
Show file tree
Hide file tree
Showing 14 changed files with 894 additions and 0 deletions.
@@ -0,0 +1,62 @@
From 162a9ac64b7babb4e831df86f6ed0efdfe84204e Mon Sep 17 00:00:00 2001
From: John Cox <jc@kynesim.co.uk>
Date: Fri, 12 Jan 2024 15:17:43 +0000
Subject: [PATCH 01/14] vf_bwdif: Add capability to deinterlace NV12

As bwdif takes no account of horizontally adjacent pixels the same
code can be used on planes that have multiple components as is used
on single component planes. Update the filtering code to cope with
multi-component planes and add NV12 to the list of supported formats.

Signed-off-by: John Cox <jc@kynesim.co.uk>
---
libavfilter/vf_bwdif.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c
index 9847d38b6a..4d69b3039d 100644
--- a/libavfilter/vf_bwdif.c
+++ b/libavfilter/vf_bwdif.c
@@ -302,19 +302,28 @@ static void filter(AVFilterContext *ctx, AVFrame *dstpic,
YADIFContext *yadif = &bwdif->yadif;
ThreadData td = { .frame = dstpic, .parity = parity, .tff = tff };
int i;
+ int last_plane = -1;

for (i = 0; i < yadif->csp->nb_components; i++) {
int w = dstpic->width;
int h = dstpic->height;
+ const AVComponentDescriptor * const comp = yadif->csp->comp + i;
+
+ // If the last plane was the same as this plane assume we've dealt
+ // with all the pels already
+ if (last_plane == comp->plane)
+ continue;
+ last_plane = comp->plane;

if (i == 1 || i == 2) {
w = AV_CEIL_RSHIFT(w, yadif->csp->log2_chroma_w);
h = AV_CEIL_RSHIFT(h, yadif->csp->log2_chroma_h);
}

- td.w = w;
- td.h = h;
- td.plane = i;
+ // comp step is in bytes but td.w is in pels
+ td.w = w * comp->step / ((comp->depth + 7) / 8);
+ td.h = h;
+ td.plane = comp->plane;

ff_filter_execute(ctx, filter_slice, &td, NULL,
FFMIN((h+3)/4, ff_filter_get_nb_threads(ctx)));
@@ -350,6 +359,7 @@ static const enum AVPixelFormat pix_fmts[] = {
AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9,
AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10,
AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16,
+ AV_PIX_FMT_NV12,
AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16,
AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP16,
--
2.34.1

@@ -0,0 +1,65 @@
From 4960acb627d736421251500b3e4e0e88d3b12cd1 Mon Sep 17 00:00:00 2001
From: John Cox <jc@kynesim.co.uk>
Date: Fri, 12 Jan 2024 16:46:27 +0000
Subject: [PATCH 02/14] v4l2_m2m_dec: Try to accomodate ffmpegs ideas about
default s/w fmts

---
libavcodec/v4l2_m2m_dec.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index f67dd23ba1..3883223079 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -1079,7 +1079,6 @@ choose_capture_format(AVCodecContext * const avctx, V4L2m2mContext * const s)
unsigned int fmts_n;
uint32_t *fmts = ff_v4l2_context_enum_drm_formats(&s->capture, &fmts_n);
enum AVPixelFormat *fmts2 = NULL;
- enum AVPixelFormat t;
enum AVPixelFormat gf_pix_fmt;
unsigned int i;
unsigned int n = 0;
@@ -1089,7 +1088,7 @@ choose_capture_format(AVCodecContext * const avctx, V4L2m2mContext * const s)
if (!fmts)
return AVERROR(ENOENT);

- if ((fmts2 = av_malloc(sizeof(*fmts2) * (fmts_n + 2))) == NULL) {
+ if ((fmts2 = av_malloc(sizeof(*fmts2) * (fmts_n + 3))) == NULL) {
rv = AVERROR(ENOMEM);
goto error;
}
@@ -1110,17 +1109,25 @@ choose_capture_format(AVCodecContext * const avctx, V4L2m2mContext * const s)
pref_n = n;
fmts2[n++] = f;
}
- fmts2[n] = AV_PIX_FMT_NONE;

if (n < 2) {
av_log(avctx, AV_LOG_DEBUG, "%s: No usable formats found\n", __func__);
goto error;
}

- // Put preferred s/w format at the end - ff_get_format will put it in sw_pix_fmt
- t = fmts2[n - 1];
- fmts2[n - 1] = fmts2[pref_n];
- fmts2[pref_n] = t;
+ if (n != 2) {
+ // ffmpeg.c really only expects one s/w format. It thinks that the
+ // last format in the list is the s/w format of the h/w format but
+ // also chooses the first non-h/w format as the preferred s/w format.
+ // The only way of reconciling this is to dup our preferred format into
+ // both last & first place :-(
+ const enum AVPixelFormat t = fmts2[pref_n];
+ fmts2[pref_n] = fmts2[1];
+ fmts2[1] = t;
+ fmts2[n++] = t;
+ }
+
+ fmts2[n] = AV_PIX_FMT_NONE;

gf_pix_fmt = ff_get_format(avctx, fmts2);
av_log(avctx, AV_LOG_DEBUG, "avctx requested=%d (%s) %dx%d; get_format requested=%d (%s)\n",
--
2.34.1

@@ -0,0 +1,92 @@
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

@@ -0,0 +1,109 @@
From c1328b956e9856210b1f2bc20c20fd152c309123 Mon Sep 17 00:00:00 2001
From: John Cox <jc@kynesim.co.uk>
Date: Mon, 29 Jan 2024 15:12:34 +0000
Subject: [PATCH 04/14] v4l2_req: Fix media pool delete race

fds & polltasks associated with media fds that are still in flight are
not freed on delete but the main pool is leading to use after free when
they finally do complete. Stop scanning the free chain on delete and
simply delete everything, in-flight or not. This requires changing alloc
as the buffers weren't previously tracked in-flight.
---
libavcodec/v4l2_req_media.c | 38 ++++++++++++++++++++-----------------
1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/libavcodec/v4l2_req_media.c b/libavcodec/v4l2_req_media.c
index 0394bb2b23..c94cc5b0f6 100644
--- a/libavcodec/v4l2_req_media.c
+++ b/libavcodec/v4l2_req_media.c
@@ -86,6 +86,8 @@ struct media_pool {
int fd;
sem_t sem;
pthread_mutex_t lock;
+ unsigned int pool_n;
+ struct media_request * pool_reqs;
struct media_request * free_reqs;
struct pollqueue * pq;
};
@@ -251,18 +253,17 @@ int media_request_abort(struct media_request ** const preq)
return 0;
}

-static void delete_req_chain(struct media_request * const chain)
+static void free_req_pool(struct media_request * const pool, const unsigned int n)
{
- struct media_request * next = chain;
- while (next) {
- struct media_request * const req = next;
- next = req->next;
+ unsigned int i;
+ for (i = 0; i != n; ++i) {
+ struct media_request * const req = pool + i;
if (req->pt)
polltask_delete(&req->pt);
if (req->fd != -1)
close(req->fd);
- free(req);
}
+ free(pool);
}

struct media_pool * media_pool_new(const char * const media_path,
@@ -283,17 +284,16 @@ struct media_pool * media_pool_new(const char * const media_path,
goto fail1;
}

+ if ((mp->pool_reqs = calloc(n, sizeof(*mp->pool_reqs))) == NULL)
+ goto fail3;
+ mp->pool_n = n;
for (i = 0; i != n; ++i) {
- struct media_request * req = malloc(sizeof(*req));
- if (!req)
- goto fail4;
+ mp->pool_reqs[i].mp = mp;
+ mp->pool_reqs[i].fd = -1;
+ }

- *req = (struct media_request){
- .next = mp->free_reqs,
- .mp = mp,
- .fd = -1
- };
- mp->free_reqs = req;
+ for (i = 0; i != n; ++i) {
+ struct media_request * const req = mp->pool_reqs + i;

if (ioctl(mp->fd, MEDIA_IOC_REQUEST_ALLOC, &req->fd) == -1) {
request_log("Failed to alloc request %d: %s\n", i, strerror(errno));
@@ -303,6 +303,9 @@ struct media_pool * media_pool_new(const char * const media_path,
req->pt = polltask_new(pq, req->fd, POLLPRI, media_request_done, req);
if (!req->pt)
goto fail4;
+
+ req->next = mp->free_reqs,
+ mp->free_reqs = req;
}

sem_init(&mp->sem, 0, n);
@@ -310,7 +313,8 @@ struct media_pool * media_pool_new(const char * const media_path,
return mp;

fail4:
- delete_req_chain(mp->free_reqs);
+ free_req_pool(mp->pool_reqs, mp->pool_n);
+fail3:
close(mp->fd);
pthread_mutex_destroy(&mp->lock);
fail1:
@@ -327,7 +331,7 @@ void media_pool_delete(struct media_pool ** pMp)
return;
*pMp = NULL;

- delete_req_chain(mp->free_reqs);
+ free_req_pool(mp->pool_reqs, mp->pool_n);
close(mp->fd);
sem_destroy(&mp->sem);
pthread_mutex_destroy(&mp->lock);
--
2.34.1

@@ -0,0 +1,30 @@
From 613e5cbb5e0a7626377876e9a441c614afe1e25e Mon Sep 17 00:00:00 2001
From: John Cox <jc@kynesim.co.uk>
Date: Tue, 30 Jan 2024 14:24:59 +0000
Subject: [PATCH 05/14] drm_vout: Fix connector etc. desc memory leak

---
libavdevice/drm_vout.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/libavdevice/drm_vout.c b/libavdevice/drm_vout.c
index 491e1dc608..275748abdc 100644
--- a/libavdevice/drm_vout.c
+++ b/libavdevice/drm_vout.c
@@ -501,6 +501,13 @@ static int find_crtc(struct AVFormatContext * const avctx, int drmfd, struct drm
crtc ? crtc->height : 0,
(s->conId == (int)con->connector_id ?
" (chosen)" : ""));
+
+ if (crtc)
+ drmModeFreeCrtc(crtc);
+ if (enc)
+ drmModeFreeEncoder(enc);
+ if (con)
+ drmModeFreeConnector(con);
}

if (!s->conId) {
--
2.34.1

0 comments on commit 23942f8

Please sign in to comment.