dual-stream: handle all eos events
authorWind Yuan <feng.yuan@intel.com>
Tue, 2 Apr 2013 09:11:52 +0000 (17:11 +0800)
committerMarko Ollonen <marko.ollonen@ixonos.com>
Sun, 7 Apr 2013 09:48:05 +0000 (12:48 +0300)
Change-Id: I9a188430345f275b2b505f6b64100a38f601030b

gst-libs/gst/camera/gstmfldcamerasrc.c
gst-libs/gst/camera/gstmfldcamerasrc.h
gst/mfldv4l2cam/gstv4l2camsrc.c
gst/mfldv4l2cam/v4l2camsrc_calls.c
gst/mfldv4l2cam/v4l2camsrc_calls.h

index 2e9cc46..7215d18 100644 (file)
@@ -445,6 +445,10 @@ ensure_second_stream_started(GstCameraSrc *src)
 {
   GstCameraSrcClass *kclass;
   gboolean ret;
+  guint w = 0, h = 0;
+  guint32 fourcc = 0;
+  guint fps_n, fps_d;
+  guint size;
 
   if (src->second_started)
     return TRUE;
@@ -460,6 +464,28 @@ ensure_second_stream_started(GstCameraSrc *src)
   if (src->second_stoped)
     return FALSE;
 
+  if (!src->second_caps)
+    goto failed;
+
+  if (!gst_camerasrc_get_caps_info(src, src->second_caps, &fourcc, &w, &h, &fps_n,
+          &fps_d, &size)) {
+    GST_DEBUG_OBJECT (src,
+        "second pad can't get capture info from caps %" GST_PTR_FORMAT, src->second_caps);
+    goto failed;
+  }
+
+  ret = kclass->set_second_capture_mode(src);
+  ret = kclass->set_second_capture(src, &fourcc, &w, &h, &fps_n, &fps_d);
+  if (ret) {
+    src->second_w = w;
+    src->second_h = h;
+    src->second_fps_n = fps_n;
+    src->second_fps_d = fps_d;
+    src->second_fourcc = fourcc;
+    src->second_duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
+  } else
+    goto failed;
+
   ret = kclass->start_second(src, src->second_caps);
   if (!ret)
     goto failed;
@@ -468,26 +494,58 @@ ensure_second_stream_started(GstCameraSrc *src)
   return TRUE;
 
 failed:
+  GST_WARNING_OBJECT(src, "second stream start failed.");
   return FALSE;
 }
 
 static void
