[MOVED FROM GST-P-FARSIGHT] Changed dtmfsrc into a subclass of GstBaseSrc
authorYouness Alaoui <youness.alaoui@collabora.co.uk>
Thu, 13 Sep 2007 17:55:20 +0000 (17:55 +0000)
committerEdward Hervey <bilboed@bilboed.com>
Sat, 21 Feb 2009 16:48:02 +0000 (17:48 +0100)
20070913175520-4f0f6-16ca4bf93690072f3e836d1c8a5b52cf7a421916.gz

gst/dtmf/gstdtmfsrc.c
gst/dtmf/gstdtmfsrc.h

index 94987de..f642558 100644 (file)
@@ -231,53 +231,30 @@ GST_STATIC_PAD_TEMPLATE ("src",
         "channels = (int) 1")
     );
 
-static GstElementClass *parent_class = NULL;
+GST_BOILERPLATE (GstDTMFSrc, gst_dtmf_src, GstBaseSrc, GST_TYPE_BASE_SRC);
 
-static void gst_dtmf_src_base_init (gpointer g_class);
-static void gst_dtmf_src_class_init (GstDTMFSrcClass * klass);
-static void gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class);
 static void gst_dtmf_src_finalize (GObject * object);
 
-GType
-gst_dtmf_src_get_type (void)
-{
-  static GType base_src_type = 0;
-
-  if (G_UNLIKELY (base_src_type == 0)) {
-    static const GTypeInfo base_src_info = {
-      sizeof (GstDTMFSrcClass),
-      (GBaseInitFunc) gst_dtmf_src_base_init,
-      NULL,
-      (GClassInitFunc) gst_dtmf_src_class_init,
-      NULL,
-      NULL,
-      sizeof (GstDTMFSrc),
-      0,
-      (GInstanceInitFunc) gst_dtmf_src_init,
-    };
-
-    base_src_type = g_type_register_static (GST_TYPE_ELEMENT,
-        "GstDTMFSrc", &base_src_info, 0);
-  }
-  return base_src_type;
-}
-
 static void gst_dtmf_src_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_dtmf_src_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-static gboolean gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event);
+static gboolean gst_dtmf_src_handle_event (GstBaseSrc *src, GstEvent * event);
 static GstStateChangeReturn gst_dtmf_src_change_state (GstElement * element,
     GstStateChange transition);
 static void gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key,
     float duration, GstBuffer * buffer);
-static void gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc);
-static void gst_dtmf_src_start (GstDTMFSrc *dtmfsrc);
-static void gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc);
+static GstFlowReturn gst_dtmf_src_create (GstBaseSrc * basesrc,
+    guint64 offset, guint length, GstBuffer ** buffer);
 static void gst_dtmf_src_add_start_event (GstDTMFSrc *dtmfsrc,
     gint event_number, gint event_volume);
 static void gst_dtmf_src_add_stop_event (GstDTMFSrc *dtmfsrc);
 
+static void gst_dtmf_src_get_times (GstBaseSrc * basesrc,
+    GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
+
+
+
 static void
 gst_dtmf_src_base_init (gpointer g_class)
 {
@@ -296,12 +273,13 @@ static void
 gst_dtmf_src_class_init (GstDTMFSrcClass * klass)
 {
   GObjectClass *gobject_class;
+  GstBaseSrcClass *gstbasesrc_class;
   GstElementClass *gstelement_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
+  gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
   gstelement_class = GST_ELEMENT_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (klass);
 
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_dtmf_src_finalize);
   gobject_class->set_property =
@@ -316,17 +294,22 @@ gst_dtmf_src_class_init (GstDTMFSrcClass * klass)
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_dtmf_src_change_state);
+
+  gstbasesrc_class->event =
+      GST_DEBUG_FUNCPTR (gst_dtmf_src_handle_event);
+  gstbasesrc_class->get_times =
+      GST_DEBUG_FUNCPTR (gst_dtmf_src_get_times);
+  gstbasesrc_class->create =
+      GST_DEBUG_FUNCPTR (gst_dtmf_src_create);
 }
 
