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 2b4f48c..cba70b3 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 dd83165..7166ecb 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 1b303aa..bc3f1ef 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);