+gst_camerasrc_second_pad_send_eos(GstCameraSrc *src)
+{
+  gboolean need_eos = FALSE;
+
+  g_mutex_lock(src->second_lock);
+  if (!src->second_eos_sent) {
+    src->second_eos_sent = TRUE;
+    need_eos = TRUE;
+  }
+  g_mutex_unlock(src->second_lock);
+
+  if (need_eos) {
+    GstEvent *event;
+    event = gst_event_new_eos ();
+    gst_event_set_seqnum (event, src->second_seqnum);
+    gst_pad_push_event (GST_CAMERA_SRC_SECOND_PAD(src), event);
+  }
+}
+
+static void
 _second_pad_loop(GstPad *pad)
 {
   GstCameraSrc *src = GST_CAMERA_SRC(GST_OBJECT_PARENT(pad));
   GstCameraSrcClass *kclass = GST_CAMERA_SRC_GET_CLASS(src);
   GstBuffer *buf = NULL;
+  gboolean stopped;
   GstFlowReturn ret;
 
+  g_mutex_lock(src->second_lock);
+  stopped = src->second_stoped;
+  g_mutex_unlock(src->second_lock);
+
+  if (stopped)
+    goto stop;
+
   if(!ensure_second_stream_started(src))
     goto stop;
 
   ret = kclass->create_second_buffer(src, &buf);
 
-  if (ret != GST_FLOW_OK || !buf) {
+  if (ret == GST_FLOW_WRONG_STATE)
+   goto pause;
+  else if (ret != GST_FLOW_OK || !buf) {
     GST_WARNING_OBJECT(src, "get second buffer failed.");
-    return;
+    goto stop;
   }
+  ++src->second_seqnum;
 
   if (!GST_BUFFER_CAPS(buf))
     gst_buffer_set_caps (buf, src->second_caps);
@@ -497,15 +555,40 @@ _second_pad_loop(GstPad *pad)
   }
 
   ret = gst_pad_push (pad, buf);
-  if (ret != GST_FLOW_OK) {
+  if (ret == GST_FLOW_WRONG_STATE)
+   goto pause;
+  else if (ret != GST_FLOW_OK) {
     GST_WARNING_OBJECT(src, "push second buffer failed.");
     goto stop;
   }
   return;
 
+pause:
+  gst_pad_pause_task (pad);
+  return;
+
 stop:
   /* TODO, may need stop whole pipeline  or send signal */
-  GST_WARNING_OBJECT(src, "second pad need to stop");
+  gst_pad_pause_task (pad);
+  gst_camerasrc_second_pad_send_eos(src);
+  GST_DEBUG_OBJECT(src, "second pad stopped");
+}
+
+static void
+gst_camerasrc_second_stop_signal(GstCameraSrc *src)
+{
+  GstCameraSrcClass *kclass = GST_CAMERA_SRC_GET_CLASS(src);
+  gboolean need_stop;
+
+  g_mutex_lock(src->second_lock);
+  need_stop = src->second_stoped;
+  if (!src->second_stoped)
+    src->second_stoped = TRUE;
+  g_cond_signal(src->first_done_cond);
+  g_mutex_unlock(src->second_lock);
+
+  if (need_stop && kclass->stop_second_wait)
+    kclass->stop_second_wait(src);
 }
 
 static gboolean
@@ -535,13 +618,10 @@ gst_camerasrc_second_pad_activate_push(GstPad *pad, gboolean active)
     ret = gst_pad_start_task (pad, (GstTaskFunction)_second_pad_loop, pad);
   }
   else {
-    g_mutex_lock(src->second_lock);
-    src->second_stoped = TRUE;
-    g_cond_signal(src->first_done_cond);
-    g_mutex_unlock(src->second_lock);
-
+    gst_camerasrc_second_stop_signal(src);
     gst_pad_stop_task (pad);
     src->second_started = FALSE;
+    src->second_eos_sent = FALSE;
 
     if (kclass->close_second)
       ret = kclass->close_second(src);
@@ -564,11 +644,6 @@ gst_camerasrc_second_pad_setcaps(GstPad *pad, GstCaps *caps)
 {
   GstCameraSrc *src;
   GstCameraSrcClass *bclass;
-  guint w = 0, h = 0;
-  guint32 fourcc = 0;
-  guint fps_n, fps_d;
-  guint size;
-  gboolean ret;
 
   src = GST_CAMERA_SRC(GST_OBJECT_PARENT(pad));
   bclass = GST_CAMERA_SRC_GET_CLASS(src);
@@ -578,13 +653,6 @@ gst_camerasrc_second_pad_setcaps(GstPad *pad, GstCaps *caps)
   if (!bclass->is_second_open (src))
     return FALSE;
 
-  if (!gst_camerasrc_get_caps_info(src, caps, &fourcc, &w, &h, &fps_n,
-          &fps_d, &size)) {
-    GST_DEBUG_OBJECT (src,
-        "second pad can't get capture info from caps %" GST_PTR_FORMAT, caps);
-    return FALSE;
-  }
-
   if (src->second_caps) {
     gst_caps_unref(src->second_caps);
     GST_DEBUG_OBJECT (src,
@@ -592,24 +660,7 @@ gst_camerasrc_second_pad_setcaps(GstPad *pad, GstCaps *caps)
   }
   src->second_caps = gst_caps_ref(caps);
 
-  ret = bclass->set_second_capture_mode(src);
-  ret = bclass->set_second_capture(src, &fourcc, &w, &h, &fps_n, &fps_d);
-  if (ret) {
-    src->second_w = w;
-    src->second_h = h;
-    src->second_fps_n = fps_n;
-    src->second_fps_d = fps_d;
-    src->second_fourcc = fourcc;
-    src->second_duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
-  } else
-    goto failed;
-
   return TRUE;
-
-failed:
-  GST_WARNING_OBJECT(src,
-      "set second pad's caps failed, caps %" GST_PTR_FORMAT, caps);
-  return FALSE;
 }
 
 static void
@@ -901,6 +952,8 @@ gst_camerasrc_init (GstCameraSrc * camerasrc, GstCameraSrcClass * klass)
   camerasrc->second_lock = g_mutex_new ();
   camerasrc->first_done_cond = g_cond_new();
   camerasrc->first_started = FALSE;
+  camerasrc->second_seqnum = 0;
+  camerasrc->second_eos_sent = FALSE;
 }
 
 /*
@@ -2282,6 +2335,11 @@ gst_camerasrc_change_state (GstElement * element, GstStateChange transition)
       if (!bclass->open (camerasrc))
         return GST_STATE_CHANGE_FAILURE;
       break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      gst_pad_start_task(GST_CAMERA_SRC_SECOND_PAD(camerasrc),
+          (GstTaskFunction)_second_pad_loop,
+          GST_CAMERA_SRC_SECOND_PAD(camerasrc));
+      break;
     default:
       break;
   }
@@ -2289,6 +2347,14 @@ gst_camerasrc_change_state (GstElement * element, GstStateChange transition)
   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
   switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      if (bclass->stop_second_wait)
+        bclass->stop_second_wait(camerasrc);
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_camerasrc_second_stop_signal(camerasrc);
+      gst_camerasrc_second_pad_send_eos(camerasrc);
+      break;
     case GST_STATE_CHANGE_READY_TO_NULL:
       if (bclass->is_open (camerasrc)) {
         bclass->close (camerasrc);
@@ -2927,6 +2993,9 @@ gst_camerasrc_send_event (GstElement * element, GstEvent * event)
     case GST_EVENT_CUSTOM_UPSTREAM:
       ret = gst_camerasrc_handle_event (camerasrc, event);
       break;
+    case GST_EVENT_EOS:
+      gst_camerasrc_second_stop_signal(camerasrc);
+      break;
     default:
       break;
   }
index 2632fe3..2a99adc 100644 (file)
@@ -262,6 +262,8 @@ struct _GstCameraSrc {
   guint   second_fps_n, second_fps_d; /* second stream framerate if device is open */
   guint32 second_fourcc;         /* second stream color format */
   GstClockTime second_duration;  /* second stream duration of one frame */
+  guint32      second_seqnum;    /**/
+  gboolean     second_eos_sent;  /**/
 };
 
 /**
@@ -356,6 +358,7 @@ struct _GstCameraSrcClass
 
   /* from task loop */
   GstFlowReturn (*create_second_buffer) (GstCameraSrc *camsrc, GstBuffer **buf);
