update related to avsystem,evasimagesink
[framework/multimedia/gst-plugins-ext0.10.git] / evasimagesink / src / gstevasimagesink.c
1 /*
2  * evasimagesink
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Sangchul Lee <sc11.lee@samsung.com>
7  *
8  * This library is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the
10  * Free Software Foundation; either version 2.1 of the License, or (at your option)
11  * any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
14  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; if not, write to the Free Software Foundation, Inc., 51
20  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23
24 /**
25  * SECTION:element-evasimagesink
26  * Gstreamer Evas Video Sink - draw video on the given Evas Image Object
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #  include <config.h>
31 #endif
32
33 #include <sys/types.h>
34 #include <gst/gst.h>
35 #include <gst/video/video.h>
36 #include <gst/video/gstvideosink.h>
37 #include <Evas.h>
38 #include <Ecore.h>
39 #include <Ecore_X.h>
40
41 #include "gstevasimagesink.h"
42
43 #define CAP_WIDTH "width"
44 #define CAP_HEIGHT "height"
45
46 GST_DEBUG_CATEGORY_STATIC (gst_evas_image_sink_debug);
47 #define GST_CAT_DEFAULT gst_evas_image_sink_debug
48
49 /* Enumerations */
50 enum
51 {
52         /* FILL ME */
53         LAST_SIGNAL
54 };
55
56 enum
57 {
58         PROP_0,
59         PROP_EVAS_OBJECT,
60         PROP_EVAS_OBJECT_SHOW,
61 };
62
63 #define COLOR_DEPTH 4
64 #define GL_X11_ENGINE "gl_x11"
65
66 static inline gboolean
67 is_evas_image_object (Evas_Object *obj)
68 {
69         const char *type;
70         if (!obj) {
71                 return FALSE;
72         }
73         type = evas_object_type_get (obj);
74         if (!type) {
75                 return FALSE;
76         }
77         if (strcmp (type, "image") == 0) {
78                 return TRUE;
79         }
80         return FALSE;
81 }
82
83 /* the capabilities of the inputs.
84  *
85  * BGRx format
86  */
87 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
88                 GST_PAD_SINK,
89                 GST_PAD_ALWAYS,
90                 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx));
91
92 GST_BOILERPLATE (GstEvasImageSink, gst_evas_image_sink, GstVideoSink, GST_TYPE_VIDEO_SINK);
93
94 static void gst_evas_image_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
95 static void gst_evas_image_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
96 static gboolean gst_evas_image_sink_set_caps (GstBaseSink * base_sink, GstCaps * caps);
97 static GstFlowReturn gst_evas_image_sink_show_frame (GstVideoSink * video_sink, GstBuffer * buf);
98
99 static void
100 gst_evas_image_sink_base_init (gpointer gclass)
101 {
102         GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
103
104         gst_element_class_set_details_simple (element_class,
105                 "EvasImageSink",
106                 "VideoSink",
107                 "Video sink element for evas image object",
108                 "Wonguk Jeong <wonguk.jeong@samsung.com>");
109
110         gst_element_class_add_pad_template (element_class,
111         gst_static_pad_template_get (&sink_factory));
112 }
113
114 static void
115 gst_evas_image_sink_class_init (GstEvasImageSinkClass * klass)
116 {
117         GObjectClass *gobject_class;
118         GstBaseSinkClass *gstbasesink_class;
119         GstVideoSinkClass *gstvideosink_class;
120
121         gobject_class = (GObjectClass *) klass;
122         gstbasesink_class = GST_BASE_SINK_CLASS (klass);
123         gstvideosink_class = GST_VIDEO_SINK_CLASS (klass);
124
125         gobject_class->set_property = gst_evas_image_sink_set_property;
126         gobject_class->get_property = gst_evas_image_sink_get_property;
127
128         g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT,
129                 g_param_spec_pointer ("evas-object", "Destination Evas Object", "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
130         g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT_SHOW,
131                 g_param_spec_boolean ("visible", "Show Evas Object", "When disabled, evas object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
132
133         gstvideosink_class->show_frame = gst_evas_image_sink_show_frame;
134         gstbasesink_class->set_caps = gst_evas_image_sink_set_caps;
135 }
136
137 static void
138 gst_evas_image_sink_fini (gpointer data, GObject *obj)
139 {
140         GstEvasImageSink *esink = GST_EVASIMAGESINK (obj);
141         if (!esink) {
142                 return;
143         }
144         if (esink->epipe) {
145                 ecore_pipe_del (esink->epipe);
146         }
147         if (esink->oldbuf) {
148                 gst_buffer_unref (esink->oldbuf);
149         }
150 }
151
152 static void
153 evas_image_sink_cb_pipe (void *data, void *buffer, unsigned int nbyte)
154 {
155         GstBuffer *buf;
156         GstEvasImageSink *esink = data;
157         void *img_data;
158
159         if (!data || !buffer) {
160                 return;
161         }
162         if (nbyte != sizeof (GstBuffer *)) {
163                 return;
164         }
165         if (!esink->eo) {
166                 return;
167         }
168
169         memcpy (&buf, buffer, sizeof (GstBuffer *));
170         if (!buf) {
171                 GST_ERROR ("There is no buffer\n");
172                 return;
173         }
174
175         if (esink->gl_zerocopy) {
176                 img_data = evas_object_image_data_get (esink->eo, EINA_TRUE);
177                 if (!img_data || !GST_BUFFER_DATA(buf)) {
178                         GST_WARNING ("Cannot get image data from evas object or cannot get gstbuffer data\n");
179                         evas_object_image_data_set(esink->eo, img_data);
180                 } else {
181                         GST_DEBUG ("img_data(%x), GST_BUFFER_DATA(buf):%x, esink->w(%d),esink->h(%d)",img_data,GST_BUFFER_DATA(buf),esink->w,esink->h);
182                         memcpy (img_data, GST_BUFFER_DATA (buf), esink->w * esink->h * COLOR_DEPTH);
183                         evas_object_image_pixels_dirty_set (esink->eo, 1);
184                         evas_object_image_data_set(esink->eo, img_data);
185                 }
186                 gst_buffer_unref (buf);
187         } else {
188                 evas_object_image_data_set (esink->eo, GST_BUFFER_DATA (buf));
189                 evas_object_image_pixels_dirty_set (esink->eo, 1);
190                 if (esink->oldbuf) {
191                         gst_buffer_unref(esink->oldbuf);
192                 }
193                 esink->oldbuf = buf;
194         }
195 }
196
197 static void
198 gst_evas_image_sink_init (GstEvasImageSink * esink, GstEvasImageSinkClass * gclass)
199 {
200         esink->eo = NULL;
201         g_object_weak_ref (G_OBJECT (esink), gst_evas_image_sink_fini, NULL);
202 }
203
204 static void
205 evas_image_sink_cb_del_eo (void *data, Evas *e, Evas_Object *obj, void *event_info)
206 {
207         GstEvasImageSink *esink = data;
208         if (!esink) {
209                 return;
210         }
211         if (esink->oldbuf) {
212                 gst_buffer_unref (esink->oldbuf);
213                 esink->oldbuf = NULL;
214                 esink->eo = NULL;
215         }
216         ecore_pipe_del (esink->epipe);
217         esink->epipe = NULL;
218 }
219
220 static int
221 evas_image_sink_get_size_from_caps (GstCaps *caps, int *w, int *h)
222 {
223         gboolean r;
224         int width, height;
225         GstStructure *s;
226
227         if (!caps || !w || !h) {
228                 return -1;
229         }
230         s = gst_caps_get_structure (caps, 0);
231         if (!s) {
232                 return -1;
233         }
234
235         r = gst_structure_get_int (s, CAP_WIDTH, &width);
236         if (r == FALSE) {
237                 return -1;
238         }
239
240         r = gst_structure_get_int (s, CAP_HEIGHT, &height);
241         if (r == FALSE) {
242                 return -1;
243         }
244
245         *w = width;
246         *h = height;
247         return 0;
248 }
249
250 static gboolean
251 is_zerocopy_supported (Evas *e)
252 {
253         Eina_List *engines, *l;
254         int cur_id;
255         int id;
256         char *name;
257
258         if (!e) {
259                 return FALSE;
260         }
261
262         engines = evas_render_method_list ();
263         if (!engines) {
264                 return FALSE;
265         }
266
267         cur_id = evas_output_method_get (e);
268
269         EINA_LIST_FOREACH (engines, l, name) {
270                 id = evas_render_method_lookup (name);
271                 if (name && id == cur_id) {
272                         if (!strcmp (name, GL_X11_ENGINE)) {
273                                 return TRUE;
274                         }
275                         break;
276                 }
277         }
278         return FALSE;
279 }
280
281 static void
282 gst_evas_image_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
283 {
284         GstEvasImageSink *esink = GST_EVASIMAGESINK (object);
285         Evas_Object *eo;
286
287         switch (prop_id) {
288         case PROP_EVAS_OBJECT:
289                 eo = g_value_get_pointer (value);
290                 if (is_evas_image_object (eo)) {
291                         esink->eo = eo;
292                         evas_object_event_callback_add (esink->eo, EVAS_CALLBACK_DEL, evas_image_sink_cb_del_eo, esink);
293                         if (esink->w > 0 && esink->h >0) {
294                                 evas_object_image_size_set (esink->eo, esink->w, esink->h);
295                         }
296                         esink->gl_zerocopy = is_zerocopy_supported (evas_object_evas_get (eo));
297                         if (esink->gl_zerocopy) {
298                                 evas_object_image_content_hint_set (esink->eo, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
299                                 GST_DEBUG("Enable gl zerocopy");
300                         }
301                         if (!esink->epipe) {
302                                 esink->epipe = ecore_pipe_add (evas_image_sink_cb_pipe, esink);
303                         }
304                         if (!esink->epipe) {
305                                 GST_ERROR ("Cannot set evas-object property: pipe create failed");
306                         }
307                         GST_DEBUG("property set, Evas Object is set");
308                         evas_object_show(esink->eo);
309                         esink->object_show = TRUE;
310                         GST_INFO ("object show..");
311                 } else {
312                         GST_ERROR ("Cannot set evas-object property: value is not an evas image object");
313                 }
314                 break;
315
316         case PROP_EVAS_OBJECT_SHOW:
317                 esink->object_show = g_value_get_boolean (value);
318                 if( !is_evas_image_object(esink->eo) ) {
319                         GST_WARNING ("Cannot apply visible(show-object) property: cannot get an evas object\n");
320                         break;
321                 }
322                 if(!esink->object_show) {
323                         evas_object_hide(esink->eo);
324                         GST_INFO ("object hide..");
325                 } else {
326                         evas_object_show(esink->eo);
327                         GST_INFO ("object show..");
328                 }
329                 break;
330
331         default:
332                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
333                 break;
334         }
335 }
336
337 static void
338 gst_evas_image_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
339 {
340         GstEvasImageSink *esink = GST_EVASIMAGESINK (object);
341
342         switch (prop_id) {
343         case PROP_EVAS_OBJECT:
344                 g_value_set_pointer (value, esink->eo);
345                 break;
346         case PROP_EVAS_OBJECT_SHOW:
347                 g_value_set_boolean (value, esink->object_show);
348                 break;
349         default:
350                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
351                 break;
352         }
353 }
354
355 static gboolean
356 gst_evas_image_sink_set_caps (GstBaseSink * base_sink, GstCaps * caps)
357 {
358         int r;
359         int w, h;
360         GstEvasImageSink *esink = GST_EVASIMAGESINK (base_sink);
361
362         r = evas_image_sink_get_size_from_caps (caps, &w, &h);
363         if (!r) {
364                 if (esink->eo) {
365                         evas_object_image_size_set (esink->eo, w, h);
366                         GST_DEBUG ("evas_object_image_size_set: w(%d) h(%d)", w, h);
367                 }
368                 esink->w = w;
369                 esink->h = h;
370         }
371         return TRUE;
372 }
373
374 static GstFlowReturn
375 gst_evas_image_sink_show_frame (GstVideoSink * video_sink, GstBuffer * buf)
376 {
377         GstEvasImageSink *esink = GST_EVASIMAGESINK (video_sink);
378         Eina_Bool r;
379         if (esink->epipe && esink->object_show) {
380                 gst_buffer_ref (buf);
381                 r = ecore_pipe_write (esink->epipe, &buf, sizeof (GstBuffer *));
382                 if (r == EINA_FALSE)  {
383                         gst_buffer_unref (buf);
384                 }
385                 GST_DEBUG ("after ecore_pipe_write()");
386         }
387         return GST_FLOW_OK;
388 }
389
390 static gboolean
391 evas_image_sink_init (GstPlugin * evasimagesink)
392 {
393         GST_DEBUG_CATEGORY_INIT (gst_evas_image_sink_debug, "evasimagesink", 0, "Evas image object based videosink");
394
395         return gst_element_register (evasimagesink, "evasimagesink", GST_RANK_NONE, GST_TYPE_EVASIMAGESINK);
396 }
397
398 #ifndef PACKAGE
399 #define PACKAGE "gstevasimagesink-plugin-package"
400 #endif
401
402 GST_PLUGIN_DEFINE (
403         GST_VERSION_MAJOR,
404         GST_VERSION_MINOR,
405         "evasimagesink",
406         "Evas image object based videosink",
407         evas_image_sink_init,
408         VERSION,
409         "LGPL",
410         "Samsung Electronics Co",
411         "http://www.samsung.com/"
412 )