gl/colorconvert: implement lazy init
authorMatthew Waters <ystreet00@gmail.com>
Fri, 9 May 2014 08:07:03 +0000 (18:07 +1000)
committerMatthew Waters <ystreet00@gmail.com>
Fri, 9 May 2014 12:32:11 +0000 (22:32 +1000)
gst-libs/gst/gl/gstglcolorconvert.c
gst-libs/gst/gl/gstglcolorconvert.h
gst-libs/gst/gl/gstgldownload.c
gst-libs/gst/gl/gstglupload.c

index 9bc7b60..ff7cf8c 100644 (file)
@@ -48,9 +48,8 @@
 #define USING_GLES3(context) (gst_gl_context_get_gl_api (context) & GST_GL_API_GLES3)
 
 static void _do_convert (GstGLContext * context, GstGLColorConvert * convert);
-static void _init_convert (GstGLContext * context, GstGLColorConvert * convert);
-static gboolean _init_convert_fbo (GstGLContext * context,
-    GstGLColorConvert * convert);
+static gboolean _init_convert (GstGLColorConvert * convert);
+static gboolean _init_convert_fbo (GstGLColorConvert * convert);
 static gboolean _gst_gl_color_convert_perform_unlocked (GstGLColorConvert *
     convert, GstGLMemory * in_tex[GST_VIDEO_MAX_PLANES],
     GstGLMemory * out_tex[GST_VIDEO_MAX_PLANES]);
@@ -377,6 +376,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_gl_color_convert_debug);
 G_DEFINE_TYPE_WITH_CODE (GstGLColorConvert, gst_gl_color_convert,
     GST_TYPE_OBJECT, DEBUG_INIT);
 static void gst_gl_color_convert_finalize (GObject * object);
+static void gst_gl_color_convert_reset (GstGLColorConvert * convert);
 
 #define GST_GL_COLOR_CONVERT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
     GST_TYPE_GL_COLOR_CONVERT, GstGLColorConvertPrivate))
@@ -415,6 +415,9 @@ gst_gl_color_convert_new (GstGLContext * context)
   priv = convert->priv;
 
   priv->draw = _do_convert_draw;
+  gst_video_info_set_format (&convert->in_info, GST_VIDEO_FORMAT_ENCODED, 0, 0);
+  gst_video_info_set_format (&convert->out_info, GST_VIDEO_FORMAT_ENCODED, 0,
+      0);
 
   return convert;
 }
@@ -423,10 +426,26 @@ static void
 gst_gl_color_convert_finalize (GObject * object)
 {
   GstGLColorConvert *convert;
-  guint i;
 
   convert = GST_GL_COLOR_CONVERT (object);
 
+  gst_gl_color_convert_reset (convert);
+
+  if (convert->context) {
+    gst_object_unref (convert->context);
+    convert->context = NULL;
+  }
+
+  g_mutex_clear (&convert->lock);
+
+  G_OBJECT_CLASS (gst_gl_color_convert_parent_class)->finalize (object);
+}
+
+static void
+gst_gl_color_convert_reset (GstGLColorConvert * convert)
+{
+  guint i;
+
   if (convert->fbo || convert->depth_buffer) {
     gst_gl_context_del_fbo (convert->context, convert->fbo,
         convert->depth_buffer);
@@ -449,69 +468,49 @@ gst_gl_color_convert_finalize (GObject * object)
     gst_memory_unref ((GstMemory *) convert->priv->scratch);
     convert->priv->scratch = NULL;
   }
-
-  if (convert->context) {
-    gst_object_unref (convert->context);
-    convert->context = NULL;
-  }
-
-  g_mutex_clear (&convert->lock);
-
-  G_OBJECT_CLASS (gst_gl_color_convert_parent_class)->finalize (object);
 }
 
