mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-04 01:32:42 +00:00
dashdemux: port to 1.0
This commit is contained in:
parent
b338cc0d34
commit
9f190cdff7
6 changed files with 112 additions and 110 deletions
|
@ -14,10 +14,10 @@ noinst_HEADERS = \
|
||||||
gstdownloadrate.h
|
gstdownloadrate.h
|
||||||
|
|
||||||
# compiler and linker flags used to compile this plugin, set in configure.ac
|
# compiler and linker flags used to compile this plugin, set in configure.ac
|
||||||
libgstdashdemux_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_CFLAGS)
|
libgstdashdemux_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_CFLAGS) $(LIBXML2_CFLAGS)
|
||||||
libgstdashdemux_la_LIBADD = \
|
libgstdashdemux_la_LIBADD = \
|
||||||
$(top_builddir)/gst-libs/gst/uridownloader/libgsturidownloader-$(GST_MAJORMINOR).la \
|
$(top_builddir)/gst-libs/gst/uridownloader/libgsturidownloader-@GST_API_VERSION@.la \
|
||||||
$(GST_LIBS) $(GST_BASE_LIBS)
|
$(GST_LIBS) $(GST_BASE_LIBS) $(LIBXML2_LIBS)
|
||||||
libgstdashdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
libgstdashdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
libgstdashdemux_la_LIBTOOLFLAGS = --tag=disable-static
|
libgstdashdemux_la_LIBTOOLFLAGS = --tag=disable-static
|
||||||
|
|
||||||
|
|
|
@ -204,10 +204,14 @@ static GstStateChangeReturn
|
||||||
gst_dash_demux_change_state (GstElement * element, GstStateChange transition);
|
gst_dash_demux_change_state (GstElement * element, GstStateChange transition);
|
||||||
|
|
||||||
/* GstDashDemux */
|
/* GstDashDemux */
|
||||||
static GstFlowReturn gst_dash_demux_pad (GstPad * pad, GstBuffer * buf);
|
static GstFlowReturn gst_dash_demux_pad (GstPad * pad, GstObject * parent,
|
||||||
static gboolean gst_dash_demux_sink_event (GstPad * pad, GstEvent * event);
|
GstBuffer * buf);
|
||||||
static gboolean gst_dash_demux_src_event (GstPad * pad, GstEvent * event);
|
static gboolean gst_dash_demux_sink_event (GstPad * pad, GstObject * parent,
|
||||||
static gboolean gst_dash_demux_src_query (GstPad * pad, GstQuery * query);
|
GstEvent * event);
|
||||||
|
static gboolean gst_dash_demux_src_event (GstPad * pad, GstObject * parent,
|
||||||
|
GstEvent * event);
|
||||||
|
static gboolean gst_dash_demux_src_query (GstPad * pad, GstObject * parent,
|
||||||
|
GstQuery * query);
|
||||||
static void gst_dash_demux_stream_loop (GstDashDemux * demux);
|
static void gst_dash_demux_stream_loop (GstDashDemux * demux);
|
||||||
static void gst_dash_demux_download_loop (GstDashDemux * demux);
|
static void gst_dash_demux_download_loop (GstDashDemux * demux);
|
||||||
static void gst_dash_demux_stop (GstDashDemux * demux);
|
static void gst_dash_demux_stop (GstDashDemux * demux);
|
||||||
|
@ -230,33 +234,10 @@ static GstClockTime gst_dash_demux_stream_get_buffering_time (GstDashDemuxStream
|
||||||
* stream);
|
* stream);
|
||||||
static GstPad *gst_dash_demux_create_pad (GstDashDemux * demux);
|
static GstPad *gst_dash_demux_create_pad (GstDashDemux * demux);
|
||||||
|
|
||||||
static void
|
#define gst_dash_demux_parent_class parent_class
|
||||||
_do_init (GType type)
|
G_DEFINE_TYPE_WITH_CODE (GstDashDemux, gst_dash_demux, GST_TYPE_ELEMENT,
|
||||||
{
|
GST_DEBUG_CATEGORY_INIT (gst_dash_demux_debug, "dashdemux", 0,
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_dash_demux_debug, "dashdemux", 0,
|
"dashdemux element"););
|
||||||
"dashdemux element");
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BOILERPLATE_FULL (GstDashDemux, gst_dash_demux, GstElement,
|
|
||||||
GST_TYPE_ELEMENT, _do_init);
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_dash_demux_base_init (gpointer g_class)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
|
||||||
|
|
||||||
gst_element_class_add_static_pad_template (element_class, &srctemplate);
|
|
||||||
|
|
||||||
gst_element_class_add_static_pad_template (element_class, &sinktemplate);
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class,
|
|
||||||
"DASH Demuxer",
|
|
||||||
"Codec/Demuxer",
|
|
||||||
"Dynamic Adaptive Streaming over HTTP demuxer",
|
|
||||||
"David Corvoysier <david.corvoysier@orange.com>\n\
|
|
||||||
Hamid Zakari <hamid.zakari@gmail.com>\n\
|
|
||||||
Gianluca Gennari <gennarone@gmail.com>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_dash_demux_dispose (GObject * obj)
|
gst_dash_demux_dispose (GObject * obj)
|
||||||
|
@ -267,13 +248,13 @@ gst_dash_demux_dispose (GObject * obj)
|
||||||
|
|
||||||
if (demux->stream_task) {
|
if (demux->stream_task) {
|
||||||
gst_object_unref (demux->stream_task);
|
gst_object_unref (demux->stream_task);
|
||||||
g_static_rec_mutex_free (&demux->stream_task_lock);
|
g_rec_mutex_clear (&demux->stream_task_lock);
|
||||||
demux->stream_task = NULL;
|
demux->stream_task = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demux->download_task) {
|
if (demux->download_task) {
|
||||||
gst_object_unref (demux->download_task);
|
gst_object_unref (demux->download_task);
|
||||||
g_static_rec_mutex_free (&demux->download_task_lock);
|
g_rec_mutex_clear (&demux->download_task_lock);
|
||||||
demux->download_task = NULL;
|
demux->download_task = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +263,7 @@ gst_dash_demux_dispose (GObject * obj)
|
||||||
demux->downloader = NULL;
|
demux->downloader = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_static_mutex_free (&demux->streams_lock);
|
g_mutex_clear (&demux->streams_lock);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (obj);
|
G_OBJECT_CLASS (parent_class)->dispose (obj);
|
||||||
}
|
}
|
||||||
|
@ -321,10 +302,24 @@ gst_dash_demux_class_init (GstDashDemuxClass * klass)
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_dash_demux_change_state);
|
GST_DEBUG_FUNCPTR (gst_dash_demux_change_state);
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&srctemplate));
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&sinktemplate));
|
||||||
|
|
||||||
|
gst_element_class_set_static_metadata (gstelement_class,
|
||||||
|
"DASH Demuxer",
|
||||||
|
"Codec/Demuxer",
|
||||||
|
"Dynamic Adaptive Streaming over HTTP demuxer",
|
||||||
|
"David Corvoysier <david.corvoysier@orange.com>\n\
|
||||||
|
Hamid Zakari <hamid.zakari@gmail.com>\n\
|
||||||
|
Gianluca Gennari <gennarone@gmail.com>");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_dash_demux_init (GstDashDemux * demux, GstDashDemuxClass * klass)
|
gst_dash_demux_init (GstDashDemux * demux)
|
||||||
{
|
{
|
||||||
/* sink pad */
|
/* sink pad */
|
||||||
demux->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
|
demux->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
|
||||||
|
@ -345,18 +340,19 @@ gst_dash_demux_init (GstDashDemux * demux, GstDashDemuxClass * klass)
|
||||||
demux->max_bitrate = DEFAULT_MAX_BITRATE;
|
demux->max_bitrate = DEFAULT_MAX_BITRATE;
|
||||||
|
|
||||||
/* Updates task */
|
/* Updates task */
|
||||||
g_static_rec_mutex_init (&demux->download_task_lock);
|
g_rec_mutex_init (&demux->download_task_lock);
|
||||||
demux->download_task =
|
demux->download_task =
|
||||||
gst_task_create ((GstTaskFunction) gst_dash_demux_download_loop, demux);
|
gst_task_new ((GstTaskFunction) gst_dash_demux_download_loop, demux,
|
||||||
|
NULL);
|
||||||
gst_task_set_lock (demux->download_task, &demux->download_task_lock);
|
gst_task_set_lock (demux->download_task, &demux->download_task_lock);
|
||||||
|
|
||||||
/* Streaming task */
|
/* Streaming task */
|
||||||
g_static_rec_mutex_init (&demux->stream_task_lock);
|
g_rec_mutex_init (&demux->stream_task_lock);
|
||||||
demux->stream_task =
|
demux->stream_task =
|
||||||
gst_task_create ((GstTaskFunction) gst_dash_demux_stream_loop, demux);
|
gst_task_new ((GstTaskFunction) gst_dash_demux_stream_loop, demux, NULL);
|
||||||
gst_task_set_lock (demux->stream_task, &demux->stream_task_lock);
|
gst_task_set_lock (demux->stream_task, &demux->stream_task_lock);
|
||||||
|
|
||||||
g_static_mutex_init (&demux->streams_lock);
|
g_mutex_init (&demux->streams_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -466,7 +462,7 @@ gst_dash_demux_stream_push_data (GstDashDemuxStream * stream,
|
||||||
item->object = GST_MINI_OBJECT_CAST (fragment);
|
item->object = GST_MINI_OBJECT_CAST (fragment);
|
||||||
item->duration = GST_BUFFER_DURATION (fragment);
|
item->duration = GST_BUFFER_DURATION (fragment);
|
||||||
item->visible = TRUE;
|
item->visible = TRUE;
|
||||||
item->size = GST_BUFFER_SIZE (fragment);
|
item->size = gst_buffer_get_size (fragment);
|
||||||
|
|
||||||
item->destroy = (GDestroyNotify) _data_queue_item_destroy;
|
item->destroy = (GDestroyNotify) _data_queue_item_destroy;
|
||||||
|
|
||||||
|
@ -474,11 +470,11 @@ gst_dash_demux_stream_push_data (GstDashDemuxStream * stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
|
gst_dash_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
{
|
{
|
||||||
GstDashDemux *demux;
|
GstDashDemux *demux;
|
||||||
|
|
||||||
demux = GST_DASH_DEMUX (gst_pad_get_element_private (pad));
|
demux = GST_DASH_DEMUX (parent);
|
||||||
|
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case GST_EVENT_SEEK:
|
case GST_EVENT_SEEK:
|
||||||
|
@ -515,11 +511,10 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
|
||||||
GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start),
|
GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start),
|
||||||
GST_TIME_ARGS (stop));
|
GST_TIME_ARGS (stop));
|
||||||
|
|
||||||
gst_segment_set_seek (&demux->segment, rate, format, flags, start_type,
|
gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
|
||||||
start, stop_type, stop, &update);
|
start, stop_type, stop, &update);
|
||||||
|
|
||||||
if (update) {
|
if (update) {
|
||||||
|
|
||||||
if (flags & GST_SEEK_FLAG_FLUSH) {
|
if (flags & GST_SEEK_FLAG_FLUSH) {
|
||||||
GST_DEBUG_OBJECT (demux, "sending flush start");
|
GST_DEBUG_OBJECT (demux, "sending flush start");
|
||||||
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
|
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
|
||||||
|
@ -535,7 +530,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
|
||||||
gst_dash_demux_stop (demux);
|
gst_dash_demux_stop (demux);
|
||||||
|
|
||||||
/* Wait for streaming to finish */
|
/* Wait for streaming to finish */
|
||||||
g_static_rec_mutex_lock (&demux->stream_task_lock);
|
g_rec_mutex_lock (&demux->stream_task_lock);
|
||||||
|
|
||||||
/* select the requested Period in the Media Presentation */
|
/* select the requested Period in the Media Presentation */
|
||||||
target_pos = (GstClockTime) demux->segment.start;
|
target_pos = (GstClockTime) demux->segment.start;
|
||||||
|
@ -618,7 +613,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
|
||||||
stream->download_end_of_period = FALSE;
|
stream->download_end_of_period = FALSE;
|
||||||
stream->stream_end_of_period = FALSE;
|
stream->stream_end_of_period = FALSE;
|
||||||
stream->stream_eos = FALSE;
|
stream->stream_eos = FALSE;
|
||||||
gst_pad_push_event (stream->pad, gst_event_new_flush_stop ());
|
gst_pad_push_event (stream->pad, gst_event_new_flush_stop (TRUE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,7 +630,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
|
||||||
GST_DEBUG_OBJECT (demux, "Resuming tasks after seeking");
|
GST_DEBUG_OBJECT (demux, "Resuming tasks after seeking");
|
||||||
gst_dash_demux_resume_download_task (demux);
|
gst_dash_demux_resume_download_task (demux);
|
||||||
gst_dash_demux_resume_stream_task (demux);
|
gst_dash_demux_resume_stream_task (demux);
|
||||||
g_static_rec_mutex_unlock (&demux->stream_task_lock);
|
g_rec_mutex_unlock (&demux->stream_task_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -644,7 +639,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gst_pad_event_default (pad, event);
|
return gst_pad_event_default (pad, parent, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -704,7 +699,7 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
|
||||||
caps = gst_dash_demux_get_input_caps (demux, active_stream);
|
caps = gst_dash_demux_get_input_caps (demux, active_stream);
|
||||||
stream->queue =
|
stream->queue =
|
||||||
gst_data_queue_new ((GstDataQueueCheckFullFunction) _check_queue_full,
|
gst_data_queue_new ((GstDataQueueCheckFullFunction) _check_queue_full,
|
||||||
stream);
|
NULL, NULL, stream);
|
||||||
|
|
||||||
stream->index = i;
|
stream->index = i;
|
||||||
stream->input_caps = caps;
|
stream->input_caps = caps;
|
||||||
|
@ -717,6 +712,7 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
|
||||||
GST_LOG_OBJECT (demux, "Creating stream %d %" GST_PTR_FORMAT, i, caps);
|
GST_LOG_OBJECT (demux, "Creating stream %d %" GST_PTR_FORMAT, i, caps);
|
||||||
streams = g_slist_prepend (streams, stream);
|
streams = g_slist_prepend (streams, stream);
|
||||||
stream->pad = gst_dash_demux_create_pad (demux);
|
stream->pad = gst_dash_demux_create_pad (demux);
|
||||||
|
gst_dash_demux_stream_push_event (stream, gst_event_new_caps (caps));
|
||||||
}
|
}
|
||||||
streams = g_slist_reverse (streams);
|
streams = g_slist_reverse (streams);
|
||||||
|
|
||||||
|
@ -727,9 +723,9 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
|
gst_dash_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
{
|
{
|
||||||
GstDashDemux *demux = GST_DASH_DEMUX (GST_PAD_PARENT (pad));
|
GstDashDemux *demux = GST_DASH_DEMUX (parent);
|
||||||
|
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case GST_EVENT_FLUSH_STOP:
|
case GST_EVENT_FLUSH_STOP:
|
||||||
|
@ -739,6 +735,7 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
gchar *manifest;
|
gchar *manifest;
|
||||||
GstQuery *query;
|
GstQuery *query;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
|
GstMapInfo mapinfo;
|
||||||
|
|
||||||
if (demux->manifest == NULL) {
|
if (demux->manifest == NULL) {
|
||||||
GST_WARNING_OBJECT (demux, "Received EOS without a manifest.");
|
GST_WARNING_OBJECT (demux, "Received EOS without a manifest.");
|
||||||
|
@ -762,11 +759,12 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
}
|
}
|
||||||
gst_query_unref (query);
|
gst_query_unref (query);
|
||||||
|
|
||||||
manifest = (gchar *) GST_BUFFER_DATA (demux->manifest);
|
gst_buffer_map (demux->manifest, &mapinfo, GST_MAP_READ);
|
||||||
|
|
||||||
|
manifest = (gchar *) mapinfo.data;
|
||||||
if (manifest == NULL) {
|
if (manifest == NULL) {
|
||||||
GST_WARNING_OBJECT (demux, "Error validating the manifest.");
|
GST_WARNING_OBJECT (demux, "Error validating the manifest.");
|
||||||
} else if (!gst_mpd_parse (demux->client, manifest,
|
} else if (!gst_mpd_parse (demux->client, manifest, mapinfo.size)) {
|
||||||
GST_BUFFER_SIZE (demux->manifest))) {
|
|
||||||
/* In most cases, this will happen if we set a wrong url in the
|
/* In most cases, this will happen if we set a wrong url in the
|
||||||
* source element and we have received the 404 HTML response instead of
|
* source element and we have received the 404 HTML response instead of
|
||||||
* the manifest */
|
* the manifest */
|
||||||
|
@ -774,6 +772,7 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
(NULL));
|
(NULL));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
gst_buffer_unmap (demux->manifest, &mapinfo);
|
||||||
gst_buffer_unref (demux->manifest);
|
gst_buffer_unref (demux->manifest);
|
||||||
demux->manifest = NULL;
|
demux->manifest = NULL;
|
||||||
|
|
||||||
|
@ -803,8 +802,7 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
"Sending duration message : %" GST_TIME_FORMAT,
|
"Sending duration message : %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (duration));
|
GST_TIME_ARGS (duration));
|
||||||
gst_element_post_message (GST_ELEMENT (demux),
|
gst_element_post_message (GST_ELEMENT (demux),
|
||||||
gst_message_new_duration (GST_OBJECT (demux), GST_FORMAT_TIME,
|
gst_message_new_duration_changed (GST_OBJECT (demux)));
|
||||||
duration));
|
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (demux,
|
GST_DEBUG_OBJECT (demux,
|
||||||
"mediaPresentationDuration unknown, can not send the duration message");
|
"mediaPresentationDuration unknown, can not send the duration message");
|
||||||
|
@ -817,7 +815,7 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
case GST_EVENT_NEWSEGMENT:
|
case GST_EVENT_SEGMENT:
|
||||||
/* Swallow newsegments, we'll push our own */
|
/* Swallow newsegments, we'll push our own */
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -825,11 +823,11 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gst_pad_event_default (pad, event);
|
return gst_pad_event_default (pad, parent, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_dash_demux_src_query (GstPad * pad, GstQuery * query)
|
gst_dash_demux_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
||||||
{
|
{
|
||||||
GstDashDemux *dashdemux;
|
GstDashDemux *dashdemux;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
@ -837,7 +835,7 @@ gst_dash_demux_src_query (GstPad * pad, GstQuery * query)
|
||||||
if (query == NULL)
|
if (query == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
dashdemux = GST_DASH_DEMUX (gst_pad_get_element_private (pad));
|
dashdemux = GST_DASH_DEMUX (parent);
|
||||||
|
|
||||||
switch (query->type) {
|
switch (query->type) {
|
||||||
case GST_QUERY_DURATION:{
|
case GST_QUERY_DURATION:{
|
||||||
|
@ -894,14 +892,14 @@ gst_dash_demux_src_query (GstPad * pad, GstQuery * query)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_dash_demux_pad (GstPad * pad, GstBuffer * buf)
|
gst_dash_demux_pad (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstDashDemux *demux = GST_DASH_DEMUX (GST_PAD_PARENT (pad));
|
GstDashDemux *demux = GST_DASH_DEMUX (parent);
|
||||||
|
|
||||||
if (demux->manifest == NULL)
|
if (demux->manifest == NULL)
|
||||||
demux->manifest = buf;
|
demux->manifest = buf;
|
||||||
else
|
else
|
||||||
demux->manifest = gst_buffer_join (demux->manifest, buf);
|
demux->manifest = gst_buffer_append (demux->manifest, buf);
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
@ -925,15 +923,15 @@ gst_dash_demux_stop (GstDashDemux * demux)
|
||||||
if (GST_TASK_STATE (demux->download_task) != GST_TASK_STOPPED) {
|
if (GST_TASK_STATE (demux->download_task) != GST_TASK_STOPPED) {
|
||||||
GST_TASK_SIGNAL (demux->download_task);
|
GST_TASK_SIGNAL (demux->download_task);
|
||||||
gst_task_stop (demux->download_task);
|
gst_task_stop (demux->download_task);
|
||||||
g_static_rec_mutex_lock (&demux->download_task_lock);
|
g_rec_mutex_lock (&demux->download_task_lock);
|
||||||
g_static_rec_mutex_unlock (&demux->download_task_lock);
|
g_rec_mutex_unlock (&demux->download_task_lock);
|
||||||
gst_task_join (demux->download_task);
|
gst_task_join (demux->download_task);
|
||||||
}
|
}
|
||||||
if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
|
if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
|
||||||
GST_TASK_SIGNAL (demux->stream_task);
|
GST_TASK_SIGNAL (demux->stream_task);
|
||||||
gst_task_stop (demux->stream_task);
|
gst_task_stop (demux->stream_task);
|
||||||
g_static_rec_mutex_lock (&demux->stream_task_lock);
|
g_rec_mutex_lock (&demux->stream_task_lock);
|
||||||
g_static_rec_mutex_unlock (&demux->stream_task_lock);
|
g_rec_mutex_unlock (&demux->stream_task_lock);
|
||||||
gst_task_join (demux->stream_task);
|
gst_task_join (demux->stream_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1001,7 +999,7 @@ static gboolean
|
||||||
gst_dash_demux_advance_period (GstDashDemux * demux)
|
gst_dash_demux_advance_period (GstDashDemux * demux)
|
||||||
{
|
{
|
||||||
GSList *old_period = NULL;
|
GSList *old_period = NULL;
|
||||||
g_static_mutex_lock (&demux->streams_lock);
|
g_mutex_lock (&demux->streams_lock);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "Advancing period from %p", demux->streams);
|
GST_DEBUG_OBJECT (demux, "Advancing period from %p", demux->streams);
|
||||||
|
|
||||||
|
@ -1019,14 +1017,14 @@ gst_dash_demux_advance_period (GstDashDemux * demux)
|
||||||
demux->streams = demux->next_periods->data;
|
demux->streams = demux->next_periods->data;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (demux, "No next periods, return FALSE");
|
GST_DEBUG_OBJECT (demux, "No next periods, return FALSE");
|
||||||
g_static_mutex_unlock (&demux->streams_lock);
|
g_mutex_unlock (&demux->streams_lock);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_dash_demux_expose_streams (demux);
|
gst_dash_demux_expose_streams (demux);
|
||||||
gst_dash_demux_remove_streams (demux, old_period);
|
gst_dash_demux_remove_streams (demux, old_period);
|
||||||
|
|
||||||
g_static_mutex_unlock (&demux->streams_lock);
|
g_mutex_unlock (&demux->streams_lock);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1148,9 +1146,7 @@ gst_dash_demux_stream_loop (GstDashDemux * demux)
|
||||||
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
|
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
|
||||||
GstDashDemuxStream *stream = iter->data;
|
GstDashDemuxStream *stream = iter->data;
|
||||||
gst_pad_push_event (stream->pad,
|
gst_pad_push_event (stream->pad,
|
||||||
gst_event_new_new_segment (FALSE, demux->segment.rate,
|
gst_event_new_segment (&demux->segment));
|
||||||
GST_FORMAT_TIME, demux->segment.start, demux->segment.stop,
|
|
||||||
demux->segment.time));
|
|
||||||
}
|
}
|
||||||
demux->need_segment = FALSE;
|
demux->need_segment = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1171,7 +1167,7 @@ gst_dash_demux_stream_loop (GstDashDemux * demux)
|
||||||
GST_DEBUG_PAD_NAME (selected_stream->pad));
|
GST_DEBUG_PAD_NAME (selected_stream->pad));
|
||||||
#endif
|
#endif
|
||||||
ret = gst_pad_push (selected_stream->pad, gst_buffer_ref (buffer));
|
ret = gst_pad_push (selected_stream->pad, gst_buffer_ref (buffer));
|
||||||
gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME, timestamp);
|
demux->segment.position = timestamp;
|
||||||
|
|
||||||
item->destroy (item);
|
item->destroy (item);
|
||||||
if ((ret != GST_FLOW_OK) && (active_stream
|
if ((ret != GST_FLOW_OK) && (active_stream
|
||||||
|
@ -1422,16 +1418,18 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
GST_WARNING_OBJECT (demux, "Error validating the manifest.");
|
GST_WARNING_OBJECT (demux, "Error validating the manifest.");
|
||||||
} else {
|
} else {
|
||||||
|
GstMapInfo mapinfo;
|
||||||
new_client = gst_mpd_client_new ();
|
new_client = gst_mpd_client_new ();
|
||||||
new_client->mpd_uri = g_strdup (demux->client->mpd_uri);
|
new_client->mpd_uri = g_strdup (demux->client->mpd_uri);
|
||||||
|
|
||||||
if (!gst_mpd_parse (new_client,
|
gst_buffer_map (buffer, &mapinfo, GST_MAP_READ);
|
||||||
(gchar *) GST_BUFFER_DATA (buffer),
|
|
||||||
GST_BUFFER_SIZE (buffer))) {
|
if (!gst_mpd_parse (new_client, (gchar *) mapinfo.data, mapinfo.size)) {
|
||||||
/* In most cases, this will happen if we set a wrong url in the
|
/* In most cases, this will happen if we set a wrong url in the
|
||||||
* source element and we have received the 404 HTML response instead of
|
* source element and we have received the 404 HTML response instead of
|
||||||
* the manifest */
|
* the manifest */
|
||||||
GST_WARNING_OBJECT (demux, "Error parsing the manifest.");
|
GST_WARNING_OBJECT (demux, "Error parsing the manifest.");
|
||||||
|
gst_buffer_unmap (buffer, &mapinfo);
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
} else {
|
} else {
|
||||||
const gchar *period_id;
|
const gchar *period_id;
|
||||||
|
@ -1441,6 +1439,7 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
|
||||||
/* prepare the new manifest and try to transfer the stream position
|
/* prepare the new manifest and try to transfer the stream position
|
||||||
* status from the old manifest client */
|
* status from the old manifest client */
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, &mapinfo);
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "Updating manifest");
|
GST_DEBUG_OBJECT (demux, "Updating manifest");
|
||||||
|
@ -1509,8 +1508,7 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
|
||||||
"Sending duration message : %" GST_TIME_FORMAT,
|
"Sending duration message : %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (duration));
|
GST_TIME_ARGS (duration));
|
||||||
gst_element_post_message (GST_ELEMENT (demux),
|
gst_element_post_message (GST_ELEMENT (demux),
|
||||||
gst_message_new_duration (GST_OBJECT (demux), GST_FORMAT_TIME,
|
gst_message_new_duration_changed (GST_OBJECT (demux)));
|
||||||
duration));
|
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (demux,
|
GST_DEBUG_OBJECT (demux,
|
||||||
"mediaPresentationDuration unknown, can not send the duration message");
|
"mediaPresentationDuration unknown, can not send the duration message");
|
||||||
|
@ -1669,6 +1667,8 @@ gst_dash_demux_select_representations (GstDashDemux * demux)
|
||||||
gst_caps_unref (stream->input_caps);
|
gst_caps_unref (stream->input_caps);
|
||||||
stream->input_caps =
|
stream->input_caps =
|
||||||
gst_dash_demux_get_input_caps (demux, active_stream);
|
gst_dash_demux_get_input_caps (demux, active_stream);
|
||||||
|
gst_dash_demux_stream_push_event (stream,
|
||||||
|
gst_event_new_caps (stream->input_caps));
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING_OBJECT (demux,
|
GST_WARNING_OBJECT (demux,
|
||||||
"Can not switch representation, aborting...");
|
"Can not switch representation, aborting...");
|
||||||
|
@ -1728,7 +1728,7 @@ gst_dash_demux_get_video_input_caps (GstDashDemux * demux,
|
||||||
if (mimeType == NULL)
|
if (mimeType == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
caps = gst_caps_new_simple (mimeType, NULL);
|
caps = gst_caps_new_empty_simple (mimeType);
|
||||||
if (width > 0 && height > 0) {
|
if (width > 0 && height > 0) {
|
||||||
gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height",
|
gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height",
|
||||||
G_TYPE_INT, height, NULL);
|
G_TYPE_INT, height, NULL);
|
||||||
|
@ -1757,7 +1757,7 @@ gst_dash_demux_get_audio_input_caps (GstDashDemux * demux,
|
||||||
if (mimeType == NULL)
|
if (mimeType == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
caps = gst_caps_new_simple (mimeType, NULL);
|
caps = gst_caps_new_empty_simple (mimeType);
|
||||||
if (rate > 0) {
|
if (rate > 0) {
|
||||||
gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate, NULL);
|
gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1782,7 +1782,7 @@ gst_dash_demux_get_application_input_caps (GstDashDemux * demux,
|
||||||
if (mimeType == NULL)
|
if (mimeType == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
caps = gst_caps_new_simple (mimeType, NULL);
|
caps = gst_caps_new_empty_simple (mimeType);
|
||||||
|
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
@ -1830,10 +1830,10 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux)
|
||||||
GstClockTime best_time = GST_CLOCK_TIME_NONE;
|
GstClockTime best_time = GST_CLOCK_TIME_NONE;
|
||||||
GSList *streams;
|
GSList *streams;
|
||||||
|
|
||||||
g_static_mutex_lock (&demux->streams_lock);
|
g_mutex_lock (&demux->streams_lock);
|
||||||
/* TODO add check */
|
/* TODO add check */
|
||||||
streams = g_slist_last (demux->next_periods)->data;
|
streams = g_slist_last (demux->next_periods)->data;
|
||||||
g_static_mutex_unlock (&demux->streams_lock);
|
g_mutex_unlock (&demux->streams_lock);
|
||||||
|
|
||||||
for (iter = streams; iter; iter = g_slist_next (iter)) {
|
for (iter = streams; iter; iter = g_slist_next (iter)) {
|
||||||
GstDashDemuxStream *stream = iter->data;
|
GstDashDemuxStream *stream = iter->data;
|
||||||
|
@ -1919,24 +1919,23 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux)
|
||||||
/* Replace fragment with a new one including the header */
|
/* Replace fragment with a new one including the header */
|
||||||
|
|
||||||
header_buffer = gst_fragment_get_buffer (header);
|
header_buffer = gst_fragment_get_buffer (header);
|
||||||
buffer = gst_buffer_join (header_buffer, buffer);
|
buffer = gst_buffer_append (header_buffer, buffer);
|
||||||
g_object_unref (header);
|
g_object_unref (header);
|
||||||
}
|
}
|
||||||
selected_stream->need_header = FALSE;
|
selected_stream->need_header = FALSE;
|
||||||
}
|
}
|
||||||
g_get_current_time (&now);
|
g_get_current_time (&now);
|
||||||
|
|
||||||
buffer = gst_buffer_make_metadata_writable (buffer);
|
buffer = gst_buffer_make_writable (buffer);
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = timestamp;
|
GST_BUFFER_TIMESTAMP (buffer) = timestamp;
|
||||||
GST_BUFFER_DURATION (buffer) = duration;
|
GST_BUFFER_DURATION (buffer) = duration;
|
||||||
GST_BUFFER_OFFSET (buffer) =
|
GST_BUFFER_OFFSET (buffer) =
|
||||||
gst_mpd_client_get_segment_index (active_stream) - 1;
|
gst_mpd_client_get_segment_index (active_stream) - 1;
|
||||||
|
|
||||||
gst_buffer_set_caps (buffer, selected_stream->input_caps);
|
|
||||||
gst_dash_demux_stream_push_data (selected_stream, buffer);
|
gst_dash_demux_stream_push_data (selected_stream, buffer);
|
||||||
selected_stream->has_data_queued = TRUE;
|
selected_stream->has_data_queued = TRUE;
|
||||||
size_buffer += GST_BUFFER_SIZE (buffer);
|
size_buffer += gst_buffer_get_size (buffer);
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING_OBJECT (demux, "Failed to download fragment for stream %p %d",
|
GST_WARNING_OBJECT (demux, "Failed to download fragment for stream %p %d",
|
||||||
selected_stream, selected_stream->index);
|
selected_stream, selected_stream->index);
|
||||||
|
|
|
@ -108,7 +108,7 @@ struct _GstDashDemux
|
||||||
|
|
||||||
GSList *streams;
|
GSList *streams;
|
||||||
GSList *next_periods;
|
GSList *next_periods;
|
||||||
GStaticMutex streams_lock;
|
GMutex streams_lock;
|
||||||
|
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
gboolean need_segment;
|
gboolean need_segment;
|
||||||
|
@ -127,11 +127,11 @@ struct _GstDashDemux
|
||||||
|
|
||||||
/* Streaming task */
|
/* Streaming task */
|
||||||
GstTask *stream_task;
|
GstTask *stream_task;
|
||||||
GStaticRecMutex stream_task_lock;
|
GRecMutex stream_task_lock;
|
||||||
|
|
||||||
/* Download task */
|
/* Download task */
|
||||||
GstTask *download_task;
|
GstTask *download_task;
|
||||||
GStaticRecMutex download_task_lock;
|
GRecMutex download_task_lock;
|
||||||
gboolean cancelled;
|
gboolean cancelled;
|
||||||
|
|
||||||
/* Manifest update */
|
/* Manifest update */
|
||||||
|
|
|
@ -41,7 +41,7 @@ void
|
||||||
gst_download_rate_init (GstDownloadRate * rate)
|
gst_download_rate_init (GstDownloadRate * rate)
|
||||||
{
|
{
|
||||||
g_queue_init (&rate->queue);
|
g_queue_init (&rate->queue);
|
||||||
g_static_mutex_init (&rate->mutex);
|
g_mutex_init (&rate->mutex);
|
||||||
rate->total = 0;
|
rate->total = 0;
|
||||||
rate->max_length = 0;
|
rate->max_length = 0;
|
||||||
}
|
}
|
||||||
|
@ -50,25 +50,25 @@ void
|
||||||
gst_download_rate_deinit (GstDownloadRate * rate)
|
gst_download_rate_deinit (GstDownloadRate * rate)
|
||||||
{
|
{
|
||||||
gst_download_rate_clear (rate);
|
gst_download_rate_clear (rate);
|
||||||
g_static_mutex_free (&rate->mutex);
|
g_mutex_clear (&rate->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_download_rate_set_max_length (GstDownloadRate * rate, gint max_length)
|
gst_download_rate_set_max_length (GstDownloadRate * rate, gint max_length)
|
||||||
{
|
{
|
||||||
g_static_mutex_lock (&rate->mutex);
|
g_mutex_lock (&rate->mutex);
|
||||||
rate->max_length = max_length;
|
rate->max_length = max_length;
|
||||||
_gst_download_rate_check_remove_rates (rate);
|
_gst_download_rate_check_remove_rates (rate);
|
||||||
g_static_mutex_unlock (&rate->mutex);
|
g_mutex_unlock (&rate->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
gst_download_rate_get_max_length (GstDownloadRate * rate)
|
gst_download_rate_get_max_length (GstDownloadRate * rate)
|
||||||
{
|
{
|
||||||
guint ret;
|
guint ret;
|
||||||
g_static_mutex_lock (&rate->mutex);
|
g_mutex_lock (&rate->mutex);
|
||||||
ret = rate->max_length;
|
ret = rate->max_length;
|
||||||
g_static_mutex_unlock (&rate->mutex);
|
g_mutex_unlock (&rate->mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -76,17 +76,17 @@ gst_download_rate_get_max_length (GstDownloadRate * rate)
|
||||||
void
|
void
|
||||||
gst_download_rate_clear (GstDownloadRate * rate)
|
gst_download_rate_clear (GstDownloadRate * rate)
|
||||||
{
|
{
|
||||||
g_static_mutex_lock (&rate->mutex);
|
g_mutex_lock (&rate->mutex);
|
||||||
g_queue_clear (&rate->queue);
|
g_queue_clear (&rate->queue);
|
||||||
rate->total = 0;
|
rate->total = 0;
|
||||||
g_static_mutex_unlock (&rate->mutex);
|
g_mutex_unlock (&rate->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_download_rate_add_rate (GstDownloadRate * rate, guint bytes, guint64 time)
|
gst_download_rate_add_rate (GstDownloadRate * rate, guint bytes, guint64 time)
|
||||||
{
|
{
|
||||||
guint64 bitrate;
|
guint64 bitrate;
|
||||||
g_static_mutex_lock (&rate->mutex);
|
g_mutex_lock (&rate->mutex);
|
||||||
|
|
||||||
/* convert from bytes / nanoseconds to bits per second */
|
/* convert from bytes / nanoseconds to bits per second */
|
||||||
bitrate = G_GUINT64_CONSTANT (8000000000) * bytes / time;
|
bitrate = G_GUINT64_CONSTANT (8000000000) * bytes / time;
|
||||||
|
@ -95,16 +95,19 @@ gst_download_rate_add_rate (GstDownloadRate * rate, guint bytes, guint64 time)
|
||||||
rate->total += bitrate;
|
rate->total += bitrate;
|
||||||
|
|
||||||
_gst_download_rate_check_remove_rates (rate);
|
_gst_download_rate_check_remove_rates (rate);
|
||||||
g_static_mutex_unlock (&rate->mutex);
|
g_mutex_unlock (&rate->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
guint
|
guint
|
||||||
gst_download_rate_get_current_rate (GstDownloadRate * rate)
|
gst_download_rate_get_current_rate (GstDownloadRate * rate)
|
||||||
{
|
{
|
||||||
guint ret;
|
guint ret;
|
||||||
g_static_mutex_lock (&rate->mutex);
|
g_mutex_lock (&rate->mutex);
|
||||||
ret = rate->total / g_queue_get_length (&rate->queue);
|
if (g_queue_get_length (&rate->queue))
|
||||||
g_static_mutex_unlock (&rate->mutex);
|
ret = rate->total / g_queue_get_length (&rate->queue);
|
||||||
|
else
|
||||||
|
ret = G_MAXUINT;
|
||||||
|
g_mutex_unlock (&rate->mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ typedef struct _GstDownloadRate GstDownloadRate;
|
||||||
struct _GstDownloadRate
|
struct _GstDownloadRate
|
||||||
{
|
{
|
||||||
GQueue queue;
|
GQueue queue;
|
||||||
GStaticMutex mutex;
|
GMutex mutex;
|
||||||
|
|
||||||
gint max_length;
|
gint max_length;
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,6 @@ fragmented_init (GstPlugin * plugin)
|
||||||
|
|
||||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||||
GST_VERSION_MINOR,
|
GST_VERSION_MINOR,
|
||||||
"dashdemux",
|
dashdemux,
|
||||||
"DASH demuxer plugin",
|
"DASH demuxer plugin",
|
||||||
fragmented_init, VERSION, "LGPL", PACKAGE_NAME, "http://www.gstreamer.org/")
|
fragmented_init, VERSION, "LGPL", PACKAGE_NAME, "http://www.gstreamer.org/")
|
||||||
|
|
Loading…
Reference in a new issue