From bd5be40f06359857a82c1ebdef473b9c8ce3ae0f Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Tue, 24 May 2022 16:16:33 +0800 Subject: [PATCH 14/14] glupload: Support NV12_10LE40 and NV12|NV12_10LE40|NV16 (AFBC) Tested on RK356x with: export GST_MPP_VIDEODEC_DEFAULT_ARM_AFBC=1 gst-play-1.0 video.mp4 --videosink=glimagesink Signed-off-by: Jeffy Chen --- gst-libs/gst/gl/egl/gsteglimage.c | 49 ++++++++++++++++++++++++++----- gst-libs/gst/gl/egl/gsteglimage.h | 44 +++++++++++++++++++++++++++ gst-libs/gst/gl/gstglmemory.h | 2 +- gst-libs/gst/gl/gstglupload.c | 15 +++++++++- 4 files changed, 101 insertions(+), 9 deletions(-) diff --git a/gst-libs/gst/gl/egl/gsteglimage.c b/gst-libs/gst/gl/egl/gsteglimage.c index 9bd2f0fa3..8b2b4f11e 100644 --- a/gst-libs/gst/gl/egl/gsteglimage.c +++ b/gst-libs/gst/gl/egl/gsteglimage.c @@ -627,6 +627,19 @@ _drm_direct_fourcc_from_info (GstVideoInfo * info) GST_DEBUG ("Getting DRM fourcc for %s", gst_video_format_to_string (format)); + if (GST_VIDEO_INFO_IS_AFBC (info)) { + /* Mali uses these formats instead */ + if (format == GST_VIDEO_FORMAT_NV12) + return DRM_FORMAT_YUV420_8BIT; + else if (format == GST_VIDEO_FORMAT_NV12_10LE40) + return DRM_FORMAT_YUV420_10BIT; + else if (format == GST_VIDEO_FORMAT_NV16) + return DRM_FORMAT_YUYV; + + GST_INFO ("unsupported format for AFBC"); + return -1; + } + switch (format) { case GST_VIDEO_FORMAT_YUY2: return DRM_FORMAT_YUYV; @@ -710,6 +723,9 @@ _drm_direct_fourcc_from_info (GstVideoInfo * info) case GST_VIDEO_FORMAT_xBGR: return DRM_FORMAT_RGBX8888; + case GST_VIDEO_FORMAT_NV12_10LE40: + return DRM_FORMAT_NV15; + default: GST_INFO ("Unsupported format for direct DMABuf."); return -1; @@ -865,10 +881,12 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, { EGLImageKHR img; + GstVideoFormat format = GST_VIDEO_INFO_FORMAT (in_info); guint n_planes = GST_VIDEO_INFO_N_PLANES (in_info); gint fourcc; gint i; gboolean with_modifiers; + guint64 modifier = DRM_FORMAT_MOD_LINEAR; /* Explanation of array length: * - 6 plane independent values are at the start (width, height, format FourCC) @@ -878,6 +896,7 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, */ guintptr attribs[41]; /* 6 + 10 * 3 + 4 + 1 */ gint atti = 0; + gfloat stride_scale = 1.0f; if (!gst_egl_image_check_dmabuf_direct (context, in_info, target)) return NULL; @@ -886,6 +905,22 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, with_modifiers = gst_gl_context_check_feature (context, "EGL_EXT_image_dma_buf_import_modifiers"); + if (GST_VIDEO_INFO_IS_AFBC (in_info)) { + if (!with_modifiers) + return NULL; + + /* Mali uses these formats instead */ + if (format == GST_VIDEO_FORMAT_NV12) + stride_scale = 1.5; + else if (format == GST_VIDEO_FORMAT_NV12_10LE40) + stride_scale = 1.5; + else if (format == GST_VIDEO_FORMAT_NV16) + stride_scale = 2; + + modifier = DRM_AFBC_MODIFIER; + n_planes = 1; + } + /* EGL DMABuf importation supports a maximum of 3 planes */ if (G_UNLIKELY (n_planes > 3)) return NULL; @@ -904,12 +939,12 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; attribs[atti++] = offset[0]; attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; - attribs[atti++] = in_info->stride[0]; + attribs[atti++] = in_info->stride[0] * stride_scale; if (with_modifiers) { attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT; - attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff; + attribs[atti++] = modifier & 0xffffffff; attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT; - attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff; + attribs[atti++] = (modifier >> 32) & 0xffffffff; } } @@ -923,9 +958,9 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, attribs[atti++] = in_info->stride[1]; if (with_modifiers) { attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT; - attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff; + attribs[atti++] = modifier & 0xffffffff; attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT; - attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff; + attribs[atti++] = (modifier >> 32) & 0xffffffff; } } @@ -939,9 +974,9 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, attribs[atti++] = in_info->stride[2]; if (with_modifiers) { attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT; - attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff; + attribs[atti++] = modifier & 0xffffffff; attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT; - attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff; + attribs[atti++] = (modifier >> 32) & 0xffffffff; } } diff --git a/gst-libs/gst/gl/egl/gsteglimage.h b/gst-libs/gst/gl/egl/gsteglimage.h index 6aa56a4b1..1b0c2ce9d 100644 --- a/gst-libs/gst/gl/egl/gsteglimage.h +++ b/gst-libs/gst/gl/egl/gsteglimage.h @@ -26,8 +26,52 @@ #include #include +#include + G_BEGIN_DECLS +#ifndef DRM_FORMAT_NV15 +#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') +#endif + +#ifndef DRM_FORMAT_YUV420_8BIT +#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8') +#endif + +#ifndef DRM_FORMAT_YUV420_10BIT +#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0') +#endif + +#ifndef DRM_FORMAT_MOD_VENDOR_ARM +#define DRM_FORMAT_MOD_VENDOR_ARM 0x08 +#endif + +#ifndef DRM_FORMAT_MOD_ARM_AFBC +#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode) +#endif + +#ifndef AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 +#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL) +#endif + +#ifndef AFBC_FORMAT_MOD_SPARSE +#define AFBC_FORMAT_MOD_SPARSE (((__u64)1) << 6) +#endif + +#define DRM_AFBC_MODIFIER \ + (DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_SPARSE) | \ + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16)) + +#ifndef GST_VIDEO_FLAG_ARM_AFBC +#define GST_VIDEO_FLAG_ARM_AFBC (1UL << 31) +#define GST_VIDEO_INFO_SET_AFBC(i) \ + GST_VIDEO_INFO_FLAG_SET (i, GST_VIDEO_FLAG_ARM_AFBC) +#define GST_VIDEO_INFO_UNSET_AFBC(i) \ + GST_VIDEO_INFO_FLAG_UNSET (i, GST_VIDEO_FLAG_ARM_AFBC) +#define GST_VIDEO_INFO_IS_AFBC(i) \ + GST_VIDEO_INFO_FLAG_IS_SET (i, GST_VIDEO_FLAG_ARM_AFBC) +#endif + GST_GL_API GType gst_egl_image_get_type (void); #define GST_TYPE_EGL_IMAGE (gst_egl_image_get_type()) diff --git a/gst-libs/gst/gl/gstglmemory.h b/gst-libs/gst/gl/gstglmemory.h index df9cab63e..9063d8ef1 100644 --- a/gst-libs/gst/gl/gstglmemory.h +++ b/gst-libs/gst/gl/gstglmemory.h @@ -64,7 +64,7 @@ GType gst_gl_memory_allocator_get_type(void); #define GST_GL_MEMORY_VIDEO_FORMATS_STR \ "{ RGBA, BGRA, RGBx, BGRx, ARGB, ABGR, xRGB, xBGR, RGB, BGR, RGB16, BGR16, " \ "AYUV, VUYA, Y410, I420, YV12, NV12, NV21, NV16, NV61, YUY2, UYVY, Y210, Y41B, " \ - "Y42B, Y444, GRAY8, GRAY16_LE, GRAY16_BE, ARGB64" \ + "Y42B, Y444, GRAY8, GRAY16_LE, GRAY16_BE, ARGB64, NV12_10LE40" \ GST_GL_MEMORY_VIDEO_EXT_FORMATS "}" /** diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c index 6462a5733..5489e4c7d 100644 --- a/gst-libs/gst/gl/gstglupload.c +++ b/gst-libs/gst/gl/gstglupload.c @@ -505,7 +505,8 @@ static GstStaticCaps _dma_buf_upload_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF, GST_GL_MEMORY_VIDEO_FORMATS_STR) ";" - GST_VIDEO_CAPS_MAKE (GST_GL_MEMORY_VIDEO_FORMATS_STR)); + GST_VIDEO_CAPS_MAKE (GST_GL_MEMORY_VIDEO_FORMATS_STR) ";" + GST_VIDEO_CAPS_MAKE ("{NV12, NV12_10LE40}") ", arm-afbc = (int) 1"); static gpointer _dma_buf_upload_new (GstGLUpload * upload) @@ -1909,6 +1910,9 @@ static gboolean _gst_gl_upload_set_caps_unlocked (GstGLUpload * upload, GstCaps * in_caps, GstCaps * out_caps) { + GstStructure *s; + gint value; + g_return_val_if_fail (upload != NULL, FALSE); g_return_val_if_fail (gst_caps_is_fixed (in_caps), FALSE); @@ -1923,6 +1927,15 @@ _gst_gl_upload_set_caps_unlocked (GstGLUpload * upload, GstCaps * in_caps, gst_video_info_from_caps (&upload->priv->in_info, in_caps); gst_video_info_from_caps (&upload->priv->out_info, out_caps); + /* parse AFBC from caps */ + s = gst_caps_get_structure (in_caps, 0); + if (gst_structure_get_int (s, "arm-afbc", &value)) { + if (value) + GST_VIDEO_INFO_SET_AFBC (&upload->priv->in_info); + else + GST_VIDEO_INFO_UNSET_AFBC (&upload->priv->in_info); + } + upload->priv->method = NULL; upload->priv->method_impl = NULL; upload->priv->method_i = 0; -- 2.20.1