gl/colorconvert: implement lazy init

This commit is contained in:
Matthew Waters 2014-05-09 18:07:03 +10:00 committed by Tim-Philipp Müller
parent 17ba668c7a
commit 977c326c59
4 changed files with 102 additions and 95 deletions

View 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);
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 (convert->initted) {
return TRUE;
} else {
convert->initted = TRUE;
}
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],

View 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]);

View 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;
}

View 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;