示例#1
0
static void
print_implementation_info (GstElement * element)
{
  n_print ("\n");
  n_print ("Element Implementation:\n");

  {
    GstElementClass *gstelement_class;

    gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));

    n_print ("  Has change_state() function: %s\n",
        GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
  }
#ifndef GST_DISABLE_LOADSAVE
  {
    GstObjectClass *gstobject_class;

    gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));

    n_print ("  Has custom save_thyself() function: %s\n",
        GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
    n_print ("  Has custom restore_thyself() function: %s\n",
        GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
  }
#endif
}
示例#2
0
/* checks if all the pads are collected and call the collectfunction
 *
 * Should be called with LOCK.
 *
 * Returns: The #GstFlowReturn of collection.
 */
static GstFlowReturn
gst_collect_pads_check_collected (GstCollectPads * pads)
{
  GstFlowReturn flow_ret = GST_FLOW_OK;

  g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), GST_FLOW_ERROR);
  g_return_val_if_fail (pads->func != NULL, GST_FLOW_NOT_SUPPORTED);

  /* check for new pads, update stats etc.. */
  gst_collect_pads_check_pads (pads);

  if (G_UNLIKELY (pads->eospads == pads->numpads)) {
    /* If all our pads are EOS just collect once to let the element
     * do its final EOS handling. */
    GST_DEBUG ("All active pads (%d) are EOS, calling %s",
        pads->numpads, GST_DEBUG_FUNCPTR_NAME (pads->func));
    flow_ret = pads->func (pads, pads->user_data);
  } else {
    gboolean collected = FALSE;

    /* We call the collected function as long as our condition matches.
     * FIXME: should we error out if the collect function did not pop anything ?
     * we can get a busy loop here if the element does not pop from the collect
     * function
     */
    while (((pads->queuedpads + pads->eospads) >= pads->numpads)) {
      GST_DEBUG ("All active pads (%d + %d >= %d) have data, calling %s",
          pads->queuedpads, pads->eospads, pads->numpads,
          GST_DEBUG_FUNCPTR_NAME (pads->func));
      flow_ret = pads->func (pads, pads->user_data);
      collected = TRUE;

      /* break on error */
      if (flow_ret != GST_FLOW_OK)
        break;
      /* Don't keep looping after telling the element EOS or flushing */
      if (pads->queuedpads == 0)
        break;
    }
    if (!collected)
      GST_DEBUG ("Not all active pads (%d) have data, continuing",
          pads->numpads);
  }
  return flow_ret;
}
示例#3
0
static void
print_implementation_info (GstElement * element)
{
  GstElementClass *gstelement_class;

  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));

  n_print ("\n");
  n_print ("Element Implementation:\n");

  n_print ("  Has change_state() function: %s\n",
      GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
}
示例#4
0
static void
print_pad_templates_info (GstElement * element, GstElementFactory * factory)
{
  GstElementClass *gstelement_class;
  const GList *pads;
  GstStaticPadTemplate *padtemplate;

  n_print ("Pad Templates:\n");
  if (gst_element_factory_get_num_pad_templates (factory) == 0) {
    n_print ("  none\n");
    return;
  }

  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));

  pads = gst_element_factory_get_static_pad_templates (factory);
  while (pads) {
    padtemplate = (GstStaticPadTemplate *) (pads->data);
    pads = g_list_next (pads);

    if (padtemplate->direction == GST_PAD_SRC)
      n_print ("  SRC template: '%s'\n", padtemplate->name_template);
    else if (padtemplate->direction == GST_PAD_SINK)
      n_print ("  SINK template: '%s'\n", padtemplate->name_template);
    else
      n_print ("  UNKNOWN!!! template: '%s'\n", padtemplate->name_template);

    if (padtemplate->presence == GST_PAD_ALWAYS)
      n_print ("    Availability: Always\n");
    else if (padtemplate->presence == GST_PAD_SOMETIMES)
      n_print ("    Availability: Sometimes\n");
    else if (padtemplate->presence == GST_PAD_REQUEST) {
      n_print ("    Availability: On request\n");
      n_print ("      Has request_new_pad() function: %s\n",
          GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
    } else
      n_print ("    Availability: UNKNOWN!!!\n");

    if (padtemplate->static_caps.string) {
      n_print ("    Capabilities:\n");
      print_caps (gst_static_caps_get (&padtemplate->static_caps), "      ");
    }

    n_print ("\n");
  }
}
示例#5
0
/* this internal thread does nothing else but write samples to the audio device.
 * It will write each segment in the ringbuffer and will update the play
 * pointer.
 * The start/stop methods control the thread.
 */
