ext/ogg/gstoggdemux.c: Better error recovery, ignore unconnected pads and non-fatal errors.

Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_pad_dispose),
(gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page),
(gst_ogg_demux_activate_chain), (gst_ogg_demux_loop):
Better error recovery, ignore unconnected pads and
non-fatal errors.
This commit is contained in:
Wim Taymans 2005-07-14 18:13:08 +00:00
parent 63cd64c514
commit 6e5b22e005
2 changed files with 80 additions and 46 deletions

View file

@ -1,3 +1,11 @@
2005-07-14 Wim Taymans <wim@fluendo.com>
* ext/ogg/gstoggdemux.c: (gst_ogg_pad_dispose),
(gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page),
(gst_ogg_demux_activate_chain), (gst_ogg_demux_loop):
Better error recovery, ignore unconnected pads and
non-fatal errors.
2005-07-14 Thomas Vander Stichele <thomas at apestaart dot org> 2005-07-14 Thomas Vander Stichele <thomas at apestaart dot org>
* docs/libs/tmpl/gstaudio.sgml: * docs/libs/tmpl/gstaudio.sgml:

View file

@ -268,8 +268,6 @@ gst_ogg_pad_dispose (GObject * object)
{ {
GstOggPad *pad = GST_OGG_PAD (object); GstOggPad *pad = GST_OGG_PAD (object);
gst_element_set_state (pad->element, GST_STATE_NULL);
gst_object_replace ((GstObject **) (&pad->elem_pad), NULL); gst_object_replace ((GstObject **) (&pad->elem_pad), NULL);
gst_object_replace ((GstObject **) (&pad->element), NULL); gst_object_replace ((GstObject **) (&pad->element), NULL);
gst_object_replace ((GstObject **) (&pad->elem_out), NULL); gst_object_replace ((GstObject **) (&pad->elem_out), NULL);
@ -662,6 +660,9 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
ret = GST_FLOW_OK; ret = GST_FLOW_OK;
} }
} }
/* we just ignore unlinked pads */
if (ret == GST_FLOW_NOT_LINKED)
ret = GST_FLOW_OK;
} else { } else {
/* initialize our internal decoder with packets */ /* initialize our internal decoder with packets */
if (!pad->elem_pad) if (!pad->elem_pad)
@ -678,6 +679,8 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
GST_BUFFER_OFFSET_END (buf) = packet->granulepos; GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
ret = gst_pad_chain (pad->elem_pad, buf); ret = gst_pad_chain (pad->elem_pad, buf);
if (GST_FLOW_IS_FATAL (ret))
goto decoder_error;
} }
pad->packetno++; pad->packetno++;
@ -687,7 +690,12 @@ no_decoder:
{ {
GST_WARNING_OBJECT (ogg, GST_WARNING_OBJECT (ogg,
"pad %08lx does not have elem_pad, no decoder ?", pad); "pad %08lx does not have elem_pad, no decoder ?", pad);
return GST_FLOW_OK; return GST_FLOW_ERROR;
}
decoder_error:
{
GST_WARNING_OBJECT (ogg, "internal decoder error");
return GST_FLOW_ERROR;
} }
} }
@ -705,13 +713,8 @@ gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page)
ogg = GST_OGG_DEMUX (GST_PAD_PARENT (pad)); ogg = GST_OGG_DEMUX (GST_PAD_PARENT (pad));
if (ogg_stream_pagein (&pad->stream, page) != 0) { if (ogg_stream_pagein (&pad->stream, page) != 0)
GST_WARNING_OBJECT (ogg, goto choked;
"ogg stream choked on page (serial %08lx), resetting stream",
pad->serialno);
gst_ogg_pad_reset (pad);
return GST_FLOW_OK;
}
while (!done) { while (!done) {
ret = ogg_stream_packetout (&pad->stream, &packet); ret = ogg_stream_packetout (&pad->stream, &packet);
@ -726,12 +729,8 @@ gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page)
break; break;
case 1: case 1:
result = gst_ogg_pad_submit_packet (pad, &packet); result = gst_ogg_pad_submit_packet (pad, &packet);
if (result != GST_FLOW_OK) { if (GST_FLOW_IS_FATAL (result))
GST_WARNING_OBJECT (ogg, "could not submit packet, error: %d", goto could_not_submit;
result);
gst_ogg_pad_reset (pad);
done = TRUE;
}
break; break;
default: default:
GST_WARNING_OBJECT (ogg, GST_WARNING_OBJECT (ogg,
@ -742,6 +741,22 @@ gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page)
} }
} }
return result; return result;
choked:
{
GST_WARNING_OBJECT (ogg,
"ogg stream choked on page (serial %08lx), resetting stream",
pad->serialno);
gst_ogg_pad_reset (pad);
/* we continue to recover */
return GST_FLOW_OK;
}
could_not_submit:
{
GST_WARNING_OBJECT (ogg, "could not submit packet, error: %d", result);
gst_ogg_pad_reset (pad);
return result;
}
} }
@ -1156,39 +1171,38 @@ static gboolean
gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain) gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain)
{ {
gint i; gint i;
GstFlowReturn ret; GList *headers;
GstOggPad *pad;
if (chain == ogg->current_chain) if (chain == ogg->current_chain)
return TRUE; return TRUE;
gst_ogg_demux_deactivate_current_chain (ogg); gst_ogg_demux_deactivate_current_chain (ogg);
/* first add the pads */
for (i = 0; i < chain->streams->len; i++) { for (i = 0; i < chain->streams->len; i++) {
GstOggPad *pad;
GList *headers;
pad = g_array_index (chain->streams, GstOggPad *, i); pad = g_array_index (chain->streams, GstOggPad *, i);
gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD (pad)); gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD (pad));
}
gst_element_no_more_pads (GST_ELEMENT (ogg));
ogg->current_chain = chain;
/* then send out the buffers */
for (i = 0; i < chain->streams->len; i++) {
pad = g_array_index (chain->streams, GstOggPad *, i);
for (headers = pad->headers; headers; headers = g_list_next (headers)) { for (headers = pad->headers; headers; headers = g_list_next (headers)) {
GstBuffer *buffer = GST_BUFFER (headers->data); GstBuffer *buffer = GST_BUFFER (headers->data);
ret = gst_pad_push (GST_PAD_CAST (pad), buffer); /* we don't care about the return value here */
if (ret != GST_FLOW_OK) gst_pad_push (GST_PAD_CAST (pad), buffer);
goto flow_error;
} }
/* and free the headers */
g_list_free (pad->headers);
pad->headers = NULL;
} }
gst_element_no_more_pads (GST_ELEMENT (ogg));
ogg->current_chain = chain;
return TRUE; return TRUE;
flow_error:
{
return FALSE;
}
} }
static gboolean static gboolean
@ -1930,40 +1944,52 @@ gst_ogg_demux_loop (GstOggPad * pad)
GST_CHAIN_LOCK (ogg); GST_CHAIN_LOCK (ogg);
got_chains = gst_ogg_demux_find_chains (ogg); got_chains = gst_ogg_demux_find_chains (ogg);
GST_CHAIN_UNLOCK (ogg); GST_CHAIN_UNLOCK (ogg);
if (!got_chains) { if (!got_chains)
GST_LOG_OBJECT (ogg, "could not read chains"); goto chain_read_failed;
goto pause;
}
ogg->need_chains = FALSE; ogg->need_chains = FALSE;
ogg->offset = 0; ogg->offset = 0;
} }
GST_LOG_OBJECT (ogg, "pull data %lld", ogg->offset); GST_LOG_OBJECT (ogg, "pull data %lld", ogg->offset);
if (ogg->offset == ogg->length) { if (ogg->offset == ogg->length) {
ret = GST_FLOW_OK;
gst_ogg_demux_send_eos (ogg); gst_ogg_demux_send_eos (ogg);
goto pause; goto pause;
} }
ret = gst_pad_pull_range (ogg->sinkpad, ogg->offset, CHUNKSIZE, &buffer); ret = gst_pad_pull_range (ogg->sinkpad, ogg->offset, CHUNKSIZE, &buffer);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK)
GST_LOG_OBJECT (ogg, "got unexpected %d", ret);
goto pause; goto pause;
}
ogg->offset += GST_BUFFER_SIZE (buffer); ogg->offset += GST_BUFFER_SIZE (buffer);
ret = gst_ogg_demux_chain (ogg->sinkpad, buffer); ret = gst_ogg_demux_chain (ogg->sinkpad, buffer);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK)
GST_LOG_OBJECT (ogg, "got unexpected %d, pausing", ret);
goto pause; goto pause;
}
return; return;
/* ERRORS */
chain_read_failed:
{
GST_ELEMENT_ERROR (ogg, STREAM, DEMUX,
("could not read chains"), ("could not read chains"));
ret = GST_FLOW_ERROR;
goto pause;
}
pause: pause:
GST_LOG_OBJECT (ogg, "pausing task"); {
GST_LOG_OBJECT (ogg, "pausing task, reason %d", ret);
gst_pad_pause_task (ogg->sinkpad); gst_pad_pause_task (ogg->sinkpad);
if (GST_FLOW_IS_FATAL (ret)) {
gst_ogg_demux_send_eos (ogg);
GST_ELEMENT_ERROR (ogg, STREAM, STOPPED,
("stream stopped, reason %d", ret),
("stream stopped, reason %d", ret));
}
return; return;
} }
}
static void static void
gst_ogg_demux_clear_chains (GstOggDemux * ogg) gst_ogg_demux_clear_chains (GstOggDemux * ogg)