gst: add keepalive-time property

Add a property to periodically send the last buffer to keep the
stream alive. Useful for sparse streams that need to keep the
encoder busy every once and a while.
This commit is contained in:
Wim Taymans 2020-07-14 13:54:21 +02:00
parent f28ca843a6
commit 993aa89030
2 changed files with 47 additions and 11 deletions

View file

@ -63,6 +63,7 @@ GST_DEBUG_CATEGORY_STATIC (pipewire_src_debug);
#define DEFAULT_MIN_BUFFERS 1 #define DEFAULT_MIN_BUFFERS 1
#define DEFAULT_MAX_BUFFERS INT32_MAX #define DEFAULT_MAX_BUFFERS INT32_MAX
#define DEFAULT_RESEND_LAST false #define DEFAULT_RESEND_LAST false
#define DEFAULT_KEEPALIVE_TIME 0
enum enum
{ {
@ -75,6 +76,7 @@ enum
PROP_MAX_BUFFERS, PROP_MAX_BUFFERS,
PROP_FD, PROP_FD,
PROP_RESEND_LAST, PROP_RESEND_LAST,
PROP_KEEPALIVE_TIME,
}; };
@ -148,6 +150,10 @@ gst_pipewire_src_set_property (GObject * object, guint prop_id,
pwsrc->resend_last = g_value_get_boolean (value); pwsrc->resend_last = g_value_get_boolean (value);
break; break;
case PROP_KEEPALIVE_TIME:
pwsrc->keepalive_time = g_value_get_int (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -193,6 +199,10 @@ gst_pipewire_src_get_property (GObject * object, guint prop_id,
g_value_set_boolean (value, pwsrc->resend_last); g_value_set_boolean (value, pwsrc->resend_last);
break; break;
case PROP_KEEPALIVE_TIME:
g_value_set_int (value, pwsrc->keepalive_time);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -313,14 +323,14 @@ gst_pipewire_src_class_init (GstPipeWireSrcClass * klass)
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_FD, PROP_FD,
g_param_spec_int ("fd", g_param_spec_int ("fd",
"Fd", "Fd",
"The fd to connect with", "The fd to connect with",
-1, G_MAXINT, -1, -1, G_MAXINT, -1,
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_RESEND_LAST, PROP_RESEND_LAST,
@ -331,6 +341,14 @@ gst_pipewire_src_class_init (GstPipeWireSrcClass * klass)
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_KEEPALIVE_TIME,
g_param_spec_int ("keepalive-time",
"Keepalive Time",
"Periodically send last buffer (in seconds, 0 = disabled)",
0, G_MAXINT, DEFAULT_KEEPALIVE_TIME,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
gstelement_class->provide_clock = gst_pipewire_src_provide_clock; gstelement_class->provide_clock = gst_pipewire_src_provide_clock;
gstelement_class->change_state = gst_pipewire_src_change_state; gstelement_class->change_state = gst_pipewire_src_change_state;
@ -371,6 +389,7 @@ gst_pipewire_src_init (GstPipeWireSrc * src)
src->max_buffers = DEFAULT_MAX_BUFFERS; src->max_buffers = DEFAULT_MAX_BUFFERS;
src->fd = -1; src->fd = -1;
src->resend_last = DEFAULT_RESEND_LAST; src->resend_last = DEFAULT_RESEND_LAST;
src->keepalive_time = DEFAULT_KEEPALIVE_TIME;
src->client_name = g_strdup(pw_get_client_name ()); src->client_name = g_strdup(pw_get_client_name ());
@ -848,6 +867,7 @@ gst_pipewire_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
GstClockTime pts, dts, base_time; GstClockTime pts, dts, base_time;
const char *error = NULL; const char *error = NULL;
GstBuffer *buf; GstBuffer *buf;
gboolean update_time = FALSE, timeout = FALSE;
pwsrc = GST_PIPEWIRE_SRC (psrc); pwsrc = GST_PIPEWIRE_SRC (psrc);
@ -876,17 +896,30 @@ gst_pipewire_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
goto streaming_eos; goto streaming_eos;
buf = pwsrc->last_buffer; buf = pwsrc->last_buffer;
pwsrc->last_buffer = NULL; pwsrc->last_buffer = NULL;
update_time = TRUE;
break; break;
} else if (timeout) {
if (pwsrc->last_buffer != NULL) {
update_time = TRUE;
buf = gst_buffer_ref(pwsrc->last_buffer);
break;
}
} else { } else {
buf = dequeue_buffer (pwsrc); buf = dequeue_buffer (pwsrc);
GST_LOG_OBJECT (pwsrc, "popped buffer %p", buf); GST_LOG_OBJECT (pwsrc, "popped buffer %p", buf);
if (buf != NULL) { if (buf != NULL) {
if (pwsrc->resend_last) if (pwsrc->resend_last || pwsrc->keepalive_time > 0)
gst_buffer_replace (&pwsrc->last_buffer, buf); gst_buffer_replace (&pwsrc->last_buffer, buf);
break; break;
} }
} }
pw_thread_loop_wait (pwsrc->core->loop); timeout = FALSE;
if (pwsrc->keepalive_time > 0) {
if (pw_thread_loop_timed_wait (pwsrc->core->loop, pwsrc->keepalive_time) == ETIMEDOUT)
timeout = TRUE;
} else {
pw_thread_loop_wait (pwsrc->core->loop);
}
} }
pw_thread_loop_unlock (pwsrc->core->loop); pw_thread_loop_unlock (pwsrc->core->loop);
@ -902,7 +935,7 @@ gst_pipewire_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
else else
base_time = 0; base_time = 0;
if (pwsrc->last_buffer == NULL && pwsrc->resend_last) { if (update_time) {
GstClock *clock = gst_element_get_clock (GST_ELEMENT_CAST (pwsrc)); GstClock *clock = gst_element_get_clock (GST_ELEMENT_CAST (pwsrc));
if (clock != NULL) { if (clock != NULL) {
pts = dts = gst_clock_get_time (clock); pts = dts = gst_clock_get_time (clock);
@ -1039,6 +1072,8 @@ no_stream:
{ {
GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED, ("can't create stream"), (NULL)); GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED, ("can't create stream"), (NULL));
pw_thread_loop_unlock (pwsrc->core->loop); pw_thread_loop_unlock (pwsrc->core->loop);
gst_pipewire_core_release (pwsrc->core);
pwsrc->core = NULL;
return FALSE; return FALSE;
} }
} }

View file

@ -66,6 +66,7 @@ struct _GstPipeWireSrc {
gint max_buffers; gint max_buffers;
int fd; int fd;
gboolean resend_last; gboolean resend_last;
gint keepalive_time;
gboolean negotiated; gboolean negotiated;
gboolean flushing; gboolean flushing;