static void
audioringbuffer_thread_func (GstRingBuffer * buf)
{
  GstAudioSink *sink;
  GstAudioSinkClass *csink;
  GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER_CAST (buf);
  WriteFunc writefunc;
  GstMessage *message;
  GValue val = { 0 };

  sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
  csink = GST_AUDIO_SINK_GET_CLASS (sink);

  GST_DEBUG_OBJECT (sink, "enter thread");

  GST_OBJECT_LOCK (abuf);
  GST_DEBUG_OBJECT (sink, "signal wait");
  GST_AUDIORING_BUFFER_SIGNAL (buf);
  GST_OBJECT_UNLOCK (abuf);

  writefunc = csink->write;
  if (writefunc == NULL)
    goto no_function;

  g_value_init (&val, G_TYPE_POINTER);
  g_value_set_pointer (&val, sink->thread);
  message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
      GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (sink));
  gst_message_set_stream_status_object (message, &val);
  GST_DEBUG_OBJECT (sink, "posting ENTER stream status");
  gst_element_post_message (GST_ELEMENT_CAST (sink), message);

  while (TRUE) {
    gint left, len;
    guint8 *readptr;
    gint readseg;

    /* buffer must be started */
    if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
      gint written;

      left = len;
      do {
        written = writefunc (sink, readptr, left);
        GST_LOG_OBJECT (sink, "transfered %d bytes of %d from segment %d",
            written, left, readseg);
        if (written < 0 || written > left) {
          /* might not be critical, it e.g. happens when aborting playback */
          GST_WARNING_OBJECT (sink,
              "error writing data in %s (reason: %s), skipping segment (left: %d, written: %d)",
              GST_DEBUG_FUNCPTR_NAME (writefunc),
              (errno > 1 ? g_strerror (errno) : "unknown"), left, written);
          break;
        }
        left -= written;
        readptr += written;
      } while (left > 0);

      /* clear written samples */
      gst_ring_buffer_clear (buf, readseg);

      /* we wrote one segment */
      gst_ring_buffer_advance (buf, 1);
    } else {
      GST_OBJECT_LOCK (abuf);
      if (!abuf->running)
        goto stop_running;
      GST_DEBUG_OBJECT (sink, "signal wait");
      GST_AUDIORING_BUFFER_SIGNAL (buf);
      GST_DEBUG_OBJECT (sink, "wait for action");
#ifndef GSTREAMER_LITE
      GST_AUDIORING_BUFFER_WAIT (buf);
#else // GSTREAMER_LITE
      // In same cases we may have condition when we waiting here for ring buffer to start,
      // while ring buffer is started and data is available. So, lets use wait with timeout
      // and recheck if we good to go. wait_segment() will start ring buffer when data is available.
      {
          GTimeVal timeout;
          g_get_current_time(&timeout);
          g_time_val_add(&timeout, 100000); // 100 millisecond
          GST_AUDIORING_BUFFER_TIMED_WAIT (buf, &timeout);
      }
#endif // GSTREAMER_LITE
      GST_DEBUG_OBJECT (sink, "got signal");
      if (!abuf->running)
        goto stop_running;
      GST_DEBUG_OBJECT (sink, "continue running");
      GST_OBJECT_UNLOCK (abuf);
    }
  }

  /* Will never be reached */
  g_assert_not_reached ();
  return;

  /* ERROR */
no_function:
  {
    GST_DEBUG_OBJECT (sink, "no write function, exit thread");
    return;
  }
stop_running:
  {
    GST_OBJECT_UNLOCK (abuf);
    GST_DEBUG_OBJECT (sink, "stop running, exit thread");
    message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
        GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (sink));
    gst_message_set_stream_status_object (message, &val);
    GST_DEBUG_OBJECT (sink, "posting LEAVE stream status");
    gst_element_post_message (GST_ELEMENT_CAST (sink), message);
    return;
  }
}
示例#6
0
static gint
print_element_info (GstElementFactory * factory)
{
  GstElement *element;
#ifndef GST_DISABLE_LOADSAVE
  GstObjectClass *gstobject_class;
#endif
  GstElementClass *gstelement_class;
  GList *pads;
  GstPad *pad;
  GstStaticPadTemplate *padtemplate;
  gint maxlevel = 0;

  element = gst_element_factory_create (factory, "element");
  if (!element) {
    g_print ("couldn't construct element for some reason\n");
    return -1;
  }
  PUT_START_TAG (0, "element");
  PUT_ESCAPED (1, "name", GST_PLUGIN_FEATURE_NAME (factory));

#ifndef GST_DISABLE_LOADSAVE
  gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));