-static gboolean
-_gst_gl_color_convert_init_format_unlocked (GstGLColorConvert * convert,
+static void
+_gst_gl_color_convert_set_format_unlocked (GstGLColorConvert * convert,
     GstVideoInfo * in_info, GstVideoInfo * out_info)
 {
-  g_return_val_if_fail (convert != NULL, FALSE);
-  g_return_val_if_fail (in_info, FALSE);
-  g_return_val_if_fail (out_info, FALSE);
-  g_return_val_if_fail (GST_VIDEO_INFO_FORMAT (in_info) !=
-      GST_VIDEO_FORMAT_UNKNOWN, FALSE);
-  g_return_val_if_fail (GST_VIDEO_INFO_FORMAT (in_info) !=
-      GST_VIDEO_FORMAT_ENCODED, FALSE);
-  g_return_val_if_fail (GST_VIDEO_INFO_FORMAT (out_info) !=
-      GST_VIDEO_FORMAT_UNKNOWN, FALSE);
-  g_return_val_if_fail (GST_VIDEO_INFO_FORMAT (out_info) !=
-      GST_VIDEO_FORMAT_ENCODED, FALSE);
-
-  if (convert->initted) {
-    return TRUE;
-  } else {
-    convert->initted = TRUE;
-  }
+  g_return_if_fail (convert != NULL);
+  g_return_if_fail (in_info);
+  g_return_if_fail (out_info);
+  g_return_if_fail (GST_VIDEO_INFO_FORMAT (in_info) !=
+      GST_VIDEO_FORMAT_UNKNOWN);
+  g_return_if_fail (GST_VIDEO_INFO_FORMAT (in_info) !=
+      GST_VIDEO_FORMAT_ENCODED);
+  g_return_if_fail (GST_VIDEO_INFO_FORMAT (out_info) !=
+      GST_VIDEO_FORMAT_UNKNOWN);
+  g_return_if_fail (GST_VIDEO_INFO_FORMAT (out_info) !=
+      GST_VIDEO_FORMAT_ENCODED);
+
+  if (gst_video_info_is_equal (&convert->in_info, in_info) &&
+      gst_video_info_is_equal (&convert->out_info, out_info))
+    return;
 
+  gst_gl_color_convert_reset (convert);
   convert->in_info = *in_info;
   convert->out_info = *out_info;
-
-  gst_gl_context_thread_add (convert->context,
-      (GstGLContextThreadFunc) _init_convert, convert);
-
-  return convert->priv->result;
+  convert->initted = FALSE;
 }
 
 /**
- * gst_gl_color_convert_init_format:
+ * gst_gl_color_convert_set_format:
  * @convert: a #GstGLColorConvert
  * @in_info: input #GstVideoInfo
  * @out_info: output #GstVideoInfo
  *
  * Initializes @convert with the information required for conversion.
- *
- * Returns: whether the initialization was successful
  */
-gboolean
-gst_gl_color_convert_init_format (GstGLColorConvert * convert,
+void
+gst_gl_color_convert_set_format (GstGLColorConvert * convert,
     GstVideoInfo * in_info, GstVideoInfo * out_info)
 {
-  gboolean ret;
-
   g_mutex_lock (&convert->lock);
-  ret = _gst_gl_color_convert_init_format_unlocked (convert, in_info, out_info);
+  _gst_gl_color_convert_set_format_unlocked (convert, in_info, out_info);
   g_mutex_unlock (&convert->lock);
-
-  return ret;
 }
 
 /**
@@ -522,7 +521,7 @@ gst_gl_color_convert_init_format (GstGLColorConvert * convert,
  *
  * Converts the data contained in in_tex into out_tex using the formats
  * specified by the #GstVideoInfo<!--  -->s passed to
- * gst_gl_color_convert_init_format() 
+ * gst_gl_color_convert_set_format() 
  *
  * Returns: whether the conversion was successful
  */
@@ -676,7 +675,7 @@ fail:
 }
 
 static void
-_RGB_to_RGB (GstGLContext * context, GstGLColorConvert * convert)
+_RGB_to_RGB (GstGLColorConvert * convert)
 {
   struct ConvertInfo *info = &convert->priv->convert_info;
   GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
@@ -695,7 +694,7 @@ _RGB_to_RGB (GstGLContext * context, GstGLColorConvert * convert)
 }
 
 static void
-_YUV_to_RGB (GstGLContext * context, GstGLColorConvert * convert)
+_YUV_to_RGB (GstGLColorConvert * convert)
 {
   struct ConvertInfo *info = &convert->priv->convert_info;
   GstVideoFormat out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
@@ -743,7 +742,8 @@ _YUV_to_RGB (GstGLContext * context, GstGLColorConvert * convert)
       info->in_n_textures = 1;
       info->shader_tex_names[1] = "Ytex";
       info->shader_tex_names[0] = "UVtex";
-      convert->priv->scratch = (GstGLMemory *) gst_gl_memory_alloc (context,
+      convert->priv->scratch =
+          (GstGLMemory *) gst_gl_memory_alloc (convert->context,
           GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA,
           GST_VIDEO_INFO_WIDTH (&convert->in_info),
           GST_VIDEO_INFO_HEIGHT (&convert->in_info),
@@ -769,7 +769,8 @@ _YUV_to_RGB (GstGLContext * context, GstGLColorConvert * convert)
       info->in_n_textures = 1;
       info->shader_tex_names[1] = "Ytex";
       info->shader_tex_names[0] = "UVtex";
-      convert->priv->scratch = (GstGLMemory *) gst_gl_memory_alloc (context,
+      convert->priv->scratch =
+          (GstGLMemory *) gst_gl_memory_alloc (convert->context,
           GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA,
           GST_VIDEO_INFO_WIDTH (&convert->in_info),
           GST_VIDEO_INFO_HEIGHT (&convert->in_info),
@@ -797,7 +798,7 @@ _YUV_to_RGB (GstGLContext * context, GstGLColorConvert * convert)
 }
 
 static void
-_RGB_to_YUV (GstGLContext * context, GstGLColorConvert * convert)
+_RGB_to_YUV (GstGLColorConvert * convert)
 {
   struct ConvertInfo *info = &convert->priv->convert_info;
   GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
@@ -868,7 +869,7 @@ _RGB_to_YUV (GstGLContext * context, GstGLColorConvert * convert)
 }
 
 static void
-_RGB_to_GRAY (GstGLContext * context, GstGLColorConvert * convert)
+_RGB_to_GRAY (GstGLColorConvert * convert)
 {
   struct ConvertInfo *info = &convert->priv->convert_info;
   GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
@@ -896,7 +897,7 @@ _RGB_to_GRAY (GstGLContext * context, GstGLColorConvert * convert)
 }
 
 static void
-_GRAY_to_RGB (GstGLContext * context, GstGLColorConvert * convert)
+_GRAY_to_RGB (GstGLColorConvert * convert)
 {
   struct ConvertInfo *info = &convert->priv->convert_info;
   GstVideoFormat out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
@@ -932,53 +933,56 @@ _GRAY_to_RGB (GstGLContext * context, GstGLColorConvert * convert)
 }
 
 /* Called in the gl thread */
-void
-_init_convert (GstGLContext * context, GstGLColorConvert * convert)
+static gboolean
+_init_convert (GstGLColorConvert * convert)
 {
   GstGLFuncs *gl;
   gboolean res;
   struct ConvertInfo *info = &convert->priv->convert_info;
   gint i;
 
-  gl = context->gl_vtable;
+  gl = convert->context->gl_vtable;
+
+  if (convert->initted)
+    return TRUE;
 
   GST_INFO ("Initializing color conversion from %s to %s",
       gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->in_info)),
       gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->out_info)));
 
   if (!gl->CreateProgramObject && !gl->CreateProgram) {
-    gst_gl_context_set_error (context,
+    gst_gl_context_set_error (convert->context,
         "Cannot perform color conversion without OpenGL shaders");
     goto error;
   }
 
   if (GST_VIDEO_INFO_IS_RGB (&convert->in_info)) {
     if (GST_VIDEO_INFO_IS_RGB (&convert->out_info)) {
-      _RGB_to_RGB (context, convert);
+      _RGB_to_RGB (convert);
     }
   }
 
   if (GST_VIDEO_INFO_IS_YUV (&convert->in_info)) {
     if (GST_VIDEO_INFO_IS_RGB (&convert->out_info)) {
-      _YUV_to_RGB (context, convert);
+      _YUV_to_RGB (convert);
     }
   }
 
   if (GST_VIDEO_INFO_IS_RGB (&convert->in_info)) {
     if (GST_VIDEO_INFO_IS_YUV (&convert->out_info)) {
-      _RGB_to_YUV (context, convert);
+      _RGB_to_YUV (convert);
     }
   }
 
   if (GST_VIDEO_INFO_IS_RGB (&convert->in_info)) {
     if (GST_VIDEO_INFO_IS_GRAY (&convert->out_info)) {
-      _RGB_to_GRAY (context, convert);
+      _RGB_to_GRAY (convert);
     }
   }
 
   if (GST_VIDEO_INFO_IS_GRAY (&convert->in_info)) {
     if (GST_VIDEO_INFO_IS_RGB (&convert->out_info)) {
-      _GRAY_to_RGB (context, convert);
+      _GRAY_to_RGB (convert);
     }
   }
 
@@ -986,15 +990,16 @@ _init_convert (GstGLContext * context, GstGLColorConvert * convert)
     goto unhandled_format;
 
   /* multiple draw targets not supported on GLES2...yet */
-  if (info->out_n_textures > 1 && (!gl->DrawBuffers || USING_GLES2 (context))) {
+  if (info->out_n_textures > 1 && (!gl->DrawBuffers ||
+          USING_GLES2 (convert->context))) {
     g_free (info->frag_prog);
     GST_ERROR ("Conversion requires output to multiple draw buffers");
     goto incompatible_api;
   }
 
   res =
-      gst_gl_context_gen_shader (context, text_vertex_shader, info->frag_prog,
-      &convert->shader);
+      gst_gl_context_gen_shader (convert->context, text_vertex_shader,
+      info->frag_prog, &convert->shader);
   g_free (info->frag_prog);
   if (!res)
     goto error;
@@ -1033,55 +1038,56 @@ _init_convert (GstGLContext * context, GstGLColorConvert * convert)
   gst_gl_shader_set_uniform_1f (convert->shader, "width",
       GST_VIDEO_INFO_WIDTH (&convert->in_info));
 
-  gst_gl_context_clear_shader (context);
+  gst_gl_context_clear_shader (convert->context);
 
-  if (!_init_convert_fbo (context, convert)) {
+  if (!_init_convert_fbo (convert)) {
     goto error;
   }
 
   gl->BindTexture (GL_TEXTURE_2D, 0);
 
-  convert->priv->result = TRUE;
-  return;
+  convert->initted = TRUE;
+
+  return TRUE;
 
 unhandled_format:
-  gst_gl_context_set_error (context, "Don't know how to convert from %s to %s",
+  gst_gl_context_set_error (convert->context,
+      "Don't know how to convert from %s to %s",
       gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->in_info)),
       gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->out_info)));
 
 error:
-  convert->priv->result = FALSE;
-  return;
+  return FALSE;
 
 incompatible_api:
   {
-    gst_gl_context_set_error (context, "Converting from %s to %s requires "
+    gst_gl_context_set_error (convert->context,
+        "Converting from %s to %s requires "
         "functionality that the current OpenGL setup does not support",
         gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->in_info)),
         gst_video_format_to_string (GST_VIDEO_INFO_FORMAT
             (&convert->out_info)));
-    convert->priv->result = FALSE;
-    return;
+    return FALSE;
   }
 }
 
 
 /* called by _init_convert (in the gl thread) */
