diff --git a/ChangeLog b/ChangeLog index a0986a1cf4..ad0bde1511 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2005-02-16 Wim Taymans + + * docs/design/part-TODO.txt: + * gst/elements/gstfakesink.c: (gst_fakesink_event), + (gst_fakesink_chain): + * gst/elements/gstfakesink.h: + * gst/elements/gstfakesrc.c: (gst_fakesrc_loop), + (gst_fakesrc_activate): + * gst/elements/gstfilesrc.c: (gst_filesrc_getrange), + (gst_filesrc_open_file), (gst_filesrc_loop), + (gst_filesrc_activate), (gst_filesrc_change_state), + (filesrc_find_peek), (gst_filesrc_type_find): + * gst/gstcaps.c: (gst_caps_copy_nth): + * gst/gstcaps.h: + * gst/gstelement.c: (gst_element_add_pad), + (gst_element_remove_pad), (iterate_pad), + (gst_element_get_state_func), (gst_element_commit_state), + (gst_element_set_state), (gst_element_pads_activate), + (gst_element_change_state), (gst_element_dispose): + * gst/gstutils.c: (gst_element_finish_preroll): + * gst/gstutils.h: + * tools/gst-launch.c: (check_intr): + add gst_caps_copy_nth as a more general replacement for + copy_1. + Slightly change the finish_preroll helper function to + include pad flush/active. + Small cleanups in fakesrc. + Add STREAM_LOCK in filesrc. + 2005-02-11 Thomas Vander Stichele * docs/gst/Makefile.am: diff --git a/docs/design/part-TODO.txt b/docs/design/part-TODO.txt index 14b4a58e99..5f52b45e2d 100644 --- a/docs/design/part-TODO.txt +++ b/docs/design/part-TODO.txt @@ -10,3 +10,7 @@ - only emit EOS in PLAYING. - implement state change order on get<->loop-get<->loop elements. + +- unlinking pads in the PAUSED state needs to make sure the stream thread is not + executing code. Can this be done with a flush to unlock all downstream chain + functions? diff --git a/gst/elements/gstfakesink.c b/gst/elements/gstfakesink.c index 08ec8dfbba..84dce23b1a 100644 --- a/gst/elements/gstfakesink.c +++ b/gst/elements/gstfakesink.c @@ -330,8 +330,7 @@ gst_fakesink_event (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: { - gst_element_finish_preroll (GST_ELEMENT (fakesink), - GST_STREAM_GET_LOCK (pad)); + gst_element_finish_preroll (GST_ELEMENT (fakesink), pad); gst_element_post_message (GST_ELEMENT (fakesink), gst_message_new_eos (GST_OBJECT (fakesink))); break; @@ -367,9 +366,7 @@ gst_fakesink_chain (GstPad * pad, GstBuffer * buffer) /* grab streaming lock to synchronize with event method */ GST_STREAM_LOCK (pad); - result = - gst_element_finish_preroll (GST_ELEMENT (fakesink), - GST_STREAM_GET_LOCK (pad)); + result = gst_element_finish_preroll (GST_ELEMENT (fakesink), pad); if (result != GST_FLOW_OK) goto exit; diff --git a/gst/elements/gstfakesink.h b/gst/elements/gstfakesink.h index f41ad61d75..4f3ab00e49 100644 --- a/gst/elements/gstfakesink.h +++ b/gst/elements/gstfakesink.h @@ -56,6 +56,8 @@ typedef struct _GstFakeSinkClass GstFakeSinkClass; struct _GstFakeSink { GstElement element; + GstPad *sinkpad; + gboolean silent; gboolean dump; gboolean sync; diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c index 748f917385..7d5d40e060 100644 --- a/gst/elements/gstfakesrc.c +++ b/gst/elements/gstfakesrc.c @@ -777,6 +777,7 @@ gst_fakesrc_loop (GstPad * pad) GstFakeSrc *src; GstBuffer *buf; GstClockTime time; + GstFlowReturn ret; src = GST_FAKESRC (GST_OBJECT_PARENT (pad)); @@ -791,15 +792,13 @@ gst_fakesrc_loop (GstPad * pad) //gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE)); } else { gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); - gst_task_pause (src->task); - goto done; + goto pause; } } if (src->rt_num_buffers == 0) { gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); - gst_task_pause (src->task); - goto done; + goto pause; } else { if (src->rt_num_buffers > 0) src->rt_num_buffers--; @@ -808,8 +807,7 @@ gst_fakesrc_loop (GstPad * pad) if (src->eos) { GST_INFO ("fakesrc is setting eos on pad"); gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); - gst_task_pause (src->task); - goto done; + goto pause; } buf = gst_fakesrc_create_buffer (src); @@ -848,10 +846,18 @@ gst_fakesrc_loop (GstPad * pad) src->bytes_sent += GST_BUFFER_SIZE (buf); - gst_pad_push (pad, buf); + ret = gst_pad_push (pad, buf); + if (ret != GST_FLOW_OK) { + goto pause; + } -done: GST_STREAM_UNLOCK (pad); + return; + +pause: + gst_task_pause (src->task); + GST_STREAM_UNLOCK (pad); + return; } static gboolean diff --git a/gst/elements/gstfilesrc.c b/gst/elements/gstfilesrc.c index 3371b3c58e..ce9354f5c0 100644 --- a/gst/elements/gstfilesrc.c +++ b/gst/elements/gstfilesrc.c @@ -907,15 +907,19 @@ gst_filesrc_loop (GstPad * pad) filesrc = GST_FILESRC (GST_PAD_PARENT (pad)); + GST_STREAM_LOCK (pad); + result = gst_filesrc_get (pad, &buffer); if (result != GST_FLOW_OK) { gst_task_pause (GST_RPAD_TASK (pad)); - return; + goto done; } result = gst_pad_push (pad, buffer); if (result != GST_FLOW_OK) { gst_task_pause (GST_RPAD_TASK (pad)); } +done: + GST_STREAM_UNLOCK (pad); } @@ -978,9 +982,9 @@ gst_filesrc_change_state (GstElement * element) return GST_STATE_FAILURE; } src->need_discont = 2; - break; case GST_STATE_PAUSED_TO_PLAYING: + gst_task_start (GST_RPAD_TASK (src->srcpad)); break; } @@ -988,6 +992,7 @@ gst_filesrc_change_state (GstElement * element) switch (GST_STATE_TRANSITION (element)) { case GST_STATE_PLAYING_TO_PAUSED: + gst_task_start (GST_RPAD_TASK (src->srcpad)); break; case GST_STATE_PAUSED_TO_READY: if (GST_FLAG_IS_SET (element, GST_FILESRC_OPEN)) diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 8eb79590cd..be51493b7d 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -530,6 +530,35 @@ gst_caps_get_structure (const GstCaps * caps, int index) return g_ptr_array_index (caps->structs, index); } +/** + * gst_caps_copy_nth: + * @caps: the @GstCaps to copy + * @nth: the nth structure to copy + * + * Creates a new @GstCaps and appends a copy of the nth structure + * contained in @caps. + * + * Returns: the new @GstCaps + */ +GstCaps * +gst_caps_copy_nth (const GstCaps * caps, gint nth) +{ + GstCaps *newcaps; + GstStructure *structure; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + newcaps = gst_caps_new_empty (); + newcaps->flags = caps->flags; + + if (caps->structs->len > nth) { + structure = gst_caps_get_structure (caps, nth); + gst_caps_append_structure (newcaps, gst_structure_copy (structure)); + } + + return newcaps; +} + /** * gst_caps_set_simple: * @caps: the @GstCaps to set diff --git a/gst/gstcaps.h b/gst/gstcaps.h index 5bf0aee575..0a75fbdeae 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -106,6 +106,7 @@ void gst_caps_append_structure (GstCaps int gst_caps_get_size (const GstCaps *caps); GstStructure * gst_caps_get_structure (const GstCaps *caps, int index); +GstCaps * gst_caps_copy_nth (const GstCaps * caps, gint nth); void gst_caps_set_simple (GstCaps *caps, char *field, ...); void gst_caps_set_simple_valist (GstCaps *caps, diff --git a/gst/gstelement.c b/gst/gstelement.c index 3b381b03ef..7c06e57dc0 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -1731,6 +1731,7 @@ gst_element_commit_state (GstElement * element) GST_STATE (element) = pending; GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING; + GST_STATE_ERROR (element) = FALSE; g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE], 0, old_state, pending); diff --git a/gst/gstutils.c b/gst/gstutils.c index bd67ffeb59..c3029bff59 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -388,7 +388,7 @@ gst_element_abort_preroll (GstElement * element) /* call with stream lock held */ GstFlowReturn -gst_element_finish_preroll (GstElement * element, GMutex * streamlock) +gst_element_finish_preroll (GstElement * element, GstPad * pad) { GstFlowReturn result = GST_FLOW_OK; @@ -403,19 +403,20 @@ gst_element_finish_preroll (GstElement * element, GMutex * streamlock) GST_CAT_DEBUG (GST_CAT_STATES, "element %s wants to finish preroll", GST_ELEMENT_NAME (element)); - /* FIXME, release streaming lock? */ - if (streamlock) - g_mutex_unlock (streamlock); - /* here we wait for the next state change */ while (GST_STATE (element) == GST_STATE_PAUSED) { + if (GST_RPAD_IS_FLUSHING (pad) || !GST_RPAD_IS_ACTIVE (pad)) { + GST_CAT_DEBUG (GST_CAT_STATES, "pad is flushing"); + result = GST_FLOW_UNEXPECTED; + goto done; + } + GST_CAT_DEBUG (GST_CAT_STATES, "waiting for next state change"); GST_STATE_WAIT (element); + GST_CAT_DEBUG (GST_CAT_STATES, " got state change"); } - if (streamlock) - g_mutex_lock (streamlock); /* check if we got playing */ if (GST_STATE (element) != GST_STATE_PLAYING) { /* not playing, we can't accept the buffer */ @@ -423,6 +424,7 @@ gst_element_finish_preroll (GstElement * element, GMutex * streamlock) } GST_CAT_DEBUG (GST_CAT_STATES, "done preroll"); } +done: GST_STATE_UNLOCK (element); return result; diff --git a/gst/gstutils.h b/gst/gstutils.h index bf995c3945..c0a6242a59 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -230,7 +230,7 @@ void gst_object_default_error (GstObject * source, /* element functions */ GstFlowReturn gst_element_abort_preroll (GstElement *element); -GstFlowReturn gst_element_finish_preroll (GstElement *element, GMutex *streamlock); +GstFlowReturn gst_element_finish_preroll (GstElement *element, GstPad *pad); GstPad* gst_element_get_compatible_pad (GstElement *element, GstPad *pad); GstPad* gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c index 08ec8dfbba..84dce23b1a 100644 --- a/plugins/elements/gstfakesink.c +++ b/plugins/elements/gstfakesink.c @@ -330,8 +330,7 @@ gst_fakesink_event (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: { - gst_element_finish_preroll (GST_ELEMENT (fakesink), - GST_STREAM_GET_LOCK (pad)); + gst_element_finish_preroll (GST_ELEMENT (fakesink), pad); gst_element_post_message (GST_ELEMENT (fakesink), gst_message_new_eos (GST_OBJECT (fakesink))); break; @@ -367,9 +366,7 @@ gst_fakesink_chain (GstPad * pad, GstBuffer * buffer) /* grab streaming lock to synchronize with event method */ GST_STREAM_LOCK (pad); - result = - gst_element_finish_preroll (GST_ELEMENT (fakesink), - GST_STREAM_GET_LOCK (pad)); + result = gst_element_finish_preroll (GST_ELEMENT (fakesink), pad); if (result != GST_FLOW_OK) goto exit; diff --git a/plugins/elements/gstfakesink.h b/plugins/elements/gstfakesink.h index f41ad61d75..4f3ab00e49 100644 --- a/plugins/elements/gstfakesink.h +++ b/plugins/elements/gstfakesink.h @@ -56,6 +56,8 @@ typedef struct _GstFakeSinkClass GstFakeSinkClass; struct _GstFakeSink { GstElement element; + GstPad *sinkpad; + gboolean silent; gboolean dump; gboolean sync; diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index 748f917385..7d5d40e060 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -777,6 +777,7 @@ gst_fakesrc_loop (GstPad * pad) GstFakeSrc *src; GstBuffer *buf; GstClockTime time; + GstFlowReturn ret; src = GST_FAKESRC (GST_OBJECT_PARENT (pad)); @@ -791,15 +792,13 @@ gst_fakesrc_loop (GstPad * pad) //gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE)); } else { gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); - gst_task_pause (src->task); - goto done; + goto pause; } } if (src->rt_num_buffers == 0) { gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); - gst_task_pause (src->task); - goto done; + goto pause; } else { if (src->rt_num_buffers > 0) src->rt_num_buffers--; @@ -808,8 +807,7 @@ gst_fakesrc_loop (GstPad * pad) if (src->eos) { GST_INFO ("fakesrc is setting eos on pad"); gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); - gst_task_pause (src->task); - goto done; + goto pause; } buf = gst_fakesrc_create_buffer (src); @@ -848,10 +846,18 @@ gst_fakesrc_loop (GstPad * pad) src->bytes_sent += GST_BUFFER_SIZE (buf); - gst_pad_push (pad, buf); + ret = gst_pad_push (pad, buf); + if (ret != GST_FLOW_OK) { + goto pause; + } -done: GST_STREAM_UNLOCK (pad); + return; + +pause: + gst_task_pause (src->task); + GST_STREAM_UNLOCK (pad); + return; } static gboolean diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c index 3371b3c58e..ce9354f5c0 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -907,15 +907,19 @@ gst_filesrc_loop (GstPad * pad) filesrc = GST_FILESRC (GST_PAD_PARENT (pad)); + GST_STREAM_LOCK (pad); + result = gst_filesrc_get (pad, &buffer); if (result != GST_FLOW_OK) { gst_task_pause (GST_RPAD_TASK (pad)); - return; + goto done; } result = gst_pad_push (pad, buffer); if (result != GST_FLOW_OK) { gst_task_pause (GST_RPAD_TASK (pad)); } +done: + GST_STREAM_UNLOCK (pad); } @@ -978,9 +982,9 @@ gst_filesrc_change_state (GstElement * element) return GST_STATE_FAILURE; } src->need_discont = 2; - break; case GST_STATE_PAUSED_TO_PLAYING: + gst_task_start (GST_RPAD_TASK (src->srcpad)); break; } @@ -988,6 +992,7 @@ gst_filesrc_change_state (GstElement * element) switch (GST_STATE_TRANSITION (element)) { case GST_STATE_PLAYING_TO_PAUSED: + gst_task_start (GST_RPAD_TASK (src->srcpad)); break; case GST_STATE_PAUSED_TO_READY: if (GST_FLAG_IS_SET (element, GST_FILESRC_OPEN)) diff --git a/tools/gst-launch.c b/tools/gst-launch.c index fca8ffeef7..e89c94d521 100644 --- a/tools/gst-launch.c +++ b/tools/gst-launch.c @@ -279,6 +279,7 @@ check_intr (user_data) } else { g_print ("Pausing pipeline.\n"); gst_element_set_state (pipeline, GST_STATE_PAUSED); + g_print ("Paused pipeline.\n"); g_main_loop_quit (loop); return FALSE; }