diff --git a/subprojects/gst-plugins-bad/ext/hls/gsthlsdemux.c b/subprojects/gst-plugins-bad/ext/hls/gsthlsdemux.c index 8cf6c2acc6..305406e476 100644 --- a/subprojects/gst-plugins-bad/ext/hls/gsthlsdemux.c +++ b/subprojects/gst-plugins-bad/ext/hls/gsthlsdemux.c @@ -1166,6 +1166,13 @@ gst_hls_demux_data_received (GstAdaptiveDemux * demux, buffer = tmp_buffer; } + if (hlsdemux->prog_dt) { + gst_adaptive_demux_stream_set_tags (stream, + gst_tag_list_new (GST_TAG_DATE_TIME, hlsdemux->prog_dt, NULL)); + gst_date_time_unref (hlsdemux->prog_dt); + hlsdemux->prog_dt = NULL; + } + return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE); } @@ -1247,7 +1254,9 @@ gst_hls_demux_update_fragment_info (GstAdaptiveDemuxStream * stream) m3u8 = gst_hls_demux_stream_get_m3u8 (hlsdemux_stream); forward = (stream->demux->segment.rate > 0); - file = gst_m3u8_get_next_fragment (m3u8, forward, &sequence_pos, &discont); + file = + gst_m3u8_get_next_fragment (m3u8, forward, &sequence_pos, + &hlsdemux->prog_dt, &discont); if (file == NULL) { GST_INFO_OBJECT (hlsdemux, "This playlist doesn't contain more fragments"); @@ -1359,6 +1368,12 @@ gst_hls_demux_reset (GstAdaptiveDemux * ademux) GST_DEBUG_OBJECT (demux, "Streams aware : %d", demux->streams_aware); gst_hls_demux_clear_all_pending_data (demux); + + if (demux->prog_dt) { + gst_date_time_unref (demux->prog_dt); + demux->prog_dt = NULL; + } + GST_M3U8_CLIENT_UNLOCK (hlsdemux->client); } diff --git a/subprojects/gst-plugins-bad/ext/hls/gsthlsdemux.h b/subprojects/gst-plugins-bad/ext/hls/gsthlsdemux.h index 98d6099cbf..846026eac3 100644 --- a/subprojects/gst-plugins-bad/ext/hls/gsthlsdemux.h +++ b/subprojects/gst-plugins-bad/ext/hls/gsthlsdemux.h @@ -141,6 +141,8 @@ struct _GstHLSDemux GHashTable *keys; GMutex keys_lock; + GstDateTime *prog_dt; + /* FIXME: check locking, protected automatically by manifest_lock already? */ /* The master playlist with the available variant streams */ GstHLSMasterPlaylist *master; diff --git a/subprojects/gst-plugins-bad/ext/hls/m3u8.c b/subprojects/gst-plugins-bad/ext/hls/m3u8.c index d20e352c3f..4f3595e5eb 100644 --- a/subprojects/gst-plugins-bad/ext/hls/m3u8.c +++ b/subprojects/gst-plugins-bad/ext/hls/m3u8.c @@ -32,7 +32,8 @@ #define GST_CAT_DEFAULT hls_debug static GstM3U8MediaFile *gst_m3u8_media_file_new (gchar * uri, - gchar * title, GstClockTime duration, guint sequence); + gchar * title, GstClockTime duration, guint sequence, + GstDateTime * program_dt); static void gst_m3u8_init_file_unref (GstM3U8InitFile * self); static gchar *uri_join (const gchar * uri, const gchar * path); @@ -116,7 +117,7 @@ gst_m3u8_unref (GstM3U8 * self) static GstM3U8MediaFile * gst_m3u8_media_file_new (gchar * uri, gchar * title, GstClockTime duration, - guint sequence) + guint sequence, GstDateTime * program_dt) { GstM3U8MediaFile *file; @@ -126,6 +127,7 @@ gst_m3u8_media_file_new (gchar * uri, gchar * title, GstClockTime duration, file->duration = duration; file->sequence = sequence; file->ref_count = 1; + file->program_dt = program_dt; return file; } @@ -150,6 +152,8 @@ gst_m3u8_media_file_unref (GstM3U8MediaFile * self) g_free (self->title); g_free (self->uri); g_free (self->key); + if (self->program_dt) + gst_date_time_unref (self->program_dt); g_free (self); } } @@ -483,6 +487,7 @@ gboolean gst_m3u8_update (GstM3U8 * self, gchar * data) { gint val; + GstDateTime *program_dt = NULL; GstClockTime duration; gchar *title, *end; gboolean discontinuity = FALSE; @@ -558,7 +563,10 @@ gst_m3u8_update (GstM3U8 * self, gchar * data) data = uri_join (self->base_uri ? self->base_uri : self->uri, data); if (data != NULL) { GstM3U8MediaFile *file; - file = gst_m3u8_media_file_new (data, title, duration, mediasequence++); + file = + gst_m3u8_media_file_new (data, title, duration, + mediasequence++, program_dt); + program_dt = NULL; /* set encryption params */ file->key = current_key ? g_strdup (current_key) : NULL; @@ -647,8 +655,12 @@ gst_m3u8_update (GstM3U8 * self, gchar * data) self->discont_sequence++; discontinuity = TRUE; } else if (g_str_has_prefix (data_ext_x, "PROGRAM-DATE-TIME:")) { - /* */ - GST_DEBUG ("FIXME parse date"); + if (program_dt) + gst_date_time_unref (program_dt); + program_dt = gst_date_time_new_from_iso8601_string (data + 25); + if (!program_dt) { + GST_WARNING ("Could not parse program date/time"); + } } else if (g_str_has_prefix (data_ext_x, "ALLOW-CACHE:")) { self->allowcache = g_ascii_strcasecmp (data + 19, "YES") == 0; } else if (g_str_has_prefix (data_ext_x, "KEY:")) { @@ -767,6 +779,11 @@ gst_m3u8_update (GstM3U8 * self, gchar * data) g_free (current_key); current_key = NULL; + if (program_dt) { + gst_date_time_unref (program_dt); + program_dt = NULL; + } + self->files = g_list_reverse (self->files); if (last_init_file) @@ -919,7 +936,8 @@ m3u8_find_next_fragment (GstM3U8 * m3u8, gboolean forward) GstM3U8MediaFile * gst_m3u8_get_next_fragment (GstM3U8 * m3u8, gboolean forward, - GstClockTime * sequence_position, gboolean * discont) + GstClockTime * sequence_position, GstDateTime ** program_dt, + gboolean * discont) { GstM3U8MediaFile *file = NULL; @@ -945,6 +963,11 @@ gst_m3u8_get_next_fragment (GstM3U8 * m3u8, gboolean forward, if (sequence_position) *sequence_position = m3u8->sequence_position; + + if (program_dt) + *program_dt = + file->program_dt ? gst_date_time_ref (file->program_dt) : NULL; + if (discont) *discont = file->discont || (m3u8->sequence != file->sequence); diff --git a/subprojects/gst-plugins-bad/ext/hls/m3u8.h b/subprojects/gst-plugins-bad/ext/hls/m3u8.h index aa511360d1..4a8d926673 100644 --- a/subprojects/gst-plugins-bad/ext/hls/m3u8.h +++ b/subprojects/gst-plugins-bad/ext/hls/m3u8.h @@ -99,6 +99,7 @@ struct _GstM3U8MediaFile gchar *key; guint8 iv[16]; gint64 offset, size; + GstDateTime *program_dt; /* program date time */ gint ref_count; /* ATOMIC */ GstM3U8InitFile *init_file; /* Media Initialization (hold ref) */ }; @@ -127,6 +128,7 @@ void gst_m3u8_set_uri (GstM3U8 * m3u8, GstM3U8MediaFile * gst_m3u8_get_next_fragment (GstM3U8 * m3u8, gboolean forward, GstClockTime * sequence_position, + GstDateTime ** program_dt, gboolean * discont); gboolean gst_m3u8_has_next_fragment (GstM3U8 * m3u8, diff --git a/subprojects/gst-plugins-bad/tests/check/elements/hlsdemux_m3u8.c b/subprojects/gst-plugins-bad/tests/check/elements/hlsdemux_m3u8.c index a418fe9f12..beb492b9ac 100644 --- a/subprojects/gst-plugins-bad/tests/check/elements/hlsdemux_m3u8.c +++ b/subprojects/gst-plugins-bad/tests/check/elements/hlsdemux_m3u8.c @@ -572,7 +572,7 @@ GST_START_TEST (test_live_playlist_rotated) ret = gst_m3u8_update (pl, g_strdup (LIVE_ROTATED_PLAYLIST)); assert_equals_int (ret, TRUE); - file = gst_m3u8_get_next_fragment (pl, TRUE, NULL, NULL); + file = gst_m3u8_get_next_fragment (pl, TRUE, NULL, NULL, NULL); fail_unless (file != NULL); gst_m3u8_media_file_unref (file); @@ -805,7 +805,7 @@ GST_START_TEST (test_get_next_fragment) pl = master->default_variant->m3u8; /* Check the next fragment */ - mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, &discontinuous); + mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, NULL, &discontinuous); fail_unless (mf != NULL); assert_equals_int (discontinuous, FALSE); assert_equals_string (mf->uri, "http://media.example.com/all.ts"); @@ -818,7 +818,7 @@ GST_START_TEST (test_get_next_fragment) gst_m3u8_advance_fragment (pl, TRUE); /* Check next media segments */ - mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, &discontinuous); + mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, NULL, &discontinuous); fail_unless (mf != NULL); assert_equals_int (discontinuous, FALSE); assert_equals_string (mf->uri, "http://media.example.com/all.ts"); @@ -831,7 +831,7 @@ GST_START_TEST (test_get_next_fragment) gst_m3u8_advance_fragment (pl, TRUE); /* Check next media segments */ - mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, &discontinuous); + mf = gst_m3u8_get_next_fragment (pl, TRUE, ×tamp, NULL, &discontinuous); assert_equals_int (discontinuous, FALSE); assert_equals_string (mf->uri, "http://media.example.com/all.ts"); assert_equals_uint64 (timestamp, 20 * GST_SECOND);