/**
 * gst_element_factory_list_filter:
 * @list: (transfer none) (element-type Gst.ElementFactory): a #GList of
 *     #GstElementFactory to filter
 * @caps: a #GstCaps
 * @direction: a #GstPadDirection to filter on
 * @subsetonly: whether to filter on caps subsets or not.
 *
 * Filter out all the elementfactories in @list that can handle @caps in
 * the given direction.
 *
 * If @subsetonly is %TRUE, then only the elements whose pads templates
 * are a complete superset of @caps will be returned. Else any element
 * whose pad templates caps can intersect with @caps will be returned.
 *
 * Returns: (transfer full) (element-type Gst.ElementFactory): a #GList of
 *     #GstElementFactory elements that match the given requisits.
 *     Use #gst_plugin_feature_list_free after usage.
 *
 * Since: 0.10.31
 */
GList *
gst_element_factory_list_filter (GList * list,
    const GstCaps * caps, GstPadDirection direction, gboolean subsetonly)
{
  GQueue results = G_QUEUE_INIT;

  GST_DEBUG ("finding factories");

  /* loop over all the factories */
  for (; list; list = list->next) {
    GstElementFactory *factory;
    const GList *templates;
    GList *walk;

    factory = (GstElementFactory *) list->data;

    GST_DEBUG ("Trying %s",
        gst_plugin_feature_get_name ((GstPluginFeature *) factory));

    /* get the templates from the element factory */
    templates = gst_element_factory_get_static_pad_templates (factory);
    for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
      GstStaticPadTemplate *templ = walk->data;

      /* we only care about the sink templates */
      if (templ->direction == direction) {
        GstCaps *tmpl_caps;

        /* try to intersect the caps with the caps of the template */
        tmpl_caps = gst_static_caps_get (&templ->static_caps);

        /* FIXME, intersect is not the right method, we ideally want to check
         * for a subset here */

        /* check if the intersection is empty */
        if ((subsetonly && gst_caps_is_subset (caps, tmpl_caps)) ||
            (!subsetonly && gst_caps_can_intersect (caps, tmpl_caps))) {
          /* non empty intersection, we can use this element */
          g_queue_push_tail (&results, gst_object_ref (factory));
          gst_caps_unref (tmpl_caps);
          break;
        }
        gst_caps_unref (tmpl_caps);
      }
    }
  }
  return results.head;
}
Beispiel #2
0
static void
gst_auto_video_sink_init (GstAutoVideoSink * sink)
{
  sink->pad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK);
  gst_element_add_pad (GST_ELEMENT (sink), sink->pad);

  gst_auto_video_sink_reset (sink);

  /* set the default raw video caps */
  sink->filter_caps = gst_static_caps_get (&raw_caps);
  sink->ts_offset = DEFAULT_TS_OFFSET;
  sink->sync = DEFAULT_SYNC;

  /* mark as sink */
  GST_OBJECT_FLAG_SET (sink, GST_ELEMENT_FLAG_SINK);
}
static void
check_caps (GstPad * pad, HandOffData * hod)
{
  GstCaps *caps, *expected_caps;
  gboolean is_subset = FALSE;

  expected_caps = gst_static_caps_get (&hod->expected_caps);
  caps = gst_pad_get_current_caps (pad);
  is_subset = gst_caps_is_subset (caps, expected_caps);
  GST_DEBUG ("expected caps: %" GST_PTR_FORMAT ", caps: %" GST_PTR_FORMAT
      ", is subset: %d", expected_caps, caps, is_subset);
  gst_caps_unref (expected_caps);
  gst_caps_unref (caps);

  fail_unless (is_subset);
}
/* Probing functions */
gboolean
gst_v4l2_is_h264_enc (GstCaps * sink_caps, GstCaps * src_caps)
{
  gboolean ret = FALSE;
  GstCaps *codec_caps;

  codec_caps = gst_static_caps_get (&src_template_caps);

  if (gst_caps_is_subset (sink_caps, gst_v4l2_object_get_raw_caps ())
      && gst_caps_can_intersect (src_caps, codec_caps))
    ret = TRUE;

  gst_caps_unref (codec_caps);

  return ret;
}
Beispiel #5
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");
  }
}
Beispiel #6
0
static gboolean
caps_can_intersect_with_static (const GstCaps * caps,
    GstStaticCaps * static_caps)
{
  GstCaps *aux;
  gboolean ret;

  if (caps == NULL) {
    return FALSE;
  }

  aux = gst_static_caps_get (static_caps);
  ret = gst_caps_can_intersect (caps, aux);
  gst_caps_unref (aux);

  return ret;
}
static GstCaps *
gst_gdk_pixbuf_dec_get_capslist (GstCaps * filter)
{
  GSList *slist;
  GSList *slist0;
  GstCaps *capslist = NULL;
  GstCaps *return_caps = NULL;
  GstCaps *tmpl_caps;

  capslist = gst_caps_new_empty ();
  slist0 = gdk_pixbuf_get_formats ();

  for (slist = slist0; slist; slist = g_slist_next (slist)) {
    GdkPixbufFormat *pixbuf_format;
    char **mimetypes;
    char **mimetype;

    pixbuf_format = slist->data;
    mimetypes = gdk_pixbuf_format_get_mime_types (pixbuf_format);

    for (mimetype = mimetypes; *mimetype; mimetype++) {
      gst_caps_append_structure (capslist, gst_structure_new_empty (*mimetype));
    }
    g_strfreev (mimetypes);
  }
  g_slist_free (slist0);

  tmpl_caps =
      gst_static_caps_get (&gst_gdk_pixbuf_dec_sink_template.static_caps);
  return_caps = gst_caps_intersect (capslist, tmpl_caps);

  gst_caps_unref (tmpl_caps);
  gst_caps_unref (capslist);

  if (filter && return_caps) {
    GstCaps *temp;

    temp = gst_caps_intersect (return_caps, filter);
    gst_caps_unref (return_caps);
    return_caps = temp;
  }

  return return_caps;
}
Beispiel #8
0
static void
gst_vtenc_base_init (GstVTEncClass * klass)
{
  const GstVTEncoderDetails *codec_details =
      GST_VTENC_CLASS_GET_CODEC_DETAILS (klass);
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  const int min_width = 1, max_width = G_MAXINT;
  const int min_height = 1, max_height = G_MAXINT;
  const int min_fps_n = 0, max_fps_n = G_MAXINT;
  const int min_fps_d = 1, max_fps_d = 1;
  GstPadTemplate *sink_template, *src_template;
  GstCaps *src_caps;
  gchar *longname, *description;

  longname = g_strdup_printf ("%s encoder", codec_details->name);
  description = g_strdup_printf ("%s encoder", codec_details->name);

  gst_element_class_set_metadata (element_class, longname,
      "Codec/Encoder/Video", description,
      "Ole André Vadla Ravnås <*****@*****.**>, Dominik Röttsches <*****@*****.**>");

  g_free (longname);
  g_free (description);

  sink_template = gst_pad_template_new ("sink",
      GST_PAD_SINK, GST_PAD_ALWAYS, gst_static_caps_get (&sink_caps));
  gst_element_class_add_pad_template (element_class, sink_template);

  src_caps = gst_caps_new_simple (codec_details->mimetype,
      "width", GST_TYPE_INT_RANGE, min_width, max_width,
      "height", GST_TYPE_INT_RANGE, min_height, max_height,
      "framerate", GST_TYPE_FRACTION_RANGE,
      min_fps_n, min_fps_d, max_fps_n, max_fps_d, NULL);
  if (codec_details->format_id == kVTFormatH264) {
    gst_structure_set (gst_caps_get_structure (src_caps, 0),
        "stream-format", G_TYPE_STRING, "avc", NULL);
  }
  src_template = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
      src_caps);
  gst_element_class_add_pad_template (element_class, src_template);
}
Beispiel #9
0
static GstCaps *
gst_video_scale_get_capslist (void)
{
  static GstCaps *caps = NULL;
  static volatile gsize inited = 0;

  if (g_once_init_enter (&inited)) {
    gint i;

    g_assert (caps == NULL);

    caps = gst_caps_new_empty ();
    for (i = 0; i < G_N_ELEMENTS (gst_video_scale_format_caps); i++)
      gst_caps_append (caps,
          gst_caps_make_writable
          (gst_static_caps_get (&gst_video_scale_format_caps[i])));
    g_once_init_leave (&inited, 1);
  }

  return caps;
}
Beispiel #10
0
static gboolean match_element(GstPluginFeature *feature, gpointer gdata) {
    struct typeinfo *data = (struct typeinfo*)gdata;
    GstElementFactory *factory;
    const GList *list;

    if (!GST_IS_ELEMENT_FACTORY(feature))
        return FALSE;
    factory = GST_ELEMENT_FACTORY(feature);
    if (!strstr(gst_element_factory_get_klass(factory), data->type))
        return FALSE;
    for (list = gst_element_factory_get_static_pad_templates(factory); list; list = list->next) {
        GstStaticPadTemplate *pad = (GstStaticPadTemplate*)list->data;
        GstCaps *caps;
        gboolean ret;
        if (pad->direction != GST_PAD_SINK)
            continue;
        caps = gst_static_caps_get(&pad->static_caps);
        ret = gst_caps_is_always_compatible(caps, data->caps);
        gst_caps_unref(caps);
        if (ret)
            return TRUE;
    }
    return FALSE;
}
void
_bp_vis_pipeline_setup (BansheePlayer *player)
{
    // The basic pipeline we're constructing is:
    // .audiotee ! queue ! audioresample ! audioconvert ! fakesink

    GstElement *fakesink, *converter, *resampler, *audiosinkqueue;
    GstCaps *caps;
    GstPad *teepad;
    GstPad *pad;

    player->vis_buffer = NULL;
    player->vis_fft = gst_fft_f32_new (SLICE_SIZE * 2, FALSE);
    player->vis_fft_buffer = g_new (GstFFTF32Complex, SLICE_SIZE + 1);
    player->vis_fft_sample_buffer = g_new0 (gfloat, SLICE_SIZE);
    
    // Core elements, if something fails here, it's the end of the world
    audiosinkqueue = gst_element_factory_make ("queue", "vis-queue");

    pad = gst_element_get_static_pad (audiosinkqueue, "sink");
    gst_pad_add_event_probe (pad, G_CALLBACK (_bp_vis_pipeline_event_probe), player);
    gst_object_unref (GST_OBJECT (pad));

    resampler = gst_element_factory_make ("audioresample", "vis-resample");
    converter = gst_element_factory_make ("audioconvert", "vis-convert");
    fakesink = gst_element_factory_make ("fakesink", "vis-sink");

    if (audiosinkqueue == NULL || resampler == NULL || converter == NULL || fakesink == NULL) {
        bp_debug ("Could not construct visualization pipeline, a fundamental element could not be created");
        return;
    }

    // Keep around the 5 most recent seconds of audio so that when resuming
    // visualization we have something to show right away.
    g_object_set (G_OBJECT (audiosinkqueue),
            "leaky", 2,
            "max-size-buffers", 0,
            "max-size-bytes", 0,
            "max-size-time", GST_SECOND * 5,
            NULL);
    
    g_signal_connect (G_OBJECT (fakesink), "handoff", G_CALLBACK (bp_vis_pcm_handoff), player);

    g_object_set (G_OBJECT (fakesink),
            // This enables the handoff signal.
            "signal-handoffs", TRUE,
            // Synchronize so we see vis at the same time as we hear it.
            "sync", TRUE,
            // Drop buffers if they come in too late.  This is mainly used when
            // thawing the vis pipeline.
            "max-lateness", GST_SECOND / 120,
            // Deliver buffers one frame early.  This allows for rendering
            // time.  (TODO: It would be great to calculate this on-the-fly so
            // we match the rendering time.
            "ts-offset", -GST_SECOND / 60,
            // Don't go to PAUSED when we freeze the pipeline.
            "async", FALSE, NULL);
    
    gst_bin_add_many (GST_BIN (player->audiobin), audiosinkqueue, resampler,
                      converter, fakesink, NULL);
    
    pad = gst_element_get_static_pad (audiosinkqueue, "sink");
    teepad = gst_element_get_request_pad (player->audiotee, "src%d");
    gst_pad_link (teepad, pad);
    gst_object_unref (GST_OBJECT (teepad));
    gst_object_unref (GST_OBJECT (pad));
    
    gst_element_link_many (audiosinkqueue, resampler, converter, NULL);
    
    caps = gst_static_caps_get (&vis_data_sink_caps);
    gst_element_link_filtered (converter, fakesink, caps);
    gst_caps_unref (caps);
    
    player->vis_buffer = gst_adapter_new ();
    player->vis_resampler = resampler;
    player->vis_thawing = FALSE;
    player->vis_enabled = FALSE;

    // Disable the pipeline till we hear otherwise from managed land.
    _bp_vis_pipeline_set_blocked (player, TRUE);
}
static GstCaps *
gst_dvbsub_overlay_get_videosink_caps (GstDVBSubOverlay * render, GstPad * pad,
    GstCaps * filter)
{
  GstPad *srcpad = render->srcpad;
  GstCaps *peer_caps = NULL, *caps = NULL, *dvdsub_overlay_filter = NULL;

  if (filter) {
    /* filter caps + composition feature + filter caps
     * filtered by the software caps. */
    GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps);
    dvdsub_overlay_filter =
        gst_dvbsub_overlay_add_feature_and_intersect (filter,
        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
    gst_caps_unref (sw_caps);

    GST_DEBUG_OBJECT (render, "dvdsub_overlay filter %" GST_PTR_FORMAT,
        dvdsub_overlay_filter);
  }

  peer_caps = gst_pad_peer_query_caps (srcpad, dvdsub_overlay_filter);

  if (dvdsub_overlay_filter)
    gst_caps_unref (dvdsub_overlay_filter);

  if (peer_caps) {

    GST_DEBUG_OBJECT (pad, "peer caps  %" GST_PTR_FORMAT, peer_caps);

    if (gst_caps_is_any (peer_caps)) {

      /* if peer returns ANY caps, return filtered src pad template caps */
      caps = gst_pad_get_pad_template_caps (srcpad);

    } else {

      /* duplicate caps which contains the composition into one version with
       * the meta and one without. Filter the other caps by the software caps */
      GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps);
      caps = gst_dvbsub_overlay_intersect_by_feature (peer_caps,
          GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
      gst_caps_unref (sw_caps);
    }

    gst_caps_unref (peer_caps);

  } else {
    /* no peer, our padtemplate is enough then */
    caps = gst_pad_get_pad_template_caps (pad);
  }

  if (filter) {
    GstCaps *intersection;

    intersection =
        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
    gst_caps_unref (caps);
    caps = intersection;
  }

  GST_DEBUG_OBJECT (render, "returning  %" GST_PTR_FORMAT, caps);

  return caps;
}
Beispiel #13
0
int
main (int argc,
      char *argv[])
{
    gst_init (&argc, &argv);
    
    GstElementFactory *factory = gst_element_factory_find("ffmpegcolorspace"); 
    const GList *list = gst_element_factory_get_static_pad_templates(factory);  
    while (NULL != list) {  
      GstStaticPadTemplate *templ = (GstStaticPadTemplate *)list->data;  
      // name  
      g_print("+++ template name %s\n", templ->name_template);  
      // direction  
      g_print ("direction: ");  
      switch (templ->direction) {  
        case GST_PAD_UNKNOWN:  
          g_print ("unknown\n");  
          break;  
        case GST_PAD_SRC:  
          g_print ("src\n");  
          break;  
        case GST_PAD_SINK:  
          g_print ("sink\n");  
          break;  
        default:  
          g_print ("this is a bug\n");  
          break;  
      }  

      // presence  
      g_print ("presence: ");  
      switch (templ->presence) {  
        case GST_PAD_ALWAYS:  
          g_print ("always\n");  
          break;  
        case GST_PAD_SOMETIMES:  
          g_print ("sometimes\n");  
          break;  
        case GST_PAD_REQUEST:  
          g_print ("request\n");  
          break;  
        default:  
          g_print ("this is a bug\n");  
          break;  
      }  

      // caps  
      GstCaps *caps = gst_static_caps_get(&templ->static_caps);  
      // copying for removing fields in struture  
      GstCaps *copy = gst_caps_copy(caps);  
      gst_caps_unref(caps);  

      guint size = gst_caps_get_size(copy);  
      guint i = 0;  
      g_print("size %u\n", size);  
      for (; i < size; i++) {  
        GstStructure *structure = gst_caps_get_structure(copy, i);  
        gst_structure_remove_fields(structure,  
                                    "format", "width", "height", "framerate",  
                                    NULL);  
        GstCaps *copy_nth = gst_caps_copy_nth(copy, i);   
        gchar *caps_str = gst_caps_to_string(copy_nth);   
        g_print("    caps num %u is %s\n", i, caps_str);   
        g_free(caps_str);   
        gst_caps_unref(copy_nth);   
      }  
      gst_caps_unref(copy);  
      list = g_list_next(list);  
    }  
    gst_object_unref(factory); 

    gst_deinit();  // for memory testing  
    return 0;
}
Beispiel #14
0
static gboolean
rsndec_factory_filter (GstPluginFeature * feature, RsnDecFactoryFilterCtx * ctx)
{
  GstElementFactory *factory;
  guint rank;
  const gchar *klass;
  const GList *templates;
  GList *walk;
  gboolean can_sink = FALSE;

  /* we only care about element factories */
  if (!GST_IS_ELEMENT_FACTORY (feature))
    return FALSE;

  factory = GST_ELEMENT_FACTORY (feature);

  klass = gst_element_factory_get_klass (factory);
  /* only decoders can play */
  if (strstr (klass, "Decoder") == NULL)
    return FALSE;

  /* only select elements with autoplugging rank */
  rank = gst_plugin_feature_get_rank (feature);
  if (rank < GST_RANK_MARGINAL)
    return FALSE;

  /* See if the element has a sink pad that can possibly sink this caps */

  /* get the templates from the element factory */
  templates = gst_element_factory_get_static_pad_templates (factory);
  for (walk = (GList *) templates; walk && !can_sink; walk = g_list_next (walk)) {
    GstStaticPadTemplate *templ = walk->data;

    /* we only care about the sink templates */
    if (templ->direction == GST_PAD_SINK) {
      GstCaps *intersect;
      GstCaps *tmpl_caps;

      /* try to intersect the caps with the caps of the template */
      tmpl_caps = gst_static_caps_get (&templ->static_caps);

      intersect = gst_caps_intersect (ctx->desired_caps, tmpl_caps);
      gst_caps_unref (tmpl_caps);

      /* check if the intersection is empty */
      if (!gst_caps_is_empty (intersect)) {
        /* non empty intersection, we can use this element */
        can_sink = TRUE;
        ctx->decoder_caps = gst_caps_merge (ctx->decoder_caps, intersect);
      } else
        gst_caps_unref (intersect);
    }
  }

  if (can_sink) {
    GST_DEBUG ("Found decoder element %s (%s)",
        gst_element_factory_get_longname (factory),
        gst_plugin_feature_get_name (feature));
  }

  return can_sink;
}
Beispiel #15
0
static VALUE
rg_get(VALUE self)
{
    return GST_CAPS2RVAL(gst_static_caps_get(SELF(self)));
}
Beispiel #16
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;
}
/* if element caps already in list, will make sure Transform elements have
 * priority and replace old ones */
