]> code.ossystems Code Review - openembedded-core.git/blob
76d29e151b2aef2a34e7e851e45d9c081cbda555
[openembedded-core.git] /
1 From e9178fa082116d4bf733b184a8b6951112c17900 Mon Sep 17 00:00:00 2001
2 From: Matthew Waters <matthew@centricular.com>
3 Date: Thu, 10 Nov 2016 17:18:36 +1100
4 Subject: [PATCH] smoothstreaming: implement adaptivedemux's
5  get_live_seek_range()
6
7 Allows seeking through the available fragments that are still available
8 on the server as specified by the DVRWindowLength attribute in the
9 manifest.
10
11 https://bugzilla.gnome.org/show_bug.cgi?id=774178
12 ---
13 Upstream-Status: Backport
14 Signed-off-by: Khem Raj <raj.khem@gmail.com>
15
16  ext/smoothstreaming/gstmssdemux.c    | 13 ++++++
17  ext/smoothstreaming/gstmssmanifest.c | 84 ++++++++++++++++++++++++++++++++++++
18  ext/smoothstreaming/gstmssmanifest.h |  1 +
19  3 files changed, 98 insertions(+)
20
21 diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c
22 index 9d0aece2b..b66e19514 100644
23 --- a/ext/smoothstreaming/gstmssdemux.c
24 +++ b/ext/smoothstreaming/gstmssdemux.c
25 @@ -138,6 +138,8 @@ gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux);
26  static GstFlowReturn
27  gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
28      GstBuffer * buffer);
29 +static gboolean gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux,
30 +    gint64 * start, gint64 * stop);
31  
32  static void
33  gst_mss_demux_class_init (GstMssDemuxClass * klass)
34 @@ -192,6 +194,8 @@ gst_mss_demux_class_init (GstMssDemuxClass * klass)
35        gst_mss_demux_stream_update_fragment_info;
36    gstadaptivedemux_class->update_manifest_data =
37        gst_mss_demux_update_manifest_data;
38 +  gstadaptivedemux_class->get_live_seek_range =
39 +      gst_mss_demux_get_live_seek_range;
40  
41    GST_DEBUG_CATEGORY_INIT (mssdemux_debug, "mssdemux", 0, "mssdemux plugin");
42  }
43 @@ -659,3 +663,12 @@ gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
44    gst_mss_manifest_reload_fragments (mssdemux->manifest, buffer);
45    return GST_FLOW_OK;
46  }
47 +
48 +static gboolean
49 +gst_mss_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
50 +    gint64 * stop)
51 +{
52 +  GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
53 +
54 +  return gst_mss_manifest_get_live_seek_range (mssdemux->manifest, start, stop);
55 +}
56 diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c
57 index 1b72e8de1..317b3cef9 100644
58 --- a/ext/smoothstreaming/gstmssmanifest.c
59 +++ b/ext/smoothstreaming/gstmssmanifest.c
60 @@ -42,6 +42,7 @@ GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);
61  
62  #define MSS_PROP_BITRATE              "Bitrate"
63  #define MSS_PROP_DURATION             "d"
64 +#define MSS_PROP_DVR_WINDOW_LENGTH    "DVRWindowLength"
65  #define MSS_PROP_LANGUAGE             "Language"
66  #define MSS_PROP_NUMBER               "n"
67  #define MSS_PROP_REPETITIONS          "r"
68 @@ -94,6 +95,7 @@ struct _GstMssManifest
69    xmlNodePtr xmlrootnode;
70  
71    gboolean is_live;
72 +  gint64 dvr_window;
73  
74    GString *protection_system_id;
75    gchar *protection_data;
76 @@ -330,6 +332,22 @@ gst_mss_manifest_new (GstBuffer * data)
77      xmlFree (live_str);
78    }
79  
80 +  /* the entire file is always available for non-live streams */
81 +  if (!manifest->is_live) {
82 +    manifest->dvr_window = 0;
83 +  } else {
84 +    /* if 0, or non-existent, the length is infinite */
85 +    gchar *dvr_window_str = (gchar *) xmlGetProp (root,
86 +        (xmlChar *) MSS_PROP_DVR_WINDOW_LENGTH);
87 +    if (dvr_window_str) {
88 +      manifest->dvr_window = g_ascii_strtoull (dvr_window_str, NULL, 10);
89 +      xmlFree (dvr_window_str);
90 +      if (manifest->dvr_window <= 0) {
91 +        manifest->dvr_window = 0;
92 +      }
93 +    }
94 +  }
95 +
96    for (nodeiter = root->children; nodeiter; nodeiter = nodeiter->next) {
97      if (nodeiter->type == XML_ELEMENT_NODE
98          && (strcmp ((const char *) nodeiter->name, "StreamIndex") == 0)) {
99 @@ -1406,3 +1424,69 @@ gst_mss_stream_get_lang (GstMssStream * stream)
100  {
101    return stream->lang;
102  }
103 +
104 +static GstClockTime
105 +gst_mss_manifest_get_dvr_window_length_clock_time (GstMssManifest * manifest)
106 +{
107 +  gint64 timescale;
108 +
109 +  /* the entire file is always available for non-live streams */
110 +  if (manifest->dvr_window == 0)
111 +    return GST_CLOCK_TIME_NONE;
112 +
113 +  timescale = gst_mss_manifest_get_timescale (manifest);
114 +  return (GstClockTime) gst_util_uint64_scale_round (manifest->dvr_window,
115 +      GST_SECOND, timescale);
116 +}
117 +
118 +static gboolean
119 +gst_mss_stream_get_live_seek_range (GstMssStream * stream, gint64 * start,
120 +    gint64 * stop)
121 +{
122 +  GList *l;
123 +  GstMssStreamFragment *fragment;
124 +  guint64 timescale = gst_mss_stream_get_timescale (stream);
125 +
126 +  g_return_val_if_fail (stream->active, FALSE);
127 +
128 +  /* XXX: assumes all the data in the stream is still available */
129 +  l = g_list_first (stream->fragments);
130 +  fragment = (GstMssStreamFragment *) l->data;
131 +  *start = gst_util_uint64_scale_round (fragment->time, GST_SECOND, timescale);
132 +
133 +  l = g_list_last (stream->fragments);
134 +  fragment = (GstMssStreamFragment *) l->data;
135 +  *stop = gst_util_uint64_scale_round (fragment->time + fragment->duration *
136 +      fragment->repetitions, GST_SECOND, timescale);
137 +
138 +  return TRUE;
139 +}
140 +
141 +gboolean
142 +gst_mss_manifest_get_live_seek_range (GstMssManifest * manifest, gint64 * start,
143 +    gint64 * stop)
144 +{
145 +  GSList *iter;
146 +  gboolean ret = FALSE;
147 +
148 +  for (iter = manifest->streams; iter; iter = g_slist_next (iter)) {
149 +    GstMssStream *stream = iter->data;
150 +
151 +    if (stream->active) {
152 +      /* FIXME: bound this correctly for multiple streams */
153 +      if (!(ret = gst_mss_stream_get_live_seek_range (stream, start, stop)))
154 +        break;
155 +    }
156 +  }
157 +
158 +  if (ret && gst_mss_manifest_is_live (manifest)) {
159 +    GstClockTime dvr_window =
160 +        gst_mss_manifest_get_dvr_window_length_clock_time (manifest);
161 +
162 +    if (GST_CLOCK_TIME_IS_VALID (dvr_window) && *stop - *start > dvr_window) {
163 +      *start = *stop - dvr_window;
164 +    }
165 +  }
166 +
167 +  return ret;
168 +}
169 diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h
170 index af7419c23..6b7b1f971 100644
171 --- a/ext/smoothstreaming/gstmssmanifest.h
172 +++ b/ext/smoothstreaming/gstmssmanifest.h
173 @@ -54,6 +54,7 @@ void gst_mss_manifest_reload_fragments (GstMssManifest * manifest, GstBuffer * d
174  GstClockTime gst_mss_manifest_get_min_fragment_duration (GstMssManifest * manifest);
175  const gchar * gst_mss_manifest_get_protection_system_id (GstMssManifest * manifest);
176  const gchar * gst_mss_manifest_get_protection_data (GstMssManifest * manifest);
177 +gboolean gst_mss_manifest_get_live_seek_range (GstMssManifest * manifest, gint64 * start, gint64 * stop);
178  
179  GstMssStreamType gst_mss_stream_get_type (GstMssStream *stream);
180  GstCaps * gst_mss_stream_get_caps (GstMssStream * stream);
181 -- 
182 2.11.0
183