- The clock_wait now returns the difference between requested time and unlock time.
authorWim Taymans <wim.taymans@gmail.com>
Sun, 26 May 2002 21:54:27 +0000 (21:54 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sun, 26 May 2002 21:54:27 +0000 (21:54 +0000)
Original commit message from CVS:
- The clock_wait now returns the difference between requested time and
unlock time.
- Misc defines like GST_SECOND in gstclock.h
- remove pre/post in gstelement.c until fixed.
- added release_locks to gstelement so that the element can unlock itself
- added some more predefined events.
- added folowing functions to gstpad:
- convert function: get the relation between formats on this pad
- query function: get stats about the pad (position/total/latency)
- internal connect function: find out how this pad connects to other
pad internally to the element.
- generic pad_dispatcher.
- removed the last bits of pullregion
- use release_locks on the queue.
- added some events to queue
- make gstthread use the new release_locks function
- make the scheduler use the new clock_wait functions
- added events to fakesink
- added query functions to filesrc
- swap type and offset in the bytestream seek API to match fseek
- added some event handling in bytestream.

31 files changed:
gst/elements/gstfakesink.c
gst/elements/gstfakesrc.c
gst/elements/gstfilesink.c
gst/elements/gstfilesrc.c
gst/gstclock.c
gst/gstclock.h
gst/gstelement.c
gst/gstelement.h
gst/gstevent.c
gst/gstevent.h
gst/gstformat.h [new file with mode: 0644]
gst/gstpad.c
gst/gstpad.h
gst/gstqueue.c
gst/gstqueue.h
gst/gstscheduler.c
gst/gstscheduler.h
gst/gstsystemclock.c
gst/gstthread.c
gst/gsttimecache.h
gst/gsttypes.h
gst/schedulers/gstbasicscheduler.c
libs/gst/bytestream/bytestream.c
libs/gst/bytestream/bytestream.h
plugins/elements/gstfakesink.c
plugins/elements/gstfakesrc.c
plugins/elements/gstfilesink.c
plugins/elements/gstfilesrc.c
plugins/elements/gstqueue.c
plugins/elements/gstqueue.h
tools/gst-inspect.c

index a9b1276..83a24a6 100644 (file)
@@ -149,6 +149,8 @@ gst_fakesink_init (GstFakeSink *fakesink)
   fakesink->last_message = NULL;
 
   GST_ELEMENT (fakesink)->setclockfunc    = gst_fakesink_set_clock;
+
+  GST_FLAG_SET (fakesink, GST_ELEMENT_EVENT_AWARE);
 }
 
 static void
@@ -251,8 +253,26 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
 
   fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
 
-  if (fakesink->sync) { 
-    gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf));
+  if (GST_IS_EVENT (buf)) {
+    GstEvent *event = GST_EVENT (buf);
+         
+    switch (GST_EVENT_TYPE (event)) {
+      case GST_EVENT_DISCONTINUOUS:
+        if (fakesink->sync && fakesink->clock) { 
+          gint64 value = GST_EVENT_DISCONT_OFFSET (event, 0).value;
+          gst_clock_handle_discont (fakesink->clock, value);
+       }
+      default:
+       gst_pad_event_default (pad, event);
+        break;
+    }
+
+    gst_event_free (event);
+    return;
+  }
+
+  if (fakesink->sync && fakesink->clock) { 
+    gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf), NULL);
   }
 
   if (!fakesink->silent) { 
index 83474cf..bace80d 100644 (file)
@@ -322,7 +322,7 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
     case GST_EVENT_SEEK:
       src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
 
-      if (!GST_EVENT_SEEK_FLUSH (event)) {
+      if (!GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
         gst_event_free (event);
         break;
       }
index 9b3cd23..a87e00c 100644 (file)
@@ -271,24 +271,29 @@ gst_filesink_handle_event (GstPad *pad, GstEvent *event)
   switch (type) {
     case GST_EVENT_SEEK:
       /* we need to seek */
-      if (GST_EVENT_SEEK_FLUSH(event))
+      if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH)
         if (fflush(filesink->file))
           gst_element_error(GST_ELEMENT(filesink),
             "Error flushing the buffer cache of file \'%s\' to disk: %s",
             gst_filesink_getcurrentfilename(filesink), sys_errlist[errno]);
-      switch (GST_EVENT_SEEK_TYPE(event))
+
+      if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
+        g_warning("Any other then byte-offset seeking is not supported!\n");
+      }
+
+      switch (GST_EVENT_SEEK_METHOD(event))
       {
-        case GST_SEEK_BYTEOFFSET_SET:
+        case GST_SEEK_METHOD_SET:
           fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_SET);
           break;
-        case GST_SEEK_BYTEOFFSET_CUR:
+        case GST_SEEK_METHOD_CUR:
           fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_CUR);
           break;
-        case GST_SEEK_BYTEOFFSET_END:
+        case GST_SEEK_METHOD_END:
           fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_END);
           break;
         default:
-          g_warning("Any other then byte-offset seeking is not supported!\n");
+          g_warning("unkown seek method!\n");
           break;
       }
       break;
index 4671033..6b885fb 100644 (file)
@@ -110,6 +110,8 @@ static void         gst_filesrc_get_property        (GObject *object, guint prop_id,
 
 static GstBuffer *     gst_filesrc_get                 (GstPad *pad);
 static gboolean        gst_filesrc_srcpad_event        (GstPad *pad, GstEvent *event);
+static gboolean        gst_filesrc_srcpad_query        (GstPad *pad, GstPadQueryType type,
+                                                        GstSeekType *format, gint64 *value);
 
 static GstElementStateReturn   gst_filesrc_change_state        (GstElement *element);
 
@@ -184,8 +186,9 @@ static void
 gst_filesrc_init (GstFileSrc *src)
 {
   src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
-  gst_pad_set_get_function (src->srcpad,gst_filesrc_get);
-  gst_pad_set_event_function (src->srcpad,gst_filesrc_srcpad_event);
+  gst_pad_set_get_function (src->srcpad, gst_filesrc_get);
+  gst_pad_set_event_function (src->srcpad, gst_filesrc_srcpad_event);
+  gst_pad_set_query_function (src->srcpad, gst_filesrc_srcpad_query);
   gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
 
   src->pagesize = getpagesize();
@@ -201,7 +204,7 @@ gst_filesrc_init (GstFileSrc *src)
   src->mapbuf = NULL;
   src->mapsize = 4 * 1024 * 1024;              /* default is 4MB */
 
-  src->map_regions = g_tree_new(gst_filesrc_bufcmp);
+  src->map_regions = g_tree_new (gst_filesrc_bufcmp);
   src->map_regions_lock = g_mutex_new();
 
   src->seek_happened = FALSE;
@@ -445,12 +448,19 @@ gst_filesrc_get (GstPad *pad)
 
   /* check for seek */
   if (src->seek_happened) {
+    GstEvent *event;
+
     src->seek_happened = FALSE;
-    return GST_BUFFER (gst_event_new (GST_EVENT_DISCONTINUOUS));
+    GST_DEBUG (GST_CAT_EVENT, "filesrc sending discont\n");
+    event = gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, src->curoffset, NULL);
+    GST_EVENT_DISCONT_FLUSH (event) = src->need_flush;
+    src->need_flush = FALSE;
+    return GST_BUFFER (event);
   }
   /* check for flush */
   if (src->need_flush) {
     src->need_flush = FALSE;
+    GST_DEBUG (GST_CAT_EVENT, "filesrc sending flush\n");
     return GST_BUFFER (gst_event_new_flush ());
   }
 
@@ -645,6 +655,7 @@ gst_filesrc_change_state (GstElement *element)
     case GST_STATE_READY_TO_PAUSED:
     case GST_STATE_PAUSED_TO_READY:
       src->curoffset = 0;
+      src->seek_happened = TRUE;
     default:
       break;
   }
@@ -656,20 +667,49 @@ gst_filesrc_change_state (GstElement *element)
 }
 
 static gboolean
+gst_filesrc_srcpad_query (GstPad *pad, GstPadQueryType type,
+                         GstFormat *format, gint64 *value)
+{
+  GstFileSrc *src = GST_FILESRC (GST_PAD_PARENT (pad));
+
+  switch (type) {
+    case GST_PAD_QUERY_TOTAL:
+      if (*format != GST_FORMAT_BYTES) {
+       return FALSE;
+      }
+      *value = src->filelen;
+      break;
+    case GST_PAD_QUERY_POSITION:
+      if (*format != GST_FORMAT_BYTES) {
+       return FALSE;
+      }
+      *value = src->curoffset;
+      break;
+    default:
+      return FALSE;
+      break;
+  }
+  return TRUE;
+}
+
+static gboolean
 gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
 {
-  GstFileSrc *src = GST_FILESRC(GST_PAD_PARENT(pad));
+  GstFileSrc *src = GST_FILESRC (GST_PAD_PARENT (pad));
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
-      switch (GST_EVENT_SEEK_TYPE (event)) {
-        case GST_SEEK_BYTEOFFSET_SET:
+      if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
+       return FALSE;
+      }
+      switch (GST_EVENT_SEEK_METHOD (event)) {
+        case GST_SEEK_METHOD_SET:
           src->curoffset = (guint64) GST_EVENT_SEEK_OFFSET (event);
          break;
-        case GST_SEEK_BYTEOFFSET_CUR:
+        case GST_SEEK_METHOD_CUR:
           src->curoffset += GST_EVENT_SEEK_OFFSET (event);
          break;
-        case GST_SEEK_BYTEOFFSET_END:
+        case GST_SEEK_METHOD_END:
           src->curoffset = src->filelen - ABS (GST_EVENT_SEEK_OFFSET (event));
          break;
        default:
@@ -678,9 +718,7 @@ gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
       }
       g_object_notify (G_OBJECT (src), "offset");  
       src->seek_happened = TRUE;
-      src->need_flush = GST_EVENT_SEEK_FLUSH(event);
-      gst_event_free (event);
-      /* push a discontinuous event? */
+      src->need_flush = GST_EVENT_SEEK_FLAGS(event) & GST_SEEK_FLAG_FLUSH;
       break;
     case GST_EVENT_FLUSH:
       src->need_flush = TRUE;
index fa72ac2..b123323 100644 (file)
@@ -258,10 +258,12 @@ gst_clock_set_active (GstClock *clock, gboolean active)
 
   GST_LOCK (clock);
   if (active) {
-    clock->start_time = time - clock->last_time;;
+    clock->start_time = time - clock->last_time;
+    clock->accept_discont = TRUE;
   }
   else {
     clock->last_time = time - clock->start_time;
+    clock->accept_discont = FALSE;
   }
   GST_UNLOCK (clock);
 
@@ -286,6 +288,39 @@ gst_clock_is_active (GstClock *clock)
   return clock->active;
 }
 
+gboolean
+gst_clock_handle_discont (GstClock *clock, guint64 time)
+{
+  GstClockTime itime = 0LL;
+  
+  GST_DEBUG (GST_CAT_CLOCK, "clock discont %llu %llu %d\n", time, clock->start_time, clock->accept_discont);
+
+  GST_LOCK (clock);
+  if (clock->accept_discont) {
+    if (CLASS (clock)->get_internal_time) {
+      itime = CLASS (clock)->get_internal_time (clock);
+    }
+  }
+  else {
+    GST_UNLOCK (clock);
+    GST_DEBUG (GST_CAT_CLOCK, "clock discont refused %llu %llu\n", time, clock->start_time);
+    return FALSE;
+  }
+
+  clock->start_time = itime - time;
+  clock->last_time = time;
+  clock->accept_discont = FALSE;
+  GST_UNLOCK (clock);
+
+  GST_DEBUG (GST_CAT_CLOCK, "new time %llu\n", gst_clock_get_time (clock));
+
+  g_mutex_lock (clock->active_mutex);  
+  g_cond_broadcast (clock->active_cond);       
+  g_mutex_unlock (clock->active_mutex);        
+
+  return TRUE;
+}
+
 /**
  * gst_clock_get_time
  * @clock: a #GstClock to query
@@ -311,7 +346,7 @@ gst_clock_get_time (GstClock *clock)
       ret = CLASS (clock)->get_internal_time (clock) - clock->start_time;
     }
     /* make sure the time is increasing, else return last_time */