#endif
  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));

  PUT_START_TAG (1, "details");
  PUT_ESCAPED (2, "long-name", factory->details.longname);
  PUT_ESCAPED (2, "class", factory->details.klass);
  PUT_ESCAPED (2, "description", factory->details.description);
  PUT_ESCAPED (2, "authors", factory->details.author);
  PUT_END_TAG (1, "details");

  output_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);

  PUT_START_TAG (1, "pad-templates");
  if (factory->numpadtemplates) {
    pads = factory->staticpadtemplates;
    while (pads) {
      padtemplate = (GstStaticPadTemplate *) (pads->data);
      pads = g_list_next (pads);

      PUT_START_TAG (2, "pad-template");
      PUT_ESCAPED (3, "name", padtemplate->name_template);

      if (padtemplate->direction == GST_PAD_SRC)
        PUT_ESCAPED (3, "direction", "src");
      else if (padtemplate->direction == GST_PAD_SINK)
        PUT_ESCAPED (3, "direction", "sink");
      else
        PUT_ESCAPED (3, "direction", "unknown");

      if (padtemplate->presence == GST_PAD_ALWAYS)
        PUT_ESCAPED (3, "presence", "always");
      else if (padtemplate->presence == GST_PAD_SOMETIMES)
        PUT_ESCAPED (3, "presence", "sometimes");
      else if (padtemplate->presence == GST_PAD_REQUEST) {
        PUT_ESCAPED (3, "presence", "request");
        PUT_ESCAPED (3, "request-function",
            GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
      } else
        PUT_ESCAPED (3, "presence", "unknown");

      if (padtemplate->static_caps.string) {
        print_caps (gst_static_caps_get (&padtemplate->static_caps), 3);
      }
      PUT_END_TAG (2, "pad-template");
    }
  }
  PUT_END_TAG (1, "pad-templates");

  PUT_START_TAG (1, "element-flags");
  PUT_END_TAG (1, "element-flags");

  if (GST_IS_BIN (element)) {
    PUT_START_TAG (1, "bin-flags");

    PUT_END_TAG (1, "bin-flags");
  }


  PUT_START_TAG (1, "element-implementation");

  PUT_STRING (2, "<state-change function=\"%s\"/>",
      GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));