static GList *
create_codec_cap_list (GstElementFactory *factory,
                       GstPadDirection direction,
                       GList *list,
                       GstCaps *rtp_caps)
{
  const GList *pads = factory->staticpadtemplates;
  gint i;


  /* Let us look at each pad for stuff to add*/
  while (pads)
  {
    GstCaps *caps = NULL;
    GstStaticPadTemplate *padtemplate = NULL;

    padtemplate = (GstStaticPadTemplate *) (pads->data);
    pads = g_list_next (pads);

    if (padtemplate->direction != direction)
      continue;

    if (GST_PAD_TEMPLATE_PRESENCE (padtemplate) != GST_PAD_ALWAYS) {
      continue;
    }

    caps = gst_static_caps_get (&padtemplate->static_caps);
    /*
      DEBUG ("%s caps are %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE
      (factory)), gst_caps_to_string (caps));
    */

    /* skips caps ANY */
    if (!caps || gst_caps_is_any (caps))
    {
      goto done;
    }

    /* let us add one entry to the list per media type */
    for (i = 0; i < gst_caps_get_size (caps); i++)
    {
      CodecCap *entry = NULL;
      GList *found_item = NULL;
      GstStructure *structure = gst_caps_get_structure (caps, i);
      GstCaps *cur_caps =
          gst_caps_new_full (gst_structure_copy (structure), NULL);

      /* FIXME fix this in gstreamer! The rtpdepay element is bogus, it claims to
       * be a depayloader yet has application/x-rtp on both sides and does
       * absolutely nothing */
      /* Let's check if media caps are really media caps, this is to deal with
       * wierd elements such as rtpdepay that says it's a depayloader but has
       * application/x-rtp on src and sink pads */
      const gchar *name = gst_structure_get_name (structure);
      if (g_ascii_strcasecmp (name, "application/x-rtp") == 0)
      {
        GST_DEBUG ("skipping %s",
            gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
        continue;
      }

      /* let's check if this caps is already in the list, if so let's replace
       * that CodecCap list instead of creating a new one */
      /* we need to compare both media caps and rtp caps */
      found_item = g_list_find_custom (list, cur_caps,
          (GCompareFunc)compare_media_caps);
      if (found_item)
      {
        entry = (CodecCap *)found_item->data;
        /* if RTP caps exist and don't match nullify entry */
        if (rtp_caps && compare_rtp_caps (found_item->data, rtp_caps))
        {
          entry = NULL;
        }
      }

      if (!entry)
      {
        entry = g_slice_new0 (CodecCap);

        entry->caps = cur_caps;
        if (rtp_caps)
        {
          entry->rtp_caps = rtp_caps;
          gst_caps_ref (rtp_caps);
        }
        list = g_list_append (list, entry);
        entry->element_list1 = g_list_prepend (NULL,
          g_list_prepend (NULL, factory));
        gst_object_ref (factory);
      }
      else
      {
        GstCaps *newcaps;

        entry->element_list1->data =
          g_list_append (entry->element_list1->data, factory);
        gst_object_ref (factory);

        if (rtp_caps) {
          if (entry->rtp_caps) {
            GstCaps *new_rtp_caps;
            new_rtp_caps = gst_caps_union (rtp_caps, entry->rtp_caps);
            gst_caps_unref (entry->rtp_caps);
            entry->rtp_caps = new_rtp_caps;
          } else {
            entry->rtp_caps = rtp_caps;
            /* This shouldn't happen, its we're looking at rtp elements
             * or we're not */
            g_assert_not_reached ();
          }
          gst_caps_unref (rtp_caps);
        }

        newcaps = gst_caps_union (cur_caps, entry->caps);
        gst_caps_unref (entry->caps);
        gst_caps_unref (cur_caps);
        entry->caps = newcaps;

      }
    }
  done:
    if (caps != NULL) {
      gst_caps_unref (caps);
    }

  }

  return list;
}
Beispiel #18
0
// ----------------------------------------------------------------------------
// Handle the "pad-added" message
void
GStreamerImportFileHandle::OnPadAdded(GstPad *pad)
{
   // Retrieve the stream caps...skip stream if unavailable
   GstCaps *caps = gst_pad_get_current_caps(pad);
   if (!caps)
   {
      WARN(mPipeline, ("OnPadAdded: unable to retrieve stream caps"));
      return;
   }

   // Get the caps structure...no need to release
   GstStructure *str = gst_caps_get_structure(caps, 0);
   if (!str)
   {
      WARN(mPipeline, ("OnPadAdded: unable to retrieve caps structure"));
      gst_caps_unref(caps);
      return;
   }

   // Only accept audio streams...no need to release
   const gchar *name = gst_structure_get_name(str);
   if (!g_strrstr(name, "audio"))
   {
      WARN(mPipeline, ("OnPadAdded: bypassing '%s' stream", name));
      gst_caps_unref(caps);
      return;
   }

   // Allocate a new stream context
   GStreamContext *c = g_new0(GStreamContext, 1);
   if (!c)
   {
      WARN(mPipeline, ("OnPadAdded: unable to allocate stream context"));
      gst_caps_unref(caps);
      return;
   }

   // Set initial state
   c->mUse = true;

   // Always add it to the context list to keep the number of contexts
   // in sync with the number of streams
   g_mutex_lock(&mStreamsLock);
   g_ptr_array_add(mStreams, c);
   g_mutex_unlock(&mStreamsLock);

   // Need pointer to context during pad removal (pad-remove signal)
   SETCTX(pad, c);

   // Save the stream's start time and duration
   gst_pad_query_position(pad, GST_FORMAT_TIME, &c->mPosition);
   gst_pad_query_duration(pad, GST_FORMAT_TIME, &c->mDuration);

   // Retrieve the number of channels and validate
   gint channels = -1;
   gst_structure_get_int(str, "channels", &channels);
   if (channels <= 0)
   {
      WARN(mPipeline, ("OnPadAdded: channel count is invalid %d", channels));
      gst_caps_unref(caps);
      return;
   }
   c->mNumChannels = channels;

   // Retrieve the sample rate and validate
   gint rate = -1;
   gst_structure_get_int(str, "rate", &rate);
   if (rate <= 0)
   {
      WARN(mPipeline, ("OnPadAdded: sample rate is invalid %d", rate));
      gst_caps_unref(caps);
      return;
   }
   c->mSampleRate = (double) rate;

   c->mType = g_strdup(name);
   if (c->mType == NULL)
   {
      WARN(mPipeline, ("OnPadAdded: unable to allocate audio type"));
      gst_caps_unref(caps);
      return;
   }

   // Done with capabilities
   gst_caps_unref(caps);

   // Create audioconvert element
   c->mConv = gst_element_factory_make("audioconvert", NULL);
   if (!c->mConv)
   {
      WARN(mPipeline, ("OnPadAdded: failed to create audioconvert element"));
      return;
   }

   // Create appsink element
   c->mSink = gst_element_factory_make("appsink", NULL);
   if (!c->mSink)
   {
      WARN(mPipeline, ("OnPadAdded: failed to create appsink element"));
      return;
   }
   SETCTX(c->mSink, c);

   // Set the appsink callbacks and add the context pointer
   gst_app_sink_set_callbacks(GST_APP_SINK(c->mSink), &AppSinkCallbacks, this, NULL);

   // Set the capabilities that we desire
   caps = gst_static_caps_get(&supportedCaps);
   if (!caps)
   {
      WARN(mPipeline, ("OnPadAdded: failed to create static caps"));
      return;
   }
   gst_app_sink_set_caps(GST_APP_SINK(c->mSink), caps);
   gst_caps_unref(caps);

   // Do not sync to the clock...process as quickly as possible
   gst_base_sink_set_sync(GST_BASE_SINK(c->mSink), FALSE);

   // Don't drop buffers...allow queue to build unfettered
   gst_app_sink_set_drop(GST_APP_SINK(c->mSink), FALSE);

   // Add both elements to the pipeline
   gst_bin_add_many(GST_BIN(mPipeline), c->mConv, c->mSink, NULL);

   // Link them together
   if (!gst_element_link(c->mConv, c->mSink))
   {
      WARN(mPipeline, ("OnPadAdded: failed to link autioconvert and appsink"));
      return;
   }

   // Link the audiconvert sink pad to the src pad
   GstPadLinkReturn ret = GST_PAD_LINK_OK;
   GstPad *convsink = gst_element_get_static_pad(c->mConv, "sink");
   if (convsink)
   {
      ret = gst_pad_link(pad, convsink);
      gst_object_unref(convsink);
   }
   if (!convsink || ret != GST_PAD_LINK_OK)
   {
      WARN(mPipeline, ("OnPadAdded: failed to link uridecodebin to audioconvert - %d", ret));
      return;
   }

   // Synchronize audioconvert state with parent
   if (!gst_element_sync_state_with_parent(c->mConv))
   {
      WARN(mPipeline, ("OnPadAdded: unable to sync audioconvert state"));
      return;
   }

   // Synchronize appsink state with parent
   if (!gst_element_sync_state_with_parent(c->mSink))
   {
      WARN(mPipeline, ("OnPadAdded: unable to sync appaink state"));
      return;
   }

   return;
}
Beispiel #19
0
int
main (int argc, char *argv[])
{
  gboolean testret;
  gint ret = 0;

  gst_init (&argc, &argv);

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&mp1parsecaps),
      gst_static_caps_get (&rawcaps));
  g_print ("4 <-> 2 == %d (invalid, wrong major type)\n", testret);
  ret = ret + (testret == FALSE) ? 0 : 1;

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&mp1parsecaps),
      gst_static_caps_get (&sinkcaps));
  g_print ("4 <-> 1 == %d (valid, subset)\n", testret);
  ret = ret + (testret == TRUE) ? 0 : 1;

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&sinkcaps),
      gst_static_caps_get (&mp1parsecaps));
  g_print ("1 <-> 4 == %d (invalid, superset)\n", testret);
  ret = ret + (testret == FALSE) ? 0 : 1;

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&rawcaps),
      gst_static_caps_get (&rawcaps2));
  g_print ("2 <-> 3 == %d (invalid, ranges)\n", testret);
  ret = ret + (testret == FALSE) ? 0 : 1;

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&rawcaps),
      gst_static_caps_get (&rawcaps3));
  g_print ("2 <-> 5 == %d (valid)\n", testret);
  ret = ret + (testret == TRUE) ? 0 : 1;

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&rawcaps3),
      gst_static_caps_get (&rawcaps));
  g_print ("5 <-> 2 == %d (invalid)\n", testret);
  ret = ret + (testret == FALSE) ? 0 : 1;

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&rawcaps2),
      gst_static_caps_get (&rawcaps3));
  g_print ("3 <-> 5 == %d (valid)\n", testret);
  ret = ret + (testret == TRUE) ? 0 : 1;

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&rawcaps2),
      gst_static_caps_get (&rawcaps));
  g_print ("3 <-> 2 == %d (invalid, property missing in source)\n", testret);
  ret = ret + (testret == FALSE) ? 0 : 1;

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&rawcaps),
      gst_static_caps_get (&rawcaps));
  g_print ("2 <-> 2 == %d (valid, same caps)\n", testret);
  ret = ret + (testret == TRUE) ? 0 : 1;

  testret = gst_caps_is_always_compatible (gst_static_caps_get (&rawcaps6),
      gst_static_caps_get (&rawcaps7));
  g_print ("6 <-> 7 == %d (invalid, second caps doesn't fit)\n", testret);
  ret = ret + (testret == FALSE) ? 0 : 1;

  return ret;
}
Beispiel #20
0
int
main (int argc, char *argv[])
{
    xmlDocPtr doc;
    xmlNodePtr parent;
    GstCaps *caps;

    gst_init (&argc, &argv);

    doc = xmlNewDoc ((const xmlChar *) "1.0");
    doc->xmlRootNode =
        xmlNewDocNode (doc, NULL, (const xmlChar *) "Capabilities", NULL);

    /*
       for (i = 0; i<100000; i++) {
       caps = gst_caps_intersect (gst_static_caps_get (rawcaps3), GST_CAPS_GET (rawcaps4));
       gst_caps_unref (caps);
       }
     */

    caps = gst_caps_intersect (gst_static_caps_get (&sinkcaps),
                               gst_static_caps_get (&mp1parsecaps));
    parent =
        xmlNewChild (doc->xmlRootNode, NULL, (const xmlChar *) "Capabilities1",
                     NULL);
    gst_caps_save_thyself (caps, parent);

    caps = gst_caps_intersect (gst_static_caps_get (&rawcaps),
                               gst_static_caps_get (&rawcaps2));
    parent =
        xmlNewChild (doc->xmlRootNode, NULL, (const xmlChar *) "Capabilities2",
                     NULL);
    gst_caps_save_thyself (caps, parent);

    caps = gst_caps_intersect (gst_static_caps_get (&rawcaps3),
                               gst_static_caps_get (&rawcaps4));
    parent =
        xmlNewChild (doc->xmlRootNode, NULL, (const xmlChar *) "Capabilities3",
                     NULL);
    gst_caps_save_thyself (caps, parent);

    caps = gst_caps_intersect (gst_static_caps_get (&rawcaps3),
                               gst_static_caps_get (&rawcaps5));
    parent =
        xmlNewChild (doc->xmlRootNode, NULL, (const xmlChar *) "Capabilities4",
                     NULL);
    gst_caps_save_thyself (caps, parent);

    caps = gst_caps_intersect (gst_static_caps_get (&rawcaps6),
                               gst_caps_new_full (gst_structure_copy (gst_caps_get_structure
                                       (gst_static_caps_get (&rawcaps6), 0)), NULL));
    parent =
        xmlNewChild (doc->xmlRootNode, NULL, (const xmlChar *) "Capabilities5",
                     NULL);
    gst_caps_save_thyself (caps, parent);

    caps = gst_caps_intersect (gst_static_caps_get (&rawcaps7),
                               gst_static_caps_get (&rawcaps8));
    g_print ("intersection: %s\n", gst_caps_to_string (caps));

    xmlDocDump (stdout, doc);

    return 0;
}
/* Probing functions */
gboolean
gst_v4l2_is_vp8_enc (GstCaps * sink_caps, GstCaps * src_caps)
{
  return gst_v4l2_is_video_enc (sink_caps, src_caps,
      gst_static_caps_get (&src_template_caps));
}
static GstPadLinkReturn
gst_hermes_colorspace_link (GstPad * pad, const GstCaps * caps)
{
  GstHermesColorspace *space;
  GstPad *otherpad;
  GstStructure *structure;
  GstPadLinkReturn link_ret;
  int width, height;
  double fps;
  int i;

  space = GST_HERMES_COLORSPACE (gst_pad_get_parent (pad));
  otherpad = (pad == space->sinkpad) ? space->srcpad : space->sinkpad;

  link_ret = gst_pad_try_set_caps (otherpad, caps);
  if (link_ret == GST_PAD_LINK_OK) {
    space->passthru = TRUE;
    return link_ret;
  }

  structure = gst_caps_get_structure (caps, 0);

  for (i = 0; i < G_N_ELEMENTS (gst_hermes_colorspace_formats); i++) {
    GstCaps *icaps;
    GstCaps *fcaps;

    fcaps =
        gst_caps_copy (gst_static_caps_get (&gst_hermes_colorspace_formats
            [i].caps));

    icaps = gst_caps_intersect (caps, fcaps);
    if (!gst_caps_is_empty (icaps)) {
      break;
    }
    gst_caps_free (icaps);
  }
  if (i == G_N_ELEMENTS (gst_hermes_colorspace_formats)) {
    g_assert_not_reached ();
    return GST_PAD_LINK_REFUSED;
  }

  gst_structure_get_int (structure, "width", &width);
  gst_structure_get_int (structure, "height", &height);
  gst_structure_get_double (structure, "framerate", &fps);

  GST_INFO ("size: %dx%d", space->width, space->height);

  if (gst_pad_is_negotiated (otherpad)) {
    GstCaps *othercaps;

    othercaps = gst_caps_copy (gst_pad_get_negotiated_caps (otherpad));

    gst_caps_set_simple (othercaps,
        "width", G_TYPE_INT, width,
        "height", G_TYPE_INT, height, "framerate", G_TYPE_DOUBLE, fps, NULL);

    link_ret = gst_pad_try_set_caps (otherpad, othercaps);
    if (link_ret != GST_PAD_LINK_OK) {
      return link_ret;
    }
  }

  if (pad == space->srcpad) {
    space->src_format_index = i;
    gst_hermes_colorspace_structure_to_hermes_format (&space->src_format,
        structure);
  } else {
    space->sink_format_index = i;
    gst_hermes_colorspace_structure_to_hermes_format (&space->sink_format,
        structure);
  }

  space->sink_stride = width * (space->sink_format.bits / 8);
  space->src_stride = width * (space->src_format.bits / 8);
  space->sink_size = space->sink_stride * height;
  space->src_size = space->src_stride * height;
  space->width = width;
  space->height = height;
  space->fps = fps;

  if (gst_pad_is_negotiated (otherpad)) {
    if (!Hermes_ConverterRequest (space->h_handle, &space->sink_format,
            &space->src_format)) {
      g_warning ("Hermes: could not get converter\n");
      return GST_PAD_LINK_REFUSED;
    }
    g_print ("inited\n");
  }

  return GST_PAD_LINK_OK;
}
static void
try_to_plug (GstPad        *pad,
	     const GstCaps *caps)
{
  GstObject *parent = GST_OBJECT (GST_OBJECT_PARENT (pad));
  const gchar *mime;
  const GList *item;
  GstCaps *res, *audiocaps;

  /* don't plug if we're already plugged - FIXME: memleak for pad */
  if (GST_PAD_IS_LINKED (gst_element_get_pad (audiosink, "sink"))) {
    g_print ("Omitting link for pad %s:%s because we're already linked\n",
	     GST_OBJECT_NAME (parent), GST_OBJECT_NAME (pad));
    return;
  }

  /* as said above, we only try to plug audio... Omit video */
  mime = gst_structure_get_name (gst_caps_get_structure (caps, 0));
  if (g_strrstr (mime, "video")) {
    g_print ("Omitting link for pad %s:%s because mimetype %s is non-audio\n",
	     GST_OBJECT_NAME (parent), GST_OBJECT_NAME (pad), mime);
    return;
  }

  /* can it link to the audiopad? */
  audiocaps = gst_pad_get_caps (gst_element_get_pad (audiosink, "sink"));
  res = gst_caps_intersect (caps, audiocaps);
  if (res && !gst_caps_is_empty (res)) {
    g_print ("Found pad to link to audiosink - plugging is now done\n");
    close_link (pad, audiosink, "sink", NULL);
    gst_caps_unref (audiocaps);
    gst_caps_unref (res);
    return;
  }
  gst_caps_unref (audiocaps);
  gst_caps_unref (res);

  /* try to plug from our list */
  for (item = factories; item != NULL; item = item->next) {
    GstElementFactory *factory = GST_ELEMENT_FACTORY (item->data);
    const GList *pads;

    for (pads = gst_element_factory_get_static_pad_templates (factory);
         pads != NULL; pads = pads->next) {
      GstStaticPadTemplate *templ = pads->data;

      /* find the sink template - need an always pad*/
      if (templ->direction != GST_PAD_SINK ||
          templ->presence != GST_PAD_ALWAYS) {
        continue;
      }

      /* can it link? */
      res = gst_caps_intersect (caps,
          gst_static_caps_get (&templ->static_caps));
      if (res && !gst_caps_is_empty (res)) {
        GstElement *element;
        gchar *name_template = g_strdup (templ->name_template);

        /* close link and return */
        gst_caps_unref (res);
        element = gst_element_factory_create (factory, NULL);
        close_link (pad, element, name_template,
		    gst_element_factory_get_static_pad_templates (factory));
        g_free (name_template);
        return;
      }
      gst_caps_unref (res);

      /* we only check one sink template per factory, so move on to the
       * next factory now */
      break;
    }
  }

  /* if we get here, no item was found */
  g_print ("No compatible pad found to decode %s on %s:%s\n",
	   mime, GST_OBJECT_NAME (parent), GST_OBJECT_NAME (pad));
}