From f00aec48fa601f967a9075dca86ead9d882c4f62 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sat, 28 Mar 2015 11:40:14 -0300 Subject: [PATCH] hlssink: implement a chain_list to request key unit for segments upstream might send buffer lists instead of buffers and hlssink's probe won't get called and a new segment won't be created when needed. This patch fixes it by adding a chain_list function to the sink pad that will just pass through the whole bufferlist if no segment needs to be requested at the moment or convert the list into buffers to check the proper timestamp to request the next key-unit that will start the segment. https://bugzilla.gnome.org/show_bug.cgi?id=746906 --- ext/hls/gsthlssink.c | 56 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/ext/hls/gsthlssink.c b/ext/hls/gsthlssink.c index ea337eaa6e..445caf50a8 100644 --- a/ext/hls/gsthlssink.c +++ b/ext/hls/gsthlssink.c @@ -85,6 +85,8 @@ static void gst_hls_sink_reset (GstHlsSink * sink); static GstStateChangeReturn gst_hls_sink_change_state (GstElement * element, GstStateChange trans); static gboolean schedule_next_key_unit (GstHlsSink * sink); +static GstFlowReturn gst_hls_sink_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * list); static void gst_hls_sink_dispose (GObject * object) @@ -180,6 +182,7 @@ gst_hls_sink_init (GstHlsSink * sink) gst_hls_sink_ghost_event_probe, sink, NULL); gst_pad_add_probe (sink->ghostpad, GST_PAD_PROBE_TYPE_BUFFER, gst_hls_sink_ghost_buffer_probe, sink, NULL); + gst_pad_set_chain_list_function (sink->ghostpad, gst_hls_sink_chain_list); sink->location = g_strdup (DEFAULT_LOCATION); sink->playlist_location = g_strdup (DEFAULT_PLAYLIST_LOCATION); @@ -499,6 +502,19 @@ out: return res; } +static void +gst_hls_sink_check_schedule_next_key_unit (GstHlsSink * sink, GstBuffer * buf) +{ + GstClockTime timestamp; + + timestamp = GST_BUFFER_TIMESTAMP (buf); + if (!GST_CLOCK_TIME_IS_VALID (timestamp)) + return; + + sink->last_running_time = gst_segment_to_running_time (&sink->segment, + GST_FORMAT_TIME, timestamp); + schedule_next_key_unit (sink); +} static GstPadProbeReturn gst_hls_sink_ghost_buffer_probe (GstPad * pad, GstPadProbeInfo * info, @@ -506,19 +522,45 @@ gst_hls_sink_ghost_buffer_probe (GstPad * pad, GstPadProbeInfo * info, { GstHlsSink *sink = GST_HLS_SINK_CAST (data); GstBuffer *buffer = gst_pad_probe_info_get_buffer (info); - GstClockTime timestamp; - timestamp = GST_BUFFER_TIMESTAMP (buffer); - if (sink->target_duration == 0 || !GST_CLOCK_TIME_IS_VALID (timestamp) - || sink->waiting_fku) + if (sink->target_duration == 0 || sink->waiting_fku) return GST_PAD_PROBE_OK; - sink->last_running_time = gst_segment_to_running_time (&sink->segment, - GST_FORMAT_TIME, timestamp); - schedule_next_key_unit (sink); + gst_hls_sink_check_schedule_next_key_unit (sink, buffer); return GST_PAD_PROBE_OK; } +static GstFlowReturn +gst_hls_sink_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list) +{ + guint i, len; + GstBuffer *buffer; + GstFlowReturn ret; + GstHlsSink *sink = GST_HLS_SINK_CAST (parent); + + if (sink->target_duration == 0 || sink->waiting_fku) + return gst_proxy_pad_chain_list_default (pad, parent, list); + + GST_DEBUG_OBJECT (pad, "chaining each group in list as a merged buffer"); + + len = gst_buffer_list_length (list); + + ret = GST_FLOW_OK; + for (i = 0; i < len; i++) { + buffer = gst_buffer_list_get (list, i); + + if (!sink->waiting_fku) + gst_hls_sink_check_schedule_next_key_unit (sink, buffer); + + ret = gst_pad_chain (pad, gst_buffer_ref (buffer)); + if (ret != GST_FLOW_OK) + break; + } + gst_buffer_list_unref (list); + + return ret; +} + gboolean gst_hls_sink_plugin_init (GstPlugin * plugin) {