-    if (ret < clock->last_time) {
+    if ((gint64) ret < (gint64) clock->last_time) {
       ret = clock->last_time;
     }
     else {
@@ -355,7 +390,7 @@ gst_clock_wait_async_func (GstClock *clock, GstClockTime time,
  * Returns: the #GstClockReturn result of the operation.
  */
 GstClockReturn
-gst_clock_wait (GstClock *clock, GstClockTime time)
+gst_clock_wait (GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
 {
   GstClockID id;
   GstClockReturn res;
@@ -363,7 +398,7 @@ gst_clock_wait (GstClock *clock, GstClockTime time)
   g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_STOPPED);
 
   id = gst_clock_wait_async_func (clock, time, NULL, NULL);
-  res = gst_clock_wait_id (clock, id);
+  res = gst_clock_wait_id (clock, id, jitter);
 
   return res;
 }
@@ -460,12 +495,13 @@ gst_clock_unlock_func (GstClock *clock, GstClockTime time, GstClockID id, gpoint
  * Returns: result of the operation.
  */
 GstClockReturn
-gst_clock_wait_id (GstClock *clock, GstClockID id)
+gst_clock_wait_id (GstClock *clock, GstClockID id, GstClockTimeDiff *jitter)
 {
   GstClockReturn res = GST_CLOCK_TIMEOUT;
   GstClockEntry *entry = (GstClockEntry *) id;
   GstClockTime current_real, current, target;
   GTimeVal timeval;
+  GstClockTimeDiff this_jitter;
   
   g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_ERROR);
   g_return_val_if_fail (entry, GST_CLOCK_ERROR);
@@ -479,16 +515,24 @@ gst_clock_wait_id (GstClock *clock, GstClockID id)
   entry->func = gst_clock_unlock_func;
   target = GST_CLOCK_ENTRY_TIME (entry) - current + current_real;
 
-  GST_DEBUG (GST_CAT_CLOCK, "%llu %llu %llu\n", target, current, current_real); 
+  GST_DEBUG (GST_CAT_CLOCK, "real_target %llu, current_real %llu, target %llu, now %llu\n", 
+                 target, current_real, GST_CLOCK_ENTRY_TIME (entry), current); 
   
   if (target > current_real) {
-    timeval.tv_usec = target % 1000000;
-    timeval.tv_sec = target / 1000000;
-
+    GST_TIME_TO_TIMEVAL (target, timeval);
     GST_CLOCK_ENTRY_TIMED_WAIT (entry, &timeval);
+    current = gst_clock_get_time (clock);
+    this_jitter = current - GST_CLOCK_ENTRY_TIME (entry);
+  }
+  else {
+    res = GST_CLOCK_EARLY;
+    this_jitter = target - current_real;
   }
   GST_CLOCK_ENTRY_UNLOCK (entry);
 
+  if (jitter)
+    *jitter = this_jitter;
+
   gst_clock_free_entry (clock, entry);
 
   return res;
index 97a88a2..9fb6d87 100644 (file)
@@ -45,8 +45,18 @@ typedef guint64      GstClockTime;
 typedef gint64                 GstClockTimeDiff;
 typedef gpointer       GstClockID;
 
-#define GST_CLOCK_DIFF(s, e)   (GstClockTimeDiff)((s)-(e))
-#define GST_TIMEVAL_TO_TIME(tv)        ((tv).tv_sec * (guint64) G_USEC_PER_SEC + (tv).tv_usec)
+#define GST_SECOND  ((guint64)G_USEC_PER_SEC)
+#define GST_MSECOND ((guint64)GST_SECOND/1000LL)
+#define GST_USECOND ((guint64)GST_SECOND/1000000LL)
+#define GST_NSECOND ((guint64)GST_SECOND/1000000000LL)
+
+#define GST_CLOCK_DIFF(s, e)           (GstClockTimeDiff)((s)-(e))
+#define GST_TIMEVAL_TO_TIME(tv)                ((tv).tv_sec * GST_SECOND + (tv).tv_usec * GST_USECOND)
+#define GST_TIME_TO_TIMEVAL(t,tv)                      \
+G_STMT_START {                                                 \
+  (tv).tv_sec  = (t) / GST_SECOND;                     \
+  (tv).tv_usec = ((t) / GST_USECOND) % GST_SECOND;     \
+} G_STMT_END
 
 typedef struct _GstClock       GstClock;
 typedef struct _GstClockClass  GstClockClass;
@@ -66,6 +76,7 @@ struct _GstClock {
 
   GstClockTime  start_time;
   GstClockTime  last_time;
+  gboolean      accept_discont;
   gdouble       speed;
   gboolean      active;
   GList                *entries;
@@ -95,18 +106,19 @@ gdouble            gst_clock_get_speed             (GstClock *clock);
 void                   gst_clock_set_active            (GstClock *clock, gboolean active);
 gboolean               gst_clock_is_active             (GstClock *clock);
 void                   gst_clock_reset                 (GstClock *clock);
+gboolean               gst_clock_handle_discont        (GstClock *clock, guint64 time);
 gboolean               gst_clock_async_supported       (GstClock *clock);
 
 GstClockTime           gst_clock_get_time              (GstClock *clock);
 
-GstClockReturn         gst_clock_wait                  (GstClock *clock, GstClockTime time);
+GstClockReturn         gst_clock_wait                  (GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter);
 GstClockID             gst_clock_wait_async            (GstClock *clock, GstClockTime time, 
                                                         GstClockCallback func, gpointer user_data);
 void                   gst_clock_cancel_wait_async     (GstClock *clock, GstClockID id);
 GstClockID             gst_clock_notify_async          (GstClock *clock, GstClockTime interval, 
                                                         GstClockCallback func, gpointer user_data);
 void                   gst_clock_remove_notify_async   (GstClock *clock, GstClockID id);
-GstClockReturn         gst_clock_wait_id               (GstClock *clock, GstClockID id);
+GstClockReturn         gst_clock_wait_id               (GstClock *clock, GstClockID id, GstClockTimeDiff *jitter);
 
 GstClockID             gst_clock_get_next_id           (GstClock *clock);
 void                   gst_clock_unlock_id             (GstClock *clock, GstClockID id);
index efb4600..8a4b351 100644 (file)
@@ -183,6 +183,7 @@ gst_element_init (GstElement *element)
   element->pads = NULL;
   element->loopfunc = NULL;
   element->sched = NULL;
+  element->clock = NULL;
   element->sched_private = NULL;
   element->state_mutex = g_mutex_new ();
   element->state_cond = g_cond_new ();
@@ -223,9 +224,8 @@ gst_element_dispatch_properties_changed (GObject     *object,
   G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
 
   /* now let the parent dispatch those, too */
-  gst_object = GST_OBJECT (object);
-  while (gst_object)
-  {
+  gst_object = GST_OBJECT_PARENT (object);
+  while (gst_object) {
     /* need own category? */
     for (i = 0; i < n_pspecs; i++) {
       GST_DEBUG (GST_CAT_EVENT, "deep notification from %s to %s (%s)", GST_OBJECT_NAME (object), 
@@ -266,7 +266,7 @@ static void
 gst_element_threadsafe_properties_pre_run (GstElement *element)
 {
   GST_DEBUG (GST_CAT_THREAD, "locking element %s", GST_OBJECT_NAME (element));
-  g_mutex_lock (element->property_mutex);
+  //g_mutex_lock (element->property_mutex);
   gst_element_set_pending_properties (element);
 }
 
@@ -274,7 +274,7 @@ static void
 gst_element_threadsafe_properties_post_run (GstElement *element)
 {
   GST_DEBUG (GST_CAT_THREAD, "unlocking element %s", GST_OBJECT_NAME (element));
-  g_mutex_unlock (element->property_mutex);
+  //g_mutex_unlock (element->property_mutex);
 }
 
 void
@@ -678,6 +678,8 @@ gst_element_set_clock (GstElement *element, GstClock *clock)
 
   if (element->setclockfunc)
     element->setclockfunc (element, clock);
+
+  element->clock = clock;
 }
 
 /**
@@ -711,16 +713,41 @@ gst_element_get_clock (GstElement *element)
  * Returns: the #GstClockReturn result of the wait operation
  */
 GstClockReturn
-gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time)
+gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
 {
+  GstClockReturn res;
+
   g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
 
   if (GST_ELEMENT_SCHED (element)) {
-    return gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time);
+    res = gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time, jitter);
   }
   else 
-    return GST_CLOCK_TIMEOUT;
+    res = GST_CLOCK_TIMEOUT;
+
+  return res;
+}
+
+
+/**
+ * gst_element_release_locks:
+ * @element: an element 
+ *
+ * Instruct the element to release all the locks it is holding, ex
+ * blocking reads, waiting for the clock, ...
+ *
+ * Returns: TRUE if the locks could be released.
+ */
+gboolean
+gst_element_release_locks (GstElement *element)
+{
+  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+
+  if (CLASS (element)->release_locks)
+    return CLASS (element)->release_locks (element);
+  
+  return TRUE;
 }
 
 /**
index 73d7ba8..1a32317 100644 (file)
@@ -130,6 +130,7 @@ struct _GstElement {
   gpointer             sched_private;
   GstElementSetClockFunction setclockfunc;
   GstElementGetClockFunction getclockfunc;
+  GstClock             *clock;
 
   /* element pads */
   guint16              numpads;
@@ -169,6 +170,7 @@ struct _GstElementClass {
   void (*get_property) (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
 
   /* vtable*/
+  gboolean             (*release_locks)        (GstElement *element);
   /* change the element state */
   GstElementStateReturn (*change_state)                (GstElement *element);
   /* request a new pad */
@@ -211,7 +213,10 @@ GstObject*              gst_element_get_parent          (GstElement *element);
 
 GstClock*              gst_element_get_clock           (GstElement *element);
 void                   gst_element_set_clock           (GstElement *element, GstClock *clock);
-GstClockReturn         gst_element_clock_wait          (GstElement *element, GstClock *clock, GstClockTime time);
+GstClockReturn         gst_element_clock_wait          (GstElement *element, GstClock *clock, 
+                                                        GstClockTime time, GstClockTimeDiff *jitter);
+
+gboolean               gst_element_release_locks       (GstElement *element);
 
 void                   gst_element_yield               (GstElement *element);
 gboolean               gst_element_interrupt           (GstElement *element);
index 880dd68..5951952 100644 (file)
@@ -25,6 +25,8 @@
 #include "gst/gstevent.h"
 #include <string.h>            /* memcpy */
 
+/* #define MEMPROF */
+
 GType _gst_event_type;
 
 static GMemChunk *_gst_event_chunk;
@@ -71,9 +73,13 @@ gst_event_new (GstEventType type)
 {
   GstEvent *event;
 
+#ifndef MEMPROF
   g_mutex_lock (_gst_event_chunk_lock);
   event = g_mem_chunk_alloc (_gst_event_chunk);
   g_mutex_unlock (_gst_event_chunk_lock);
+#else
+  event = g_new0(GstEvent, 1);
+#endif
   GST_INFO (GST_CAT_EVENT, "creating new event %p", event);
 
   GST_DATA_TYPE (event) = _gst_event_type;
@@ -97,9 +103,13 @@ gst_event_copy (GstEvent *event)
 {
   GstEvent *copy;
 
+#ifndef MEMPROF
   g_mutex_lock (_gst_event_chunk_lock);
   copy = g_mem_chunk_alloc (_gst_event_chunk);
   g_mutex_unlock (_gst_event_chunk_lock);
+#else
+  copy = g_new0(GstEvent, 1);
+#endif
 
   memcpy (copy, event, sizeof (GstEvent));
   
@@ -127,7 +137,11 @@ gst_event_free (GstEvent* event)
     default:
       break;
   }
+#ifndef MEMPROF
   g_mem_chunk_free (_gst_event_chunk, event);
+#else
+  g_free (event);
+#endif
   g_mutex_unlock (_gst_event_chunk_lock);
 }
 
@@ -142,16 +156,65 @@ gst_event_free (GstEvent* event)
  * Returns: A new seek event.
  */
 GstEvent*       
-gst_event_new_seek (GstSeekType type, gint64 offset, gboolean flush)
+gst_event_new_seek (GstSeekType type, gint64 offset)
 {
   GstEvent *event;
 
   event = gst_event_new (GST_EVENT_SEEK);
   GST_EVENT_SEEK_TYPE (event) = type;
   GST_EVENT_SEEK_OFFSET (event) = offset;
-  GST_EVENT_SEEK_FLUSH (event) = flush;
 
   return event;
 }
 
+GstEvent*
+gst_event_new_discontinuous (gboolean new_media, GstSeekType format1, ...)
+{
+  va_list var_args;
+  GstEvent *event;
+  gint count = 0;
+
+  event = gst_event_new (GST_EVENT_DISCONTINUOUS);
+  GST_EVENT_DISCONT_NEW_MEDIA (event) = new_media;
+
+  va_start (var_args, format1);
+               
+  while (format1) {
+
+    GST_EVENT_DISCONT_OFFSET (event, count).format = format1 & GST_SEEK_FORMAT_MASK;
+    GST_EVENT_DISCONT_OFFSET (event, count).value = va_arg (var_args, gint64);
+
+    format1 = va_arg (var_args, GstSeekType);
+
+    count++;
+  }
+  va_end (var_args);
+
+  GST_EVENT_DISCONT_OFFSET_LEN (event) = count;
+                   
+  return event;
+}
+
+gboolean
+gst_event_discont_get_value (GstEvent *event, GstSeekType type, gint64 *value)
+{
+  gint i, n;
+
+  g_return_val_if_fail (event, FALSE);
+  g_return_val_if_fail (value, FALSE);
+
+  n = GST_EVENT_DISCONT_OFFSET_LEN (event);
+
+  for (i = 0; i < n; i++) {
+    if (GST_EVENT_DISCONT_OFFSET(event,i).format == type) {
+      *value = GST_EVENT_DISCONT_OFFSET(event,i).value;
+      return TRUE;
+    }
+  }
+  
+  return FALSE;
+}
+
+
+
 
index 46166ff..1595b63 100644 (file)
 #define __GST_EVENT_H__
 
 #include <gst/gsttypes.h>
-#include <gst/gstelement.h>
-#include <gst/gstobject.h>
 #include <gst/gstdata.h>
 #include <gst/gstcaps.h>
+#include <gst/gstformat.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
 
 typedef enum {
   GST_EVENT_UNKNOWN,
   GST_EVENT_EOS,
   GST_EVENT_FLUSH,
   GST_EVENT_EMPTY,
-  GST_EVENT_SEEK,
   GST_EVENT_DISCONTINUOUS,
   GST_EVENT_NEW_MEDIA,
+  GST_EVENT_QOS,
+  GST_EVENT_SEEK,
+  GST_EVENT_FILLER,
 } GstEventType;
 
 extern GType _gst_event_type;
@@ -54,20 +53,45 @@ extern GType _gst_event_type;
 #define GST_EVENT_TIMESTAMP(event)     (GST_EVENT(event)->timestamp)
 #define GST_EVENT_SRC(event)           (GST_EVENT(event)->src)
 
+#define GST_SEEK_FORMAT_SHIFT  0
+#define GST_SEEK_METHOD_SHIFT  16
+#define GST_SEEK_FLAGS_SHIFT   20
+#define GST_SEEK_FORMAT_MASK   0x0000ffff
+#define GST_SEEK_METHOD_MASK   0x000f0000
+#define GST_SEEK_FLAGS_MASK    0xfff00000
+
 /* seek events */
 typedef enum {
-  GST_SEEK_ANY,
-  GST_SEEK_TIMEOFFSET_CUR,
-  GST_SEEK_TIMEOFFSET_SET,
-  GST_SEEK_TIMEOFFSET_END,
-  GST_SEEK_BYTEOFFSET_SET,
-  GST_SEEK_BYTEOFFSET_CUR,
-  GST_SEEK_BYTEOFFSET_END,
+  GST_SEEK_METHOD_CUR          = (1 << GST_SEEK_METHOD_SHIFT),
+  GST_SEEK_METHOD_SET          = (2 << GST_SEEK_METHOD_SHIFT),
+  GST_SEEK_METHOD_END          = (3 << GST_SEEK_METHOD_SHIFT),
+
+  GST_SEEK_FLAG_FLUSH          = (1 << (GST_SEEK_FLAGS_SHIFT + 0)),
+  GST_SEEK_FLAG_ACCURATE       = (1 << (GST_SEEK_FLAGS_SHIFT + 1)),
 } GstSeekType;
 
-#define GST_EVENT_SEEK_TYPE(event)     (GST_EVENT(event)->event_data.seek.type)
-#define GST_EVENT_SEEK_OFFSET(event)   (GST_EVENT(event)->event_data.seek.offset)
-#define GST_EVENT_SEEK_FLUSH(event)    (GST_EVENT(event)->event_data.seek.flush)
+typedef enum {
+  GST_SEEK_CERTAIN,
+  GST_SEEK_FUZZY,
+} GstSeekAccuracy;
+
+typedef struct
+{
+  GstFormat    format;
+  gint64       value;
+} GstFormatValue;
+
+#define GST_EVENT_SEEK_TYPE(event)             (GST_EVENT(event)->event_data.seek.type)
+#define GST_EVENT_SEEK_FORMAT(event)           (GST_EVENT_SEEK_TYPE(event) & GST_SEEK_FORMAT_MASK)
+#define GST_EVENT_SEEK_METHOD(event)           (GST_EVENT_SEEK_TYPE(event) & GST_SEEK_METHOD_MASK)
+#define GST_EVENT_SEEK_FLAGS(event)            (GST_EVENT_SEEK_TYPE(event) & GST_SEEK_FLAGS_MASK)
+#define GST_EVENT_SEEK_OFFSET(event)           (GST_EVENT(event)->event_data.seek.offset)
+#define GST_EVENT_SEEK_ACCURACY(event)         (GST_EVENT(event)->event_data.seek.accuracy)
+
+#define GST_EVENT_DISCONT_NEW_MEDIA(event)     (GST_EVENT(event)->event_data.discont.new_media)
+#define GST_EVENT_DISCONT_FLUSH(event)         (GST_EVENT(event)->event_data.discont.flush)
+#define GST_EVENT_DISCONT_OFFSET(event,i)      (GST_EVENT(event)->event_data.discont.offsets[i])
+#define GST_EVENT_DISCONT_OFFSET_LEN(event)    (GST_EVENT(event)->event_data.discont.noffsets)
 
 struct _GstEvent {
   GstData data;
@@ -78,27 +102,37 @@ struct _GstEvent {
 
   union {
     struct {
-      GstSeekType type;
-      gint64      offset;
-      gboolean   flush;
+      GstSeekType      type;
+      gint64           offset;
+      GstSeekAccuracy  accuracy;
     } seek;
+    struct {
+      GstFormatValue   offsets[8];
+      gint             noffsets;
+      gboolean         new_media;
+      gboolean         flush;
+      GstSeekAccuracy  accuracy;
+    } discont;
   } event_data;
 };
 
-void           _gst_event_initialize   (void);
+void           _gst_event_initialize           (void);
        
-GstEvent*      gst_event_new           (GstEventType type);
-GstEvent*      gst_event_copy          (GstEvent *event);
-void           gst_event_free          (GstEvent *event);
+GstEvent*      gst_event_new                   (GstEventType type);
+GstEvent*      gst_event_copy                  (GstEvent *event);
+void           gst_event_free                  (GstEvent *event);
 
 /* seek events */
-GstEvent*      gst_event_new_seek      (GstSeekType type, gint64 offset, gboolean flush);
+GstEvent*      gst_event_new_seek              (GstSeekType type, gint64 offset);
+GstEvent*      gst_event_new_discontinuous     (gboolean new_media,
+                                                GstFormat format1, ...);
+gboolean       gst_event_discont_get_value     (GstEvent *event, GstFormat format, gint64 *value);
+
+#define                gst_event_new_filler()          gst_event_new(GST_EVENT_FILLER)
 
 /* flush events */
-#define                gst_event_new_flush()   gst_event_new(GST_EVENT_FLUSH)
+#define                gst_event_new_flush()           gst_event_new(GST_EVENT_FLUSH)
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
 
 #endif /* __GST_EVENT_H__ */
diff --git a/gst/gstformat.h b/gst/gstformat.h
new file mode 100644 (file)
index 0000000..fbce2aa
--- /dev/null
@@ -0,0 +1,49 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstevent.h: Header for GstEvent subsystem
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_FORMAT_H__
+#define __GST_FORMAT_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+  GST_FORMAT_NONE      = 0,
+  GST_FORMAT_DEFAULT           = 1,
+  GST_FORMAT_BYTES     = 2,
+  GST_FORMAT_TIME      = 6,
+  GST_FORMAT_BUFFERS   = 7,
+  GST_FORMAT_PERCENT   = 8,
+
+  /* audio related */
+  GST_FORMAT_SAMPLES   = 3,
+
+  /* video related */
+  GST_FORMAT_FRAMES    = 4,
+  GST_FORMAT_FIELDS    = 5,
+} GstFormat;
+
+G_END_DECLS
+
+#endif /* __GST_FORMAT_H__ */
index 229f411..cb1498d 100644 (file)
 #include "gstscheduler.h"
 #include "gstevent.h"
 
+enum {
+  TEMPL_PAD_CREATED,
+  /* FILL ME */
+  TEMPL_LAST_SIGNAL
+};
+
+static GstObject *padtemplate_parent_class = NULL;
+static guint gst_pad_template_signals[TEMPL_LAST_SIGNAL] = { 0 };
+
 GType _gst_pad_type = 0;
 
 /***** Start with the base GstPad class *****/
@@ -206,11 +215,9 @@ gst_real_pad_init (GstRealPad *pad)
 
   pad->chainfunc = NULL;
   pad->getfunc = NULL;
-  pad->getregionfunc = NULL;
 
   pad->chainhandler = GST_DEBUG_FUNCPTR (gst_pad_push_func);
   pad->gethandler = NULL;
-  pad->pullregionfunc = NULL;
 
   pad->bufferpoolfunc = NULL;
   pad->ghostpads = NULL;
@@ -218,6 +225,12 @@ gst_real_pad_init (GstRealPad *pad)
 
   pad->connectfunc = NULL;
   pad->getcapsfunc = NULL;
+
+  pad->convertfunc     = gst_pad_convert_default;
+  pad->eventfunc       = gst_pad_event_default;
+  pad->convertfunc     = gst_pad_convert_default;
+  pad->queryfunc       = gst_pad_query_default;
+  pad->intconnfunc     = gst_pad_get_internal_connections_default;
 }
 
 static void
@@ -259,24 +272,25 @@ gst_real_pad_get_property (GObject *object, guint prop_id, GValue *value, GParam
 
 
 /**
- * gst_pad_new:
+ * gst_pad_custom_new:
+ * @type: the type of the pad
  * @name: name of new pad
  * @direction: either GST_PAD_SRC or GST_PAD_SINK
  *
- * Create a new pad with given name.
+ * Create a new pad with given name from the given type.
  *
  * Returns: new pad
  */
 GstPad*
-gst_pad_new (gchar *name,
-            GstPadDirection direction)
+gst_pad_custom_new (GType type, const gchar *name,
+                   GstPadDirection direction)
 {
   GstRealPad *pad;
 
   g_return_val_if_fail (name != NULL, NULL);
   g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
 
-  pad = g_object_new (gst_real_pad_get_type (), NULL);
+  pad = g_object_new (type, NULL);
   gst_object_set_name (GST_OBJECT (pad), name);
   GST_RPAD_DIRECTION (pad) = direction;
 
@@ -284,7 +298,23 @@ gst_pad_new (gchar *name,
 }
 
 /**
- * gst_pad_new_from_template:
+ * gst_pad_new:
+ * @name: name of new pad
+ * @direction: either GST_PAD_SRC or GST_PAD_SINK
+ *
+ * Create a new pad with given name.
+ *
+ * Returns: new pad
+ */
+GstPad*
+gst_pad_new (const gchar *name,
+            GstPadDirection direction)
+{
+  return gst_pad_custom_new (gst_real_pad_get_type (), name, direction);
+}
+/**
+ * gst_pad_custom_new_from_template:
+ * @type: the custom GType for this pad
  * @templ: the pad template to use
  * @name: the name of the element
  *
@@ -293,8 +323,8 @@ gst_pad_new (gchar *name,
  * Returns: new pad
  */
 GstPad*
-gst_pad_new_from_template (GstPadTemplate *templ,
-                          gchar *name)
+gst_pad_custom_new_from_template (GType type, GstPadTemplate *templ,
+                                 const gchar *name)
 {
   GstPad *pad;
 
@@ -305,11 +335,29 @@ gst_pad_new_from_template (GstPadTemplate *templ,
   
   gst_object_ref (GST_OBJECT (templ));
   GST_PAD_PAD_TEMPLATE (pad) = templ;
+
+  g_signal_emit (G_OBJECT (templ), gst_pad_template_signals[TEMPL_PAD_CREATED], 0, pad);
   
   return pad;
 }
 
 /**
+ * gst_pad_new_from_template:
+ * @templ: the pad template to use
+ * @name: the name of the element
+ *
+ * Create a new pad with given name from the given template.
+ *
+ * Returns: new pad
+ */
+GstPad*
+gst_pad_new_from_template (GstPadTemplate *templ,
+                          const gchar *name)
+{
+  return gst_pad_custom_new_from_template (gst_real_pad_get_type (), templ, name);
+}
+
+/**
  * gst_pad_get_direction:
  * @pad: the Pad to get the direction from
  *
@@ -418,24 +466,43 @@ gst_pad_set_event_function (GstPad *pad,
 }
 
 /**
- * gst_pad_set_getregion_function:
- * @pad: the pad to set the getregion function for
- * @getregion: the getregion function
+ * gst_pad_set_convert_function:
+ * @pad: the pad to set the event handler for
+ * @convert: the convert function
+ *
+ * Set the given convert function for the pad.
+ */
+void
+gst_pad_set_convert_function (GstPad *pad,
+                              GstPadConvertFunction convert)
+{
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_REAL_PAD (pad));
+
+  GST_RPAD_CONVERTFUNC(pad) = convert;
+  GST_DEBUG (GST_CAT_PADS, "convertfunc for %s:%s  set to %s",
+             GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (convert));
+}
+
+/**
+ * gst_pad_set_query_function:
+ * @pad: the pad to set the event handler for
+ * @query: the query function
  *
- * Set the given getregion function for the pad.
+ * Set the given query function for the pad.
  */
 void
-gst_pad_set_getregion_function (GstPad *pad,
-                               GstPadGetRegionFunction getregion)
+gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query)
 {
   g_return_if_fail (pad != NULL);
   g_return_if_fail (GST_IS_REAL_PAD (pad));
 
-  GST_RPAD_GETREGIONFUNC(pad) = getregion;
-  GST_DEBUG (GST_CAT_PADS, "getregionfunc for %s:%s set to %s",
-             GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (getregion));
+  GST_RPAD_QUERYFUNC(pad) = query;
+  GST_DEBUG (GST_CAT_PADS, "queryfunc for %s:%s  set to %s",
+             GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (query));
 }
 
+
 /**
  * gst_pad_set_connect_function:
  * @pad: the pad to set the connect function for
@@ -1832,56 +1899,6 @@ gst_pad_pull (GstPad *pad)
 }
 #endif
 
-#ifndef gst_pad_pullregion
-/**
- * gst_pad_pullregion:
- * @pad: the pad to pull the region from
- * @type: the regiontype
- * @offset: the offset/start of the buffer to pull
- * @len: the length of the buffer to pull
- *
- * Pull a buffer region from the peer pad. The region to pull can be 
- * specified with a offset/lenght pair or with a start/legnth time
- * indicator as specified by the type parameter.
- *
- * Returns: a new buffer from the peer pad with data in the specified
- * region.
- */
-GstBuffer*
-gst_pad_pullregion (GstPad *pad, GstRegionType type, guint64 offset, guint64 len) 
-{
-  GstRealPad *peer;
-  GstBuffer *result = NULL;
-  
-  g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, NULL);
-
-  do {
-    peer = GST_RPAD_PEER(pad);
-    g_return_val_if_fail (peer != NULL, NULL);
-
-    if (result) 
-      gst_buffer_unref (result);
-
-    GST_DEBUG_ENTER("(%s:%s,%d,%lld,%lld)",GST_DEBUG_PAD_NAME(pad),type,offset,len);
-
-    if (peer->pullregionfunc) {
-      GST_DEBUG (GST_CAT_DATAFLOW, "calling pullregionfunc &%s of peer pad %s:%s",
-          GST_DEBUG_FUNCPTR_NAME (peer->pullregionfunc), GST_DEBUG_PAD_NAME(GST_PAD_CAST (peer)));
-      result = (peer->pullregionfunc) (GST_PAD_CAST (peer), type, offset, len);
-    } else {
-      GST_DEBUG (GST_CAT_DATAFLOW,"no pullregionfunc");
-      result = NULL;
-      break;
-    }
-  }
-  /* FIXME */
-  while (result && !(GST_BUFFER_OFFSET (result) == offset && 
-          GST_BUFFER_SIZE (result) == len));
-
-  return result;
-}
-#endif
-
 /**
  * gst_pad_peek:
  * @pad: the pad to peek
@@ -1959,15 +1976,6 @@ gst_pad_selectv (GstPad *pad, ...)
 static void            gst_pad_template_class_init     (GstPadTemplateClass *klass);
 static void            gst_pad_template_init           (GstPadTemplate *templ);
 
-enum {
-  TEMPL_PAD_CREATED,
-  /* FILL ME */
-  TEMPL_LAST_SIGNAL
-};
-
-static GstObject *padtemplate_parent_class = NULL;
-static guint gst_pad_template_signals[TEMPL_LAST_SIGNAL] = { 0 };
-
 GType
 gst_pad_template_get_type (void)
 {
@@ -2238,7 +2246,72 @@ gst_ghost_pad_new (gchar *name,
   return GST_PAD (ghostpad);
 }
 
-static void 
+/**
+ * gst_pad_get_internal_connections_default:
+ * @pad: the pad to get the internal connections of
+ *
+ * Get a GList of pads that this pad is connected to internally
+ * to the parent element.
+ *
+ * Returns: a GList of pads, g_list_free after use.
+ */
+GList*
+gst_pad_get_internal_connections_default (GstPad *pad)
+{
+  GList *res = NULL;
+  GstElement *parent;
+  GList *parent_pads;
+  GstPadDirection direction;
+  GstRealPad *rpad;
+  
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+
+  rpad = GST_PAD_REALIZE (pad);
+  direction = rpad->direction;
+
+  parent = GST_PAD_PARENT (rpad);
+  parent_pads = parent->pads;
+
+  while (parent_pads) {
+    GstRealPad *parent_pad = GST_PAD_REALIZE (parent_pads->data);
+    
+    if (parent_pad->direction != direction) {
+      res = g_list_prepend (res, parent_pad);
+    }
+    
+    parent_pads = g_list_next (parent_pads);
+  }
+
+  return res;
+}
+
+/**
+ * gst_pad_get_internal_connections:
+ * @pad: the pad to get the internal connections of
+ *
+ * Get a GList of pads that this pad is connected to internally
+ * to the parent element.
+ *
+ * Returns: a GList of pads, g_list_free after use.
+ */
+GList*
+gst_pad_get_internal_connections (GstPad *pad)
+{
+  GList *res = NULL;
+  GstRealPad *rpad;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+
+  rpad = GST_PAD_REALIZE (pad);
+
+  if (GST_RPAD_INTCONNFUNC (rpad))
+    res = GST_RPAD_INTCONNFUNC (rpad) (GST_PAD_CAST (rpad));
+
+  return res;
+}
+
+
+static gboolean 
 gst_pad_event_default_dispatch (GstPad *pad, GstElement *element, GstEvent *event)
 {
   GList *pads = element->pads;
@@ -2255,10 +2328,13 @@ gst_pad_event_default_dispatch (GstPad *pad, GstElement *element, GstEvent *even
       else {
        GstPad *peerpad = GST_PAD_CAST (GST_RPAD_PEER (eventpad));
 
-        gst_pad_send_event (peerpad, gst_event_copy (event));
+       /* we only send the event on one pad, multi-sinkpad elements should implement
+        * a handler */
+        return gst_pad_send_event (peerpad, event);
       }
     }
   }
+  return TRUE;
 }
 
 /**
@@ -2267,8 +2343,10 @@ gst_pad_event_default_dispatch (GstPad *pad, GstElement *element, GstEvent *even
  * @event: the event to handle
  *
  * Invoke the default event handler for the given pad.
+ *
+ * Returns: TRUE if the event was sent succesfully.
  */
-void 
+gboolean 
 gst_pad_event_default (GstPad *pad, GstEvent *event)
 {
   GstElement *element = GST_PAD_PARENT (pad);
@@ -2282,11 +2360,61 @@ gst_pad_event_default (GstPad *pad, GstEvent *event)
       /* we have to try to schedule another element because this one is disabled */
       gst_element_yield (element);
       break;
+    case GST_EVENT_DISCONTINUOUS:
+    {
+      guint64 time;
+      
+      if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)) {
+       if (element->setclockfunc && element->clock) {
+         gst_clock_handle_discont (element->clock, time); 
+       }
+      }
+    }
     case GST_EVENT_FLUSH:
     default:
-      gst_pad_event_default_dispatch (pad, element, event);
-      break;
+      return gst_pad_event_default_dispatch (pad, element, event);
   }
+  return TRUE;
+}
+
+/**
+ * gst_pad_dispatcher:
+ * @pad: the pad to dispatch
+ * @dispatch: the GstDispatcherFunc to call
+ * @data: data passed to the dispatcher function.
+ *
+ * Invoke the given dispatcher function on all internally connected
+ * pads of the given pad. The GstPadDispatcherFunc should return
+ * TRUE when no further pads need to be preocessed.
+ *
+ * Returns: TRUE if one of the dispatcher functions returned TRUE.
+ */
+gboolean
+gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunc dispatch, gpointer data)
+{
+  gboolean res = FALSE;
+  GList *int_pads, *orig;
+  
+  g_return_val_if_fail (pad, FALSE);
+  g_return_val_if_fail (data, FALSE);
+
+  orig = int_pads = gst_pad_get_internal_connections (pad);
+
+  while (int_pads) {
+    GstRealPad *int_rpad = GST_PAD_REALIZE (int_pads->data);
+    GstRealPad *int_peer = GST_RPAD_PEER (int_rpad);
+
+    if (int_peer && GST_PAD_IS_CONNECTED (int_peer)) {
+      res = dispatch (GST_PAD_CAST (int_peer), data);
+      if (res)
+        break;
+    }
+    int_pads = g_list_next (int_pads);
+  }
+
+  g_list_free (orig);
+  
+  return res;
 }
 
 /**
@@ -2301,10 +2429,13 @@ gst_pad_event_default (GstPad *pad, GstEvent *event)
 gboolean
 gst_pad_send_event (GstPad *pad, GstEvent *event)
 {
-  gboolean handled = FALSE;
+  gboolean success = FALSE;
 
   g_return_val_if_fail (event, FALSE);
 
+  if (!pad || (GST_PAD_IS_SINK (pad) && !GST_PAD_IS_CONNECTED (pad))) 
+    return FALSE;
+
   if (GST_EVENT_SRC (event) == NULL)
     GST_EVENT_SRC (event) = gst_object_ref (GST_OBJECT (pad));
 
@@ -2312,17 +2443,166 @@ gst_pad_send_event (GstPad *pad, GstEvent *event)
                  GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
 
   if (GST_RPAD_EVENTFUNC (pad))
-    handled = GST_RPAD_EVENTFUNC (pad) (pad, event);
+    success = GST_RPAD_EVENTFUNC (pad) (pad, event);
   else {
     GST_DEBUG(GST_CAT_EVENT, "there's no event function for pad %s:%s", GST_DEBUG_PAD_NAME (pad));
   }
 
-  if (!handled) {
-    GST_DEBUG(GST_CAT_EVENT, "proceeding with default event behavior here");
-    gst_pad_event_default (pad, event);
-    handled = TRUE;
+  return success;
+}
+
+typedef struct 
+{
+  GstFormat     src_format;
+  gint64        src_value;
+  GstFormat     *dest_format;
+  gint64        *dest_value;
+} GstPadConvertData;
+
+static gboolean
+gst_pad_convert_dispatcher (GstPad *pad, GstPadConvertData *data)
+{
+  return gst_pad_convert (pad, data->src_format, data->src_value, 
+                              data->dest_format, data->dest_value);
+}
+
+/**
+ * gst_pad_convert_default:
+ * @pad: the pad to invoke the default converter on
+ * @src_format: the source format
+ * @src_value: the source value
+ * @dest_format: a pointer to the destination format
+ * @dest_value: a pointer to the destination value
+ *
+ * Invoke the default converter on a pad. This will forward the
+ * call to the pad obtained using the internal connection of
+ * the element.
+ *
+ * Returns: TRUE if the conversion could be performed.
+ */
+gboolean
+gst_pad_convert_default (GstPad *pad, 
+                        GstFormat src_format,  gint64  src_value,
+                        GstFormat *dest_format, gint64 *dest_value)
+{
+  GstPadConvertData data;
+
+  g_return_val_if_fail (pad, FALSE);
+  g_return_val_if_fail (dest_format, FALSE);
+  g_return_val_if_fail (dest_value, FALSE);
+
+  data.src_format = src_format;
+  data.src_value = src_value;
+  data.dest_format = dest_format;
+  data.dest_value = dest_value;
+
+  return gst_pad_dispatcher (pad, (GstPadDispatcherFunc) gst_pad_convert_dispatcher, &data);
+}
+
+/**
+ * gst_pad_convert:
+ * @pad: the pad to invoke the converter on
+ * @src_format: the source format
+ * @src_value: the source value
+ * @dest_format: a pointer to the destination format
+ * @dest_value: a pointer to the destination value
+ *
+ * Invoke a conversion on the pad. 
+ *
+ * Returns: TRUE if the conversion could be performed.
+ */
+gboolean
+gst_pad_convert (GstPad *pad, 
+                GstFormat src_format,  gint64  src_value,
+                GstFormat *dest_format, gint64 *dest_value)
+{
+  GstRealPad *rpad;
+  
+  g_return_val_if_fail (pad, FALSE);
+  g_return_val_if_fail (dest_format, FALSE);
+  g_return_val_if_fail (dest_value, FALSE);
+
+  rpad = GST_PAD_REALIZE (pad);
+
+  g_return_val_if_fail (rpad, FALSE);
+
+  if (GST_RPAD_CONVERTFUNC (rpad)) {
+    return GST_RPAD_CONVERTFUNC (rpad) (GST_PAD_CAST (rpad), src_format, src_value, dest_format, dest_value);
   }
 
-  return handled;
+  return FALSE;
 }
 
+typedef struct 
+{
+  GstPadQueryType type;
+  GstFormat     *format;
+  gint64        *value;
+} GstPadQueryData;
+
+static gboolean
+gst_pad_query_dispatcher (GstPad *pad, GstPadQueryData *data)
+{
+  return gst_pad_query (pad, data->type, data->format, data->value);
+}
+
+/**
+ * gst_pad_query_default:
+ * @pad: the pad to invoke the default query on
+ * @type: the type of query to perform
+ * @format: a pointer to the format of the query
+ * @value: a pointer to the result of the query
+ *
+ * Invoke the default query function on a pad. 
+ *
+ * Returns: TRUE if the query could be performed.
+ */
+gboolean
+gst_pad_query_default (GstPad *pad, GstPadQueryType type,
+                      GstFormat *format,  gint64 *value)
+{
+  GstPadQueryData data;
+
+  g_return_val_if_fail (pad, FALSE);
+  g_return_val_if_fail (format, FALSE);
+  g_return_val_if_fail (value, FALSE);
+
+  data.type = type;
+  data.format = format;
+  data.value = value;
+
+  return gst_pad_dispatcher (pad, (GstPadDispatcherFunc) gst_pad_query_dispatcher, &data);
+}
+
+/**
+ * gst_pad_query:
+ * @pad: the pad to invoke the query on
+ * @type: the type of query to perform
+ * @format: a pointer to the format of the query
+ * @value: a pointer to the result of the query
+ *
+ * Query a pad for one of the available GstPadQuery properties.
+ *
+ * Returns: TRUE if the query could be performed.
+ */
+gboolean
+gst_pad_query (GstPad *pad, GstPadQueryType type,
+              GstFormat *format, gint64 *value) 
+{
+  GstRealPad *rpad;
+  
+  if (pad == NULL)
+    return FALSE;
+
+  g_return_val_if_fail (format, FALSE);
+  g_return_val_if_fail (value, FALSE);
+
+  rpad = GST_PAD_REALIZE (pad);
+
+  g_return_val_if_fail (rpad, FALSE);
+
+  if (GST_RPAD_QUERYFUNC (rpad))
+    return GST_RPAD_QUERYFUNC (rpad) (GST_PAD_CAST (pad), type, format, value);
+
+  return FALSE;
+}
index 285a667..c1808c1 100644 (file)
@@ -112,33 +112,37 @@ typedef struct _GstGhostPadClass GstGhostPadClass;
 
 
 typedef enum {
-  GST_REGION_VOID,
-  GST_REGION_OFFSET_LEN,
-  GST_REGION_TIME_LEN,
-} GstRegionType;
-
-typedef enum {
   GST_PAD_CONNECT_REFUSED = -1,
   GST_PAD_CONNECT_DELAYED =  0,
   GST_PAD_CONNECT_OK      =  1,
   GST_PAD_CONNECT_DONE    =  2,
 } GstPadConnectReturn;
 
+typedef enum {
+  GST_PAD_QUERY_TOTAL,
+  GST_PAD_QUERY_POSITION,
+  GST_PAD_QUERY_LATENCY,
+} GstPadQueryType;
 /* this defines the functions used to chain buffers
  * pad is the sink pad (so the same chain function can be used for N pads)
  * buf is the buffer being passed */
 typedef void                   (*GstPadChainFunction)          (GstPad *pad,GstBuffer *buf);
 typedef GstBuffer*             (*GstPadGetFunction)            (GstPad *pad);
 typedef gboolean               (*GstPadEventFunction)          (GstPad *pad, GstEvent *event);
+typedef gboolean               (*GstPadConvertFunction)        (GstPad *pad, 
+                                                                GstSeekType src_format,  gint64  src_value,
+                                                                GstSeekType *dest_format, gint64 *dest_value);
+typedef gboolean               (*GstPadQueryFunction)          (GstPad *pad, GstPadQueryType type,
+                                                                GstSeekType *format, gint64  *value);
+typedef GList*                 (*GstPadIntConnFunction)        (GstPad *pad);
 
-typedef GstBuffer*             (*GstPadGetRegionFunction)      (GstPad *pad, GstRegionType type, 
-                                                                guint64 offset, guint64 len);
-typedef GstBuffer*             (*GstPadPullRegionFunction)     (GstPad *pad, GstRegionType type, 
-                                                                guint64 offset, guint64 len);
 typedef GstPadConnectReturn    (*GstPadConnectFunction)        (GstPad *pad, GstCaps *caps);
 typedef GstCaps*               (*GstPadGetCapsFunction)        (GstPad *pad, GstCaps *caps);
 typedef GstBufferPool*         (*GstPadBufferPoolFunction)     (GstPad *pad);
 
+typedef gboolean               (*GstPadDispatcherFunc)         (GstPad *pad, gpointer data);
+
 typedef enum {
   GST_PAD_UNKNOWN,
   GST_PAD_SRC,
@@ -178,10 +182,6 @@ struct _GstRealPad {
   GstRealPad                   *peer;
 
   GstBuffer                    *bufpen;
-  /* CR1: FIXME: regiontype should go away */
-  GstRegionType                regiontype;
-  guint64                      offset;
-  guint64                      len;
 
   GstPadChainFunction          chainfunc;
   GstPadChainFunction          chainhandler;
@@ -190,9 +190,9 @@ struct _GstRealPad {
 
   GstPadEventFunction          eventfunc;
   GstPadEventFunction          eventhandler;
-
-  GstPadGetRegionFunction      getregionfunc;
-  GstPadPullRegionFunction     pullregionfunc;
+  GstPadConvertFunction                convertfunc;
+  GstPadQueryFunction          queryfunc;
+  GstPadIntConnFunction                intconnfunc;
 
   GstPadGetCapsFunction        getcapsfunc;
   GstPadConnectFunction        connectfunc;
@@ -247,18 +247,14 @@ struct _GstGhostPadClass {
 #define GST_RPAD_GETHANDLER(pad)       (((GstRealPad *)(pad))->gethandler)
 #define GST_RPAD_EVENTFUNC(pad)                (((GstRealPad *)(pad))->eventfunc)
 #define GST_RPAD_EVENTHANDLER(pad)     (((GstRealPad *)(pad))->eventhandler)
-
-#define GST_RPAD_GETREGIONFUNC(pad)    (((GstRealPad *)(pad))->getregionfunc)
-#define GST_RPAD_PULLREGIONFUNC(pad)   (((GstRealPad *)(pad))->pullregionfunc)
+#define GST_RPAD_CONVERTFUNC(pad)      (((GstRealPad *)(pad))->convertfunc)
+#define GST_RPAD_QUERYFUNC(pad)                (((GstRealPad *)(pad))->queryfunc)
+#define GST_RPAD_INTCONNFUNC(pad)      (((GstRealPad *)(pad))->intconnfunc)
 
 #define GST_RPAD_CONNECTFUNC(pad)      (((GstRealPad *)(pad))->connectfunc)
 #define GST_RPAD_GETCAPSFUNC(pad)      (((GstRealPad *)(pad))->getcapsfunc)
 #define GST_RPAD_BUFFERPOOLFUNC(pad)   (((GstRealPad *)(pad))->bufferpoolfunc)
 
-#define GST_RPAD_REGIONTYPE(pad)       (((GstRealPad *)(pad))->regiontype)
-#define GST_RPAD_OFFSET(pad)           (((GstRealPad *)(pad))->offset)
-#define GST_RPAD_LEN(pad)              (((GstRealPad *)(pad))->len)
-
 /* GstGhostPad */
 #define GST_GPAD_REALPAD(pad)          (((GstGhostPad *)(pad))->realpad)
 
@@ -342,17 +338,20 @@ GType                     gst_pad_get_type                        (void);
 GType                  gst_real_pad_get_type                   (void);
 GType                  gst_ghost_pad_get_type                  (void);
 
-GstPad*                        gst_pad_new                             (gchar *name, GstPadDirection direction);
+GstPad*                        gst_pad_new                             (const gchar *name, GstPadDirection direction);
 #define                        gst_pad_destroy(pad)                    gst_object_destroy (GST_OBJECT (pad))
-GstPad*                        gst_pad_new_from_template               (GstPadTemplate *templ, gchar *name);
+GstPad*                        gst_pad_new_from_template               (GstPadTemplate *templ, const gchar *name);
+GstPad*                        gst_pad_custom_new                      (GType type, const gchar *name, GstPadDirection direction);
+GstPad*                        gst_pad_custom_new_from_template        (GType type, GstPadTemplate *templ, const gchar *name);
 
 GstPadDirection                gst_pad_get_direction                   (GstPad *pad);
 
 void                   gst_pad_set_chain_function              (GstPad *pad, GstPadChainFunction chain);
 void                   gst_pad_set_get_function                (GstPad *pad, GstPadGetFunction get);
 void                   gst_pad_set_event_function              (GstPad *pad, GstPadEventFunction event);
-
-void                   gst_pad_set_getregion_function          (GstPad *pad, GstPadGetRegionFunction getregion);
+void                   gst_pad_set_convert_function            (GstPad *pad, GstPadConvertFunction convert);
+void                   gst_pad_set_query_function              (GstPad *pad, GstPadQueryFunction query);
+void                   gst_pad_set_internal_connection_function        (GstPad *pad, GstPadIntConnFunction intconn);
 
 void                   gst_pad_set_connect_function            (GstPad *pad, GstPadConnectFunction connect);
 void                   gst_pad_set_getcaps_function            (GstPad *pad, GstPadGetCapsFunction getcaps);
@@ -411,22 +410,33 @@ void                      gst_pad_push                            (GstPad *pad, GstBuffer *buf);
 #endif
 #if 1
 GstBuffer*             gst_pad_pull                            (GstPad *pad);
-GstBuffer*             gst_pad_pullregion                      (GstPad *pad, GstRegionType type, 
-                                                                guint64 offset, guint64 len);
 #else
 #define gst_pad_pull(pad) \
   ( (((GstRealPad *)(pad))->peer->gethandler) ? \
 (((GstRealPad *)(pad))->peer->gethandler)((GstPad *)(((GstRealPad *)(pad))->peer)) : \
 NULL )
-#define gst_pad_pullregion(pad,type,offset,len) \
-  ( (((GstRealPad *)(pad))->peer->pullregionfunc) ? \
-(((GstRealPad *)(pad))->peer->pullregionfunc)((GstPad *)(((GstRealPad *)(pad))->peer),(type),(offset),(len)) : \
-NULL )
 #endif
 
 gboolean               gst_pad_send_event                      (GstPad *pad, GstEvent *event);
-void                   gst_pad_event_default                   (GstPad *pad, GstEvent *event);
-
+gboolean               gst_pad_event_default                   (GstPad *pad, GstEvent *event);
+
+gboolean               gst_pad_convert                         (GstPad *pad, 
+                                                                GstFormat src_format,  gint64  src_value,
+                                                                GstFormat *dest_format, gint64 *dest_value);
+gboolean               gst_pad_convert_default                 (GstPad *pad,
+                                                                GstFormat src_format,  gint64  src_value,
+                                                                GstFormat *dest_format, gint64 *dest_value);
+
+gboolean               gst_pad_query                           (GstPad *pad, GstPadQueryType type,
+                                                                GstFormat *format, gint64 *value);
+gboolean               gst_pad_query_default                   (GstPad *pad, GstPadQueryType type,
+                                                                GstFormat *format, gint64 *value);
+
+GList*                 gst_pad_get_internal_connections        (GstPad *pad);
+GList*                 gst_pad_get_internal_connections_default (GstPad *pad);
+       
+gboolean               gst_pad_dispatcher                      (GstPad *pad, GstPadDispatcherFunc dispatch, 
+                                                                gpointer data);
 
 
 GstBuffer*             gst_pad_peek                            (GstPad *pad);
index 11b3e9c..32b6cb4 100644 (file)
@@ -82,9 +82,13 @@ static void                  gst_queue_chain                 (GstPad *pad, GstBuffer *buf);
 static GstBuffer *             gst_queue_get                   (GstPad *pad);
 static GstBufferPool*          gst_queue_get_bufferpool        (GstPad *pad);
        
-static void                    gst_queue_locked_flush                  (GstQueue *queue);
+static gboolean                gst_queue_handle_src_event      (GstPad *pad, GstEvent *event);
+
+
+static void                    gst_queue_locked_flush          (GstQueue *queue);
 
 static GstElementStateReturn   gst_queue_change_state          (GstElement *element);
+static gboolean                        gst_queue_release_locks         (GstElement *element);
 
   
 #define GST_TYPE_QUEUE_LEAKY (queue_leaky_get_type())
@@ -157,7 +161,8 @@ gst_queue_class_init (GstQueueClass *klass)
   gobject_class->set_property          = GST_DEBUG_FUNCPTR (gst_queue_set_property);
   gobject_class->get_property          = GST_DEBUG_FUNCPTR (gst_queue_get_property);
 
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
+  gstelement_class->change_state  = GST_DEBUG_FUNCPTR(gst_queue_change_state);
+  gstelement_class->release_locks = GST_DEBUG_FUNCPTR(gst_queue_release_locks);
 }
 
 static GstPadConnectReturn
@@ -207,6 +212,7 @@ gst_queue_init (GstQueue *queue)
   gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
   gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
   gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
+  gst_pad_set_event_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_handle_src_event));
 
   queue->leaky = GST_QUEUE_NO_LEAK;
   queue->queue = NULL;
@@ -301,6 +307,9 @@ restart:
        GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "eos in on %s %d\n", 
                           GST_ELEMENT_NAME (queue), queue->level_buffers);
        break;
+      case GST_EVENT_DISCONTINUOUS:
+        //gst_queue_locked_flush (queue);
+       break;
       default:
        /*gst_pad_event_default (pad, GST_EVENT (buf)); */
        break;
@@ -350,7 +359,8 @@ restart:
     while (queue->level_buffers == queue->size_buffers) {
       /* if there's a pending state change for this queue or its manager, switch */
       /* back to iterator so bottom half of state change executes */
-      while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
+      //while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
+      if (queue->interrupt) {
         GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
         g_mutex_unlock (queue->qlock);
        if (gst_element_interrupt (GST_ELEMENT (queue)))
@@ -435,7 +445,8 @@ restart:
     /* if there's a pending state change for this queue or its manager, switch
      * back to iterator so bottom half of state change executes
      */ 
-    while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
+    //while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
+    if (queue->interrupt) {
       GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
       g_mutex_unlock (queue->qlock);
       if (gst_element_interrupt (GST_ELEMENT (queue)))
@@ -507,6 +518,51 @@ restart:
   return buf;
 }
 
+
+static gboolean
+gst_queue_handle_src_event (GstPad *pad, GstEvent *event)
+{
+  GstQueue *queue;
+
+  queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+  g_mutex_lock (queue->qlock);
+
+  if (gst_element_get_state (GST_ELEMENT (queue)) == GST_STATE_PLAYING) {
+    g_warning ("queue event in playing state");
+  }
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH:
+      GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "FLUSH event, flushing queue\n");
+      gst_queue_locked_flush (queue);
+      break;
+    case GST_EVENT_SEEK:
+      gst_queue_locked_flush (queue);
+    default:
+      gst_pad_event_default (pad, event); 
+      break;
+  }
+  g_mutex_unlock (queue->qlock);
+  return TRUE;
+}
+
+static gboolean
+gst_queue_release_locks (GstElement *element)
+{
+  GstQueue *queue;
+
+  queue = GST_QUEUE (element);
+
+  g_mutex_lock (queue->qlock);
+  queue->interrupt = TRUE;
+  g_cond_signal (queue->not_full);
+  g_cond_signal (queue->not_empty); 
+  g_mutex_unlock (queue->qlock);
+
+  return TRUE;
+}
+
 static GstElementStateReturn
 gst_queue_change_state (GstElement *element)
 {
@@ -543,6 +599,7 @@ gst_queue_change_state (GstElement *element)
 
       return GST_STATE_FAILURE;
     }
+    queue->interrupt = FALSE;
   }
 
   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
index 6122d2a..e3ab5bd 100644 (file)
@@ -75,6 +75,7 @@ struct _GstQueue {
 
   gint leaky;          /* whether the queue is leaky, and if so at which end */
   gboolean may_deadlock; /* it the queue should fail on possible deadlocks */
+  gboolean interrupt;
 
   GMutex *qlock;       /* lock for queue (vs object lock) */
   /* we are single reader and single writer queue */
index 46de9a5..0291bbc 100644 (file)
@@ -548,12 +548,13 @@ gst_scheduler_auto_clock (GstScheduler *sched)
  * Returns: the status of the operation
  */
 GstClockReturn
-gst_scheduler_clock_wait (GstScheduler *sched, GstElement *element, GstClock *clock, GstClockTime time)
+gst_scheduler_clock_wait (GstScheduler *sched, GstElement *element, GstClock *clock, GstClockTime time,
+               GstClockTimeDiff *jitter)
 {
   g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_CLOCK_ERROR);
 
   if (CLASS (sched)->clock_wait)
-    return CLASS (sched)->clock_wait (sched, element, clock, time);
+    return CLASS (sched)->clock_wait (sched, element, clock, time, jitter);
 
   return GST_CLOCK_TIMEOUT;
 }
index ba61ffe..7006d02 100644 (file)
@@ -100,7 +100,7 @@ struct _GstSchedulerClass {
   void                         (*pad_disconnect)       (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
   void                         (*pad_select)           (GstScheduler *sched, GList *padlist);
   GstClockReturn       (*clock_wait)           (GstScheduler *sched, GstElement *element,
-                                                GstClock *clock, GstClockTime time);
+                                                GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter);
   GstSchedulerState    (*iterate)              (GstScheduler *sched);
   /* for debugging */
   void                         (*show)                 (GstScheduler *sched);
@@ -129,7 +129,7 @@ void                        gst_scheduler_pad_connect       (GstScheduler *sched, GstPad *srcpad, GstPad *s
 void                   gst_scheduler_pad_disconnect    (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
 GstPad*                 gst_scheduler_pad_select       (GstScheduler *sched, GList *padlist);
 GstClockReturn         gst_scheduler_clock_wait        (GstScheduler *sched, GstElement *element,
-                                                        GstClock *clock, GstClockTime time);
+                                                        GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter);
 gboolean               gst_scheduler_iterate           (GstScheduler *sched);
 
 void                   gst_scheduler_use_clock         (GstScheduler *sched, GstClock *clock);
index 9786483..8ea28b0 100644 (file)
@@ -108,14 +108,16 @@ static GstClockTime
 gst_system_clock_get_internal_time (GstClock *clock)
 {
   GTimeVal timeval;
+
   g_get_current_time (&timeval);
+  
   return GST_TIMEVAL_TO_TIME (timeval);
 }
 
 static guint64
 gst_system_clock_get_resolution (GstClock *clock)
 {
-  return 1;
+  return 1 * GST_USECOND;
 }
 
 
index 58fe4ec..072d97d 100644 (file)
@@ -318,7 +318,7 @@ gst_thread_change_state (GstElement * element)
        * to perform each elements' change_state() (by calling gstbin.c::
        * change_state()).
        * + the pending state was already set by gstelement.c::set_state()
-       * + find every queue we manage, and signal its empty and full conditions
+       * + unlock all elements so the bottom half can start the state change.
        */ 
       g_mutex_lock (thread->lock);
 
@@ -326,65 +326,45 @@ gst_thread_change_state (GstElement * element)
 
       while (elements) {
        GstElement *element = GST_ELEMENT (elements->data);
+       GList *pads;
+       
 
        g_assert (element);
-       THR_DEBUG ("  element \"%s\"", GST_ELEMENT_NAME (element));
+       THR_DEBUG ("  waking element \"%s\"", GST_ELEMENT_NAME (element));
        elements = g_list_next (elements);
-       if (GST_IS_QUEUE (element)) {
-          GstQueue *queue = GST_QUEUE (element);
-  /* FIXME make this more efficient by only waking queues that are asleep
-   *  FIXME and only waking the appropriate condition (depending on if it's
-   *  FIXME on up- or down-stream side)
-   * FIXME also make this more efficient by keeping list of managed queues
-   */
-         THR_DEBUG ("waking queue \"%s\"", GST_ELEMENT_NAME (element));
-         g_mutex_lock (queue->qlock);
-         GST_STATE_PENDING (element) = GST_STATE_PAUSED;
-         g_cond_signal (queue->not_full);
-         g_cond_signal (queue->not_empty);
-         g_mutex_unlock (queue->qlock);
-       }
-       else {
-         GList *pads = GST_ELEMENT_PADS (element);
 
-         while (pads) {
-           GstRealPad *peer = GST_REAL_PAD (GST_PAD_PEER (pads->data));
-           GstElement *peerelement;
+       if (!gst_element_release_locks (element)) {
+          g_warning ("element %s could not release locks", GST_ELEMENT_NAME (element));
+       }
 
-           pads = g_list_next (pads);
+       pads = GST_ELEMENT_PADS (element);
 
-           if (!peer)
-             continue;
+       while (pads) {
+         GstRealPad *peer = GST_REAL_PAD (GST_PAD_PEER (pads->data));
+         GstElement *peerelement;
 
-           peerelement = GST_PAD_PARENT (peer);
-           if (!peerelement)
-             continue;         /* deal with case where there's no peer */
+         pads = g_list_next (pads);
 
-           if (!GST_FLAG_IS_SET (peerelement, GST_ELEMENT_DECOUPLED)) {
-             GST_DEBUG (GST_CAT_THREAD, "peer element isn't DECOUPLED");
-             continue;
-           }
+         if (!peer)
+           continue;
 
-           /* FIXME this needs to go away eventually */
-           if (!GST_IS_QUEUE (peerelement)) {
-             GST_DEBUG (GST_CAT_THREAD, "peer element isn't a Queue");
-             continue;
-           }
+         peerelement = GST_PAD_PARENT (peer);
+         if (!peerelement)
+           continue;           /* deal with case where there's no peer */
 
-           if (GST_ELEMENT_SCHED (peerelement) != GST_ELEMENT_SCHED (thread)) {
-             GstQueue *queue = GST_QUEUE (peerelement);
+         if (!GST_FLAG_IS_SET (peerelement, GST_ELEMENT_DECOUPLED)) {
+           GST_DEBUG (GST_CAT_THREAD, "peer element isn't DECOUPLED");
+           continue;
+         }
 
-             THR_DEBUG ("  element \"%s\" has pad cross sched boundary", GST_ELEMENT_NAME (element));
-             /* FIXME!! */
-             g_mutex_lock (queue->qlock);
-             g_cond_signal (queue->not_full);
-             g_cond_signal (queue->not_empty);
-             g_mutex_unlock (queue->qlock);
+         if (GST_ELEMENT_SCHED (peerelement) != GST_ELEMENT_SCHED (thread)) {
+           THR_DEBUG ("  element \"%s\" has pad cross sched boundary", GST_ELEMENT_NAME (element));
+           if (!gst_element_release_locks (element)) {
+              g_warning ("element %s could not release locks", GST_ELEMENT_NAME (element));
            }
          }
        }
 
-        gst_element_disable_threadsafe_properties (element);
       }
       THR_DEBUG ("telling thread to pause, signaling");
       g_cond_signal (thread->cond);
@@ -392,6 +372,12 @@ gst_thread_change_state (GstElement * element)
       g_cond_wait (thread->cond, thread->lock);
       THR_DEBUG ("got ack");
       g_mutex_unlock (thread->lock);
+
+      elements = gst_bin_get_list (GST_BIN (thread));
+      while (elements) {
+        gst_element_disable_threadsafe_properties ((GstElement*)elements->data);
+        elements = g_list_next (elements);
+      }
       break;
     }
     case GST_STATE_READY_TO_NULL:
index 826d018..ff150e6 100644 (file)
@@ -88,14 +88,14 @@ struct _GstTimeCache {
 GType                  gst_time_cache_get_type         (void);
 GstTimeCache*          gst_time_cache_new              (void);
 
-gint                   gst_time_cache_get_group                (GstTimeCache *tc);
-gint                   gst_time_cache_new_group                (GstTimeCache *tc);
-gboolean               gst_time_cache_set_group                (GstTimeCache *tc, gint groupnum);
+gint                   gst_time_cache_get_group        (GstTimeCache *tc);
+gint                   gst_time_cache_new_group        (GstTimeCache *tc);
+gboolean               gst_time_cache_set_group        (GstTimeCache *tc, gint groupnum);
 
 void                   gst_time_cache_set_certainty    (GstTimeCache *tc, GstTimeCacheCertainty certainty);
 GstTimeCacheCertainty  gst_time_cache_get_certainty    (GstTimeCache *tc);
 
-void                   gst_time_cache_add_entry                (GstTimeCache *tc, guint64 location, gint64 timestamp);
+void                   gst_time_cache_add_entry        (GstTimeCache *tc, guint64 location, gint64 timestamp);
 
 gboolean               gst_time_cache_find_location    (GstTimeCache *tc, guint64 location, gint64 *timestamp);
 gboolean               gst_time_cache_find_timestamp   (GstTimeCache *tc, gint64 timestamp, guint64 *location);
index 54acaf1..5595ab5 100644 (file)
@@ -29,5 +29,10 @@ typedef enum {
   GST_STATE_ASYNC               = 2,
 } GstElementStateReturn;
 
+typedef enum {
+  GST_RESULT_OK,
+  GST_RESULT_NOK,
+  GST_RESULT_NOT_IMPL,
+} GstResult;
 
 #endif
index c2bb846..94c2a8d 100644 (file)
@@ -117,7 +117,7 @@ static void         gst_basic_scheduler_pad_connect         (GstScheduler *sched, GstPad *
 static void            gst_basic_scheduler_pad_disconnect      (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
 static GstPad*         gst_basic_scheduler_pad_select          (GstScheduler *sched, GList *padlist);
 static GstClockReturn  gst_basic_scheduler_clock_wait          (GstScheduler *sched, GstElement *element,
-                                                                GstClock *clock, GstClockTime time);
+                                                                GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter);
 static GstSchedulerState
                        gst_basic_scheduler_iterate             (GstScheduler *sched);
 
@@ -289,7 +289,6 @@ gst_basic_scheduler_chain_wrapper (int argc, char *argv[])
        buf = gst_pad_pull (pad);
        if (buf) {
          if (GST_IS_EVENT (buf) && !GST_ELEMENT_IS_EVENT_AWARE (element)) {
-           /*gst_pad_event_default (pad, GST_EVENT (buf)); */
            gst_pad_send_event (pad, GST_EVENT (buf));
          }
          else {
@@ -299,12 +298,6 @@ gst_basic_scheduler_chain_wrapper (int argc, char *argv[])
            GST_DEBUG (GST_CAT_DATAFLOW, "calling chain function of element %s done", name);
          }
        }
-       /* 
-       else {
-          gst_element_error (element, "NULL buffer detected. Is \"%s:%s\" connected?",
-                         name, GST_PAD_NAME (pad), NULL);
-       }
-       */
       }
     }
   } while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
@@ -341,27 +334,13 @@ gst_basic_scheduler_src_wrapper (int argc, char *argv[])
       pads = g_list_next (pads);
       if (GST_RPAD_DIRECTION (realpad) == GST_PAD_SRC) {
        GST_DEBUG (GST_CAT_DATAFLOW, "calling _getfunc for %s:%s", GST_DEBUG_PAD_NAME (realpad));
-       if (realpad->regiontype != GST_REGION_VOID) {
-         g_return_val_if_fail (GST_RPAD_GETREGIONFUNC (realpad) != NULL, 0);
-/*          if (GST_RPAD_GETREGIONFUNC(realpad) == NULL)                  */   
-/*            fprintf(stderr,"error, no getregionfunc in \"%s\"\n", name); */
-/*          else                                                          */
-         buf =
-           (GST_RPAD_GETREGIONFUNC (realpad)) (GST_PAD_CAST (realpad), realpad->regiontype,
-                                               realpad->offset, realpad->len);
-         realpad->regiontype = GST_REGION_VOID;
-       }
-       else {
-         g_return_val_if_fail (GST_RPAD_GETFUNC (realpad) != NULL, 0);
-/*          if (GST_RPAD_GETFUNC(realpad) == NULL)                     */
-/*            fprintf(stderr,"error, no getfunc in \"%s\"\n", name);   */
-/*          else                                                       */
-         buf = GST_RPAD_GETFUNC (realpad) (GST_PAD_CAST (realpad));
+       g_return_val_if_fail (GST_RPAD_GETFUNC (realpad) != NULL, 0);
+       buf = GST_RPAD_GETFUNC (realpad) (GST_PAD_CAST (realpad));
+       if (buf) {
+         GST_DEBUG (GST_CAT_DATAFLOW, "calling gst_pad_push on pad %s:%s",
+                    GST_DEBUG_PAD_NAME (realpad));
+         gst_pad_push (GST_PAD_CAST (realpad), buf);
        }
-
-       GST_DEBUG (GST_CAT_DATAFLOW, "calling gst_pad_push on pad %s:%s",
-                  GST_DEBUG_PAD_NAME (realpad));
-       gst_pad_push (GST_PAD_CAST (realpad), buf);
       }
     }
   } while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
@@ -483,46 +462,6 @@ gst_basic_scheduler_gethandler_proxy (GstPad * pad)
   return buf;
 }
 
-static GstBuffer *
-gst_basic_scheduler_pullregionfunc_proxy (GstPad * pad, GstRegionType type, guint64 offset, guint64 len)
-{
-  GstBuffer *buf;
-  GstElement *parent;
-  GstRealPad *peer;
-
-  parent = GST_PAD_PARENT (pad);
-  peer = GST_RPAD_PEER (pad);
-
-  GST_DEBUG_ENTER ("%s:%s,%d,%lld,%lld", GST_DEBUG_PAD_NAME (pad), type, offset, len);
-
-  /* put the region info into the pad */
-  GST_RPAD_REGIONTYPE (pad) = type;
-  GST_RPAD_OFFSET (pad) = offset;
-  GST_RPAD_LEN (pad) = len;
-
-  /* FIXME this should be bounded */
-  /* we will loop switching to the peer until it's filled up the bufferpen */
-  while (GST_RPAD_BUFPEN (pad) == NULL) {
-    GST_DEBUG (GST_CAT_DATAFLOW, "switching to %p to fill bufpen",
-              GST_ELEMENT_THREADSTATE (parent));
-
-    do_element_switch (parent);
-
-    /* we may no longer be the same pad, check. */
-    if (GST_RPAD_PEER (peer) != (GstRealPad *) pad) {
-      GST_DEBUG (GST_CAT_DATAFLOW, "new pad in mid-switch!");
-      pad = (GstPad *) GST_RPAD_PEER (peer);
-    }
-  }
-  GST_DEBUG (GST_CAT_DATAFLOW, "done switching");
-
-  /* now grab the buffer from the pen, clear the pen, and return the buffer */
-  buf = GST_RPAD_BUFPEN (pad);
-  GST_RPAD_BUFPEN (pad) = NULL;
-  return buf;
-}
-
-
 static gboolean
 gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
 {
@@ -607,7 +546,6 @@ gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
          GST_DEBUG (GST_CAT_SCHEDULING, "copying get function into pull proxy for %s:%s",
                     GST_DEBUG_PAD_NAME (pad));
          GST_RPAD_GETHANDLER (pad) = GST_RPAD_GETFUNC (pad);
-         GST_RPAD_PULLREGIONFUNC (pad) = GST_RPAD_GETREGIONFUNC (pad);
        }
 
       }
