From fd92f8d6a29595274abc425f574430ecc891894e Mon Sep 17 00:00:00 2001 From: Gil Pedersen Date: Tue, 28 Feb 2012 16:40:31 +0100 Subject: [PATCH] hlsdemux: add floating point segment duration support --- gst/hls/gsthlsdemux.c | 10 +++----- gst/hls/m3u8.c | 58 +++++++++++++++++++++++++++++++++---------- gst/hls/m3u8.h | 4 +-- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/gst/hls/gsthlsdemux.c b/gst/hls/gsthlsdemux.c index afafacaf04..900f25fc1b 100644 --- a/gst/hls/gsthlsdemux.c +++ b/gst/hls/gsthlsdemux.c @@ -341,9 +341,8 @@ gst_hls_demux_src_event (GstPad * pad, GstEvent * event) GstSeekType start_type, stop_type; gint64 start, stop; GList *walk; - gint current_pos; + GstClockTime current_pos, target_pos; gint current_sequence; - gint target_second; GstM3U8MediaFile *file; GST_INFO_OBJECT (demux, "Received GST_EVENT_SEEK"); @@ -367,14 +366,13 @@ gst_hls_demux_src_event (GstPad * pad, GstEvent * event) file = GST_M3U8_MEDIA_FILE (demux->client->current->files->data); current_sequence = file->sequence; current_pos = 0; - target_second = start / GST_SECOND; - GST_DEBUG_OBJECT (demux, "Target seek to %d", target_second); + target_pos = (GstClockTime) start; for (walk = demux->client->current->files; walk; walk = walk->next) { file = walk->data; current_sequence = file->sequence; - if (current_pos <= target_second - && target_second < current_pos + file->duration) { + if (current_pos <= target_pos + && target_pos < current_pos + file->duration) { break; } current_pos += file->duration; diff --git a/gst/hls/m3u8.c b/gst/hls/m3u8.c index c27f159b59..eecb467e2c 100644 --- a/gst/hls/m3u8.c +++ b/gst/hls/m3u8.c @@ -20,6 +20,7 @@ */ #include +#include #include #include @@ -34,7 +35,7 @@ static void gst_m3u8_free (GstM3U8 * m3u8); static gboolean gst_m3u8_update (GstM3U8 * m3u8, gchar * data, gboolean * updated); static GstM3U8MediaFile *gst_m3u8_media_file_new (gchar * uri, - gchar * title, gint duration, guint sequence); + gchar * title, GstClockTime duration, guint sequence); static void gst_m3u8_media_file_free (GstM3U8MediaFile * self); static GstM3U8 * @@ -77,7 +78,7 @@ gst_m3u8_free (GstM3U8 * self) } static GstM3U8MediaFile * -gst_m3u8_media_file_new (gchar * uri, gchar * title, gint duration, +gst_m3u8_media_file_new (gchar * uri, gchar * title, GstClockTime duration, guint sequence) { GstM3U8MediaFile *file; @@ -131,6 +132,36 @@ int_from_string (gchar * ptr, gchar ** endptr, gint * val) return end != ptr; } +static gboolean +double_from_string (gchar * ptr, gchar ** endptr, gdouble * val) +{ + gchar *end; + gdouble ret; + + g_return_val_if_fail (ptr != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + errno = 0; + ret = strtod (ptr, &end); + if ((errno == ERANGE && (ret == HUGE_VAL || ret == -HUGE_VAL)) + || (errno != 0 && ret == 0)) { + GST_WARNING ("%s", g_strerror (errno)); + return FALSE; + } + + if (!isfinite (ret)) { + GST_WARNING ("%s", g_strerror (ERANGE)); + return FALSE; + } + + if (endptr) + *endptr = end; + + *val = (gint) ret; + + return end != ptr; +} + static gboolean parse_attributes (gchar ** ptr, gchar ** a, gchar ** v) { @@ -186,7 +217,8 @@ gst_m3u8_compare_playlist_by_bitrate (gconstpointer a, gconstpointer b) static gboolean gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) { - gint val, duration; + gint val; + GstClockTime duration; gchar *title, *end; // gboolean discontinuity; GstM3U8 *list; @@ -222,7 +254,7 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) } list = NULL; - duration = -1; + duration = 0; title = NULL; data += 7; while (TRUE) { @@ -233,7 +265,7 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) if (data[0] != '#') { gchar *r; - if (duration < 0 && list == NULL) { + if (duration <= 0 && list == NULL) { GST_LOG ("%s: got line without EXTINF or EXTSTREAMINF, dropping", data); goto next_line; } @@ -277,7 +309,7 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) file = gst_m3u8_media_file_new (data, title, duration, self->mediasequence++); - duration = -1; + duration = 0; title = NULL; self->files = g_list_append (self->files, file); } @@ -321,7 +353,7 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) } } else if (g_str_has_prefix (data, "#EXT-X-TARGETDURATION:")) { if (int_from_string (data + 22, &data, &val)) - self->targetduration = val; + self->targetduration = val * GST_SECOND; } else if (g_str_has_prefix (data, "#EXT-X-MEDIA-SEQUENCE:")) { if (int_from_string (data + 22, &data, &val)) self->mediasequence = val; @@ -334,11 +366,12 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) g_free (self->allowcache); self->allowcache = g_strdup (data + 19); } else if (g_str_has_prefix (data, "#EXTINF:")) { - if (!int_from_string (data + 8, &data, &val)) { + gdouble fval; + if (!double_from_string (data + 8, &data, &fval)) { GST_WARNING ("Can't read EXTINF duration"); goto next_line; } - duration = val; + duration = fval * (gdouble) GST_SECOND; if (duration > self->targetduration) GST_WARNING ("EXTINF duration > TARGETDURATION"); if (!data || *data != ',') @@ -485,7 +518,6 @@ gst_m3u8_client_get_current_position (GstM3U8Client * client, break; *timestamp += GST_M3U8_MEDIA_FILE (walk->data)->duration; } - *timestamp *= GST_SECOND; } gboolean @@ -517,7 +549,7 @@ gst_m3u8_client_get_next_fragment (GstM3U8Client * client, client->sequence = file->sequence + 1; *uri = file->uri; - *duration = file->duration * GST_SECOND; + *duration = file->duration; GST_M3U8_CLIENT_UNLOCK (client); return TRUE; @@ -545,7 +577,7 @@ gst_m3u8_client_get_duration (GstM3U8Client * client) g_list_foreach (client->current->files, (GFunc) _sum_duration, &duration); GST_M3U8_CLIENT_UNLOCK (client); - return duration * GST_SECOND; + return duration; } GstClockTime @@ -558,7 +590,7 @@ gst_m3u8_client_get_target_duration (GstM3U8Client * client) GST_M3U8_CLIENT_LOCK (client); duration = client->current->targetduration; GST_M3U8_CLIENT_UNLOCK (client); - return duration * GST_SECOND; + return duration; } const gchar * diff --git a/gst/hls/m3u8.h b/gst/hls/m3u8.h index a428a67a48..a03828716a 100644 --- a/gst/hls/m3u8.h +++ b/gst/hls/m3u8.h @@ -41,7 +41,7 @@ struct _GstM3U8 gboolean endlist; /* if ENDLIST has been reached */ gint version; /* last EXT-X-VERSION */ - gint targetduration; /* last EXT-X-TARGETDURATION */ + GstClockTime targetduration; /* last EXT-X-TARGETDURATION */ gchar *allowcache; /* last EXT-X-ALLOWCACHE */ gint bandwidth; @@ -62,7 +62,7 @@ struct _GstM3U8 struct _GstM3U8MediaFile { gchar *title; - gint duration; + GstClockTime duration; gchar *uri; guint sequence; /* the sequence nb of this file */ };