From 7b46405ddbca266c6a84bdb19e37cb3a922187eb Mon Sep 17 00:00:00 2001 From: Alex Bee Date: Mon, 11 Oct 2021 15:28:31 +0200 Subject: [PATCH] Rockchip: ffmpeg: support more formats / automatic output format selection in deinterlace filter Also increase input/output buffer count --- ...2m-increase-input-and-output-buffers.patch | 26 ++ ...deinterlace-support-more-formats-aut.patch | 288 ++++++++++++++++++ 2 files changed, 314 insertions(+) create mode 100644 projects/Rockchip/patches/ffmpeg/ffmpeg-0006-deint_v4l2m2m-increase-input-and-output-buffers.patch create mode 100644 projects/Rockchip/patches/ffmpeg/ffmpeg-0006-libavfilter-v4l2deinterlace-support-more-formats-aut.patch diff --git a/projects/Rockchip/patches/ffmpeg/ffmpeg-0006-deint_v4l2m2m-increase-input-and-output-buffers.patch b/projects/Rockchip/patches/ffmpeg/ffmpeg-0006-deint_v4l2m2m-increase-input-and-output-buffers.patch new file mode 100644 index 0000000000..8ccbe42b6c --- /dev/null +++ b/projects/Rockchip/patches/ffmpeg/ffmpeg-0006-deint_v4l2m2m-increase-input-and-output-buffers.patch @@ -0,0 +1,26 @@ +From 1a4b8070ff968a07dc24467922849c1142995e30 Mon Sep 17 00:00:00 2001 +From: popcornmix +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; diff --git a/projects/Rockchip/patches/ffmpeg/ffmpeg-0006-libavfilter-v4l2deinterlace-support-more-formats-aut.patch b/projects/Rockchip/patches/ffmpeg/ffmpeg-0006-libavfilter-v4l2deinterlace-support-more-formats-aut.patch new file mode 100644 index 0000000000..a46cc8f83d --- /dev/null +++ b/projects/Rockchip/patches/ffmpeg/ffmpeg-0006-libavfilter-v4l2deinterlace-support-more-formats-aut.patch @@ -0,0 +1,288 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alex Bee +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 +--- + 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;