@@ -622,7 +560,6 @@ gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
          GST_DEBUG (GST_CAT_SCHEDULING, "setting cothreaded pull proxy for srcpad %s:%s",
             GST_DEBUG_PAD_NAME (pad));
          GST_RPAD_GETHANDLER (pad) = GST_DEBUG_FUNCPTR (gst_basic_scheduler_gethandler_proxy);
-         GST_RPAD_PULLREGIONFUNC (pad) = GST_DEBUG_FUNCPTR (gst_basic_scheduler_pullregionfunc_proxy);
        }
       }
     }
@@ -1116,10 +1053,12 @@ gst_basic_scheduler_yield (GstScheduler *sched, GstElement *element)
 static gboolean
 gst_basic_scheduler_interrupt (GstScheduler *sched, GstElement *element)
 {
+  GstElement *current = SCHED (element)->current;
+        
   GST_FLAG_SET (element, GST_ELEMENT_COTHREAD_STOPPING);
 
-  if (element->post_run_func)
-    element->post_run_func (element);
+  if (current->post_run_func)
+    current->post_run_func (current);
 
   SCHED (element)->current = NULL;
   do_cothread_switch (do_cothread_get_main (((GstBasicScheduler *) sched)->context));
@@ -1257,9 +1196,9 @@ gst_basic_scheduler_pad_select (GstScheduler * sched, GList * padlist)
 
 static GstClockReturn
 gst_basic_scheduler_clock_wait (GstScheduler *sched, GstElement *element,
-                               GstClock *clock, GstClockTime time)
+                               GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
 {
-  return gst_clock_wait (clock, time);
+  return gst_clock_wait (clock, time, jitter);
 }
 
 static GstSchedulerState
index 0218100..6a20cb8 100644 (file)
@@ -58,6 +58,7 @@ gst_bytestream_new (GstPad * pad)
   bs->listavail = 0;
   bs->assembled = NULL;
   bs->offset = 0LL;
+  bs->in_seek = FALSE;
 
   return bs;
 }