#ifndef GST_DISABLE_LOADSAVE
  PUT_STRING (2, "<save function=\"%s\"/>",
      GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
  PUT_STRING (2, "<load function=\"%s\"/>",
      GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
#endif
  PUT_END_TAG (1, "element-implementation");

  PUT_START_TAG (1, "clocking-interaction");
  if (gst_element_requires_clock (element)) {
    PUT_STRING (2, "<requires-clock/>");
  }
  if (gst_element_provides_clock (element)) {
    GstClock *clock;

    clock = gst_element_get_clock (element);
    if (clock)
      PUT_STRING (2, "<provides-clock name=\"%s\"/>", GST_OBJECT_NAME (clock));
  }
  PUT_END_TAG (1, "clocking-interaction");

  if (gst_element_is_indexable (element)) {
    PUT_STRING (1, "<indexing-capabilities/>");
  }

  PUT_START_TAG (1, "pads");
  if (element->numpads) {
    const GList *pads;

    pads = element->pads;
    while (pads) {
      pad = GST_PAD (pads->data);
      pads = g_list_next (pads);

      PUT_START_TAG (2, "pad");
      PUT_ESCAPED (3, "name", gst_pad_get_name (pad));

      if (gst_pad_get_direction (pad) == GST_PAD_SRC)
        PUT_ESCAPED (3, "direction", "src");
      else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
        PUT_ESCAPED (3, "direction", "sink");
      else
        PUT_ESCAPED (3, "direction", "unknown");

      if (pad->padtemplate)
        PUT_ESCAPED (3, "template", pad->padtemplate->name_template);

      PUT_START_TAG (3, "implementation");
      if (pad->chainfunc)
        PUT_STRING (4, "<chain-based function=\"%s\"/>",
            GST_DEBUG_FUNCPTR_NAME (pad->chainfunc));
      if (pad->getrangefunc)
        PUT_STRING (4, "<get-range-based function=\"%s\"/>",
            GST_DEBUG_FUNCPTR_NAME (pad->getrangefunc));
      if (pad->eventfunc != gst_pad_event_default)
        PUT_STRING (4, "<event-function function=\"%s\"/>",
            GST_DEBUG_FUNCPTR_NAME (pad->eventfunc));
      if (pad->queryfunc != gst_pad_query_default)
        PUT_STRING (4, "<query-function function=\"%s\"/>",
            GST_DEBUG_FUNCPTR_NAME (pad->queryfunc));
      if (pad->querytypefunc != gst_pad_get_query_types_default) {
        PUT_STRING (4, "<query-type-func function=\"%s\">",
            GST_DEBUG_FUNCPTR_NAME (pad->querytypefunc));
        print_query_types (gst_pad_get_query_types (pad), 5);
        PUT_END_TAG (4, "query-type-func");
      }

      if (pad->iterintlinkfunc != gst_pad_iterate_internal_links_default)
        PUT_STRING (4, "<iterintlink-function function=\"%s\"/>",
            GST_DEBUG_FUNCPTR_NAME (pad->iterintlinkfunc));

      if (pad->bufferallocfunc)
        PUT_STRING (4, "<bufferalloc-function function=\"%s\"/>",
            GST_DEBUG_FUNCPTR_NAME (pad->bufferallocfunc));
      PUT_END_TAG (3, "implementation");

      if (pad->caps) {
        print_caps (pad->caps, 3);
      }
      PUT_END_TAG (2, "pad");
    }
  }
  PUT_END_TAG (1, "pads");

  print_element_properties (element, 1);
  print_element_signals (element, 1);

  /* for compound elements */
  /* FIXME: gst_bin_get_list does not exist anymore
     if (GST_IS_BIN (element)) {
     GList *children;
     GstElement *child;
     PUT_START_TAG (1, "children");
     children = (GList *) gst_bin_get_list (GST_BIN (element));
     while (children) {
     child = GST_ELEMENT (children->data);
     children = g_list_next (children);

     PUT_ESCAPED (2, "child", GST_ELEMENT_NAME (child));
     }
     PUT_END_TAG (1, "children");
     }
   */
  PUT_END_TAG (0, "element");

  return 0;
}
示例#7
0
static void
print_pad_info (GstElement * element)
{
  const GList *pads;
  GstPad *pad;

  n_print ("\n");
  n_print ("Pads:\n");

  if (!element->numpads) {
    n_print ("  none\n");
    return;
  }

  pads = element->pads;
  while (pads) {
    gchar *name;

    pad = GST_PAD (pads->data);
    pads = g_list_next (pads);

    n_print ("");

    name = gst_pad_get_name (pad);
    if (gst_pad_get_direction (pad) == GST_PAD_SRC)
      g_print ("  SRC: '%s'", name);
    else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
      g_print ("  SINK: '%s'", name);
    else
      g_print ("  UNKNOWN!!!: '%s'", name);

    g_free (name);

    g_print ("\n");

    n_print ("    Implementation:\n");
    if (pad->chainfunc)
      n_print ("      Has chainfunc(): %s\n",
          GST_DEBUG_FUNCPTR_NAME (pad->chainfunc));
    if (pad->getrangefunc)
      n_print ("      Has getrangefunc(): %s\n",
          GST_DEBUG_FUNCPTR_NAME (pad->getrangefunc));
    if (pad->eventfunc != gst_pad_event_default)
      n_print ("      Has custom eventfunc(): %s\n",
          GST_DEBUG_FUNCPTR_NAME (pad->eventfunc));
    if (pad->queryfunc != gst_pad_query_default)
      n_print ("      Has custom queryfunc(): %s\n",
          GST_DEBUG_FUNCPTR_NAME (pad->queryfunc));
    if (pad->querytypefunc != gst_pad_get_query_types_default) {
      n_print ("        Provides query types:\n");
      print_query_types (gst_pad_get_query_types (pad));
    }

    if (pad->intlinkfunc != gst_pad_get_internal_links_default)
      n_print ("      Has custom intconnfunc(): %s\n",
          GST_DEBUG_FUNCPTR_NAME (pad->intlinkfunc));

    if (pad->bufferallocfunc)
      n_print ("      Has bufferallocfunc(): %s\n",
          GST_DEBUG_FUNCPTR_NAME (pad->bufferallocfunc));

    if (pad->padtemplate)
      n_print ("    Pad Template: '%s'\n", pad->padtemplate->name_template);

    if (pad->caps) {
      n_print ("    Capabilities:\n");
      print_caps (pad->caps, "      ");
    }
  }
}
/* this internal thread does nothing else but write samples to the audio device.
 * It will write each segment in the ringbuffer and will update the play
 * pointer.
 * The start/stop methods control the thread.
 */
static void
audioringbuffer_thread_func (GstAudioRingBuffer * buf)
{
    GstAudioSink *sink;
    GstAudioSinkClass *csink;
    GstAudioSinkRingBuffer *abuf = GST_AUDIO_SINK_RING_BUFFER_CAST (buf);
    WriteFunc writefunc;
    GstMessage *message;
    GValue val = { 0 };

    sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
    csink = GST_AUDIO_SINK_GET_CLASS (sink);

    GST_DEBUG_OBJECT (sink, "enter thread");

    GST_OBJECT_LOCK (abuf);
    GST_DEBUG_OBJECT (sink, "signal wait");
    GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
    GST_OBJECT_UNLOCK (abuf);

    writefunc = csink->write;
    if (writefunc == NULL)
        goto no_function;

    message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
              GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (sink));
    g_value_init (&val, GST_TYPE_G_THREAD);
    g_value_set_boxed (&val, g_thread_self ());
    gst_message_set_stream_status_object (message, &val);
    g_value_unset (&val);
    GST_DEBUG_OBJECT (sink, "posting ENTER stream status");
    gst_element_post_message (GST_ELEMENT_CAST (sink), message);

    while (TRUE) {
        gint left, len;
        guint8 *readptr;
        gint readseg;

        /* buffer must be started */
        if (gst_audio_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
            gint written;

            left = len;
            do {
                written = writefunc (sink, readptr, left);
                GST_LOG_OBJECT (sink, "transfered %d bytes of %d from segment %d",
                                written, left, readseg);
                if (written < 0 || written > left) {
                    /* might not be critical, it e.g. happens when aborting playback */
                    GST_WARNING_OBJECT (sink,
                                        "error writing data in %s (reason: %s), skipping segment (left: %d, written: %d)",
                                        GST_DEBUG_FUNCPTR_NAME (writefunc),
                                        (errno > 1 ? g_strerror (errno) : "unknown"), left, written);
                    break;
                }
                left -= written;
                readptr += written;
            } while (left > 0);

            /* clear written samples */
            gst_audio_ring_buffer_clear (buf, readseg);

            /* we wrote one segment */
            gst_audio_ring_buffer_advance (buf, 1);
        } else {
            GST_OBJECT_LOCK (abuf);
            if (!abuf->running)
                goto stop_running;
            if (G_UNLIKELY (g_atomic_int_get (&buf->state) ==
                            GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
                GST_OBJECT_UNLOCK (abuf);
                continue;
            }
            GST_DEBUG_OBJECT (sink, "signal wait");
            GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
            GST_DEBUG_OBJECT (sink, "wait for action");
            GST_AUDIO_SINK_RING_BUFFER_WAIT (buf);
            GST_DEBUG_OBJECT (sink, "got signal");
            if (!abuf->running)
                goto stop_running;
            GST_DEBUG_OBJECT (sink, "continue running");
            GST_OBJECT_UNLOCK (abuf);
        }
    }

    /* Will never be reached */
    g_assert_not_reached ();
    return;

    /* ERROR */
no_function:
    {
        GST_DEBUG_OBJECT (sink, "no write function, exit thread");
        return;
    }
stop_running:
    {
        GST_OBJECT_UNLOCK (abuf);
        GST_DEBUG_OBJECT (sink, "stop running, exit thread");
        message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
                  GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (sink));
        g_value_init (&val, GST_TYPE_G_THREAD);
        g_value_set_boxed (&val, g_thread_self ());
        gst_message_set_stream_status_object (message, &val);
        g_value_unset (&val);
        GST_DEBUG_OBJECT (sink, "posting LEAVE stream status");
        gst_element_post_message (GST_ELEMENT_CAST (sink), message);
        return;
    }
}