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);
}
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");
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);
}
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;
#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);
static GstM3U8MediaFile *
gst_m3u8_media_file_new (gchar * uri, gchar * title, GstClockTime duration,
- guint sequence)
+ guint sequence, GstDateTime * program_dt)
{
GstM3U8MediaFile *file;
file->duration = duration;
file->sequence = sequence;
file->ref_count = 1;
+ file->program_dt = program_dt;
return file;
}
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);
}
}
gst_m3u8_update (GstM3U8 * self, gchar * data)
{
gint val;
+ GstDateTime *program_dt = NULL;
GstClockTime duration;
gchar *title, *end;
gboolean discontinuity = FALSE;
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;
self->discont_sequence++;
discontinuity = TRUE;
} else if (g_str_has_prefix (data_ext_x, "PROGRAM-DATE-TIME:")) {
- /* <YYYY-MM-DDThh:mm:ssZ> */
- 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:")) {
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)
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;
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);
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) */
};
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,
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);
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");
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");
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);