-gboolean
-_init_convert_fbo (GstGLContext * context, GstGLColorConvert * convert)
+static gboolean
+_init_convert_fbo (GstGLColorConvert * convert)
 {
   GstGLFuncs *gl;
   guint out_width, out_height;
   GLuint fake_texture = 0;      /* a FBO must hava texture to init */
 
-  gl = context->gl_vtable;
+  gl = convert->context->gl_vtable;
 
   out_width = GST_VIDEO_INFO_WIDTH (&convert->out_info);
   out_height = GST_VIDEO_INFO_HEIGHT (&convert->out_info);
 
   if (!gl->GenFramebuffers) {
     /* turn off the pipeline because Frame buffer object is a not present */
-    gst_gl_context_set_error (context,
+    gst_gl_context_set_error (convert->context,
         "Context, EXT_framebuffer_object supported: no");
     return FALSE;
   }
@@ -1095,13 +1101,13 @@ _init_convert_fbo (GstGLContext * context, GstGLColorConvert * convert)
   /* setup the render buffer for depth */
   gl->GenRenderbuffers (1, &convert->depth_buffer);
   gl->BindRenderbuffer (GL_RENDERBUFFER, convert->depth_buffer);
-  if (USING_OPENGL (context)) {
+  if (USING_OPENGL (convert->context)) {
     gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
         out_width, out_height);
     gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
         out_width, out_height);
   }
-  if (USING_GLES2 (context)) {
+  if (USING_GLES2 (convert->context)) {
     gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
         out_width, out_height);
   }
@@ -1124,13 +1130,14 @@ _init_convert_fbo (GstGLContext * context, GstGLColorConvert * convert)
   gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
       GL_RENDERBUFFER, convert->depth_buffer);
 