+
 static void
-gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class)
+gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, GstDTMFSrcClass *g_class)
 {
-  dtmfsrc->srcpad =
-      gst_pad_new_from_static_template (&gst_dtmf_src_template, "src");
-  GST_DEBUG_OBJECT (dtmfsrc, "adding src pad");
-  gst_element_add_pad (GST_ELEMENT (dtmfsrc), dtmfsrc->srcpad);
-
-  gst_pad_set_event_function (dtmfsrc->srcpad, gst_dtmf_src_handle_event);
+  /* we operate in time */
+  gst_base_src_set_format (GST_BASE_SRC (dtmfsrc), GST_FORMAT_TIME);
+  gst_base_src_set_live (GST_BASE_SRC (dtmfsrc), TRUE);
 
   dtmfsrc->interval = DEFAULT_PACKET_INTERVAL;
 
@@ -334,7 +317,6 @@ gst_dtmf_src_init (GstDTMFSrc * dtmfsrc, gpointer g_class)
   dtmfsrc->last_event = NULL;
 
   dtmfsrc->clock_id = NULL;
-  dtmfsrc->task_paused = TRUE;
 
   GST_DEBUG_OBJECT (dtmfsrc, "init done");
 }
@@ -346,9 +328,6 @@ gst_dtmf_src_finalize (GObject * object)
 
   dtmfsrc = GST_DTMF_SRC (object);
 
-
-  gst_dtmf_src_stop (dtmfsrc);
-
   if (dtmfsrc->event_queue) {
     g_async_queue_unref (dtmfsrc->event_queue);
     dtmfsrc->event_queue = NULL;
@@ -424,36 +403,18 @@ ret:
 }
 
 static gboolean
-gst_dtmf_src_handle_event (GstPad * pad, GstEvent * event)
+gst_dtmf_src_handle_event (GstBaseSrc * src, GstEvent * event)
 {
   GstDTMFSrc *dtmfsrc;
   gboolean result = FALSE;
-  GstElement *parent = gst_pad_get_parent_element (pad);
-  dtmfsrc = GST_DTMF_SRC (parent);
+
+  dtmfsrc = GST_DTMF_SRC (src);
 
   GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad");
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_CUSTOM_UPSTREAM:
-    {
-      result = gst_dtmf_src_handle_custom_upstream (dtmfsrc, event);
-      break;
-    }
-    /* Ideally this element should not be flushed but let's handle the event
-     * just in case it is */
-    case GST_EVENT_FLUSH_START:
-      gst_dtmf_src_stop (dtmfsrc);
-      result = TRUE;
-      break;
-    case GST_EVENT_FLUSH_STOP:
-      gst_segment_init (&dtmfsrc->segment, GST_FORMAT_TIME);
-      break;
-    default:
-      result = gst_pad_event_default (pad, event);
-      break;
+  if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) {
+    result = gst_dtmf_src_handle_custom_upstream (dtmfsrc, event);
   }
 
-  gst_object_unref (parent);
-  gst_event_unref (event);
   return result;
 }
 
@@ -496,6 +457,7 @@ gst_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value,
 static void
 gst_dtmf_src_set_stream_lock (GstDTMFSrc *dtmfsrc, gboolean lock)
 {
+   GstPad *srcpad = GST_BASE_SRC_PAD (dtmfsrc);
    GstEvent *event;
    GstStructure *structure;
 
@@ -503,7 +465,7 @@ gst_dtmf_src_set_stream_lock (GstDTMFSrc *dtmfsrc, gboolean lock)
                       "lock", G_TYPE_BOOLEAN, lock, NULL);
 
    event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure);
-   if (!gst_pad_push_event (dtmfsrc->srcpad, event)) {
+   if (!gst_pad_push_event (srcpad, event)) {
      GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled");
    }
 }
