Initialize Tizen 2.3
[framework/multimedia/gst-plugins-ext0.10.git] / mobile / xvimagesrc / src / gstxvimagesrc.c
1 /*
2  * xvimagesrc
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyunil Park <hyunil46.park@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 * SECTION:element-xvimagesrc
25 *
26 * xvimagesrc captures frame buffer which includes the application data along with video layer data
27 * from the XServer and pushes the data to the downstream element.
28 *
29 *
30 * <refsect2>
31 * <title>Example launch line</title>
32 * |[
33 * gst-launch xvimagesrc ! "video/x-raw-yuv, width=720, height=1280, framerate=(fraction)30/1, format=(fourcc)ST12" ! fakesink
34 * ]| captures the frame buffer from the XServer and send the buffers to a fakesink.
35 * </refsect2>
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include "gstxvimagesrc.h"
43
44 /* headers for drm */
45 #include <sys/stat.h>
46 #include <sys/ioctl.h>
47 #include <fcntl.h>
48 #include <unistd.h>
49 #include <X11/Xmd.h>
50 #include <X11/Xlibint.h>
51 #include <dri2.h>
52 #include <drm.h>
53 #include <sys/time.h>
54 #include <sys/times.h>
55 #include <exynos_drm.h>
56
57 GST_DEBUG_CATEGORY_STATIC (xvimagesrc_debug);
58 #define GST_CAT_DEFAULT xvimagesrc_debug
59
60
61 #define GST_XV_IMAGE_SRC_CAPS                    \
62   "video/x-raw-rgb, "                            \
63   "bpp = (int) 32, "                             \
64   "depth = (int) 24, "                           \
65   "endianness = (int) BIG_ENDIAN, "              \
66   "red_mask = (int) 0xFF000000, "                \
67   "green_mask = (int) 0x00FF0000, "              \
68   "blue_mask = (int) 0x0000FF00, "               \
69   "width  = (int)  [ 16, 4096 ], "               \
70   "height = (int)  [ 16, 4096 ], "               \
71   "framerate = (fraction) [0/1, 2147483647/1];"  \
72   "video/x-raw-yuv,"                             \
73   "format = (fourcc) { SN12, ST12 }, "                 \
74   "width = (int) [ 1, 4096 ], "                  \
75   "height = (int) [ 1, 4096 ], "                 \
76   "framerate = (fraction) [0/1, 2147483647/1];"  \
77
78 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
79   GST_PAD_SRC,
80   GST_PAD_ALWAYS,
81   GST_STATIC_CAPS(GST_XV_IMAGE_SRC_CAPS)
82 );
83
84 enum
85 {
86   PROP_0
87 };
88
89 enum
90 {
91   VIDEO_TYPE_VIDEO_WITH_UI,
92   VIDEO_TYPE_VIDEO_ONLY,
93 };
94
95 enum
96 {
97   SIGNAL_VIDEO_WITH_UI = 0,
98   SIGNAL_VIDEO_ONLY,
99   SIGNAL_LAST
100 };
101 #define GEM_NAME_MAX                10
102
103 #define SCMN_CS_YUV420              1 /* Y:U:V 4:2:0 */
104 #define SCMN_CS_I420                SCMN_CS_YUV420 /* Y:U:V */
105 #define SCMN_CS_NV12                6
106 #define SCMN_CS_NV12_T64X32         11 /* 64x32 Tiled NV12 type */
107 #define SCMN_CS_UYVY                100
108 #define SCMN_CS_YUYV                101
109 #define SCMN_CS_YUY2                SCMN_CS_YUYV
110
111 /* max channel count *********************************************************/
112 #define SCMN_IMGB_MAX_PLANE         (4)
113
114 /* image buffer definition ***************************************************
115
116     +------------------------------------------+ ---
117     |                                          |  ^
118     |     a[], p[]                             |  |
119     |     +---------------------------+ ---    |  |
120     |     |                           |  ^     |  |
121     |     |<---------- w[] ---------->|  |     |  |
122     |     |                           |  |     |  |
123     |     |                           |        |
124     |     |                           |  h[]   |  e[]
125     |     |                           |        |
126     |     |                           |  |     |  |
127     |     |                           |  |     |  |
128     |     |                           |  v     |  |
129     |     +---------------------------+ ---    |  |
130     |                                          |  v
131     +------------------------------------------+ ---
132
133     |<----------------- s[] ------------------>|
134 */
135
136 typedef struct
137 {
138   /* width of each image plane */
139   int w[SCMN_IMGB_MAX_PLANE];
140   /* height of each image plane */
141   int h[SCMN_IMGB_MAX_PLANE];
142   /* stride of each image plane */
143   int s[SCMN_IMGB_MAX_PLANE];
144   /* elevation of each image plane */
145   int e[SCMN_IMGB_MAX_PLANE];
146   /* user space address of each image plane */
147   void *a[SCMN_IMGB_MAX_PLANE];
148   /* physical address of each image plane, if needs */
149   void *p[SCMN_IMGB_MAX_PLANE];
150   /* color space type of image */
151   int cs;
152   /* left postion, if needs */
153   int x;
154   /* top position, if needs */
155   int y;
156   /* to align memory */
157   int __dummy2;
158   /* arbitrary data */
159   int data[16];
160   /* dmabuf fd */
161   gint32 fd[SCMN_IMGB_MAX_PLANE];
162   /* flag for buffer share */
163   int buf_share_method;
164   /* Y plane size in case of ST12 */
165   int y_size;
166   /* UV plane size in case of ST12 */
167   int uv_size;
168
169   /* Tizen buffer object of each image plane */
170   void *bo[SCMN_IMGB_MAX_PLANE];
171
172   /* JPEG data */
173   void *jpeg_data;
174   /* JPEG size */
175   int jpeg_size;
176
177   /* tzmem buffer */
178   int tz_enable;
179 } SCMN_IMGB;
180
181 typedef struct
182 {
183   void  *address[GEM_NAME_MAX];
184   int buffer_size[GEM_NAME_MAX];
185   int name[GEM_NAME_MAX];
186   gint32 fd[GEM_NAME_MAX];
187   gint32 handle[GEM_NAME_MAX];
188 } GEM_MMAP;
189
190 typedef enum {
191  BUF_SHARE_METHOD_PADDR = 0,
192  BUF_SHARE_METHOD_FD
193 } buf_share_method_t;
194
195 typedef struct GstXvImageOutBuffer GstXvImageOutBuffer;
196
197 struct GstXvImageOutBuffer {
198   GstBuffer buffer;
199   int fd_name;
200   int YBuf;
201   GstXVImageSrc * xvimagesrc;
202 };
203
204
205
206 #define DEFAULT_USER_AGENT           "GStreamer xvimagesrc "
207
208 static guint gst_xv_image_src_signals[SIGNAL_LAST] = { 0 };
209
210 #define BASE_TIME 33000
211 #define LIMIT_TIME -33000
212 //#define COUNT_FRAMES
213 #ifdef COUNT_FRAMES
214 gchar old_time[10] = {0, };
215 #endif
216 static gboolean error_caught = FALSE;
217
218 #define HANDLE_OUTBUF_UNREF
219
220 #ifdef HANDLE_OUTBUF_UNREF
221 #define BUFFER_COND_WAIT_TIMEOUT            1000000
222 #define GST_TYPE_GST_XV_IMAGE_OUT_BUFFER               (gst_xv_image_out_buffer_get_type())
223 #define GST_IS_GST_XV_IMAGE_OUT_BUFFER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GST_XV_IMAGE_OUT_BUFFER))
224 static GstBufferClass *gst_xv_image_out_buffer_parent_class = NULL;
225 static void gst_xv_image_out_buffer_class_init(gpointer g_class, gpointer class_data);
226 static void gst_xv_image_out_buffer_finalize(GstXvImageOutBuffer *buffer);
227 static GstXvImageOutBuffer *gst_xv_image_out_buffer_new(GstXVImageSrc *src);
228 #endif
229 static GstStateChangeReturn gst_xv_image_src_change_state (GstElement * element, GstStateChange transition);
230 static void gst_xv_image_src_finalize (GObject * gobject);
231
232 static void gst_xv_image_src_set_property (GObject *object, guint prop_id, const GValue * value, GParamSpec * pspec);
233 static void gst_xv_image_src_get_property (GObject *object, guint prop_id, GValue * value, GParamSpec * pspec);
234 static GstFlowReturn gst_xv_image_src_create (GstPushSrc * psrc, GstBuffer ** outbuf);
235 static gboolean gst_xv_image_src_start (GstBaseSrc * bsrc);
236 static gboolean gst_xv_image_src_stop (GstBaseSrc * bsrc);
237 static gboolean gst_xv_image_src_get_size (GstBaseSrc * bsrc, guint64 * size);
238 static gboolean gst_xv_image_src_is_seekable (GstBaseSrc * bsrc);
239 static gboolean gst_xv_image_src_query (GstBaseSrc * bsrc, GstQuery * query);
240 static gboolean gst_xv_image_src_unlock (GstBaseSrc * bsrc);
241 static gboolean gst_xv_image_src_unlock_stop (GstBaseSrc * bsrc);
242 static gboolean gst_xv_image_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
243
244 static tbm_bufmgr bufmgr_get (Display *dpy, Pixmap pixmap);
245 static int port_get (GstXVImageSrc * src, unsigned int id);
246 static void pixmap_update (GstXVImageSrc * src,Display *dpy, tbm_bufmgr bufmgr, Pixmap pixmap,
247                int x, int y, int width, int height);
248 static Pixmap pixmap_create (GstXVImageSrc * src, Display *dpy, int width, int height);
249
250 static void* gst_xv_image_src_update_thread (void * asrc);
251 static gboolean xvimagesrc_thread_start(GstXVImageSrc *src);
252 static void drm_init(GstXVImageSrc *src);
253 static void drm_finalize(GstXVImageSrc *src);
254 static gint32 drm_convert_gem_to_fd(int * gemname_cnt, int drm_fd, unsigned int name,  void * data, void **virtual_address);
255 static void gst_xv_get_image_sleep(void *asrc, long duration);
256
257 static void
258 _do_init (GType type)
259 {
260   GST_DEBUG_CATEGORY_INIT (xvimagesrc_debug, "xvimagesrc", 0, "Xv image src");
261 }
262
263 GST_BOILERPLATE_FULL (GstXVImageSrc, gst_xv_image_src, GstPushSrc, GST_TYPE_PUSH_SRC, _do_init);
264
265 #ifdef HANDLE_OUTBUF_UNREF
266 static void gst_xv_image_out_buffer_class_init(gpointer g_class, gpointer class_data)
267 {
268   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
269   gst_xv_image_out_buffer_parent_class = g_type_class_peek_parent(g_class);
270   mini_object_class->finalize = (GstMiniObjectFinalizeFunction)gst_xv_image_out_buffer_finalize;
271 }
272
273 static GType gst_xv_image_out_buffer_get_type(void)
274 {
275   static GType _gst_gst_xv_image_out_buffer_type;
276
277   if (G_UNLIKELY(_gst_gst_xv_image_out_buffer_type == 0)) {
278     static const GTypeInfo gst_xv_image_out_buffer_info = {
279       sizeof (GstBufferClass),
280       NULL,
281       NULL,
282       gst_xv_image_out_buffer_class_init,
283       NULL,
284       NULL,
285       sizeof (GstXvImageOutBuffer),
286       0,
287       NULL,
288       NULL
289     };
290     _gst_gst_xv_image_out_buffer_type = g_type_register_static(GST_TYPE_BUFFER,
291                                                         "GstOmxOutBuffer",
292                                                         &gst_xv_image_out_buffer_info, 0);
293   }
294   return _gst_gst_xv_image_out_buffer_type;
295 }
296 #ifdef DEBUG_BUFFER
297  int value[5] ={0};
298  static int value_count =0;
299 #endif
300
301 static GstStateChangeReturn
302 gst_xv_image_src_change_state (GstElement * element, GstStateChange transition)
303 {
304   GstXVImageSrc *src = GST_XV_IMAGE_SRC (element);
305
306   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
307   switch (transition) {
308   case GST_STATE_CHANGE_NULL_TO_READY:
309     break;
310   case GST_STATE_CHANGE_READY_TO_PAUSED:
311     break;
312   case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
313     src->pause_cond_var = FALSE;
314     g_cond_signal(src->pause_cond);
315     break;
316   case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
317     src->pause_cond_var = TRUE;
318     break;
319   case GST_STATE_CHANGE_PAUSED_TO_READY:
320     src->thread_return = TRUE;
321     g_cond_signal(src->pause_cond);
322     g_cond_signal(src->queue_cond);
323     break;
324   case GST_STATE_CHANGE_READY_TO_NULL:
325     break;
326   default :
327     break;
328   }
329   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
330   return result;
331 }
332
333
334 static void gst_xv_image_out_buffer_finalize(GstXvImageOutBuffer *buffer)
335 {
336   Atom atom_retbuf = 0;
337   g_mutex_lock (buffer->xvimagesrc->dpy_lock);
338   atom_retbuf = XInternAtom (buffer->xvimagesrc->dpy, "_USER_WM_PORT_ATTRIBUTE_RETURN_BUFFER", False);
339   XvSetPortAttribute (buffer->xvimagesrc->dpy, buffer->xvimagesrc->p, atom_retbuf, buffer->YBuf);  //data->YBuf is gemname, refer to drm_convert_gem_to_fd
340   g_mutex_unlock (buffer->xvimagesrc->dpy_lock);
341   g_cond_signal(buffer->xvimagesrc->buffer_cond);
342   GST_INFO(" xvimagesrc = %p, gem_name =%d, fd_name =%d", buffer->xvimagesrc, buffer->YBuf, buffer->fd_name);
343 #ifdef DEBUG_BUFFER
344  int i = 0;
345  for(i=0 ; i<5; i++){
346    if (value[i] == buffer->YBuf) {
347      value[i]=0;
348      GST_ERROR("value[%d]=%d", i, value[i]);
349    }
350  }
351 #endif
352   return;
353 }
354
355
356 static GstXvImageOutBuffer *gst_xv_image_out_buffer_new(GstXVImageSrc *src)
357 {
358   GstXvImageOutBuffer *newbuf = NULL;
359   GST_LOG("gst_omx_out_buffer_new");
360
361   newbuf = (GstXvImageOutBuffer *)gst_mini_object_new(GST_TYPE_GST_XV_IMAGE_OUT_BUFFER);
362   if(!newbuf)
363   {
364     GST_ERROR("gst_omx_out_buffer_new out of memory");
365     return NULL;
366   }
367   GST_LOG("creating buffer : %p", newbuf);
368   newbuf->xvimagesrc = gst_object_ref(GST_OBJECT(src));
369   newbuf->fd_name = 0;
370   newbuf->YBuf =0;
371   return newbuf;
372 }
373 #endif
374
375 static void
376 gst_xv_image_src_base_init (gpointer g_class)
377 {
378   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
379   gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&srctemplate));
380   gst_element_class_set_details_simple (element_class, "XServer Display FB video source",
381     "Source/video",
382     "Receive frame buffer data from XServer and passes to next element",
383     "");
384 }
385
386 static void
387 gst_xv_image_src_class_init (GstXVImageSrcClass * klass)
388 {
389   GObjectClass *gobject_class;
390   GstBaseSrcClass *gstbasesrc_class;
391   GstPushSrcClass *gstpushsrc_class;
392   GstElementClass *gstelement_class;
393   gobject_class = G_OBJECT_CLASS (klass);
394   gstelement_class = (GstElementClass *) klass;
395   gstbasesrc_class = (GstBaseSrcClass *) klass;
396   gstpushsrc_class = (GstPushSrcClass *) klass;
397   gobject_class->set_property = gst_xv_image_src_set_property;
398   gobject_class->get_property = gst_xv_image_src_get_property;
399   gobject_class->finalize = gst_xv_image_src_finalize;
400
401   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_xv_image_src_start);
402   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_xv_image_src_stop);
403   gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_xv_image_src_unlock);
404   gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_xv_image_src_unlock_stop);
405   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_xv_image_src_get_size);
406   gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_xv_image_src_is_seekable);
407   gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_xv_image_src_query);
408   gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_xv_image_src_setcaps);
409   gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_xv_image_src_create);
410   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_xv_image_src_change_state);
411
412   gst_xv_image_src_signals[SIGNAL_VIDEO_WITH_UI] =
413      g_signal_new ("video-with-ui", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
414      G_STRUCT_OFFSET (GstXVImageSrcClass, video_with_ui), NULL, NULL,
415      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
416
417   gst_xv_image_src_signals[SIGNAL_VIDEO_ONLY] =
418      g_signal_new ("video-only", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
419      G_STRUCT_OFFSET (GstXVImageSrcClass, video_only), NULL, NULL,
420      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
421
422 }
423
424 static gboolean gst_xv_image_src_get_frame_size(int fourcc, int width, int height, unsigned int *outsize)
425 {
426   switch (fourcc) {
427 /* case GST_MAKE_FOURCC('I','4','2','0'):       // V4L2_PIX_FMT_YUV420
428     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
429     *outsize += 2 * ((GST_ROUND_UP_8 (width) / 2) * (GST_ROUND_UP_2 (height) / 2));
430     break;*/
431   case GST_MAKE_FOURCC('S','N','1','2'):        // V4L2_PIX_FMT_NV12 non-linear
432      GST_INFO("SN12");
433   case GST_MAKE_FOURCC('S','T','1','2'):        // V4L2_PIX_FMT_NV12 tiled non-linear
434      GST_INFO("ST12");
435     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
436     *outsize += (GST_ROUND_UP_4 (width) * height) / 2;
437     break;
438   case GST_MAKE_FOURCC('R','G','B','4'):
439     /* jpeg size can't be calculated here. */
440     *outsize = width * height * 4;
441     break;
442   default:
443     /* unkown format!! */
444     *outsize = 0;
445     return FALSE;
446   }
447   return TRUE;
448 }
449
450 static gboolean
451 gst_xv_image_src_parse_caps (const GstCaps * caps, guint32 *fourcc,
452   gint * width, gint * height, gint * rate_numerator, gint * rate_denominator, unsigned int *framesize)
453 {
454   const GstStructure *structure;
455   GstPadLinkReturn ret = TRUE;
456   const GValue *framerate;
457   const char *media_type = NULL;
458   GST_DEBUG ("parsing caps");
459   if (gst_caps_get_size (caps) < 1) return FALSE;
460   GST_INFO("xvimagesrc src caps:%"GST_PTR_FORMAT, caps);
461   structure = gst_caps_get_structure (caps, 0);
462   ret = gst_structure_get_int (structure, "width", width);
463   if(!ret) {
464     GST_ERROR ("xvimagesrc width not specified in caps");
465     goto error;
466   }
467   ret = gst_structure_get_int (structure, "height", height);
468   if(!ret) {
469     GST_ERROR ("xvimagesrc height not specified in caps");
470     goto error;
471   }
472   media_type = gst_structure_get_name (structure);
473   if(media_type == NULL) {
474     GST_ERROR ("xvimagesrc media type not specified in caps");
475     goto error;
476   }
477   framerate = gst_structure_get_value (structure, "framerate");
478   if (framerate) {
479     *rate_numerator = gst_value_get_fraction_numerator (framerate);
480     *rate_denominator = gst_value_get_fraction_denominator (framerate);
481   } else {
482     GST_ERROR ("xvimagesrc frametype not specified in caps");
483     goto error;
484   }
485   if (g_strcmp0 (media_type, "video/x-raw-rgb") == 0) {
486     gst_xv_image_src_get_frame_size(FOURCC_RGB32, *width, *height, framesize);
487     *fourcc = FOURCC_RGB32;
488     GST_DEBUG ("Caps set to RGB32");
489   } else if(g_strcmp0 (media_type, "video/x-raw-yuv") == 0) {
490
491     GST_INFO ("media_type is video/x-raw-yuv");
492     guint32 format = FOURCC_SN12;
493     ret = gst_structure_get_fourcc (structure, "format", &format);
494     if (!ret) GST_DEBUG ("xvimagesrc format not specified in caps, SN12 selected as default");
495     ret = gst_xv_image_src_get_frame_size(format, *width, *height, framesize);
496     if(!ret) {
497       GST_ERROR ("xvimagesrc unsupported format type specified in caps");
498       goto error;
499     }
500     *fourcc = format;
501   }
502   return TRUE;
503 /* ERRORS */
504 error:
505     return FALSE;
506 }
507
508 static gboolean gst_xv_image_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
509 {
510   gboolean res = TRUE;
511   gint width, height, rate_denominator, rate_numerator;
512   GstXVImageSrc *src;
513   src = GST_XV_IMAGE_SRC (bsrc);
514   res = gst_xv_image_src_parse_caps (caps, &src->format_id, &width, &height,
515     &rate_numerator, &rate_denominator, &src->framesize);
516   if (res) {
517     /* looks ok here */
518     src->width = width;
519     src->height = height;
520     src->rate_numerator = rate_numerator;
521     src->rate_denominator = rate_denominator;
522     GST_DEBUG_OBJECT (src, "size %dx%d, %d/%d fps",
523       src->width, src->height,
524       src->rate_numerator, src->rate_denominator);
525   }
526   xvimagesrc_thread_start(src);
527   return res;
528 }
529 static void
530 gst_xv_image_src_reset (GstXVImageSrc * src)
531 {
532 }
533
534 static void
535 gst_xv_image_src_init (GstXVImageSrc * src, GstXVImageSrcClass * g_class)
536 {
537   src->format_id = 0;
538   src->running_time = GST_CLOCK_TIME_NONE;
539   src->frame_duration = GST_CLOCK_TIME_NONE;
540   src->virtual = NULL;
541   src->bo = NULL;
542   src->dri2_buffers = NULL;
543   src->queue_lock = g_mutex_new ();
544   src->queue = g_queue_new ();
545   src->queue_cond = g_cond_new ();
546   src->cond_lock = g_mutex_new ();
547   src->buffer_cond = g_cond_new ();
548   src->buffer_cond_lock = g_mutex_new ();
549   src->pause_cond = g_cond_new ();
550   src->pause_cond_lock = g_mutex_new ();
551   src->dpy_lock = g_mutex_new ();
552   src->pause_cond_var = FALSE;
553   src->drm_fd = -1;
554   src->current_data_type = VIDEO_TYPE_VIDEO_WITH_UI;
555   src->new_data_type = VIDEO_TYPE_VIDEO_WITH_UI;
556   src->get_image_overtime = 0;
557   src->get_image_overtime_cnt = 0;
558   src->gemname_cnt = 0;
559   src->tz_enable = 0;
560   drm_init(src);
561   gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
562 }
563
564 static void
565 gst_xv_image_src_finalize (GObject * gobject)
566 {
567   GstXVImageSrc *src = GST_XV_IMAGE_SRC (gobject);
568   GST_DEBUG_OBJECT (src, "finalize");
569   g_mutex_free (src->queue_lock);
570   drm_finalize(src);
571   G_OBJECT_CLASS (parent_class)->finalize (gobject);
572 }
573 static void drm_init(GstXVImageSrc *src)
574 {
575   Display *dpy;
576   int eventBase, errorBase;
577   int dri2Major, dri2Minor;
578   char *driverName, *deviceName;
579   struct drm_auth auth_arg = {0};
580
581   src->drm_fd = -1;
582   dpy = XOpenDisplay(0);
583
584   /* DRI2 */
585   if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
586     GST_ERROR("DRI2QueryExtension !!");
587     return;
588   }
589   if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
590    GST_ERROR("DRI2QueryVersion !!");
591    return;
592   }
593   if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
594     GST_ERROR("DRI2Connect !!");
595     return;
596   }
597   GST_INFO("Open drm device : %s", deviceName);
598
599   /* get the drm_fd though opening the deviceName */
600   src->drm_fd = open(deviceName, O_RDWR);
601   if (src->drm_fd < 0) {
602     GST_ERROR("cannot open drm device (%s)", deviceName);
603     return;
604   }
605
606   /* get magic from drm to authentication */
607   if (ioctl(src->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
608     GST_ERROR("cannot get drm auth magic");
609     close(src->drm_fd);
610     src->drm_fd = -1;
611     return;
612   }
613   if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
614     GST_ERROR("cannot get drm authentication from X");
615     close(src->drm_fd);
616     src->drm_fd = -1;
617     return;
618   }
619 }
620 static void drm_finalize(GstXVImageSrc *src)
621 {
622   if (src->drm_fd >= 0) {
623     close(src->drm_fd);
624     src->drm_fd = -1;
625   }
626 }
627 static gint32 drm_convert_gem_to_fd(int *gemname_cnt, int drm_fd, unsigned int name, void  *data, void **virtual_address)
628 {
629   g_return_val_if_fail((data != NULL),0);
630   int count=0;
631   gint32 fd = 0;
632   count = *gemname_cnt;
633   GST_DEBUG("gamname_cnt = %d", count);
634   GST_DEBUG("name = %u", name);
635
636
637   GEM_MMAP *xv_gem_mmap = NULL;
638   xv_gem_mmap = (GEM_MMAP *) data;
639   if(count >=GEM_NAME_MAX)
640     goto PASS;
641
642   if (count < GEM_NAME_MAX ) {
643     int i =0;
644     for ( i =0 ; i < GEM_NAME_MAX ; i++) {
645       if (name == xv_gem_mmap->name[i])
646         goto PASS;
647     }
648
649     struct drm_prime_handle prime;
650     struct drm_gem_open gem_open;
651     struct drm_exynos_gem_mmap gem_mmap; //for virtual address
652
653     memset (&gem_open, 0, sizeof (struct drm_gem_open));
654     gem_open.name = name;
655     if (ioctl(drm_fd, DRM_IOCTL_GEM_OPEN, &gem_open)) {
656       GST_ERROR("Gem Open failed");
657       return 0;
658     }
659     memset (&prime, 0, sizeof (struct drm_prime_handle));
660     prime.handle = gem_open.handle;
661     prime.flags = DRM_CLOEXEC;
662     /*get gem_open handle*/
663     xv_gem_mmap->handle[count] = gem_open.handle;
664     GST_DEBUG("gem_open.handle =%d, xv_gem_mmap->handle[count]=%d", gem_open.handle, xv_gem_mmap->handle[count]);
665     /*get virtual address */
666     /*set name*/
667     xv_gem_mmap->name[count] = name;
668     memset (&gem_mmap, 0, sizeof (struct drm_exynos_gem_mmap));
669     gem_mmap.handle = prime.handle;
670     gem_mmap.size = gem_open.size;
671     /*set size*/
672     xv_gem_mmap->buffer_size[count] = gem_mmap.size;
673     if (drmIoctl(drm_fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &gem_mmap) !=0) {
674       GST_ERROR("Gem mmap failed [handle %d, size %d]", gem_mmap.handle, gem_mmap.size);
675       return 0;
676     }
677     /*set virtual address*/
678     xv_gem_mmap->address[count] = (void *)(gem_mmap.mapped);
679     GST_DEBUG ("%d - Virtual address[%d] = %p size=%d ", name, count, xv_gem_mmap->address[count],  xv_gem_mmap->buffer_size[count] );
680
681     /*get fd*/
682     if (ioctl(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime) < 0) {
683       GST_ERROR("Gem Handle to Fd failed");
684       return 0;
685     }
686     xv_gem_mmap->fd[count] = prime.fd;
687     GST_DEBUG("fd = %d", xv_gem_mmap->fd[count]);
688   }
689
690   if (count < GEM_NAME_MAX) {
691     count ++;
692     *gemname_cnt = count;
693   }
694
695 PASS:
696
697   if (name == xv_gem_mmap->name[0]) {
698     *virtual_address = xv_gem_mmap->address[0];
699     fd = xv_gem_mmap->fd[0];
700   } else if (name == xv_gem_mmap->name[1]) {
701     *virtual_address = xv_gem_mmap->address[1];
702      fd = xv_gem_mmap->fd[1];
703   } else if (name == xv_gem_mmap->name[2]) {
704     *virtual_address = xv_gem_mmap->address[2];
705      fd = xv_gem_mmap->fd[2];
706   } else if ( name == xv_gem_mmap->name[3]) {
707     *virtual_address = xv_gem_mmap->address[3];
708      fd = xv_gem_mmap->fd[3];
709   } else if (name == xv_gem_mmap->name[4]) {
710     *virtual_address = xv_gem_mmap->address[4];
711      fd = xv_gem_mmap->fd[4];
712   } else if ( name == xv_gem_mmap->name[5]) {
713     *virtual_address = xv_gem_mmap->address[5];
714      fd = xv_gem_mmap->fd[5];
715   } else if (name == xv_gem_mmap->name[6]) {
716     *virtual_address = xv_gem_mmap->address[6];
717      fd = xv_gem_mmap->fd[6];
718   } else if (name == xv_gem_mmap->name[7]) {
719     *virtual_address = xv_gem_mmap->address[7];
720      fd = xv_gem_mmap->fd[7];
721   } else if ( name == xv_gem_mmap->name[8]) {
722     *virtual_address = xv_gem_mmap->address[8];
723      fd = xv_gem_mmap->fd[8];
724   } else if (name == xv_gem_mmap->name[9]) {
725     *virtual_address = xv_gem_mmap->address[9];
726      fd = xv_gem_mmap->fd[9];
727   }
728
729   GST_DEBUG("virtual_address = %p  fd = %d", *virtual_address, fd);
730   return fd;
731 }
732 static void
733 gst_xv_image_src_set_property (GObject * object, guint prop_id,
734     const GValue * value, GParamSpec * pspec)
735 {
736   GstXVImageSrc *src = GST_XV_IMAGE_SRC (object);
737   GST_INFO ("set property function %x", src);
738   switch (prop_id) {
739     default:
740       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
741     break;
742   }
743   return;
744 }
745
746 static void
747 gst_xv_image_src_get_property (GObject * object, guint prop_id,
748     GValue * value, GParamSpec * pspec)
749 {
750   GstXVImageSrc *src = GST_XV_IMAGE_SRC (object);
751   GST_INFO ("get property function %x", src);
752   switch (prop_id) {
753     default:
754       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
755     break;
756   }
757 }
758
759 static inline GstClockTime xvimagesrc_clock (GstXVImageSrc *src)
760 {
761   struct timeval tv;
762   gettimeofday (&tv, NULL);
763   if(!src->base_time) {
764     src->base_time = GST_TIMEVAL_TO_TIME(tv);
765   }
766   return (GstClockTime)(GST_TIMEVAL_TO_TIME(tv) - src->base_time);
767 }
768
769 static gboolean gst_xv_image_src_get_timeinfo(GstXVImageSrc *src, GstBuffer *buffer)
770 {
771   int fps_nu = 0;
772   int fps_de = 0;
773   GstClockTime timestamp = GST_CLOCK_TIME_NONE;
774   GstClockTime duration = GST_CLOCK_TIME_NONE;
775   GstClock *clock;
776   if (!src || !buffer) {
777     GST_WARNING("Invalid pointer [handle:%p, buffer:%p]", src, buffer);
778     return FALSE;
779   }
780   clock = gst_element_get_clock (GST_ELEMENT (src));
781   if (clock) {
782     timestamp = gst_clock_get_time (clock);
783     timestamp -= gst_element_get_base_time (GST_ELEMENT (src));
784     gst_object_unref (clock);
785   } else {
786     /* not an error not to have a clock */
787     timestamp = GST_CLOCK_TIME_NONE;
788   }
789
790   //timestamp = xvimagesrc_clock(src);
791   /* if we have a framerate adjust timestamp for frame latency */
792   if ((int)((float)src->rate_numerator / (float)src->rate_denominator) <= 0) {
793     /*if fps is zero, auto fps mode*/
794     fps_nu = 0;
795     fps_de = 1;
796   } else {
797     fps_nu = 1;
798     fps_de = (int)((float)src->rate_numerator / (float)src->rate_denominator);
799   }
800   if (fps_nu > 0 && fps_de > 0) {
801     GstClockTime latency;
802     latency = gst_util_uint64_scale_int(GST_SECOND, fps_nu, fps_de);
803     duration = latency;
804   }
805   GST_BUFFER_TIMESTAMP(buffer) = timestamp;
806   GST_BUFFER_DURATION(buffer) = duration;
807   return TRUE;
808 }
809 #ifdef COUNT_FRAMES
810 static  int fps = 0;
811
812 static gchar *get_current_system_time()
813 {
814         gchar target[10]={0,};
815         time_t t;
816         struct tm tm;
817
818         t = time(NULL);
819         tzset();
820         /*localtimer_r : available since libc 5.2.5*/
821         if(localtime_r(&t, &tm) == NULL) {
822                 return NULL;
823         }
824         snprintf(target, sizeof(target), "%02i:%02i:%02i", tm.tm_hour, tm.tm_min, tm.tm_sec);
825         return g_strdup(target);
826 }
827 #endif
828 static void gst_xv_get_image_sleep(void *asrc, long duration)
829 {
830     GST_INFO("end_time duration=%d", duration);
831     if (duration < 0) return;
832     GstXVImageSrc *src = (GstXVImageSrc *)asrc;
833     g_return_if_fail(src != NULL);
834     long sleep_time = 0;
835     sleep_time = (long)BASE_TIME - duration;
836     if (sleep_time < 0) {
837         src->get_image_overtime_cnt ++;
838         src->get_image_overtime += sleep_time;
839         if (src->get_image_overtime_cnt > 2)
840           src->get_image_overtime = 0;
841         if (src->get_image_overtime <= (long)LIMIT_TIME)
842           src->get_image_overtime = 0;
843     } else if (sleep_time > 0) {
844        src->get_image_overtime_cnt = 0;
845         sleep_time = sleep_time + src->get_image_overtime;
846         src->get_image_overtime = (sleep_time < 0) ? sleep_time : 0;
847         if (sleep_time >0) {
848            GST_INFO("end_time : sleep_time = %d", sleep_time);
849           usleep(sleep_time);
850         }
851     }
852 }
853 static GstFlowReturn
854 gst_xv_image_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
855 {
856   GST_INFO("gst_xv_image_src_create");
857   GstXVImageSrc *src;
858   GstXvImageOutBuffer *outbuf = NULL;
859   src = GST_XV_IMAGE_SRC (psrc);
860   g_mutex_lock (src->queue_lock);
861   if(g_queue_is_empty (src->queue)) {
862     GST_INFO("g_queue_is_empty");
863     g_mutex_unlock (src->queue_lock);
864     GST_INFO("g_cond_wait");
865     g_cond_wait(src->queue_cond, src->cond_lock);
866     if(src->pause_cond_var) return GST_FLOW_WRONG_STATE;
867     g_mutex_lock (src->queue_lock);
868     outbuf = (GstXvImageOutBuffer *)g_queue_pop_head(src->queue);
869     GST_INFO("g_queue_pop_head");
870     g_mutex_unlock (src->queue_lock);
871   }
872   else {
873     GstXvImageOutBuffer *tempbuf = NULL;
874     while((tempbuf = (GstXvImageOutBuffer*)g_queue_pop_head(src->queue)) != NULL)
875     {
876       outbuf = tempbuf;    // To reduce latency, skipping the old frames and submitting only latest frames
877       g_mutex_unlock (src->queue_lock);
878     }
879     GST_INFO("g_queue_pop_head end");
880   }
881   if(outbuf == NULL) return GST_FLOW_ERROR;
882   GST_INFO("gem_name=%d, fd_name=%d, Time stamp of the buffer is %"GST_TIME_FORMAT, outbuf->YBuf, outbuf->fd_name, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(outbuf)));
883   *buffer = outbuf;
884 #ifdef COUNT_FRAMES
885     gchar *current_time = NULL;
886     current_time =      get_current_system_time();
887     if (strncmp(current_time, old_time, 10) == 0) {
888         fps ++;
889         strncpy(old_time, current_time, 10);
890     } else {
891        g_printf("xvimagesrc %s - fps : %d\n", old_time, fps);
892        fps = 1;
893         strncpy(old_time, current_time, 10);
894     }
895 #endif
896   GST_INFO("return ok");
897   return GST_FLOW_OK;
898 }
899
900 static gboolean xvimagesrc_thread_start(GstXVImageSrc *src)
901 {
902   GError *error;
903   if(!src->updates_thread) src->updates_thread = g_thread_create ((GThreadFunc) gst_xv_image_src_update_thread, src, TRUE, &error);
904   else GST_LOG_OBJECT (src, "The thread function already running");
905   return TRUE;
906 }
907
908 static gboolean
909 gst_xv_image_src_start (GstBaseSrc * bsrc)
910 {
911   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
912   if(src->format_id) xvimagesrc_thread_start(src);
913   return TRUE;
914 }
915
916 gboolean signal_emit_func(void *asrc)
917 {
918     GstXVImageSrc *src = (GstXVImageSrc *)asrc;
919     if (src->current_data_type == VIDEO_TYPE_VIDEO_ONLY) {
920       g_signal_emit (src, gst_xv_image_src_signals[SIGNAL_VIDEO_ONLY] , 0, NULL);
921    } else if (src->current_data_type == VIDEO_TYPE_VIDEO_WITH_UI) {
922      g_signal_emit (src, gst_xv_image_src_signals[SIGNAL_VIDEO_WITH_UI] , 0, NULL);
923    }
924     return FALSE;
925 }
926
927 static int
928 gst_xvimagesrc_handle_xerror (Display * display, XErrorEvent * xevent)
929 {
930   char error_msg[1024];
931
932   XGetErrorText (display, xevent->error_code, error_msg, 1024);
933   GST_DEBUG ("XError. error: %s", error_msg);
934   error_caught = TRUE;
935   return 0;
936 }
937
938 //static gboolean first_frame=TRUE;
939 static void* gst_xv_image_src_update_thread (void * asrc)
940 {
941   GstXVImageSrc *src = (GstXVImageSrc *)asrc;
942   Atom atom_data_type = 0;
943   Atom atom_secure = 0, atom_capture=0;
944   Atom atom_fps = 0;
945   g_return_val_if_fail((src != NULL),NULL);
946
947   struct drm_gem_close gem_close;
948   int i=0;
949   GEM_MMAP *xv_gem_mmap = NULL;
950   xv_gem_mmap = (GEM_MMAP *)malloc(sizeof(GEM_MMAP));
951   g_return_val_if_fail((xv_gem_mmap != NULL),NULL);
952
953   memset(xv_gem_mmap, 0, sizeof(GEM_MMAP));
954
955   GST_LOG_OBJECT (src, "The thread function start");
956   {
957     int damage_err_base = 0;
958     Atom atom_format = 0;
959     src->dpy = XOpenDisplay (NULL);
960     src->p = port_get (src, src->format_id);
961     if (src->p < 0) goto finish;
962     /*src->width and src->height is set by caps info */
963     GST_DEBUG (" width and height of caps : %dx%d ", src->width, src->height);
964     if (src->width == 0 || src->height == 0) goto finish;
965     GST_DEBUG ("gst_xv_image_src_update_thread pixmap_create !!");
966     src->pixmap = pixmap_create (src, src->dpy, src->width, src->height);
967     GST_DEBUG ("gst_xv_image_src_update_thread pixmap_create !!");
968     src->gc = XCreateGC (src->dpy, src->pixmap, 0, 0);
969     GST_DEBUG ("gst_xv_image_src_update_thread XCreateGC !!");
970     src->bufmgr = bufmgr_get (src->dpy, src->pixmap);
971     if (!src->bufmgr) goto finish;
972     GST_DEBUG ("gst_xv_image_src_update_thread bufmgr_get !!");
973     if (!XDamageQueryExtension(src->dpy, &src->damage_base, &damage_err_base)) goto finish;
974     GST_DEBUG ("gst_xv_image_src_update_thread XDamageQueryExtension !!");
975     src->damage = XDamageCreate (src->dpy, src->pixmap, XDamageReportNonEmpty);
976     atom_format = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_FORMAT", False);
977     atom_capture = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
978     atom_secure = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_SECURE", False);
979     src->atom_stream_off = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False);
980     XvSetPortAttribute (src->dpy, src->p, atom_format, src->format_id);
981
982     /*get data type*/
983     atom_data_type = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE", False);
984     XvSelectPortNotify (src->dpy, src->p, 1);
985     XvGetPortAttribute (src->dpy, src->p, atom_data_type, &(src->new_data_type));
986 #if 0
987     /*set Xorg write-back hz*/
988     atom_fps = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_FPS", False);
989     GST_DEBUG("frame rate of caps %d", src->rate_numerator);
990     XvSetPortAttribute (src->dpy, src->p, atom_fps, src->rate_numerator);
991     GST_DEBUG ("gst_xv_image_src_update_thread XvSetPortAttribute !!");
992 #endif
993   }
994
995   struct timeval start_time, end_time;
996   long duration;
997   long starttime, endtime;
998   GTimeVal timeout;
999   XEvent ev;
1000   int eventcount = 0;
1001   void *virtual_address = NULL;
1002   int (*handler) (Display *, XErrorEvent *);
1003   GstXvImageOutBuffer *outbuf = NULL;
1004
1005   while(!src->thread_return) {
1006     if(src->pause_cond_var == TRUE) {
1007       g_cond_wait(src->pause_cond,src->pause_cond_lock);
1008     }
1009     duration = 0;
1010     starttime =0;
1011     endtime = 0;
1012     start_time.tv_sec = 0;
1013     start_time.tv_usec = 0;
1014     end_time.tv_sec      = 0;
1015     end_time.tv_usec = 0;
1016     gettimeofday(&start_time, NULL);
1017
1018     eventcount = 0;
1019     virtual_address = NULL;
1020     duration = 0;
1021     outbuf = NULL;
1022     g_mutex_lock (src->dpy_lock);
1023     XSync(src->dpy, 0);
1024     GST_INFO ("gst_xv_image_src_update_thread XSync@@ !!");
1025     g_mutex_unlock (src->dpy_lock);
1026     error_caught = FALSE;
1027     GST_DEBUG ("gst_xv_image_src_update_thread XSetErrorHandler in !!");
1028     handler = XSetErrorHandler (gst_xvimagesrc_handle_xerror);
1029     GST_INFO ("gst_xv_image_src_update_thread XSetErrorHandler !!");
1030     GST_INFO ("gst_xv_image_src_update_thread XvPutStill in !!");
1031     g_mutex_lock (src->dpy_lock);
1032     XvPutStill (src->dpy, src->p, src->pixmap, src->gc, 0, 0, src->width, src->height, 0, 0, src->width, src->height);
1033     GST_INFO ("gst_xv_image_src_update_thread XvPutStill !!");
1034     XSync (src->dpy, 0);
1035     g_mutex_unlock (src->dpy_lock);
1036     if (error_caught) {
1037       GST_ERROR("gst_xv_image_src_update_thread error_caught is TRUE, X is out of buffers");
1038             error_caught = FALSE;
1039             XSetErrorHandler(handler);
1040       g_get_current_time(&timeout);
1041       g_time_val_add(&timeout, BUFFER_COND_WAIT_TIMEOUT);
1042       if(!g_cond_timed_wait(src->buffer_cond, src->buffer_cond_lock, &timeout)) {
1043               GST_ERROR("skip wating");
1044       } else {
1045           GST_ERROR("Signal received");
1046       }
1047             continue;
1048     }
1049     /*reset error handler*/
1050     error_caught = FALSE;
1051     XSetErrorHandler(handler);
1052
1053     GST_INFO ("gst_xv_image_src_update_thread XSync !!");
1054 next_event:
1055     g_mutex_lock (src->dpy_lock);
1056     GST_INFO("XNextEvent in");
1057     XNextEvent (src->dpy, &ev); /* wating for x event */
1058     GST_INFO("XNextEvent out");
1059     g_mutex_unlock (src->dpy_lock);
1060     GST_INFO ("gst_xv_image_src_update_thread XNextEvent !!");
1061     if (ev.type == (src->damage_base + XDamageNotify)) {
1062       XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
1063       GST_INFO ("gst_xv_image_src_update_thread XDamageNotifyEvent");
1064       g_mutex_lock (src->dpy_lock);
1065       if (damage_ev->drawable == src->pixmap) {
1066         pixmap_update (src, src->dpy, src->bufmgr, src->pixmap,
1067         damage_ev->area.x,
1068         damage_ev->area.y,
1069         damage_ev->area.width,
1070         damage_ev->area.height);
1071               GST_INFO("gst_xv_image_src_update_thread pixmap_update");
1072       }
1073       XDamageSubtract (src->dpy, src->damage, None, None );
1074       g_mutex_unlock (src->dpy_lock);
1075       GST_INFO ("gst_xv_image_src_update_thread XDamageSubtract");
1076     }
1077     else if (ev.type == (src->evt_base + XvPortNotify)) {
1078       XvPortNotifyEvent *notify_ev = (XvPortNotifyEvent*)&ev;
1079       if (notify_ev->attribute == atom_secure) {
1080           GST_WARNING ("secure attr changed : %s \n", ((int)notify_ev->value)?"Secure":"Normal");
1081            src->tz_enable = (int)notify_ev->value;
1082            GST_ERROR("src->tz_enable = %d", src->tz_enable);
1083       }
1084       else if (notify_ev->attribute == atom_data_type) {
1085         /* got a port notify, data_type */
1086         src->new_data_type = (int)notify_ev->value;
1087         if (src->current_data_type != src->new_data_type) {
1088           src->current_data_type = src->new_data_type;
1089           GST_WARNING("current_data_type : %s \n", (src->current_data_type)?"Video":"UI+Video");
1090           g_timeout_add(1, signal_emit_func, src);
1091         }
1092       }
1093       goto next_event;
1094     }
1095
1096     if(!src->virtual) continue;
1097     if(src->format_id == FOURCC_RGB32) {
1098       outbuf = gst_buffer_new_and_alloc (src->framesize);
1099       gst_buffer_set_caps (outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src)));
1100       memcpy(GST_BUFFER_DATA (outbuf), src->virtual, src->framesize);
1101     } else if (src->format_id == FOURCC_SN12) {
1102       XV_PUTSTILL_DATA_PTR data = (XV_PUTSTILL_DATA_PTR)src->virtual;
1103       int error = XV_PUTSTILL_VALIDATE_DATA (data);
1104       outbuf = gst_xv_image_out_buffer_new(src);
1105       if(!outbuf)
1106       {
1107         GST_ERROR("Out of memory");
1108         continue;
1109       }
1110       gst_buffer_set_caps (outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src)));
1111       if (error == XV_HEADER_ERROR)
1112         GST_ERROR ("XV_HEADER_ERROR\n");
1113       else if (error == XV_VERSION_MISMATCH)
1114         GST_ERROR ("XV_VERSION_MISMATCH\n");
1115       else
1116       {
1117         SCMN_IMGB *psimgb = NULL;
1118         psimgb = (SCMN_IMGB *)malloc(sizeof(SCMN_IMGB));
1119         if (psimgb == NULL) {
1120           GST_ERROR_OBJECT(src, "failed to alloc SCMN_IMGB");
1121           return NULL;
1122         }
1123         memset(psimgb, 0x00, sizeof(SCMN_IMGB));
1124          if (data->BufType == XV_BUF_TYPE_LEGACY) {
1125            psimgb->p[0] = (void *)data->YBuf;
1126           psimgb->p[1] = (void *)data->CbBuf;
1127            psimgb->buf_share_method = BUF_SHARE_METHOD_PADDR;
1128            psimgb->a[0] = NULL;
1129           psimgb->a[1] = NULL;
1130          } else if (data->BufType == XV_BUF_TYPE_DMABUF) {
1131           psimgb->fd[0] = drm_convert_gem_to_fd(&src->gemname_cnt, src->drm_fd, (void *)data->YBuf, xv_gem_mmap, &virtual_address);
1132      if(!virtual_address) continue;
1133            psimgb->a[0] = virtual_address;
1134            GST_DEBUG("YBuf gem to fd[0]=%d virtual_address = %p", psimgb->fd[0], psimgb->a[0]);
1135           psimgb->fd[1] = drm_convert_gem_to_fd(&src->gemname_cnt, src->drm_fd, (void *)data->CbBuf, xv_gem_mmap, &virtual_address);
1136      if(!virtual_address) continue;
1137            psimgb->a[1] = virtual_address;
1138            GST_DEBUG("CbBuf gem to fd[1]=%d  virtual_address = %p", psimgb->fd[1], psimgb->a[1]);
1139            psimgb->buf_share_method = BUF_SHARE_METHOD_FD;
1140          }
1141         psimgb->w[0] = src->width;
1142         psimgb->h[0] = src->height;
1143         psimgb->cs   = SCMN_CS_NV12;
1144         psimgb->w[1] = src->width;
1145         psimgb->h[1] = src->height >> 1;
1146          psimgb->tz_enable = 0;
1147         psimgb->s[0] = GST_ROUND_UP_16(psimgb->w[0]);
1148         psimgb->e[0] = GST_ROUND_UP_16(psimgb->h[0]);
1149         psimgb->s[1] = GST_ROUND_UP_16(psimgb->w[1]);
1150         psimgb->e[1] = GST_ROUND_UP_16(psimgb->h[1]);
1151          outbuf->fd_name = psimgb->fd[0];
1152         GST_BUFFER_MALLOCDATA(outbuf) = (unsigned char*)psimgb;
1153         GST_BUFFER_DATA(outbuf) = src->virtual;
1154         outbuf->YBuf = (void *)data->YBuf;
1155             outbuf->fd_name = psimgb->fd[0];
1156 #ifdef DEBUG_BUFFER
1157         for ( i=0; i<5 ; i++) {
1158          if(value[value_count] == outbuf->YBuf ) {
1159             GST_ERROR("ERROR: value[%d](%d)==YBUf(%d)", value_count, value[value_count], outbuf->YBuf);
1160          }
1161         }
1162         value[value_count] = outbuf->YBuf ;
1163             GST_ERROR("value[%d]=%d", value_count, value[value_count]);
1164             if( value_count < 4){
1165               value_count ++;
1166             } else {
1167               value_count = 0;
1168             }
1169 #endif
1170       }
1171     }
1172   if(!outbuf) continue;
1173         GST_BUFFER_SIZE (outbuf) = src->framesize;
1174     gst_xv_image_src_get_timeinfo(src,outbuf);
1175     src->running_time = GST_BUFFER_TIMESTAMP(outbuf);
1176     src->frame_duration = GST_BUFFER_DURATION(outbuf);
1177     //first_frame = FALSE;
1178     g_mutex_lock (src->queue_lock);
1179     g_queue_push_tail(src->queue, outbuf);
1180     GST_INFO("g_queue_push_tail");
1181     g_mutex_unlock (src->queue_lock);
1182     g_cond_signal(src->queue_cond);
1183     GST_INFO("g_cond_signal");
1184
1185     update_done:
1186       if (src->virtual) tbm_bo_unmap(src->bo);
1187       src->virtual = NULL;
1188       GST_INFO("g_cond_signal");
1189       if (src->bo) tbm_bo_unref(src->bo);
1190       src->bo = NULL;
1191       if (src->dri2_buffers) free(src->dri2_buffers);
1192       src->dri2_buffers = NULL;
1193       gettimeofday(&end_time, NULL);
1194       starttime = start_time.tv_usec;
1195       endtime =  end_time.tv_usec;
1196       GST_INFO("star_time: %d, end_time:%d", starttime, endtime);
1197       if (endtime > starttime) {
1198         GST_INFO("end_time > start_time");
1199         duration = endtime - starttime;
1200          } else {
1201          GST_INFO("end_time.tv_usec < start_time.tv_usec");
1202          endtime=endtime+1000000;
1203          GST_INFO("end_time =%d", endtime);
1204         duration = endtime -starttime;
1205       }
1206       GST_INFO("end_time duration = %d", duration);
1207       gst_xv_get_image_sleep (src, duration);
1208       GST_INFO ("gst_xv_image_src_update_thread cleanup !!");
1209   }
1210   for ( i=0 ; i < GEM_NAME_MAX ; i++) {
1211     /*gem munmap*/
1212     if (xv_gem_mmap->address[i]) {
1213       if (-1 == munmap(xv_gem_mmap->address[i],xv_gem_mmap->buffer_size[i])) {
1214         GST_ERROR ("munmap failed");
1215          return NULL;
1216       }
1217     }
1218     if (xv_gem_mmap->handle[i]) {
1219         gem_close.handle = xv_gem_mmap->handle[i];
1220         if (ioctl(src->drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close)) {
1221           GST_ERROR("Gem Close failed");
1222         }
1223     }
1224     if (xv_gem_mmap->fd[i]) {
1225       close(xv_gem_mmap->fd[i]);
1226     }
1227   }
1228   if (xv_gem_mmap) {
1229     free(xv_gem_mmap);
1230     xv_gem_mmap = NULL;
1231   }
1232   GST_LOG_OBJECT (src, "The thread function cleanup");
1233   if (src->atom_stream_off > 0) {
1234     XvSetPortAttribute (src->dpy, src->p, src->atom_stream_off, 1);
1235     src->atom_stream_off = 0;
1236   }
1237   if (src->bufmgr) {
1238     tbm_bufmgr_deinit (src->bufmgr);
1239     src->bufmgr = NULL;
1240   }
1241   if (src->p > 0) {
1242     XvUngrabPort (src->dpy, src->p, 0);
1243     src->p = 0;
1244   }
1245   if (src->gc) {
1246     XFreeGC (src->dpy, src->gc);
1247     src->gc = NULL;
1248   }
1249   if (src->pixmap > 0) {
1250     XFreePixmap (src->dpy, src->pixmap);
1251     src->pixmap = 0;
1252   }
1253   if (src->dpy) {
1254     XCloseDisplay (src->dpy);
1255     src->dpy = NULL;
1256   }
1257   GST_LOG_OBJECT (src, "The thread function stop");
1258   return NULL;
1259 finish:
1260   GST_LOG_OBJECT (src, "The thread function Error cleanup");
1261   if (src->atom_stream_off > 0) {
1262     XvSetPortAttribute (src->dpy, src->p, src->atom_stream_off, 1);
1263     src->atom_stream_off = 0;
1264   }
1265   if (src->bufmgr) tbm_bufmgr_deinit (src->bufmgr);
1266   src->bufmgr = NULL;
1267   if (src->p > 0) XvUngrabPort (src->dpy, src->p, 0);
1268   src->p = 0;
1269   if (src->gc) XFreeGC (src->dpy, src->gc);
1270   src->gc = NULL;
1271   if (src->pixmap > 0) XFreePixmap (src->dpy, src->pixmap);
1272   src->pixmap = 0;
1273   if (src->dpy) XCloseDisplay (src->dpy);
1274   src->dpy = NULL;
1275   GST_LOG_OBJECT (src, "The thread function Error stop");
1276   return NULL;
1277 }
1278
1279 static tbm_bufmgr bufmgr_get (Display *dpy, Pixmap pixmap)
1280 {
1281   int screen;
1282   int drm_fd;
1283   tbm_bufmgr bufmgr;
1284   int eventBase, errorBase;
1285   int dri2Major, dri2Minor;
1286   char *driverName, *deviceName;
1287   drm_magic_t magic;
1288
1289   screen = DefaultScreen(dpy);
1290   if (!DRI2QueryExtension (dpy, &eventBase, &errorBase)) {
1291     GST_ERROR ("!!Error : DRI2QueryExtension !!");
1292     return NULL;
1293   }
1294   if (!DRI2QueryVersion (dpy, &dri2Major, &dri2Minor)) {
1295     GST_ERROR ("!!Error : DRI2QueryVersion !!");
1296     return NULL;
1297   }
1298   if (!DRI2Connect (dpy, RootWindow(dpy, screen), &driverName, &deviceName)) {
1299     GST_ERROR ( "!!Error : DRI2Connect !!");
1300     if(driverName) Xfree(driverName);
1301     if(deviceName) Xfree(deviceName);
1302     return NULL;
1303   }
1304   if(driverName) Xfree(driverName);
1305   GST_DEBUG("Open drm device : %s", deviceName);
1306   // get the drm_fd though opening the deviceName
1307   drm_fd = open (deviceName, O_RDWR);
1308   if (drm_fd < 0) {
1309     GST_ERROR ("!!Error : cannot open drm device (%s)", deviceName);
1310     if(deviceName) Xfree(deviceName);
1311     return NULL;
1312   }
1313   if(deviceName) Xfree(deviceName);
1314   /* get the drm magic */
1315   drmGetMagic(drm_fd, &magic);
1316   fprintf(stderr, ">>> drm magic=%d \n", magic);
1317   if (!DRI2Authenticate(dpy, RootWindow(dpy, screen), magic))
1318   {
1319     fprintf(stderr, "!!Error : DRI2Authenticate !!\n");
1320     close (drm_fd);
1321     return NULL;
1322   }
1323   // drm slp buffer manager init
1324   bufmgr = tbm_bufmgr_init (drm_fd);
1325   if (!bufmgr) {
1326     GST_ERROR ("!!Error : fail to init buffer manager ");
1327     close (drm_fd);
1328     return NULL;
1329   }
1330   DRI2CreateDrawable (dpy, pixmap);
1331   return bufmgr;
1332 }
1333
1334 static int port_get (GstXVImageSrc * src, unsigned int id)
1335 {
1336   unsigned int ver, rev, req_base, err_base;
1337   unsigned int adaptors;
1338   XvAdaptorInfo *ai = NULL;
1339   XvAttribute *at = NULL;
1340   XvImageFormatValues *fo = NULL;
1341   int attributes, formats;
1342   int i, j, p;
1343
1344   if (XvQueryExtension (src->dpy, &ver, &rev, &req_base, &src->evt_base, &err_base) != Success) return -1;
1345   if (XvQueryAdaptors (src->dpy, DefaultRootWindow (src->dpy), &adaptors, &ai) != Success) return -1;
1346   if (!ai) return -1;
1347   for (i = 0; i < adaptors; i++) {
1348     int support_format = False;
1349     if (!(ai[i].type & XvInputMask) || !(ai[i].type & XvStillMask)) continue;
1350     GST_LOG ("===========================================");
1351     GST_LOG (" name:        %s"
1352                 " first port:  %ld"
1353                 " ports:       %ld",
1354                 ai[i].name,
1355                 ai[i].base_id,
1356                 ai[i].num_ports);
1357     p = ai[i].base_id;
1358     GST_LOG (" attribute list:");
1359     at = XvQueryPortAttributes (src->dpy, p, &attributes);
1360     for (j = 0; j < attributes; j++) GST_LOG ("\t-  name: %s\n"
1361                     "\t\t  flags:     %s%s\n"
1362                     "\t\t  min_value:  %i\n"
1363                     "\t\t  max_value:  %i\n",
1364                     at[j].name,
1365                     (at[j].flags & XvGettable) ? " get" : "",
1366                     (at[j].flags & XvSettable) ? " set" : "",
1367                     at[j].min_value, at[j].max_value);
1368     if (at) XFree (at);
1369     GST_LOG (" image format list:");
1370     fo = XvListImageFormats (src->dpy, p, &formats);
1371     for (j = 0; j < formats; j++) {
1372       GST_LOG ("\t-  0x%x (%4.4s) %s", fo[j].id, (char *)&fo[j].id, (fo[j].format == XvPacked) ? "packed" : "planar");
1373       if (fo[j].id == (int)id) support_format = True;
1374     }
1375     if (fo) XFree (fo);
1376     if (!support_format) continue;
1377     for (; p < ai[i].base_id + ai[i].num_ports; p++) {
1378       if (XvGrabPort (src->dpy, p, 0) == Success) {
1379         GST_LOG ("========================================");
1380         GST_DEBUG ("XvGrabPort success : %d", p);
1381         GST_LOG ("========================================");
1382         XvFreeAdaptorInfo (ai);
1383         return p;
1384       }
1385     }
1386   }
1387   XvFreeAdaptorInfo (ai);
1388   return -1;
1389 }
1390
1391 static void pixmap_update (GstXVImageSrc * src, Display *dpy, tbm_bufmgr bufmgr, Pixmap pixmap,
1392                int x, int y, int width, int height)
1393 {
1394   unsigned int attachments[1];
1395   int dri2_count, dri2_out_count;
1396   int dri2_width, dri2_height, dri2_stride;
1397   int opt;
1398   tbm_bo_handle temp_virtual;
1399   attachments[0] = DRI2BufferFrontLeft;
1400   dri2_count = 1;
1401   src->dri2_buffers = DRI2GetBuffers (dpy, pixmap, &dri2_width, &dri2_height, attachments, dri2_count, &dri2_out_count);
1402   if (!src->dri2_buffers) {
1403     GST_ERROR ("[Error] : fail to get buffers");
1404     goto update_done;
1405   }
1406   if (!src->dri2_buffers[0].name) {
1407     GST_ERROR ("[Error] : a handle of the dri2 buffer is null  ");
1408     goto update_done;
1409   }
1410   src->bo = tbm_bo_import(bufmgr, src->dri2_buffers[0].name);
1411   if (!src->bo) {
1412     GST_ERROR ("[Error] : cannot import bo (key:%d)", src->dri2_buffers[0].name);
1413     goto update_done;
1414   }
1415   dri2_stride = src->dri2_buffers[0].pitch;
1416   opt = TBM_OPTION_READ|TBM_OPTION_WRITE;
1417   temp_virtual = tbm_bo_map (src->bo, TBM_DEVICE_CPU, opt);
1418   src->virtual = temp_virtual.ptr;
1419   if (!src->virtual) {
1420     GST_ERROR ("[Error] : fail to map ");
1421     goto update_done;
1422   }
1423   return;
1424 update_done:
1425   if (src->virtual) tbm_bo_unmap(src->bo);
1426   src->virtual = NULL;
1427   if (src->bo) tbm_bo_unref(src->bo);
1428   src->bo = NULL;
1429   if (src->dri2_buffers) free(src->dri2_buffers);
1430   src->dri2_buffers = NULL;
1431   return;
1432 }
1433
1434 static Pixmap pixmap_create (GstXVImageSrc * src, Display *dpy, int width, int height)
1435 {
1436   src->pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, DefaultDepth(dpy, DefaultScreen(dpy)));
1437   src->gc = XCreateGC (dpy, src->pixmap, 0, 0);
1438   XSetForeground (dpy, src->gc, 0xFFFF0000);
1439   XFillRectangle (dpy, src->pixmap, src->gc, 0, 0, width, height);
1440   XSync(dpy, 0);
1441   XFreeGC (dpy, src->gc);
1442   return src->pixmap;
1443 }
1444
1445 static gboolean
1446 gst_xv_image_src_stop (GstBaseSrc * bsrc)
1447 {
1448   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1449   GST_DEBUG_OBJECT (src, "stop()");
1450
1451   if(src->updates_thread) {
1452     src->thread_return = TRUE;
1453     g_thread_join ( src->updates_thread);
1454     src->updates_thread = NULL;
1455   }
1456   GST_DEBUG_OBJECT (src, "stop end ");
1457   return TRUE;
1458 }
1459
1460 /* Interrupt a blocking request. */
1461 static gboolean
1462 gst_xv_image_src_unlock (GstBaseSrc * bsrc)
1463 {
1464   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1465   GST_DEBUG_OBJECT (src, "unlock()");
1466   g_cond_signal(src->queue_cond);
1467   return TRUE;
1468 }
1469
1470 /* Interrupt interrupt. */
1471 static gboolean
1472 gst_xv_image_src_unlock_stop (GstBaseSrc * bsrc)
1473 {
1474   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1475   GST_DEBUG_OBJECT (src, "unlock_stop()");
1476   return TRUE;
1477 }
1478
1479 static gboolean
1480 gst_xv_image_src_get_size (GstBaseSrc * bsrc, guint64 * size)
1481 {
1482   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1483   GST_INFO ("Get size %x", src);
1484   return FALSE;
1485 }
1486
1487 static gboolean
1488 gst_xv_image_src_is_seekable (GstBaseSrc * bsrc)
1489 {
1490   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1491   GST_INFO ("Is seekable %x", src);
1492   return FALSE;
1493 }
1494
1495 static gboolean
1496 gst_xv_image_src_query (GstBaseSrc * bsrc, GstQuery * query)
1497 {
1498   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1499   gboolean ret;
1500   GST_INFO ("src query %x", src);
1501   switch (GST_QUERY_TYPE (query)) {
1502     case GST_QUERY_URI:
1503       ret = TRUE;
1504     break;
1505     default:
1506       ret = FALSE;
1507     break;
1508   }
1509
1510   if (!ret)
1511     ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1512
1513   return ret;
1514 }
1515
1516 static gboolean
1517 plugin_init (GstPlugin * plugin)
1518 {
1519   GST_DEBUG_CATEGORY_INIT (xvimagesrc_debug, "xvimagesrc", 0, "XServer display FB video capture Source");
1520   return gst_element_register (plugin, "xvimagesrc", GST_RANK_PRIMARY, GST_TYPE_XV_IMAGE_SRC);
1521 }
1522
1523 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1524   GST_VERSION_MINOR,
1525   "xvimage",
1526   "XServer display video src",
1527   plugin_init, VERSION, "LGPL", "Samsung Electronics Co", "http://www.samsung.com")