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
This commit is contained in:
Thiago Santos 2015-03-28 11:40:14 -03:00
parent 32e87b1024
commit f00aec48fa

View file

@ -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)
{