Waylandsink : 1. change video format name for SN12 and ST12
[platform/upstream/gstreamer.git] / ext / wayland / waylandpool.c
1 /* GStreamer
2  * Copyright (C) 2012 Intel Corporation
3  * Copyright (C) 2012 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
4  * Copyright (C) 2014 Collabora Ltd.
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., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "waylandpool.h"
27 #include "wldisplay.h"
28 #include "wlvideoformat.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <sys/mman.h>
36 #include <sys/types.h>
37 #ifdef GST_WLSINK_ENHANCEMENT
38 //#define DUMP_BUFFER
39 #ifdef DUMP_BUFFER
40 int dump_cnt = 0;
41 int _write_rawdata (const char *file, const void *data, unsigned int size);
42 #endif
43 #endif
44
45 GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
46 #define GST_CAT_DEFAULT gstwayland_debug
47
48 /* wl metadata */
49 GType
50 gst_wl_meta_api_get_type (void)
51 {
52   static volatile GType type;
53   static const gchar *tags[] =
54       { "memory", "size", "colorspace", "orientation", NULL };
55
56   if (g_once_init_enter (&type)) {
57     GType _type = gst_meta_api_type_register ("GstWlMetaAPI", tags);
58     g_once_init_leave (&type, _type);
59   }
60   return type;
61 }
62
63 static void
64 gst_wl_meta_free (GstWlMeta * meta, GstBuffer * buffer)
65 {
66   GST_DEBUG ("destroying wl_buffer %p", meta->wbuffer);
67   wl_buffer_destroy (meta->wbuffer);
68 }
69
70 const GstMetaInfo *
71 gst_wl_meta_get_info (void)
72 {
73   static const GstMetaInfo *wl_meta_info = NULL;
74
75   if (g_once_init_enter (&wl_meta_info)) {
76     const GstMetaInfo *meta =
77         gst_meta_register (GST_WL_META_API_TYPE, "GstWlMeta",
78         sizeof (GstWlMeta), (GstMetaInitFunction) NULL,
79         (GstMetaFreeFunction) gst_wl_meta_free,
80         (GstMetaTransformFunction) NULL);
81     g_once_init_leave (&wl_meta_info, meta);
82   }
83   return wl_meta_info;
84 }
85
86 /* bufferpool */
87 static void gst_wayland_buffer_pool_finalize (GObject * object);
88 static gboolean gst_wayland_buffer_pool_set_config (GstBufferPool * pool,
89     GstStructure * config);
90 static gboolean gst_wayland_buffer_pool_start (GstBufferPool * pool);
91 static gboolean gst_wayland_buffer_pool_stop (GstBufferPool * pool);
92 static GstFlowReturn gst_wayland_buffer_pool_alloc (GstBufferPool * pool,
93     GstBuffer ** buffer, GstBufferPoolAcquireParams * params);
94
95 #ifdef GST_WLSINK_ENHANCEMENT
96 /*tizen buffer pool*/
97 static void gst_wayland_tizen_buffer_pool_finalize (GObject * object);
98 static gboolean gst_wayland_tizen_buffer_pool_start (GstBufferPool * pool);
99 static gboolean gst_wayland_tizen_buffer_pool_stop (GstBufferPool * pool);
100 static GstFlowReturn gst_wayland_tizen_buffer_pool_alloc (GstBufferPool * pool,
101     GstBuffer ** buffer, GstBufferPoolAcquireParams * params);
102 #endif
103
104 #define gst_wayland_buffer_pool_parent_class parent_class
105 G_DEFINE_TYPE (GstWaylandBufferPool, gst_wayland_buffer_pool,
106     GST_TYPE_BUFFER_POOL);
107
108 static void
109 gst_wayland_buffer_pool_class_init (GstWaylandBufferPoolClass * klass)
110 {
111   FUNCTION_ENTER ();
112
113   GObjectClass *gobject_class = (GObjectClass *) klass;
114   GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
115
116   gstbufferpool_class->set_config = gst_wayland_buffer_pool_set_config;
117 #ifdef GST_WLSINK_ENHANCEMENT
118   gobject_class->finalize = gst_wayland_tizen_buffer_pool_finalize;
119   gstbufferpool_class->start = gst_wayland_tizen_buffer_pool_start;
120   gstbufferpool_class->stop = gst_wayland_tizen_buffer_pool_stop;
121   gstbufferpool_class->alloc_buffer = gst_wayland_tizen_buffer_pool_alloc;
122 #else
123   gobject_class->finalize = gst_wayland_buffer_pool_finalize;
124   gstbufferpool_class->start = gst_wayland_buffer_pool_start;
125   gstbufferpool_class->stop = gst_wayland_buffer_pool_stop;
126   gstbufferpool_class->alloc_buffer = gst_wayland_buffer_pool_alloc;
127 #endif
128 }
129
130 static void
131 gst_wayland_buffer_pool_init (GstWaylandBufferPool * self)
132 {
133   FUNCTION_ENTER ();
134
135   gst_video_info_init (&self->info);
136   g_mutex_init (&self->buffers_map_mutex);
137   self->buffers_map = g_hash_table_new (g_direct_hash, g_direct_equal);
138 }
139
140 static void
141 gst_wayland_buffer_pool_finalize (GObject * object)
142 {
143   FUNCTION_ENTER ();
144
145   GstWaylandBufferPool *pool = GST_WAYLAND_BUFFER_POOL_CAST (object);
146
147   if (pool->wl_pool)
148     gst_wayland_buffer_pool_stop (GST_BUFFER_POOL (pool));
149
150   g_mutex_clear (&pool->buffers_map_mutex);
151   g_hash_table_unref (pool->buffers_map);
152
153   g_object_unref (pool->display);
154
155   G_OBJECT_CLASS (gst_wayland_buffer_pool_parent_class)->finalize (object);
156 }
157
158 static void
159 buffer_release (void *data, struct wl_buffer *wl_buffer)
160 {
161   FUNCTION_ENTER ();
162
163   GstWaylandBufferPool *self = data;
164   GstBuffer *buffer;
165   GstWlMeta *meta;
166
167   g_mutex_lock (&self->buffers_map_mutex);
168   buffer = g_hash_table_lookup (self->buffers_map, wl_buffer);
169
170   GST_LOG_OBJECT (self, "wl_buffer::release (GstBuffer: %p)", buffer);
171
172   if (buffer) {
173     meta = gst_buffer_get_wl_meta (buffer);
174     if (meta->used_by_compositor) {
175       meta->used_by_compositor = FALSE;
176       /* unlock before unref because stop() may be called from here */
177       g_mutex_unlock (&self->buffers_map_mutex);
178           GST_ERROR("gst_buffer_unref");
179       gst_buffer_unref (buffer);
180       return;
181     }
182   }
183   g_mutex_unlock (&self->buffers_map_mutex);
184 }
185
186 static const struct wl_buffer_listener buffer_listener = {
187   buffer_release
188 };
189
190 void
191 gst_wayland_compositor_acquire_buffer (GstWaylandBufferPool * self,
192     GstBuffer * buffer)
193 {
194   FUNCTION_ENTER ();
195
196   GstWlMeta *meta;
197
198   meta = gst_buffer_get_wl_meta (buffer);
199   g_return_if_fail (meta != NULL);
200   g_return_if_fail (meta->pool == self);
201   g_return_if_fail (meta->used_by_compositor == FALSE);
202
203   meta->used_by_compositor = TRUE;
204   gst_buffer_ref (buffer);
205 }
206
207 static void
208 unref_used_buffers (gpointer key, gpointer value, gpointer data)
209 {
210   FUNCTION_ENTER ();
211
212   GstBuffer *buffer = value;
213   GstWlMeta *meta = gst_buffer_get_wl_meta (buffer);
214   GList **to_unref = data;
215
216   g_return_if_fail (meta != NULL);
217
218   if (meta->used_by_compositor) {
219     meta->used_by_compositor = FALSE;
220     *to_unref = g_list_prepend (*to_unref, buffer);
221   }
222 }
223
224 void
225 gst_wayland_compositor_release_all_buffers (GstWaylandBufferPool * self)
226 {
227   FUNCTION_ENTER ();
228
229   GList *to_unref = NULL;
230
231   g_mutex_lock (&self->buffers_map_mutex);
232   g_hash_table_foreach (self->buffers_map, unref_used_buffers, &to_unref);
233   g_mutex_unlock (&self->buffers_map_mutex);
234
235   /* unref without the lock because stop() may be called from here */
236   if (to_unref) {
237     g_list_free_full (to_unref, (GDestroyNotify) gst_buffer_unref);
238   }
239 }
240
241 static gboolean
242 gst_wayland_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
243 {
244   FUNCTION_ENTER ();
245
246   GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL_CAST (pool);
247   GstCaps *caps;
248
249   if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
250     goto wrong_config;
251
252   if (caps == NULL)
253     goto no_caps;
254
255   /* now parse the caps from the config */
256   if (!gst_video_info_from_caps (&self->info, caps))
257     goto wrong_caps;
258
259   GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT,
260       GST_VIDEO_INFO_WIDTH (&self->info), GST_VIDEO_INFO_HEIGHT (&self->info),
261       caps);
262
263   /*Fixme: Enable metadata checking handling based on the config of pool */
264
265   return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
266   /* ERRORS */
267 wrong_config:
268   {
269     GST_WARNING_OBJECT (pool, "invalid config");
270     return FALSE;
271   }
272 no_caps:
273   {
274     GST_WARNING_OBJECT (pool, "no caps in config");
275     return FALSE;
276   }
277 wrong_caps:
278   {
279     GST_WARNING_OBJECT (pool,
280         "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
281     return FALSE;
282   }
283 }
284
285 static gboolean
286 gst_wayland_buffer_pool_start (GstBufferPool * pool)
287 {
288   FUNCTION_ENTER ();
289
290   GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL (pool);
291
292   GST_DEBUG_OBJECT (self, "Initializing wayland buffer pool");
293
294   guint size = 0;
295   int fd;
296   char filename[1024];
297   static int init = 0;
298
299   GST_DEBUG_OBJECT (self, "Initializing wayland buffer pool");
300
301   /* configure */
302   size = GST_VIDEO_INFO_SIZE (&self->info) * 15;
303
304   /* allocate shm pool */
305   snprintf (filename, 1024, "%s/%s-%d-%s", g_get_user_runtime_dir (),
306       "wayland-shm", init++, "XXXXXX");
307
308   fd = mkstemp (filename);
309   if (fd < 0) {
310     GST_ERROR_OBJECT (pool, "opening temp file %s failed: %s", filename,
311         strerror (errno));
312     return FALSE;
313   }
314   if (ftruncate (fd, size) < 0) {
315     GST_ERROR_OBJECT (pool, "ftruncate failed: %s", strerror (errno));
316     close (fd);
317     return FALSE;
318   }
319
320   self->data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
321   if (self->data == MAP_FAILED) {
322     GST_ERROR_OBJECT (pool, "mmap failed: %s", strerror (errno));
323     close (fd);
324     return FALSE;
325   }
326
327   self->wl_pool = wl_shm_create_pool (self->display->shm, fd, size);
328   unlink (filename);
329   close (fd);
330
331   self->size = size;
332   self->used = 0;
333
334
335   return GST_BUFFER_POOL_CLASS (parent_class)->start (pool);
336 }
337
338 static gboolean
339 gst_wayland_buffer_pool_stop (GstBufferPool * pool)
340 {
341   FUNCTION_ENTER ();
342
343   GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL (pool);
344
345   GST_DEBUG_OBJECT (self, "Stopping wayland buffer pool");
346
347   munmap (self->data, self->size);
348   wl_shm_pool_destroy (self->wl_pool);
349
350   self->wl_pool = NULL;
351   self->size = 0;
352   self->used = 0;
353
354   /* all buffers are about to be destroyed;
355    * we should no longer do anything with them */
356   g_mutex_lock (&self->buffers_map_mutex);
357   g_hash_table_remove_all (self->buffers_map);
358   g_mutex_unlock (&self->buffers_map_mutex);
359
360   return GST_BUFFER_POOL_CLASS (parent_class)->stop (pool);
361 }
362
363 static GstFlowReturn
364 gst_wayland_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
365     GstBufferPoolAcquireParams * params)
366 {
367   FUNCTION_ENTER ();
368
369   GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL_CAST (pool);
370
371   gint width, height, stride;
372   gsize size;
373   enum wl_shm_format format;
374   gint offset;
375   void *data;
376   GstWlMeta *meta;
377
378   width = GST_VIDEO_INFO_WIDTH (&self->info);
379   height = GST_VIDEO_INFO_HEIGHT (&self->info);
380   stride = GST_VIDEO_INFO_PLANE_STRIDE (&self->info, 0);
381   size = GST_VIDEO_INFO_SIZE (&self->info);
382   format =
383       gst_video_format_to_wayland_format (GST_VIDEO_INFO_FORMAT (&self->info));
384
385   GST_DEBUG_OBJECT (self, "Allocating buffer of size %" G_GSSIZE_FORMAT
386       " (%d x %d, stride %d), format %s", size, width, height, stride,
387       gst_wayland_format_to_string (format));
388   /* try to reserve another memory block from the shm pool */
389   if (self->used + size > self->size)
390     goto no_buffer;
391
392   offset = self->used;
393   self->used += size;
394
395   data = ((gchar *) self->data) + offset;
396
397   /* create buffer and its metadata object */
398   *buffer = gst_buffer_new ();
399   meta = (GstWlMeta *) gst_buffer_add_meta (*buffer, GST_WL_META_INFO, NULL);
400   meta->pool = self;
401
402   meta->wbuffer = wl_shm_pool_create_buffer (self->wl_pool, offset,
403       width, height, stride, format);
404   meta->used_by_compositor = FALSE;
405
406   /* configure listening to wl_buffer.release */
407   g_mutex_lock (&self->buffers_map_mutex);
408   g_hash_table_insert (self->buffers_map, meta->wbuffer, *buffer);
409   g_mutex_unlock (&self->buffers_map_mutex);
410
411   wl_buffer_add_listener (meta->wbuffer, &buffer_listener, self);
412
413   /* add the allocated memory on the GstBuffer */
414   gst_buffer_append_memory (*buffer,
415       gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, data,
416           size, 0, size, NULL, NULL));
417
418   return GST_FLOW_OK;
419
420   /* ERROR */
421 no_buffer:
422   {
423     GST_WARNING_OBJECT (pool, "can't create buffer");
424     return GST_FLOW_ERROR;
425   }
426 }
427
428 GstBufferPool *
429 gst_wayland_buffer_pool_new (GstWlDisplay * display)
430 {
431   FUNCTION_ENTER ();
432
433   GstWaylandBufferPool *pool;
434
435   g_return_val_if_fail (GST_IS_WL_DISPLAY (display), NULL);
436   pool = g_object_new (GST_TYPE_WAYLAND_BUFFER_POOL, NULL);
437   pool->display = g_object_ref (display);
438
439   return GST_BUFFER_POOL_CAST (pool);
440 }
441
442 #ifdef GST_WLSINK_ENHANCEMENT
443
444 static gboolean
445 gst_wayland_tizen_buffer_pool_start (GstBufferPool * pool)
446 {
447   FUNCTION_ENTER ();
448
449   GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL (pool);
450
451   GST_DEBUG_OBJECT (self, "Initializing tizen buffer pool");
452
453   tbm_bo_handle vitual_addr;
454   guint size = 0;
455
456   if (self->display->is_native_format == TRUE) {
457     /*in case of SN12 or ST12 video  format */
458     size = self->display->native_video_size * 15;
459     vitual_addr.ptr = NULL;
460
461   } else {
462     /*in case of normal video format */
463     size = GST_VIDEO_INFO_SIZE (&self->info) * 15;
464
465     self->display->tbm_bufmgr = tbm_bufmgr_init (self->display->drm_fd);
466     g_return_if_fail (self->display->tbm_bufmgr != NULL);
467
468     self->display->tbm_bo =
469         tbm_bo_alloc (self->display->tbm_bufmgr, size, TBM_BO_DEFAULT);
470     if (!self->display->tbm_bo) {
471       GST_ERROR_OBJECT (pool, "alloc tbm bo(size:%d) failed: %s", size,
472           strerror (errno));
473       tbm_bufmgr_deinit (self->display->tbm_bufmgr);
474       self->display->tbm_bufmgr = NULL;
475       return FALSE;
476     }
477
478     vitual_addr = tbm_bo_get_handle (self->display->tbm_bo, TBM_DEVICE_CPU);
479     if (!vitual_addr.ptr) {
480       GST_ERROR_OBJECT (pool, "get tbm bo handle failed: %s", strerror (errno));
481       tbm_bo_unref (self->display->tbm_bo);
482       tbm_bufmgr_deinit (self->display->tbm_bufmgr);
483       self->display->tbm_bo = NULL;
484       self->display->tbm_bufmgr = NULL;
485       return FALSE;
486     }
487   }
488
489   self->data = vitual_addr.ptr;
490   self->size = size;
491   self->used = 0;
492
493   return GST_BUFFER_POOL_CLASS (parent_class)->start (pool);
494 }
495
496 static gboolean
497 gst_wayland_tizen_buffer_pool_stop (GstBufferPool * pool)
498 {
499   FUNCTION_ENTER ();
500
501   GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL (pool);
502
503   GST_DEBUG_OBJECT (self, "Stopping tizen buffer pool");
504
505   self->size = 0;
506   self->used = 0;
507
508   /* all buffers are about to be destroyed;
509    * we should no longer do anything with them */
510   g_mutex_lock (&self->buffers_map_mutex);
511   g_hash_table_remove_all (self->buffers_map);
512   g_mutex_unlock (&self->buffers_map_mutex);
513
514   return GST_BUFFER_POOL_CLASS (parent_class)->stop (pool);
515 }
516
517 static GstFlowReturn
518 gst_wayland_tizen_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
519     GstBufferPoolAcquireParams * params)
520 {
521   FUNCTION_ENTER ();
522
523   GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL_CAST (pool);
524
525   gint width, height;
526   gsize size;
527   enum tizen_buffer_pool_format format;
528   gint data_offset;
529   void *data;
530   GstWlMeta *meta;
531   tbm_bo_handle vitual_addr;
532
533   if (self->display->is_native_format == TRUE) {
534     /*in case of SN12 or ST12 video  format */
535     unsigned int name[NV_BUF_PLANE_NUM];
536     unsigned int offset[NV_BUF_PLANE_NUM] = { 0, };
537     unsigned int stride[NV_BUF_PLANE_NUM] = { 0, };
538     width = GST_VIDEO_INFO_WIDTH (&self->info);
539     height = GST_VIDEO_INFO_HEIGHT (&self->info);
540     size = self->display->native_video_size;
541
542     format =
543         gst_video_format_to_wayland_format (GST_VIDEO_INFO_FORMAT
544         (&self->info));
545
546
547     vitual_addr = tbm_bo_get_handle (self->display->bo[0], TBM_DEVICE_CPU);
548     if (!vitual_addr.ptr) {
549       GST_ERROR_OBJECT (pool, "get tbm bo handle failed: %s", strerror (errno));
550       return FALSE;
551     }
552     self->data = vitual_addr.ptr;
553     data = ((gchar *) self->data);
554 #ifdef DUMP_BUFFER
555     int ret;
556     char file_name[128];
557         if (dump_cnt < 10) {
558           sprintf (file_name, "/root/WLSINK_OUT_DUMP_%2.2d.dump", dump_cnt++);
559       ret = _write_rawdata (file_name, vitual_addr.ptr,size);
560       if (ret) {
561         GST_ERROR_OBJECT (pool, "_write_rawdata() failed");
562       }
563         }
564 #endif
565     /* create buffer and its metadata object */
566     *buffer = gst_buffer_new ();
567     meta = (GstWlMeta *) gst_buffer_add_meta (*buffer, GST_WL_META_INFO, NULL);
568     meta->pool = self;
569     GST_DEBUG ("TBM bo %p %p %p", self->display->bo[0],
570         self->display->bo[1], 0);
571     for (int i = 0; i < NV_BUF_PLANE_NUM; i++) {
572       if (self->display->bo[i] != NULL) {
573         name[i] = tbm_bo_export (self->display->bo[i]);
574         offset[i] = 0;
575       } else {
576         name[i] = 0;
577         if (i > 0) {
578           offset[i] = offset[i - 1] + self->display->plane_size[i - 1];
579         }
580       }
581       stride[i] = self->display->stride_width[i];
582     }
583
584     meta->wbuffer =
585         tizen_buffer_pool_create_planar_buffer (self->display->
586         tizen_buffer_pool, width, height, format, name[0], offset[0], stride[0],
587         name[1], offset[1], stride[1], 0, 0, 0);
588     meta->used_by_compositor = FALSE;
589
590     GST_DEBUG ("tizen_buffer_pool_create_planar_buffer create wl_buffer %p",
591         meta->wbuffer);
592   } else {
593     int stride;
594
595     /*in case of normal video format */
596     width = GST_VIDEO_INFO_WIDTH (&self->info);
597     height = GST_VIDEO_INFO_HEIGHT (&self->info);
598     stride = GST_VIDEO_INFO_PLANE_STRIDE (&self->info, 0);
599     size = GST_VIDEO_INFO_SIZE (&self->info);
600     format =
601         gst_video_format_to_wayland_format (GST_VIDEO_INFO_FORMAT
602         (&self->info));
603
604     GST_DEBUG_OBJECT (self, "Allocating buffer of size %" G_GSSIZE_FORMAT
605         " (%d x %d, stride %d), format %s", size, width, height, stride,
606         gst_wayland_format_to_string (format));
607
608     /* try to reserve another memory block from the shm pool */
609     if (self->used + size > self->size)
610       goto no_buffer;
611
612     data_offset = self->used;
613     self->used += size;
614
615     data = ((gchar *) self->data) + data_offset;
616
617     /* create buffer and its metadata object */
618     *buffer = gst_buffer_new ();
619     meta = (GstWlMeta *) gst_buffer_add_meta (*buffer, GST_WL_META_INFO, NULL);
620     meta->pool = self;
621
622     meta->wbuffer =
623         tizen_buffer_pool_create_buffer (self->display->tizen_buffer_pool,
624         tbm_bo_export (self->display->tbm_bo), width, height, stride, format);
625     meta->used_by_compositor = FALSE;
626   }
627
628   /* configure listening to wl_buffer.release */
629   g_mutex_lock (&self->buffers_map_mutex);
630   g_hash_table_insert (self->buffers_map, meta->wbuffer, *buffer);
631   g_mutex_unlock (&self->buffers_map_mutex);
632
633   wl_buffer_add_listener (meta->wbuffer, &buffer_listener, self);
634
635   /* add the allocated memory on the GstBuffer */
636   gst_buffer_append_memory (*buffer,
637       gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, data,
638           size, 0, size, NULL, NULL));
639   return GST_FLOW_OK;
640
641   /* ERROR */
642 no_buffer:
643   {
644     GST_WARNING_OBJECT (pool, "can't create buffer");
645     return GST_FLOW_ERROR;
646   }
647 }
648
649 static void
650 gst_wayland_tizen_buffer_pool_finalize (GObject * object)
651 {
652   FUNCTION_ENTER ();
653
654   GstWaylandBufferPool *pool = GST_WAYLAND_BUFFER_POOL_CAST (object);
655
656   if (pool->display->tizen_buffer_pool) {
657     gst_wayland_tizen_buffer_pool_stop (GST_BUFFER_POOL (pool));
658   } else {
659     /*already stop*/
660         return;
661   }
662   g_mutex_clear (&pool->buffers_map_mutex);
663   g_hash_table_unref (pool->buffers_map);
664
665   g_object_unref (pool->display);
666
667   G_OBJECT_CLASS (gst_wayland_buffer_pool_parent_class)->finalize (object);
668 }
669
670 #endif
671 #ifdef DUMP_BUFFER
672 int
673 _write_rawdata (const char *file, const void *data, unsigned int size)
674 {
675   FILE *fp;
676
677   fp = fopen (file, "wb");
678   if (fp == NULL)
679     return -1;
680
681   fwrite ((char *) data, sizeof (char), size, fp);
682   fclose (fp);
683
684   return 0;
685 }
686 #endif