mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-01 09:21:03 +00:00
hlsdemux: handle errors from internal source
Set up a message handling function to catch errors from the internal source and store the last return code to identify error situations when returning from a fragment download. Also moves the duration increase to after the download when we know if it was successful or not
This commit is contained in:
parent
f16560c520
commit
4431388cab
2 changed files with 65 additions and 8 deletions
|
@ -83,6 +83,8 @@ static void gst_hls_demux_dispose (GObject * obj);
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
gst_hls_demux_change_state (GstElement * element, GstStateChange transition);
|
gst_hls_demux_change_state (GstElement * element, GstStateChange transition);
|
||||||
|
|
||||||
|
static void gst_hls_demux_handle_message (GstBin * bin, GstMessage * msg);
|
||||||
|
|
||||||
/* GstHLSDemux */
|
/* GstHLSDemux */
|
||||||
static GstFlowReturn gst_hls_demux_chain (GstPad * pad, GstObject * parent,
|
static GstFlowReturn gst_hls_demux_chain (GstPad * pad, GstObject * parent,
|
||||||
GstBuffer * buf);
|
GstBuffer * buf);
|
||||||
|
@ -157,9 +159,11 @@ gst_hls_demux_class_init (GstHLSDemuxClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
GstElementClass *element_class;
|
GstElementClass *element_class;
|
||||||
|
GstBinClass *bin_class;
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
gobject_class = (GObjectClass *) klass;
|
||||||
element_class = (GstElementClass *) klass;
|
element_class = (GstElementClass *) klass;
|
||||||
|
bin_class = (GstBinClass *) klass;
|
||||||
|
|
||||||
gobject_class->set_property = gst_hls_demux_set_property;
|
gobject_class->set_property = gst_hls_demux_set_property;
|
||||||
gobject_class->get_property = gst_hls_demux_get_property;
|
gobject_class->get_property = gst_hls_demux_get_property;
|
||||||
|
@ -200,6 +204,8 @@ gst_hls_demux_class_init (GstHLSDemuxClass * klass)
|
||||||
"Marc-Andre Lureau <marcandre.lureau@gmail.com>\n"
|
"Marc-Andre Lureau <marcandre.lureau@gmail.com>\n"
|
||||||
"Andoni Morales Alastruey <ylatuya@gmail.com>");
|
"Andoni Morales Alastruey <ylatuya@gmail.com>");
|
||||||
|
|
||||||
|
bin_class->handle_message = gst_hls_demux_handle_message;
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_hls_demux_debug, "hlsdemux", 0,
|
GST_DEBUG_CATEGORY_INIT (gst_hls_demux_debug, "hlsdemux", 0,
|
||||||
"hlsdemux element");
|
"hlsdemux element");
|
||||||
}
|
}
|
||||||
|
@ -327,6 +333,41 @@ gst_hls_demux_change_state (GstElement * element, GstStateChange transition)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_hls_demux_handle_message (GstBin * bin, GstMessage * msg)
|
||||||
|
{
|
||||||
|
GstHLSDemux *demux = GST_HLS_DEMUX_CAST (bin);
|
||||||
|
|
||||||
|
switch (GST_MESSAGE_TYPE (msg)) {
|
||||||
|
case GST_MESSAGE_ERROR:{
|
||||||
|
GError *err = NULL;
|
||||||
|
gchar *debug = NULL;
|
||||||
|
|
||||||
|
gst_message_parse_error (msg, &err, &debug);
|
||||||
|
|
||||||
|
GST_WARNING_OBJECT (demux, "Source posted error: %d:%d %s (%s)",
|
||||||
|
err->domain, err->code, err->message, debug);
|
||||||
|
|
||||||
|
/* error, but ask to retry */
|
||||||
|
g_mutex_lock (&demux->fragment_download_lock);
|
||||||
|
demux->last_ret = GST_FLOW_CUSTOM_ERROR;
|
||||||
|
g_cond_signal (&demux->fragment_download_cond);
|
||||||
|
g_mutex_unlock (&demux->fragment_download_lock);
|
||||||
|
|
||||||
|
g_error_free (err);
|
||||||
|
g_free (debug);
|
||||||
|
gst_message_unref (msg);
|
||||||
|
msg = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg)
|
||||||
|
GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_hls_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
gst_hls_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
{
|
{
|
||||||
|
@ -790,6 +831,7 @@ _src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
("decryption failed %s", err->message));
|
("decryption failed %s", err->message));
|
||||||
g_error_free (err);
|
g_error_free (err);
|
||||||
|
|
||||||
|
demux->last_ret = GST_FLOW_ERROR;
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,6 +866,7 @@ _src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND,
|
GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND,
|
||||||
("Could not determine type of stream"), (NULL));
|
("Could not determine type of stream"), (NULL));
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
|
demux->last_ret = GST_FLOW_NOT_NEGOTIATED;
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,10 +891,6 @@ _src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
demux->starting_fragment = FALSE;
|
demux->starting_fragment = FALSE;
|
||||||
|
|
||||||
demux->segment.position = GST_BUFFER_TIMESTAMP (buffer);
|
demux->segment.position = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
#if 0
|
|
||||||
if (demux->segment.rate > 0)
|
|
||||||
demux->segment.position += GST_BUFFER_DURATION (buf);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (demux->need_segment) {
|
if (demux->need_segment) {
|
||||||
/* And send a newsegment */
|
/* And send a newsegment */
|
||||||
|
@ -882,12 +921,14 @@ _src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* avoid having the source handle the same error again */
|
/* avoid having the source handle the same error again */
|
||||||
|
demux->last_ret = ret;
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
key_failed:
|
key_failed:
|
||||||
/* TODO ERROR here */
|
/* TODO ERROR here */
|
||||||
|
demux->last_ret = GST_FLOW_ERROR;
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -924,9 +965,11 @@ _src_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
demux->pending_buffer = NULL;
|
demux->pending_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demux->segment.rate > 0)
|
GST_DEBUG_OBJECT (demux, "Fragment download finished");
|
||||||
demux->segment.position += demux->current_duration;
|
|
||||||
|
g_mutex_lock (&demux->fragment_download_lock);
|
||||||
g_cond_signal (&demux->fragment_download_cond);
|
g_cond_signal (&demux->fragment_download_cond);
|
||||||
|
g_mutex_unlock (&demux->fragment_download_lock);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1849,9 +1892,20 @@ gst_hls_demux_get_next_fragment (GstHLSDemux * demux,
|
||||||
|
|
||||||
/* wait for the fragment to be completely downloaded */
|
/* wait for the fragment to be completely downloaded */
|
||||||
g_cond_wait (&demux->fragment_download_cond, &demux->fragment_download_lock);
|
g_cond_wait (&demux->fragment_download_cond, &demux->fragment_download_lock);
|
||||||
|
|
||||||
gst_element_set_state (demux->src, GST_STATE_READY);
|
|
||||||
g_mutex_unlock (&demux->fragment_download_lock);
|
g_mutex_unlock (&demux->fragment_download_lock);
|
||||||
|
|
||||||
|
if (demux->last_ret != GST_FLOW_OK) {
|
||||||
|
gst_element_set_state (demux->src, GST_STATE_NULL);
|
||||||
|
*err = g_error_new (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
|
||||||
|
"Failed to download fragment");
|
||||||
|
} else {
|
||||||
|
gst_element_set_state (demux->src, GST_STATE_READY);
|
||||||
|
if (demux->segment.rate > 0)
|
||||||
|
demux->segment.position += demux->current_duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (demux->last_ret != GST_FLOW_OK)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ G_BEGIN_DECLS
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_HLS_DEMUX))
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_HLS_DEMUX))
|
||||||
#define GST_HLS_DEMUX_GET_CLASS(obj) \
|
#define GST_HLS_DEMUX_GET_CLASS(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_HLS_DEMUX,GstHLSDemuxClass))
|
(G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_HLS_DEMUX,GstHLSDemuxClass))
|
||||||
|
#define GST_HLS_DEMUX_CAST(obj) \
|
||||||
|
((GstHLSDemux *)obj)
|
||||||
typedef struct _GstHLSDemux GstHLSDemux;
|
typedef struct _GstHLSDemux GstHLSDemux;
|
||||||
typedef struct _GstHLSDemuxClass GstHLSDemuxClass;
|
typedef struct _GstHLSDemuxClass GstHLSDemuxClass;
|
||||||
|
|
||||||
|
@ -121,6 +123,7 @@ struct _GstHLSDemux
|
||||||
gint64 download_start_time;
|
gint64 download_start_time;
|
||||||
gint64 download_total_time;
|
gint64 download_total_time;
|
||||||
gint64 download_total_bytes;
|
gint64 download_total_bytes;
|
||||||
|
GstFlowReturn last_ret;
|
||||||
|
|
||||||
/* decryption tooling */
|
/* decryption tooling */
|
||||||
#ifdef HAVE_NETTLE
|
#ifdef HAVE_NETTLE
|
||||||
|
|
Loading…
Reference in a new issue