diff --git a/ext/hls/gsthlsdemux.c b/ext/hls/gsthlsdemux.c index 3e21f5932b..2b8880bd8f 100644 --- a/ext/hls/gsthlsdemux.c +++ b/ext/hls/gsthlsdemux.c @@ -105,7 +105,7 @@ static gboolean gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update, GError ** err); static void gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose); static gboolean gst_hls_demux_set_location (GstHLSDemux * demux, - const gchar * uri); + const gchar * uri, const gchar * base_uri); static gchar *gst_hls_src_buf_to_utf8_playlist (GstBuffer * buf); static gboolean gst_hls_demux_change_playlist (GstHLSDemux * demux, @@ -572,7 +572,6 @@ gst_hls_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) GstHLSDemux *demux; GstQuery *query; gboolean ret; - gchar *uri; demux = GST_HLS_DEMUX (parent); @@ -592,18 +591,19 @@ gst_hls_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) ret = gst_pad_peer_query (demux->sinkpad, query); if (ret) { gboolean permanent; + gchar *uri, *redirect_uri; - gst_query_parse_uri_redirection (query, &uri); + gst_query_parse_uri (query, &uri); + gst_query_parse_uri_redirection (query, &redirect_uri); gst_query_parse_uri_redirection_permanent (query, &permanent); - /* Only use the redirect target for permanent redirects */ - if (!permanent || uri == NULL) { - g_free (uri); - gst_query_parse_uri (query, &uri); + if (permanent) { + gst_hls_demux_set_location (demux, redirect_uri, redirect_uri); + } else { + gst_hls_demux_set_location (demux, uri, redirect_uri); } - - gst_hls_demux_set_location (demux, uri); g_free (uri); + g_free (redirect_uri); } gst_query_unref (query); @@ -1291,7 +1291,7 @@ gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose) } if (!dispose) { - demux->client = gst_m3u8_client_new (""); + demux->client = gst_m3u8_client_new ("", NULL); } gst_segment_init (&demux->segment, GST_FORMAT_TIME); @@ -1324,12 +1324,14 @@ gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose) } static gboolean -gst_hls_demux_set_location (GstHLSDemux * demux, const gchar * uri) +gst_hls_demux_set_location (GstHLSDemux * demux, const gchar * uri, + const gchar * base_uri) { if (demux->client) gst_m3u8_client_free (demux->client); - demux->client = gst_m3u8_client_new (uri); - GST_INFO_OBJECT (demux, "Changed location: %s", uri); + demux->client = gst_m3u8_client_new (uri, base_uri); + GST_INFO_OBJECT (demux, "Changed location: %s (base uri: %s)", uri, + GST_STR_NULL (base_uri)); return TRUE; } @@ -1489,7 +1491,6 @@ gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update, GstBuffer *buf; gchar *playlist; gboolean updated = FALSE; - const gchar *uri = gst_m3u8_client_get_current_uri (demux->client); download = @@ -1499,6 +1500,19 @@ gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update, if (download == NULL) return FALSE; + /* Set the base URI of the playlist to the redirect target if any */ + GST_M3U8_CLIENT_LOCK (demux->client); + g_free (demux->client->current->uri); + g_free (demux->client->current->base_uri); + if (download->redirect_permanent) { + demux->client->current->uri = g_strdup (download->redirect_uri); + demux->client->current->base_uri = NULL; + } else { + demux->client->current->uri = g_strdup (download->uri); + demux->client->current->base_uri = g_strdup (download->redirect_uri); + } + GST_M3U8_CLIENT_UNLOCK (demux->client); + buf = gst_fragment_get_buffer (download); playlist = gst_hls_src_buf_to_utf8_playlist (buf); g_object_unref (download); diff --git a/ext/hls/m3u8.c b/ext/hls/m3u8.c index d129723e7a..618d52d1b0 100644 --- a/ext/hls/m3u8.c +++ b/ext/hls/m3u8.c @@ -50,13 +50,15 @@ gst_m3u8_new (void) } static void -gst_m3u8_set_uri (GstM3U8 * self, gchar * uri) +gst_m3u8_set_uri (GstM3U8 * self, gchar * uri, gchar * base_uri) { g_return_if_fail (self != NULL); - if (self->uri) - g_free (self->uri); + g_free (self->uri); self->uri = uri; + + g_free (self->base_uri); + self->base_uri = base_uri; } static void @@ -65,6 +67,7 @@ gst_m3u8_free (GstM3U8 * self) g_return_if_fail (self != NULL); g_free (self->uri); + g_free (self->base_uri); g_free (self->codecs); g_free (self->key); @@ -322,7 +325,7 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) goto next_line; } - data = uri_join (self->uri, data); + data = uri_join (self->base_uri ? self->base_uri : self->uri, data); if (data == NULL) goto next_line; @@ -333,7 +336,7 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) gst_m3u8_free (list); g_free (data); } else { - gst_m3u8_set_uri (list, data); + gst_m3u8_set_uri (list, data, NULL); self->lists = g_list_append (self->lists, list); } list = NULL; @@ -427,12 +430,12 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) if (uri[0] == '"') uri += 1; - uri = uri_join (self->uri, uri); + uri = uri_join (self->base_uri ? self->base_uri : self->uri, uri); g_free (urip); if (uri == NULL) continue; - gst_m3u8_set_uri (new_list, uri); + gst_m3u8_set_uri (new_list, uri, NULL); } } @@ -484,7 +487,8 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) if (key[0] == '"') key += 1; - self->key = uri_join (self->uri, key); + self->key = + uri_join (self->base_uri ? self->base_uri : self->uri, key); g_free (keyp); } else if (g_str_equal (a, "IV")) { gchar *ivp = v; @@ -591,7 +595,7 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) } GstM3U8Client * -gst_m3u8_client_new (const gchar * uri) +gst_m3u8_client_new (const gchar * uri, const gchar * base_uri) { GstM3U8Client *client; @@ -604,7 +608,7 @@ gst_m3u8_client_new (const gchar * uri) client->sequence_position = 0; client->update_failed_count = 0; g_mutex_init (&client->lock); - gst_m3u8_set_uri (client->main, g_strdup (uri)); + gst_m3u8_set_uri (client->main, g_strdup (uri), g_strdup (base_uri)); return client; } diff --git a/ext/hls/m3u8.h b/ext/hls/m3u8.h index 096287a604..d49287a062 100644 --- a/ext/hls/m3u8.h +++ b/ext/hls/m3u8.h @@ -37,7 +37,9 @@ typedef struct _GstM3U8Client GstM3U8Client; struct _GstM3U8 { - gchar *uri; + gchar *uri; /* actually downloaded URI */ + gchar *base_uri; /* URI to use as base for resolving relative URIs. + * This will be different to uri in case of redirects */ gboolean endlist; /* if ENDLIST has been reached */ gint version; /* last EXT-X-VERSION */ @@ -85,7 +87,7 @@ struct _GstM3U8Client }; -GstM3U8Client *gst_m3u8_client_new (const gchar * uri); +GstM3U8Client *gst_m3u8_client_new (const gchar * uri, const gchar * base_uri); void gst_m3u8_client_free (GstM3U8Client * client); gboolean gst_m3u8_client_update (GstM3U8Client * client, gchar * data); void gst_m3u8_client_set_current (GstM3U8Client * client, GstM3U8 * m3u8);