Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gst-plugins-base.git] / tests / icles / test-colorkey.c
1 /* GStreamer
2  * Copyright (C) <2008> Stefan Kost <ensonic@users.sf.net>
3  *
4  * test-colorkey: test manual colorkey handling
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <glib.h>
30 #include <gdk/gdkx.h>
31 #include <gtk/gtk.h>
32
33 #include <gst/gst.h>
34 #include <gst/interfaces/videooverlay.h>
35 #include <gst/interfaces/propertyprobe.h>
36
37 #if !GTK_CHECK_VERSION (2, 17, 7)
38 static void
39 gtk_widget_get_allocation (GtkWidget * w, GtkAllocation * a)
40 {
41   *a = w->allocation;
42 }
43 #endif
44
45 static GtkWidget *video_window = NULL;
46 static GstElement *sink = NULL;
47 static gulong embed_xid = 0;
48 static GdkColor trans_color;
49 static gboolean trans_color_set = FALSE;
50
51 static void
52 redraw_overlay (GtkWidget * widget)
53 {
54   GtkAllocation allocation;
55   GdkWindow *window = gtk_widget_get_window (widget);
56   cairo_t *cr;
57
58   cr = gdk_cairo_create (window);
59   gtk_widget_get_allocation (widget, &allocation);
60
61   cairo_set_source_rgb (cr, 1, 1, 1);
62   cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
63   cairo_fill (cr);
64
65   if (trans_color_set) {
66     guint x, y;
67     guint h = allocation.height * 0.75;
68
69     gdk_cairo_set_source_color (cr, &trans_color);
70     cairo_rectangle (cr, 0, 0, allocation.width, h);
71     cairo_fill (cr);
72
73     for (y = h; y < allocation.height; y++) {
74       for (x = 0; x < allocation.width; x++) {
75         if (((x & 1) || (y & 1)) && (x & 1) != (y & 1)) {
76           cairo_move_to (cr, x, y);
77           cairo_paint (cr);
78         }
79       }
80     }
81   }
82 }
83
84 static gboolean
85 handle_resize_cb (GtkWidget * widget, GdkEventConfigure * event, gpointer data)
86 {
87   redraw_overlay (widget);
88   return FALSE;
89 }
90
91 static gboolean
92 handle_expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer data)
93 {
94   redraw_overlay (widget);
95   return FALSE;
96 }
97
98 static void
99 realize_cb (GtkWidget * widget, gpointer data)
100 {
101 #if GTK_CHECK_VERSION(2,18,0)
102   {
103     GdkWindow *window = gtk_widget_get_window (widget);
104
105     /* This is here just for pedagogical purposes, GDK_WINDOW_XID will call it
106      * as well */
107     if (!gdk_window_ensure_native (window))
108       g_error ("Couldn't create native window needed for GstVideoOverlay!");
109   }
110 #endif
111
112   {
113     GdkWindow *window = gtk_widget_get_window (video_window);
114
115     embed_xid = GDK_WINDOW_XID (window);
116     g_print ("Window realize: video window XID = %lu\n", embed_xid);
117   }
118 }
119
120 static void
121 msg_state_changed (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
122 {
123   const GstStructure *s;
124
125   s = gst_message_get_structure (message);
126
127   /* We only care about state changed on the pipeline */
128   if (s && GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (pipeline)) {
129     GstState old, new, pending;
130     gint color;
131
132     gst_message_parse_state_changed (message, &old, &new, &pending);
133
134     /* When state of the pipeline changes to paused or playing we start updating scale */
135     switch (GST_STATE_TRANSITION (old, new)) {
136       case GST_STATE_CHANGE_READY_TO_PAUSED:{
137         g_object_get (G_OBJECT (sink), "colorkey", &color, NULL);
138         if (color != -1) {
139           trans_color.red = (color & 0xff0000) >> 8;
140           trans_color.green = (color & 0xff00);
141           trans_color.blue = (color & 0xff) << 8;
142           trans_color_set = TRUE;
143         } else {
144           trans_color_set = FALSE;
145         }
146         handle_resize_cb (video_window, NULL, NULL);
147         break;
148       }
149       default:
150         break;
151     }
152   }
153 }
154
155 static void
156 window_closed (GtkWidget * widget, GdkEvent * event, gpointer user_data)
157 {
158   GstElement *pipeline = user_data;
159
160   g_print ("stopping\n");
161   gtk_widget_hide (widget);
162   gst_element_set_state (pipeline, GST_STATE_NULL);
163   gtk_main_quit ();
164 }
165
166 static gboolean
167 start_pipeline (gpointer user_data)
168 {
169   GstElement *pipeline = GST_ELEMENT (user_data);
170   GstStateChangeReturn sret;
171
172   sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
173   if (sret == GST_STATE_CHANGE_FAILURE) {
174     gst_element_set_state (pipeline, GST_STATE_NULL);
175     gst_object_unref (pipeline);
176     gtk_main_quit ();
177   }
178   return FALSE;
179 }
180
181 int
182 main (int argc, char **argv)
183 {
184   GtkWidget *window;
185   GstElement *pipeline, *src;
186   GstBus *bus;
187   GstStateChangeReturn sret;
188   GstPropertyProbe *probe;
189   GValueArray *arr;
190
191   if (!g_thread_supported ())
192     g_thread_init (NULL);
193
194   gst_init (&argc, &argv);
195   gtk_init (&argc, &argv);
196
197   /* prepare the pipeline */
198
199   pipeline = gst_pipeline_new ("xvoverlay");
200   src = gst_element_factory_make ("videotestsrc", NULL);
201   sink = gst_element_factory_make ("xvimagesink", NULL);
202   gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
203   gst_element_link (src, sink);
204
205 #define COLOR_GRAY 0x7F7F7F
206
207   g_object_set (G_OBJECT (sink), "autopaint-colorkey", FALSE,
208       "force-aspect-ratio", TRUE, "draw-borders", FALSE,
209       "colorkey", COLOR_GRAY, NULL);
210
211   /* check xvimagesink capabilities */
212   sret = gst_element_set_state (pipeline, GST_STATE_READY);
213   if (sret == GST_STATE_CHANGE_FAILURE) {
214     g_printerr ("Can't set pipeline to READY\n");
215     gst_object_unref (pipeline);
216     return -1;
217   }
218
219   probe = GST_PROPERTY_PROBE (sink);
220   if (!probe) {
221     g_printerr ("Can't probe sink\n");
222     gst_element_set_state (pipeline, GST_STATE_NULL);
223     gst_object_unref (pipeline);
224     return -1;
225   }
226   arr =
227       gst_property_probe_probe_and_get_values_name (probe,
228       "autopaint-colorkey");
229   if (!arr || !arr->n_values) {
230     g_printerr ("Can't disable autopaint-colorkey property\n");
231     gst_element_set_state (pipeline, GST_STATE_NULL);
232     gst_object_unref (pipeline);
233     return -1;
234   }
235   if (arr)
236     g_value_array_free (arr);
237
238   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
239   gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
240   g_signal_connect (bus, "message::state-changed",
241       G_CALLBACK (msg_state_changed), pipeline);
242   gst_object_unref (bus);
243
244   /* prepare the ui */
245
246   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
247   g_signal_connect (G_OBJECT (window), "delete-event",
248       G_CALLBACK (window_closed), (gpointer) pipeline);
249   gtk_window_set_default_size (GTK_WINDOW (window), 320, 240);
250
251   video_window = gtk_drawing_area_new ();
252   g_signal_connect (G_OBJECT (video_window), "configure-event",
253       G_CALLBACK (handle_resize_cb), NULL);
254   g_signal_connect (G_OBJECT (video_window), "expose-event",
255       G_CALLBACK (handle_expose_cb), NULL);
256   g_signal_connect (video_window, "realize", G_CALLBACK (realize_cb), NULL);
257   gtk_widget_set_double_buffered (video_window, FALSE);
258   gtk_container_add (GTK_CONTAINER (window), video_window);
259
260   /* show the gui and play */
261
262   gtk_widget_show_all (window);
263
264   /* realize window now so that the video window gets created and we can
265    * obtain its XID before the pipeline is started up and the videosink
266    * asks for the XID of the window to render onto */
267   gtk_widget_realize (window);
268
269   /* we should have the XID now */
270   g_assert (embed_xid != 0);
271
272   /* we know what the video sink is in this case (xvimagesink), so we can
273    * just set it directly here now (instead of waiting for a
274    * prepare-window-handle element message in a sync bus handler and setting
275    * it there) */
276   g_print ("setting XID %lu\n", embed_xid);
277   gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), embed_xid);
278
279   g_idle_add (start_pipeline, pipeline);
280   gtk_main ();
281
282   gst_object_unref (pipeline);
283
284   return 0;
285 }