messenger-gtk

Gtk+3 graphical user interfaces for GNUnet Messenger
Log | Files | Refs | Submodules | README | LICENSE

commit 96b277f53db3470f029e2545a93388a47256ec7b
parent 234c1591171e5f0941fb17c31a2207515e857627
Author: Jacki <jacki@thejackimonster.de>
Date:   Fri, 16 Aug 2024 02:04:15 +0200

Implement proper heartbeat for video streams

Signed-off-by: Jacki <jacki@thejackimonster.de>

Diffstat:
Msrc/discourse.c | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/discourse.h | 4+++-
2 files changed, 124 insertions(+), 11 deletions(-)

diff --git a/src/discourse.c b/src/discourse.c @@ -391,7 +391,9 @@ discourse_subscription_stream_message(MESSENGER_DiscourseSubscriptionInfo *info, buffer = NULL; - if ((info->last_timestamp == timestamp) || + GDateTime *dt = g_date_time_new_now_local(); + + if ((!payload_len) || (info->last_timestamp == timestamp) || ((!(info->last_timestamp)) && (!(info->position)))) goto skip_buffer; @@ -437,7 +439,6 @@ discourse_subscription_stream_message(MESSENGER_DiscourseSubscriptionInfo *info, info->position += duration; - GDateTime *dt = g_date_time_new_now_local(); pthread_mutex_lock(&(info->mutex)); if (info->end_datetime) @@ -447,15 +448,27 @@ discourse_subscription_stream_message(MESSENGER_DiscourseSubscriptionInfo *info, } if (dt) - { - info->end_datetime = g_date_time_add_seconds(dt, (gdouble) duration / clockrate); - g_date_time_unref(dt); - } + info->end_datetime = g_date_time_add_seconds(dt, 0.1 + (gdouble) duration / clockrate); pthread_mutex_unlock(&(info->mutex)); skip_buffer: - info->last_timestamp = timestamp; + if (payload_len) + info->last_timestamp = timestamp; + else if (dt) + { + pthread_mutex_lock(&(info->mutex)); + + if (info->end_datetime) + g_date_time_unref(info->end_datetime); + + info->end_datetime = g_date_time_add_seconds(dt, 0.1); + + pthread_mutex_unlock(&(info->mutex)); + } + + if (dt) + g_date_time_unref(dt); if (buffer) gst_buffer_unref(buffer); @@ -465,6 +478,46 @@ skip_buffer: } static gboolean +_discourse_video_heartbeat(gpointer user_data) +{ + MESSENGER_DiscourseInfo *info = (MESSENGER_DiscourseInfo*) user_data; + + info->heartbeat = 0; + + GstBuffer *buffer = gst_buffer_new(); + + if (!buffer) + return FALSE; + + GstFlowReturn ret = GST_FLOW_ERROR; + + gst_rtp_buffer_allocate_data( + buffer, + 0, + 0, + 0 + ); + + g_signal_emit_by_name( + info->video_heartbeat_source, + "push-buffer", + buffer, + &ret + ); + + if (buffer) + gst_buffer_unref(buffer); + + info->heartbeat = util_timeout_add( + 100, + G_SOURCE_FUNC(_discourse_video_heartbeat), + info + ); + + return FALSE; +} + +static gboolean discourse_subscription_link_widget(MESSENGER_DiscourseSubscriptionInfo *info, GtkContainer *container) { @@ -602,9 +655,7 @@ _setup_video_gst_pipelines(MESSENGER_DiscourseInfo *info) "video/x-raw,width=1280,height=720 ! videoconvert ! video/x-raw,format=I420 ! " "x264enc bitrate=1000 speed-preset=fast bframes=0 key-int-max=30 tune=zerolatency byte-stream=true ! " "video/x-h264,profile=baseline ! rtph264pay aggregate-mode=zero-latency mtu=45000 ! " - "tee ! queue ! capsfilter name=filter ! fdsink name=sink " - "fakesrc num-buffers=-1 sizetype=empty filltype=zero ! " - "video/x-h264,stream-format=avc,alignment=au ! rtph264pay ! mux.", + "tee ! queue ! rtpmux name=mux ! capsfilter name=filter ! fdsink name=sink", NULL ); @@ -616,6 +667,28 @@ _setup_video_gst_pipelines(MESSENGER_DiscourseInfo *info) GST_BIN(info->video_record_pipeline), "sink" ); + GstElement *mux = gst_bin_get_by_name( + GST_BIN(info->video_record_pipeline), + "mux" + ); + + info->video_heartbeat_source = gst_element_factory_make("appsrc", NULL); + + { + gst_bin_add( + GST_BIN(info->video_record_pipeline), + info->video_heartbeat_source + ); + + GstPad *mux_pad = gst_element_request_pad_simple(mux, "sink_%u"); + + GstPad *pad = gst_element_get_static_pad( + info->video_heartbeat_source, "src" + ); + + gst_pad_link(pad, mux_pad); + } + GstElement *filter = gst_bin_get_by_name( GST_BIN(info->video_record_pipeline), "filter" ); @@ -635,6 +708,7 @@ _setup_video_gst_pipelines(MESSENGER_DiscourseInfo *info) NULL ); + g_object_set(info->video_heartbeat_source, "caps", caps, NULL); g_object_set(filter, "caps", caps, NULL); gst_caps_unref(caps); @@ -665,6 +739,7 @@ discourse_create_info(struct GNUNET_CHAT_Discourse *discourse) info->video_record_pipeline = NULL; info->video_record_source = NULL; info->video_record_sink = NULL; + info->video_heartbeat_source = NULL; info->audio_mix_pipeline = NULL; info->audio_mix_element = NULL; @@ -672,6 +747,7 @@ discourse_create_info(struct GNUNET_CHAT_Discourse *discourse) pthread_mutex_init(&(info->mutex), NULL); + info->heartbeat = 0; info->subscriptions = NULL; const struct GNUNET_ShortHashCode *id = GNUNET_CHAT_discourse_get_id( @@ -715,9 +791,30 @@ discourse_destroy_info(struct GNUNET_CHAT_Discourse *discourse) pthread_mutex_unlock(&(info->mutex)); + if (info->heartbeat) + util_source_remove(info->heartbeat); + if (info->video_record_pipeline) { gst_element_set_state(info->video_record_pipeline, GST_STATE_NULL); + + GstElement *mux = gst_bin_get_by_name( + GST_BIN(info->video_record_pipeline), + "mux" + ); + + GstPad *mux_pad = gst_element_request_pad_simple(mux, "sink_%u"); + GstPad *pad = gst_element_get_static_pad( + info->video_heartbeat_source, "src" + ); + + gst_pad_unlink(pad, mux_pad); + + gst_bin_remove( + GST_BIN(info->video_record_pipeline), + info->video_heartbeat_source + ); + gst_object_unref(GST_OBJECT(info->video_record_pipeline)); } @@ -923,13 +1020,27 @@ discourse_set_mute(struct GNUNET_CHAT_Discourse *discourse, if (!info) return; + if ((mute) && (info->heartbeat)) + { + util_source_remove(info->heartbeat); + info->heartbeat = 0; + } + const GstState state = mute? GST_STATE_NULL : GST_STATE_PLAYING; if (info->audio_record_pipeline) gst_element_set_state(info->audio_record_pipeline, state); if (info->video_record_pipeline) + { gst_element_set_state(info->video_record_pipeline, state); + + if ((!mute) && (!(info->heartbeat))) + info->heartbeat = util_idle_add( + G_SOURCE_FUNC(_discourse_video_heartbeat), + info + ); + } } bool diff --git a/src/discourse.h b/src/discourse.h @@ -67,13 +67,15 @@ typedef struct MESSENGER_DiscourseInfo GstElement *video_record_pipeline; GstElement *video_record_source; GstElement *video_record_sink; + GstElement *video_heartbeat_source; GstElement *audio_mix_pipeline; GstElement *audio_mix_element; GstElement *audio_volume_element; pthread_mutex_t mutex; - + guint heartbeat; + GList *subscriptions; } MESSENGER_DiscourseInfo;