mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 19:20:35 +00:00
[195/906] fix gstgldifferencematte and add an example app to test it dragging an image over the video (works with pixbufoverlay too, see pixbufdrop --help)
This commit is contained in:
parent
745a078f7f
commit
5425839342
3 changed files with 318 additions and 20 deletions
|
@ -366,6 +366,7 @@ const gchar *texture_interp_fragment_source =
|
|||
"vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);"
|
||||
"vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);"
|
||||
"vec4 alphacolor = texture2DRect (alpha, gl_TexCoord[0].st);"
|
||||
// "gl_FragColor = alphacolor;"
|
||||
"gl_FragColor = (alphacolor * blendcolor) + (1.0 - alphacolor) * basecolor;"
|
||||
"}";
|
||||
|
||||
|
|
|
@ -312,12 +312,12 @@ gst_gl_differencematte_diff (gint width, gint height, guint texture, gpointer st
|
|||
|
||||
gst_gl_shader_set_uniform_1i (differencematte->shader[0], "current", 0);
|
||||
|
||||
glActiveTexture (GL_TEXTURE2);
|
||||
glActiveTexture (GL_TEXTURE1);
|
||||
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->savedbgtexture);
|
||||
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
gst_gl_shader_set_uniform_1i (differencematte->shader[0], "saved", 2);
|
||||
gst_gl_shader_set_uniform_1i (differencematte->shader[0], "saved", 1);
|
||||
|
||||
gst_gl_differencematte_draw_texture (differencematte, texture);
|
||||
}
|
||||
|
@ -331,7 +331,6 @@ gst_gl_differencematte_hblur (gint width, gint height, guint texture, gpointer s
|
|||
0.176033, 0.199471, 0.176033,
|
||||
0.120985, 0.064759, 0.026995
|
||||
};
|
||||
|
||||
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glLoadIdentity ();
|
||||
|
@ -396,14 +395,14 @@ gst_gl_differencematte_interp (gint width, gint height, guint texture, gpointer
|
|||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
gst_gl_shader_set_uniform_1i (differencematte->shader[3], "base", 0);
|
||||
gst_gl_shader_set_uniform_1i (differencematte->shader[3], "blend", 0);
|
||||
|
||||
glActiveTexture (GL_TEXTURE1);
|
||||
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->newbgtexture);
|
||||
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
gst_gl_shader_set_uniform_1i (differencematte->shader[3], "blend", 1);
|
||||
gst_gl_shader_set_uniform_1i (differencematte->shader[3], "base", 1);
|
||||
|
||||
glActiveTexture (GL_TEXTURE2);
|
||||
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
@ -415,6 +414,17 @@ gst_gl_differencematte_interp (gint width, gint height, guint texture, gpointer
|
|||
gst_gl_differencematte_draw_texture (differencematte, texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_differencematte_identity (gint width, gint height, guint texture, gpointer stuff)
|
||||
{
|
||||
GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff);
|
||||
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glLoadIdentity ();
|
||||
|
||||
gst_gl_differencematte_draw_texture (differencematte, texture);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_gl_differencematte_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
|
||||
GstGLBuffer* outbuf)
|
||||
|
@ -450,20 +460,29 @@ gst_gl_differencematte_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
|
|||
differencematte->bg_has_changed = FALSE;
|
||||
}
|
||||
|
||||
gst_gl_filter_render_to_target (filter, inbuf->texture, differencematte->midtexture[0],
|
||||
gst_gl_differencematte_diff, differencematte);
|
||||
gst_gl_filter_render_to_target (filter,
|
||||
differencematte->midtexture[0],
|
||||
differencematte->midtexture[1],
|
||||
gst_gl_differencematte_hblur, differencematte);
|
||||
gst_gl_filter_render_to_target (filter,
|
||||
differencematte->midtexture[1],
|
||||
differencematte->midtexture[2],
|
||||
gst_gl_differencematte_vblur, differencematte);
|
||||
gst_gl_filter_render_to_target (filter,
|
||||
inbuf->texture,
|
||||
outbuf->texture,
|
||||
gst_gl_differencematte_interp, differencematte);
|
||||
|
||||
if (differencematte->savedbgtexture != 0) {
|
||||
gst_gl_filter_render_to_target (filter,
|
||||
inbuf->texture,
|
||||
differencematte->midtexture[0],
|
||||
gst_gl_differencematte_diff, differencematte);
|
||||
gst_gl_filter_render_to_target (filter,
|
||||
differencematte->midtexture[0],
|
||||
differencematte->midtexture[1],
|
||||
gst_gl_differencematte_hblur, differencematte);
|
||||
gst_gl_filter_render_to_target (filter,
|
||||
differencematte->midtexture[1],
|
||||
differencematte->midtexture[2],
|
||||
gst_gl_differencematte_vblur, differencematte);
|
||||
gst_gl_filter_render_to_target (filter,
|
||||
inbuf->texture,
|
||||
outbuf->texture,
|
||||
gst_gl_differencematte_interp, differencematte);
|
||||
} else {
|
||||
gst_gl_filter_render_to_target (filter,
|
||||
inbuf->texture,
|
||||
outbuf->texture,
|
||||
gst_gl_differencematte_identity, differencematte);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
278
tests/examples/gtk/fxtest/pixbufdrop.c
Normal file
278
tests/examples/gtk/fxtest/pixbufdrop.c
Normal file
|
@ -0,0 +1,278 @@
|
|||
#include <gst/gst.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gst/interfaces/xoverlay.h>
|
||||
|
||||
static gint delay = 0;
|
||||
static gint saveddelay = 0;
|
||||
static gint method = 1;
|
||||
|
||||
struct _SourceData
|
||||
{
|
||||
gpointer data;
|
||||
gpointer nick;
|
||||
gpointer value;
|
||||
};
|
||||
typedef struct _SourceData SourceData;
|
||||
|
||||
static GstBusSyncReply
|
||||
create_window (GstBus *bus, GstMessage *message, GtkWidget *widget)
|
||||
{
|
||||
// ignore anything but 'prepare-xwindow-id' element messages
|
||||
if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
|
||||
return GST_BUS_PASS;
|
||||
|
||||
if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
|
||||
return GST_BUS_PASS;
|
||||
|
||||
#ifdef WIN32
|
||||
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
|
||||
reinterpret_cast<gulong>GDK_WINDOW_HWND(widget->window));
|
||||
#else
|
||||
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
|
||||
GDK_WINDOW_XWINDOW(widget->window));
|
||||
#endif
|
||||
|
||||
gst_message_unref (message);
|
||||
|
||||
return GST_BUS_DROP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
expose_cb(GtkWidget *widget, GdkEventExpose *event, GstElement *videosink)
|
||||
{
|
||||
gst_x_overlay_expose (GST_X_OVERLAY (videosink));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_cb (GtkWidget *widget, GdkEvent *event, GstElement *pipeline)
|
||||
{
|
||||
g_message ("destroy callback");
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (pipeline);
|
||||
|
||||
gtk_main_quit ();
|
||||
}
|
||||
|
||||
gboolean
|
||||
play_cb (GtkWidget * widget, gpointer data)
|
||||
{
|
||||
g_message ("playing");
|
||||
gst_element_set_state (GST_ELEMENT (data), GST_STATE_PLAYING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
null_cb (GtkWidget * widget, gpointer data)
|
||||
{
|
||||
g_message ("nulling");
|
||||
gst_element_set_state (GST_ELEMENT (data), GST_STATE_NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ready_cb (GtkWidget * widget, gpointer data)
|
||||
{
|
||||
g_message ("readying");
|
||||
gst_element_set_state (GST_ELEMENT (data), GST_STATE_READY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pause_cb (GtkWidget * widget, gpointer data)
|
||||
{
|
||||
g_message ("pausing");
|
||||
gst_element_set_state (GST_ELEMENT (data), GST_STATE_PAUSED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_location_delayed (gpointer data)
|
||||
{
|
||||
SourceData *sdata = (SourceData *) data;
|
||||
delay--;
|
||||
g_print ("%d\n", delay);
|
||||
if (delay > 0) {
|
||||
return TRUE;
|
||||
}
|
||||
g_object_set (G_OBJECT (sdata->data), sdata->nick, sdata->value, NULL);
|
||||
delay = saveddelay;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_drag_data_received (GtkWidget * widget,
|
||||
GdkDragContext * context, int x, int y,
|
||||
GtkSelectionData * seldata, guint inf, guint time,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPixbufFormat *format;
|
||||
SourceData *userdata = g_new0 (SourceData, 1);
|
||||
gchar **uris = gtk_selection_data_get_uris (seldata);
|
||||
gchar *filename = g_filename_from_uri (uris[0], NULL, NULL);
|
||||
g_return_if_fail (filename != NULL);
|
||||
format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
|
||||
g_return_if_fail (format);
|
||||
g_print ("received %s image: %s\n", filename,
|
||||
gdk_pixbuf_format_get_name (format));
|
||||
userdata->nick = "location";
|
||||
userdata->value = g_strdup (filename);
|
||||
userdata->data = data;
|
||||
saveddelay = delay;
|
||||
if (delay > 0) {
|
||||
g_print ("%d\n", delay);
|
||||
g_timeout_add_seconds (1, set_location_delayed, userdata);
|
||||
}
|
||||
else
|
||||
g_object_set (G_OBJECT (userdata->data), userdata->nick, userdata->value, NULL);
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
|
||||
gint
|
||||
main (gint argc, gchar * argv[])
|
||||
{
|
||||
GstStateChangeReturn ret;
|
||||
GstElement *pipeline;
|
||||
GstElement *uload, *filter, *sink;
|
||||
GstElement *sourcebin;
|
||||
GstBus *bus;
|
||||
GError *error = NULL;
|
||||
|
||||
GtkWidget *window;
|
||||
GtkWidget *screen;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *play, *pause, *null, *ready;
|
||||
|
||||
gchar **source_desc_array = NULL;
|
||||
gchar *source_desc = NULL;
|
||||
|
||||
GOptionContext *context;
|
||||
GOptionEntry options[] = {
|
||||
{ "source-bin", 's', 0, G_OPTION_ARG_STRING_ARRAY, &source_desc_array,
|
||||
"Use a custom source bin description (gst-launch style)", NULL },
|
||||
{ "method", 'm', 0, G_OPTION_ARG_INT, &method, "1 for gstdifferencematte, 2 for gstpixbufoverlay", "M" },
|
||||
{ "delay", 'd', 0, G_OPTION_ARG_INT, &delay, "Wait N seconds before to send the image to gstreamer (useful with differencematte)", "N" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
g_thread_init (NULL);
|
||||
|
||||
context = g_option_context_new (NULL);
|
||||
g_option_context_add_main_entries (context, options, NULL);
|
||||
g_option_context_add_group (context, gst_init_get_option_group ());
|
||||
g_option_context_add_group (context, gtk_get_option_group (TRUE));
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error)) {
|
||||
g_print ("Inizialization error: %s\n", GST_STR_NULL (error->message));
|
||||
return -1;
|
||||
}
|
||||
g_option_context_free (context);
|
||||
|
||||
if (source_desc_array != NULL) {
|
||||
source_desc = g_strjoinv (" ", source_desc_array);
|
||||
g_strfreev (source_desc_array);
|
||||
}
|
||||
if (source_desc == NULL) {
|
||||
source_desc = g_strdup ("videotestsrc ! video/x-raw-rgb, width=352, height=288 ! identity");
|
||||
}
|
||||
|
||||
sourcebin = gst_parse_bin_from_description (g_strdup (source_desc), TRUE, &error);
|
||||
g_free (source_desc);
|
||||
if (error) {
|
||||
g_print ("Error while parsing source bin description: %s\n",
|
||||
GST_STR_NULL (error->message));
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_set_application_name ("gst-gl-effects test app");
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (window), 3);
|
||||
|
||||
pipeline = gst_pipeline_new ("pipeline");
|
||||
|
||||
uload = gst_element_factory_make ("glupload", "glu");
|
||||
if (method == 2) {
|
||||
filter = gst_element_factory_make ("glpixbufoverlay", "flt");
|
||||
} else {
|
||||
filter = gst_element_factory_make ("gldifferencematte", "flt");
|
||||
}
|
||||
sink = gst_element_factory_make ("glimagesink", "glsink");
|
||||
|
||||
gst_bin_add_many (GST_BIN (pipeline), sourcebin, uload, filter, sink, NULL);
|
||||
|
||||
if (!gst_element_link_many (sourcebin, uload, filter, sink, NULL)) {
|
||||
g_print ("Failed to link one or more elements!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_signal_connect (G_OBJECT (window), "delete-event",
|
||||
G_CALLBACK (destroy_cb), pipeline);
|
||||
g_signal_connect (G_OBJECT (window), "destroy-event",
|
||||
G_CALLBACK (destroy_cb), pipeline);
|
||||
|
||||
screen = gtk_drawing_area_new ();
|
||||
|
||||
gtk_widget_set_size_request (screen, 640, 480); // 500 x 376
|
||||
|
||||
vbox = gtk_vbox_new (FALSE, 2);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), screen, TRUE, TRUE, 0);
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 0);
|
||||
|
||||
play = gtk_button_new_with_label ("PLAY");
|
||||
|
||||
g_signal_connect (G_OBJECT (play), "clicked", G_CALLBACK (play_cb), pipeline);
|
||||
|
||||
pause = gtk_button_new_with_label ("PAUSE");
|
||||
|
||||
g_signal_connect (G_OBJECT (pause), "clicked",
|
||||
G_CALLBACK (pause_cb), pipeline);
|
||||
|
||||
null = gtk_button_new_with_label ("NULL");
|
||||
|
||||
g_signal_connect (G_OBJECT (null), "clicked", G_CALLBACK (null_cb), pipeline);
|
||||
|
||||
ready = gtk_button_new_with_label ("READY");
|
||||
|
||||
g_signal_connect (G_OBJECT (ready), "clicked",
|
||||
G_CALLBACK (ready_cb), pipeline);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (hbox), null, TRUE, TRUE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), ready, TRUE, TRUE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), play, TRUE, TRUE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), pause, TRUE, TRUE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
||||
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, screen);
|
||||
gst_object_unref (bus);
|
||||
g_signal_connect(screen, "expose-event", G_CALLBACK(expose_cb), sink);
|
||||
|
||||
gtk_drag_dest_set (screen, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY);
|
||||
gtk_drag_dest_add_uri_targets (screen);
|
||||
|
||||
g_signal_connect (screen, "drag-data-received",
|
||||
G_CALLBACK (on_drag_data_received), filter);
|
||||
|
||||
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||
g_print ("Failed to start up pipeline!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gtk_widget_show_all (GTK_WIDGET (window));
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue