mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +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_schedule (GstHLSDemux * demux);
|
||||||
static gboolean gst_hls_demux_switch_playlist (GstHLSDemux * demux);
|
static gboolean gst_hls_demux_switch_playlist (GstHLSDemux * demux);
|
||||||
static gboolean gst_hls_demux_get_next_fragment (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,
|
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 void gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose);
|
||||||
static gboolean gst_hls_demux_set_location (GstHLSDemux * demux,
|
static gboolean gst_hls_demux_set_location (GstHLSDemux * demux,
|
||||||
const gchar * uri);
|
const gchar * uri);
|
||||||
|
@ -883,8 +883,10 @@ gst_hls_demux_updates_loop (GstHLSDemux * demux)
|
||||||
|
|
||||||
/* fetch the next fragment */
|
/* fetch the next fragment */
|
||||||
if (g_queue_get_length (demux->queue) < demux->fragments_cache) {
|
if (g_queue_get_length (demux->queue) < demux->fragments_cache) {
|
||||||
|
GError *err = NULL;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "queue not full, get next fragment");
|
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) {
|
if (demux->cancelled) {
|
||||||
goto quit;
|
goto quit;
|
||||||
} else if (!demux->end_of_playlist) {
|
} 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");
|
GST_WARNING_OBJECT (demux, "Could not fetch the next fragment");
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
|
gst_element_post_message (GST_ELEMENT_CAST (demux),
|
||||||
("Could not fetch the next fragment"), (NULL));
|
gst_message_new_error (GST_OBJECT_CAST (demux), err,
|
||||||
|
"Could not fetch the next fragment"));
|
||||||
|
g_error_free (err);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -926,7 +930,9 @@ gst_hls_demux_updates_loop (GstHLSDemux * demux)
|
||||||
|
|
||||||
/* update the playlist for live sources */
|
/* update the playlist for live sources */
|
||||||
if (gst_m3u8_client_is_live (demux->client)) {
|
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)
|
if (demux->cancelled)
|
||||||
goto quit;
|
goto quit;
|
||||||
demux->client->update_failed_count++;
|
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");
|
GST_WARNING_OBJECT (demux, "Could not update the playlist");
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
|
gst_element_post_message (GST_ELEMENT_CAST (demux),
|
||||||
("Could not update the playlist"), (NULL));
|
gst_message_new_error (GST_OBJECT_CAST (demux), err,
|
||||||
|
"Could not update the playlist"));
|
||||||
|
g_error_free (err);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -980,6 +988,7 @@ gst_hls_demux_cache_fragments (GstHLSDemux * demux)
|
||||||
* and update it */
|
* and update it */
|
||||||
if (gst_m3u8_client_has_variant_playlist (demux->client)) {
|
if (gst_m3u8_client_has_variant_playlist (demux->client)) {
|
||||||
GstM3U8 *child = NULL;
|
GstM3U8 *child = NULL;
|
||||||
|
GError *err = NULL;
|
||||||
|
|
||||||
if (demux->connection_speed == 0) {
|
if (demux->connection_speed == 0) {
|
||||||
|
|
||||||
|
@ -994,9 +1003,11 @@ gst_hls_demux_cache_fragments (GstHLSDemux * demux)
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_m3u8_client_set_current (demux->client, child);
|
gst_m3u8_client_set_current (demux->client, child);
|
||||||
if (!gst_hls_demux_update_playlist (demux, FALSE)) {
|
if (!gst_hls_demux_update_playlist (demux, FALSE, &err)) {
|
||||||
GST_ERROR_OBJECT (demux, "Could not fetch the child playlist %s",
|
gst_element_post_message (GST_ELEMENT_CAST (demux),
|
||||||
child->uri);
|
gst_message_new_error (GST_OBJECT_CAST (demux), err,
|
||||||
|
"Could not fetch the child playlist"));
|
||||||
|
g_error_free (err);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1013,15 +1024,21 @@ gst_hls_demux_cache_fragments (GstHLSDemux * demux)
|
||||||
|
|
||||||
/* Cache the first fragments */
|
/* Cache the first fragments */
|
||||||
for (i = 0; i < demux->fragments_cache; i++) {
|
for (i = 0; i < demux->fragments_cache; i++) {
|
||||||
|
GError *err = NULL;
|
||||||
|
|
||||||
gst_element_post_message (GST_ELEMENT (demux),
|
gst_element_post_message (GST_ELEMENT (demux),
|
||||||
gst_message_new_buffering (GST_OBJECT (demux),
|
gst_message_new_buffering (GST_OBJECT (demux),
|
||||||
100 * i / demux->fragments_cache));
|
100 * i / demux->fragments_cache));
|
||||||
demux->next_update = g_get_monotonic_time ();
|
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)
|
if (demux->end_of_playlist)
|
||||||
break;
|
break;
|
||||||
if (!demux->cancelled)
|
if (!demux->cancelled) {
|
||||||
GST_ERROR_OBJECT (demux, "Error caching the first fragments");
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* make sure we stop caching fragments if something cancelled it */
|
/* make sure we stop caching fragments if something cancelled it */
|
||||||
|
@ -1068,7 +1085,8 @@ map_error:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update)
|
gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update,
|
||||||
|
GError ** err)
|
||||||
{
|
{
|
||||||
GstFragment *download;
|
GstFragment *download;
|
||||||
GstBuffer *buf;
|
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);
|
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)
|
if (download == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -1087,11 +1104,19 @@ gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update)
|
||||||
g_object_unref (download);
|
g_object_unref (download);
|
||||||
|
|
||||||
if (playlist == NULL) {
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
updated = gst_m3u8_client_update (demux->client, playlist);
|
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
|
/* If it's a live source, do not let the sequence number go beyond
|
||||||
* three fragments before the end of the list */
|
* 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"
|
GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
|
||||||
" to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
|
" 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;
|
GstStructure *s;
|
||||||
|
|
||||||
s = gst_structure_new ("playlist",
|
s = gst_structure_new ("playlist",
|
||||||
|
@ -1299,7 +1324,8 @@ out:
|
||||||
|
|
||||||
static GstFragment *
|
static GstFragment *
|
||||||
gst_hls_demux_decrypt_fragment (GstHLSDemux * demux,
|
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;
|
GstFragment *key_fragment, *ret = NULL;
|
||||||
GstBuffer *key_buffer, *encrypted_buffer, *decrypted_buffer;
|
GstBuffer *key_buffer, *encrypted_buffer, *decrypted_buffer;
|
||||||
|
@ -1307,7 +1333,7 @@ gst_hls_demux_decrypt_fragment (GstHLSDemux * demux,
|
||||||
gsize unpadded_size;
|
gsize unpadded_size;
|
||||||
|
|
||||||
GST_INFO_OBJECT (demux, "Fetching key %s", key);
|
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)
|
if (key_fragment == NULL)
|
||||||
goto key_failed;
|
goto key_failed;
|
||||||
|
|
||||||
|
@ -1348,6 +1374,8 @@ key_failed:
|
||||||
|
|
||||||
decrypt_error:
|
decrypt_error:
|
||||||
GST_ERROR_OBJECT (demux, "Failed to decrypt fragment");
|
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 (key_buffer);
|
||||||
gst_buffer_unref (encrypted_buffer);
|
gst_buffer_unref (encrypted_buffer);
|
||||||
|
@ -1362,7 +1390,8 @@ decrypt_error:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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;
|
GstFragment *download;
|
||||||
const gchar *next_fragment_uri;
|
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);
|
GST_INFO_OBJECT (demux, "Fetching next fragment %s", next_fragment_uri);
|
||||||
|
|
||||||
download = gst_uri_downloader_fetch_uri (demux->downloader,
|
download = gst_uri_downloader_fetch_uri (demux->downloader,
|
||||||
next_fragment_uri, NULL);
|
next_fragment_uri, err);
|
||||||
|
|
||||||
if (download && key)
|
|
||||||
download = gst_hls_demux_decrypt_fragment (demux, download, key, iv);
|
|
||||||
|
|
||||||
if (download == NULL)
|
if (download == NULL)
|
||||||
goto error;
|
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);
|
buf = gst_fragment_get_buffer (download);
|
||||||
|
|
||||||
GST_BUFFER_DURATION (buf) = duration;
|
GST_BUFFER_DURATION (buf) = duration;
|
||||||
|
|
Loading…
Reference in a new issue