opengl: Add NV12_16L32S conversion support

This adds a first detiling shader with initial support for
NV12_16L32S as produced by Mediatek decoders.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2190>
This commit is contained in:
Nicolas Dufresne 2022-04-12 14:18:59 -04:00 committed by GStreamer Marge Bot
parent 77a88c4572
commit 39615e4f3c
5 changed files with 110 additions and 17 deletions

View file

@ -512,6 +512,7 @@ _drm_rgba_fourcc_from_info (const GstVideoInfo * info, int plane,
case GST_VIDEO_FORMAT_NV21:
case GST_VIDEO_FORMAT_NV16:
case GST_VIDEO_FORMAT_NV61:
case GST_VIDEO_FORMAT_NV12_16L32S:
*out_format = plane == 0 ? GST_GL_RED : GST_GL_RG;
return plane == 0 ? DRM_FORMAT_R8 : rg_fourcc;

View file

@ -50,6 +50,8 @@
#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
#define USING_OPENGL30(context) \
(gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 3, 0) || USING_OPENGL3(context))
#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
@ -357,6 +359,49 @@ static const struct shader_templ templ_AV12_to_RGB =
GST_GL_TEXTURE_TARGET_2D
};
#define glsl_func_frag_to_tile \
"ivec2 frag_to_tile(ivec2 tile_coord, ivec2 delta_coord, ivec2 dim, int width, int tiles_per_row, int need_offset) {\n" \
" int tile_size = (dim.x * dim.y);\n" \
" int tile_index = tile_coord.y * tiles_per_row + tile_coord.x;\n" \
" int linear_index = tile_index * tile_size + delta_coord.y * dim.x + delta_coord.x;\n" \
" linear_index += need_offset * tile_size / 2;\n" \
" return ivec2(linear_index % width, linear_index / width);\n" \
"}\n"
/* TILED semi-planar to RGB conversion */
static const gchar templ_TILED_SEMI_PLANAR_to_RGB_BODY[] =
" vec4 rgba;\n"
" vec3 yuv;\n"
" ivec2 texel;\n"
"\n"
" const ivec2 luma_dim = ivec2(%i, %i);\n"
" const ivec2 chroma_dim = ivec2(%i, %i);\n"
" const int fy = chroma_dim.y * 2 / luma_dim.y;\n"
"\n"
" int iwidth = int(width);\n"
" int tiles_per_row = iwidth / luma_dim.x;\n"
"\n"
" ivec2 coord = ivec2(gl_FragCoord.xy);\n"
" ivec2 tile_coord = coord / luma_dim;\n"
" ivec2 delta_coord = coord %% luma_dim;\n" \
" texel = frag_to_tile(tile_coord, delta_coord, luma_dim, iwidth, tiles_per_row, 0);\n"
" yuv.x = texelFetch(Ytex, texel, 0).r;\n"
"\n"
" ivec2 chroma_tcoord = ivec2(tile_coord.x, tile_coord.y / fy);\n"
" texel = frag_to_tile(chroma_tcoord, delta_coord / 2, chroma_dim, iwidth / 2, tiles_per_row, tile_coord.y %% fy);\n"
" yuv.yz = texelFetch(UVtex, texel, 0).%c%c;\n"
"\n"
" rgba.rgb = yuv_to_rgb (yuv, offset, coeff1, coeff2, coeff3);\n"
" rgba.a = 1.0;\n"
" gl_FragColor=vec4(rgba.%c,rgba.%c,rgba.%c,rgba.%c);\n";
static const struct shader_templ templ_TILED_SEMI_PLANAR_to_RGB =
{ NULL,
DEFAULT_UNIFORMS YUV_TO_RGB_COEFFICIENTS "uniform sampler2D Ytex, UVtex;\n",
{ glsl_func_yuv_to_rgb, glsl_func_frag_to_tile, NULL, },
GST_GL_TEXTURE_TARGET_2D
};
/* RGB to NV12/NV21/NV16/NV61 conversion */
/* NV12/NV16: u, v
NV21/NV61: v, u */
@ -1082,6 +1127,10 @@ _init_supported_formats (GstGLContext * context, gboolean output,
_append_value_string_list (supported_formats, "Y412_BE", NULL);
#endif
}
if (!context || USING_GLES3 (context) || USING_OPENGL30 (context)) {
_append_value_string_list (supported_formats, "NV12_16L32S", NULL);
}
}
/* copies the given caps */
@ -1713,6 +1762,7 @@ _get_n_textures (GstVideoFormat v_format)
case GST_VIDEO_FORMAT_P012_BE:
case GST_VIDEO_FORMAT_P016_LE:
case GST_VIDEO_FORMAT_P016_BE:
case GST_VIDEO_FORMAT_NV12_16L32S:
return 2;
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_Y444:
@ -2066,6 +2116,17 @@ _YUV_to_RGB (GstGLColorConvert * convert)
info->shader_tex_names[1] = "UVtex";
break;
}
case GST_VIDEO_FORMAT_NV12_16L32S:
{
char val2 = convert->priv->in_tex_formats[1] == GST_GL_RG ? 'g' : 'a';
info->templ = &templ_TILED_SEMI_PLANAR_to_RGB;
info->frag_body = g_strdup_printf (templ_TILED_SEMI_PLANAR_to_RGB_BODY,
16, 32, 8, 16, 'r', val2,
pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
info->shader_tex_names[0] = "Ytex";
info->shader_tex_names[1] = "UVtex";
break;
}
default:
break;
}
@ -2313,13 +2374,14 @@ _bind_buffer (GstGLColorConvert * convert)
/* Load the vertex position */
gl->VertexAttribPointer (convert->priv->attr_position, 3, GL_FLOAT, GL_FALSE,
5 * sizeof (GLfloat), (void *) 0);
/* Load the texture coordinate */
gl->VertexAttribPointer (convert->priv->attr_texture, 2, GL_FLOAT, GL_FALSE,
5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat)));
gl->EnableVertexAttribArray (convert->priv->attr_position);
gl->EnableVertexAttribArray (convert->priv->attr_texture);
if (convert->priv->attr_texture != -1) {
/* Load the texture coordinate */
gl->VertexAttribPointer (convert->priv->attr_texture, 2, GL_FLOAT, GL_FALSE,
5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat)));
gl->EnableVertexAttribArray (convert->priv->attr_texture);
}
}
static void
@ -2328,10 +2390,12 @@ _unbind_buffer (GstGLColorConvert * convert)
const GstGLFuncs *gl = convert->context->gl_vtable;
gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
gl->BindBuffer (GL_ARRAY_BUFFER, 0);
gl->DisableVertexAttribArray (convert->priv->attr_position);
gl->DisableVertexAttribArray (convert->priv->attr_texture);
if (convert->priv->attr_texture != -1) {
gl->BindBuffer (GL_ARRAY_BUFFER, 0);
gl->DisableVertexAttribArray (convert->priv->attr_texture);
}
}
static GstGLShader *
@ -2573,13 +2637,25 @@ _init_convert (GstGLColorConvert * convert)
goto incompatible_api;
}
/* Requires texelFetch() function... */
if (!(USING_GLES3 (convert->context) || USING_OPENGL30 (convert->context)) &&
GST_VIDEO_FORMAT_INFO_IS_TILED (convert->in_info.finfo)) {
GST_ERROR ("Conversion requires texelFetch() function available since "
"GLSL 1.30");
goto incompatible_api;
}
if (!(convert->shader = _create_shader (convert)))
goto error;
convert->priv->attr_position =
gst_gl_shader_get_attribute_location (convert->shader, "a_position");
convert->priv->attr_texture =
gst_gl_shader_get_attribute_location (convert->shader, "a_texcoord");
if (!GST_VIDEO_FORMAT_INFO_IS_TILED (convert->in_info.finfo))
convert->priv->attr_texture =
gst_gl_shader_get_attribute_location (convert->shader, "a_texcoord");
else
convert->priv->attr_texture = -1;
gst_gl_shader_use (convert->shader);
@ -2601,10 +2677,25 @@ _init_convert (GstGLColorConvert * convert)
i);
}
gst_gl_shader_set_uniform_1f (convert->shader, "width",
GST_VIDEO_INFO_WIDTH (&convert->in_info));
gst_gl_shader_set_uniform_1f (convert->shader, "height",
GST_VIDEO_INFO_HEIGHT (&convert->in_info));
if (GST_VIDEO_FORMAT_INFO_IS_TILED (convert->in_info.finfo)) {
guint ws, hs;
gsize stride;
gfloat width, height;
stride = GST_VIDEO_INFO_PLANE_STRIDE (&convert->in_info, 0);
gst_video_format_info_get_tile_sizes (convert->in_info.finfo, 0, &ws, &hs);
width = GST_VIDEO_TILE_X_TILES (stride) << ws;
height = GST_VIDEO_TILE_Y_TILES (stride) << hs;
gst_gl_shader_set_uniform_1f (convert->shader, "width", width);
gst_gl_shader_set_uniform_1f (convert->shader, "height", height);
} else {
gst_gl_shader_set_uniform_1f (convert->shader, "width",
GST_VIDEO_INFO_WIDTH (&convert->in_info));
gst_gl_shader_set_uniform_1f (convert->shader, "height",
GST_VIDEO_INFO_HEIGHT (&convert->in_info));
}
if (convert->priv->from_texture_target == GST_GL_TEXTURE_TARGET_RECTANGLE) {
gst_gl_shader_set_uniform_1f (convert->shader, "poffset_x", 1.);

View file

@ -103,7 +103,7 @@ struct _GstGLColorConvertClass
"xBGR, ARGB, ABGR, GBRA, GBR, RGBP, BGRP, Y444, I420, YV12, Y42B, " \
"Y41B, NV12, NV21, NV16, NV61, YUY2, UYVY, Y210, AYUV, " \
"VUYA, Y410, GRAY8, GRAY16_LE, GRAY16_BE, " \
"RGB16, BGR16, ARGB64, A420, AV12" \
"RGB16, BGR16, ARGB64, A420, AV12, NV12_16L32S" \
GST_GL_COLOR_CONVERT_EXT_FORMATS "}"
/**

View file

@ -192,6 +192,7 @@ gst_gl_format_from_video_info (GstGLContext * context,
case GST_VIDEO_FORMAT_NV21:
case GST_VIDEO_FORMAT_NV16:
case GST_VIDEO_FORMAT_NV61:
case GST_VIDEO_FORMAT_NV12_16L32S:
n_plane_components = plane == 0 ? 1 : 2;
break;
case GST_VIDEO_FORMAT_AV12:

View file

@ -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, GBRA, GBR, RGBP, BGRP, 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, A420, AV12" \
"Y42B, Y444, GRAY8, GRAY16_LE, GRAY16_BE, ARGB64, A420, AV12, NV12_16L32S" \
GST_GL_MEMORY_VIDEO_EXT_FORMATS "}"
/**