From 2d24aef0831e6ea0c7b27a98f56a5dd5abdcf6bf Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 15 Jun 2006 15:58:09 +0000 Subject: [PATCH] gst/qtdemux/qtdemux.c: Combine return values from src pad pushes. Original commit message from CVS: * gst/qtdemux/qtdemux.c: (gst_qtdemux_perform_seek), (gst_qtdemux_combine_flows), (gst_qtdemux_loop_state_movie), (gst_qtdemux_loop), (gst_qtdemux_chain), (qtdemux_parse_trak): Combine return values from src pad pushes. --- gst/qtdemux/qtdemux.c | 122 +++++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 38 deletions(-) diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c index a7d2c30fcf..15530608ae 100644 --- a/gst/qtdemux/qtdemux.c +++ b/gst/qtdemux/qtdemux.c @@ -145,6 +145,9 @@ struct _QtDemuxStream guint32 sample_index; guint64 time_position; /* in gst time */ + /* last GstFlowReturn */ + GstFlowReturn last_ret; + /* quicktime segments */ guint32 n_segments; QtDemuxSegment *segments; @@ -631,6 +634,8 @@ gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str, * fact, none of the segments could contain a keyframe. We take a * practical approach: seek to the previous keyframe in the segment, * if there is none, seek to the beginning of the segment. + * + * Called with STREAM_LOCK */ static gboolean gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment) @@ -713,6 +718,7 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment) stream->time_position = desired_offset; stream->sample_index = 0; stream->segment_index = -1; + stream->last_ret = GST_FLOW_OK; } segment->last_stop = desired_offset; segment->time = desired_offset; @@ -1229,6 +1235,40 @@ next_segment: } } +static GstFlowReturn +gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream, + GstFlowReturn ret) +{ + gint i; + + /* store the value */ + stream->last_ret = ret; + + /* if it's success we can return the value right away */ + if (GST_FLOW_IS_SUCCESS (ret)) + goto done; + + /* any other error that is not-linked can be returned right + * away */ + if (ret != GST_FLOW_NOT_LINKED) + goto done; + + /* only return NOT_LINKED if all other pads returned NOT_LINKED */ + for (i = 0; i < demux->n_streams; i++) { + QtDemuxStream *ostream = demux->streams[i]; + + ret = ostream->last_ret; + /* some other return value (must be SUCCESS but we can return + * other values as well) */ + if (ret != GST_FLOW_NOT_LINKED) + goto done; + } + /* if we get here, all other pads were unlinked and we return + * NOT_LINKED then */ +done: + return ret; +} + static GstFlowReturn gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux) { @@ -1315,6 +1355,8 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux) gst_buffer_set_caps (buf, stream->caps); ret = gst_pad_push (stream->pad, buf); + /* combine flows */ + ret = gst_qtdemux_combine_flows (qtdemux, stream, ret); next: gst_qtdemux_advance_sample (qtdemux, stream); @@ -1357,44 +1399,9 @@ gst_qtdemux_loop (GstPad * pad) goto invalid_state; } - /* if all is fine, continue */ - if (G_LIKELY (ret == GST_FLOW_OK)) - goto done; - - /* we don't care about unlinked pads */ - if (ret == GST_FLOW_NOT_LINKED) - goto done; - - /* other errors make us stop */ - GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", gst_flow_get_name (ret)); - - qtdemux->segment_running = FALSE; - gst_pad_pause_task (pad); - - /* fatal errors need special actions */ - if (GST_FLOW_IS_FATAL (ret)) { - /* check EOS */ - if (ret == GST_FLOW_UNEXPECTED) { - if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) { - gint64 stop; - - if ((stop = qtdemux->segment.stop) == -1) - stop = qtdemux->segment.duration; - - GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment"); - gst_element_post_message (GST_ELEMENT_CAST (qtdemux), - gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux), - GST_FORMAT_TIME, stop)); - } else { - GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment"); - gst_qtdemux_push_event (qtdemux, gst_event_new_eos ()); - } - } else { - gst_qtdemux_push_event (qtdemux, gst_event_new_eos ()); - GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED, - (NULL), ("streaming stopped, reason %s", gst_flow_get_name (ret))); - } - } + /* if something went wrong, pause */ + if (ret != GST_FLOW_OK) + goto pause; done: gst_object_unref (qtdemux); @@ -1410,6 +1417,41 @@ invalid_state: gst_qtdemux_push_event (qtdemux, gst_event_new_eos ()); goto done; } +pause: + { + const gchar *reason = gst_flow_get_name (ret); + + GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason); + + qtdemux->segment_running = FALSE; + gst_pad_pause_task (pad); + + /* fatal errors need special actions */ + if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { + /* check EOS */ + if (ret == GST_FLOW_UNEXPECTED) { + if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) { + gint64 stop; + + if ((stop = qtdemux->segment.stop) == -1) + stop = qtdemux->segment.duration; + + GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment"); + gst_element_post_message (GST_ELEMENT_CAST (qtdemux), + gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux), + GST_FORMAT_TIME, stop)); + } else { + GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment"); + gst_qtdemux_push_event (qtdemux, gst_event_new_eos ()); + } + } else { + gst_qtdemux_push_event (qtdemux, gst_event_new_eos ()); + GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED, + (NULL), ("streaming stopped, reason %s", reason)); + } + } + goto done; + } } /* @@ -1653,6 +1695,9 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf) gst_buffer_set_caps (outbuf, stream->caps); ret = gst_pad_push (stream->pad, outbuf); + /* combine flows */ + ret = gst_qtdemux_combine_flows (demux, stream, ret); + stream->sample_index++; /* update current offset and figure out size of next buffer */ @@ -2977,6 +3022,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) stream->segment_index = -1; stream->time_position = 0; stream->sample_index = 0; + stream->last_ret = GST_FLOW_OK; stream->timescale = QTDEMUX_GUINT32_GET (mdhd->data + 20); stream->duration = QTDEMUX_GUINT32_GET (mdhd->data + 24);