static gboolean gst_gl_filter_glass_filter (GstGLFilter * filter, GstGLBuffer * inbuf, GstGLBuffer * outbuf) { gpointer glass_filter = GST_GL_FILTER_GLASS (filter); GST_GL_FILTER_GLASS (glass_filter)->timestamp = GST_BUFFER_TIMESTAMP (inbuf); //blocking call, use a FBO gst_gl_display_use_fbo (filter->display, filter->width, filter->height, filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_glass_callback, inbuf->width, inbuf->height, inbuf->texture, 80, (gdouble) filter->width / (gdouble) filter->height, 1.0, 5000.0, GST_GL_DISPLAY_PROJECTION_PERSPECTIVE, (gpointer) glass_filter); return TRUE; }
static void gst_gl_filter_glass_reset (GstGLFilter * filter) { GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); //blocking call, wait the opengl thread has destroyed the shader gst_gl_display_del_shader (filter->display, glass_filter->shader); }
static gboolean gst_gl_filter_glass_init_shader (GstGLFilter * filter) { GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); //blocking call, wait the opengl thread has compiled the shader return gst_gl_display_gen_shader (filter->display, 0, glass_fragment_source, &glass_filter->shader); }
//opengl scene, params: input texture (not the output filter->texture) static void gst_gl_filter_glass_callback (gpointer stuff) { static gint64 start_time = 0; gfloat rotation; GstGLFilter *filter = GST_GL_FILTER (stuff); GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (stuff); GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; gint width = GST_VIDEO_INFO_WIDTH (&filter->out_info); gint height = GST_VIDEO_INFO_HEIGHT (&filter->out_info); guint texture = glass_filter->in_tex; if (start_time == 0) start_time = get_time (); else { gint64 time_left = (glass_filter->timestamp / 1000) - (get_time () - start_time); time_left -= 1000000 / 25; if (time_left > 2000) { GST_LOG ("escape"); return; } } gst_gl_shader_use (glass_filter->passthrough_shader); gst_gl_filter_glass_draw_background_gradient (glass_filter); //Rotation if (start_time != 0) { gint64 time_passed = get_time () - start_time; rotation = sin (time_passed / 1200000.0) * 45.0f; } else { rotation = 0.0f; } gl->Enable (GL_BLEND); gl->BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gst_gl_shader_use (glass_filter->shader); //Reflection gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, 0.0f, 2.0f, 0.3f, 0.0f, TRUE, rotation); //Main video gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, 0.0f, 0.0f, 1.0f, 1.0f, FALSE, rotation); gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context); gl->Disable (GL_BLEND); }
static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter, gint width, gint height, guint texture, gfloat center_x, gfloat center_y, gfloat start_alpha, gfloat stop_alpha, gboolean reversed, gfloat rotation) { GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; gfloat topy = reversed ? center_y - 1.0f : center_y + 1.0f; gfloat bottomy = reversed ? center_y + 1.0f : center_y - 1.0f; /* *INDENT-OFF* */ gfloat mesh[] = { /*| Vertex |TexCoord0| Colour |*/ center_x-1.6, topy, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, start_alpha, center_x+1.6, topy, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, start_alpha, center_x+1.6, bottomy, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, stop_alpha, center_x-1.6, bottomy, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, stop_alpha, }; /* *INDENT-ON* */ GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; gl->ActiveTexture (GL_TEXTURE0); gl->BindTexture (GL_TEXTURE_2D, texture); gst_gl_shader_set_uniform_1i (glass_filter->shader, "tex", 0); gst_gl_shader_set_uniform_1f (glass_filter->shader, "yrot", rotation); gst_gl_shader_set_uniform_1f (glass_filter->shader, "aspect", (gfloat) width / (gfloat) height); gl->ClientActiveTexture (GL_TEXTURE0); gl->EnableClientState (GL_TEXTURE_COORD_ARRAY); gl->EnableClientState (GL_VERTEX_ARRAY); gl->EnableClientState (GL_COLOR_ARRAY); gl->VertexPointer (3, GL_FLOAT, 9 * sizeof (gfloat), mesh); gl->TexCoordPointer (2, GL_FLOAT, 9 * sizeof (gfloat), &mesh[3]); gl->ColorPointer (4, GL_FLOAT, 9 * sizeof (gfloat), &mesh[5]); gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); gl->DisableClientState (GL_TEXTURE_COORD_ARRAY); gl->DisableClientState (GL_VERTEX_ARRAY); gl->DisableClientState (GL_COLOR_ARRAY); }
static gboolean gst_gl_filter_glass_filter_texture (GstGLFilter * filter, guint in_tex, guint out_tex) { GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); glass_filter->in_tex = in_tex; //blocking call, use a FBO gst_gl_context_use_fbo_v2 (GST_GL_BASE_FILTER (filter)->context, GST_VIDEO_INFO_WIDTH (&filter->out_info), GST_VIDEO_INFO_HEIGHT (&filter->out_info), filter->fbo, filter->depthbuffer, out_tex, gst_gl_filter_glass_callback, (gpointer) glass_filter); return TRUE; }
//opengl scene, params: input texture (not the output filter->texture) static void gst_gl_filter_glass_callback (gint width, gint height, guint texture, gpointer stuff) { static gint64 start_time = 0; GstGLFilter *filter = GST_GL_FILTER (stuff); GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (stuff); if (start_time == 0) start_time = get_time (); else { gint64 time_left = (glass_filter->timestamp / 1000) - (get_time () - start_time); time_left -= 1000000 / 25; if (time_left > 2000) { GST_LOG ("escape"); return; } } glTranslatef (0.0f, 2.0f, -3.0f); gst_gl_filter_glass_draw_background_gradient (); //Rotation if (start_time != 0) { gint64 time_passed = get_time () - start_time; glRotated (sin (time_passed / 1200000.0) * 45.0, 0.0, 1.0, 0.0); } glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Reflection gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, 0.0f, 0.0f, 0.3f, 0.0f, TRUE); //Main video gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, 0.0f, -2.0f, 1.0f, 1.0f, FALSE); glDisable (GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_BLEND); }
static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter, gint width, gint height, guint texture, gfloat center_x, gfloat center_y, gfloat start_alpha, gfloat stop_alpha, gboolean reversed) { GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); gfloat topy; gfloat bottomy; if (reversed) { topy = center_y - 1.0f; bottomy = center_y + 1.0f; } else { topy = center_y + 1.0f; bottomy = center_y - 1.0f; } gst_gl_shader_use (glass_filter->shader); glActiveTextureARB (GL_TEXTURE0_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glDisable (GL_TEXTURE_RECTANGLE_ARB); gst_gl_shader_set_uniform_1i (glass_filter->shader, "tex", 0); gst_gl_shader_set_uniform_1f (glass_filter->shader, "width", (gfloat) width); gst_gl_shader_set_uniform_1f (glass_filter->shader, "height", (gfloat) height); glBegin (GL_QUADS); glColor4f (1.0f, 1.0f, 1.0f, start_alpha); glTexCoord2i (0, height); glVertex2f (center_x - 1.6f, topy); glTexCoord2i (width, height); glVertex2f (center_x + 1.6f, topy); glColor4f (1.0, 1.0, 1.0, stop_alpha); glTexCoord2i (width, 0); glVertex2f (center_x + 1.6f, bottomy); glTexCoord2i (0, 0); glVertex2f (center_x - 1.6f, bottomy); glEnd (); gst_gl_shader_use (0); }
static gboolean gst_gl_filter_glass_reset (GstBaseTransform * trans) { GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (trans); //blocking call, wait the opengl thread has destroyed the shader if (glass_filter->shader) gst_gl_context_del_shader (GST_GL_BASE_FILTER (trans)->context, glass_filter->shader); glass_filter->shader = NULL; if (glass_filter->passthrough_shader) gst_gl_context_del_shader (GST_GL_BASE_FILTER (trans)->context, glass_filter->passthrough_shader); glass_filter->passthrough_shader = NULL; return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans); }
static gboolean gst_gl_filter_glass_init_shader (GstGLFilter * filter) { gboolean ret; GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); //blocking call, wait the opengl thread has compiled the shader ret = gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, glass_vertex_source, glass_fragment_source, &glass_filter->shader); if (ret) ret = gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, passthrough_vertex, passthrough_fragment, &glass_filter->passthrough_shader); return ret; }