dashdemux: include segment duration when calculating seek range
authorAlex Ashley <bugzilla@ashley-family.net>
Wed, 24 Feb 2016 15:54:54 +0000 (15:54 +0000)
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Tue, 2 Aug 2016 11:52:34 +0000 (12:52 +0100)
The gst_dash_demux_get_live_seek_range () function returns a stop value
that is beyond the available range. The functions
gst_mpd_client_check_time_position() and
gst_mpd_client_get_next_segment_availability_end_time() in
gstmpdparser.c include the segment duration when checking if a segment
is available. The gst_dash_demux_get_live_seek_range() function
in gstdashdemux.c ignores the segment duration.

According to the DASH specification, if maxSegmentDuration is not present,
then the maximum Segment duration is the maximum duration of any Segment
documented in the MPD.

https://bugzilla.gnome.org/show_bug.cgi?id=753751

ext/dash/gstdashdemux.c
ext/dash/gstmpdparser.c
ext/dash/gstmpdparser.h

index 2b4f48c487d47fde45866b396ce2429d648e6f66..cba70b39793b588c2ec2f1403164e9220aee6689 100644 (file)
@@ -317,10 +317,12 @@ gst_dash_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
   GDateTime *now;
   GDateTime *mstart;
   GTimeSpan stream_now;
+  GstClockTime seg_duration;
 
   if (self->client->mpd_node->availabilityStartTime == NULL)
     return FALSE;
 
+  seg_duration = gst_mpd_client_get_maximum_segment_duration (self->client);
   now = gst_dash_demux_get_server_now_utc (self);
   mstart =
       gst_date_time_to_g_date_time (self->client->
@@ -341,6 +343,17 @@ gst_dash_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
     if (*start < 0)
       *start = 0;
   }
+
+  /* As defined in 5.3.9.5.3 of the DASH specification, a segment does
+     not become available until the sum of:
+     * the value of the MPD@availabilityStartTime,
+     * the PeriodStart time of the containing Period
+     * the MPD start time of the Media Segment, and
+     * the MPD duration of the Media Segment.
+     Therefore we need to subtract the media segment duration from the stop
+     time.
+   */
+  *stop -= seg_duration;
   return TRUE;
 }
 
index dd831659172d89876e56ae177b29cf6243f2d9ac..7166ecbf4a9c3888d21d33300e42486a8a049b53 100644 (file)
@@ -5989,3 +5989,29 @@ gst_mpd_client_parse_default_presentation_delay (GstMpdClient * client,
   }
   return value;
 }
+
+GstClockTime
+gst_mpd_client_get_maximum_segment_duration (GstMpdClient * client)
+{
+  GstClockTime ret = GST_CLOCK_TIME_NONE, dur;
+  GList *stream;
+
+  g_return_val_if_fail (client != NULL, GST_CLOCK_TIME_NONE);
+  g_return_val_if_fail (client->mpd_node != NULL, GST_CLOCK_TIME_NONE);
+
+  if (client->mpd_node->maxSegmentDuration != GST_MPD_DURATION_NONE) {
+    return client->mpd_node->maxSegmentDuration * GST_MSECOND;
+  }
+
+  /* According to the DASH specification, if maxSegmentDuration is not present:
+     "If not present, then the maximum Segment duration shall be the maximum
+     duration of any Segment documented in this MPD"
+   */
+  for (stream = client->active_streams; stream; stream = g_list_next (stream)) {
+    dur = gst_mpd_client_get_segment_duration (client, stream->data, NULL);
+    if (dur != GST_CLOCK_TIME_NONE && (dur > ret || ret == GST_CLOCK_TIME_NONE)) {
+      ret = dur;
+    }
+  }
+  return ret;
+}
index 1b303aaabd067338de69fea68a2354041c511c91..bc3f1ef2fff6d9636605eb29eb46c9f44c50eca4 100644 (file)
@@ -538,6 +538,7 @@ gboolean gst_mpd_client_setup_streaming (GstMpdClient * client, GstAdaptationSet
 gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation);
 GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream);
 GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client);
+GstClockTime gst_mpd_client_get_maximum_segment_duration (GstMpdClient * client);
 gboolean gst_mpd_client_get_last_fragment_timestamp_end (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
 gboolean gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
 gboolean gst_mpd_client_get_next_fragment (GstMpdClient *client, guint indexStream, GstMediaFragmentInfo * fragment);