@@ -122,7 +123,9 @@ gst_bytestream_get_next_buf (GstByteStream * bs)
   GstBuffer *nextbuf, *lastbuf, *headbuf;
   GSList *end;
 
-  g_assert (!bs->event);
+  /* if there is an event pending, return FALSE */
+  if (bs->event)
+    return FALSE;
 
   bs_print ("get_next_buf: pulling buffer");
   nextbuf = gst_pad_pull (bs->pad);
@@ -429,33 +432,30 @@ gst_bytestream_flush_fast (GstByteStream * bs, guint32 len)
 }
 
 gboolean
-gst_bytestream_seek (GstByteStream *bs, GstSeekType type, gint64 offset)
+gst_bytestream_seek (GstByteStream *bs, gint64 offset, GstSeekType method)
 {
-  GstRealPad *peer = GST_RPAD_PEER (bs->pad);
-  guint32 waiting;
-  GstEvent *event = NULL;
-  GstBuffer *headbuf;
-
-  if (gst_pad_send_event (GST_PAD (peer), gst_event_new_seek (type, offset, TRUE))) {
-    
+  GstRealPad *peer;
+  
+  g_return_val_if_fail (bs != NULL, FALSE);
+  
+  peer = GST_RPAD_PEER (bs->pad);
+
+  bs_print ("bs: send event\n");
+  if (gst_pad_send_event (GST_PAD (peer), gst_event_new_seek (
+                                 GST_FORMAT_BYTES | 
+                                 (method & GST_SEEK_METHOD_MASK) | 
+                                 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, 
+                                 offset))) 
+  {
     gst_bytestream_flush_fast (bs, bs->listavail);
 
-    while (!gst_bytestream_get_next_buf(bs)) {
-      gst_bytestream_get_status(bs, &waiting, &event);
-
-      /* it is valid for a seek to cause eos, so lets say it succeeded */
-      if (GST_EVENT_TYPE(event) == GST_EVENT_EOS){
-        bs->offset = 0LL;
-        return TRUE;
-      }
-    }
-
-    headbuf = GST_BUFFER (bs->buflist->data);
-    /* we have a new offset */
-    bs->offset = GST_BUFFER_OFFSET(headbuf);
+    /* we set the seek flag here. We cannot pull the pad here
+     * bacause a seek might occur outisde of the pads cothread context */
+    bs->in_seek = TRUE;
     
     return TRUE;
   }
+  bs_print ("bs: send event failed\n");
   return FALSE;
 }
 
index 051482b..3f12866 100644 (file)
@@ -43,6 +43,9 @@ struct _GstByteStream {
 
   /* this is needed for gst_bytestream_tell */
   guint64      offset;
+
+  /* if we are in the seek state (waiting for DISCONT) */
+  gboolean     in_seek;
 };
 
 GstByteStream*         gst_bytestream_new              (GstPad *pad);
@@ -50,7 +53,7 @@ void                  gst_bytestream_destroy          (GstByteStream *bs);
 
 guint32                        gst_bytestream_read             (GstByteStream *bs, GstBuffer** buf, guint32 len);
 guint64                        gst_bytestream_tell             (GstByteStream *bs);
-gboolean               gst_bytestream_seek             (GstByteStream *bs, GstSeekType type, gint64 offset);
+gboolean               gst_bytestream_seek             (GstByteStream *bs, gint64 offset, GstSeekType type);
 guint32                        gst_bytestream_peek             (GstByteStream *bs, GstBuffer** buf, guint32 len);
 guint32                        gst_bytestream_peek_bytes       (GstByteStream *bs, guint8** data, guint32 len);
 gboolean               gst_bytestream_flush            (GstByteStream *bs, guint32 len);
index a9b1276..83a24a6 100644 (file)
@@ -149,6 +149,8 @@ gst_fakesink_init (GstFakeSink *fakesink)
   fakesink->last_message = NULL;
 
   GST_ELEMENT (fakesink)->setclockfunc    = gst_fakesink_set_clock;
+
+  GST_FLAG_SET (fakesink, GST_ELEMENT_EVENT_AWARE);
 }
 
 static void
