SmartAudio/package/multimedia/gst1-plugins-good/patches/0002-add-pause-and-resume-t...

197 lines
5.4 KiB
Diff
Executable File

diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 86d5c8b..b3f973a 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -2013,3 +2013,89 @@ gst_v4l2_buffer_pool_flush (GstBufferPool * bpool)
return ret;
}
+
+gboolean
+gst_v4l2_buffer_pool_resume (GstBufferPool * bpool)
+{
+ GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
+ GstV4l2Object *obj = pool->obj;
+
+ if (pool->streaming) {
+ GST_ERROR_OBJECT (pool, "Streaming had been resmued or started");
+ return FALSE;
+ }
+
+ switch (obj->mode) {
+ case GST_V4L2_IO_MMAP:
+ case GST_V4L2_IO_USERPTR:
+ case GST_V4L2_IO_DMABUF:
+ case GST_V4L2_IO_DMABUF_IMPORT:
+ if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type)) {
+ /* For captures, we need to enqueue buffers before we start streaming,
+ * so the driver don't underflow immediatly. As we have put then back
+ * into the base class queue, resurect them, then releasing will queue
+ * them back. */
+ while (gst_v4l2_buffer_pool_resurect_buffer (pool) == GST_FLOW_OK)
+ continue;
+ }
+
+ if (obj->ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
+ goto resume_failed;
+
+ pool->streaming = TRUE;
+
+ GST_DEBUG_OBJECT (pool, "Resume streaming");
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+
+resume_failed:
+ {
+ GST_ERROR_OBJECT (pool, "error with RESUME STREAM %d (%s)", errno,
+ g_strerror (errno));
+ return FALSE;
+ }
+}
+
+gboolean
+gst_v4l2_buffer_pool_pause (GstBufferPool * bpool)
+{
+ GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
+ GstV4l2Object *obj = pool->obj;
+
+
+ if (!pool->streaming) {
+ GST_ERROR_OBJECT (pool, "Streaming had been paused or closed");
+ return FALSE;
+ }
+
+ switch (obj->mode) {
+ case GST_V4L2_IO_MMAP:
+ case GST_V4L2_IO_USERPTR:
+ case GST_V4L2_IO_DMABUF:
+ case GST_V4L2_IO_DMABUF_IMPORT:
+
+ if (obj->ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
+ goto pause_failed;
+
+ pool->streaming = FALSE;
+
+ GST_DEBUG_OBJECT (pool, "Pause streaming");
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+
+pause_failed:
+ {
+ GST_ERROR_OBJECT (pool, "error with PAUSE STREAM %d (%s)", errno,
+ g_strerror (errno));
+ return FALSE;
+ }
+}
+
diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h
index 0fffc71..14198dc 100644
--- a/sys/v4l2/gstv4l2bufferpool.h
+++ b/sys/v4l2/gstv4l2bufferpool.h
@@ -109,6 +109,9 @@ void gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool *
gboolean gst_v4l2_buffer_pool_flush (GstBufferPool *pool);
+gboolean gst_v4l2_buffer_pool_resume (GstBufferPool * bpool);
+
+gboolean gst_v4l2_buffer_pool_pause (GstBufferPool * bpool);
G_END_DECLS
#endif /*__GST_V4L2_BUFFER_POOL_H__ */
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index aba4496..fa27b65 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -205,6 +205,10 @@ gst_v4l2src_init (GstV4l2Src * v4l2src)
gst_base_src_set_format (GST_BASE_SRC (v4l2src), GST_FORMAT_TIME);
gst_base_src_set_live (GST_BASE_SRC (v4l2src), TRUE);
+
+ /* add for resume and pause */
+ v4l2src->suspending = FALSE;
+ v4l2src->keyevent = FALSE;
}
@@ -797,8 +801,27 @@ gst_v4l2src_change_state (GstElement * element, GstStateChange transition)
/* close the device */
if (!gst_v4l2_object_close (obj))
return GST_STATE_CHANGE_FAILURE;
-
break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ /* when task pause before pool_pause we should skip pool_pause */
+ if (v4l2src->keyevent == TRUE) {
+ v4l2src->suspending = TRUE;
+ break;
+ } else {
+ /* when suspending we should resume pool */
+ if (v4l2src->suspending == TRUE)
+ v4l2src->keyevent = TRUE;
+ break;
+ }
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ if (v4l2src->keyevent == TRUE) {
+ v4l2src->suspending = FALSE;
+ break;
+ } else {
+ if (v4l2src->suspending == FALSE)
+ v4l2src->keyevent = TRUE;
+ break;
+ }
default:
break;
}
@@ -818,6 +841,16 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
GstClockTime delay;
GstMessage *qos_msg;
+ /* ensure resuming stream before dqbuf and not resume when playing */
+ while (v4l2src->suspending == TRUE) {
+ if (v4l2src->suspending == TRUE && v4l2src->keyevent == TRUE) {
+ gst_v4l2_buffer_pool_resume (pool);
+ v4l2src->keyevent = FALSE;
+ v4l2src->suspending = FALSE;
+ break;
+ }
+ }
+
do {
ret = GST_BASE_SRC_CLASS (parent_class)->alloc (GST_BASE_SRC (src), 0,
obj->info.size, buf);
@@ -980,6 +1013,13 @@ retry:
GST_BUFFER_TIMESTAMP (*buf) = timestamp;
GST_BUFFER_DURATION (*buf) = duration;
+ /* ensure pausing stream when buf is ok */
+ if (v4l2src->suspending == FALSE && v4l2src->keyevent == TRUE) {
+ gst_v4l2_buffer_pool_pause (pool);
+ v4l2src->keyevent = FALSE;
+ v4l2src->suspending = TRUE;
+ }
+
return ret;
/* ERROR */
diff --git a/sys/v4l2/gstv4l2src.h b/sys/v4l2/gstv4l2src.h
index cb7f751..06dd88d 100644
--- a/sys/v4l2/gstv4l2src.h
+++ b/sys/v4l2/gstv4l2src.h
@@ -67,6 +67,8 @@ struct _GstV4l2Src
/* Timestamp sanity check */
GstClockTime last_timestamp;
gboolean has_bad_timestamp;
+ gboolean suspending;
+ gboolean keyevent;
};
struct _GstV4l2SrcClass