mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
hlsdemux: Propagate download errors properly and post error messages if they're fatal
This commit is contained in:
parent
3a5abc233d
commit
591598da48
1 changed files with 58 additions and 26 deletions
|
@ -108,9 +108,9 @@ static gboolean gst_hls_demux_cache_fragments (GstHLSDemux * demux);
|
|||
static gboolean gst_hls_demux_schedule (GstHLSDemux * demux);
|
||||
static gboolean gst_hls_demux_switch_playlist (GstHLSDemux * demux);
|
||||
static gboolean gst_hls_demux_get_next_fragment (GstHLSDemux * demux,
|
||||
gboolean caching);
|
||||
gboolean caching, GError ** err);
|
||||
static gboolean gst_hls_demux_update_playlist (GstHLSDemux * demux,
|
||||
gboolean update);
|
||||
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);
|
||||
|
@ -883,8 +883,10 @@ gst_hls_demux_updates_loop (GstHLSDemux * demux)
|
|||
|
||||
/* fetch the next fragment */
|
||||
if (g_queue_get_length (demux->queue) < demux->fragments_cache) {
|
||||
GError *err = NULL;
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "queue not full, get next fragment");
|
||||
if (!gst_hls_demux_get_next_fragment (demux, FALSE)) {
|
||||
if (!gst_hls_demux_get_next_fragment (demux, FALSE, &err)) {
|
||||
if (demux->cancelled) {
|
||||
goto quit;
|
||||
} else if (!demux->end_of_playlist) {
|
||||
|
@ -893,8 +895,10 @@ gst_hls_demux_updates_loop (GstHLSDemux * demux)
|
|||
GST_WARNING_OBJECT (demux, "Could not fetch the next fragment");
|
||||
continue;
|
||||
} else {
|
||||
GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
|
||||
("Could not fetch the next fragment"), (NULL));
|
||||
gst_element_post_message (GST_ELEMENT_CAST (demux),
|
||||
gst_message_new_error (GST_OBJECT_CAST (demux), err,
|
||||
"Could not fetch the next fragment"));
|
||||
g_error_free (err);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -926,7 +930,9 @@ gst_hls_demux_updates_loop (GstHLSDemux * demux)
|
|||
|
||||
/* update the playlist for live sources */
|
||||
if (gst_m3u8_client_is_live (demux->client)) {
|
||||
if (!gst_hls_demux_update_playlist (demux, TRUE)) {
|
||||
GError *err = NULL;
|
||||
|
||||
if (!gst_hls_demux_update_playlist (demux, TRUE, &err)) {
|
||||
if (demux->cancelled)
|
||||
goto quit;
|
||||
demux->client->update_failed_count++;
|
||||
|
@ -934,8 +940,10 @@ gst_hls_demux_updates_loop (GstHLSDemux * demux)
|
|||
GST_WARNING_OBJECT (demux, "Could not update the playlist");
|
||||
continue;
|
||||
} else {
|
||||
GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
|
||||
("Could not update the playlist"), (NULL));
|
||||
gst_element_post_message (GST_ELEMENT_CAST (demux),
|
||||
gst_message_new_error (GST_OBJECT_CAST (demux), err,
|
||||
"Could not update the playlist"));
|
||||
g_error_free (err);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -980,6 +988,7 @@ gst_hls_demux_cache_fragments (GstHLSDemux * demux)
|
|||
* and update it */
|
||||
if (gst_m3u8_client_has_variant_playlist (demux->client)) {
|
||||
GstM3U8 *child = NULL;
|
||||
GError *err = NULL;
|
||||
|
||||
if (demux->connection_speed == 0) {
|
||||
|
||||
|
@ -994,9 +1003,11 @@ gst_hls_demux_cache_fragments (GstHLSDemux * demux)
|
|||
}
|
||||
|
||||
gst_m3u8_client_set_current (demux->client, child);
|
||||
if (!gst_hls_demux_update_playlist (demux, FALSE)) {
|
||||
GST_ERROR_OBJECT (demux, "Could not fetch the child playlist %s",
|
||||
child->uri);
|
||||
if (!gst_hls_demux_update_playlist (demux, FALSE, &err)) {
|
||||
gst_element_post_message (GST_ELEMENT_CAST (demux),
|
||||
gst_message_new_error (GST_OBJECT_CAST (demux), err,
|
||||
"Could not fetch the child playlist"));
|
||||
g_error_free (err);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -1013,15 +1024,21 @@ gst_hls_demux_cache_fragments (GstHLSDemux * demux)
|
|||
|
||||
/* Cache the first fragments */
|
||||
for (i = 0; i < demux->fragments_cache; i++) {
|
||||
GError *err = NULL;
|
||||
|
||||
gst_element_post_message (GST_ELEMENT (demux),
|
||||
gst_message_new_buffering (GST_OBJECT (demux),
|
||||
100 * i / demux->fragments_cache));
|
||||
demux->next_update = g_get_monotonic_time ();
|
||||
if (!gst_hls_demux_get_next_fragment (demux, TRUE)) {
|
||||
if (!gst_hls_demux_get_next_fragment (demux, TRUE, &err)) {
|
||||
if (demux->end_of_playlist)
|
||||
break;
|
||||
if (!demux->cancelled)
|
||||
GST_ERROR_OBJECT (demux, "Error caching the first fragments");
|
||||
if (!demux->cancelled) {
|
||||
gst_element_post_message (GST_ELEMENT_CAST (demux),
|
||||
gst_message_new_error (GST_OBJECT_CAST (demux), err,
|
||||
"Error caching the first fragments"));
|
||||
g_error_free (err);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/* make sure we stop caching fragments if something cancelled it */
|
||||
|
@ -1068,7 +1085,8 @@ map_error:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update)
|
||||
gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update,
|
||||
GError ** err)
|
||||
{
|
||||
GstFragment *download;
|
||||
GstBuffer *buf;
|
||||
|
@ -1077,8 +1095,7 @@ gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update)
|
|||
|
||||
const gchar *uri = gst_m3u8_client_get_current_uri (demux->client);
|
||||
|
||||
download = gst_uri_downloader_fetch_uri (demux->downloader, uri, NULL);
|
||||
|
||||
download = gst_uri_downloader_fetch_uri (demux->downloader, uri, err);
|
||||
if (download == NULL)
|
||||
return FALSE;
|
||||
|
||||
|
@ -1087,11 +1104,19 @@ gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update)
|
|||
g_object_unref (download);
|
||||
|
||||
if (playlist == NULL) {
|
||||
GST_WARNING_OBJECT (demux, "Couldn't not validate playlist encoding");
|
||||
GST_WARNING_OBJECT (demux, "Couldn't validate playlist encoding");
|
||||
g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
|
||||
"Couldn't validate playlist encoding");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
updated = gst_m3u8_client_update (demux->client, playlist);
|
||||
if (!updated) {
|
||||
GST_WARNING_OBJECT (demux, "Couldn't update playlist");
|
||||
g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED,
|
||||
"Couldn't update playlist");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If it's a live source, do not let the sequence number go beyond
|
||||
* three fragments before the end of the list */
|
||||
|
@ -1148,7 +1173,7 @@ retry_failover_protection:
|
|||
GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
|
||||
" to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
|
||||
|
||||
if (gst_hls_demux_update_playlist (demux, FALSE)) {
|
||||
if (gst_hls_demux_update_playlist (demux, FALSE, NULL)) {
|
||||
GstStructure *s;
|
||||
|
||||
s = gst_structure_new ("playlist",
|
||||
|
@ -1299,7 +1324,8 @@ out:
|
|||
|
||||
static GstFragment *
|
||||
gst_hls_demux_decrypt_fragment (GstHLSDemux * demux,
|
||||
GstFragment * encrypted_fragment, const gchar * key, const guint8 * iv)
|
||||
GstFragment * encrypted_fragment, const gchar * key, const guint8 * iv,
|
||||
GError ** err)
|
||||
{
|
||||
GstFragment *key_fragment, *ret = NULL;
|
||||
GstBuffer *key_buffer, *encrypted_buffer, *decrypted_buffer;
|
||||
|
@ -1307,7 +1333,7 @@ gst_hls_demux_decrypt_fragment (GstHLSDemux * demux,
|
|||
gsize unpadded_size;
|
||||
|
||||
GST_INFO_OBJECT (demux, "Fetching key %s", key);
|
||||
key_fragment = gst_uri_downloader_fetch_uri (demux->downloader, key, NULL);
|
||||
key_fragment = gst_uri_downloader_fetch_uri (demux->downloader, key, err);
|
||||
if (key_fragment == NULL)
|
||||
goto key_failed;
|
||||
|
||||
|
@ -1348,6 +1374,8 @@ key_failed:
|
|||
|
||||
decrypt_error:
|
||||
GST_ERROR_OBJECT (demux, "Failed to decrypt fragment");
|
||||
g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_DECRYPT,
|
||||
"Failed to decrypt fragment");
|
||||
|
||||
gst_buffer_unref (key_buffer);
|
||||
gst_buffer_unref (encrypted_buffer);
|
||||
|
@ -1362,7 +1390,8 @@ decrypt_error:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_hls_demux_get_next_fragment (GstHLSDemux * demux, gboolean caching)
|
||||
gst_hls_demux_get_next_fragment (GstHLSDemux * demux, gboolean caching,
|
||||
GError ** err)
|
||||
{
|
||||
GstFragment *download;
|
||||
const gchar *next_fragment_uri;
|
||||
|
@ -1384,14 +1413,17 @@ gst_hls_demux_get_next_fragment (GstHLSDemux * demux, gboolean caching)
|
|||
GST_INFO_OBJECT (demux, "Fetching next fragment %s", next_fragment_uri);
|
||||
|
||||
download = gst_uri_downloader_fetch_uri (demux->downloader,
|
||||
next_fragment_uri, NULL);
|
||||
|
||||
if (download && key)
|
||||
download = gst_hls_demux_decrypt_fragment (demux, download, key, iv);
|
||||
next_fragment_uri, err);
|
||||
|
||||
if (download == NULL)
|
||||
goto error;
|
||||
|
||||
if (key) {
|
||||
download = gst_hls_demux_decrypt_fragment (demux, download, key, iv, err);
|
||||
if (download == NULL)
|
||||
goto error;
|
||||
}
|
||||
|
||||
buf = gst_fragment_get_buffer (download);
|
||||
|
||||
GST_BUFFER_DURATION (buf) = duration;
|
||||
|
|
Loading…
Reference in a new issue