@@ -251,8 +253,26 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
 
   fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
 
-  if (fakesink->sync) { 
-    gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf));
+  if (GST_IS_EVENT (buf)) {
+    GstEvent *event = GST_EVENT (buf);
+         
+    switch (GST_EVENT_TYPE (event)) {
+      case GST_EVENT_DISCONTINUOUS:
+        if (fakesink->sync && fakesink->clock) { 
+          gint64 value = GST_EVENT_DISCONT_OFFSET (event, 0).value;
+          gst_clock_handle_discont (fakesink->clock, value);
+       }
+      default:
+       gst_pad_event_default (pad, event);
+        break;
+    }
+
+    gst_event_free (event);
+    return;
+  }
+
+  if (fakesink->sync && fakesink->clock) { 
+    gst_element_clock_wait (GST_ELEMENT (fakesink), fakesink->clock, GST_BUFFER_TIMESTAMP (buf), NULL);
   }
 
   if (!fakesink->silent) { 
index 83474cf..bace80d 100644 (file)
@@ -322,7 +322,7 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
     case GST_EVENT_SEEK:
       src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
 
-      if (!GST_EVENT_SEEK_FLUSH (event)) {
+      if (!GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
         gst_event_free (event);
         break;
       }
index 9b3cd23..a87e00c 100644 (file)
@@ -271,24 +271,29 @@ gst_filesink_handle_event (GstPad *pad, GstEvent *event)
   switch (type) {
     case GST_EVENT_SEEK:
       /* we need to seek */
-      if (GST_EVENT_SEEK_FLUSH(event))
+      if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH)
         if (fflush(filesink->file))
           gst_element_error(GST_ELEMENT(filesink),
             "Error flushing the buffer cache of file \'%s\' to disk: %s",
             gst_filesink_getcurrentfilename(filesink), sys_errlist[errno]);
-      switch (GST_EVENT_SEEK_TYPE(event))
+
+      if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
+        g_warning("Any other then byte-offset seeking is not supported!\n");
+      }
+
+      switch (GST_EVENT_SEEK_METHOD(event))
       {
-        case GST_SEEK_BYTEOFFSET_SET:
+        case GST_SEEK_METHOD_SET:
           fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_SET);
           break;
-        case GST_SEEK_BYTEOFFSET_CUR:
+        case GST_SEEK_METHOD_CUR:
           fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_CUR);
           break;
