From 484d9a322492b214981526cedb114d79fe367d56 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 11 Feb 2005 15:50:53 +0000 Subject: [PATCH] Added more docs. Original commit message from CVS: * docs/design/part-clocks.txt: * docs/design/part-events.txt: * gst/elements/gstfakesrc.c: (gst_fakesrc_get_event_mask), (gst_fakesrc_event_handler), (gst_fakesrc_loop), (gst_fakesrc_activate): * gst/gstclock.c: (gst_clock_id_ref), (gst_clock_id_unref), (gst_clock_id_compare_func), (gst_clock_id_wait), (gst_clock_id_wait_async), (gst_clock_init), (gst_clock_adjust_unlocked), (gst_clock_get_time): * gst/gstevent.c: (gst_event_new_discontinuous_valist), (gst_event_discont_get_value), (gst_event_new_segment_seek): * gst/gstevent.h: * gst/gstpipeline.c: (gst_pipeline_init), (is_eos), (pipeline_bus_handler), (gst_pipeline_change_state): * gst/gstpipeline.h: * gst/gstsystemclock.c: (gst_system_clock_init), (gst_system_clock_async_thread), (gst_system_clock_id_wait_unlocked), (gst_system_clock_id_wait_async), (gst_system_clock_id_unschedule): * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_event), (gst_dp_event_from_packet): * testsuite/clock/Makefile.am: * testsuite/clock/clock4.c: (gst_clock_debug), (ok_callback), (error_callback), (main): Added more docs. Remove more silly events. Implement periodic clock notifications. Add async testsuite. --- ChangeLog | 31 ++++++++ docs/design/part-clocks.txt | 102 ++++++++++++++++++++++++++ docs/design/part-events.txt | 14 ++-- gst/elements/gstfakesrc.c | 13 +--- gst/gstclock.c | 30 +++++++- gst/gstevent.c | 2 +- gst/gstevent.h | 2 - gst/gstpipeline.c | 22 +++--- gst/gstpipeline.h | 2 +- gst/gstsystemclock.c | 17 ++++- libs/gst/dataprotocol/dataprotocol.c | 25 ------- plugins/elements/gstfakesrc.c | 13 +--- tests/old/testsuite/clock/Makefile.am | 2 +- tests/old/testsuite/clock/clock4.c | 100 +++++++++++++++++++++++++ testsuite/clock/Makefile.am | 2 +- testsuite/clock/clock4.c | 100 +++++++++++++++++++++++++ 16 files changed, 407 insertions(+), 70 deletions(-) create mode 100644 docs/design/part-clocks.txt create mode 100644 tests/old/testsuite/clock/clock4.c create mode 100644 testsuite/clock/clock4.c diff --git a/ChangeLog b/ChangeLog index 1010340652..d6e7f23d4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2005-02-11 Wim Taymans + + * docs/design/part-clocks.txt: + * docs/design/part-events.txt: + * gst/elements/gstfakesrc.c: (gst_fakesrc_get_event_mask), + (gst_fakesrc_event_handler), (gst_fakesrc_loop), + (gst_fakesrc_activate): + * gst/gstclock.c: (gst_clock_id_ref), (gst_clock_id_unref), + (gst_clock_id_compare_func), (gst_clock_id_wait), + (gst_clock_id_wait_async), (gst_clock_init), + (gst_clock_adjust_unlocked), (gst_clock_get_time): + * gst/gstevent.c: (gst_event_new_discontinuous_valist), + (gst_event_discont_get_value), (gst_event_new_segment_seek): + * gst/gstevent.h: + * gst/gstpipeline.c: (gst_pipeline_init), (is_eos), + (pipeline_bus_handler), (gst_pipeline_change_state): + * gst/gstpipeline.h: + * gst/gstsystemclock.c: (gst_system_clock_init), + (gst_system_clock_async_thread), + (gst_system_clock_id_wait_unlocked), + (gst_system_clock_id_wait_async), (gst_system_clock_id_unschedule): + * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_event), + (gst_dp_event_from_packet): + * testsuite/clock/Makefile.am: + * testsuite/clock/clock4.c: (gst_clock_debug), (ok_callback), + (error_callback), (main): + Added more docs. + Remove more silly events. + Implement periodic clock notifications. + Add async testsuite. + 2005-02-11 Andy Wingo * tools/gst-inspect.c (print_field): Change prototype for diff --git a/docs/design/part-clocks.txt b/docs/design/part-clocks.txt new file mode 100644 index 0000000000..0a3c0bc7f1 --- /dev/null +++ b/docs/design/part-clocks.txt @@ -0,0 +1,102 @@ +Clocks +------ + +To synchronize the different elements, the GstPipeline is responsible for +selecting and distributing a global GstClock for all the elements in it. + +This selection happens whenever an element is added or removed from the +pipeline. Whever the clock changes in a pipeline, a message is posted on +the bus signaling the new clock to the application. + +The GstClock returns a monotonically increasing time with the method +_get_time(). Its accuracy and base time depends on the specific clock +implementation but time is always expessed in nanoseconds. Since the +baseline of the clock is undefined, the clock time returned is not +meaningfull in itself, what matters are the deltas between two clock +times. +The time reported by the clock is called the absolute time. + + +Time in GStreamer +----------------- + +The absolute time is used to calculate the stream time. The stream time +is defined as follows: + + - If the pipeline is NULL/READY, the stream time is undefined. + - In PAUSED, the stream time remains at the time when it was last + PAUSED. When the stream is PAUSED for the first time, the stream time + is 0. + - In PLAYING, the stream time is the delta between the absolute time + and the base time. The base time is defined as the absolute time minus + the stream time at the time when the pipeline is set to PLAYING. + - after a seek, the stream time is set to 0 again. + + +Timestamps +---------- + +Timestamps on buffers are always expressed in stream time. This means that +all elements that require synchronizing to the clock need to be aware of +the clock base time in order to know the absolute time of the timestamp. +Converting a timestamp (in stream time) to absolute time is performed using +the following formula: + + AT = BT + ST where: AT = absolute time + BT = base time + ST = stream time + +The pipeline base time is propagated to all the element during the PAUSED +to PLAYING state change. All elements are therefore able to convert the +stream time to the absolute time. It is possible to specify an aditional +delay to the base time to compensate for the delay it takes to perform +the state change. + + +Clock features +-------------- + +The clock supports periodic and single shot clock notifications both +synchronous and asynchronous. + +One first needs to create a GstClockID for the periodic or single shot +notification using _clock_new_single_shot_id() or _clock_new_periodic_id(). + +To perform a blocking wait for the specific time of the GstClockID use the +gst_clock_id_wait(). To receive a callback when the specific time is reached +in the clock use gst_clock_id_wait_async(). Both these calls can be interrupted +with the gst_clock_id_unschedule() call. If the blocking wait is unscheduled +a return value of GST_CLOCK_UNSCHEDULED is returned. + +The async callbacks can happen from any thread, either provided by the +core or from a streaming thread. The application should be prepared for this. + +A GstClockID that has been unscheduled cannot be used again for any wait +operation. + +It is possible to perform a blocking wait on the same ID from multiple +threads. However, registering the same ID for multiple async notifications is +not possible, the callback will only be called once. + +None of the wait operations unref the GstClockID, the application is +responsible for unreffing the ids itself. + +These clock operations do not operate on the stream time, so the callbacks +will also occur when not in PLAYING state as if the clock just keeps on +running. + + +Clock implementations +--------------------- + +The GStreamer core provides a GstSystemClock based on the system time. +Asynchronous callbacks are scheduled from an internal thread. + +Clock implementors are encouraged to subclass this systemclock as it +implements the async notification. + +Subclasses can however override all of the important methods for sync and +async notifications to implement their own callback methods or blocking +wait operations. + + diff --git a/docs/design/part-events.txt b/docs/design/part-events.txt index 210cbd8c8b..2ab9e022ef 100644 --- a/docs/design/part-events.txt +++ b/docs/design/part-events.txt @@ -24,9 +24,9 @@ Different types of events exist to implement various functionalities. EOS --- -The EOS event can only be send on a sinkpad. It is typically emited by the -source element when it has finished sending data. This event is mainly send -in the streaming thread but can also be send from the application thread. +The EOS event can only be sent on a sinkpad. It is typically emited by the +source element when it has finished sending data. This event is mainly sent +in the streaming thread but can also be sent from the application thread. The downstream element should forward the EOS event to its downstream peer elements. This way the event will eventually reach the renderers which should @@ -58,7 +58,7 @@ goes to PLAYING. FLUSH ----- -A flush event is send both downstream and upstream to clear any pending data +A flush event is sent both downstream and upstream to clear any pending data from the pipeline. This might be neede to make the graph more responsive when the normal dataflow gets interrupted by for example a seek event. @@ -90,10 +90,10 @@ unlocks and any pending buffers are cleared in the upstream elements. DISCONTINUOUS ------------- -A discont event is send downstream by an element to indicate that the following +A discont event is sent downstream by an element to indicate that the following group of buffers start and end at the specified time. -After a seek event for example, a discont event is send. +After a seek event for example, a discont event is sent. SEEK @@ -168,7 +168,7 @@ Navigation events travel downstream. TAG --- -The tag event is send downstream when an element has discovered metadata +The tag event is sent downstream when an element has discovered metadata tags in a media file. Encoders can use this event to adjust their tagging system. diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c index 15fbcf855d..748f917385 100644 --- a/gst/elements/gstfakesrc.c +++ b/gst/elements/gstfakesrc.c @@ -419,8 +419,7 @@ static const GstEventMask * gst_fakesrc_get_event_mask (GstPad * pad) { static const GstEventMask masks[] = { - {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH}, - {GST_EVENT_SEEK_SEGMENT, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP}, + {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP}, {GST_EVENT_FLUSH, 0}, {0, 0}, }; @@ -437,18 +436,12 @@ gst_fakesrc_event_handler (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: - src->buffer_count = GST_EVENT_SEEK_OFFSET (event); - - if (!GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) { - break; - } - /* else we do a flush too */ - case GST_EVENT_SEEK_SEGMENT: src->segment_start = GST_EVENT_SEEK_OFFSET (event); src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event); src->buffer_count = src->segment_start; src->segment_loop = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP; + src->need_flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH; break; case GST_EVENT_FLUSH: src->need_flush = TRUE; @@ -795,7 +788,7 @@ gst_fakesrc_loop (GstPad * pad) if (src->buffer_count == src->segment_end) { if (src->segment_loop) { - gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE)); + //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); diff --git a/gst/gstclock.c b/gst/gstclock.c index a06147c79d..494fd8e4ee 100644 --- a/gst/gstclock.c +++ b/gst/gstclock.c @@ -211,7 +211,14 @@ gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2) entry1 = (GstClockEntry *) id1; entry2 = (GstClockEntry *) id2; - return GST_CLOCK_ENTRY_TIME (entry1) - GST_CLOCK_ENTRY_TIME (entry2); + if (GST_CLOCK_ENTRY_TIME (entry1) > GST_CLOCK_ENTRY_TIME (entry2)) { + return 1; + } + if (GST_CLOCK_ENTRY_TIME (entry1) < GST_CLOCK_ENTRY_TIME (entry2)) { + return -1; + } + + return entry1 - entry2; } /** @@ -262,6 +269,9 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter) if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested))) goto invalid_time; + if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED)) + goto unscheduled; + clock = GST_CLOCK_ENTRY_CLOCK (entry); cclass = GST_CLOCK_GET_CLASS (clock); @@ -276,6 +286,9 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter) *jitter = now - requested; } + if (entry->type == GST_CLOCK_ENTRY_PERIODIC) { + entry->time += entry->interval; + } if (clock->stats) { gst_clock_update_stats (clock); @@ -291,6 +304,11 @@ invalid_time: GST_CAT_DEBUG (GST_CAT_CLOCK, "invalid time requested, returning _BADTIME"); return GST_CLOCK_BADTIME; } +unscheduled: + { + GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was unscheduled return _UNSCHEDULED"); + return GST_CLOCK_UNSCHEDULED; + } } /** @@ -329,6 +347,9 @@ gst_clock_id_wait_async (GstClockID id, if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested))) goto invalid_time; + if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED)) + goto unscheduled; + cclass = GST_CLOCK_GET_CLASS (clock); if (cclass->wait_async) { @@ -348,6 +369,11 @@ invalid_time: GST_CAT_DEBUG (GST_CAT_CLOCK, "invalid time requested, returning _BADTIME"); return GST_CLOCK_BADTIME; } +unscheduled: + { + GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was unscheduled return _UNSCHEDULED"); + return GST_CLOCK_UNSCHEDULED; + } } /** @@ -356,6 +382,8 @@ invalid_time: * * Cancel an outstanding request with the given ID. This can either * be an outstanding async notification or a pending sync notification. + * After this call, the @id cannot be used anymore to receive sync or + * async notifications, you need to create a new GstClockID. * * MT safe. */ diff --git a/gst/gstevent.c b/gst/gstevent.c index 0f09e2001c..661b956155 100644 --- a/gst/gstevent.c +++ b/gst/gstevent.c @@ -354,7 +354,7 @@ gst_event_new_segment_seek (GstSeekType type, gint64 start, gint64 stop) g_return_val_if_fail (start < stop, NULL); - event = gst_event_new (GST_EVENT_SEEK_SEGMENT); + event = gst_event_new (GST_EVENT_SEEK); GST_EVENT_SEEK_TYPE (event) = type; GST_EVENT_SEEK_OFFSET (event) = start; diff --git a/gst/gstevent.h b/gst/gstevent.h index 58eb88af48..a0dfa81c0f 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -41,8 +41,6 @@ typedef enum { GST_EVENT_DISCONTINUOUS = 3, GST_EVENT_QOS = 4, GST_EVENT_SEEK = 5, - GST_EVENT_SEEK_SEGMENT = 6, - GST_EVENT_SEGMENT_DONE = 7, GST_EVENT_SIZE = 8, GST_EVENT_RATE = 9, GST_EVENT_NAVIGATION = 10, diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index c5fc17e5e2..a2820cbc76 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -134,6 +134,7 @@ gst_pipeline_init (GTypeInstance * instance, gpointer g_class) gst_bus_set_sync_handler (bus, (GstBusSyncHandler) pipeline_bus_handler, pipeline); pipeline->eosed = NULL; + pipeline->delay = 0; /* we are our own manager */ GST_ELEMENT_MANAGER (pipeline) = pipeline; gst_element_set_bus (GST_ELEMENT (pipeline), bus); @@ -288,13 +289,17 @@ gst_pipeline_change_state (GstElement * element) } case GST_STATE_PAUSED_TO_PLAYING: if (element->clock) { - /* we set time slightly ahead because of context switches */ - pipeline->start_time = gst_clock_get_time (element->clock); // + 10*GST_MSECOND; - element->base_time = pipeline->start_time - pipeline->stream_time; + GstClockTime start_time = gst_clock_get_time (element->clock); + + element->base_time = start_time - + pipeline->stream_time + pipeline->delay; + GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", start_time=%" + GST_TIME_FORMAT, GST_TIME_ARGS (pipeline->stream_time), + GST_TIME_ARGS (start_time)); + } else { + element->base_time = 0; + GST_DEBUG ("no clock, using base time of 0"); } - GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", start_time=%" - GST_TIME_FORMAT, GST_TIME_ARGS (pipeline->stream_time), - GST_TIME_ARGS (pipeline->start_time)); break; case GST_STATE_PLAYING_TO_PAUSED: case GST_STATE_PAUSED_TO_READY: @@ -315,9 +320,8 @@ gst_pipeline_change_state (GstElement * element) pipeline->stream_time = gst_clock_get_time (element->clock) - element->base_time; } - GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", start_time=%" - GST_TIME_FORMAT, GST_TIME_ARGS (pipeline->stream_time), - GST_TIME_ARGS (pipeline->start_time)); + GST_DEBUG ("stream_time=%" GST_TIME_FORMAT, + GST_TIME_ARGS (pipeline->stream_time)); break; case GST_STATE_PAUSED_TO_READY: break; diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h index 53cb99e2f2..2568be12bd 100644 --- a/gst/gstpipeline.h +++ b/gst/gstpipeline.h @@ -50,8 +50,8 @@ struct _GstPipeline { /*< public >*/ /* with LOCK */ GstClock *fixed_clock; /* fixed clock if any */ - GstClockTime start_time; GstClockTime stream_time; + GstClockTime delay; GList *eosed; /* list of elements that posted EOS */ diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c index 0365246c48..8c45060877 100644 --- a/gst/gstsystemclock.c +++ b/gst/gstsystemclock.c @@ -244,6 +244,7 @@ gst_system_clock_async_thread (GstClock * clock) goto next_entry; case GST_CLOCK_OK: case GST_CLOCK_EARLY: + { /* entry timed out normally, fire the callback and move to the next * entry */ GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p unlocked", entry); @@ -251,7 +252,18 @@ gst_system_clock_async_thread (GstClock * clock) entry->func (clock, entry->time, (GstClockID) entry, entry->user_data); } - goto next_entry; + if (entry->type == GST_CLOCK_ENTRY_PERIODIC) { + /* adjust time now */ + entry->time += entry->interval; + /* and resort the list now */ + clock->entries = + g_list_sort (clock->entries, gst_clock_id_compare_func); + /* and restart */ + continue; + } else { + goto next_entry; + } + } case GST_CLOCK_BUSY: /* somebody unlocked the entry but is was not canceled, This means that * either a new entry was added in front of the queue or some other entry @@ -313,6 +325,7 @@ gst_system_clock_id_wait_unlocked (GstClock * clock, GstClockEntry * entry) GstClockTime real, current, target; GstClockTimeDiff diff; + /* need to call the overridden method */ real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock); target = GST_CLOCK_ENTRY_TIME (entry); @@ -389,7 +402,7 @@ gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry) /* only need to send the signal if the entry was added to the * front, else the thread is just waiting for another entry and - * will discard this entry automatically. */ + * will get to this entry automatically. */ if (clock->entries->data == entry) { GST_CAT_DEBUG (GST_CAT_CLOCK, "send signal"); GST_CLOCK_SIGNAL (clock); diff --git a/libs/gst/dataprotocol/dataprotocol.c b/libs/gst/dataprotocol/dataprotocol.c index eadef1aceb..3fd282e077 100644 --- a/libs/gst/dataprotocol/dataprotocol.c +++ b/libs/gst/dataprotocol/dataprotocol.c @@ -330,15 +330,6 @@ gst_dp_packet_from_event (const GstEvent * event, GstDPHeaderFlag flags, *payload = NULL; break; case GST_EVENT_SEEK: - pl_length = 4 + 8 + 4; - *payload = g_malloc0 (pl_length); - GST_WRITE_UINT32_BE (*payload, (guint32) GST_EVENT_SEEK_TYPE (event)); - GST_WRITE_UINT64_BE (*payload + 4, - (guint64) GST_EVENT_SEEK_OFFSET (event)); - GST_WRITE_UINT32_BE (*payload + 12, - (guint32) GST_EVENT_SEEK_ACCURACY (event)); - break; - case GST_EVENT_SEEK_SEGMENT: pl_length = 4 + 8 + 8 + 4; *payload = g_malloc0 (pl_length); GST_WRITE_UINT32_BE (*payload, (guint32) GST_EVENT_SEEK_TYPE (event)); @@ -350,7 +341,6 @@ gst_dp_packet_from_event (const GstEvent * event, GstDPHeaderFlag flags, (guint32) GST_EVENT_SEEK_ACCURACY (event)); break; case GST_EVENT_QOS: - case GST_EVENT_SEGMENT_DONE: case GST_EVENT_SIZE: case GST_EVENT_RATE: case GST_EVENT_NAVIGATION: @@ -490,20 +480,6 @@ gst_dp_event_from_packet (guint header_length, const guint8 * header, GST_EVENT_TIMESTAMP (event) = GST_DP_HEADER_TIMESTAMP (header); break; case GST_EVENT_SEEK: - { - GstSeekType type; - gint64 offset; - GstSeekAccuracy accuracy; - - type = (GstSeekType) GST_READ_UINT32_BE (payload); - offset = (gint64) GST_READ_UINT64_BE (payload + 4); - accuracy = (GstSeekAccuracy) GST_READ_UINT32_BE (payload + 12); - event = gst_event_new_seek (type, offset); - GST_EVENT_TIMESTAMP (event) = GST_DP_HEADER_TIMESTAMP (header); - GST_EVENT_SEEK_ACCURACY (event) = accuracy; - break; - } - case GST_EVENT_SEEK_SEGMENT: { GstSeekType type; gint64 offset, endoffset; @@ -519,7 +495,6 @@ gst_dp_event_from_packet (guint header_length, const guint8 * header, break; } case GST_EVENT_QOS: - case GST_EVENT_SEGMENT_DONE: case GST_EVENT_SIZE: case GST_EVENT_RATE: case GST_EVENT_NAVIGATION: diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index 15fbcf855d..748f917385 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -419,8 +419,7 @@ static const GstEventMask * gst_fakesrc_get_event_mask (GstPad * pad) { static const GstEventMask masks[] = { - {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH}, - {GST_EVENT_SEEK_SEGMENT, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP}, + {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP}, {GST_EVENT_FLUSH, 0}, {0, 0}, }; @@ -437,18 +436,12 @@ gst_fakesrc_event_handler (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: - src->buffer_count = GST_EVENT_SEEK_OFFSET (event); - - if (!GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) { - break; - } - /* else we do a flush too */ - case GST_EVENT_SEEK_SEGMENT: src->segment_start = GST_EVENT_SEEK_OFFSET (event); src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event); src->buffer_count = src->segment_start; src->segment_loop = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP; + src->need_flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH; break; case GST_EVENT_FLUSH: src->need_flush = TRUE; @@ -795,7 +788,7 @@ gst_fakesrc_loop (GstPad * pad) if (src->buffer_count == src->segment_end) { if (src->segment_loop) { - gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE)); + //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); diff --git a/tests/old/testsuite/clock/Makefile.am b/tests/old/testsuite/clock/Makefile.am index 986837fecd..3111f34253 100644 --- a/tests/old/testsuite/clock/Makefile.am +++ b/tests/old/testsuite/clock/Makefile.am @@ -1,5 +1,5 @@ include ../Rules -tests_pass = signedness clock1 clock2 clock3 +tests_pass = signedness clock1 clock2 clock3 clock4 tests_fail = tests_ignore = diff --git a/tests/old/testsuite/clock/clock4.c b/tests/old/testsuite/clock/clock4.c new file mode 100644 index 0000000000..ff4e398b9b --- /dev/null +++ b/tests/old/testsuite/clock/clock4.c @@ -0,0 +1,100 @@ +/* + * testsuite program to test clock behaviour + * + * creates a fakesrc ! identity ! fakesink pipeline + * registers a callback on fakesrc and one on fakesink + * also register a normal GLib timeout which should not be reached + */ + +#include + +static GstClock *clock = NULL; + +void +gst_clock_debug (GstClock * clock) +{ + GstClockTime time; + + time = gst_clock_get_time (clock); + + g_print ("Clock info: time %" G_GUINT64_FORMAT "\n", time); +} + +static gboolean +ok_callback (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + g_print ("unlocked async id %p\n", id); + return FALSE; +} + +static gboolean +error_callback (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + g_print ("unlocked unscheduled async id %p, this is wrong\n", id); + g_assert_not_reached (); + + return FALSE; +} + +int +main (int argc, char *argv[]) +{ + GstClockID id, id2; + GstClockTime base; + GstClockReturn result; + + gst_init (&argc, &argv); + + clock = gst_system_clock_obtain (); + g_assert (clock != NULL); + + gst_clock_debug (clock); + base = gst_clock_get_time (clock); + + /* signal every half a second */ + id = gst_clock_new_periodic_id (clock, base + GST_SECOND, GST_SECOND / 2); + g_assert (id); + + g_print ("waiting one second\n"); + result = gst_clock_id_wait (id, NULL); + gst_clock_debug (clock); + g_assert (result == GST_CLOCK_OK); + + g_print ("waiting for the next\n"); + result = gst_clock_id_wait (id, NULL); + gst_clock_debug (clock); + g_assert (result == GST_CLOCK_OK); + + g_print ("waiting for the next async %p\n", id); + result = gst_clock_id_wait_async (id, ok_callback, NULL); + g_assert (result == GST_CLOCK_OK); + g_usleep (2 * G_USEC_PER_SEC); + + g_print ("waiting some more for the next async %p\n", id); + result = gst_clock_id_wait_async (id, ok_callback, NULL); + g_assert (result == GST_CLOCK_OK); + g_usleep (2 * G_USEC_PER_SEC); + + id2 = gst_clock_new_periodic_id (clock, base + GST_SECOND, GST_SECOND / 2); + g_assert (id2); + + g_print ("waiting some more for another async %p\n", id2); + result = gst_clock_id_wait_async (id2, ok_callback, NULL); + g_assert (result == GST_CLOCK_OK); + g_usleep (2 * G_USEC_PER_SEC); + + g_print ("unschedule %p\n", id); + gst_clock_id_unschedule (id); + + /* entry cannot be used again */ + result = gst_clock_id_wait_async (id, error_callback, NULL); + g_assert (result == GST_CLOCK_UNSCHEDULED); + result = gst_clock_id_wait (id, NULL); + g_assert (result == GST_CLOCK_UNSCHEDULED); + g_usleep (2 * G_USEC_PER_SEC); + + /* success */ + return 0; +} diff --git a/testsuite/clock/Makefile.am b/testsuite/clock/Makefile.am index 986837fecd..3111f34253 100644 --- a/testsuite/clock/Makefile.am +++ b/testsuite/clock/Makefile.am @@ -1,5 +1,5 @@ include ../Rules -tests_pass = signedness clock1 clock2 clock3 +tests_pass = signedness clock1 clock2 clock3 clock4 tests_fail = tests_ignore = diff --git a/testsuite/clock/clock4.c b/testsuite/clock/clock4.c new file mode 100644 index 0000000000..ff4e398b9b --- /dev/null +++ b/testsuite/clock/clock4.c @@ -0,0 +1,100 @@ +/* + * testsuite program to test clock behaviour + * + * creates a fakesrc ! identity ! fakesink pipeline + * registers a callback on fakesrc and one on fakesink + * also register a normal GLib timeout which should not be reached + */ + +#include + +static GstClock *clock = NULL; + +void +gst_clock_debug (GstClock * clock) +{ + GstClockTime time; + + time = gst_clock_get_time (clock); + + g_print ("Clock info: time %" G_GUINT64_FORMAT "\n", time); +} + +static gboolean +ok_callback (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + g_print ("unlocked async id %p\n", id); + return FALSE; +} + +static gboolean +error_callback (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + g_print ("unlocked unscheduled async id %p, this is wrong\n", id); + g_assert_not_reached (); + + return FALSE; +} + +int +main (int argc, char *argv[]) +{ + GstClockID id, id2; + GstClockTime base; + GstClockReturn result; + + gst_init (&argc, &argv); + + clock = gst_system_clock_obtain (); + g_assert (clock != NULL); + + gst_clock_debug (clock); + base = gst_clock_get_time (clock); + + /* signal every half a second */ + id = gst_clock_new_periodic_id (clock, base + GST_SECOND, GST_SECOND / 2); + g_assert (id); + + g_print ("waiting one second\n"); + result = gst_clock_id_wait (id, NULL); + gst_clock_debug (clock); + g_assert (result == GST_CLOCK_OK); + + g_print ("waiting for the next\n"); + result = gst_clock_id_wait (id, NULL); + gst_clock_debug (clock); + g_assert (result == GST_CLOCK_OK); + + g_print ("waiting for the next async %p\n", id); + result = gst_clock_id_wait_async (id, ok_callback, NULL); + g_assert (result == GST_CLOCK_OK); + g_usleep (2 * G_USEC_PER_SEC); + + g_print ("waiting some more for the next async %p\n", id); + result = gst_clock_id_wait_async (id, ok_callback, NULL); + g_assert (result == GST_CLOCK_OK); + g_usleep (2 * G_USEC_PER_SEC); + + id2 = gst_clock_new_periodic_id (clock, base + GST_SECOND, GST_SECOND / 2); + g_assert (id2); + + g_print ("waiting some more for another async %p\n", id2); + result = gst_clock_id_wait_async (id2, ok_callback, NULL); + g_assert (result == GST_CLOCK_OK); + g_usleep (2 * G_USEC_PER_SEC); + + g_print ("unschedule %p\n", id); + gst_clock_id_unschedule (id); + + /* entry cannot be used again */ + result = gst_clock_id_wait_async (id, error_callback, NULL); + g_assert (result == GST_CLOCK_UNSCHEDULED); + result = gst_clock_id_wait (id, NULL); + g_assert (result == GST_CLOCK_UNSCHEDULED); + g_usleep (2 * G_USEC_PER_SEC); + + /* success */ + return 0; +}