{
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;
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;
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);
}
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
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);
{
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);
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,
}
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
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;
}
/*
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;
}
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);
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;
}