-        case GST_SEEK_BYTEOFFSET_END:
+        case GST_SEEK_METHOD_END:
           fseek(filesink->file, GST_EVENT_SEEK_OFFSET(event), SEEK_END);
           break;
         default:
-          g_warning("Any other then byte-offset seeking is not supported!\n");
+          g_warning("unkown seek method!\n");
           break;
       }
       break;
index 4671033..6b885fb 100644 (file)
@@ -110,6 +110,8 @@ static void         gst_filesrc_get_property        (GObject *object, guint prop_id,
 
 static GstBuffer *     gst_filesrc_get                 (GstPad *pad);
 static gboolean        gst_filesrc_srcpad_event        (GstPad *pad, GstEvent *event);
+static gboolean        gst_filesrc_srcpad_query        (GstPad *pad, GstPadQueryType type,
+                                                        GstSeekType *format, gint64 *value);
 
 static GstElementStateReturn   gst_filesrc_change_state        (GstElement *element);
 
@@ -184,8 +186,9 @@ static void
 gst_filesrc_init (GstFileSrc *src)
 {
   src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
-  gst_pad_set_get_function (src->srcpad,gst_filesrc_get);
-  gst_pad_set_event_function (src->srcpad,gst_filesrc_srcpad_event);
+  gst_pad_set_get_function (src->srcpad, gst_filesrc_get);
+  gst_pad_set_event_function (src->srcpad, gst_filesrc_srcpad_event);
+  gst_pad_set_query_function (src->srcpad, gst_filesrc_srcpad_query);
   gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
 
   src->pagesize = getpagesize();
@@ -201,7 +204,7 @@ gst_filesrc_init (GstFileSrc *src)
   src->mapbuf = NULL;
   src->mapsize = 4 * 1024 * 1024;              /* default is 4MB */
 
-  src->map_regions = g_tree_new(gst_filesrc_bufcmp);
+  src->map_regions = g_tree_new (gst_filesrc_bufcmp);
   src->map_regions_lock = g_mutex_new();
 
   src->seek_happened = FALSE;
@@ -445,12 +448,19 @@ gst_filesrc_get (GstPad *pad)
 
   /* check for seek */
   if (src->seek_happened) {
+    GstEvent *event;
+
     src->seek_happened = FALSE;
-    return GST_BUFFER (gst_event_new (GST_EVENT_DISCONTINUOUS));
+    GST_DEBUG (GST_CAT_EVENT, "filesrc sending discont\n");
+    event = gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, src->curoffset, NULL);
+    GST_EVENT_DISCONT_FLUSH (event) = src->need_flush;
+    src->need_flush = FALSE;
+    return GST_BUFFER (event);
   }
   /* check for flush */
   if (src->need_flush) {
     src->need_flush = FALSE;
+    GST_DEBUG (GST_CAT_EVENT, "filesrc sending flush\n");
     return GST_BUFFER (gst_event_new_flush ());
   }
 
@@ -645,6 +655,7 @@ gst_filesrc_change_state (GstElement *element)
     case GST_STATE_READY_TO_PAUSED:
     case GST_STATE_PAUSED_TO_READY:
       src->curoffset = 0;
+      src->seek_happened = TRUE;
     default:
       break;
   }
