static void
gst_caps_setter_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstCapsSetter *filter;

  g_return_if_fail (GST_IS_CAPS_SETTER (object));
  filter = GST_CAPS_SETTER (object);

  switch (prop_id) {
    case PROP_CAPS:{
      GstCaps *new_caps;
      const GstCaps *new_caps_val = gst_value_get_caps (value);
      gint i;

      if (new_caps_val == NULL) {
        new_caps = gst_caps_new_any ();
      } else {
        new_caps = gst_caps_copy (new_caps_val);
      }

      for (i = 0; new_caps && (i < gst_caps_get_size (new_caps)); ++i) {
        GstStructure *s;

        s = gst_caps_get_structure (new_caps, i);
        if (!gst_structure_foreach (s, gst_caps_is_fixed_foreach, NULL)) {
          GST_ERROR_OBJECT (filter, "rejected unfixed caps: %" GST_PTR_FORMAT,
              new_caps);
          gst_caps_unref (new_caps);
          new_caps = NULL;
          break;
        }
      }

      if (new_caps) {
        GST_OBJECT_LOCK (filter);
        gst_caps_replace (&filter->caps, new_caps);
        /* drop extra ref */
        gst_caps_unref (new_caps);
        GST_OBJECT_UNLOCK (filter);

        GST_DEBUG_OBJECT (filter, "set new caps %" GST_PTR_FORMAT, new_caps);
      }

      /* try to activate these new caps next time around */
      gst_base_transform_reconfigure (GST_BASE_TRANSFORM (filter));
      break;
    }
    case PROP_JOIN:
      filter->join = g_value_get_boolean (value);
      break;
    case PROP_REPLACE:
      filter->replace = g_value_get_boolean (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static void
gst_caps_setter_finalize (GObject * object)
{
  GstCapsSetter *filter = GST_CAPS_SETTER (object);

  gst_caps_replace (&filter->caps, NULL);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
static GstCaps *
gst_caps_setter_transform_caps (GstBaseTransform * trans,
    GstPadDirection direction, GstCaps * caps)
{
  GstCapsSetter *filter;
  GstCaps *ret, *filter_caps;
  GstStructure *structure, *merge;
  const gchar *name;
  gint i, j;

  filter = GST_CAPS_SETTER (trans);

  GST_DEBUG_OBJECT (trans, "receiving caps: %" GST_PTR_FORMAT, caps);

  ret = gst_caps_copy (caps);

  /* this function is always called with a simple caps */
  if (!GST_CAPS_IS_SIMPLE (ret) || direction != GST_PAD_SINK)
    return ret;

  structure = gst_caps_get_structure (ret, 0);
  name = gst_structure_get_name (structure);

  GST_OBJECT_LOCK (filter);
  filter_caps = gst_caps_ref (filter->caps);
  GST_OBJECT_UNLOCK (filter);

  for (i = 0; i < gst_caps_get_size (filter_caps); ++i) {
    merge = gst_caps_get_structure (filter_caps, i);
    if (gst_structure_has_name (merge, name) || !filter->join) {

      if (!filter->join)
        gst_structure_set_name (structure, gst_structure_get_name (merge));

      if (filter->replace)
        gst_structure_remove_all_fields (structure);

      for (j = 0; j < gst_structure_n_fields (merge); ++j) {
        const gchar *fname;

        fname = gst_structure_nth_field_name (merge, j);
        gst_structure_set_value (structure, fname,
            gst_structure_get_value (merge, fname));
      }
    }
  }

  GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, ret);

  gst_caps_unref (filter_caps);

  return ret;
}
static void
gst_caps_setter_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * pspec)
{
  GstCapsSetter *filter = GST_CAPS_SETTER (object);

  switch (prop_id) {
    case PROP_CAPS:
      gst_value_set_caps (value, filter->caps);
      break;
    case PROP_JOIN:
      g_value_set_boolean (value, filter->join);
      break;
    case PROP_REPLACE:
      g_value_set_boolean (value, filter->replace);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}