[tizencamerasrc] Support video command 72/197572/4
authorJeongmo Yang <jm80.yang@samsung.com>
Mon, 14 Jan 2019 07:24:39 +0000 (16:24 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Wed, 23 Jan 2019 00:55:08 +0000 (00:55 +0000)
[Version] 1.0.0
[Profile] Common
[Issue Type] Update
[Dependency module] N/A

Change-Id: I5aceed6108476010046104d815b4a11bd35ea498
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
tizencamerasrc/src/gsttizencamerasrc.c
tizencamerasrc/src/gsttizencamerasrccontrol.c
tizencamerasrc/src/include/gsttizencamerasrc.h
tizencamerasrc/src/include/gsttizencamerasrccontrol.h

index 684f7ff..9022b96 100644 (file)
@@ -101,6 +101,7 @@ enum {
 enum {
   /*signal*/
   SIGNAL_STILL_CAPTURE,
+  SIGNAL_VIDEO_STREAM_CB,
 
   /*SIGNAL_REGISTER_TROUBLE,*/
   LAST_SIGNAL
@@ -122,6 +123,12 @@ enum {
   ARG_CAMERA_CAPTURE_JPG_QUALITY,
   ARG_CAMERA_CAPTURE_PROVIDE_EXIF,
 
+  /* record */
+  ARG_CAMERA_VIDEO_WIDTH,
+  ARG_CAMERA_VIDEO_HEIGHT,
+  ARG_CAMERA_VIDEO_FPS,
+  ARG_CAMERA_RECORDING_HINT,
+
   /* etc */
   ARG_VFLIP,
   ARG_HFLIP,
@@ -146,6 +153,14 @@ static GstStaticPadTemplate src_factory =
                           GST_PAD_SRC,
                           GST_PAD_ALWAYS,
                           GST_STATIC_CAPS("video/x-raw,"
+                                          "format = (string) { NV12 }, "
+                                          "width = (int) [ 1, 4096 ], "
+                                          "height = (int) [ 1, 4096 ]; "
+                                          "video/x-raw,"
+                                          "format = (string) { SN12 }, "
+                                          "width = (int) [ 1, 4096 ], "
+                                          "height = (int) [ 1, 4096 ]; "
+                                          "video/x-raw,"
                                           "format = (string) { I420 }, "
                                           "width = (int) [ 1, 4096 ], "
                                           "height = (int) [ 1, 4096 ]; "
@@ -180,6 +195,7 @@ static gboolean gst_tizencamerasrc_capture_stop(GstTizenCameraSrc *camerasrc);
 static void gst_tizencamerasrc_error_handler(GstTizenCameraSrc *camerasrc, int ret);
 static GstBuffer *gst_tizencamerasrc_buffer_new(GstTizenCameraSrc *camerasrc, camera_buffer_t *buffer, GstTizenCameraBufferType type);
 static void gst_tizencamerasrc_buffer_finalize(GstTizenCameraBuffer *buffer);
+static void gst_tizencamerasrc_set_video_format(GstTizenCameraSrc *camerasrc);
 
 /* Util functions */
 #if 0
@@ -304,17 +320,24 @@ static void gst_tizencamerasrc_buffer_finalize(GstTizenCameraBuffer *buffer)
 
   if (buffer->type == BUFFER_TYPE_PREVIEW) {
     camera_hal_interface_release_preview_buffer(camerasrc->hal_intf_handle, buffer->index);
+
+    g_mutex_lock(&camerasrc->preview_buffer_lock);
+    camerasrc->preview_live_buffers--;
+    GST_LOG_OBJECT(camerasrc, "preview live buffers %d", camerasrc->preview_live_buffers);
+    g_cond_broadcast(&camerasrc->preview_buffer_cond);
+    g_mutex_unlock(&camerasrc->preview_buffer_lock);
   } else if (buffer->type == BUFFER_TYPE_VIDEO) {
     camera_hal_interface_release_video_buffer(camerasrc->hal_intf_handle, buffer->index);
+
+    g_mutex_lock(&camerasrc->video_buffer_lock);
+    camerasrc->video_live_buffers--;
+    GST_LOG_OBJECT(camerasrc, "video live buffers %d", camerasrc->video_live_buffers);
+    g_cond_broadcast(&camerasrc->video_buffer_cond);
+    g_mutex_unlock(&camerasrc->video_buffer_lock);
   } else {
     GST_ERROR_OBJECT(camerasrc, "unknown type %d", buffer->type);
   }
 
-  g_mutex_lock(&camerasrc->buffer_lock);
-  camerasrc->num_live_buffers--;
-  g_cond_broadcast(&camerasrc->buffer_cond);
-  g_mutex_unlock(&camerasrc->buffer_lock);
-
   if (buffer->t_surface) {
     tbm_surface_destroy(buffer->t_surface);
     buffer->t_surface = NULL;
@@ -329,6 +352,58 @@ static void gst_tizencamerasrc_buffer_finalize(GstTizenCameraBuffer *buffer)
 }
 
 
+static void gst_tizencamerasrc_set_video_format(GstTizenCameraSrc *camerasrc)
+{
+  int ret = CAMERA_ERROR_NONE;
+  camera_format_t set_format;
+
+  if (!camerasrc) {
+    GST_ERROR("NULL handle");
+    return;
+  }
+
+  CLEAR(set_format);
+
+  set_format.stream_format = camerasrc->pix_format;
+  set_format.stream_resolution.width = camerasrc->video_width;
+  set_format.stream_resolution.height = camerasrc->video_height;
+  set_format.stream_fps = camerasrc->video_fps;
+
+  switch (camerasrc->rotate) {
+  case 90:
+    set_format.stream_rotation = CAMERA_ROTATION_90;
+    break;
+  case 180:
+    set_format.stream_rotation = CAMERA_ROTATION_180;
+    break;
+  case 270:
+    set_format.stream_rotation = CAMERA_ROTATION_270;
+    break;
+  case 0:
+  default:
+    set_format.stream_rotation = CAMERA_ROTATION_0;
+    break;
+  }
+
+  set_format.capture_format = CAMERA_PIXEL_FORMAT_JPEG;
+  set_format.capture_resolution.width = camerasrc->cap_width;
+  set_format.capture_resolution.height = camerasrc->cap_height;
+  set_format.capture_quality = (uint32_t)camerasrc->cap_jpg_quality;
+
+  GST_INFO_OBJECT(camerasrc, "video resolution %dx%d, fps %d, format %d, rotation %d",
+    set_format.stream_resolution.width, set_format.stream_resolution.height,
+    set_format.stream_fps, set_format.stream_format, set_format.stream_rotation);
+
+  ret = camera_hal_interface_set_video_stream_format(camerasrc->hal_intf_handle, &set_format);
+  if (ret != CAMERA_ERROR_NONE)
+    GST_ERROR_OBJECT(camerasrc, "set video stream failed 0x%x", ret);
+
+  GST_INFO_OBJECT(camerasrc, "done");
+
+  return;
+}
+
+
 static void gst_tizencamerasrc_error_handler(GstTizenCameraSrc *camerasrc, int ret)
 {
   if (!camerasrc) {
@@ -383,10 +458,9 @@ static void gst_tizencamerasrc_error_handler(GstTizenCameraSrc *camerasrc, int r
 
 
 /* VOID:OBJECT,OBJECT,OBJECT (generated by 'glib-genmarshal') */
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
 #define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
 static void
-g_cclosure_user_marshal_VOID__OBJECT_OBJECT_OBJECT(GClosure *closure,
+g_tizencamerasrc_marshal_VOID__OBJECT_OBJECT_OBJECT(GClosure *closure,
   GValue *return_value G_GNUC_UNUSED,
   guint n_param_values,
   const GValue *param_values,
@@ -417,14 +491,46 @@ g_cclosure_user_marshal_VOID__OBJECT_OBJECT_OBJECT(GClosure *closure,
   callback = (GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT)(marshal_data ? marshal_data : cc->callback);
 
   callback(data1,
-    g_marshal_value_peek_object (param_values + 1),
-    g_marshal_value_peek_object (param_values + 2),
-    g_marshal_value_peek_object (param_values + 3),
+    g_marshal_value_peek_object(param_values + 1),
+    g_marshal_value_peek_object(param_values + 2),
+    g_marshal_value_peek_object(param_values + 3),
     data2);
 
   return;
 }
 
+void
+gst_tizencamerasrc_VOID__OBJECT_VIDEO_STREAM(GClosure *closure,
+  GValue *return_value,
+  guint n_param_values,
+  const GValue *param_values,
+  gpointer invocation_hint,
+  gpointer marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__OBJECT_VIDEO_STREAM)(gpointer data1,
+    gpointer arg,
+    gpointer data2);
+  register GMarshalFunc_VOID__OBJECT_VIDEO_STREAM callback;
+  register GCClosure *cc = (GCClosure *) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA(closure)) {
+    data1 = closure->data;
+    data2 = g_value_peek_pointer(param_values + 0);
+  } else {
+    data1 = g_value_peek_pointer(param_values + 0);
+    data2 = closure->data;
+  }
+
+  callback = (GMarshalFunc_VOID__OBJECT_VIDEO_STREAM)(marshal_data ? marshal_data : cc->callback);
+
+  callback(data1,
+    g_marshal_value_peek_object(param_values + 1),
+    data2);
+}
+
 /* use following BOILERPLATE MACRO as _get_type entry */
 G_DEFINE_TYPE_WITH_CODE(GstTizenCameraSrc, gst_tizencamerasrc, GST_TYPE_PUSH_SRC,
   G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, gst_tizencamerasrc_uri_handler_init)
@@ -477,13 +583,13 @@ static int _camera_preview_frame_cb(camera_buffer_t *buffer, camera_metadata_t *
 
   camerasrc = (GstTizenCameraSrc *)user_data;
 
-  g_mutex_lock(&camerasrc->buffer_lock);
-  if (!camerasrc->buffer_running) {
-    GST_WARNING_OBJECT(camerasrc, "buffer is NOT running");
+  g_mutex_lock(&camerasrc->preview_buffer_lock);
+  if (!camerasrc->preview_buffer_running) {
+    GST_WARNING_OBJECT(camerasrc, "preview buffer is NOT running");
 
     camera_hal_interface_release_preview_buffer(camerasrc->hal_intf_handle, buffer->index);
 
-    goto _FRAME_CB_DONE;
+    goto _PREVIEW_FRAME_CB_DONE;
   }
 
   /* create new buffer */
@@ -493,21 +599,100 @@ static int _camera_preview_frame_cb(camera_buffer_t *buffer, camera_metadata_t *
 
     camera_hal_interface_release_preview_buffer(camerasrc->hal_intf_handle, buffer->index);
 
-    goto _FRAME_CB_DONE;
+    goto _PREVIEW_FRAME_CB_DONE;
   }
 
-  camerasrc->num_live_buffers++;
+  camerasrc->preview_live_buffers++;
 
   /* add new buffer to preview buffer list */
   g_queue_push_tail(camerasrc->preview_buffer_list, gst_buffer);
 
-  GST_DEBUG_OBJECT(camerasrc, "index %d, %p [size total %u][num_live_buffers %d]",
-    buffer->index, gst_buffer, buffer->total_size, camerasrc->num_live_buffers);
+  GST_DEBUG_OBJECT(camerasrc, "index %d, %p [size total %u][preview_live_buffers %d]",
+    buffer->index, gst_buffer, buffer->total_size, camerasrc->preview_live_buffers);
 
-  g_cond_broadcast(&camerasrc->buffer_cond);
+  g_cond_broadcast(&camerasrc->preview_buffer_cond);
 
-_FRAME_CB_DONE:
-  g_mutex_unlock(&camerasrc->buffer_lock);
+_PREVIEW_FRAME_CB_DONE:
+  g_mutex_unlock(&camerasrc->preview_buffer_lock);
+
+  GST_DEBUG_OBJECT(camerasrc, "done");
+
+  return TRUE;
+}
+
+
+static int _camera_video_frame_cb(camera_buffer_t *buffer, camera_metadata_t *meta, void *user_data)
+{
+  GstTizenCameraSrc *camerasrc = NULL;
+  GstBuffer *gst_buffer = NULL;
+  GstSample *gst_sample = NULL;
+  GstCaps *gst_caps = NULL;
+
+  if (!buffer || !user_data) {
+    GST_ERROR("video callback error %p %p", buffer, user_data);
+    return FALSE;
+  }
+
+  camerasrc = (GstTizenCameraSrc *)user_data;
+
+  g_mutex_lock(&camerasrc->video_buffer_lock);
+  if (!camerasrc->video_buffer_running) {
+    GST_WARNING_OBJECT(camerasrc, "video buffer is NOT running");
+
+    camera_hal_interface_release_video_buffer(camerasrc->hal_intf_handle, buffer->index);
+
+    goto _VIDEO_FRAME_CB_DONE;
+  }
+
+  /* create new buffer */
+  gst_buffer = gst_tizencamerasrc_buffer_new(camerasrc, buffer, BUFFER_TYPE_VIDEO);
+  if (!gst_buffer) {
+    GST_ERROR_OBJECT(camerasrc, "new buffer allocation failed. size %u", buffer->total_size);
+
+    camera_hal_interface_release_video_buffer(camerasrc->hal_intf_handle, buffer->index);
+
+    goto _VIDEO_FRAME_CB_DONE;
+  }
+
+  if (camerasrc->video_first_frame) {
+    /* caps should be set for first buffer */
+    gst_caps = gst_caps_new_simple("video/x-raw",
+      "format", G_TYPE_STRING, camerasrc->format_name,
+      "width", G_TYPE_INT, camerasrc->video_width,
+      "height", G_TYPE_INT, camerasrc->video_height,
+      "framerate", GST_TYPE_FRACTION, camerasrc->video_fps, 1,
+      NULL);
+
+    GST_INFO_OBJECT(camerasrc, "set caps for first video frame %"GST_PTR_FORMAT, gst_caps);
+  }
+
+  gst_sample = gst_sample_new(gst_buffer, gst_caps, NULL, NULL);
+
+  if (gst_caps) {
+    gst_caps_unref(gst_caps);
+    gst_caps = NULL;
+  }
+
+  camerasrc->video_live_buffers++;
+
+  GST_DEBUG_OBJECT(camerasrc, "index %d, %p, %p [size total %u][video_live_buffers %d]",
+    buffer->index, gst_sample, gst_buffer, buffer->total_size, camerasrc->video_live_buffers);
+
+_VIDEO_FRAME_CB_DONE:
+  g_mutex_unlock(&camerasrc->video_buffer_lock);
+
+  if (gst_sample) {
+    if (camerasrc->video_first_frame) {
+
+    }
+
+    /* signal callback for video stream */
+    g_signal_emit(G_OBJECT(camerasrc),
+      gst_tizencamerasrc_signals[SIGNAL_VIDEO_STREAM_CB],
+      0,
+      gst_sample
+      );
+  }
 
   GST_DEBUG_OBJECT(camerasrc, "done");
 
@@ -906,20 +1091,20 @@ static gboolean gst_tizencamerasrc_start(GstTizenCameraSrc *camerasrc)
 
   GST_INFO("VFLIP : %d, HFLIP : %d", camerasrc->vflip, camerasrc->hflip);
 
-  camerasrc->num_live_buffers = 0;
+  camerasrc->preview_live_buffers = 0;
 
   /* start preview stream */
   ret = camera_hal_interface_start_preview(camerasrc->hal_intf_handle, _camera_preview_frame_cb, camerasrc);
   if (ret != CAMERA_ERROR_NONE) {
     GST_ERROR_OBJECT(camerasrc, "camera_hal_interface_start_preview() failed 0x%x", ret);
-    camerasrc->buffer_running = FALSE;
+    camerasrc->preview_buffer_running = FALSE;
     goto _ERROR;
   }
 
   GST_INFO_OBJECT(camerasrc, "camerasrc_start_preview_stream() done");
 
   camerasrc->mode = VIDEO_IN_MODE_PREVIEW;
-  camerasrc->buffer_running = TRUE;
+  camerasrc->preview_buffer_running = TRUE;
 
   GST_INFO_OBJECT(camerasrc, "LEAVED");
 
@@ -942,17 +1127,17 @@ static gboolean gst_tizencamerasrc_stop(GstTizenCameraSrc *camerasrc)
   GST_INFO_OBJECT (camerasrc, "ENTERED");
 
   if (camerasrc->hal_intf_handle) {
-    g_mutex_lock(&camerasrc->buffer_lock);
+    g_mutex_lock(&camerasrc->preview_buffer_lock);
 
-    if (camerasrc->buffer_running) {
-      camerasrc->buffer_running = FALSE;
+    if (camerasrc->preview_buffer_running) {
+      camerasrc->preview_buffer_running = FALSE;
     } else {
       GST_ERROR_OBJECT(camerasrc, "buffer NOT running");
-      g_mutex_unlock(&camerasrc->buffer_lock);
+      g_mutex_unlock(&camerasrc->preview_buffer_lock);
       return FALSE;
     }
 
-    g_mutex_unlock(&camerasrc->buffer_lock);
+    g_mutex_unlock(&camerasrc->preview_buffer_lock);
 
     /* remove all cached buffers */
     while (!g_queue_is_empty(camerasrc->preview_buffer_list)) {
@@ -961,20 +1146,20 @@ static gboolean gst_tizencamerasrc_stop(GstTizenCameraSrc *camerasrc)
       gst_buffer_unref(buffer);
     }
 
-    g_mutex_lock(&camerasrc->buffer_lock);
+    g_mutex_lock(&camerasrc->preview_buffer_lock);
 
     /* wait until all buffers are returned */
-    while (camerasrc->num_live_buffers > 0) {
+    while (camerasrc->preview_live_buffers > 0) {
       end_time = g_get_monotonic_time() + 1 * G_TIME_SPAN_SECOND;
-      if (!g_cond_wait_until(&camerasrc->buffer_cond, &camerasrc->buffer_lock, end_time)) {
+      if (!g_cond_wait_until(&camerasrc->preview_buffer_cond, &camerasrc->preview_buffer_lock, end_time)) {
         GST_ERROR_OBJECT(camerasrc, "buffer wait failed");
         break;
       } else {
-        GST_INFO_OBJECT(camerasrc, "signal received. check again [num %d]", camerasrc->num_live_buffers);
+        GST_INFO_OBJECT(camerasrc, "signal received. check again [num %d]", camerasrc->preview_live_buffers);
       }
     }
 
-    g_mutex_unlock(&camerasrc->buffer_lock);
+    g_mutex_unlock(&camerasrc->preview_buffer_lock);
 
     GST_INFO_OBJECT(camerasrc, "stop preview stream");
 
@@ -982,7 +1167,7 @@ static gboolean gst_tizencamerasrc_stop(GstTizenCameraSrc *camerasrc)
     ret = camera_hal_interface_stop_preview(camerasrc->hal_intf_handle);
     if (ret != CAMERA_ERROR_NONE) {
       GST_ERROR_OBJECT(camerasrc, "camera_hal_interface_stop_preview failed 0x%x", ret);
-      camerasrc->buffer_running = TRUE;
+      camerasrc->preview_buffer_running = TRUE;
       return FALSE;
     }
 
@@ -1003,36 +1188,36 @@ static gboolean gst_tizencamerasrc_capture_start(GstTizenCameraSrc *camerasrc)
 
   if (camerasrc->mode == VIDEO_IN_MODE_PREVIEW) {
     /* set preview buffer running flag to FALSE to release preview buffer immediately */
-    g_mutex_lock(&camerasrc->buffer_lock);
+    g_mutex_lock(&camerasrc->preview_buffer_lock);
 
-    if (camerasrc->buffer_running) {
-      camerasrc->buffer_running = FALSE;
+    if (camerasrc->preview_buffer_running) {
+      camerasrc->preview_buffer_running = FALSE;
     } else {
       GST_ERROR_OBJECT(camerasrc, "buffer NOT running");
-      g_mutex_unlock(&camerasrc->buffer_lock);
+      g_mutex_unlock(&camerasrc->preview_buffer_lock);
       return FALSE;
     }
 
-    g_mutex_unlock(&camerasrc->buffer_lock);
+    g_mutex_unlock(&camerasrc->preview_buffer_lock);
 
     GST_INFO_OBJECT(camerasrc, "start capture");
 
     ret = camera_hal_interface_start_capture(camerasrc->hal_intf_handle, _camera_capture_cb, camerasrc);
     if (ret != CAMERA_ERROR_NONE) {
       GST_ERROR_OBJECT(camerasrc, "camera_hal_interface_start_capture failed 0x%x", ret);
-      camerasrc->buffer_running = TRUE;
+      camerasrc->preview_buffer_running = TRUE;
       return FALSE;
     }
 
     camerasrc->mode = VIDEO_IN_MODE_CAPTURE;
 
-    g_mutex_lock(&camerasrc->buffer_lock);
+    g_mutex_lock(&camerasrc->preview_buffer_lock);
 
-    camerasrc->buffer_running = TRUE;
+    camerasrc->preview_buffer_running = TRUE;
 
-    g_cond_signal(&camerasrc->buffer_cond);
+    g_cond_signal(&camerasrc->preview_buffer_cond);
 
-    g_mutex_unlock(&camerasrc->buffer_lock);
+    g_mutex_unlock(&camerasrc->preview_buffer_lock);
 
     GST_INFO_OBJECT(camerasrc, "CAPTURE STARTED!");
 
@@ -1057,13 +1242,13 @@ static gboolean gst_tizencamerasrc_capture_stop(GstTizenCameraSrc *camerasrc)
       return FALSE;
     }
 
-    g_mutex_lock(&camerasrc->buffer_lock);
+    g_mutex_lock(&camerasrc->preview_buffer_lock);
 
     camerasrc->mode = VIDEO_IN_MODE_PREVIEW;
 
-    g_cond_signal(&camerasrc->buffer_cond);
+    g_cond_signal(&camerasrc->preview_buffer_cond);
 
-    g_mutex_unlock(&camerasrc->buffer_lock);
+    g_mutex_unlock(&camerasrc->preview_buffer_lock);
 
     GST_INFO_OBJECT(camerasrc, "CAPTURE STOPPED!");
 
@@ -1082,16 +1267,16 @@ static GstFlowReturn gst_tizencamerasrc_read_preview(GstTizenCameraSrc *camerasr
 
   GST_DEBUG_OBJECT(camerasrc, "check preview buffer list");
 
-  g_mutex_lock(&camerasrc->buffer_lock);
+  g_mutex_lock(&camerasrc->preview_buffer_lock);
 
   while (g_queue_is_empty(camerasrc->preview_buffer_list)) {
     GST_DEBUG_OBJECT(camerasrc, "Preview buffer list is empty. waiting...");
 
     if (camerasrc->mode == VIDEO_IN_MODE_PREVIEW) {
       end_time = g_get_monotonic_time () + _PREVIEW_BUFFER_WAIT_TIMEOUT;
-      if (!g_cond_wait_until(&camerasrc->buffer_cond, &camerasrc->buffer_lock, end_time)) {
+      if (!g_cond_wait_until(&camerasrc->preview_buffer_cond, &camerasrc->preview_buffer_lock, end_time)) {
         GST_ERROR_OBJECT(camerasrc, "Buffer wait timeout[%d usec]. Return ERROR", _PREVIEW_BUFFER_WAIT_TIMEOUT);
-        g_mutex_unlock(&camerasrc->buffer_lock);
+        g_mutex_unlock(&camerasrc->preview_buffer_lock);
         gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_DEVICE_READ);
         return GST_FLOW_ERROR;
       } else {
@@ -1100,12 +1285,12 @@ static GstFlowReturn gst_tizencamerasrc_read_preview(GstTizenCameraSrc *camerasr
       }
     } else if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE) {
       GST_INFO_OBJECT(camerasrc, "now capture mode. wait...");
-      g_cond_wait(&camerasrc->buffer_cond, &camerasrc->buffer_lock);
+      g_cond_wait(&camerasrc->preview_buffer_cond, &camerasrc->preview_buffer_lock);
       GST_INFO_OBJECT(camerasrc, "capture mode - signal received, check preview buffer again.");
       preview_check_count = 0;
     } else if (preview_check_count > 5) {
       GST_ERROR_OBJECT(camerasrc, "preview buffer check failed");
-      g_mutex_unlock(&camerasrc->buffer_lock);
+      g_mutex_unlock(&camerasrc->preview_buffer_lock);
       gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_DEVICE_READ);
       return GST_FLOW_ERROR;
     }
@@ -1113,7 +1298,7 @@ static GstFlowReturn gst_tizencamerasrc_read_preview(GstTizenCameraSrc *camerasr
 
   *buffer = g_queue_pop_head(camerasrc->preview_buffer_list);
 
-  g_mutex_unlock(&camerasrc->buffer_lock);
+  g_mutex_unlock(&camerasrc->preview_buffer_lock);
 
   if (*buffer == NULL) {
     GST_ERROR_OBJECT(camerasrc, "popped buffer is NULL");
@@ -1332,6 +1517,26 @@ static void gst_tizencamerasrc_set_property(GObject *object, guint prop_id,
     camerasrc->hflip = g_value_get_boolean(value);
     GST_INFO_OBJECT(camerasrc, "Set HFLIP : %d", camerasrc->hflip);
     break;
+  case ARG_CAMERA_VIDEO_WIDTH:
+    camerasrc->video_width = g_value_get_int(value);
+    GST_INFO_OBJECT(camerasrc, "video width %d", camerasrc->video_width);
+    break;
+  case ARG_CAMERA_VIDEO_HEIGHT:
+    camerasrc->video_height = g_value_get_int(value);
+    GST_INFO_OBJECT(camerasrc, "video height %d", camerasrc->video_height);
+    break;
+  case ARG_CAMERA_VIDEO_FPS:
+    camerasrc->video_fps = g_value_get_int(value);
+    GST_INFO_OBJECT(camerasrc, "video fps %d", camerasrc->video_fps);
+    break;
+  case ARG_CAMERA_RECORDING_HINT:
+    camerasrc->recording_hint = g_value_get_boolean(value);
+
+    GST_INFO_OBJECT(camerasrc, "recording-hint %d", camerasrc->recording_hint);
+
+    if (camerasrc->recording_hint)
+      gst_tizencamerasrc_set_video_format(camerasrc);
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     break;
@@ -1388,6 +1593,18 @@ static void gst_tizencamerasrc_get_property(GObject *object, guint prop_id,
   case ARG_HFLIP:
     g_value_set_boolean(value, camerasrc->hflip);
     break;
+  case ARG_CAMERA_VIDEO_WIDTH:
+    g_value_set_int(value, camerasrc->video_width);
+    break;
+  case ARG_CAMERA_VIDEO_HEIGHT:
+    g_value_set_int(value, camerasrc->video_height);
+    break;
+  case ARG_CAMERA_VIDEO_FPS:
+    g_value_set_int(value, camerasrc->video_fps);
+    break;
+  case ARG_CAMERA_RECORDING_HINT:
+    g_value_set_boolean(value, camerasrc->recording_hint);
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     break;
@@ -1462,9 +1679,11 @@ static void gst_tizencamerasrc_finalize(GObject *object)
 
   GST_INFO("ENTERED");
 
-  g_cond_clear(&camerasrc->buffer_cond);
-  g_mutex_clear(&camerasrc->buffer_lock);
+  g_cond_clear(&camerasrc->preview_buffer_cond);
+  g_mutex_clear(&camerasrc->preview_buffer_lock);
   SAFE_FREE_GQUEUE(camerasrc->preview_buffer_list);
+  g_cond_clear(&camerasrc->video_buffer_cond);
+  g_mutex_clear(&camerasrc->video_buffer_lock);
 
   if (camerasrc->allocator) {
     gst_object_unref(camerasrc->allocator);
@@ -1502,6 +1721,33 @@ void gst_tizencamerasrc_set_capture_command(GstTizenCameraSrc *camerasrc, GstCam
 }
 
 
+void gst_tizencamerasrc_set_record_command(GstTizenCameraSrc *camerasrc, GstCameraControlRecordCommand cmd)
+{
+  int ret = CAMERA_ERROR_NONE;
+
+  if (camerasrc == NULL) {
+    GST_ERROR_OBJECT(camerasrc, "camerasrc is NULL");
+    return;
+  }
+
+  GST_INFO_OBJECT(camerasrc, "ENTERED - cmd %d", cmd);
+
+  if (cmd == GST_CAMERA_CONTROL_RECORD_COMMAND_START) {
+    ret = camera_hal_interface_start_record(camerasrc->hal_intf_handle, _camera_video_frame_cb, camerasrc);
+    if (ret == CAMERA_ERROR_NONE)
+      camerasrc->video_first_frame = TRUE;
+  } else if (cmd == GST_CAMERA_CONTROL_RECORD_COMMAND_STOP) {
+    ret = camera_hal_interface_stop_record(camerasrc->hal_intf_handle);
+  } else {
+    GST_WARNING_OBJECT(camerasrc, "not supported command %d", cmd);
+  }
+
+  GST_INFO_OBJECT(camerasrc, "LEAVE - ret 0x%x", ret);
+
+  return;
+}
+
+
 static gboolean
 gst_tizencamerasrc_negotiate (GstBaseSrc * basesrc)
 {
@@ -2146,13 +2392,32 @@ static void gst_tizencamerasrc_class_init(GstTizenCameraSrcClass *klass)
                  G_STRUCT_OFFSET(GstTizenCameraSrcClass, still_capture),
                  NULL,
                  NULL,
-                 g_cclosure_user_marshal_VOID__OBJECT_OBJECT_OBJECT,
+                 g_tizencamerasrc_marshal_VOID__OBJECT_OBJECT_OBJECT,
                  G_TYPE_NONE,
                  3, /* Number of parameter */
                  GST_TYPE_SAMPLE,  /* Main image buffer */
                  GST_TYPE_SAMPLE,  /* Thumbnail image buffer */
                  GST_TYPE_SAMPLE); /* Screennail image buffer */
 
+  /**
+  * GstCameraSrc::start-record:
+  * @camerasrc: the camerasrc instance
+  * @buffer: the buffer that will be pushed
+  *
+  * This signal gets emitted before sending the buffer.
+  */
+  gst_tizencamerasrc_signals[SIGNAL_VIDEO_STREAM_CB] =
+    g_signal_new("video-stream-cb",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GstTizenCameraSrcClass, video_stream_cb),
+                 NULL,
+                 NULL,
+                 gst_tizencamerasrc_VOID__OBJECT_VIDEO_STREAM,
+                 G_TYPE_NONE,
+                 1, /* Number of parameter */
+                 GST_TYPE_SAMPLE); /* record buffer */
+
   GST_DEBUG("LEAVED");
 
   return;
@@ -2177,7 +2442,7 @@ static void gst_tizencamerasrc_init(GstTizenCameraSrc *camerasrc)
   camerasrc->fps_auto = _DEFAULT_FPS_AUTO;
   camerasrc->pix_format = _DEFAULT_PIX_FORMAT;
   strcpy(camerasrc->format_name, _DEFAULT_PIX_FORMAT_NAME);
-  camerasrc->buffer_running = FALSE;
+  camerasrc->preview_buffer_running = FALSE;
   camerasrc->vflip = FALSE;
   camerasrc->hflip = FALSE;
   camerasrc->camera_id = _DEFAULT_CAMERA_ID;
@@ -2192,8 +2457,10 @@ static void gst_tizencamerasrc_init(GstTizenCameraSrc *camerasrc)
   camerasrc->cap_jpg_quality = _DEFAULT_CAP_JPG_QUALITY;
   camerasrc->cap_provide_exif = _DEFAULT_CAP_PROVIDE_EXIF;
 
-  g_mutex_init(&camerasrc->buffer_lock);
-  g_cond_init(&camerasrc->buffer_cond);
+  g_mutex_init(&camerasrc->preview_buffer_lock);
+  g_cond_init(&camerasrc->preview_buffer_cond);
+  g_mutex_init(&camerasrc->video_buffer_lock);
+  g_cond_init(&camerasrc->video_buffer_cond);
 
   /* tizen allocator */
   camerasrc->allocator = gst_tizen_allocator_new();
index 9bdb110..be6c2f8 100644 (file)
@@ -725,3 +725,17 @@ void gst_tizencamerasrc_control_set_capture_command(GstTizenCameraSrc *camerasrc
 
   return;
 }
+
+void gst_tizencamerasrc_control_set_record_command(GstTizenCameraSrc *camerasrc, GstCameraControlRecordCommand cmd)
+{
+  gst_tizencamerasrc_debug("set record command");
+
+  if (camerasrc == NULL) {
+    gst_tizencamerasrc_debug("camerasrc is NULL");
+    return;
+  }
+
+  gst_tizencamerasrc_set_record_command(camerasrc, cmd);
+
+  return;
+}
index 5796aa2..0f08e23 100644 (file)
@@ -84,30 +84,33 @@ struct _GstTizenCameraSrc
 
   /*private*/
   camera_hal_interface *hal_intf_handle;  /**< Camera HAL interface handle */
-  int mode;
+  gint mode;
   gboolean vflip;                         /**< flip camera input vertically */
   gboolean hflip;                         /**< flip camera input horizontally */
   gboolean firsttime;
   gboolean is_flushing;
-  int num_live_buffers;
 
-  int cap_count_current;                  /**< current capture count */
-  int cap_count_reverse;                  /**< current capture count (reverse counting) */
+  gint cap_count_current;                 /**< current capture count */
+  gint cap_count_reverse;                 /**< current capture count (reverse counting) */
   GQueue *preview_buffer_list;
   uint32_t msg_cb_id;
 
   /*camera property*/
-  int width;                              /**< Width */
-  int height;                             /**< Height */
-  int fps;                                /**< Video source fps */
+  gint width;                             /**< Width of preview stream */
+  gint height;                            /**< Height of preview stream */
+  gint fps;                               /**< FPS of preview stream */
+  gint video_width;                       /**< Width of video stream */
+  gint video_height;                      /**< Height of video stream */
+  gint video_fps;                         /**< FPS of video stream */
+  gboolean recording_hint;                /**< Hint of recording */
 
   gchar format_name[FORMAT_NAME_LENGTH];  /**< Format name */
-  int pix_format;                         /**< Image format of video source */
-  int high_speed_fps;                     /**< Video source fps for high speed recording */
+  gint pix_format;                        /**< Image format of video source */
+  gint high_speed_fps;                    /**< Video source fps for high speed recording */
   gboolean fps_auto;                      /**< Auto Video source fps */
 
-  int camera_id;
-  int rotate;                             /**< Video source rotate */
+  gint camera_id;
+  gint rotate;                            /**< Video source rotate */
   gboolean use_rotate_caps;               /**< Use or not rotate value in caps */
 
   /* Colorbalance , CameraControl interface */
@@ -116,25 +119,32 @@ struct _GstTizenCameraSrc
 
   /* capture property */
   guint32 cap_fourcc;                     /**< gstreamer fourcc value(GST_MAKE_FOURCC format) for raw capturing */
-  int cap_width;                          /**< Capture width */
-  int cap_height;                         /**< Capture height */
-  int cap_interval;                       /**< Capture interval */
-  int cap_count;                          /**< Capture count */
-  int cap_jpg_quality;                    /**< Capture quality for jpg compress ratio */
+  gint cap_width;                         /**< Capture width */
+  gint cap_height;                        /**< Capture height */
+  gint cap_interval;                      /**< Capture interval */
+  gint cap_count;                         /**< Capture count */
+  gint cap_jpg_quality;                   /**< Capture quality for jpg compress ratio */
   gboolean cap_provide_exif;              /**< Is exif provided? */
 
   /* buffer control */
-  GCond buffer_cond;                      /**< condition for buffer control */
-  GMutex buffer_lock;                     /**< lock for buffer control */
-  gboolean buffer_running;                /**< flag for buffer running */
+  /* preview */
+  gint preview_live_buffers;              /**< Number of live buffers for preview */
+  GCond preview_buffer_cond;              /**< condition for preview buffer control */
+  GMutex preview_buffer_lock;             /**< lock for preview buffer control */
+  gboolean preview_buffer_running;        /**< flag for preview buffer running */
+  /* video */
+  gint video_live_buffers;                /**< Number of live buffers for video */
+  GCond video_buffer_cond;                /**< condition for video buffer control */
+  GMutex video_buffer_lock;               /**< lock for video buffer control */
+  gboolean video_buffer_running;          /**< flag for video buffer running */
+  gboolean video_first_frame;             /**< flag for first video frame */
 };
 
 struct _GstTizenCameraSrcClass {
   GstPushSrcClass parent_class;
   /* signals */
   void (*still_capture) (GstElement *element, GstBuffer *main, GstBuffer *sub, GstBuffer *scrnl);
-  void (*nego_complete) (GstElement *element);
-  void (*register_trouble) (GstElement *element);
+  void (*video_stream_cb) (GstElement *element, GstBuffer *main);
 };
 
 typedef enum {
@@ -145,6 +155,7 @@ typedef enum {
 
 
 void gst_tizencamerasrc_set_capture_command(GstTizenCameraSrc* camerasrc, GstCameraControlCaptureCommand cmd);
+void gst_tizencamerasrc_set_record_command(GstTizenCameraSrc* camerasrc, GstCameraControlRecordCommand cmd);
 
 
 GType gst_tizencamerasrc_get_type(void);
index f5afe10..4badc37 100644 (file)
@@ -78,6 +78,7 @@ gboolean    gst_tizencamerasrc_control_get_basic_dev_info (GstTizenCameraSrc *ca
 gboolean    gst_tizencamerasrc_control_get_misc_dev_info  (GstTizenCameraSrc *camera_src, gint dev_id, GstCameraControlCtrlListInfoType *info);
 gboolean    gst_tizencamerasrc_control_get_extra_dev_info (GstTizenCameraSrc *camera_src, gint dev_id, GstCameraControlExtraInfoType *info);
 void        gst_tizencamerasrc_control_set_capture_command(GstTizenCameraSrc *camera_src, GstCameraControlCaptureCommand cmd);
+void        gst_tizencamerasrc_control_set_record_command (GstTizenCameraSrc *camera_src, GstCameraControlRecordCommand cmd);
 
 #define GST_IMPLEMENT_TIZENCAMERASRC_CONTROL_METHODS(Type, interface_as_function) \
  \
@@ -322,6 +323,15 @@ interface_as_function ## _control_set_capture_command(GstCameraControl *control,
   return; \
 } \
  \
+static void \
+interface_as_function ## _control_set_record_command(GstCameraControl *control, \
+                                                     GstCameraControlRecordCommand cmd) \
+{ \
+  Type *this = (Type *)control; \
+  gst_tizencamerasrc_control_set_record_command(this, cmd); \
+  return; \
+} \
+ \
 void \
 interface_as_function ## _control_interface_init(GstCameraControlClass *klass) \
 { \
@@ -358,6 +368,7 @@ interface_as_function ## _control_interface_init(GstCameraControlClass *klass) \
   klass->get_misc_dev_info = interface_as_function ## _control_get_misc_dev_info; \
   klass->get_extra_dev_info = interface_as_function ## _control_get_extra_dev_info; \
   klass->set_capture_command = interface_as_function ## _control_set_capture_command; \
+  klass->set_record_command = interface_as_function ## _control_set_record_command; \
  \
 }