/* * GStreamer * Copyright (C) 2015 Matthew Waters * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** * SECTION:gstglformat * @short_description: utilities for dealing with OpenGL formats * @see_also: #GstGLBaseMemory, #GstGLMemory, #GstGLFramebuffer, #GstGLBuffer * * Some useful utilities for converting between various formats and OpenGL * formats. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #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_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)) #ifndef GL_TEXTURE_RECTANGLE #define GL_TEXTURE_RECTANGLE 0x84F5 #endif #ifndef GL_TEXTURE_EXTERNAL_OES #define GL_TEXTURE_EXTERNAL_OES 0x8D65 #endif static inline guint _gl_format_n_components (guint format) { switch (format) { case GST_VIDEO_GL_TEXTURE_TYPE_RGBA: case GST_GL_RGBA: return 4; case GST_VIDEO_GL_TEXTURE_TYPE_RGB: case GST_VIDEO_GL_TEXTURE_TYPE_RGB16: case GST_GL_RGB: return 3; case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA: case GST_VIDEO_GL_TEXTURE_TYPE_RG: case GST_GL_LUMINANCE_ALPHA: case GST_GL_RG: return 2; case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE: case GST_VIDEO_GL_TEXTURE_TYPE_R: case GST_GL_LUMINANCE: case GST_GL_RED: return 1; default: return 0; } } static inline guint _gl_type_n_components (guint type) { switch (type) { case GL_UNSIGNED_BYTE: return 1; case GL_UNSIGNED_SHORT_5_6_5: return 3; default: g_assert_not_reached (); return 0; } } static inline guint _gl_type_n_bytes (guint type) { switch (type) { case GL_UNSIGNED_BYTE: return 1; case GL_UNSIGNED_SHORT_5_6_5: return 2; default: g_assert_not_reached (); return 0; } } /** * gst_gl_format_type_n_bytes: * @format: the OpenGL format, %GL_RGBA, %GL_LUMINANCE, etc * @type: the OpenGL type, %GL_UNSIGNED_BYTE, %GL_FLOAT, etc * * Returns: the number of bytes the specified @format, @type combination takes * per pixel */ guint gst_gl_format_type_n_bytes (guint format, guint type) { return _gl_format_n_components (format) / _gl_type_n_components (type) * _gl_type_n_bytes (type); } /** * gst_gl_texture_type_n_bytes: * @tex_format: a #GstVideoGLTextureType * * Returns: the number of bytes @tex_format used per pixel */ guint gst_gl_texture_type_n_bytes (GstVideoGLTextureType tex_format) { guint format, type; format = gst_gl_format_from_gl_texture_type (tex_format); type = GL_UNSIGNED_BYTE; if (tex_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16) type = GL_UNSIGNED_SHORT_5_6_5; return gst_gl_format_type_n_bytes (format, type); } /** * gst_gl_format_from_gl_texture_type: * @tex_format: a #GstVideoGLTextureType * * Returns: the OpenGL format specified by @tex_format */ guint gst_gl_format_from_gl_texture_type (GstVideoGLTextureType tex_format) { switch (tex_format) { case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA: return GST_GL_LUMINANCE_ALPHA; case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE: return GST_GL_LUMINANCE; case GST_VIDEO_GL_TEXTURE_TYPE_RGBA: return GST_GL_RGBA; case GST_VIDEO_GL_TEXTURE_TYPE_RGB: case GST_VIDEO_GL_TEXTURE_TYPE_RGB16: return GST_GL_RGB; case GST_VIDEO_GL_TEXTURE_TYPE_RG: return GST_GL_RG; case GST_VIDEO_GL_TEXTURE_TYPE_R: return GST_GL_RED; default: return tex_format; } } /** * gst_gl_texture_type_from_format: * @context: a #GstGLContext * @v_format: a #GstVideoFormat * @plane: the plane number (starting from 0) * * Returns: the #GstVideoGLTextureType for the specified @format and @plane * that can be allocated using @context */ GstVideoGLTextureType gst_gl_texture_type_from_format (GstGLContext * context, GstVideoFormat v_format, guint plane) { gboolean texture_rg = gst_gl_context_check_feature (context, "GL_EXT_texture_rg") || gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0) || gst_gl_context_check_feature (context, "GL_ARB_texture_rg") || gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 0); guint n_plane_components; switch (v_format) { case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_xRGB: case GST_VIDEO_FORMAT_xBGR: case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_BGRA: case GST_VIDEO_FORMAT_ARGB: case GST_VIDEO_FORMAT_ABGR: case GST_VIDEO_FORMAT_AYUV: n_plane_components = 4; break; case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: n_plane_components = 3; break; case GST_VIDEO_FORMAT_RGB16: case GST_VIDEO_FORMAT_BGR16: return GST_VIDEO_GL_TEXTURE_TYPE_RGB16; case GST_VIDEO_FORMAT_GRAY16_BE: case GST_VIDEO_FORMAT_GRAY16_LE: case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_UYVY: n_plane_components = 2; break; case GST_VIDEO_FORMAT_NV12: case GST_VIDEO_FORMAT_NV21: n_plane_components = plane == 0 ? 1 : 2; break; case GST_VIDEO_FORMAT_GRAY8: case GST_VIDEO_FORMAT_Y444: case GST_VIDEO_FORMAT_Y42B: case GST_VIDEO_FORMAT_Y41B: case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: n_plane_components = 1; break; default: n_plane_components = 4; g_assert_not_reached (); break; } switch (n_plane_components) { case 4: return GST_VIDEO_GL_TEXTURE_TYPE_RGBA; break; case 3: return GST_VIDEO_GL_TEXTURE_TYPE_RGB; break; case 2: return texture_rg ? GST_VIDEO_GL_TEXTURE_TYPE_RG : GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA; break; case 1: return texture_rg ? GST_VIDEO_GL_TEXTURE_TYPE_R : GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE; break; default: g_assert_not_reached (); break; } return GST_VIDEO_GL_TEXTURE_TYPE_RGBA; } /** * gst_gl_sized_gl_format_from_gl_format_type: * @context: a #GstGLContext * @format: an OpenGL format, %GL_RGBA, %GL_LUMINANCE, etc * @type: an OpenGL type, %GL_UNSIGNED_BYTE, %GL_FLOAT, etc * * Returns: the sized internal format specified by @format and @type that can * be used in @context */ guint gst_gl_sized_gl_format_from_gl_format_type (GstGLContext * context, guint format, guint type) { gboolean ext_texture_rg = gst_gl_context_check_feature (context, "GL_EXT_texture_rg"); switch (format) { case GST_GL_RGBA: switch (type) { case GL_UNSIGNED_BYTE: return USING_GLES2 (context) && !USING_GLES3 (context) ? GST_GL_RGBA : GST_GL_RGBA8; break; } break; case GST_GL_RGB: switch (type) { case GL_UNSIGNED_BYTE: return GST_GL_RGB8; break; case GL_UNSIGNED_SHORT_5_6_5: return GST_GL_RGB; break; } break; case GST_GL_RG: switch (type) { case GL_UNSIGNED_BYTE: if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg) return GST_GL_RG; return GST_GL_RG8; break; } break; case GST_GL_RED: switch (type) { case GL_UNSIGNED_BYTE: if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg) return GST_GL_RED; return GST_GL_R8; break; } break; case GST_GL_RGBA8: case GST_GL_RGB8: case GST_GL_RG8: case GST_GL_R8: case GST_GL_LUMINANCE: case GST_GL_LUMINANCE_ALPHA: case GST_GL_ALPHA: case GST_GL_DEPTH_COMPONENT16: case GST_GL_DEPTH24_STENCIL8: return format; default: break; } g_assert_not_reached (); return 0; } /** * gst_gl_texture_target_to_string: * @target: a #GstGLTextureTarget * * Returns: the stringified version of @target or %NULL */ const gchar * gst_gl_texture_target_to_string (GstGLTextureTarget target) { switch (target) { case GST_GL_TEXTURE_TARGET_2D: return GST_GL_TEXTURE_TARGET_2D_STR; case GST_GL_TEXTURE_TARGET_RECTANGLE: return GST_GL_TEXTURE_TARGET_RECTANGLE_STR; case GST_GL_TEXTURE_TARGET_EXTERNAL_OES: return GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR; default: return NULL; } } /** * gst_gl_texture_target_from_string: * @str: a string equivalant to one of the GST_GL_TEXTURE_TARGET_*_STR values * * Returns: the #GstGLTextureTarget represented by @str or * %GST_GL_TEXTURE_TARGET_NONE */ GstGLTextureTarget gst_gl_texture_target_from_string (const gchar * str) { if (!str) return GST_GL_TEXTURE_TARGET_NONE; if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_2D_STR) == 0) return GST_GL_TEXTURE_TARGET_2D; if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_RECTANGLE_STR) == 0) return GST_GL_TEXTURE_TARGET_RECTANGLE; if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR) == 0) return GST_GL_TEXTURE_TARGET_EXTERNAL_OES; return GST_GL_TEXTURE_TARGET_NONE; } /** * gst_gl_texture_target_to_gl: * @target: a #GstGLTextureTarget * * Returns: the OpenGL value for binding the @target with glBindTexture() and * similar functions or 0 */ guint gst_gl_texture_target_to_gl (GstGLTextureTarget target) { switch (target) { case GST_GL_TEXTURE_TARGET_2D: return GL_TEXTURE_2D; case GST_GL_TEXTURE_TARGET_RECTANGLE: return GL_TEXTURE_RECTANGLE; case GST_GL_TEXTURE_TARGET_EXTERNAL_OES: return GL_TEXTURE_EXTERNAL_OES; default: return 0; } } /** * gst_gl_texture_target_from_gl: * @target: an OpenGL texture binding target * * Returns: the #GstGLTextureTarget that's equiavalant to @target or * %GST_GL_TEXTURE_TARGET_NONE */ GstGLTextureTarget gst_gl_texture_target_from_gl (guint target) { switch (target) { case GL_TEXTURE_2D: return GST_GL_TEXTURE_TARGET_2D; case GL_TEXTURE_RECTANGLE: return GST_GL_TEXTURE_TARGET_RECTANGLE; case GL_TEXTURE_EXTERNAL_OES: return GST_GL_TEXTURE_TARGET_EXTERNAL_OES; default: return GST_GL_TEXTURE_TARGET_NONE; } } /** * gst_gl_texture_target_to_buffer_pool_option: * @target: a #GstGLTextureTarget * * Returns: a string representing the @GstBufferPoolOption specified by @target */ const gchar * gst_gl_texture_target_to_buffer_pool_option (GstGLTextureTarget target) { switch (target) { case GST_GL_TEXTURE_TARGET_2D: return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D; case GST_GL_TEXTURE_TARGET_RECTANGLE: return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE; case GST_GL_TEXTURE_TARGET_EXTERNAL_OES: return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES; default: return NULL; } }