mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-08-03 16:07:51 +00:00
Rockchip: ffmpeg: support more formats / automatic output format selection in deinterlace filter
Also increase input/output buffer count
This commit is contained in:
parent
3198acc472
commit
7b46405ddb
@ -0,0 +1,26 @@
|
||||
From 1a4b8070ff968a07dc24467922849c1142995e30 Mon Sep 17 00:00:00 2001
|
||||
From: popcornmix <popcornmix@gmail.com>
|
||||
Date: Tue, 14 Sep 2021 19:14:24 +0100
|
||||
Subject: [PATCH] deint_v4l2m2m: increase input and output buffers
|
||||
|
||||
Required for advanced deinterlacer on pi
|
||||
---
|
||||
libavfilter/vf_deinterlace_v4l2m2m.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
index a545d551d9ee..0adc96d25435 100644
|
||||
--- a/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
+++ b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
@@ -954,9 +954,9 @@ static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx)
|
||||
priv->shared = ctx;
|
||||
ctx->fd = -1;
|
||||
ctx->output.ctx = ctx;
|
||||
- ctx->output.num_buffers = 6;
|
||||
+ ctx->output.num_buffers = 8;
|
||||
ctx->capture.ctx = ctx;
|
||||
- ctx->capture.num_buffers = 6;
|
||||
+ ctx->capture.num_buffers = 8;
|
||||
ctx->done = 0;
|
||||
ctx->field_order = V4L2_FIELD_ANY;
|
||||
ctx->cur_in_frame = NULL;
|
@ -0,0 +1,288 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Bee <knaerzche@gmail.com>
|
||||
Date: Wed, 15 Sep 2021 00:37:15 +0200
|
||||
Subject: [PATCH] libavfilter: v4l2deinterlace: support more formats /
|
||||
automatic output format selection
|
||||
|
||||
Signed-off-by: Alex Bee <knaerzche@gmail.com>
|
||||
---
|
||||
libavfilter/vf_deinterlace_v4l2m2m.c | 120 +++++++++++++++++++++++----
|
||||
1 file changed, 102 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
index d7935d92f9..8161fd9e75 100644
|
||||
--- a/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
+++ b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
@@ -85,6 +85,9 @@ typedef struct DeintV4L2M2MContextShared {
|
||||
int height;
|
||||
int orig_width;
|
||||
int orig_height;
|
||||
+ uint64_t drm_in_format;
|
||||
+ uint64_t drm_out_format;
|
||||
+
|
||||
atomic_uint refcount;
|
||||
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
@@ -108,6 +111,65 @@ typedef struct DeintV4L2M2MContext {
|
||||
DeintV4L2M2MContextShared *shared;
|
||||
} DeintV4L2M2MContext;
|
||||
|
||||
+typedef struct drm_v4l2_pix_fmt_mapping {
|
||||
+ uint64_t drm_format;
|
||||
+ uint32_t v4l2_pix_fmt;
|
||||
+};
|
||||
+
|
||||
+static struct drm_v4l2_pix_fmt_mapping drm_v4l2_pix_fmt_map[] = {
|
||||
+ { .drm_format = DRM_FORMAT_NV12, .v4l2_pix_fmt = V4L2_PIX_FMT_NV12 },
|
||||
+ { .drm_format = DRM_FORMAT_NV21, .v4l2_pix_fmt = V4L2_PIX_FMT_NV21 },
|
||||
+ { .drm_format = DRM_FORMAT_NV16, .v4l2_pix_fmt = V4L2_PIX_FMT_NV16 },
|
||||
+ { .drm_format = DRM_FORMAT_NV16, .v4l2_pix_fmt = V4L2_PIX_FMT_NV16 },
|
||||
+#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED
|
||||
+ { .drm_format = DRM_FORMAT_MOD_ALLWINNER_TILED, .v4l2_pix_fmt = V4L2_PIX_FMT_SUNXI_TILED_NV12 },
|
||||
+#endif
|
||||
+#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15)
|
||||
+ { .drm_format = DRM_FORMAT_NV15, .v4l2_pix_fmt = V4L2_PIX_FMT_NV15 },
|
||||
+#endif
|
||||
+#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20)
|
||||
+ { .drm_format = DRM_FORMAT_NV20, .v4l2_pix_fmt = V4L2_PIX_FMT_NV20 },
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static inline uint32_t v4l2_pix_fmt_from_drm_format(uint64_t drm_format)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < FF_ARRAY_ELEMS(drm_v4l2_pix_fmt_map); i++) {
|
||||
+ if (drm_v4l2_pix_fmt_map[i].drm_format == drm_format)
|
||||
+ return drm_v4l2_pix_fmt_map[i].v4l2_pix_fmt;
|
||||
+ }
|
||||
+
|
||||
+ av_log(NULL, AV_LOG_WARNING, "%s unknown drm format 0x%llx using default v4l2_pix_fmt 0x%x\n",
|
||||
+ __func__ , drm_format, drm_v4l2_pix_fmt_map[0].v4l2_pix_fmt);
|
||||
+ return drm_v4l2_pix_fmt_map[0].v4l2_pix_fmt;
|
||||
+}
|
||||
+
|
||||
+static inline uint64_t drm_format_from_v4l2_pix_fmt(uint32_t v4l2_pix_fmt)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < FF_ARRAY_ELEMS(drm_v4l2_pix_fmt_map); i++) {
|
||||
+ if (drm_v4l2_pix_fmt_map[i].v4l2_pix_fmt == v4l2_pix_fmt)
|
||||
+ return drm_v4l2_pix_fmt_map[i].drm_format;
|
||||
+ }
|
||||
+
|
||||
+ av_log(NULL, AV_LOG_WARNING, "%s unknown v4l2_pix_fmt format 0x%x using default drm_format 0x%llx\n",
|
||||
+ __func__ , v4l2_pix_fmt, drm_v4l2_pix_fmt_map[0].drm_format);
|
||||
+ return drm_v4l2_pix_fmt_map[0].drm_format;
|
||||
+}
|
||||
+
|
||||
+static inline uint64_t drm_format_modifier(uint64_t drm_format)
|
||||
+{
|
||||
+#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED
|
||||
+ if (drm_format == DRM_FORMAT_MOD_ALLWINNER_TILED)
|
||||
+ return DRM_FORMAT_MOD_ALLWINNER_TILED;
|
||||
+#endif
|
||||
+ return DRM_FORMAT_MOD_LINEAR;
|
||||
+
|
||||
+}
|
||||
+
|
||||
static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx)
|
||||
{
|
||||
struct v4l2_capability cap;
|
||||
@@ -138,11 +200,12 @@ static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx)
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
-static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
+static int deint_v4l2m2m_try_format(V4L2Queue *queue, uint64_t drm_format)
|
||||
{
|
||||
struct v4l2_format *fmt = &queue->format;
|
||||
DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
int ret, field;
|
||||
+ uint32_t v4l2_pix_fmt = v4l2_pix_fmt_from_drm_format(drm_format);
|
||||
|
||||
ret = ioctl(ctx->fd, VIDIOC_G_FMT, fmt);
|
||||
if (ret)
|
||||
@@ -154,12 +217,12 @@ static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
field = V4L2_FIELD_NONE;
|
||||
|
||||
if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
- fmt->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
|
||||
+ fmt->fmt.pix_mp.pixelformat = v4l2_pix_fmt;
|
||||
fmt->fmt.pix_mp.field = field;
|
||||
fmt->fmt.pix_mp.width = ctx->width;
|
||||
fmt->fmt.pix_mp.height = ctx->height;
|
||||
} else {
|
||||
- fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
|
||||
+ fmt->fmt.pix.pixelformat = v4l2_pix_fmt;
|
||||
fmt->fmt.pix.field = field;
|
||||
fmt->fmt.pix.width = ctx->width;
|
||||
fmt->fmt.pix.height = ctx->height;
|
||||
@@ -170,14 +233,14 @@ static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
- if (fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12 ||
|
||||
+ if (fmt->fmt.pix_mp.pixelformat != v4l2_pix_fmt ||
|
||||
fmt->fmt.pix_mp.field != field) {
|
||||
av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
|
||||
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
} else {
|
||||
- if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12 ||
|
||||
+ if (fmt->fmt.pix.pixelformat != v4l2_pix_fmt ||
|
||||
fmt->fmt.pix.field != field) {
|
||||
av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
|
||||
|
||||
@@ -187,19 +250,21 @@ static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
|
||||
return 0;
|
||||
}
|
||||
-
|
||||
-static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width, int height)
|
||||
+static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width, int height, uint64_t drm_format)
|
||||
{
|
||||
struct v4l2_format *fmt = &queue->format;
|
||||
DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
int ret;
|
||||
+ uint32_t v4l2_pix_fmt = v4l2_pix_fmt_from_drm_format(drm_format);
|
||||
|
||||
if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
+ fmt->fmt.pix_mp.pixelformat = v4l2_pix_fmt;
|
||||
fmt->fmt.pix_mp.field = field;
|
||||
fmt->fmt.pix_mp.width = width;
|
||||
fmt->fmt.pix_mp.height = height;
|
||||
/* TODO: bytesperline and imagesize */
|
||||
} else {
|
||||
+ fmt->fmt.pix.pixelformat = v4l2_pix_fmt;
|
||||
fmt->fmt.pix.field = field;
|
||||
fmt->fmt.pix.width = width;
|
||||
fmt->fmt.pix.height = height;
|
||||
@@ -211,6 +276,18 @@ static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width,
|
||||
if (ret)
|
||||
av_log(NULL, AV_LOG_ERROR, "VIDIOC_S_FMT failed: %d\n", ret);
|
||||
|
||||
+ else if (!V4L2_TYPE_IS_OUTPUT(queue->format.type)) {
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type) && fmt->fmt.pix_mp.pixelformat != v4l2_pix_fmt) {
|
||||
+ ctx->drm_out_format = drm_format_from_v4l2_pix_fmt(fmt->fmt.pix_mp.pixelformat);
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "%s driver updated v4l2_pixfmt from: %x to %x, so now using %llx as drm output format\n",
|
||||
+ __func__, v4l2_pix_fmt, fmt->fmt.pix_mp.pixelformat, ctx->drm_out_format);
|
||||
+ } else if (fmt->fmt.pix.pixelformat != v4l2_pix_fmt) {
|
||||
+ ctx->drm_out_format = drm_format_from_v4l2_pix_fmt(fmt->fmt.pix.pixelformat);
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "%s driver updated v4l2_pixfmt from: %x to %x, so now using %llx as drm output format\n",
|
||||
+ __func__, v4l2_pix_fmt, fmt->fmt.pix.pixelformat, ctx->drm_out_format);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -226,11 +303,11 @@ static int deint_v4l2m2m_probe_device(DeintV4L2M2MContextShared *ctx, char *node
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
- ret = deint_v4l2m2m_try_format(&ctx->capture);
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->capture, ctx->drm_out_format);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
- ret = deint_v4l2m2m_try_format(&ctx->output);
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->output, ctx->drm_in_format);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
@@ -293,7 +370,7 @@ static int deint_v4l2m2m_enqueue_buffer(V4L2Buffer *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
|
||||
+static int v4l2_buffer_export_drm(V4L2Buffer* avbuf, uint64_t drm_format)
|
||||
{
|
||||
struct v4l2_exportbuffer expbuf;
|
||||
int i, ret;
|
||||
@@ -315,12 +392,12 @@ static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
|
||||
/* drm frame */
|
||||
avbuf->drm_frame.objects[i].size = avbuf->buffer.m.planes[i].length;
|
||||
avbuf->drm_frame.objects[i].fd = expbuf.fd;
|
||||
- avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
+ avbuf->drm_frame.objects[i].format_modifier = drm_format_modifier(drm_format);
|
||||
} else {
|
||||
/* drm frame */
|
||||
avbuf->drm_frame.objects[0].size = avbuf->buffer.length;
|
||||
avbuf->drm_frame.objects[0].fd = expbuf.fd;
|
||||
- avbuf->drm_frame.objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
+ avbuf->drm_frame.objects[0].format_modifier = drm_format_modifier(drm_format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +482,7 @@ static int deint_v4l2m2m_allocate_buffers(V4L2Queue *queue)
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
- ret = v4l2_buffer_export_drm(buf);
|
||||
+ ret = v4l2_buffer_export_drm(buf, ctx->drm_out_format);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
@@ -597,7 +674,7 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused)
|
||||
deint_v4l2m2m_destroy_context(ctx);
|
||||
}
|
||||
|
||||
-static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height)
|
||||
+static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height, uint64_t drm_format)
|
||||
{
|
||||
AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame;
|
||||
AVDRMLayerDescriptor *layer;
|
||||
@@ -615,7 +692,7 @@ static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height)
|
||||
layer->planes[i].pitch = avbuf->plane_info[i].bytesperline;
|
||||
}
|
||||
|
||||
- layer->format = DRM_FORMAT_NV12;
|
||||
+ layer->format = drm_format;
|
||||
|
||||
if (avbuf->num_planes == 1) {
|
||||
layer->nb_planes = 2;
|
||||
@@ -647,7 +724,7 @@ static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int tim
|
||||
|
||||
atomic_fetch_add(&ctx->refcount, 1);
|
||||
|
||||
- frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height);
|
||||
+ frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height, ctx->drm_out_format);
|
||||
frame->format = AV_PIX_FMT_DRM_PRIME;
|
||||
frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx);
|
||||
frame->height = ctx->height;
|
||||
@@ -797,17 +874,22 @@ static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
|
||||
AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0];
|
||||
ctx->orig_width = drm_desc->layers[0].planes[0].pitch;
|
||||
ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width;
|
||||
+ ctx->drm_in_format = drm_desc->layers->format;
|
||||
+ ctx->drm_out_format = drm_desc->layers->format;
|
||||
+
|
||||
|
||||
if (in->top_field_first)
|
||||
ctx->field_order = V4L2_FIELD_INTERLACED_TB;
|
||||
else
|
||||
ctx->field_order = V4L2_FIELD_INTERLACED_BT;
|
||||
|
||||
- ret = deint_v4l2m2m_set_format(output, ctx->field_order, ctx->orig_width, ctx->orig_height);
|
||||
+ ret = deint_v4l2m2m_set_format(output, ctx->field_order, ctx->orig_width, ctx->orig_height,
|
||||
+ ctx->drm_in_format);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- ret = deint_v4l2m2m_set_format(capture, V4L2_FIELD_NONE, ctx->orig_width, ctx->orig_height);
|
||||
+ ret = deint_v4l2m2m_set_format(capture, V4L2_FIELD_NONE, ctx->orig_width, ctx->orig_height,
|
||||
+ ctx->drm_out_format);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -864,6 +946,8 @@ static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx)
|
||||
ctx->field_order = V4L2_FIELD_ANY;
|
||||
ctx->cur_in_frame = NULL;
|
||||
ctx->prev_in_frame = NULL;
|
||||
+ ctx->drm_in_format = drm_v4l2_pix_fmt_map[0].drm_format;
|
||||
+ ctx->drm_out_format = drm_v4l2_pix_fmt_map[0].drm_format;
|
||||
atomic_init(&ctx->refcount, 1);
|
||||
|
||||
return 0;
|
Loading…
x
Reference in New Issue
Block a user