@@ -512,10 +474,13 @@ static void
 gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc)
 {
   GstClock *clock;
+  GstClockTime base_time;
+
+  base_time = GST_ELEMENT_CAST (dtmfsrc)->base_time;
 
   clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
   if (clock != NULL) {
-    dtmfsrc->timestamp = gst_clock_get_time (clock);
+    dtmfsrc->timestamp = gst_clock_get_time (clock) - base_time;
     gst_object_unref (clock);
   } else {
     gchar *dtmf_name = gst_element_get_name (dtmfsrc);
@@ -526,65 +491,6 @@ gst_dtmf_prepare_timestamps (GstDTMFSrc *dtmfsrc)
 }
 
 static void
-gst_dtmf_src_start (GstDTMFSrc *dtmfsrc)
-{
-  const GstCaps * caps = gst_pad_get_pad_template_caps (dtmfsrc->srcpad);
-
-  if (!gst_pad_set_caps (dtmfsrc->srcpad, (GstCaps *)caps))
-    GST_ERROR_OBJECT (dtmfsrc,
-            "Failed to set caps %" GST_PTR_FORMAT " on src pad", caps);
-  else
-    GST_DEBUG_OBJECT (dtmfsrc,
-            "caps %" GST_PTR_FORMAT " set on src pad", caps);
-
-  dtmfsrc->task_paused = FALSE;
-  if (!gst_pad_start_task (dtmfsrc->srcpad,
-      (GstTaskFunction) gst_dtmf_src_push_next_tone_packet, dtmfsrc)) {
-    GST_ERROR_OBJECT (dtmfsrc, "Failed to start task on src pad");
-  }
-}
-
-static void
-gst_dtmf_src_stop (GstDTMFSrc *dtmfsrc)
-{
-  GstDTMFSrcEvent *event = NULL;
-
-  dtmfsrc->task_paused = TRUE;
-  GST_OBJECT_LOCK (dtmfsrc);
-  if (dtmfsrc->clock_id != NULL) {
-    gst_clock_id_unschedule(dtmfsrc->clock_id);
-  }
-  GST_OBJECT_UNLOCK (dtmfsrc);
-
-  event = g_malloc (sizeof(GstDTMFSrcEvent));
-  event->event_type = DTMF_EVENT_TYPE_PAUSE_TASK;
-  g_async_queue_push (dtmfsrc->event_queue, event);
-
-  event = NULL;
-
-  if (!gst_pad_pause_task (dtmfsrc->srcpad)) {
-    GST_ERROR_OBJECT (dtmfsrc, "Failed to pause task on src pad");
-    return;
-  }
-
-  if (dtmfsrc->last_event) {
-    /* Don't forget to release the stream lock */
-    gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE);
-    g_free (dtmfsrc->last_event);
-    dtmfsrc->last_event = NULL;
-  }
-
-  /* Flushing the event queue */
-  event = g_async_queue_try_pop (dtmfsrc->event_queue);
-
-  while (event != NULL) {
-    g_free (event);
-    event = g_async_queue_try_pop (dtmfsrc->event_queue);
-  }
-
-}
-
-static void
 gst_dtmf_src_add_start_event (GstDTMFSrc *dtmfsrc, gint event_number,
     gint event_volume)
 {
@@ -671,51 +577,25 @@ gst_dtmf_src_generate_tone(GstDTMFSrcEvent *event, DTMF_KEY key, float duration,
 }
 
 static void
-gst_dtmf_src_wait_for_buffer_ts (GstDTMFSrc *dtmfsrc, GstBuffer * buf)
+gst_dtmf_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
+    GstClockTime * start, GstClockTime * end)
 {
-  GstClock *clock;
-
-  clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
-  if (clock != NULL) {
-    GstClockReturn clock_ret;
-    GstClockID clock_id;
-
-    clock_id = gst_clock_new_single_shot_id (clock, GST_BUFFER_TIMESTAMP (buf));
-    gst_object_unref (clock);
+  /* for live sources, sync on the timestamp of the buffer */
+  if (gst_base_src_is_live (basesrc)) {
+    GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
 
-    GST_OBJECT_LOCK (dtmfsrc);
-    dtmfsrc->clock_id = clock_id;
-    GST_OBJECT_UNLOCK (dtmfsrc);
+    if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+      /* get duration to calculate end time */
+      GstClockTime duration = GST_BUFFER_DURATION (buffer);
 
-    if (dtmfsrc->task_paused) {
-      clock_ret = GST_CLOCK_UNSCHEDULED;
-    } else {
-      clock_ret = gst_clock_id_wait (dtmfsrc->clock_id, NULL);
-    }
-
-    GST_OBJECT_LOCK (dtmfsrc);
-    dtmfsrc->clock_id = NULL;
-    gst_clock_id_unref (clock_id);
-    GST_OBJECT_UNLOCK (dtmfsrc);
-
-    if (clock_ret == GST_CLOCK_UNSCHEDULED) {
-      GST_DEBUG_OBJECT (dtmfsrc, "Clock wait unscheduled");
-    } else {
-      if (clock_ret != GST_CLOCK_OK && clock_ret != GST_CLOCK_EARLY) {
-        gchar *clock_name = NULL;
-
-        clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
-        clock_name = gst_element_get_name (clock);
-        gst_object_unref (clock);
-
-        GST_ERROR_OBJECT (dtmfsrc, "Failed to wait on clock %s", clock_name);
-        g_free (clock_name);
+      *start = timestamp;
+      if (GST_CLOCK_TIME_IS_VALID (duration)) {
+        *end = *start + duration;
       }
     }
   } else {
-    gchar *dtmf_name = gst_element_get_name (dtmfsrc);
-    GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name);
-    g_free (dtmf_name);
+    *start = -1;
+    *end = -1;
   }
 }
 
@@ -726,6 +606,7 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc,
 {
   GstBuffer *buf = NULL;
   gboolean send_silence = FALSE;
+  GstPad *srcpad = GST_BASE_SRC_PAD (dtmfsrc);
 
   GST_DEBUG_OBJECT (dtmfsrc, "Creating buffer for tone %s",
       DTMF_KEYS[event->event_number].event_name);
@@ -753,24 +634,26 @@ gst_dtmf_src_create_next_tone_packet (GstDTMFSrc *dtmfsrc,
   GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp;
   dtmfsrc->timestamp += GST_BUFFER_DURATION (buf);
 
-  /* FIXME: Should we sync to clock ourselves or leave it to sink */
-  gst_dtmf_src_wait_for_buffer_ts (dtmfsrc, buf);
-
   /* Set caps on the buffer before pushing it */
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (dtmfsrc->srcpad));
+  gst_buffer_set_caps (buf, GST_PAD_CAPS (srcpad));
 
   return buf;
 }
 
-static void
-gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc)
+static GstFlowReturn
+gst_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset,
+    guint length, GstBuffer ** buffer)
 {
   GstBuffer *buf = NULL;
   GstFlowReturn ret;
   GstDTMFSrcEvent *event;
+  GstDTMFSrc * dtmfsrc;
+
+  dtmfsrc = GST_DTMF_SRC (basesrc);
 
   g_async_queue_ref (dtmfsrc->event_queue);
 
+ start:
   if (dtmfsrc->last_event == NULL) {
     event = g_async_queue_pop (dtmfsrc->event_queue);
 
@@ -788,11 +671,10 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc)
     } else if (event->event_type == DTMF_EVENT_TYPE_PAUSE_TASK) {
       /*
        * We're pushing it back because it has to stay in there until
-       * the task is really paused (and the queue will then be flushed
+       * the task is really paused (and the queue will then be flushed)
        */
       g_async_queue_push (dtmfsrc->event_queue, event);
       g_async_queue_unref (dtmfsrc->event_queue);
-      return;
     }
   } else if (dtmfsrc->last_event->packet_count  * dtmfsrc->interval >=
       MIN_DUTY_CYCLE) {
@@ -806,6 +688,7 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc)
         gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE);
         g_free (dtmfsrc->last_event);
         dtmfsrc->last_event = NULL;
