mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 16:51:10 +00:00
dashdemux: Change first fragment selection for live streams
When dashdemux selects its first fragment, it always selects the first fragment listed in the manifest. For on-demand content, this is the correct behaviour. However for live content, this behaviour is undesirable because the first fragment listed in the manifest might be some considerable time behind "now". The commit uses the host's idea of UTC and tries to find the oldest fragment that contains samples for this time of day. https://bugzilla.gnome.org/show_bug.cgi?id=701509
This commit is contained in:
parent
51d8fa5860
commit
5ad2a2d161
3 changed files with 136 additions and 7 deletions
|
@ -793,8 +793,52 @@ gst_dash_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
|||
|
||||
gst_dash_demux_advance_period (demux);
|
||||
|
||||
/* start playing from the first segment */
|
||||
gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
|
||||
/* If stream is live, try to find the segment that is closest to current time */
|
||||
if (gst_mpd_client_is_live (demux->client)) {
|
||||
GSList *iter;
|
||||
GstDateTime *now = gst_date_time_new_now_utc ();
|
||||
gint seg_idx;
|
||||
|
||||
GST_DEBUG_OBJECT (demux,
|
||||
"Seeking to current time of day for live stream ");
|
||||
if (demux->client->mpd_node->suggestedPresentationDelay != -1) {
|
||||
GstDateTime *target = gst_mpd_client_add_time_difference (now,
|
||||
demux->client->mpd_node->suggestedPresentationDelay * -1000);
|
||||
gst_date_time_unref (now);
|
||||
now = target;
|
||||
}
|
||||
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
|
||||
GstDashDemuxStream *stream = iter->data;
|
||||
GstActiveStream *active_stream;
|
||||
|
||||
active_stream =
|
||||
gst_mpdparser_get_active_stream_by_index (demux->client,
|
||||
stream->index);
|
||||
|
||||
/* Get segment index corresponding to current time. */
|
||||
seg_idx =
|
||||
gst_mpd_client_get_segment_index_at_time (demux->client,
|
||||
active_stream, now);
|
||||
if (seg_idx < 0) {
|
||||
GST_WARNING_OBJECT (demux,
|
||||
"Failed to find a segment that is available "
|
||||
"at this point in time for stream %d.", stream->index);
|
||||
seg_idx = 0;
|
||||
}
|
||||
GST_INFO_OBJECT (demux,
|
||||
"Segment index corresponding to current time for stream "
|
||||
"%d is %d.", stream->index, seg_idx);
|
||||
gst_mpd_client_set_segment_index (active_stream, seg_idx);
|
||||
}
|
||||
|
||||
gst_date_time_unref (now);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (demux,
|
||||
"Seeking to first segment for on-demand stream ");
|
||||
|
||||
/* start playing from the first segment */
|
||||
gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
|
||||
}
|
||||
|
||||
/* Send duration message */
|
||||
if (!gst_mpd_client_is_live (demux->client)) {
|
||||
|
|
|
@ -137,6 +137,10 @@ static gboolean gst_mpd_client_add_media_segment (GstActiveStream * stream,
|
|||
static const gchar *gst_mpdparser_mimetype_to_caps (const gchar * mimeType);
|
||||
static GstClockTime gst_mpd_client_get_segment_duration (GstMpdClient * client,
|
||||
GstActiveStream * stream);
|
||||
static GstDateTime *gst_mpd_client_get_availability_start_time (GstMpdClient *
|
||||
client);
|
||||
static gint64 gst_mpd_client_calculate_time_difference (const GstDateTime * t1,
|
||||
const GstDateTime * t2);
|
||||
|
||||
/* Adaptation Set */
|
||||
static GstAdaptationSetNode
|
||||
|
@ -3498,6 +3502,87 @@ gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gint64
|
||||
gst_mpd_client_calculate_time_difference (const GstDateTime * t1,
|
||||
const GstDateTime * t2)
|
||||
{
|
||||
GDateTime *gdt1, *gdt2;
|
||||
GTimeSpan diff;
|
||||
|
||||
g_assert (t1 != NULL && t2 != NULL);
|
||||
gdt1 = gst_date_time_to_g_date_time ((GstDateTime *) t1);
|
||||
gdt2 = gst_date_time_to_g_date_time ((GstDateTime *) t2);
|
||||
diff = g_date_time_difference (gdt2, gdt1);
|
||||
g_date_time_unref (gdt1);
|
||||
g_date_time_unref (gdt2);
|
||||
return diff * GST_USECOND;
|
||||
}
|
||||
|
||||
GstDateTime *
|
||||
gst_mpd_client_add_time_difference (GstDateTime * t1, gint64 usecs)
|
||||
{
|
||||
GDateTime *gdt;
|
||||
GDateTime *gdt2;
|
||||
GstDateTime *rv;
|
||||
|
||||
g_assert (t1 != NULL);
|
||||
gdt = gst_date_time_to_g_date_time (t1);
|
||||
g_assert (gdt != NULL);
|
||||
gdt2 = g_date_time_add (gdt, usecs);
|
||||
g_assert (gdt2 != NULL);
|
||||
g_date_time_unref (gdt);
|
||||
rv = gst_date_time_new_from_g_date_time (gdt2);
|
||||
|
||||
/* Don't g_date_time_unref(gdt2) because gst_date_time_new_from_g_date_time takes
|
||||
* ownership of the GDateTime pointer.
|
||||
*/
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
gint
|
||||
gst_mpd_client_get_segment_index_at_time (GstMpdClient * client,
|
||||
GstActiveStream * stream, const GstDateTime * time)
|
||||
{
|
||||
GstClockTime seg_duration;
|
||||
gint64 diff;
|
||||
GstDateTime *avail_start =
|
||||
gst_mpd_client_get_availability_start_time (client);
|
||||
GstStreamPeriod *stream_period = gst_mpdparser_get_stream_period (client);
|
||||
|
||||
if (avail_start == NULL)
|
||||
return -1;
|
||||
|
||||
if (stream_period && stream_period->period) {
|
||||
/* intentionally not unreffing avail_start */
|
||||
avail_start = gst_mpd_client_add_time_difference (avail_start,
|
||||
stream_period->period->start * 1000);
|
||||
}
|
||||
diff = gst_mpd_client_calculate_time_difference (avail_start, time);
|
||||
if (diff < 0)
|
||||
return -2;
|
||||
if (diff > gst_mpd_client_get_media_presentation_duration (client))
|
||||
return -3;
|
||||
|
||||
/* TODO: Assumes all fragments are roughly the same duration */
|
||||
seg_duration = gst_mpd_client_get_next_fragment_duration (client, stream);
|
||||
g_assert (seg_duration > 0);
|
||||
return diff / seg_duration;
|
||||
}
|
||||
|
||||
GstDateTime *
|
||||
gst_mpd_client_get_availability_start_time (GstMpdClient * client)
|
||||
{
|
||||
GstDateTime *t;
|
||||
|
||||
g_return_val_if_fail (client != NULL, NULL);
|
||||
|
||||
GST_MPD_CLIENT_LOCK (client);
|
||||
t = client->mpd_node->availabilityStartTime;
|
||||
GST_MPD_CLIENT_UNLOCK (client);
|
||||
return t;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client,
|
||||
guint stream_idx, GstClockTime * ts)
|
||||
|
@ -3790,13 +3875,11 @@ gst_mpd_client_get_current_position (GstMpdClient * client)
|
|||
}
|
||||
|
||||
GstClockTime
|
||||
gst_mpd_client_get_next_fragment_duration (GstMpdClient * client)
|
||||
gst_mpd_client_get_next_fragment_duration (GstMpdClient * client,
|
||||
GstActiveStream * stream)
|
||||
{
|
||||
GstActiveStream *stream;
|
||||
GstMediaSegment *media_segment;
|
||||
|
||||
GST_DEBUG ("Stream index: %i", client->stream_idx);
|
||||
stream = g_list_nth_data (client->active_streams, client->stream_idx);
|
||||
g_return_val_if_fail (stream != NULL, 0);
|
||||
|
||||
media_segment =
|
||||
|
|
|
@ -486,7 +486,7 @@ gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client);
|
|||
gboolean gst_mpd_client_setup_streaming (GstMpdClient *client, GstStreamMimeType mimeType, const gchar* lang);
|
||||
gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation);
|
||||
GstClockTime gst_mpd_client_get_current_position (GstMpdClient *client);
|
||||
GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client);
|
||||
GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream);
|
||||
GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client);
|
||||
gboolean gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
|
||||
gboolean gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
|
||||
|
@ -495,6 +495,8 @@ gboolean gst_mpd_client_get_next_header (GstMpdClient *client, gchar **uri, guin
|
|||
gboolean gst_mpd_client_get_next_header_index (GstMpdClient *client, gchar **uri, guint stream_idx, gint64 * range_start, gint64 * range_end);
|
||||
gboolean gst_mpd_client_is_live (GstMpdClient * client);
|
||||
gboolean gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream, GstClockTime ts);
|
||||
GstDateTime *gst_mpd_client_add_time_difference (GstDateTime * t1, gint64 usecs);
|
||||
gint gst_mpd_client_get_segment_index_at_time (GstMpdClient *client, GstActiveStream * stream, const GstDateTime *time);
|
||||
|
||||
/* Period selection */
|
||||
gboolean gst_mpd_client_set_period_index (GstMpdClient *client, guint period_idx);
|
||||
|
|
Loading…
Reference in a new issue