From e0507435cad8239a19b9b1a0686a354deb13c49b Mon Sep 17 00:00:00 2001 From: Wind Yuan Date: Tue, 2 Apr 2013 17:11:52 +0800 Subject: [PATCH] dual-stream: handle all eos events Change-Id: I9a188430345f275b2b505f6b64100a38f601030b --- gst-libs/gst/camera/gstmfldcamerasrc.c | 145 ++++++++++++++++++++++++--------- gst-libs/gst/camera/gstmfldcamerasrc.h | 3 + gst/mfldv4l2cam/gstv4l2camsrc.c | 1 + gst/mfldv4l2cam/v4l2camsrc_calls.c | 18 +++- gst/mfldv4l2cam/v4l2camsrc_calls.h | 14 ++-- 5 files changed, 134 insertions(+), 47 deletions(-) diff --git a/gst-libs/gst/camera/gstmfldcamerasrc.c b/gst-libs/gst/camera/gstmfldcamerasrc.c index 2e9cc46..7215d18 100644 --- a/gst-libs/gst/camera/gstmfldcamerasrc.c +++ b/gst-libs/gst/camera/gstmfldcamerasrc.c @@ -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; } diff --git a/gst-libs/gst/camera/gstmfldcamerasrc.h b/gst-libs/gst/camera/gstmfldcamerasrc.h index 2632fe3..2a99adc 100644 --- a/gst-libs/gst/camera/gstmfldcamerasrc.h +++ b/gst-libs/gst/camera/gstmfldcamerasrc.h @@ -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); diff --git a/gst/mfldv4l2cam/gstv4l2camsrc.c b/gst/mfldv4l2cam/gstv4l2camsrc.c index eff1b2b..29f716c 100644 --- a/gst/mfldv4l2cam/gstv4l2camsrc.c +++ b/gst/mfldv4l2cam/gstv4l2camsrc.c @@ -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); diff --git a/gst/mfldv4l2cam/v4l2camsrc_calls.c b/gst/mfldv4l2cam/v4l2camsrc_calls.c index 18d3551..7b6331b 100644 --- a/gst/mfldv4l2cam/v4l2camsrc_calls.c +++ b/gst/mfldv4l2cam/v4l2camsrc_calls.c @@ -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); +} diff --git a/gst/mfldv4l2cam/v4l2camsrc_calls.h b/gst/mfldv4l2cam/v4l2camsrc_calls.h index 70cfcea..9d1d488 100644 --- a/gst/mfldv4l2cam/v4l2camsrc_calls.h +++ b/gst/mfldv4l2cam/v4l2camsrc_calls.h @@ -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__ */ -- 2.7.4