+  void (*stop_second_wait)      (GstCameraSrc *camsrc);
 
   /* from set caps */
   gboolean (*set_second_capture_mode) (GstCameraSrc *camsrc);
index eff1b2b..29f716c 100644 (file)
@@ -994,6 +994,7 @@ gst_v4l2camsrc_class_init (GstMFLDV4l2CamSrcClass * klass)
   camera_class->start_second = GST_DEBUG_FUNCPTR(gst_v4l2camsrc_start_second);
   camera_class->create_second_buffer =
       GST_DEBUG_FUNCPTR(gst_v4l2camsrc_create_second_buffer);
+  camera_class->stop_second_wait = GST_DEBUG_FUNCPTR(gst_v4l2camsrc_stop_second_wait);
 
   camera_class->set_capture_mode =
       GST_DEBUG_FUNCPTR (gst_v4l2camsrc_set_capture_mode);
index 18d3551..7b6331b 100644 (file)
@@ -105,6 +105,7 @@ static gint find_item (const gint table[], const gint item);
 
 #define RESIZER_MAX_DOWNSCALE_FACTOR 4
 #define V4L2CAMSRC_POLL_TIMEOUT (20 * GST_SECOND)
+#define V4L2CAMSRC_SECOND_POLL_TIMEOUT (1 * GST_SECOND)
 
 #define GST_TYPE_V4L2CAMSRC_BUFFER (gst_v4l2camsrc_buffer_get_type())
 #define GST_IS_V4L2CAMSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2CAMSRC_BUFFER))
