mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
smoothstreaming: implement adaptivedemux's get_live_seek_range()
Allows seeking through the available fragments that are still available on the server as specified by the DVRWindowLength attribute in the manifest. https://bugzilla.gnome.org/show_bug.cgi?id=774178
This commit is contained in:
parent
28396d348f
commit
e9178fa082
3 changed files with 98 additions and 0 deletions
|
@ -138,6 +138,8 @@ gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux);
|
|||
static GstFlowReturn
|
||||
gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
|
||||
GstBuffer * buffer);
|
||||
static gboolean gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux,
|
||||
gint64 * start, gint64 * stop);
|
||||
|
||||
static void
|
||||
gst_mss_demux_class_init (GstMssDemuxClass * klass)
|
||||
|
@ -192,6 +194,8 @@ gst_mss_demux_class_init (GstMssDemuxClass * klass)
|
|||
gst_mss_demux_stream_update_fragment_info;
|
||||
gstadaptivedemux_class->update_manifest_data =
|
||||
gst_mss_demux_update_manifest_data;
|
||||
gstadaptivedemux_class->get_live_seek_range =
|
||||
gst_mss_demux_get_live_seek_range;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (mssdemux_debug, "mssdemux", 0, "mssdemux plugin");
|
||||
}
|
||||
|
@ -659,3 +663,12 @@ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
|
|||
gst_mss_manifest_reload_fragments (mssdemux->manifest, buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
|
||||
gint64 * stop)
|
||||
{
|
||||
GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
|
||||
|
||||
return gst_mss_manifest_get_live_seek_range (mssdemux->manifest, start, stop);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);
|
|||
|
||||
#define MSS_PROP_BITRATE "Bitrate"
|
||||
#define MSS_PROP_DURATION "d"
|
||||
#define MSS_PROP_DVR_WINDOW_LENGTH "DVRWindowLength"
|
||||
#define MSS_PROP_LANGUAGE "Language"
|
||||
#define MSS_PROP_NUMBER "n"
|
||||
#define MSS_PROP_REPETITIONS "r"
|
||||
|
@ -94,6 +95,7 @@ struct _GstMssManifest
|
|||
xmlNodePtr xmlrootnode;
|
||||
|
||||
gboolean is_live;
|
||||
gint64 dvr_window;
|
||||
|
||||
GString *protection_system_id;
|
||||
gchar *protection_data;
|
||||
|
@ -330,6 +332,22 @@ gst_mss_manifest_new (GstBuffer * data)
|
|||
xmlFree (live_str);
|
||||
}
|
||||
|
||||
/* the entire file is always available for non-live streams */
|
||||
if (!manifest->is_live) {
|
||||
manifest->dvr_window = 0;
|
||||
} else {
|
||||
/* if 0, or non-existent, the length is infinite */
|
||||
gchar *dvr_window_str = (gchar *) xmlGetProp (root,
|
||||
(xmlChar *) MSS_PROP_DVR_WINDOW_LENGTH);
|
||||
if (dvr_window_str) {
|
||||
manifest->dvr_window = g_ascii_strtoull (dvr_window_str, NULL, 10);
|
||||
xmlFree (dvr_window_str);
|
||||
if (manifest->dvr_window <= 0) {
|
||||
manifest->dvr_window = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (nodeiter = root->children; nodeiter; nodeiter = nodeiter->next) {
|
||||
if (nodeiter->type == XML_ELEMENT_NODE
|
||||
&& (strcmp ((const char *) nodeiter->name, "StreamIndex") == 0)) {
|
||||
|
@ -1406,3 +1424,69 @@ gst_mss_stream_get_lang (GstMssStream * stream)
|
|||
{
|
||||
return stream->lang;
|
||||
}
|
||||
|
||||
static GstClockTime
|
||||
gst_mss_manifest_get_dvr_window_length_clock_time (GstMssManifest * manifest)
|
||||
{
|
||||
gint64 timescale;
|
||||
|
||||
/* the entire file is always available for non-live streams */
|
||||
if (manifest->dvr_window == 0)
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
|
||||
timescale = gst_mss_manifest_get_timescale (manifest);
|
||||
return (GstClockTime) gst_util_uint64_scale_round (manifest->dvr_window,
|
||||
GST_SECOND, timescale);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_mss_stream_get_live_seek_range (GstMssStream * stream, gint64 * start,
|
||||
gint64 * stop)
|
||||
{
|
||||
GList *l;
|
||||
GstMssStreamFragment *fragment;
|
||||
guint64 timescale = gst_mss_stream_get_timescale (stream);
|
||||
|
||||
g_return_val_if_fail (stream->active, FALSE);
|
||||
|
||||
/* XXX: assumes all the data in the stream is still available */
|
||||
l = g_list_first (stream->fragments);
|
||||
fragment = (GstMssStreamFragment *) l->data;
|
||||
*start = gst_util_uint64_scale_round (fragment->time, GST_SECOND, timescale);
|
||||
|
||||
l = g_list_last (stream->fragments);
|
||||
fragment = (GstMssStreamFragment *) l->data;
|
||||
*stop = gst_util_uint64_scale_round (fragment->time + fragment->duration *
|
||||
fragment->repetitions, GST_SECOND, timescale);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_mss_manifest_get_live_seek_range (GstMssManifest * manifest, gint64 * start,
|
||||
gint64 * stop)
|
||||
{
|
||||
GSList *iter;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
for (iter = manifest->streams; iter; iter = g_slist_next (iter)) {
|
||||
GstMssStream *stream = iter->data;
|
||||
|
||||
if (stream->active) {
|
||||
/* FIXME: bound this correctly for multiple streams */
|
||||
if (!(ret = gst_mss_stream_get_live_seek_range (stream, start, stop)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret && gst_mss_manifest_is_live (manifest)) {
|
||||
GstClockTime dvr_window =
|
||||
gst_mss_manifest_get_dvr_window_length_clock_time (manifest);
|
||||
|
||||
if (GST_CLOCK_TIME_IS_VALID (dvr_window) && *stop - *start > dvr_window) {
|
||||
*start = *stop - dvr_window;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ void gst_mss_manifest_reload_fragments (GstMssManifest * manifest, GstBuffer * d
|
|||
GstClockTime gst_mss_manifest_get_min_fragment_duration (GstMssManifest * manifest);
|
||||
const gchar * gst_mss_manifest_get_protection_system_id (GstMssManifest * manifest);
|
||||
const gchar * gst_mss_manifest_get_protection_data (GstMssManifest * manifest);
|
||||
gboolean gst_mss_manifest_get_live_seek_range (GstMssManifest * manifest, gint64 * start, gint64 * stop);
|
||||
|
||||
GstMssStreamType gst_mss_stream_get_type (GstMssStream *stream);
|
||||
GstCaps * gst_mss_stream_get_caps (GstMssStream * stream);
|
||||
|
|
Loading…
Reference in a new issue