+        goto start;
       }
     }
   }
@@ -814,19 +697,16 @@ gst_dtmf_src_push_next_tone_packet (GstDTMFSrc *dtmfsrc)
   if (dtmfsrc->last_event) {
     buf = gst_dtmf_src_create_next_tone_packet (dtmfsrc, dtmfsrc->last_event);
 
-    gst_buffer_ref(buf);
-
-    GST_DEBUG_OBJECT (dtmfsrc,
-        "pushing buffer on src pad of size %d", GST_BUFFER_SIZE (buf));
-    ret = gst_pad_push (dtmfsrc->srcpad, buf);
-    if (ret != GST_FLOW_OK) {
-      GST_ERROR_OBJECT (dtmfsrc, "Failed to push buffer on src pad");
-    }
-
-    gst_buffer_unref(buf);
-    GST_DEBUG_OBJECT (dtmfsrc, "pushed DTMF tone on src pad");
+    GST_DEBUG_OBJECT (dtmfsrc, "Created buffer of size %d", GST_BUFFER_SIZE (buf));
+    *buffer = buf;
+    ret = GST_FLOW_OK;
+  } else {
+    *buffer = NULL;
+    ret = GST_FLOW_WRONG_STATE;
   }
 
+  return ret;
+
 }
 
 static GstStateChangeReturn
