tizencamerasrc: Update error handling while previewing
[platform/upstream/gst-plugins-tizen.git] / tizencamerasrc / src / gsttizencamerasrc.c
1 /*
2  * gsttizencamerasrc.c
3  *
4  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jeongmo Yang <jm80.yang@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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <inttypes.h>
29 #include <gst/gst.h>
30 #include <gst/gstutils.h>
31 #include <gst/video/video-info.h>
32 #include <glib-object.h>
33 #include <unistd.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38
39 #include "gsttizencamerasrc.h"
40 #include "gsttizencamerasrccontrol.h"
41 #include "gsttizencamerasrccolorbalance.h"
42
43
44 /******************************************************************************
45  * Definitions
46  *******************************************************************************/
47 GST_DEBUG_CATEGORY (tizencamerasrc_debug);
48 #define GST_CAT_DEFAULT tizencamerasrc_debug
49
50
51 #define CAMERASRC_ALIGN(addr,size)              (((addr)+((size)-1))&(~((size)-1)))
52
53 #if !defined (CLEAR)
54   #define CLEAR(x)                              memset(&(x), 0, sizeof(x))
55 #endif
56
57 /* Local definitions */
58 #define _DEFAULT_FPS                            15
59 #define _DEFAULT_HIGH_SPEED_FPS                 0
60 #define _DEFAULT_FPS_AUTO                       FALSE
61 #define _DEFAULT_EXTRA_PREVIEW                  FALSE
62 #define _DEFAULT_PIX_FORMAT                     CAMERA_PIXEL_FORMAT_NV12
63 #define _DEFAULT_PIX_FORMAT_NAME                "NV12"
64 #define _DEFAULT_CAPTURE_FORMAT_NAME            "JPEG"
65 #define _DEFAULT_CAMERA_ID                      0
66
67 #define _CAMERA_ID_MIN                          0
68 #define _CAMERA_ID_MAX                          1
69
70 #define _DEFAULT_CAP_QUALITY                    95
71 #define _DEFAULT_CAP_WIDTH                      640
72 #define _DEFAULT_CAP_HEIGHT                     480
73 #define _DEFAULT_CAP_COUNT                      1
74 #define _DEFAULT_CAP_INTERVAL                   0
75 #define _DEFAULT_CAP_PROVIDE_EXIF               FALSE
76 #define _DEFAULT_BITRATE                        (1024 * 1024)   /* bps, 1 Mbps */
77 #define _DEFAULT_GOP_INTERVAL                   1000            /* msec, 1 second */
78 #define _DEFAULT_LIVE_BUFFER_MAX                32
79 #define _DEFAULT_LIVE_BUFFER_MAX_RAW            16
80 #define _BUFFER_WAIT_TIMEOUT                    1000000         /* usec */
81 #define _DEFAULT_EMPTY_BUFFER_TIMEOUT           5000            /* msec */
82 #define _DEFAULT_BUFFER_QUARK                   0
83
84 enum {
85   CAMERA_COLOR_BALANCE_BRIGHTNESS = 0,
86   CAMERA_COLOR_BALANCE_CONTRAST,
87   CAMERA_COLOR_BALANCE_WHITE_BALANCE,
88   CAMERA_COLOR_BALANCE_COLOR_TONE,
89   CAMERA_COLOR_BALANCE_SATURATION,
90   CAMERA_COLOR_BALANCE_HUE,
91   CAMERA_COLOR_BALANCE_SHARPNESS,
92   CAMERA_COLOR_BALANCE_NUM
93 };
94
95 enum {
96   CAMERA_CONTROL_PTZ_TYPE = 0,
97   CAMERA_CONTROL_PAN,
98   CAMERA_CONTROL_TILT,
99   CAMERA_CONTROL_NUM
100 };
101
102 #define SAFE_FREE_GQUEUE(gqueue) \
103   if (gqueue) { \
104     g_queue_free(gqueue); \
105     gqueue = NULL; \
106   }
107
108 #define MAKE_FOURCC_FROM_STRING(string) ((guint32)(string[0] | (string[1] << 8) | (string[2] << 16) | (string[3] << 24)))
109
110
111 /* Enumerations */
112 enum {
113   /*signal*/
114   SIGNAL_STILL_CAPTURE,
115   SIGNAL_VIDEO_STREAM_CB,
116   SIGNAL_EXTRA_PREVIEW_STREAM_CB,
117
118   /*SIGNAL_REGISTER_TROUBLE,*/
119   LAST_SIGNAL
120 };
121
122 enum {
123   ARG_0,
124   /* device */
125   ARG_CAMERA_ID,
126   ARG_DEVICE_NAME,
127   ARG_DEVICE_BUS,
128   ARG_DEVICE_PORT,
129   ARG_HAL_NAME,
130
131   /* preview */
132   ARG_VFLIP,
133   ARG_HFLIP,
134   ARG_HIGH_SPEED_FPS,
135   ARG_AUTO_FPS,
136   ARG_EXTRA_PREVIEW,
137   ARG_LIVE_BUFFER_MAX,
138   ARG_LIVE_BUFFER_MAX_RAW,
139   ARG_EMPTY_BUFFER_TIMEOUT,
140   ARG_BUFFER_QUARK,
141
142   /* capture */
143   ARG_CAPTURE_FOURCC,
144   ARG_CAPTURE_WIDTH,
145   ARG_CAPTURE_HEIGHT,
146   ARG_CAPTURE_INTERVAL,
147   ARG_CAPTURE_COUNT,
148   ARG_CAPTURE_QUALITY,
149   ARG_CAPTURE_PROVIDE_EXIF,
150
151   /* video */
152   ARG_VIDEO_WIDTH,
153   ARG_VIDEO_HEIGHT,
154   ARG_VIDEO_FPS,
155   ARG_RECORDING_HINT,
156
157   /* encoded format */
158   ARG_BITRATE,
159   ARG_GOP_INTERVAL,
160
161   ARG_NUM
162 };
163
164 enum {
165   VIDEO_IN_MODE_NONE,
166   VIDEO_IN_MODE_PREVIEW,
167   VIDEO_IN_MODE_VIDEO,
168   VIDEO_IN_MODE_CAPTURE,
169 };
170
171 typedef struct _GstTizenCameraSrcCommand {
172   const char *label;
173   uint64_t cmd;
174 } GstTizenCameraSrcCommand;
175
176
177 static void gst_tizencamerasrc_uri_handler_init (gpointer g_iface, gpointer iface_data);
178
179 static guint gst_tizencamerasrc_signals[LAST_SIGNAL] = { 0 };
180
181 /* Element template variables */
182 static GstStaticPadTemplate src_factory =
183   GST_STATIC_PAD_TEMPLATE("src",
184                           GST_PAD_SRC,
185                           GST_PAD_ALWAYS,
186                           GST_STATIC_CAPS("video/x-raw,"
187                                           "format = (string) { NV12, SN12, NV21, SN21, I420, S420, YV12, YUY2, SUYV, UYVY, SYVY }, "
188                                           "width = (int) [ 1, 8192 ], "
189                                           "height = (int) [ 1, 8192 ]; "
190                                           "video/x-h264,"
191                                           "stream-format = (string) { byte-stream, avc }, "
192                                           "alignment = (string) au; "
193                                           "video/x-vp8,"
194                                           "width = (int) [ 1, 8192 ], "
195                                           "height = (int) [ 1, 8192 ]; "
196                                           "video/x-vp9,"
197                                           "width = (int) [ 1, 8192 ], "
198                                           "height = (int) [ 1, 8192 ]; "
199                                           "image/jpeg,"
200                                           "width = (int) [ 1, 8192 ], "
201                                           "height = (int) [ 1, 8192 ]; "
202                                           "video/x-jpeg,"
203                                           "width = (int) [ 1, 8192 ], "
204                                           "height = (int) [ 1, 8192 ]; "
205                                           ));
206
207 /* Local static functions */
208 static void gst_tizencamerasrc_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
209 static void gst_tizencamerasrc_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
210 static gboolean gst_tizencamerasrc_negotiate(GstBaseSrc *basesrc);
211 static gboolean gst_tizencamerasrc_src_start(GstBaseSrc *src);
212 static gboolean gst_tizencamerasrc_src_stop(GstBaseSrc *src);
213 static gboolean gst_tizencamerasrc_start(GstTizenCameraSrc *camerasrc);
214 static GstFlowReturn gst_tizencamerasrc_src_create(GstPushSrc *src, GstBuffer **buffer);
215 static GstFlowReturn gst_tizencamerasrc_read_preview(GstTizenCameraSrc *camerasrc, GstBuffer **buffer);
216 static GstStateChangeReturn gst_tizencamerasrc_change_state(GstElement *element, GstStateChange transition);
217 static GstCaps *gst_tizencamerasrc_get_caps(GstBaseSrc *src, GstCaps *filter);
218 static gboolean gst_tizencamerasrc_set_caps(GstBaseSrc *src, GstCaps *caps);
219 static gboolean gst_tizencamerasrc_get_caps_info(GstTizenCameraSrc *camerasrc, GstCaps *caps, guint *size);
220 static gboolean gst_tizencamerasrc_fill_ctrl_list(GstTizenCameraSrc *camerasrc);
221 static gboolean gst_tizencamerasrc_empty_ctrl_list(GstTizenCameraSrc *camerasrc);
222 static void gst_tizencamerasrc_finalize(GObject *object);
223 static gboolean gst_tizencamerasrc_get_timeinfo(GstTizenCameraSrc *camerasrc, GstBuffer *buffer);
224 static gboolean gst_tizencamerasrc_capture_start(GstTizenCameraSrc *camerasrc);
225 static gboolean gst_tizencamerasrc_capture_stop(GstTizenCameraSrc *camerasrc);
226 static void gst_tizencamerasrc_error_handler(GstTizenCameraSrc *camerasrc, int ret);
227 static GstBuffer *gst_tizencamerasrc_buffer_new(GstTizenCameraSrc *camerasrc, camera_buffer_s *buffer,
228   camera_metadata_s *meta, GstTizenCameraBufferType type, BufferControl *control, int stream_id);
229 static void gst_tizencamerasrc_buffer_finalize(GstTizenCameraBuffer *buffer);
230 static void gst_tizencamerasrc_set_video_format(GstTizenCameraSrc *camerasrc);
231 static void gst_tizencamerasrc_set_capture_format(GstTizenCameraSrc *camerasrc);
232
233 /* callbacks */
234 static int __camera_preview_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, void *user_data);
235 static int __camera_extra_preview_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, int stream_id, void *user_data);
236 static int __camera_video_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, void *user_data);
237 static int __camera_hal_message_callback(camera_message_s *message, void *user_data);
238
239 /* Util functions */
240 static gboolean __gst_tizencamerasrc_get_frame_size(int fourcc, int width, int height, unsigned int *outsize);
241 static gboolean __gst_tizencamerasrc_get_raw_pixel_info(int fourcc, camera_pixel_format_e *pix_format);
242 static gboolean __gst_tizencamerasrc_get_tbm_format(int pix_format, guint32 *tbm_format);
243 static GstCaps *__gst_tizencamerasrc_get_caps_from_buffer(camera_buffer_s *buffer);
244 static void __gst_tizencamerasrc_post_message_int(GstTizenCameraSrc *camerasrc, const char *msg_name, const char *field_name, int value);
245 static int __gst_tizencamerasrc_release_buffer(GstTizenCameraSrc *camerasrc, GstTizenCameraBufferType type, int index, int stream_id);
246
247 GST_IMPLEMENT_TIZENCAMERASRC_COLOR_BALANCE_METHODS(GstTizenCameraSrc, gst_tizencamera_src);
248 GST_IMPLEMENT_TIZENCAMERASRC_CONTROL_METHODS(GstTizenCameraSrc, gst_tizencamera_src);
249
250
251 /******************************************************************************
252  * Implementations
253  *******************************************************************************/
254 static GstBuffer *gst_tizencamerasrc_buffer_new(GstTizenCameraSrc *camerasrc, camera_buffer_s *buffer,
255   camera_metadata_s *meta, GstTizenCameraBufferType type, BufferControl *control, int stream_id)
256 {
257   int ret = CAMERA_ERROR_NONE;
258   gsize maxsize = 0;
259   gboolean is_tbm_used = FALSE;
260   gboolean is_delta_frame = FALSE;
261
262   GstTizenCameraBuffer *new_buffer = NULL;
263   GstMemory *memory = NULL;
264   GstStructure *structure_metadata = NULL;
265
266   if (!camerasrc || !buffer) {
267     GST_ERROR("NULL pointer %p %p", camerasrc, buffer);
268     return NULL;
269   }
270
271   if (!buffer->total_size) {
272     GST_ERROR_OBJECT(camerasrc, "requested buffer size is incorrect");
273     return NULL;
274   }
275
276   if (buffer->num_bos > 0)
277     is_tbm_used = TRUE;
278
279   GST_DEBUG_OBJECT(camerasrc, "index[%d] is_tbm[%d], is_delta[%d]",
280     buffer->index, is_tbm_used, is_delta_frame);
281
282   /* allocate new buffer */
283   new_buffer = g_new0(GstTizenCameraBuffer, 1);
284
285   new_buffer->type = type;
286   new_buffer->index = buffer->index;
287   new_buffer->stream_id = stream_id;
288   new_buffer->control = control;
289   new_buffer->buffer = gst_buffer_new();
290   if (!new_buffer->buffer) {
291     GST_ERROR_OBJECT(camerasrc, "new GstBuffer failed");
292     goto _BUFFER_NEW_FAILED;
293   }
294
295   if (meta) {
296     GST_DEBUG_OBJECT(camerasrc, "delta[%d], focus[%d], direction[%d], flip[%d], rotation[%d]",
297       meta->is_delta_frame, meta->focus_state, meta->facing_direction, meta->flip, meta->rotation);
298
299     is_delta_frame = (gboolean)meta->is_delta_frame;
300
301     if (camerasrc->buffer_quark != _DEFAULT_BUFFER_QUARK) {
302       structure_metadata = gst_structure_new("metadata",
303         "focus-state", G_TYPE_INT, meta->focus_state,
304         "facing-direction", G_TYPE_INT, meta->facing_direction,
305         "flip", G_TYPE_INT, meta->flip,
306         "rotation", G_TYPE_INT, meta->rotation,
307         NULL);
308       if (structure_metadata) {
309         GST_LOG_OBJECT(camerasrc, "new structure [%p]", structure_metadata);
310         gst_mini_object_set_qdata(GST_MINI_OBJECT_CAST(new_buffer->buffer),
311           camerasrc->buffer_quark, structure_metadata, (GDestroyNotify)gst_structure_free);
312       } else {
313         GST_WARNING_OBJECT(camerasrc, "failed to create structure for metadata");
314       }
315     }
316   }
317
318   if (is_delta_frame)
319     GST_BUFFER_FLAG_SET(new_buffer->buffer, GST_BUFFER_FLAG_DELTA_UNIT);
320   else
321     GST_BUFFER_FLAG_UNSET(new_buffer->buffer, GST_BUFFER_FLAG_DELTA_UNIT);
322
323   /* set timestamp info */
324   gst_tizencamerasrc_get_timeinfo(camerasrc, new_buffer->buffer);
325
326   if (is_tbm_used) {
327     GST_DEBUG_OBJECT(camerasrc, "TBM -> Tizen allocator");
328
329     if (camerasrc->is_encoded_format) {
330       /* create tizen memory for gst buffer with tbm bo */
331       memory = gst_tizen_allocator_alloc_bo(camerasrc->allocator,
332         &camerasrc->video_info,
333         buffer->bos[0],
334         (buffer->planes[0].bytesused > 0 ? buffer->planes[0].bytesused : buffer->planes[0].size),
335         (gpointer)new_buffer,
336         (GDestroyNotify)gst_tizencamerasrc_buffer_finalize);
337     } else {
338       /* create tbm surface from buffer */
339       new_buffer->t_surface = tbm_surface_internal_create_with_bos(&camerasrc->ts_info,
340         (tbm_bo *)buffer->bos, buffer->num_bos);
341       if (!new_buffer->t_surface) {
342         GST_ERROR_OBJECT(camerasrc, "tbm surface create failed");
343         goto _BUFFER_NEW_FAILED;
344       }
345
346       /* create tizen memory for gst buffer with tbm surface */
347       memory = gst_tizen_allocator_alloc_surface(camerasrc->allocator,
348         &camerasrc->video_info,
349         new_buffer->t_surface,
350         (gpointer)new_buffer,
351         (GDestroyNotify)gst_tizencamerasrc_buffer_finalize);
352     }
353   } else {
354     GST_DEBUG_OBJECT(camerasrc, "NOT TBM - size %u", buffer->total_size);
355
356     if (camerasrc->pix_format == CAMERA_PIXEL_FORMAT_H264 ||
357         camerasrc->pix_format == CAMERA_PIXEL_FORMAT_MJPEG ||
358         camerasrc->pix_format == CAMERA_PIXEL_FORMAT_VP8 ||
359         camerasrc->pix_format == CAMERA_PIXEL_FORMAT_VP9) {
360       /* memory copy for h264/mjpeg/vp8/vp9 stream */
361       int i = 0;
362       uint32_t total_size = 0;
363       new_buffer->copied_data = g_malloc(buffer->total_size);
364       for (i = 0 ; i < buffer->num_planes ; i++) {
365         memcpy(new_buffer->copied_data + total_size, buffer->planes[i].data, buffer->planes[i].size);
366         total_size += buffer->planes[i].size;
367       }
368     } else {
369       new_buffer->copied_data = g_memdup2(buffer->planes[0].data, buffer->total_size);
370     }
371
372     ret = __gst_tizencamerasrc_release_buffer(camerasrc, type, buffer->index, stream_id);
373     if (ret != CAMERA_ERROR_NONE) {
374       GST_ERROR_OBJECT(camerasrc, "release buffer failed[0x%x]", ret);
375       goto _BUFFER_NEW_FAILED;
376     }
377
378     memory = gst_memory_new_wrapped(0,
379       new_buffer->copied_data,
380       buffer->total_size,
381       0,
382       buffer->total_size,
383       (gpointer)new_buffer,
384       (GDestroyNotify)gst_tizencamerasrc_buffer_finalize);
385   }
386
387   if (!memory) {
388     GST_ERROR_OBJECT(camerasrc, "GstMemory failed");
389     goto _BUFFER_NEW_FAILED;
390   }
391
392   new_buffer->camerasrc = gst_object_ref(GST_OBJECT(camerasrc));
393   gst_buffer_append_memory(new_buffer->buffer, memory);
394
395   GST_DEBUG_OBJECT(camerasrc, "memory[%p][%"G_GSIZE_FORMAT"], buffer[%p,%p][%"G_GSIZE_FORMAT"], buffer max[%"G_GSIZE_FORMAT"]",
396     memory, gst_memory_get_sizes(memory, NULL, NULL),
397     new_buffer, new_buffer->buffer,
398     gst_buffer_get_sizes(new_buffer->buffer, NULL, &maxsize),
399     maxsize);
400
401   return new_buffer->buffer;
402
403 _BUFFER_NEW_FAILED:
404   if (new_buffer) {
405     if (new_buffer->t_surface)
406       tbm_surface_destroy(new_buffer->t_surface);
407     if (new_buffer->buffer)
408       gst_buffer_unref(new_buffer->buffer);
409     g_free(new_buffer);
410   }
411
412   return NULL;
413 }
414
415
416 static void gst_tizencamerasrc_buffer_finalize(GstTizenCameraBuffer *buffer)
417 {
418   int ret = CAMERA_ERROR_NONE;
419   GstTizenCameraSrc *camerasrc = NULL;
420
421   if (!buffer) {
422     GST_ERROR("NULL buffer");
423     return;
424   }
425
426   GST_DEBUG("type[%d], index[%d], stream_id[%d], copied_data[%p]",
427     buffer->type, buffer->index, buffer->stream_id, buffer->copied_data);
428
429   camerasrc = buffer->camerasrc;
430
431   /* "copied_data != NULL" means that TBM is not used for buffer
432      and no need to call function to release buffer to HAL. */
433   if (buffer->copied_data) {
434     g_free(buffer->copied_data);
435     buffer->copied_data = NULL;
436   } else {
437     ret = __gst_tizencamerasrc_release_buffer(camerasrc, buffer->type, buffer->index, buffer->stream_id);
438     if (ret != CAMERA_ERROR_NONE)
439       GST_WARNING_OBJECT(camerasrc, "release buffer failed[0x%x]", ret);
440   }
441
442   g_mutex_lock(&buffer->control->lock);
443
444   buffer->control->live_buffers--;
445   GST_LOG_OBJECT(camerasrc, "type[%d] live buffers %d", buffer->type, buffer->control->live_buffers);
446   g_cond_broadcast(&buffer->control->cond);
447
448   g_mutex_unlock(&buffer->control->lock);
449
450   if (buffer->t_surface) {
451     tbm_surface_destroy(buffer->t_surface);
452     buffer->t_surface = NULL;
453   }
454
455   gst_object_unref(camerasrc);
456   g_free(buffer);
457
458   GST_DEBUG("done");
459
460   return;
461 }
462
463
464 static void gst_tizencamerasrc_set_video_format(GstTizenCameraSrc *camerasrc)
465 {
466   int ret = CAMERA_ERROR_NONE;
467   camera_format_s set_format;
468
469   if (!camerasrc) {
470     GST_ERROR("NULL handle");
471     return;
472   }
473
474   CLEAR(set_format);
475
476   set_format.stream_format = camerasrc->pix_format;
477   set_format.stream_resolution.width = camerasrc->video_width;
478   set_format.stream_resolution.height = camerasrc->video_height;
479   set_format.stream_fps = camerasrc->video_fps;
480
481   switch (camerasrc->rotate) {
482   case 90:
483     set_format.stream_rotation = CAMERA_ROTATION_90;
484     break;
485   case 180:
486     set_format.stream_rotation = CAMERA_ROTATION_180;
487     break;
488   case 270:
489     set_format.stream_rotation = CAMERA_ROTATION_270;
490     break;
491   case 0:
492   default:
493     set_format.stream_rotation = CAMERA_ROTATION_0;
494     break;
495   }
496
497   if (!__gst_tizencamerasrc_get_raw_pixel_info(camerasrc->cap_fourcc, &set_format.capture_format)) {
498     GST_WARNING_OBJECT(camerasrc, "__gst_tizencamerasrc_get_raw_pixel_info failed, set default JPEG");
499     set_format.capture_format = CAMERA_PIXEL_FORMAT_JPEG;
500   }
501   set_format.capture_resolution.width = camerasrc->cap_width;
502   set_format.capture_resolution.height = camerasrc->cap_height;
503   set_format.capture_quality = (uint32_t)camerasrc->cap_quality;
504
505   GST_INFO_OBJECT(camerasrc, "video resolution %dx%d, fps %d, format %d, rotation %d",
506     set_format.stream_resolution.width, set_format.stream_resolution.height,
507     set_format.stream_fps, set_format.stream_format, set_format.stream_rotation);
508
509   ret = hal_camera_set_video_stream_format(camerasrc->hal_handle, &set_format);
510   if (ret != CAMERA_ERROR_NONE)
511     GST_ERROR_OBJECT(camerasrc, "set video stream failed 0x%x", ret);
512
513   GST_INFO_OBJECT(camerasrc, "done");
514
515   return;
516 }
517
518
519 static void gst_tizencamerasrc_set_capture_format(GstTizenCameraSrc *camerasrc)
520 {
521   int ret = CAMERA_ERROR_NONE;
522   GstState state = GST_STATE_NULL;
523   GstStateChangeReturn gst_ret;
524   camera_format_s stream_format;
525
526   if (!camerasrc) {
527     GST_ERROR("NULL handle");
528     return;
529   }
530
531   gst_ret = gst_element_get_state((GstElement *)camerasrc, &state, NULL, GST_CLOCK_TIME_NONE);
532   if (gst_ret == GST_STATE_CHANGE_FAILURE || gst_ret == GST_STATE_CHANGE_ASYNC) {
533     GST_WARNING_OBJECT(camerasrc, "failed to get state : %d", gst_ret);
534     return;
535   }
536
537   GST_INFO_OBJECT(camerasrc, "Set capture resolution %dx%d - state %d",
538     camerasrc->cap_width_tmp, camerasrc->cap_height_tmp, state);
539
540   /* check state */
541   if (state <= GST_STATE_READY) {
542     GST_INFO_OBJECT(camerasrc, "[state %d] it will be set later", state);
543     goto _SET_DONE;
544   }
545
546   /* preview capture resolution */
547   ret = hal_camera_get_preview_stream_format(camerasrc->hal_handle, &stream_format);
548   if (ret != CAMERA_ERROR_NONE) {
549     GST_ERROR_OBJECT(camerasrc, "failed to get stream format for preview");
550     return;
551   }
552
553   if (!__gst_tizencamerasrc_get_raw_pixel_info(camerasrc->cap_fourcc, &stream_format.capture_format)) {
554     GST_WARNING_OBJECT(camerasrc, "_gst_tizencamerasrc_get_raw_pixel_info failed, set default JPEG");
555     stream_format.capture_format = CAMERA_PIXEL_FORMAT_JPEG;
556   }
557   stream_format.capture_resolution.width = camerasrc->cap_width_tmp;
558   stream_format.capture_resolution.height = camerasrc->cap_height_tmp;
559
560   ret = hal_camera_set_preview_stream_format(camerasrc->hal_handle, &stream_format);
561   if (ret != CAMERA_ERROR_NONE) {
562     GST_ERROR_OBJECT(camerasrc, "failed to set stream format for preview 0x%x", ret);
563     return;
564   }
565
566   /* video capture resolution */
567   if (camerasrc->recording_hint) {
568     ret = hal_camera_get_video_stream_format(camerasrc->hal_handle, &stream_format);
569     if (ret != CAMERA_ERROR_NONE) {
570       GST_ERROR_OBJECT(camerasrc, "failed to get stream format for video");
571       return;
572     }
573
574     stream_format.capture_resolution.width = camerasrc->cap_width_tmp;
575     stream_format.capture_resolution.height = camerasrc->cap_height_tmp;
576
577     ret = hal_camera_set_video_stream_format(camerasrc->hal_handle, &stream_format);
578     if (ret != CAMERA_ERROR_NONE) {
579       GST_ERROR_OBJECT(camerasrc, "failed to set stream format for video 0x%x", ret);
580       return;
581     }
582   }
583
584 _SET_DONE:
585   if (ret == CAMERA_ERROR_NONE) {
586     camerasrc->cap_width = camerasrc->cap_width_tmp;
587     camerasrc->cap_height = camerasrc->cap_height_tmp;
588   }
589
590   GST_INFO_OBJECT(camerasrc, "done");
591
592   return;
593 }
594
595
596 static void gst_tizencamerasrc_error_handler(GstTizenCameraSrc *camerasrc, int ret)
597 {
598   if (!camerasrc) {
599     GST_ERROR_OBJECT(camerasrc, "NULL camerasrc");
600     return;
601   }
602
603   switch (ret) {
604   case CAMERA_ERROR_NONE:
605     GST_WARNING_OBJECT(camerasrc, "NO ERROR");
606     break;
607   case CAMERA_ERROR_INTERNAL:
608     GST_ELEMENT_ERROR(camerasrc, RESOURCE, FAILED, ("IO control error"), GST_ERROR_SYSTEM);
609     break;
610   case CAMERA_ERROR_DEVICE_OPEN:
611     GST_ELEMENT_ERROR(camerasrc, RESOURCE, OPEN_READ_WRITE, ("camera open failed"), GST_ERROR_SYSTEM);
612     break;
613   case CAMERA_ERROR_DEVICE_BUSY:
614     GST_ELEMENT_ERROR(camerasrc, RESOURCE, BUSY, ("camera device busy"), GST_ERROR_SYSTEM);
615     break;
616   case CAMERA_ERROR_DEVICE_NOT_FOUND:
617     GST_ELEMENT_ERROR(camerasrc, RESOURCE, NOT_FOUND, ("camera device not found"), GST_ERROR_SYSTEM);
618     break;
619   case CAMERA_ERROR_DEVICE_UNAVAILABLE:
620     GST_ELEMENT_ERROR(camerasrc, RESOURCE, OPEN_READ, ("camera device unavailable"), GST_ERROR_SYSTEM);
621     break;
622   case CAMERA_ERROR_DEVICE_TIME_OUT:
623     GST_ELEMENT_ERROR(camerasrc, RESOURCE, TOO_LAZY, ("Time Out"), GST_ERROR_SYSTEM);
624     break;
625   case CAMERA_ERROR_DEVICE_NOT_SUPPORTED:
626     GST_ELEMENT_ERROR(camerasrc, RESOURCE, SETTINGS, ("Not supported"), GST_ERROR_SYSTEM);
627     break;
628   case CAMERA_ERROR_OUT_OF_MEMORY:
629     GST_ELEMENT_ERROR(camerasrc, RESOURCE, SETTINGS, ("memory allocation failed"), GST_ERROR_SYSTEM);
630     break;
631   case CAMERA_ERROR_PERMISSION_DENIED:
632     GST_ELEMENT_ERROR(camerasrc, RESOURCE, FAILED, ("Security service failed"), GST_ERROR_SYSTEM);
633     break;
634   case CAMERA_ERROR_DEVICE_READ:
635     GST_ELEMENT_ERROR(camerasrc, RESOURCE, READ, ("camera read failed"), GST_ERROR_SYSTEM);
636     break;
637   case CAMERA_ERROR_DEVICE_WRITE:
638     GST_ELEMENT_ERROR(camerasrc, RESOURCE, WRITE, ("camera write failed"), GST_ERROR_SYSTEM);
639     break;
640   default:
641     GST_ELEMENT_ERROR(camerasrc, RESOURCE, SEEK, (("General video device error[ret=%x]"), ret), GST_ERROR_SYSTEM);
642     break;
643   }
644
645   return;
646 }
647
648
649 /* VOID:OBJECT,OBJECT,OBJECT (generated by 'glib-genmarshal') */
650 #define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
651 static void
652 gst_tizencamerasrc_VOID__OBJECT_OBJECT_OBJECT(GClosure *closure,
653   GValue *return_value G_GNUC_UNUSED,
654   guint n_param_values,
655   const GValue *param_values,
656   gpointer invocation_hint G_GNUC_UNUSED,
657   gpointer marshal_data)
658 {
659   typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT)(gpointer data1,
660     gpointer arg_1,
661     gpointer arg_2,
662     gpointer arg_3,
663     gpointer data2);
664
665   register GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT callback;
666   register GCClosure *cc = (GCClosure *)closure;
667   register gpointer data1;
668   register gpointer data2;
669
670   g_return_if_fail(n_param_values == 4);
671
672   if (G_CCLOSURE_SWAP_DATA(closure)) {
673     data1 = closure->data;
674     data2 = g_value_peek_pointer(param_values + 0);
675   } else {
676     data1 = g_value_peek_pointer(param_values + 0);
677     data2 = closure->data;
678   }
679
680   callback = (GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT)(marshal_data ? marshal_data : cc->callback);
681
682   callback(data1,
683     g_marshal_value_peek_object(param_values + 1),
684     g_marshal_value_peek_object(param_values + 2),
685     g_marshal_value_peek_object(param_values + 3),
686     data2);
687
688   return;
689 }
690
691 static void
692 gst_tizencamerasrc_VOID__OBJECT_VIDEO_STREAM(GClosure *closure,
693   GValue *return_value,
694   guint n_param_values,
695   const GValue *param_values,
696   gpointer invocation_hint,
697   gpointer marshal_data)
698 {
699   typedef void (*GMarshalFunc_VOID__OBJECT_VIDEO_STREAM)(gpointer data1,
700     gpointer arg,
701     gpointer data2);
702   register GMarshalFunc_VOID__OBJECT_VIDEO_STREAM callback;
703   register GCClosure *cc = (GCClosure *) closure;
704   register gpointer data1, data2;
705
706   g_return_if_fail (n_param_values == 2);
707
708   if (G_CCLOSURE_SWAP_DATA(closure)) {
709     data1 = closure->data;
710     data2 = g_value_peek_pointer(param_values + 0);
711   } else {
712     data1 = g_value_peek_pointer(param_values + 0);
713     data2 = closure->data;
714   }
715
716   callback = (GMarshalFunc_VOID__OBJECT_VIDEO_STREAM)(marshal_data ? marshal_data : cc->callback);
717
718   callback(data1,
719     g_marshal_value_peek_object(param_values + 1),
720     data2);
721 }
722
723 static void
724 gst_tizencamerasrc_VOID__OBJECT_EXTRA_PREVIEW_STREAM(GClosure *closure,
725   GValue *return_value G_GNUC_UNUSED,
726   guint n_param_values,
727   const GValue *param_values,
728   gpointer invocation_hint G_GNUC_UNUSED,
729   gpointer marshal_data)
730 {
731   typedef void (*GMarshalFunc_VOID__OBJECT_EXTRA_PREVIEW_STREAM)(gpointer data1,
732     gpointer arg_1,
733     gpointer arg_2,
734     gpointer data2);
735
736   register GMarshalFunc_VOID__OBJECT_EXTRA_PREVIEW_STREAM callback;
737   register GCClosure *cc = (GCClosure *)closure;
738   register gpointer data1;
739   register gpointer data2;
740
741   g_return_if_fail(n_param_values == 3);
742
743   if (G_CCLOSURE_SWAP_DATA(closure)) {
744     data1 = closure->data;
745     data2 = g_value_peek_pointer(param_values + 0);
746   } else {
747     data1 = g_value_peek_pointer(param_values + 0);
748     data2 = closure->data;
749   }
750
751   callback = (GMarshalFunc_VOID__OBJECT_EXTRA_PREVIEW_STREAM)(marshal_data ? marshal_data : cc->callback);
752
753   callback(data1,
754     g_marshal_value_peek_object(param_values + 1),
755     g_marshal_value_peek_object(param_values + 2),
756     data2);
757
758   return;
759 }
760
761 /* use following BOILERPLATE MACRO as _get_type entry */
762 G_DEFINE_TYPE_WITH_CODE(GstTizenCameraSrc, gst_tizencamerasrc, GST_TYPE_PUSH_SRC,
763   G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, gst_tizencamerasrc_uri_handler_init)
764   G_IMPLEMENT_INTERFACE(GST_TYPE_CAMERA_CONTROL, gst_tizencamera_src_control_interface_init)
765   G_IMPLEMENT_INTERFACE(GST_TYPE_COLOR_BALANCE, gst_tizencamera_src_color_balance_interface_init));
766
767 static int __camera_hal_message_callback(camera_message_s *message, void *user_data)
768 {
769   GstTizenCameraSrc *camerasrc = NULL;
770
771   if (message == NULL || user_data == NULL) {
772     GST_ERROR("message callback error %p %p", message, user_data);
773     return FALSE;
774   }
775
776   camerasrc = (GstTizenCameraSrc *)user_data;
777
778   switch (message->type) {
779   case CAMERA_MESSAGE_TYPE_FOCUS_CHANGED:
780     GST_INFO_OBJECT(camerasrc, "focus state %d", message->focus_state);
781     __gst_tizencamerasrc_post_message_int(camerasrc, "camerasrc-AF", "focus-state", message->focus_state);
782     break;
783   case CAMERA_MESSAGE_TYPE_CAPTURED:
784     GST_INFO_OBJECT(camerasrc, "CAPTURED");
785     break;
786   case CAMERA_MESSAGE_TYPE_HDR_PROGRESS:
787     GST_INFO_OBJECT(camerasrc, "HDR progress %d", message->hdr_progress);
788     break;
789   case CAMERA_MESSAGE_TYPE_ERROR:
790     GST_ERROR_OBJECT(camerasrc, "error from camera HAL 0x%x", message->error_code);
791     camerasrc->hal_error_code = message->error_code;
792     gst_tizencamerasrc_error_handler(camerasrc, camerasrc->hal_error_code);
793     g_cond_broadcast(&camerasrc->preview_control.cond);
794     break;
795   default:
796     GST_ERROR_OBJECT(camerasrc, "unknown type message %d", message->type);
797     return FALSE;
798   }
799
800   return TRUE;
801 }
802
803
804 static int __camera_preview_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, void *user_data)
805 {
806   GstTizenCameraSrc *camerasrc = NULL;
807   GstBuffer *gst_buffer = NULL;
808
809   if (!buffer || !user_data) {
810     GST_ERROR("preview callback error %p %p", buffer, user_data);
811     return FALSE;
812   }
813
814   camerasrc = (GstTizenCameraSrc *)user_data;
815
816   g_mutex_lock(&camerasrc->preview_control.lock);
817
818   if (camerasrc->preview_control.running == FALSE ||
819     camerasrc->live_buffer_check < camerasrc->preview_control.live_buffers) {
820     hal_camera_release_preview_buffer(camerasrc->hal_handle, buffer->index);
821     GST_WARNING_OBJECT(camerasrc, "Skip buffer[%d] running %d, Live buffer[%d/%d]",
822       buffer->index, camerasrc->preview_control.running,
823       camerasrc->preview_control.live_buffers, camerasrc->live_buffer_check);
824     goto _PREVIEW_FRAME_CB_DONE;
825   }
826
827   /* create new buffer */
828   gst_buffer = gst_tizencamerasrc_buffer_new(camerasrc, buffer, meta,
829     BUFFER_TYPE_PREVIEW, &camerasrc->preview_control, -1);
830   if (!gst_buffer) {
831     GST_ERROR_OBJECT(camerasrc, "new buffer allocation failed. size %u", buffer->total_size);
832     hal_camera_release_preview_buffer(camerasrc->hal_handle, buffer->index);
833     goto _PREVIEW_FRAME_CB_DONE;
834   }
835
836   if (camerasrc->preview_control.is_first_frame) {
837     camerasrc->preview_control.is_first_frame = FALSE;
838     camerasrc->preview_control.is_tbm_used = (buffer->num_bos > 0);
839     GST_WARNING_OBJECT(camerasrc, "TBM in buffer[%d] (num_bos[%u])",
840       camerasrc->preview_control.is_tbm_used, buffer->num_bos);
841   }
842
843   camerasrc->preview_control.live_buffers++;
844   GST_DEBUG_OBJECT(camerasrc, "%p [size %u][preview_live_buffers %d]",
845     gst_buffer, buffer->total_size, camerasrc->preview_control.live_buffers);
846
847   /* add new buffer to preview buffer list */
848   g_queue_push_tail(camerasrc->preview_buffer_list, gst_buffer);
849   g_cond_broadcast(&camerasrc->preview_control.cond);
850
851 _PREVIEW_FRAME_CB_DONE:
852   g_mutex_unlock(&camerasrc->preview_control.lock);
853
854   GST_DEBUG_OBJECT(camerasrc, "done");
855
856   return TRUE;
857 }
858
859
860 static int __camera_extra_preview_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, int stream_id, void *user_data)
861 {
862   GstTizenCameraSrc *camerasrc = NULL;
863   GstSample *gst_sample = NULL;
864   GstBuffer *gst_buffer = NULL;
865
866   if (!buffer || !user_data || stream_id < 0 || stream_id >= EXTRA_PREVIEW_STREAM_MAX) {
867     GST_ERROR("invalid param[%p,%p,%d]", buffer, user_data, stream_id);
868     return FALSE;
869   }
870
871   camerasrc = (GstTizenCameraSrc *)user_data;
872
873   g_mutex_lock(&camerasrc->extra_preview_control.lock);
874
875   if (camerasrc->preview_control.running == FALSE) {
876     GST_WARNING("Skip buffer[stream_id:%d,i:%d]", stream_id, buffer->index);
877     goto _EXTRA_PREVIEW_FRAME_CB_DONE;
878   }
879
880   if (!camerasrc->extra_caps[stream_id])
881     camerasrc->extra_caps[stream_id] = __gst_tizencamerasrc_get_caps_from_buffer(buffer);
882
883   if (!camerasrc->extra_caps[stream_id]) {
884     GST_ERROR("extra caps failed for stream id[%d]", stream_id);
885     goto _EXTRA_PREVIEW_FRAME_CB_DONE;
886   }
887
888   /* create new buffer and sample */
889   gst_buffer = gst_tizencamerasrc_buffer_new(camerasrc, buffer, meta,
890     BUFFER_TYPE_EXTRA_PREVIEW, &camerasrc->extra_preview_control, stream_id);
891   if (!gst_buffer) {
892     GST_ERROR("new buffer allocation failed. size %u", buffer->total_size);
893     goto _EXTRA_PREVIEW_FRAME_CB_DONE;
894   }
895
896   gst_sample = gst_sample_new(gst_buffer, camerasrc->extra_caps[stream_id], NULL, NULL);
897   if (!gst_sample) {
898     GST_ERROR("new sample failed for stream_id[%d]", stream_id);
899     goto _EXTRA_PREVIEW_FRAME_CB_DONE;
900   }
901
902   camerasrc->extra_preview_control.live_buffers++;
903
904 _EXTRA_PREVIEW_FRAME_CB_DONE:
905   g_mutex_unlock(&camerasrc->extra_preview_control.lock);
906
907   if (gst_sample) {
908     g_signal_emit(G_OBJECT(camerasrc),
909       gst_tizencamerasrc_signals[SIGNAL_EXTRA_PREVIEW_STREAM_CB],
910       0,
911       stream_id,
912       gst_sample);
913   } else {
914     hal_camera_release_extra_preview_buffer(camerasrc->hal_handle, stream_id, buffer->index);
915   }
916
917   if (gst_buffer)
918     gst_buffer_unref(gst_buffer);
919
920   GST_DEBUG("done");
921
922   return TRUE;
923 }
924
925
926 static int __camera_video_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, void *user_data)
927 {
928   GstTizenCameraSrc *camerasrc = NULL;
929   GstBuffer *gst_buffer = NULL;
930   GstSample *gst_sample = NULL;
931
932   if (!buffer || !user_data) {
933     GST_ERROR("video callback error %p %p", buffer, user_data);
934     return FALSE;
935   }
936
937   camerasrc = (GstTizenCameraSrc *)user_data;
938
939   g_mutex_lock(&camerasrc->video_control.lock);
940
941   if (camerasrc->video_control.running == FALSE ||
942     camerasrc->live_buffer_check < camerasrc->video_control.live_buffers) {
943     GST_WARNING("Skip buffer[%d] running %d, Live buffer[%d/%d]",
944       buffer->index, camerasrc->video_control.running,
945       camerasrc->video_control.live_buffers, camerasrc->live_buffer_check);
946     goto _VIDEO_FRAME_CB_DONE;
947   }
948
949   /* create new buffer and sample */
950   gst_buffer = gst_tizencamerasrc_buffer_new(camerasrc, buffer, meta,
951     BUFFER_TYPE_VIDEO, &camerasrc->video_control, -1);
952   if (!gst_buffer) {
953     GST_ERROR("new buffer allocation failed. size %u", buffer->total_size);
954     goto _VIDEO_FRAME_CB_DONE;
955   }
956
957   if (!camerasrc->video_caps)
958     camerasrc->video_caps = __gst_tizencamerasrc_get_caps_from_buffer(buffer);
959
960   if (!camerasrc->video_caps) {
961     GST_ERROR("video caps failed");
962     goto _VIDEO_FRAME_CB_DONE;
963   }
964
965   gst_sample = gst_sample_new(gst_buffer, camerasrc->video_caps, NULL, NULL);
966   if (!gst_sample) {
967     GST_ERROR("new sample failed for buffer index[%d]", buffer->index);
968     goto _VIDEO_FRAME_CB_DONE;
969   }
970
971   camerasrc->video_control.live_buffers++;
972
973   GST_DEBUG_OBJECT(camerasrc, "index %d, %p, %p [size total %u][video_live_buffers %d]",
974     buffer->index, gst_sample, gst_buffer, buffer->total_size, camerasrc->video_control.live_buffers);
975
976 _VIDEO_FRAME_CB_DONE:
977   g_mutex_unlock(&camerasrc->video_control.lock);
978
979   if (gst_sample) {
980     g_signal_emit(G_OBJECT(camerasrc),
981       gst_tizencamerasrc_signals[SIGNAL_VIDEO_STREAM_CB],
982       0,
983       gst_sample);
984   } else {
985     hal_camera_release_video_buffer(camerasrc->hal_handle, buffer->index);
986   }
987
988   if (gst_buffer)
989     gst_buffer_unref(gst_buffer);
990
991   GST_DEBUG_OBJECT(camerasrc, "done");
992
993   return TRUE;
994 }
995
996
997 static GstVideoFormat __get_gst_video_format(camera_pixel_format_e pixel_format)
998 {
999   switch (pixel_format) {
1000   case CAMERA_PIXEL_FORMAT_NV12:
1001     return GST_VIDEO_FORMAT_NV12;
1002   case CAMERA_PIXEL_FORMAT_NV21:
1003     return GST_VIDEO_FORMAT_NV21;
1004   case CAMERA_PIXEL_FORMAT_I420:
1005     return GST_VIDEO_FORMAT_I420;
1006   case CAMERA_PIXEL_FORMAT_YV12:
1007     return GST_VIDEO_FORMAT_YV12;
1008   case CAMERA_PIXEL_FORMAT_YUYV:
1009     return GST_VIDEO_FORMAT_YUY2;
1010   case CAMERA_PIXEL_FORMAT_UYVY:
1011     return GST_VIDEO_FORMAT_UYVY;
1012   case CAMERA_PIXEL_FORMAT_H264:
1013     /* fall through */
1014   case CAMERA_PIXEL_FORMAT_MJPEG:
1015     /* fall through */
1016   case CAMERA_PIXEL_FORMAT_VP8:
1017     /* fall through */
1018   case CAMERA_PIXEL_FORMAT_VP9:
1019     return GST_VIDEO_FORMAT_ENCODED;
1020   default:
1021     GST_ERROR("unknown pixel format %d", pixel_format);
1022     return -1;
1023   }
1024 }
1025
1026 static GstSample *__create_buffer_sample(GstTizenCameraSrc *camerasrc, camera_buffer_s *cam_buffer)
1027 {
1028   GstBuffer *gst_buffer = NULL;
1029   GstCaps *caps = NULL;
1030   GstSample *sample = NULL;
1031   const gchar *string_fourcc = NULL;
1032   const gchar *media_type = NULL;
1033
1034   if (!camerasrc) {
1035     GST_ERROR("NULL handle");
1036     return NULL;
1037   }
1038
1039   if (!cam_buffer) {
1040     GST_ERROR_OBJECT(camerasrc, "NULL buffer");
1041     return NULL;
1042   }
1043
1044   gst_buffer = gst_buffer_new_wrapped_full(0,
1045     cam_buffer->planes[0].data,
1046     cam_buffer->planes[0].size,
1047     0,
1048     cam_buffer->planes[0].bytesused,
1049     NULL, NULL);
1050   if (!gst_buffer) {
1051     GST_ERROR_OBJECT(camerasrc, "failed to allocate gst buffer for %p", cam_buffer);
1052     return NULL;
1053   }
1054
1055   switch (cam_buffer->format) {
1056   case CAMERA_PIXEL_FORMAT_JPEG:
1057     /* fall through */
1058   case CAMERA_PIXEL_FORMAT_MJPEG:
1059     media_type = "image/jpeg";
1060     break;
1061   case CAMERA_PIXEL_FORMAT_H264:
1062     media_type = "video/x-h264";
1063     break;
1064   case CAMERA_PIXEL_FORMAT_VP8:
1065     media_type = "video/x-vp8";
1066     break;
1067   case CAMERA_PIXEL_FORMAT_VP9:
1068     media_type = "video/x-vp9";
1069     break;
1070   default:
1071     media_type = "video/x-raw";
1072     string_fourcc = gst_video_format_to_string(__get_gst_video_format(cam_buffer->format));
1073     if (!string_fourcc) {
1074       GST_WARNING_OBJECT(camerasrc, "failed to get string_fourcc[%d]", cam_buffer->format);
1075       goto _CREATE_BUFFER_SAMPLE_DONE;
1076     }
1077     break;
1078   }
1079
1080   caps = gst_caps_new_simple(media_type,
1081     "width", G_TYPE_INT, cam_buffer->resolution.width,
1082     "height", G_TYPE_INT, cam_buffer->resolution.height,
1083     NULL);
1084   if (!caps) {
1085     GST_ERROR_OBJECT(camerasrc, "sample caps creation failed for[%s]", media_type);
1086     goto _CREATE_BUFFER_SAMPLE_DONE;
1087   }
1088
1089   if (string_fourcc) {
1090     gst_caps_set_simple(caps,
1091       "format", G_TYPE_STRING, string_fourcc,
1092       NULL);
1093   }
1094
1095   sample = gst_sample_new(gst_buffer, caps, NULL, NULL);
1096   if (!sample) {
1097     GST_ERROR_OBJECT(camerasrc, "buffer sample1 creation failed");
1098     goto _CREATE_BUFFER_SAMPLE_DONE;
1099   }
1100
1101 _CREATE_BUFFER_SAMPLE_DONE:
1102   if (gst_buffer)
1103     gst_buffer_unref(gst_buffer);
1104   if (caps)
1105     gst_caps_unref(caps);
1106
1107   GST_INFO_OBJECT(camerasrc, "sample %p - format %d, %dx%d",
1108     sample, cam_buffer->format, cam_buffer->resolution.width, cam_buffer->resolution.height);
1109
1110   return sample;
1111 }
1112
1113
1114 static int _camera_capture_cb(camera_buffer_s *main, camera_buffer_s *postview, camera_buffer_s *thumbnail, void *user_data)
1115 {
1116   GstTizenCameraSrc *camerasrc = NULL;
1117   GstSample *buf_sample1 = NULL;
1118   GstSample *buf_sample2 = NULL;
1119   GstSample *buf_sample3 = NULL;
1120
1121   if (!main || !user_data) {
1122     GST_ERROR("capture callback error %p %p", main, user_data);
1123     return FALSE;
1124   }
1125
1126   camerasrc = (GstTizenCameraSrc *)user_data;
1127
1128   buf_sample1 = __create_buffer_sample(camerasrc, main);
1129   if (!buf_sample1) {
1130     GST_ERROR_OBJECT(camerasrc, "buffer sample1 creation failed");
1131     return FALSE;
1132   }
1133
1134   buf_sample2 = __create_buffer_sample(camerasrc, postview);
1135   if (!buf_sample2)
1136     GST_WARNING_OBJECT(camerasrc, "No sample for postview");
1137
1138   buf_sample3 = __create_buffer_sample(camerasrc, thumbnail);
1139   if (!buf_sample3)
1140     GST_WARNING_OBJECT(camerasrc, "No sample for thumbnail");
1141
1142   GST_INFO_OBJECT(camerasrc, "CALL: capture callback");
1143
1144   g_signal_emit(G_OBJECT(camerasrc),
1145     gst_tizencamerasrc_signals[SIGNAL_STILL_CAPTURE],
1146     0,
1147     buf_sample1,
1148     buf_sample2,
1149     buf_sample3);
1150
1151   GST_INFO_OBJECT(camerasrc, "RETURN: capture callback");
1152
1153   return TRUE;
1154 }
1155
1156
1157 static gboolean gst_tizencamerasrc_create(GstTizenCameraSrc *camerasrc)
1158 {
1159   int ret = 0;
1160
1161   if (!camerasrc->hal_handle) {
1162     GST_ERROR_OBJECT(camerasrc, "no camera HAL interface handle");
1163     gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_DEVICE_NOT_FOUND);
1164     return FALSE;
1165   }
1166
1167   if (camerasrc->device_name) {
1168     GST_INFO_OBJECT(camerasrc, "open device - device name [%s]", camerasrc->device_name);
1169     ret = hal_camera_open_device_ext(camerasrc->hal_handle, camerasrc->device_name);
1170   } else {
1171     GST_INFO_OBJECT(camerasrc, "open device - camera id [%d]", camerasrc->camera_id);
1172     ret = hal_camera_open_device(camerasrc->hal_handle, camerasrc->camera_id);
1173   }
1174
1175   if (ret != CAMERA_ERROR_NONE) {
1176     GST_ERROR_OBJECT(camerasrc, "device open failed 0x%08X", ret);
1177     gst_tizencamerasrc_error_handler(camerasrc, ret);
1178     return FALSE;
1179   }
1180
1181   if (!gst_tizencamerasrc_fill_ctrl_list(camerasrc))
1182     GST_WARNING_OBJECT(camerasrc, "Can't fill v4l2 control list.");
1183
1184   GST_INFO_OBJECT(camerasrc, "DONE");
1185
1186   return TRUE;
1187 }
1188
1189
1190 static gboolean gst_tizencamerasrc_destroy(GstTizenCameraSrc *camerasrc)
1191 {
1192   int ret = CAMERA_ERROR_NONE;
1193
1194   GST_INFO_OBJECT(camerasrc, "ENTERED");
1195
1196   if (camerasrc->hal_handle == NULL) {
1197     GST_ERROR_OBJECT(camerasrc, "not initialized");
1198     return FALSE;
1199   }
1200
1201   /* camera hal interface close device */
1202   GST_INFO_OBJECT(camerasrc, "ENTERED");
1203
1204   ret = hal_camera_close_device(camerasrc->hal_handle);
1205   if (ret != CAMERA_ERROR_NONE) {
1206     GST_ERROR_OBJECT(camerasrc, "hal_camera_close_device failed 0x%x", ret);
1207     return FALSE;
1208   }
1209
1210   /* Empty control list */
1211   gst_tizencamerasrc_empty_ctrl_list(camerasrc);
1212
1213   GST_INFO_OBJECT(camerasrc, "LEAVE");
1214
1215   return TRUE;
1216 }
1217
1218
1219 static gboolean gst_tizencamerasrc_fill_ctrl_list(GstTizenCameraSrc *camerasrc)
1220 {
1221   int n = 0;
1222   GstTizenCameraSrcCommand color_balance[] = {
1223     {"brightness",    CAMERA_COMMAND_BRIGHTNESS},
1224     {"contrast",      CAMERA_COMMAND_CONTRAST},
1225     {"white balance", CAMERA_COMMAND_WHITE_BALANCE},
1226     {"color tone",    CAMERA_COMMAND_EFFECT},
1227     {"saturation",    CAMERA_COMMAND_SATURATION},
1228     {"hue",           CAMERA_COMMAND_HUE},
1229     {"sharpness",     CAMERA_COMMAND_SHARPNESS}
1230   };
1231   GstTizenCameraSrcCommand camera_control[] = {
1232     {"ptz_type",         CAMERA_COMMAND_PTZ_TYPE},
1233     {"pan",              CAMERA_COMMAND_PAN},
1234     {"tilt",             CAMERA_COMMAND_TILT}
1235   };
1236
1237   g_return_val_if_fail(camerasrc, FALSE);
1238
1239   GST_DEBUG_OBJECT(camerasrc, "ENTERED");
1240
1241   for (n = 0 ; n < G_N_ELEMENTS(color_balance) ; n++) {
1242     GstTizenCameraSrcColorBalanceChannel *camerasrc_color_channel = NULL;
1243     GstColorBalanceChannel *color_channel = NULL;
1244
1245     camerasrc_color_channel = g_object_new(GST_TYPE_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL, NULL);
1246     color_channel = GST_COLOR_BALANCE_CHANNEL(camerasrc_color_channel);
1247
1248     color_channel->label = g_strdup(color_balance[n].label);
1249     camerasrc_color_channel->id = color_balance[n].cmd;
1250     color_channel->min_value = 0;
1251     color_channel->max_value = 0;
1252
1253     camerasrc->colors = g_list_append(camerasrc->colors, (gpointer)color_channel);
1254     GST_INFO_OBJECT(camerasrc, "Adding Color Balance Channel %s [%"PRIx64"]",
1255                                color_channel->label, camerasrc_color_channel->id);
1256   }
1257
1258   for (n = 0 ; n < G_N_ELEMENTS(camera_control) ; n++) {
1259     GstTizenCamerasrcControlChannel *camerasrc_control_channel = NULL;
1260     GstCameraControlChannel *control_channel = NULL;
1261
1262     camerasrc_control_channel = g_object_new(GST_TYPE_TIZENCAMERASRC_CONTROL_CHANNEL, NULL);
1263     control_channel = GST_CAMERA_CONTROL_CHANNEL(camerasrc_control_channel);
1264
1265     control_channel->label = g_strdup(camera_control[n].label);
1266     camerasrc_control_channel->id = camera_control[n].cmd;
1267     control_channel->min_value = 0;
1268     control_channel->max_value = 0;
1269
1270     camerasrc->camera_controls = g_list_append(camerasrc->camera_controls, (gpointer)control_channel);
1271     GST_INFO_OBJECT(camerasrc, "Adding Camera Control Channel %s  [%"PRIx64"]",
1272                                control_channel->label, camerasrc_control_channel->id);
1273   }
1274
1275   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
1276
1277   return TRUE;
1278 }
1279
1280
1281 static gboolean gst_tizencamerasrc_empty_ctrl_list(GstTizenCameraSrc *camerasrc)
1282 {
1283   g_return_val_if_fail(camerasrc, FALSE);
1284
1285   GST_DEBUG_OBJECT (camerasrc, "ENTERED");
1286
1287   g_list_foreach(camerasrc->colors, (GFunc)g_object_unref, NULL);
1288   g_list_free(camerasrc->colors);
1289   camerasrc->colors = NULL;
1290
1291   g_list_foreach(camerasrc->camera_controls, (GFunc)g_object_unref, NULL);
1292   g_list_free(camerasrc->camera_controls);
1293   camerasrc->camera_controls = NULL;
1294
1295   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
1296
1297   return TRUE;
1298 }
1299
1300
1301 static gboolean gst_tizencamerasrc_start(GstTizenCameraSrc *camerasrc)
1302 {
1303   int i = 0;
1304   int ret = 0;
1305
1306   camera_flip_e set_flip;
1307   camera_format_s set_format;
1308
1309   GST_DEBUG_OBJECT(camerasrc, "ENTERED");
1310
1311   CLEAR(set_format);
1312
1313   /* set preview stream format */
1314   set_format.stream_format = camerasrc->pix_format;
1315   set_format.stream_resolution.width = camerasrc->width;
1316   set_format.stream_resolution.height = camerasrc->height;
1317   switch (camerasrc->rotate) {
1318   case 90:
1319     set_format.stream_rotation = CAMERA_ROTATION_90;
1320     break;
1321   case 180:
1322     set_format.stream_rotation = CAMERA_ROTATION_180;
1323     break;
1324   case 270:
1325     set_format.stream_rotation = CAMERA_ROTATION_270;
1326     break;
1327   case 0:
1328   default:
1329     set_format.stream_rotation = CAMERA_ROTATION_0;
1330     break;
1331   }
1332   if (camerasrc->fps_auto) {
1333     /*if fps is zero, auto fps mode*/
1334     set_format.stream_fps = 0;
1335
1336     GST_INFO_OBJECT (camerasrc, "AUTO FPS mode");
1337   } else if (camerasrc->high_speed_fps <= 0) {
1338     if (camerasrc->fps <= 0) {
1339       /*if fps is zero, auto fps mode*/
1340       set_format.stream_fps = 0;
1341     } else {
1342       set_format.stream_fps = camerasrc->fps;
1343     }
1344   } else {
1345     GST_INFO_OBJECT(camerasrc, "high speed fps %d", camerasrc->high_speed_fps);
1346     set_format.stream_fps = camerasrc->high_speed_fps;
1347   }
1348
1349   if (!__gst_tizencamerasrc_get_raw_pixel_info(camerasrc->cap_fourcc, &set_format.capture_format)) {
1350     GST_WARNING_OBJECT(camerasrc, "_gst_tizencamerasrc_get_raw_pixel_info failed, set default JPEG");
1351     set_format.capture_format = CAMERA_PIXEL_FORMAT_JPEG;
1352   }
1353   set_format.capture_resolution.width = camerasrc->cap_width;
1354   set_format.capture_resolution.height = camerasrc->cap_height;
1355   set_format.capture_quality = (uint32_t)camerasrc->cap_quality;
1356
1357   GST_WARNING_OBJECT(camerasrc, "resolution[%dx%d] fps[%d], format[%d], rotation[%d]",
1358     camerasrc->width, camerasrc->height, set_format.stream_fps,
1359     camerasrc->pix_format, camerasrc->rotate);
1360
1361   ret = hal_camera_set_preview_stream_format(camerasrc->hal_handle, &set_format);
1362   if (ret != CAMERA_ERROR_NONE) {
1363     GST_ERROR_OBJECT(camerasrc, "hal_camera_set_preview_stream_format() failed 0x%x", ret);
1364     goto _ERROR;
1365   }
1366
1367   /* set flip */
1368   if (camerasrc->vflip) {
1369     if (camerasrc->hflip)
1370       set_flip = CAMERA_FLIP_BOTH;
1371     else
1372       set_flip = CAMERA_FLIP_VERTICAL;
1373   } else {
1374     if (camerasrc->hflip)
1375       set_flip = CAMERA_FLIP_HORIZONTAL;
1376     else
1377       set_flip = CAMERA_FLIP_NONE;
1378   }
1379
1380   for (i = 0 ; i < EXTRA_PREVIEW_STREAM_MAX ; i++) {
1381     if (camerasrc->extra_caps[i]) {
1382       gst_caps_unref(camerasrc->extra_caps[i]);
1383       camerasrc->extra_caps[i] = NULL;
1384     }
1385   }
1386
1387   ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_FLIP, (void *)&set_flip);
1388   if (ret != CAMERA_ERROR_NONE) {
1389     GST_ERROR_OBJECT(camerasrc, "hal_camera_set_command() failed 0x%x", ret);
1390     goto _ERROR;
1391   }
1392
1393   GST_INFO_OBJECT(camerasrc, "VFLIP : %d, HFLIP : %d", camerasrc->vflip, camerasrc->hflip);
1394
1395   if (camerasrc->preview_control.live_buffers != 0)
1396     GST_WARNING_OBJECT(camerasrc, "CURRENT LIVE BUFFER COUNT[%d]", camerasrc->preview_control.live_buffers);
1397
1398   camerasrc->preview_control.live_buffers = 0;
1399   camerasrc->preview_control.is_first_frame = TRUE;
1400   camerasrc->extra_preview_control.live_buffers = 0;
1401   camerasrc->extra_preview_control.is_first_frame = TRUE;
1402
1403   if (!camerasrc->is_encoded_format && camerasrc->live_buffer_max_raw > 0)
1404     camerasrc->live_buffer_check = camerasrc->live_buffer_max_raw;
1405   else
1406     camerasrc->live_buffer_check = camerasrc->live_buffer_max;
1407
1408   GST_WARNING_OBJECT(camerasrc, "live buffer check[%d], max[%d,%d]",
1409     camerasrc->live_buffer_check, camerasrc->live_buffer_max, camerasrc->live_buffer_max_raw);
1410
1411   /* start preview stream */
1412   ret = hal_camera_start_preview(camerasrc->hal_handle, __camera_preview_frame_cb, camerasrc);
1413   if (ret != CAMERA_ERROR_NONE) {
1414     GST_ERROR_OBJECT(camerasrc, "hal_camera_start_preview() failed 0x%x", ret);
1415     camerasrc->preview_control.running = FALSE;
1416     goto _ERROR;
1417   }
1418
1419   GST_INFO_OBJECT(camerasrc, "camerasrc_start_preview_stream() done");
1420
1421   camerasrc->mode = VIDEO_IN_MODE_PREVIEW;
1422   camerasrc->preview_control.running = TRUE;
1423   camerasrc->hal_error_code = CAMERA_ERROR_NONE;
1424
1425   GST_INFO_OBJECT(camerasrc, "LEAVE");
1426
1427   return TRUE;
1428
1429 _ERROR:
1430   gst_tizencamerasrc_error_handler(camerasrc, ret);
1431   GST_ERROR_OBJECT(camerasrc, "LEAVE 0x%x", ret);
1432
1433   return FALSE;
1434 }
1435
1436
1437 static gboolean gst_tizencamerasrc_stop(GstTizenCameraSrc *camerasrc)
1438 {
1439   int ret = CAMERA_ERROR_NONE;
1440   gint64 end_time;
1441   GstBuffer *buffer = NULL;
1442
1443   GST_INFO_OBJECT (camerasrc, "ENTERED");
1444
1445   if (camerasrc->hal_handle) {
1446     g_mutex_lock(&camerasrc->preview_control.lock);
1447
1448     if (camerasrc->preview_control.running) {
1449       camerasrc->preview_control.running = FALSE;
1450     } else {
1451       GST_ERROR_OBJECT(camerasrc, "buffer NOT running");
1452       g_mutex_unlock(&camerasrc->preview_control.lock);
1453       return FALSE;
1454     }
1455
1456     g_mutex_unlock(&camerasrc->preview_control.lock);
1457
1458     /* remove all cached buffers */
1459     while (!g_queue_is_empty(camerasrc->preview_buffer_list)) {
1460       buffer = g_queue_pop_head(camerasrc->preview_buffer_list);
1461       GST_INFO_OBJECT(camerasrc, "unref queued buffer %p", buffer);
1462       gst_buffer_unref(buffer);
1463     }
1464
1465     g_mutex_lock(&camerasrc->preview_control.lock);
1466
1467     GST_INFO_OBJECT(camerasrc, "live buffer count %d", camerasrc->preview_control.live_buffers);
1468
1469       /* wait until all buffers are returned */
1470     while (camerasrc->preview_control.live_buffers > 0) {
1471       end_time = g_get_monotonic_time() + 1 * G_TIME_SPAN_SECOND;
1472       if (!g_cond_wait_until(&camerasrc->preview_control.cond, &camerasrc->preview_control.lock, end_time)) {
1473         GST_ERROR_OBJECT(camerasrc, "buffer wait failed");
1474         break;
1475       } else {
1476         GST_INFO_OBJECT(camerasrc, "signal received. check again [num %d]", camerasrc->preview_control.live_buffers);
1477       }
1478     }
1479
1480     g_mutex_unlock(&camerasrc->preview_control.lock);
1481
1482     GST_INFO_OBJECT(camerasrc, "stop preview stream");
1483
1484     /* stop preview stream */
1485     ret = hal_camera_stop_preview(camerasrc->hal_handle);
1486     if (ret != CAMERA_ERROR_NONE) {
1487       GST_ERROR_OBJECT(camerasrc, "hal_camera_stop_preview failed 0x%x", ret);
1488       camerasrc->preview_control.running = TRUE;
1489       return FALSE;
1490     }
1491
1492     camerasrc->mode = VIDEO_IN_MODE_NONE;
1493   }
1494
1495   GST_INFO_OBJECT(camerasrc, "LEAVE");
1496
1497   return TRUE;
1498 }
1499
1500
1501 static gboolean gst_tizencamerasrc_capture_start(GstTizenCameraSrc *camerasrc)
1502 {
1503   int ret = CAMERA_ERROR_NONE;
1504
1505   GST_INFO_OBJECT(camerasrc, "ENTERED - mode %d", camerasrc->mode);
1506
1507   if (camerasrc->mode != VIDEO_IN_MODE_PREVIEW) {
1508     GST_WARNING_OBJECT(camerasrc, "Wrong state[%d]!", camerasrc->mode);
1509     return FALSE;
1510   }
1511
1512   GST_INFO_OBJECT(camerasrc, "start capture - count %d, interval %d",
1513     camerasrc->cap_count, camerasrc->cap_interval);
1514
1515   ret = hal_camera_set_command(camerasrc->hal_handle,
1516     CAMERA_COMMAND_CAPTURE_COUNT, (void *)&camerasrc->cap_count);
1517   if (ret != CAMERA_ERROR_NONE)
1518     GST_WARNING_OBJECT(camerasrc, "set capture count failed 0x%x", ret);
1519
1520   if (camerasrc->cap_count > 1) {
1521     ret = hal_camera_set_command(camerasrc->hal_handle,
1522       CAMERA_COMMAND_CAPTURE_INTERVAL, (void *)&camerasrc->cap_interval);
1523     if (ret != CAMERA_ERROR_NONE)
1524       GST_WARNING_OBJECT(camerasrc, "set capture interval failed 0x%x", ret);
1525   }
1526
1527   ret = hal_camera_start_capture(camerasrc->hal_handle, _camera_capture_cb, camerasrc);
1528   if (ret != CAMERA_ERROR_NONE) {
1529     GST_ERROR_OBJECT(camerasrc, "start capture failed 0x%x", ret);
1530     return FALSE;
1531   }
1532
1533   camerasrc->mode = VIDEO_IN_MODE_CAPTURE;
1534
1535   GST_INFO_OBJECT(camerasrc, "CAPTURE STARTED!");
1536
1537   return TRUE;
1538 }
1539
1540
1541 static gboolean gst_tizencamerasrc_capture_stop(GstTizenCameraSrc *camerasrc)
1542 {
1543   int ret = CAMERA_ERROR_NONE;
1544
1545   GST_INFO_OBJECT(camerasrc, "ENTERED - mode %d", camerasrc->mode);
1546
1547   if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE) {
1548     ret = hal_camera_stop_capture(camerasrc->hal_handle);
1549     if (ret != CAMERA_ERROR_NONE) {
1550       GST_ERROR_OBJECT(camerasrc, "hal_camera_stop_capture failed 0x%x", ret);
1551       return FALSE;
1552     }
1553
1554     g_mutex_lock(&camerasrc->preview_control.lock);
1555     camerasrc->mode = VIDEO_IN_MODE_PREVIEW;
1556     g_cond_signal(&camerasrc->preview_control.cond);
1557     g_mutex_unlock(&camerasrc->preview_control.lock);
1558
1559     GST_INFO_OBJECT(camerasrc, "CAPTURE STOPPED!");
1560
1561     return TRUE;
1562   } else {
1563     GST_WARNING_OBJECT(camerasrc, "Wrong state[%d]!", camerasrc->mode);
1564     return FALSE;
1565   }
1566 }
1567
1568
1569 static GstFlowReturn gst_tizencamerasrc_read_preview(GstTizenCameraSrc *camerasrc, GstBuffer **buffer)
1570 {
1571   int preview_check_count = 0;
1572   gint64 end_time;
1573   BufferControl *control = &camerasrc->preview_control;
1574
1575   GST_DEBUG_OBJECT(camerasrc, "check preview buffer list");
1576
1577   g_mutex_lock(&control->lock);
1578
1579   while (g_queue_is_empty(camerasrc->preview_buffer_list)) {
1580     GST_DEBUG_OBJECT(camerasrc, "buffer list is empty. waiting...");
1581
1582     end_time = g_get_monotonic_time () + _BUFFER_WAIT_TIMEOUT;
1583     if (g_cond_wait_until(&control->cond, &control->lock, end_time)) {
1584       GST_DEBUG_OBJECT(camerasrc, "Signal received. Retry...");
1585       continue;
1586     }
1587
1588     if (camerasrc->hal_error_code != CAMERA_ERROR_NONE) {
1589       GST_WARNING_OBJECT(camerasrc, "buffer timeout and error[0x%x]", camerasrc->hal_error_code);
1590       break;
1591     }
1592
1593     if (camerasrc->is_flushing) {
1594       g_mutex_unlock(&control->lock);
1595       GST_WARNING_OBJECT(camerasrc, "FLUSHING now");
1596       goto _FLUSHING;
1597     }
1598
1599     if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE)
1600       GST_WARNING_OBJECT(camerasrc, "capture mode now.");
1601     else
1602       preview_check_count++;
1603
1604     if (camerasrc->empty_buffer_timeout > 0 &&
1605         preview_check_count * _BUFFER_WAIT_TIMEOUT >= camerasrc->empty_buffer_timeout * 1000) {
1606       GST_ERROR_OBJECT(camerasrc, "wait buffer failed for [%d]ms", camerasrc->empty_buffer_timeout);
1607       break;
1608     }
1609
1610     GST_WARNING_OBJECT(camerasrc, "preview buffer timeout[%d]usec, retry[%d]",
1611       _BUFFER_WAIT_TIMEOUT, preview_check_count);
1612   }
1613
1614   *buffer = g_queue_pop_head(camerasrc->preview_buffer_list);
1615
1616   g_mutex_unlock(&control->lock);
1617
1618   if (*buffer == NULL) {
1619     GST_ERROR_OBJECT(camerasrc, "buffer is NULL (HAL error 0x%x)", camerasrc->hal_error_code);
1620
1621     if (camerasrc->hal_error_code == CAMERA_ERROR_NONE)
1622       gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_DEVICE_READ);
1623
1624     return GST_FLOW_ERROR;
1625   }
1626
1627   if (camerasrc->is_flushing)
1628     goto _FLUSHING;
1629
1630   if (camerasrc->firsttime)
1631     camerasrc->firsttime = FALSE;
1632
1633   GST_DEBUG_OBJECT(camerasrc, "preview buffer %p", *buffer);
1634
1635   return GST_FLOW_OK;
1636
1637 _FLUSHING:
1638   if (*buffer) {
1639     gst_buffer_unref(*buffer);
1640     *buffer = NULL;
1641   }
1642
1643   GST_WARNING_OBJECT(camerasrc, "return GST_FLOW_FLUSHING");
1644
1645   return GST_FLOW_FLUSHING;
1646 }
1647
1648
1649 static GstFlowReturn gst_tizencamerasrc_read(GstTizenCameraSrc *camerasrc, GstBuffer **buffer)
1650 {
1651   GstFlowReturn ret = GST_FLOW_OK;
1652
1653   switch (camerasrc->mode) {
1654   case VIDEO_IN_MODE_PREVIEW:
1655   case VIDEO_IN_MODE_CAPTURE:
1656   case VIDEO_IN_MODE_VIDEO:
1657     GST_DEBUG_OBJECT(camerasrc, "gst_tizencamerasrc_read_preview");
1658     ret = gst_tizencamerasrc_read_preview(camerasrc, buffer);
1659     break;
1660   case VIDEO_IN_MODE_NONE:
1661   default:
1662     ret = GST_FLOW_ERROR;
1663     GST_ERROR_OBJECT (camerasrc, "can't reach statement.[camerasrc->mode=%d]", camerasrc->mode);
1664     break;
1665   }
1666
1667   if (buffer && (!(*buffer) || !GST_IS_BUFFER(*buffer))) {
1668     /* To avoid seg fault, make dummy buffer. */
1669     GST_WARNING_OBJECT (camerasrc, "Make a dummy buffer");
1670     *buffer = gst_buffer_new();
1671   }
1672
1673   return ret;
1674 }
1675
1676
1677 static gboolean gst_tizencamerasrc_get_timeinfo(GstTizenCameraSrc *camerasrc, GstBuffer *buffer)
1678 {
1679   int fps_nu = 0;
1680   int fps_de = 0;
1681   GstClock *clock = NULL;
1682   GstClockTime timestamp = GST_CLOCK_TIME_NONE;
1683   GstClockTime duration = GST_CLOCK_TIME_NONE;
1684
1685   if (!camerasrc || !buffer) {
1686     GST_WARNING_OBJECT (camerasrc, "Invalid pointer [hadle:%p, buffer:%p]", camerasrc, buffer);
1687     return FALSE;
1688   }
1689
1690   /* timestamps, LOCK to get clock and base time. */
1691   clock = GST_ELEMENT_CLOCK(camerasrc);
1692   if (clock) {
1693     /* the time now is the time of the clock minus the base time */
1694     gst_object_ref(clock);
1695     timestamp = gst_clock_get_time(clock) - GST_ELEMENT(camerasrc)->base_time;
1696     gst_object_unref(clock);
1697
1698     /* if we have a framerate adjust timestamp for frame latency */
1699     if (camerasrc->fps_auto) {
1700       /* auto fps mode */
1701       duration = GST_CLOCK_TIME_NONE;
1702     } else {
1703       if (camerasrc->fps <= 0) {
1704         /*if fps is zero, auto fps mode*/
1705         fps_nu = 0;
1706         fps_de = 1;
1707       } else {
1708         fps_nu = 1;
1709         fps_de = camerasrc->fps;
1710       }
1711
1712       if (fps_nu > 0 && fps_de > 0) {
1713         duration = gst_util_uint64_scale_int(GST_SECOND, fps_nu, fps_de);
1714       }
1715     }
1716
1717     /* set default duration if duration is NONE : 30 fps */
1718     if (duration == GST_CLOCK_TIME_NONE) {
1719       duration = gst_util_uint64_scale_int(GST_SECOND, 1, 30);
1720     }
1721   } else {
1722     /* no clock, can't set timestamps */
1723     timestamp = GST_CLOCK_TIME_NONE;
1724   }
1725
1726   GST_BUFFER_TIMESTAMP(buffer) = timestamp;
1727   GST_BUFFER_DURATION(buffer) = duration;
1728
1729   GST_LOG_OBJECT(camerasrc, "timestamp [%"GST_TIME_FORMAT" dur %" GST_TIME_FORMAT "]",
1730     GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)),
1731     GST_TIME_ARGS(GST_BUFFER_DURATION(buffer)));
1732
1733   return TRUE;
1734 }
1735
1736
1737 /* Gstreamer general functions */
1738 static gboolean gst_tizencamerasrc_src_start(GstBaseSrc *src)
1739 {
1740   int ret = TRUE;
1741   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC (src);
1742
1743   GST_DEBUG_OBJECT(camerasrc, "ENTERED");
1744
1745   camerasrc->firsttime = TRUE;
1746   /* 'gst_tizencamerasrc_set_caps' will call gst_tizencamerasrc_start(). So skip to call it. */
1747   /*ret = gst_tizencamerasrc_start(camerasrc);*/
1748
1749   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
1750
1751   return ret;
1752 }
1753
1754
1755 static gboolean gst_tizencamerasrc_src_stop(GstBaseSrc *src)
1756 {
1757   int ret = 0;
1758   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(src);
1759
1760   GST_DEBUG_OBJECT (camerasrc, "ENTERED");
1761
1762   ret = gst_tizencamerasrc_stop(camerasrc);
1763
1764   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
1765
1766   return ret;
1767 }
1768
1769
1770 static GstFlowReturn gst_tizencamerasrc_src_create(GstPushSrc *src, GstBuffer **buffer)
1771 {
1772   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC (src);
1773   GstFlowReturn ret;
1774
1775   GST_LOG_OBJECT(camerasrc, "ENTERED");
1776
1777   ret = gst_tizencamerasrc_read(camerasrc, buffer);
1778
1779   GST_LOG_OBJECT (camerasrc, "LEAVE");
1780
1781   return ret;
1782 }
1783
1784
1785 static void gst_tizencamerasrc_set_property(GObject *object, guint prop_id,
1786                                        const GValue *value, GParamSpec *pspec)
1787 {
1788   int ret = 0;
1789   int tmp = 0;
1790   GstTizenCameraSrc *camerasrc = NULL;
1791
1792   g_return_if_fail(GST_IS_TIZENCAMERA_SRC(object));
1793   camerasrc = GST_TIZENCAMERA_SRC(object);
1794
1795   switch (prop_id) {
1796   case ARG_CAMERA_ID:
1797     camerasrc->camera_id = g_value_get_int(value);
1798     break;
1799   case ARG_DEVICE_NAME:
1800     g_free(camerasrc->device_name);
1801     camerasrc->device_name = g_value_dup_string(value);
1802     GST_INFO_OBJECT(camerasrc, "Set device name: %s", camerasrc->device_name);
1803     break;
1804   case ARG_DEVICE_BUS:
1805     camerasrc->device_bus = g_value_get_int(value);
1806     GST_INFO_OBJECT(camerasrc, "Set device bus: %d", camerasrc->device_bus);
1807     ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_DEVICE_BUS, (void *)&camerasrc->device_bus);
1808     break;
1809   case ARG_DEVICE_PORT:
1810     g_free(camerasrc->device_port);
1811     camerasrc->device_port = g_value_dup_string(value);
1812     GST_INFO_OBJECT(camerasrc, "Set device port: %s", camerasrc->device_port);
1813     ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_DEVICE_PORT, (void *)camerasrc->device_port);
1814     break;
1815   case ARG_HAL_NAME:
1816     g_free(camerasrc->hal_name);
1817     camerasrc->hal_name = g_value_dup_string(value);
1818
1819     /* reset camera hal interface handle */
1820     if (camerasrc->hal_handle) {
1821       GST_INFO_OBJECT(camerasrc, "Reset HAL intf: %p", camerasrc->hal_handle);
1822       hal_camera_deinit(camerasrc->hal_handle);
1823       camerasrc->hal_handle = NULL;
1824     }
1825
1826     GST_WARNING_OBJECT(camerasrc, "Set HAL name: %s", camerasrc->hal_name);
1827
1828     ret = hal_camera_init(camerasrc->hal_name, &camerasrc->hal_handle);
1829     if (ret == CAMERA_ERROR_NONE) {
1830       ret = hal_camera_get_device_info_list(camerasrc->hal_handle, camerasrc->device_info);
1831       GST_WARNING_OBJECT(camerasrc, "HAL device info: 0x%x, count: %d", ret, camerasrc->device_info->count);
1832
1833       ret = hal_camera_add_message_callback(camerasrc->hal_handle, __camera_hal_message_callback, camerasrc, &camerasrc->msg_cb_id);
1834       GST_WARNING_OBJECT(camerasrc, "HAL message cb: 0x%x, id: %d", ret, camerasrc->msg_cb_id);
1835     } else {
1836       GST_ERROR_OBJECT(camerasrc, "hal_camera_init failed: 0x%x", ret);
1837     }
1838     break;
1839   case ARG_VFLIP:
1840     camerasrc->vflip = g_value_get_boolean(value);
1841     GST_INFO_OBJECT(camerasrc, "Set VFLIP : %d", camerasrc->vflip);
1842     break;
1843   case ARG_HFLIP:
1844     camerasrc->hflip = g_value_get_boolean(value);
1845     GST_INFO_OBJECT(camerasrc, "Set HFLIP : %d", camerasrc->hflip);
1846     break;
1847   case ARG_HIGH_SPEED_FPS:
1848     camerasrc->high_speed_fps = g_value_get_int(value);
1849     GST_INFO_OBJECT(camerasrc, "Set HIGH SPEED FPS: %d", camerasrc->high_speed_fps);
1850     break;
1851   case ARG_AUTO_FPS:
1852     camerasrc->fps_auto = g_value_get_boolean(value);
1853     GST_INFO_OBJECT(camerasrc, "Set AUTO_FPS: %d", camerasrc->fps_auto);
1854     break;
1855   case ARG_EXTRA_PREVIEW:
1856     camerasrc->extra_preview = g_value_get_boolean(value);
1857     GST_INFO_OBJECT(camerasrc, "Enable extra preview: %d", camerasrc->extra_preview);
1858     if (camerasrc->extra_preview)
1859       ret = hal_camera_set_extra_preview_frame_cb(camerasrc->hal_handle, __camera_extra_preview_frame_cb, camerasrc);
1860     else
1861       ret = hal_camera_unset_extra_preview_frame_cb(camerasrc->hal_handle);
1862     GST_INFO_OBJECT(camerasrc, "extra preview %s result: 0x%x",
1863       camerasrc->extra_preview ? "set" : "unset", ret);
1864     break;
1865   case ARG_LIVE_BUFFER_MAX:
1866     camerasrc->live_buffer_max = g_value_get_int(value);
1867     GST_WARNING_OBJECT(camerasrc, "live buffer max %d", camerasrc->live_buffer_max);
1868     break;
1869   case ARG_LIVE_BUFFER_MAX_RAW:
1870     camerasrc->live_buffer_max_raw = g_value_get_int(value);
1871     GST_WARNING_OBJECT(camerasrc, "live buffer max for raw format %d", camerasrc->live_buffer_max_raw);
1872     break;
1873   case ARG_EMPTY_BUFFER_TIMEOUT:
1874     camerasrc->empty_buffer_timeout = g_value_get_int(value);
1875     GST_INFO_OBJECT(camerasrc, "empty buffer timeout %dms", camerasrc->empty_buffer_timeout);
1876     break;
1877   case ARG_CAPTURE_FOURCC:
1878     camerasrc->cap_fourcc = g_value_get_uint(value);
1879     gst_tizencamerasrc_set_capture_format(camerasrc);
1880     break;
1881   case ARG_CAPTURE_WIDTH:
1882     camerasrc->cap_width_tmp = g_value_get_int(value);
1883     break;
1884   case ARG_CAPTURE_HEIGHT:
1885     camerasrc->cap_height_tmp = g_value_get_int(value);
1886     gst_tizencamerasrc_set_capture_format(camerasrc);
1887     break;
1888   case ARG_CAPTURE_INTERVAL:
1889     camerasrc->cap_interval = g_value_get_int(value);
1890     GST_INFO_OBJECT(camerasrc, "Set capture interval: %d", camerasrc->cap_interval);
1891     break;
1892   case ARG_CAPTURE_COUNT:
1893     tmp = g_value_get_int(value);
1894     camerasrc->cap_count = tmp;
1895     camerasrc->cap_count_reverse = tmp;
1896     GST_INFO_OBJECT(camerasrc, "Set capture count: %d", camerasrc->cap_count_reverse);
1897     break;
1898   case ARG_CAPTURE_QUALITY:
1899     camerasrc->cap_quality = g_value_get_int(value);
1900     GST_INFO_OBJECT(camerasrc, "Set capture quality : %d", camerasrc->cap_quality);
1901     break;
1902   case ARG_VIDEO_WIDTH:
1903     camerasrc->video_width = g_value_get_int(value);
1904     GST_INFO_OBJECT(camerasrc, "video width %d", camerasrc->video_width);
1905     break;
1906   case ARG_VIDEO_HEIGHT:
1907     camerasrc->video_height = g_value_get_int(value);
1908     GST_INFO_OBJECT(camerasrc, "video height %d", camerasrc->video_height);
1909     break;
1910   case ARG_VIDEO_FPS:
1911     camerasrc->video_fps = g_value_get_int(value);
1912     GST_INFO_OBJECT(camerasrc, "video fps %d", camerasrc->video_fps);
1913     break;
1914   case ARG_RECORDING_HINT:
1915     camerasrc->recording_hint = g_value_get_boolean(value);
1916
1917     GST_INFO_OBJECT(camerasrc, "recording-hint %d", camerasrc->recording_hint);
1918
1919     if (camerasrc->recording_hint)
1920       gst_tizencamerasrc_set_video_format(camerasrc);
1921     break;
1922   case ARG_BITRATE:
1923     camerasrc->bitrate = g_value_get_int(value);
1924     ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_BITRATE, (void *)&camerasrc->bitrate);
1925     GST_INFO_OBJECT(camerasrc, "Set bitrate : %d, ret 0x%x", camerasrc->bitrate, ret);
1926     break;
1927   case ARG_GOP_INTERVAL:
1928     camerasrc->gop_interval = g_value_get_int(value);
1929     ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_GOP_INTERVAL, (void *)&camerasrc->gop_interval);
1930     GST_INFO_OBJECT(camerasrc, "Set GOP interval : %d, ret 0x%x", camerasrc->gop_interval, ret);
1931     break;
1932   default:
1933     G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1934     break;
1935   }
1936
1937   return;
1938 }
1939
1940
1941 static void gst_tizencamerasrc_get_property(GObject *object, guint prop_id,
1942                                        GValue *value, GParamSpec *pspec)
1943 {
1944   GstTizenCameraSrc *camerasrc;
1945
1946   g_return_if_fail(GST_IS_TIZENCAMERA_SRC(object));
1947   camerasrc = GST_TIZENCAMERA_SRC(object);
1948
1949   switch (prop_id) {
1950   case ARG_CAMERA_ID:
1951     g_value_set_int(value, camerasrc->camera_id);
1952     break;
1953   case ARG_DEVICE_NAME:
1954     g_value_set_string(value, camerasrc->device_name);
1955     break;
1956   case ARG_DEVICE_BUS:
1957     g_value_set_int(value, camerasrc->device_bus);
1958     break;
1959   case ARG_DEVICE_PORT:
1960     g_value_set_string(value, camerasrc->device_port);
1961     break;
1962   case ARG_HAL_NAME:
1963     g_value_set_string(value, camerasrc->hal_name);
1964     break;
1965   case ARG_VFLIP:
1966     g_value_set_boolean(value, camerasrc->vflip);
1967     break;
1968   case ARG_HFLIP:
1969     g_value_set_boolean(value, camerasrc->hflip);
1970     break;
1971   case ARG_HIGH_SPEED_FPS:
1972     g_value_set_int(value, camerasrc->high_speed_fps);
1973     break;
1974   case ARG_AUTO_FPS:
1975     g_value_set_boolean(value, camerasrc->fps_auto);
1976     break;
1977   case ARG_EXTRA_PREVIEW:
1978     g_value_set_boolean(value, camerasrc->extra_preview);
1979     break;
1980   case ARG_LIVE_BUFFER_MAX:
1981     g_value_set_int(value, camerasrc->live_buffer_max);
1982     break;
1983   case ARG_LIVE_BUFFER_MAX_RAW:
1984     g_value_set_int(value, camerasrc->live_buffer_max_raw);
1985     break;
1986   case ARG_EMPTY_BUFFER_TIMEOUT:
1987     g_value_set_int(value, camerasrc->empty_buffer_timeout);
1988     break;
1989   case ARG_BUFFER_QUARK:
1990     if (camerasrc->buffer_quark == _DEFAULT_BUFFER_QUARK) {
1991       camerasrc->buffer_quark = g_quark_from_static_string("tizencamerabuffer");
1992       GST_INFO_OBJECT(camerasrc, "quark for buffer [%u]", camerasrc->buffer_quark);
1993     }
1994     g_value_set_uint(value, camerasrc->buffer_quark);
1995     break;
1996   case ARG_CAPTURE_FOURCC:
1997     g_value_set_uint(value, camerasrc->cap_fourcc);
1998     break;
1999   case ARG_CAPTURE_WIDTH:
2000     g_value_set_int(value, camerasrc->cap_width);
2001     break;
2002   case ARG_CAPTURE_HEIGHT:
2003     g_value_set_int(value, camerasrc->cap_height);
2004     break;
2005   case ARG_CAPTURE_INTERVAL:
2006     g_value_set_int(value, camerasrc->cap_interval);
2007     break;
2008   case ARG_CAPTURE_COUNT:
2009     g_value_set_int(value, camerasrc->cap_count);
2010     break;
2011   case ARG_CAPTURE_QUALITY:
2012     g_value_set_int(value, camerasrc->cap_quality);
2013     GST_INFO("GET capture quality : %d", camerasrc->cap_quality);
2014     break;
2015   case ARG_CAPTURE_PROVIDE_EXIF:
2016     g_value_set_boolean(value, camerasrc->cap_provide_exif);
2017     GST_INFO("Is Exif provided? : %d", camerasrc->cap_provide_exif);
2018     break;
2019   case ARG_VIDEO_WIDTH:
2020     g_value_set_int(value, camerasrc->video_width);
2021     break;
2022   case ARG_VIDEO_HEIGHT:
2023     g_value_set_int(value, camerasrc->video_height);
2024     break;
2025   case ARG_VIDEO_FPS:
2026     g_value_set_int(value, camerasrc->video_fps);
2027     break;
2028   case ARG_RECORDING_HINT:
2029     g_value_set_boolean(value, camerasrc->recording_hint);
2030     break;
2031   case ARG_BITRATE:
2032     g_value_set_int(value, camerasrc->bitrate);
2033     break;
2034   case ARG_GOP_INTERVAL:
2035     g_value_set_int(value, camerasrc->gop_interval);
2036     break;
2037   default:
2038     G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
2039     break;
2040   }
2041
2042   return;
2043 }
2044
2045
2046 static GstStateChangeReturn gst_tizencamerasrc_change_state(GstElement *element, GstStateChange transition)
2047 {
2048   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2049   GstTizenCameraSrc *camerasrc;
2050   camerasrc = GST_TIZENCAMERA_SRC (element);
2051
2052   switch (transition) {
2053   case GST_STATE_CHANGE_NULL_TO_READY:
2054     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: NULL -> READY");
2055     GST_INFO("    gst_tizencamerasrc_create");
2056     if (!gst_tizencamerasrc_create(camerasrc)){
2057       goto statechange_failed;
2058     }
2059     break;
2060   case GST_STATE_CHANGE_READY_TO_PAUSED:
2061     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: READY -> PAUSED");
2062     ret = GST_STATE_CHANGE_NO_PREROLL;
2063     break;
2064   case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2065     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: PAUSED -> PLAYING");
2066     break;
2067   default:
2068     break;
2069   }
2070
2071   ret = GST_ELEMENT_CLASS(gst_tizencamerasrc_parent_class)->change_state(element, transition);
2072   if (ret == GST_STATE_CHANGE_FAILURE){
2073     return ret;
2074   }
2075
2076   switch (transition) {
2077   case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2078     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: PLAYING -> PAUSED");
2079     ret = GST_STATE_CHANGE_NO_PREROLL;
2080     break;
2081   case GST_STATE_CHANGE_PAUSED_TO_READY:
2082     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: PAUSED -> READY");
2083     break;
2084   case GST_STATE_CHANGE_READY_TO_NULL:
2085     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: READY -> NULL");
2086     GST_INFO("    gst_tizencamerasrc_destroy");
2087     if (!gst_tizencamerasrc_destroy(camerasrc)){
2088       goto statechange_failed;
2089     }
2090     break;
2091   default:
2092     break;
2093   }
2094
2095   return ret;
2096
2097  statechange_failed:
2098   /* subclass must post a meaningful error message */
2099   GST_ERROR_OBJECT(camerasrc, "state change failed");
2100
2101   return GST_STATE_CHANGE_FAILURE;
2102 }
2103
2104
2105 static void gst_tizencamerasrc_finalize(GObject *object)
2106 {
2107   int i = 0;
2108   int ret = 0;
2109   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(object);
2110
2111   GST_INFO_OBJECT(camerasrc, "ENTERED");
2112
2113   ret = hal_camera_deinit(camerasrc->hal_handle);
2114   if (ret != CAMERA_ERROR_NONE)
2115     GST_ERROR_OBJECT(camerasrc, "hal_camera_deinit failed 0x%x", ret);
2116
2117   camerasrc->hal_handle = NULL;
2118
2119   g_cond_clear(&camerasrc->preview_control.cond);
2120   g_mutex_clear(&camerasrc->preview_control.lock);
2121   g_cond_clear(&camerasrc->extra_preview_control.cond);
2122   g_mutex_clear(&camerasrc->extra_preview_control.lock);
2123   SAFE_FREE_GQUEUE(camerasrc->preview_buffer_list);
2124   g_cond_clear(&camerasrc->video_control.cond);
2125   g_mutex_clear(&camerasrc->video_control.lock);
2126
2127   if (camerasrc->allocator) {
2128     gst_object_unref(camerasrc->allocator);
2129     camerasrc->allocator = NULL;
2130   }
2131
2132   if (camerasrc->video_caps) {
2133     gst_caps_unref(camerasrc->video_caps);
2134     camerasrc->video_caps = NULL;
2135   }
2136
2137   for (i = 0 ; i < EXTRA_PREVIEW_STREAM_MAX ; i++) {
2138     if (camerasrc->extra_caps[i]) {
2139       gst_caps_unref(camerasrc->extra_caps[i]);
2140       camerasrc->extra_caps[i] = NULL;
2141     }
2142   }
2143
2144   g_free(camerasrc->hal_name);
2145   g_free(camerasrc->device_info);
2146   g_free(camerasrc->device_name);
2147   g_free(camerasrc->device_port);
2148
2149   GST_INFO_OBJECT(camerasrc, "LEAVE");
2150
2151   if (G_OBJECT_CLASS (gst_tizencamerasrc_parent_class)->finalize)
2152     G_OBJECT_CLASS(gst_tizencamerasrc_parent_class)->finalize(object);
2153
2154   return;
2155 }
2156
2157
2158 void gst_tizencamerasrc_set_capture_command(GstTizenCameraSrc *camerasrc, GstCameraControlCaptureCommand cmd)
2159 {
2160   if (camerasrc == NULL) {
2161     GST_ERROR_OBJECT(camerasrc, "camerasrc is NULL");
2162     return;
2163   }
2164
2165   GST_INFO_OBJECT(camerasrc, "ENTERED");
2166
2167   if (cmd == GST_CAMERA_CONTROL_CAPTURE_COMMAND_START)
2168     gst_tizencamerasrc_capture_start(camerasrc);
2169   else if (cmd == GST_CAMERA_CONTROL_CAPTURE_COMMAND_STOP)
2170     gst_tizencamerasrc_capture_stop(camerasrc);
2171   else
2172     GST_WARNING_OBJECT(camerasrc, "not supported command %d", cmd);
2173
2174   GST_INFO_OBJECT(camerasrc, "LEAVE");
2175
2176   return;
2177 }
2178
2179
2180 void gst_tizencamerasrc_set_record_command(GstTizenCameraSrc *camerasrc, GstCameraControlRecordCommand cmd)
2181 {
2182   int ret = CAMERA_ERROR_NONE;
2183
2184   if (camerasrc == NULL) {
2185     GST_ERROR_OBJECT(camerasrc, "camerasrc is NULL");
2186     return;
2187   }
2188
2189   GST_INFO_OBJECT(camerasrc, "ENTERED - cmd %d", cmd);
2190
2191   if (cmd == GST_CAMERA_CONTROL_RECORD_COMMAND_START) {
2192     camerasrc->video_control.live_buffers = 0;
2193     camerasrc->video_control.is_first_frame = TRUE;
2194     if (camerasrc->video_caps) {
2195       gst_caps_unref(camerasrc->video_caps);
2196       camerasrc->video_caps = NULL;
2197     }
2198     ret = hal_camera_start_record(camerasrc->hal_handle, __camera_video_frame_cb, camerasrc);
2199   } else if (cmd == GST_CAMERA_CONTROL_RECORD_COMMAND_STOP) {
2200     ret = hal_camera_stop_record(camerasrc->hal_handle);
2201   } else {
2202     GST_WARNING_OBJECT(camerasrc, "not supported command %d", cmd);
2203   }
2204
2205   GST_INFO_OBJECT(camerasrc, "LEAVE - ret[0x%x]", ret);
2206
2207   return;
2208 }
2209
2210
2211 gboolean gst_tizencamerasrc_set_user_buffer_fd(GstTizenCameraSrc *camerasrc, int *fds, int number)
2212 {
2213   int ret = CAMERA_ERROR_NONE;
2214
2215   if (camerasrc == NULL) {
2216     GST_ERROR_OBJECT(camerasrc, "camerasrc is NULL");
2217     return FALSE;
2218   }
2219
2220   GST_INFO_OBJECT(camerasrc, "ENTERED - number %d", number);
2221
2222   ret = hal_camera_set_user_buffer_fd(camerasrc->hal_handle, fds, number);
2223
2224   GST_INFO_OBJECT(camerasrc, "LEAVE - ret 0x%x", ret);
2225
2226   return (ret == CAMERA_ERROR_NONE ? TRUE : FALSE);
2227 }
2228
2229
2230 static gboolean
2231 gst_tizencamerasrc_negotiate (GstBaseSrc * basesrc)
2232 {
2233   GstCaps *thiscaps;
2234   GstCaps *caps = NULL;
2235   GstCaps *peercaps = NULL;
2236   gboolean result = FALSE;
2237   GstStructure *s;
2238   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(basesrc);
2239
2240   GST_INFO_OBJECT(camerasrc, "ENTERED");
2241   /* first see what is possible on our source pad */
2242   thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
2243   GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
2244
2245   /* nothing or anything is allowed, we're done */
2246   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
2247     goto no_nego_needed;
2248
2249   /* get the peer caps */
2250   peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
2251   GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
2252   //LOG_CAPS (basesrc, peercaps);
2253   if (peercaps && !gst_caps_is_any (peercaps)) {
2254     GstCaps *icaps = NULL;
2255     int i;
2256
2257     /* Prefer the first caps we are compatible with that the peer proposed */
2258     for (i = 0; i < gst_caps_get_size (peercaps); i++) {
2259       /* get intersection */
2260       GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
2261
2262       GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
2263       icaps = gst_caps_intersect (thiscaps, ipcaps);
2264       gst_caps_unref (ipcaps);
2265
2266       /*s = gst_caps_get_structure (icaps, 0);
2267       gst_structure_get_fourcc(s, "format", &camerasrc->fourcc);
2268       if ((camerasrc->fourcc == GST_MAKE_FOURCC('S','N','1','2')) ||
2269         (camerasrc->fourcc == GST_MAKE_FOURCC('S','T','1','2'))) {
2270         break;
2271       }*/
2272       if (!gst_caps_is_empty (icaps))
2273         break;
2274
2275       gst_caps_unref (icaps);
2276       icaps = NULL;
2277     }
2278
2279     GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
2280     if (icaps) {
2281       /* If there are multiple intersections pick the one with the smallest
2282       * resolution strictly bigger then the first peer caps */
2283       if (gst_caps_get_size (icaps) > 1) {
2284         s = gst_caps_get_structure (peercaps, 0);
2285         int best = 0;
2286         int twidth, theight;
2287         int width = G_MAXINT, height = G_MAXINT;
2288
2289         if (gst_structure_get_int (s, "width", &twidth)
2290           && gst_structure_get_int (s, "height", &theight)) {
2291
2292           /* Walk the structure backwards to get the first entry of the
2293           * smallest resolution bigger (or equal to) the preferred resolution)
2294           */
2295           for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
2296             GstStructure *is = gst_caps_get_structure (icaps, i);
2297             int w, h;
2298
2299             if (gst_structure_get_int (is, "width", &w)
2300               && gst_structure_get_int (is, "height", &h)) {
2301               if (w >= twidth && w <= width && h >= theight && h <= height) {
2302                 width = w;
2303                 height = h;
2304                 best = i;
2305               }
2306             }
2307           }
2308         }
2309
2310         caps = gst_caps_copy_nth (icaps, best);
2311         gst_caps_unref (icaps);
2312       } else {
2313         caps = icaps;
2314       }
2315     }
2316     gst_caps_unref (thiscaps);
2317     gst_caps_unref (peercaps);
2318   } else {
2319     /* no peer or peer have ANY caps, work with our own caps then */
2320     caps = thiscaps;
2321   }
2322   if (caps) {
2323         caps = gst_caps_fixate(caps);
2324
2325     /* now fixate */
2326     if (!gst_caps_is_empty (caps)) {
2327       GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
2328
2329       if (gst_caps_is_any (caps)) {
2330         /* hmm, still anything, so element can do anything and
2331         * nego is not needed */
2332         result = TRUE;
2333       } else if (gst_caps_is_fixed (caps)) {
2334         /* yay, fixed caps, use those then */
2335           result = gst_tizencamerasrc_set_caps(basesrc, caps);
2336       }
2337     }
2338     gst_caps_unref (caps);
2339   }
2340   return result;
2341
2342 no_nego_needed:
2343   {
2344     GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
2345     if (thiscaps)
2346       gst_caps_unref (thiscaps);
2347     return TRUE;
2348   }
2349 }
2350
2351
2352 static GstCaps *gst_tizencamerasrc_get_caps(GstBaseSrc *src, GstCaps *filter)
2353 {
2354   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(src);
2355   GstCaps *ret = NULL;
2356
2357   GST_DEBUG_OBJECT(camerasrc, "ENTERED");
2358
2359   if (camerasrc->mode == VIDEO_IN_MODE_NONE) {
2360     GST_INFO_OBJECT(camerasrc, "Just return template caps.");
2361     GST_DEBUG_OBJECT(camerasrc, "LEAVE");
2362
2363     ret = gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(camerasrc));
2364     return filter ? gst_caps_intersect(ret, filter) : gst_caps_copy(ret);
2365   }
2366
2367   /*FIXME: Using "VIDIOC_ENUM_FMT".*/
2368   ret = gst_caps_copy(gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(camerasrc)));
2369
2370   if (filter != NULL) {
2371       gst_caps_take(&ret, gst_caps_intersect(ret, filter));
2372   }
2373
2374   GST_INFO_OBJECT(camerasrc, "probed caps: %p", ret);
2375   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
2376
2377   return ret;
2378 }
2379
2380
2381 static gboolean __gst_tizencamerasrc_get_raw_pixel_info(int fourcc, camera_pixel_format_e *pix_format)
2382 {
2383   if (pix_format == NULL) {
2384     GST_ERROR("NULL pointer");
2385     return FALSE;
2386   }
2387
2388   switch (fourcc) {
2389   case GST_MAKE_FOURCC('I','4','2','0'):
2390   case GST_MAKE_FOURCC('S','4','2','0'):
2391     *pix_format = CAMERA_PIXEL_FORMAT_I420;;
2392     break;
2393   case GST_MAKE_FOURCC('Y','V','1','2'):
2394     *pix_format = CAMERA_PIXEL_FORMAT_YV12;
2395     break;
2396   case GST_MAKE_FOURCC('Y','U','Y','V'):
2397   case GST_MAKE_FOURCC('Y','U','Y','2'):
2398   case GST_MAKE_FOURCC('S','U','Y','V'):
2399   case GST_MAKE_FOURCC('S','U','Y','2'):
2400     *pix_format = CAMERA_PIXEL_FORMAT_YUYV;
2401     break;
2402   case GST_MAKE_FOURCC('U','Y','V','Y'):
2403   case GST_MAKE_FOURCC('S','Y','V','Y'):
2404     *pix_format = CAMERA_PIXEL_FORMAT_UYVY;
2405     break;
2406   case GST_MAKE_FOURCC('N','V','1','2'):
2407   case GST_MAKE_FOURCC('S','N','1','2'):
2408     *pix_format = CAMERA_PIXEL_FORMAT_NV12;
2409     break;
2410   case GST_MAKE_FOURCC('N','V','2','1'):
2411   case GST_MAKE_FOURCC('S','N','2','1'):
2412     *pix_format = CAMERA_PIXEL_FORMAT_NV21;
2413     break;
2414   case GST_MAKE_FOURCC('J','P','E','G'):
2415     *pix_format = CAMERA_PIXEL_FORMAT_JPEG;
2416     break;
2417   case GST_MAKE_FOURCC('M','J','P','G'):
2418     *pix_format = CAMERA_PIXEL_FORMAT_MJPEG;
2419     break;
2420   default:
2421     GST_ERROR("unknown fourcc %c%c%c%c",
2422       fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24);
2423     return FALSE;
2424   }
2425
2426   GST_INFO("pixel format[%c%c%c%c] -> [%d]",
2427     fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24,
2428     *pix_format);
2429
2430   return TRUE;
2431 }
2432
2433
2434 static gboolean __gst_tizencamerasrc_get_tbm_format(int pix_format, guint32 *tbm_format)
2435 {
2436   if (tbm_format == NULL) {
2437     GST_ERROR("NULL pointer");
2438     return FALSE;
2439   }
2440
2441   switch (pix_format) {
2442   case CAMERA_PIXEL_FORMAT_I420:
2443     *tbm_format = TBM_FORMAT_YUV420;
2444     break;
2445   case CAMERA_PIXEL_FORMAT_YV12:
2446     *tbm_format = TBM_FORMAT_YVU420;
2447     break;
2448   case CAMERA_PIXEL_FORMAT_YUYV:
2449     *tbm_format = TBM_FORMAT_YUYV;
2450     break;
2451   case CAMERA_PIXEL_FORMAT_UYVY:
2452     *tbm_format = TBM_FORMAT_UYVY;
2453     break;
2454   case CAMERA_PIXEL_FORMAT_NV12:
2455     *tbm_format = TBM_FORMAT_NV12;
2456     break;
2457   case CAMERA_PIXEL_FORMAT_NV21:
2458     *tbm_format = TBM_FORMAT_NV21;
2459     break;
2460   default:
2461     GST_WARNING("unsupported pixel format[%d] for tbm", pix_format);
2462     return FALSE;
2463   }
2464
2465   return TRUE;
2466 }
2467
2468
2469 static gboolean __gst_tizencamerasrc_get_frame_size(int fourcc, int width, int height, unsigned int *outsize)
2470 {
2471   switch (fourcc) {
2472   case GST_MAKE_FOURCC('I','4','2','0'):  /* V4L2_PIX_FMT_YUV420 */
2473   case GST_MAKE_FOURCC('I','Y','U','V'):
2474   case GST_MAKE_FOURCC('Y','U','1','2'):
2475   case GST_MAKE_FOURCC('Y','V','1','2'):
2476   case GST_MAKE_FOURCC('S','4','2','0'):  /* V4L2_PIX_FMT_NV12 tiled non-linear */
2477     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
2478     *outsize += 2 * ((GST_ROUND_UP_8 (width) / 2) * (GST_ROUND_UP_2 (height) / 2));
2479     break;
2480   case GST_MAKE_FOURCC('Y','U','Y','V'):  /* V4L2_PIX_FMT_YUYV */
2481   case GST_MAKE_FOURCC('Y','U','Y','2'):  /* V4L2_PIX_FMT_YUYV */
2482   case GST_MAKE_FOURCC('S','U','Y','V'):
2483   case GST_MAKE_FOURCC('S','U','Y','2'):
2484   case GST_MAKE_FOURCC('U','Y','V','Y'):  /* V4L2_PIX_FMT_UYVY */
2485   case GST_MAKE_FOURCC('S','Y','V','Y'):  /* V4L2_PIX_FMT_UYVY */
2486   case GST_MAKE_FOURCC('4','2','2','P'):  /* V4L2_PIX_FMT_YUV422P */
2487   case GST_MAKE_FOURCC('Y','4','2','B'):  /* V4L2_PIX_FMT_YUV422P */
2488   case GST_MAKE_FOURCC('Y','4','1','P'):  /* V4L2_PIX_FMT_Y41P */
2489     *outsize = (GST_ROUND_UP_2 (width) * 2) * height;
2490     break;
2491   case GST_MAKE_FOURCC('Y','4','1','B'):  /* V4L2_PIX_FMT_YUV411P */
2492     *outsize = GST_ROUND_UP_4 (width) * height;
2493     *outsize += 2 * ((GST_ROUND_UP_8 (width) / 4) * height);
2494     break;
2495   case GST_MAKE_FOURCC('N','V','1','2'):  /* V4L2_PIX_FMT_NV12 */
2496   case GST_MAKE_FOURCC('N','V','2','1'):  /* V4L2_PIX_FMT_NV21 */
2497   case GST_MAKE_FOURCC('S','N','1','2'):  /* V4L2_PIX_FMT_NV12 non-linear */
2498   case GST_MAKE_FOURCC('S','N','2','1'):  /* V4L2_PIX_FMT_NV21 non-linear */
2499     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
2500     *outsize += (GST_ROUND_UP_4 (width) * height) / 2;
2501     break;
2502   case GST_MAKE_FOURCC('J','P','E','G'):
2503   case GST_MAKE_FOURCC('M','J','P','G'):
2504     /* jpeg size can't be calculated here. */
2505     *outsize = 0;
2506     break;
2507   default:
2508     /* unknown format!! */
2509     *outsize = 0;
2510     break;
2511   }
2512
2513   return TRUE;
2514 }
2515
2516
2517 static GstCaps *__gst_tizencamerasrc_get_caps_from_buffer(camera_buffer_s *buffer)
2518 {
2519   char *format_string = NULL;
2520   char mimetype[32];
2521   GstCaps *caps = NULL;
2522
2523   if (!buffer) {
2524     GST_ERROR("NULL buffer");
2525     return NULL;
2526   }
2527
2528   switch (buffer->format) {
2529   case CAMERA_PIXEL_FORMAT_NV12:
2530     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2531     format_string = "NV12";
2532     break;
2533   case CAMERA_PIXEL_FORMAT_NV21:
2534     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2535     format_string = "NV21";
2536     break;
2537   case CAMERA_PIXEL_FORMAT_I420:
2538     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2539     format_string = "I420";
2540     break;
2541   case CAMERA_PIXEL_FORMAT_YV12:
2542     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2543     format_string = "YV12";
2544     break;
2545   case CAMERA_PIXEL_FORMAT_YUYV:
2546     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2547     format_string = "YUY2";
2548     break;
2549   case CAMERA_PIXEL_FORMAT_UYVY:
2550     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2551     format_string = "UYVY";
2552     break;
2553   case CAMERA_PIXEL_FORMAT_H264:
2554     snprintf(mimetype, sizeof(mimetype), "video/x-h264");
2555     break;
2556   case CAMERA_PIXEL_FORMAT_JPEG:
2557     snprintf(mimetype, sizeof(mimetype), "image/jpeg");
2558     break;
2559   case CAMERA_PIXEL_FORMAT_MJPEG:
2560     snprintf(mimetype, sizeof(mimetype), "video/x-jpeg");
2561     break;
2562   case CAMERA_PIXEL_FORMAT_VP8:
2563     snprintf(mimetype, sizeof(mimetype), "video/x-vp8");
2564     break;
2565   case CAMERA_PIXEL_FORMAT_VP9:
2566     snprintf(mimetype, sizeof(mimetype), "video/x-vp9");
2567     break;
2568   default:
2569     GST_ERROR("unsupported format[%d]", buffer->format);
2570     return NULL;
2571   }
2572
2573   caps = gst_caps_new_simple(mimetype,
2574     "width", G_TYPE_INT, buffer->resolution.width,
2575     "height", G_TYPE_INT, buffer->resolution.height,
2576     NULL);
2577   if (!caps) {
2578     GST_ERROR("caps failed for [%s][%s]", mimetype, format_string);
2579     return NULL;
2580   }
2581
2582   if (format_string)
2583     gst_caps_set_simple(caps, "format", G_TYPE_STRING, format_string, NULL);
2584
2585   GST_INFO("new caps [%"GST_PTR_FORMAT"]", caps);
2586
2587   return caps;
2588 }
2589
2590
2591 static gboolean gst_tizencamerasrc_get_caps_info(GstTizenCameraSrc *camerasrc, GstCaps *caps, guint *size)
2592 {
2593   gint fps_n = 0;
2594   gint fps_d = 0;
2595   gint width = 0;
2596   gint height = 0;
2597   gint rotate = 0;
2598   const gchar *mimetype;
2599   GstVideoInfo video_info;
2600   const gchar *caps_format_name = NULL;
2601   guint32 caps_fourcc = 0;
2602   const GValue *framerate;
2603   GstStructure *structure = NULL;
2604
2605   GST_WARNING_OBJECT(camerasrc, "caps[%"GST_PTR_FORMAT"]", caps);
2606
2607   structure = gst_caps_get_structure(caps, 0);
2608
2609   if (!gst_structure_get_int(structure, "width", &width)) {
2610     GST_ERROR_OBJECT(camerasrc, "width failed");
2611     return FALSE;
2612   }
2613
2614   if (!gst_structure_get_int(structure, "height", &height)) {
2615     GST_ERROR_OBJECT(camerasrc, "height failed");
2616     return FALSE;
2617   }
2618
2619   if (!gst_structure_get_int(structure, "rotate", &rotate))
2620     GST_WARNING_OBJECT(camerasrc, "Failed to get rotate info in caps. set default 0.");
2621   else
2622     GST_INFO_OBJECT(camerasrc, "Succeed to get rotate [%d] info in caps", rotate);
2623
2624   if (!gst_video_info_from_caps(&camerasrc->video_info, caps)) {
2625     GST_ERROR_OBJECT(camerasrc, "failed to get video info from caps");
2626     return FALSE;
2627   }
2628
2629   camerasrc->width = width;
2630   camerasrc->height = height;
2631   camerasrc->rotate = rotate;
2632
2633   framerate = gst_structure_get_value(structure, "framerate");
2634   if (!framerate) {
2635     GST_INFO("Set FPS as default(30/1)");
2636
2637     /* set default fps if framerate is not existed in caps */
2638     fps_n = _DEFAULT_FPS;
2639     fps_d = 1;
2640   } else {
2641     fps_n = gst_value_get_fraction_numerator(framerate);
2642     fps_d = gst_value_get_fraction_denominator(framerate);
2643
2644     /* numerator and denominator should be bigger than zero */
2645     if (fps_n <= 0) {
2646       GST_WARNING("numerator of FPS is %d. make it default(15).", fps_n);
2647       fps_n = _DEFAULT_FPS;
2648     }
2649
2650     if (fps_d <= 0) {
2651       GST_WARNING("denominator of FPS is %d. make it 1.", fps_d);
2652       fps_d = 1;
2653     }
2654   }
2655
2656   camerasrc->fps = (int)((float)fps_n / (float)fps_d);
2657
2658   if (!gst_video_info_from_caps(&video_info, caps)) {
2659     GST_ERROR_OBJECT(camerasrc, "get video info from caps[%"GST_PTR_FORMAT"]", caps);
2660     return FALSE;
2661   }
2662
2663   if (GST_VIDEO_INFO_IS_YUV(&video_info)) {
2664     caps_format_name = gst_structure_get_string(structure, "format");
2665     if (!caps_format_name) {
2666       GST_ERROR_OBJECT(camerasrc, "NULL format name from caps[%"GST_PTR_FORMAT"]", caps);
2667       return FALSE;
2668     }
2669
2670     g_strlcpy(camerasrc->format_name, caps_format_name, sizeof(camerasrc->format_name));
2671     caps_fourcc = MAKE_FOURCC_FROM_STRING(camerasrc->format_name);
2672
2673     __gst_tizencamerasrc_get_frame_size(caps_fourcc, width, height, size);
2674     __gst_tizencamerasrc_get_raw_pixel_info(caps_fourcc, &camerasrc->pix_format);
2675
2676     camerasrc->is_encoded_format = FALSE;
2677   } else {
2678
2679     mimetype = gst_structure_get_name(structure);
2680     *size = 0;
2681
2682     if (!strcmp(mimetype, "video/x-h264")) {
2683       g_strlcpy(camerasrc->format_name, GST_VIDEO_INFO_NAME(&video_info), sizeof(camerasrc->format_name));
2684       camerasrc->pix_format = CAMERA_PIXEL_FORMAT_H264;
2685     } else if (!strcmp(mimetype, "image/jpeg") || !strcmp(mimetype, "video/x-jpeg")) {
2686       g_strlcpy(camerasrc->format_name, GST_VIDEO_INFO_NAME(&video_info), sizeof(camerasrc->format_name));
2687       camerasrc->pix_format = CAMERA_PIXEL_FORMAT_MJPEG;
2688     } else if (!strcmp(mimetype, "video/x-vp8")) {
2689       g_strlcpy(camerasrc->format_name, GST_VIDEO_INFO_NAME(&video_info), sizeof(camerasrc->format_name));
2690       camerasrc->pix_format = CAMERA_PIXEL_FORMAT_VP8;
2691     } else if (!strcmp(mimetype, "video/x-vp9")) {
2692       g_strlcpy(camerasrc->format_name, GST_VIDEO_INFO_NAME(&video_info), sizeof(camerasrc->format_name));
2693       camerasrc->pix_format = CAMERA_PIXEL_FORMAT_VP9;
2694     } else {
2695       GST_ERROR_OBJECT(camerasrc, "unsupported caps[%"GST_PTR_FORMAT"]", caps);
2696       return FALSE;
2697     }
2698
2699     camerasrc->is_encoded_format = TRUE;
2700   }
2701
2702   GST_INFO_OBJECT(camerasrc, "pixformat[%d], size[%u] from [%"GST_PTR_FORMAT"]",
2703     camerasrc->pix_format, *size, caps);
2704
2705   return TRUE;
2706 }
2707
2708
2709 static void __gst_tizencamerasrc_post_message_int(GstTizenCameraSrc *camerasrc, const char *msg_name, const char *field_name, int value)
2710 {
2711   GstMessage *m = NULL;
2712   GstStructure *s = NULL;
2713
2714   if (!camerasrc || !msg_name || !field_name) {
2715     GST_ERROR("pointer is NULL %p, %p, %p", camerasrc, msg_name, field_name);
2716     return;
2717   }
2718
2719   GST_INFO("post message [%s] %s %d", msg_name, field_name, value);
2720
2721   s = gst_structure_new(msg_name, field_name, G_TYPE_INT, value, NULL);
2722   if (s == NULL) {
2723     GST_ERROR("gst_structure_new failed");
2724     gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_OUT_OF_MEMORY);
2725     return;
2726   }
2727
2728   m = gst_message_new_element(GST_OBJECT(camerasrc), s);
2729   if (m == NULL) {
2730     GST_ERROR("gst_message_new_element failed");
2731     gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_OUT_OF_MEMORY);
2732     return;
2733   }
2734
2735   gst_element_post_message(GST_ELEMENT(camerasrc), m);
2736
2737   return;
2738 }
2739
2740
2741 static int __gst_tizencamerasrc_release_buffer(GstTizenCameraSrc *camerasrc, GstTizenCameraBufferType type, int index, int stream_id)
2742 {
2743   if (!camerasrc) {
2744     GST_ERROR("NULL handle");
2745     return CAMERA_ERROR_INVALID_PARAMETER;
2746   }
2747
2748   switch (type) {
2749   case BUFFER_TYPE_PREVIEW:
2750     return hal_camera_release_preview_buffer(camerasrc->hal_handle, index);
2751   case BUFFER_TYPE_VIDEO:
2752     return hal_camera_release_video_buffer(camerasrc->hal_handle, index);
2753   case BUFFER_TYPE_EXTRA_PREVIEW:
2754     return hal_camera_release_extra_preview_buffer(camerasrc->hal_handle, stream_id, index);
2755   default:
2756     GST_ERROR_OBJECT(camerasrc, "unknown type[%d], [%d,%d]", type, index, stream_id);
2757     return CAMERA_ERROR_INVALID_PARAMETER;
2758   }
2759 }
2760
2761
2762 static gboolean gst_tizencamerasrc_set_caps(GstBaseSrc *src, GstCaps *caps)
2763 {
2764   guint size;
2765   GstTizenCameraSrc *camerasrc = NULL;
2766   gboolean res = FALSE;
2767
2768   int tbm_ret = 0;
2769   tbm_surface_h t_surface = NULL;
2770
2771   camerasrc = GST_TIZENCAMERA_SRC(src);
2772
2773   GST_INFO_OBJECT(camerasrc, "ENTERED");
2774
2775   if (camerasrc->mode == VIDEO_IN_MODE_PREVIEW ||
2776       camerasrc->mode == VIDEO_IN_MODE_VIDEO) {
2777     GST_INFO_OBJECT(camerasrc, "Proceed set_caps");
2778     GST_INFO("            gst_tizencamerasrc_stop");
2779     if (!gst_tizencamerasrc_stop(camerasrc)) {
2780       GST_INFO_OBJECT(camerasrc, "Cam sensor stop failed.");
2781     }
2782   } else if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE) {
2783     GST_ERROR_OBJECT(camerasrc, "A mode of avsystem camera is capture. Not to proceed set_caps.");
2784     GST_DEBUG_OBJECT(camerasrc, "LEAVE");
2785     return FALSE;
2786   } else {
2787     GST_INFO_OBJECT(camerasrc, "A mode of avsystem camera is unknown[%d]. Proceed set_caps.", camerasrc->mode);
2788   }
2789
2790   /* we want our own v4l2 type of fourcc codes */
2791   if (!gst_tizencamerasrc_get_caps_info(camerasrc, caps, &size)) {
2792     GST_INFO_OBJECT(camerasrc, "can't get capture information from caps %p", caps);
2793     return FALSE;
2794   }
2795
2796   /* get tbm surface info */
2797   if (__gst_tizencamerasrc_get_tbm_format(camerasrc->pix_format, &camerasrc->tbm_format)) {
2798
2799     t_surface = tbm_surface_create(camerasrc->width, camerasrc->height, camerasrc->tbm_format);
2800     if (!t_surface) {
2801       GST_ERROR_OBJECT(camerasrc, "tbm surface create failed");
2802       return FALSE;
2803     }
2804
2805     memset(&camerasrc->ts_info, 0x0, sizeof(tbm_surface_info_s));
2806
2807     tbm_ret = tbm_surface_get_info(t_surface, &camerasrc->ts_info);
2808
2809     GST_WARNING_OBJECT(camerasrc, "TBM info: res[%ux%u], stride[%u], size[%u]",
2810       camerasrc->ts_info.width, camerasrc->ts_info.height,
2811       camerasrc->ts_info.planes[0].stride, camerasrc->ts_info.size);
2812
2813     tbm_surface_destroy(t_surface);
2814     t_surface = NULL;
2815
2816     if (tbm_ret != TBM_SURFACE_ERROR_NONE) {
2817       GST_ERROR_OBJECT(camerasrc, "tbm surface info get failed");
2818       return FALSE;
2819     }
2820   } else if (camerasrc->pix_format != CAMERA_PIXEL_FORMAT_H264 &&
2821     camerasrc->pix_format != CAMERA_PIXEL_FORMAT_MJPEG &&
2822     camerasrc->pix_format != CAMERA_PIXEL_FORMAT_VP8 &&
2823     camerasrc->pix_format != CAMERA_PIXEL_FORMAT_VP9) {
2824     GST_ERROR_OBJECT(camerasrc, "unsupported pixel format %d",camerasrc->pix_format);
2825     return FALSE;
2826   }
2827
2828   GST_INFO("            gst_tizencamerasrc_start");
2829   if (!gst_tizencamerasrc_start(camerasrc)) {
2830     GST_INFO_OBJECT (camerasrc,  "Cam sensor start failed.");
2831   }
2832
2833   res = gst_pad_push_event (GST_BASE_SRC_PAD (src), gst_event_new_caps (caps));
2834
2835   GST_INFO_OBJECT (camerasrc, "LEAVE");
2836
2837   return res;
2838 }
2839
2840
2841 static gboolean gst_tizencamerasrc_unlock(GstBaseSrc *basesrc)
2842 {
2843   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(basesrc);
2844
2845   if (!camerasrc) {
2846     GST_ERROR("NULL handle");
2847     return FALSE;
2848   }
2849
2850   GST_INFO_OBJECT(camerasrc, "flush start");
2851
2852   camerasrc->is_flushing = TRUE;
2853
2854   return TRUE;
2855 }
2856
2857 static gboolean gst_tizencamerasrc_unlock_stop(GstBaseSrc *basesrc)
2858 {
2859   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(basesrc);
2860
2861   if (!camerasrc) {
2862     GST_ERROR("NULL handle");
2863     return FALSE;
2864   }
2865
2866   GST_INFO_OBJECT(camerasrc, "flush stop");
2867
2868   camerasrc->is_flushing = FALSE;
2869
2870   return TRUE;
2871 }
2872
2873 static void gst_tizencamerasrc_class_init(GstTizenCameraSrcClass *klass)
2874 {
2875   GST_DEBUG_CATEGORY_INIT(tizencamerasrc_debug, "tizencamerasrc", 0, "tizencamerasrc element");
2876
2877   GObjectClass *gobject_class;
2878   GstElementClass *element_class;
2879   GstBaseSrcClass *basesrc_class;
2880   GstPushSrcClass *pushsrc_class;
2881
2882   GST_DEBUG("ENTERED");
2883
2884   gobject_class = G_OBJECT_CLASS(klass);
2885   element_class = GST_ELEMENT_CLASS(klass);
2886   basesrc_class = GST_BASE_SRC_CLASS(klass);
2887   pushsrc_class = GST_PUSH_SRC_CLASS(klass);
2888
2889   gobject_class->set_property = gst_tizencamerasrc_set_property;
2890   gobject_class->get_property = gst_tizencamerasrc_get_property;
2891   gobject_class->finalize = gst_tizencamerasrc_finalize;
2892   element_class->change_state = gst_tizencamerasrc_change_state;
2893   gst_element_class_add_pad_template(element_class, gst_static_pad_template_get (&src_factory));
2894   gst_element_class_set_static_metadata(element_class,
2895     "Camera Source GStreamer Plug-in",
2896     "Source/Video",
2897     "camera src for videosrc based GStreamer Plug-in",
2898     "Jeongmo Yang <jm80.yang@samsung.com>");
2899   basesrc_class->start = gst_tizencamerasrc_src_start;
2900   basesrc_class->stop = gst_tizencamerasrc_src_stop;
2901   basesrc_class->get_caps = gst_tizencamerasrc_get_caps;
2902   basesrc_class->set_caps = gst_tizencamerasrc_set_caps;
2903   basesrc_class->negotiate = gst_tizencamerasrc_negotiate;
2904   basesrc_class->unlock = GST_DEBUG_FUNCPTR(gst_tizencamerasrc_unlock);
2905   basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(gst_tizencamerasrc_unlock_stop);
2906   pushsrc_class->create = gst_tizencamerasrc_src_create;
2907
2908   g_object_class_install_property(gobject_class, ARG_CAMERA_ID,
2909     g_param_spec_int("camera-id", "index number of camera to activate",
2910       "index number of camera to activate",
2911       _CAMERA_ID_MIN, _CAMERA_ID_MAX, 0,
2912       G_PARAM_READWRITE));
2913
2914   g_object_class_install_property(gobject_class, ARG_DEVICE_NAME,
2915     g_param_spec_string("device-name", "Device name",
2916       "Name of the device, camera-id will be ignored if this is set",
2917       NULL,
2918       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2919
2920   g_object_class_install_property(gobject_class, ARG_DEVICE_BUS,
2921     g_param_spec_int("device-bus", "The device bus number",
2922       "The device bus number",
2923       0, G_MAXINT, 0,
2924       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2925
2926   g_object_class_install_property(gobject_class, ARG_DEVICE_PORT,
2927     g_param_spec_string("device-port", "The device port number",
2928       "The device port number",
2929       NULL,
2930       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2931
2932   g_object_class_install_property(gobject_class, ARG_HAL_NAME,
2933     g_param_spec_string("hal-name", "HAL name",
2934       "Name of the HAL library, \"libtizen-camera.so\" will be used as a default",
2935       NULL,
2936       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2937
2938   g_object_class_install_property(gobject_class, ARG_VFLIP,
2939     g_param_spec_boolean("vflip", "Flip vertically",
2940       "Flip camera input vertically",
2941       0,
2942       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2943
2944   g_object_class_install_property(gobject_class, ARG_HFLIP,
2945     g_param_spec_boolean("hflip", "Flip horizontally",
2946       "Flip camera input horizontally",
2947       0,
2948       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2949
2950   g_object_class_install_property(gobject_class, ARG_HIGH_SPEED_FPS,
2951     g_param_spec_int("high-speed-fps", "Fps for high speed recording",
2952       "If this value is 0, the element doesn't activate high speed recording.",
2953       0, G_MAXINT, _DEFAULT_HIGH_SPEED_FPS,
2954       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2955
2956   g_object_class_install_property(gobject_class, ARG_AUTO_FPS,
2957     g_param_spec_boolean("fps-auto", "FPS Auto",
2958       "Field for auto fps setting",
2959       _DEFAULT_FPS_AUTO,
2960       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2961
2962   g_object_class_install_property(gobject_class, ARG_EXTRA_PREVIEW,
2963     g_param_spec_boolean("extra-preview", "Extra preview",
2964       "Flag for extra preview",
2965       _DEFAULT_EXTRA_PREVIEW,
2966       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2967
2968   g_object_class_install_property(gobject_class, ARG_LIVE_BUFFER_MAX,
2969     g_param_spec_int("live-buffer-max", "Live buffer max",
2970       "Maximum number of live buffers",
2971       1, G_MAXINT, _DEFAULT_LIVE_BUFFER_MAX,
2972       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2973
2974   g_object_class_install_property(gobject_class, ARG_LIVE_BUFFER_MAX_RAW,
2975     g_param_spec_int("live-buffer-max-raw", "Live buffer max for RAW format",
2976       "Maximum number of live buffers for RAW format",
2977       1, G_MAXINT, _DEFAULT_LIVE_BUFFER_MAX_RAW,
2978       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2979
2980   g_object_class_install_property(gobject_class, ARG_EMPTY_BUFFER_TIMEOUT,
2981     g_param_spec_int("empty-buffer-timeout", "Timeout for empty buffer",
2982       "Timeout to wait for buffer to be available. (ms, 0 = unlimited)",
2983       0, G_MAXINT, _DEFAULT_EMPTY_BUFFER_TIMEOUT,
2984       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2985
2986   g_object_class_install_property(gobject_class, ARG_BUFFER_QUARK,
2987     g_param_spec_uint("buffer-quark", "Buffer quark",
2988       "GQuark for buffer.",
2989       0, G_MAXUINT, _DEFAULT_BUFFER_QUARK,
2990       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
2991
2992   g_object_class_install_property(gobject_class, ARG_CAPTURE_FOURCC,
2993     g_param_spec_uint("capture-fourcc", "Capture format",
2994       "Fourcc value for capture format",
2995       0, G_MAXUINT, 0,
2996       G_PARAM_READWRITE));
2997
2998   g_object_class_install_property(gobject_class, ARG_CAPTURE_WIDTH,
2999     g_param_spec_int("capture-width", "Capture width",
3000       "Width for camera size to capture, it should be set before Height",
3001       0, G_MAXINT, _DEFAULT_CAP_WIDTH,
3002       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3003
3004   g_object_class_install_property(gobject_class, ARG_CAPTURE_HEIGHT,
3005     g_param_spec_int("capture-height", "Capture height",
3006       "Height for camera size to capture, it should be set after width",
3007       0, G_MAXINT, _DEFAULT_CAP_HEIGHT,
3008       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3009
3010   g_object_class_install_property(gobject_class, ARG_CAPTURE_INTERVAL,
3011     g_param_spec_int("capture-interval", "Capture interval",
3012       "Interval time to capture (millisecond)",
3013       0, G_MAXINT, _DEFAULT_CAP_INTERVAL,
3014       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3015
3016   g_object_class_install_property(gobject_class, ARG_CAPTURE_COUNT,
3017     g_param_spec_int("capture-count", "Capture count",
3018       "Capture count for multishot",
3019       1, G_MAXINT, _DEFAULT_CAP_COUNT,
3020       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3021
3022   g_object_class_install_property(gobject_class, ARG_CAPTURE_QUALITY,
3023     g_param_spec_int("capture-quality", "Capture quality",
3024       "Quality of capture image",
3025       1, 100, _DEFAULT_CAP_QUALITY,
3026       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3027
3028   g_object_class_install_property(gobject_class, ARG_CAPTURE_PROVIDE_EXIF,
3029     g_param_spec_boolean("provide-exif", "Whether EXIF is provided",
3030       "Does capture provide EXIF?",
3031       _DEFAULT_CAP_PROVIDE_EXIF,
3032       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
3033
3034   g_object_class_install_property(gobject_class, ARG_BITRATE,
3035     g_param_spec_int("bitrate", "Bitrate of encoded stream",
3036       "Bitrate of encoded stream like H.264",
3037       1, G_MAXINT, _DEFAULT_BITRATE,
3038       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3039
3040   g_object_class_install_property(gobject_class, ARG_GOP_INTERVAL,
3041     g_param_spec_int("gop-interval", "GOP interval of encoded stream",
3042       "GOP(Group Of Pictures) interval of encoded stream like H.264",
3043       1, G_MAXINT, _DEFAULT_GOP_INTERVAL,
3044       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3045
3046   /**
3047   * GstTizenCameraSrc::still-capture:
3048   * @camerasrc: the camerasrc instance
3049   * @buffer: the buffer that will be pushed - Main
3050   * @buffer: the buffer that will be pushed - Thumbnail
3051   * @buffer: the buffer that will be pushed - Screennail
3052   */
3053   gst_tizencamerasrc_signals[SIGNAL_STILL_CAPTURE] =
3054     g_signal_new("still-capture",
3055       G_TYPE_FROM_CLASS(klass),
3056       G_SIGNAL_RUN_LAST,
3057       G_STRUCT_OFFSET(GstTizenCameraSrcClass, still_capture),
3058       NULL,
3059       NULL,
3060       gst_tizencamerasrc_VOID__OBJECT_OBJECT_OBJECT,
3061       G_TYPE_NONE,
3062       3, /* Number of parameter */
3063       GST_TYPE_SAMPLE,  /* Main image buffer */
3064       GST_TYPE_SAMPLE,  /* Thumbnail image buffer */
3065       GST_TYPE_SAMPLE); /* Screennail image buffer */
3066
3067   /**
3068   * GstCameraSrc::video-stream-cb:
3069   * @camerasrc: the camerasrc instance
3070   * @buffer: the buffer that will be pushed
3071   */
3072   gst_tizencamerasrc_signals[SIGNAL_VIDEO_STREAM_CB] =
3073     g_signal_new("video-stream-cb",
3074       G_TYPE_FROM_CLASS(klass),
3075       G_SIGNAL_RUN_LAST,
3076       G_STRUCT_OFFSET(GstTizenCameraSrcClass, video_stream_cb),
3077       NULL,
3078       NULL,
3079       gst_tizencamerasrc_VOID__OBJECT_VIDEO_STREAM,
3080       G_TYPE_NONE,
3081       1, /* Number of parameter */
3082       GST_TYPE_SAMPLE); /* record buffer */
3083
3084   /**
3085   * GstCameraSrc::extra-preview-stream-cb:
3086   * @camerasrc: the camerasrc instance
3087   * @stream_id: the id of extra stream
3088   * @buffer: the buffer that will be pushed
3089   */
3090   gst_tizencamerasrc_signals[SIGNAL_EXTRA_PREVIEW_STREAM_CB] =
3091     g_signal_new("extra-preview-stream-cb",
3092       G_TYPE_FROM_CLASS(klass),
3093       G_SIGNAL_RUN_LAST,
3094       G_STRUCT_OFFSET(GstTizenCameraSrcClass, extra_preview_stream_cb),
3095       NULL,
3096       NULL,
3097       gst_tizencamerasrc_VOID__OBJECT_EXTRA_PREVIEW_STREAM,
3098       G_TYPE_NONE,
3099       2, /* Number of parameter */
3100       G_TYPE_INT,       /* stream id */
3101       GST_TYPE_SAMPLE); /* extra preview buffer */
3102
3103   GST_DEBUG("LEAVE");
3104
3105   return;
3106 }
3107
3108
3109 static void gst_tizencamerasrc_init(GstTizenCameraSrc *camerasrc)
3110 {
3111   GST_INFO_OBJECT(camerasrc, "ENTERED");
3112
3113   camerasrc->hal_handle = NULL;
3114   camerasrc->mode = VIDEO_IN_MODE_NONE;
3115   camerasrc->firsttime = TRUE;
3116   camerasrc->cap_count_current = -1;
3117   camerasrc->cap_count_reverse = _DEFAULT_CAP_COUNT;
3118
3119   /* camera */
3120   camerasrc->device_info = g_new0(camera_device_info_list_s, 1);
3121   camerasrc->fps = _DEFAULT_FPS;
3122   camerasrc->rotate = 0;
3123   camerasrc->high_speed_fps = _DEFAULT_HIGH_SPEED_FPS;
3124   camerasrc->fps_auto = _DEFAULT_FPS_AUTO;
3125   camerasrc->pix_format = _DEFAULT_PIX_FORMAT;
3126   g_strlcpy(camerasrc->format_name, _DEFAULT_PIX_FORMAT_NAME, sizeof(camerasrc->format_name));
3127   camerasrc->preview_control.running = FALSE;
3128   camerasrc->vflip = FALSE;
3129   camerasrc->hflip = FALSE;
3130   camerasrc->camera_id = _DEFAULT_CAMERA_ID;
3131   camerasrc->device_name = NULL;
3132   camerasrc->device_port = NULL;
3133   camerasrc->preview_buffer_list = g_queue_new ();
3134   camerasrc->live_buffer_max = _DEFAULT_LIVE_BUFFER_MAX;
3135   camerasrc->live_buffer_max_raw = _DEFAULT_LIVE_BUFFER_MAX_RAW;
3136   camerasrc->empty_buffer_timeout = _DEFAULT_EMPTY_BUFFER_TIMEOUT;
3137
3138   /* capture */
3139   camerasrc->cap_fourcc = MAKE_FOURCC_FROM_STRING(_DEFAULT_CAPTURE_FORMAT_NAME);
3140   camerasrc->cap_width = _DEFAULT_CAP_WIDTH;
3141   camerasrc->cap_height = _DEFAULT_CAP_HEIGHT;
3142   camerasrc->cap_interval = _DEFAULT_CAP_INTERVAL;
3143   camerasrc->cap_count = _DEFAULT_CAP_COUNT;
3144   camerasrc->cap_quality = _DEFAULT_CAP_QUALITY;
3145   camerasrc->cap_provide_exif = _DEFAULT_CAP_PROVIDE_EXIF;
3146
3147   /* encoded stream */
3148   camerasrc->bitrate = _DEFAULT_BITRATE;
3149   camerasrc->gop_interval = _DEFAULT_GOP_INTERVAL;
3150
3151   g_mutex_init(&camerasrc->preview_control.lock);
3152   g_cond_init(&camerasrc->preview_control.cond);
3153   g_mutex_init(&camerasrc->extra_preview_control.lock);
3154   g_cond_init(&camerasrc->extra_preview_control.cond);
3155   g_mutex_init(&camerasrc->video_control.lock);
3156   g_cond_init(&camerasrc->video_control.cond);
3157
3158   /* tizen allocator */
3159   camerasrc->allocator = gst_tizen_allocator_new();
3160
3161   camerasrc->buffer_quark = _DEFAULT_BUFFER_QUARK;
3162
3163   /* we operate in time */
3164   gst_base_src_set_format(GST_BASE_SRC(camerasrc), GST_FORMAT_TIME);
3165   gst_base_src_set_live(GST_BASE_SRC(camerasrc), TRUE);
3166   gst_base_src_set_do_timestamp(GST_BASE_SRC(camerasrc), TRUE);
3167
3168   GST_INFO_OBJECT(camerasrc, "LEAVE");
3169
3170   return;
3171 }
3172
3173
3174 static gboolean plugin_init(GstPlugin *plugin)
3175 {
3176   gboolean error;
3177
3178   error = gst_element_register(plugin, "tizencamerasrc", GST_RANK_PRIMARY + 100, GST_TYPE_TIZENCAMERA_SRC);
3179
3180   return error;
3181 }
3182
3183
3184 GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
3185                   GST_VERSION_MINOR,
3186                   tizencamerasrc,
3187                   "Tizen reference camera source plug-in",
3188                   plugin_init,
3189                   PACKAGE_VERSION,
3190                   "LGPL",
3191                   "Samsung Electronics Co",
3192                   "http://www.samsung.com")
3193
3194 /* GstURIHandler interface */
3195 static GstURIType
3196 gst_tizencamerasrc_uri_get_type (GType type)
3197 {
3198   return GST_URI_SRC;
3199 }
3200
3201 static const gchar * const*
3202 gst_tizencamerasrc_uri_get_protocols (GType type)
3203 {
3204   static const gchar *protocols[] = { "camera", NULL };
3205   return protocols;
3206 }
3207
3208 static gchar *
3209 gst_tizencamerasrc_uri_get_uri (GstURIHandler * handler)
3210 {
3211   return strdup("camera://0");
3212 }
3213
3214 static gboolean
3215 gst_tizencamerasrc_uri_set_uri (GstURIHandler * handler, const gchar * uri, GError **error)
3216 {
3217   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC (handler);
3218   const gchar *device = "0";
3219   if (strcmp (uri, "camera://") != 0) {
3220     device = uri + 9;
3221   }
3222   g_object_set (camerasrc, "camera-id", atoi(device), NULL);
3223
3224   return TRUE;
3225 }
3226
3227
3228 static void
3229 gst_tizencamerasrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
3230 {
3231   GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
3232
3233   iface->get_type = gst_tizencamerasrc_uri_get_type;
3234   iface->get_protocols = gst_tizencamerasrc_uri_get_protocols;
3235   iface->get_uri = gst_tizencamerasrc_uri_get_uri;
3236   iface->set_uri = gst_tizencamerasrc_uri_set_uri;
3237 }
3238 /* EOF */