@@ -656,20 +667,49 @@ gst_filesrc_change_state (GstElement *element)
 }
 
 static gboolean
+gst_filesrc_srcpad_query (GstPad *pad, GstPadQueryType type,
+                         GstFormat *format, gint64 *value)
+{
+  GstFileSrc *src = GST_FILESRC (GST_PAD_PARENT (pad));
+
+  switch (type) {
+    case GST_PAD_QUERY_TOTAL:
+      if (*format != GST_FORMAT_BYTES) {
+       return FALSE;
+      }
+      *value = src->filelen;
+      break;
+    case GST_PAD_QUERY_POSITION:
+      if (*format != GST_FORMAT_BYTES) {
+       return FALSE;
+      }
+      *value = src->curoffset;
+      break;
+    default:
+      return FALSE;
+      break;
+  }
+  return TRUE;
+}
+
+static gboolean
 gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
 {
-  GstFileSrc *src = GST_FILESRC(GST_PAD_PARENT(pad));
+  GstFileSrc *src = GST_FILESRC (GST_PAD_PARENT (pad));
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
-      switch (GST_EVENT_SEEK_TYPE (event)) {
-        case GST_SEEK_BYTEOFFSET_SET:
+      if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
+       return FALSE;
+      }
+      switch (GST_EVENT_SEEK_METHOD (event)) {
+        case GST_SEEK_METHOD_SET:
           src->curoffset = (guint64) GST_EVENT_SEEK_OFFSET (event);
          break;
-        case GST_SEEK_BYTEOFFSET_CUR:
+        case GST_SEEK_METHOD_CUR:
           src->curoffset += GST_EVENT_SEEK_OFFSET (event);
          break;
-        case GST_SEEK_BYTEOFFSET_END:
+        case GST_SEEK_METHOD_END:
           src->curoffset = src->filelen - ABS (GST_EVENT_SEEK_OFFSET (event));
          break;
        default:
@@ -678,9 +718,7 @@ gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
       }
       g_object_notify (G_OBJECT (src), "offset");  
       src->seek_happened = TRUE;
-      src->need_flush = GST_EVENT_SEEK_FLUSH(event);
-      gst_event_free (event);
-      /* push a discontinuous event? */
+      src->need_flush = GST_EVENT_SEEK_FLAGS(event) & GST_SEEK_FLAG_FLUSH;
       break;
     case GST_EVENT_FLUSH:
       src->need_flush = TRUE;
index 11b3e9c..32b6cb4 100644 (file)
@@ -82,9 +82,13 @@ static void                  gst_queue_chain                 (GstPad *pad, GstBuffer *buf);
 static GstBuffer *             gst_queue_get                   (GstPad *pad);
 static GstBufferPool*          gst_queue_get_bufferpool        (GstPad *pad);
        
-static void                    gst_queue_locked_flush                  (GstQueue *queue);
+static gboolean                gst_queue_handle_src_event      (GstPad *pad, GstEvent *event);
+
+
+static void                    gst_queue_locked_flush          (GstQueue *queue);
 
 static GstElementStateReturn   gst_queue_change_state          (GstElement *element);
+static gboolean                        gst_queue_release_locks         (GstElement *element);
 
   
 #define GST_TYPE_QUEUE_LEAKY (queue_leaky_get_type())
@@ -157,7 +161,8 @@ gst_queue_class_init (GstQueueClass *klass)
   gobject_class->set_property          = GST_DEBUG_FUNCPTR (gst_queue_set_property);
   gobject_class->get_property          = GST_DEBUG_FUNCPTR (gst_queue_get_property);
 
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
+  gstelement_class->change_state  = GST_DEBUG_FUNCPTR(gst_queue_change_state);
+  gstelement_class->release_locks = GST_DEBUG_FUNCPTR(gst_queue_release_locks);
 }
 
 static GstPadConnectReturn