@@ -838,23 +718,6 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition)
 
   dtmfsrc = GST_DTMF_SRC (element);
 
-  switch (transition) {
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      gst_segment_init (&dtmfsrc->segment, GST_FORMAT_TIME);
-      gst_pad_push_event (dtmfsrc->srcpad, gst_event_new_new_segment (FALSE,
-              dtmfsrc->segment.rate, dtmfsrc->segment.format,
-              dtmfsrc->segment.start, dtmfsrc->segment.stop,
-              dtmfsrc->segment.time));
-      /* Indicate that we don't do PRE_ROLL */
-      no_preroll = TRUE;
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      gst_dtmf_src_start (dtmfsrc);
-      break;
-    default:
-      break;
-  }
-
   if ((result =
           GST_ELEMENT_CLASS (parent_class)->change_state (element,
               transition)) == GST_STATE_CHANGE_FAILURE)
@@ -862,10 +725,30 @@ gst_dtmf_src_change_state (GstElement * element, GstStateChange transition)
 
   switch (transition) {
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      /* Indicate that we don't do PRE_ROLL */
-      gst_dtmf_src_stop (dtmfsrc);
-      no_preroll = TRUE;
-      break;
+      {
+        GstDTMFSrcEvent *event = NULL;
+
+        /* TODO lock the element */
+
+        if (dtmfsrc->last_event) {
+          /* Don't forget to release the stream lock */
+          gst_dtmf_src_set_stream_lock (dtmfsrc, FALSE);
+          g_free (dtmfsrc->last_event);
+          dtmfsrc->last_event = NULL;
+        }
+
+        /* Flushing the event queue */
+        event = g_async_queue_try_pop (dtmfsrc->event_queue);
+
+        while (event != NULL) {
+          g_free (event);
+          event = g_async_queue_try_pop (dtmfsrc->event_queue);
+        }
+
+        /* Indicate that we don't do PRE_ROLL */
+        no_preroll = TRUE;
+        break;
+      }
     default:
       break;
   }
index 27e91a0..1ca4464 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <gst/gst.h>
 #include <gst/gstbuffer.h>
+#include <gst/base/gstbasesrc.h>
 
 G_BEGIN_DECLS
 
@@ -69,9 +70,7 @@ struct _GstDTMFSrcEvent {
 typedef struct _GstDTMFSrcEvent GstDTMFSrcEvent;
 
 struct _GstDTMFSrc {
-  GstElement        element;
-  GstPad            *srcpad;
-  GstSegment        segment;
+  GstBaseSrc        parent;
   GAsyncQueue*      event_queue;
   GstDTMFSrcEvent*  last_event;
   GstClockID        clock_id;
@@ -83,7 +82,7 @@ struct _GstDTMFSrc {
 
 
 struct _GstDTMFSrcClass {
-  GstElementClass parent_class;
+  GstBaseSrcClass parent_class;
 };
 
 GType gst_dtmf_src_get_type (void);