-  if (USING_OPENGL (context)) {
+  if (USING_OPENGL (convert->context)) {
     gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
         GL_RENDERBUFFER, convert->depth_buffer);
   }
 
-  if (!gst_gl_context_check_framebuffer_status (context)) {
-    gst_gl_context_set_error (context, "GL framebuffer status incomplete");
+  if (!gst_gl_context_check_framebuffer_status (convert->context)) {
+    gst_gl_context_set_error (convert->context,
+        "GL framebuffer status incomplete");
     return FALSE;
   }
 
@@ -1157,6 +1164,11 @@ _do_convert (GstGLContext * context, GstGLColorConvert * convert)
   in_width = GST_VIDEO_INFO_WIDTH (&convert->in_info);
   in_height = GST_VIDEO_INFO_HEIGHT (&convert->in_info);
 
+  if (!_init_convert (convert)) {
+    convert->priv->result = FALSE;
+    return;
+  }
+
   GST_TRACE ("converting to textures:%p,%p,%p,%p dimensions:%ux%u, "
       "from textures:%p,%p,%p,%p dimensions:%ux%u", convert->out_tex[0],
       convert->out_tex[1], convert->out_tex[2], convert->out_tex[3],
index d259c28..44f68c6 100644 (file)
@@ -101,9 +101,9 @@ struct _GstGLColorConvertClass
 
 GstGLColorConvert * gst_gl_color_convert_new (GstGLContext * context);
 
-gboolean gst_gl_color_convert_init_format    (GstGLColorConvert * convert,
-                                              GstVideoInfo * in_info,
-                                              GstVideoInfo * out_info);
+void     gst_gl_color_convert_set_format    (GstGLColorConvert * convert,
+                                             GstVideoInfo * in_info,
+                                             GstVideoInfo * out_info);
 
 void     gst_gl_color_convert_set_texture_scaling (GstGLColorConvert * convert,
                                                    gfloat scaling[GST_VIDEO_MAX_PLANES][2]);
index 15586ab..5128c0a 100644 (file)
@@ -338,11 +338,8 @@ _init_download (GstGLContext * context, GstGLDownload * download)
   gst_video_info_set_format (&in_info, GST_VIDEO_FORMAT_RGBA, out_width,
       out_height);
 
-  download->priv->result =
-      gst_gl_color_convert_init_format (download->convert, &in_info,
+  gst_gl_color_convert_set_format (download->convert, &in_info,
       &download->info);
-  if (!download->priv->result)
-    return;
 
   download->priv->result = TRUE;
 }
index 3261d96..eaa34fe 100644 (file)
@@ -625,9 +625,7 @@ _init_upload (GstGLUpload * upload)
       GST_VIDEO_INFO_WIDTH (&upload->in_info),
       GST_VIDEO_INFO_HEIGHT (&upload->in_info));
 
-  if (!gst_gl_color_convert_init_format (upload->convert, &upload->in_info,
-        &out_info))
-    goto error;
+  gst_gl_color_convert_set_format (upload->convert, &upload->in_info, &out_info);
 
   upload->initted = TRUE;