@@ -207,6 +212,7 @@ gst_queue_init (GstQueue *queue)
   gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
   gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
   gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
+  gst_pad_set_event_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_handle_src_event));
 
   queue->leaky = GST_QUEUE_NO_LEAK;
   queue->queue = NULL;
@@ -301,6 +307,9 @@ restart:
        GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "eos in on %s %d\n", 
                           GST_ELEMENT_NAME (queue), queue->level_buffers);
        break;
+      case GST_EVENT_DISCONTINUOUS:
+        //gst_queue_locked_flush (queue);
+       break;
       default:
        /*gst_pad_event_default (pad, GST_EVENT (buf)); */
        break;
@@ -350,7 +359,8 @@ restart:
     while (queue->level_buffers == queue->size_buffers) {
       /* if there's a pending state change for this queue or its manager, switch */
       /* back to iterator so bottom half of state change executes */
-      while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
+      //while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
+      if (queue->interrupt) {
         GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
         g_mutex_unlock (queue->qlock);
        if (gst_element_interrupt (GST_ELEMENT (queue)))
@@ -435,7 +445,8 @@ restart:
     /* if there's a pending state change for this queue or its manager, switch
      * back to iterator so bottom half of state change executes
      */ 
-    while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
+    //while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
+    if (queue->interrupt) {
       GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!");
       g_mutex_unlock (queue->qlock);
       if (gst_element_interrupt (GST_ELEMENT (queue)))
@@ -507,6 +518,51 @@ restart:
   return buf;
 }
 
+
+static gboolean
+gst_queue_handle_src_event (GstPad *pad, GstEvent *event)
+{
+  GstQueue *queue;
+
+  queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+  g_mutex_lock (queue->qlock);
+
+  if (gst_element_get_state (GST_ELEMENT (queue)) == GST_STATE_PLAYING) {
+    g_warning ("queue event in playing state");
+  }
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH:
+      GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "FLUSH event, flushing queue\n");
+      gst_queue_locked_flush (queue);
+      break;
+    case GST_EVENT_SEEK:
+      gst_queue_locked_flush (queue);
+    default:
+      gst_pad_event_default (pad, event); 
+      break;
+  }
+  g_mutex_unlock (queue->qlock);
+  return TRUE;
+}
+
+static gboolean
+gst_queue_release_locks (GstElement *element)
+{
+  GstQueue *queue;
+
+  queue = GST_QUEUE (element);
+
+  g_mutex_lock (queue->qlock);
+  queue->interrupt = TRUE;
+  g_cond_signal (queue->not_full);
+  g_cond_signal (queue->not_empty); 
+  g_mutex_unlock (queue->qlock);
+
+  return TRUE;
+}
+
 static GstElementStateReturn
 gst_queue_change_state (GstElement *element)
 {
@@ -543,6 +599,7 @@ gst_queue_change_state (GstElement *element)
 
       return GST_STATE_FAILURE;
     }
+    queue->interrupt = FALSE;
   }
 
   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
index 6122d2a..e3ab5bd 100644 (file)
@@ -75,6 +75,7 @@ struct _GstQueue {
 
   gint leaky;          /* whether the queue is leaky, and if so at which end */
   gboolean may_deadlock; /* it the queue should fail on possible deadlocks */
+  gboolean interrupt;
 
   GMutex *qlock;       /* lock for queue (vs object lock) */
   /* we are single reader and single writer queue */
index ee8622b..0b83570 100644 (file)
@@ -435,8 +435,6 @@ print_element_info (GstElementFactory *factory)
         printf("      Has chainfunc(): %s\n",GST_DEBUG_FUNCPTR_NAME(realpad->chainfunc));
       if (realpad->getfunc)
         printf("      Has getfunc(): %s\n",GST_DEBUG_FUNCPTR_NAME(realpad->getfunc));
-      if (realpad->getregionfunc)
-        printf("      Has getregionfunc(): %s\n",GST_DEBUG_FUNCPTR_NAME(realpad->getregionfunc));
 
       if (pad->padtemplate)
         printf("    Pad Template: '%s'\n",pad->padtemplate->name_template);