@@ -4117,13 +4118,13 @@ gst_v4l2camsrc_create_second_buffer(GstCameraSrc *base, GstBuffer **buf)
   gint index;
   gint ret;
 
-  gst_v4l2_buffer_pool_update (src->second_poll, src, src->second_num_buffers);
+  gst_v4l2_buffer_pool_update (src->second_pool, src, src->second_num_buffers);
 
   for (;;) {
-    ret = gst_poll_wait (src->second_poll, V4L2CAMSRC_POLL_TIMEOUT);
+    ret = gst_poll_wait (src->second_poll, V4L2CAMSRC_SECOND_POLL_TIMEOUT);
     if (G_UNLIKELY (ret < 0)) {
       if (errno == EBUSY)
-        goto failed;
+        goto busy;
       if (errno != EAGAIN && errno != EINTR)
         goto failed;
     }
@@ -4207,7 +4208,16 @@ gst_v4l2camsrc_create_second_buffer(GstCameraSrc *base, GstBuffer **buf)
 
   return GST_FLOW_OK;
 
+busy:
+  return GST_FLOW_WRONG_STATE;
 timeout:
 failed:
   return GST_FLOW_ERROR;
-}
\ No newline at end of file
+}
+
+void
+gst_v4l2camsrc_stop_second_wait(GstCameraSrc *base)
+{
+  GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
+  gst_poll_set_flushing (src->second_poll, TRUE);
+}
index 70cfcea..9d1d488 100644 (file)
@@ -143,23 +143,27 @@ gboolean
 gst_v4l2camsrc_libmfldcam_get_focus_posi(GstMFLDV4l2CamSrc * v4l2camsrc, unsigned *posi);
 
 gboolean
-gst_v4l2camsrc_open_second(GstCameraSrc *base);
+gst_v4l2camsrc_open_second(GstCameraSrc *camsrc);
 
 gboolean
-gst_v4l2camsrc_close_second(GstCameraSrc *base);
+gst_v4l2camsrc_close_second(GstCameraSrc *camsrc);
 
 gboolean
-gst_v4l2camsrc_set_second_capture_mode(GstCameraSrc *base);
+gst_v4l2camsrc_set_second_capture_mode(GstCameraSrc *camsrc);
 
 gboolean
-gst_v4l2camsrc_set_second_capture(GstCameraSrc *base, guint32 *pixelformat,
+gst_v4l2camsrc_set_second_capture(GstCameraSrc *camsrc, guint32 *pixelformat,
     guint *width, guint32 *height,
     guint *fps_n, guint *fps_d);
 
 gboolean
-gst_v4l2camsrc_start_second(GstCameraSrc *base, GstCaps *caps);
+gst_v4l2camsrc_start_second(GstCameraSrc *camsrc, GstCaps *caps);
 
 GstFlowReturn
 gst_v4l2camsrc_create_second_buffer(GstCameraSrc *camsrc, GstBuffer **buf);
 
+void
+gst_v4l2camsrc_stop_second_wait(GstCameraSrc *camsrc);
+
+
 #endif /* __V4L2CAMSRC_CALLS_H__ */