Esempio n. 1
0
static gboolean
gst_capsfilter_accept_caps (GstBaseTransform * base,
    GstPadDirection direction, GstCaps * caps)
{
  GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
  GstCaps *filter_caps;
  gboolean ret;

  GST_OBJECT_LOCK (capsfilter);
  filter_caps = gst_caps_ref (capsfilter->filter_caps);
  GST_OBJECT_UNLOCK (capsfilter);

  ret = gst_caps_can_intersect (caps, filter_caps);
  GST_DEBUG_OBJECT (capsfilter, "can intersect: %d", ret);
  if (ret) {
    /* if we can intersect, see if the other end also accepts */
    if (direction == GST_PAD_SRC)
      ret =
          gst_pad_peer_query_accept_caps (GST_BASE_TRANSFORM_SINK_PAD (base),
          caps);
    else
      ret =
          gst_pad_peer_query_accept_caps (GST_BASE_TRANSFORM_SRC_PAD (base),
          caps);
    GST_DEBUG_OBJECT (capsfilter, "peer accept: %d", ret);
  }

  gst_caps_unref (filter_caps);

  return ret;
}
Esempio n. 2
0
static void
gst_capsfilter_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstCapsFilter *capsfilter = GST_CAPSFILTER (object);

  switch (prop_id) {
    case PROP_FILTER_CAPS:{
      GstCaps *new_caps;
      GstCaps *old_caps;
      const GstCaps *new_caps_val = gst_value_get_caps (value);

      if (new_caps_val == NULL) {
        new_caps = gst_caps_new_any ();
      } else {
        new_caps = (GstCaps *) new_caps_val;
        gst_caps_ref (new_caps);
      }

      old_caps = capsfilter->filter_caps;
      capsfilter->filter_caps = new_caps;
      gst_caps_unref (old_caps);

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

      /* FIXME: Need to activate these caps on the pads
       * http://bugzilla.gnome.org/show_bug.cgi?id=361718
       */
      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
Esempio n. 3
0
static GstCaps *
gst_capsfilter_transform_caps (GstBaseTransform * base,
    GstPadDirection direction, GstCaps * caps, GstCaps * filter)
{
  GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
  GstCaps *ret, *filter_caps, *tmp;

  GST_OBJECT_LOCK (capsfilter);
  filter_caps = gst_caps_ref (capsfilter->filter_caps);
  GST_OBJECT_UNLOCK (capsfilter);

  if (filter) {
    tmp =
        gst_caps_intersect_full (filter, filter_caps, GST_CAPS_INTERSECT_FIRST);
    gst_caps_unref (filter_caps);
    filter_caps = tmp;
  }

  ret = gst_caps_intersect_full (filter_caps, caps, GST_CAPS_INTERSECT_FIRST);

  GST_DEBUG_OBJECT (capsfilter, "input:     %" GST_PTR_FORMAT, caps);
  GST_DEBUG_OBJECT (capsfilter, "filter:    %" GST_PTR_FORMAT, filter);
  GST_DEBUG_OBJECT (capsfilter, "caps filter:    %" GST_PTR_FORMAT,
      filter_caps);
  GST_DEBUG_OBJECT (capsfilter, "intersect: %" GST_PTR_FORMAT, ret);

  gst_caps_unref (filter_caps);

  return ret;
}
Esempio n. 4
0
static void
gst_capsfilter_dispose (GObject * object)
{
  GstCapsFilter *filter = GST_CAPSFILTER (object);

  gst_caps_replace (&filter->filter_caps, NULL);

  G_OBJECT_CLASS (parent_class)->dispose (object);
}
Esempio n. 5
0
static gboolean
gst_capsfilter_stop (GstBaseTransform * trans)
{
  GstCapsFilter *filter = GST_CAPSFILTER (trans);

  g_list_free_full (filter->pending_events, (GDestroyNotify) gst_event_unref);
  filter->pending_events = NULL;

  return TRUE;
}
Esempio n. 6
0
static void
gst_capsfilter_dispose (GObject * object)
{
  GstCapsFilter *filter = GST_CAPSFILTER (object);

  gst_caps_replace (&filter->filter_caps, NULL);
  g_list_free_full (filter->pending_events, (GDestroyNotify) gst_event_unref);
  filter->pending_events = NULL;

  G_OBJECT_CLASS (parent_class)->dispose (object);
}
Esempio n. 7
0
static GstCaps *
gst_capsfilter_transform_caps (GstBaseTransform * base,
    GstPadDirection direction, GstCaps * caps)
{
  GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
  GstCaps *ret;

  ret = gst_caps_intersect (caps, capsfilter->filter_caps);

  return ret;
}
Esempio n. 8
0
static void
gst_capsfilter_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * pspec)
{
  GstCapsFilter *capsfilter = GST_CAPSFILTER (object);

  switch (prop_id) {
    case PROP_FILTER_CAPS:
      gst_value_set_caps (value, capsfilter->filter_caps);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
Esempio n. 9
0
/* Queue the segment event if there was no caps event */
static gboolean
gst_capsfilter_sink_event (GstBaseTransform * trans, GstEvent * event)
{
  GstCapsFilter *filter = GST_CAPSFILTER (trans);

  if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
    GList *l;

    for (l = filter->pending_events; l;) {
      if (GST_EVENT_TYPE (l->data) == GST_EVENT_SEGMENT) {
        gst_event_unref (l->data);
        l = g_list_delete_link (l, l);
      } else {
        l = l->next;
      }
    }
  }

  if (!GST_EVENT_IS_STICKY (event) || GST_EVENT_TYPE (event) <= GST_EVENT_CAPS)
    goto done;

  /* If we get EOS before any buffers, just push all pending events */
  if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
    GList *l;

    for (l = g_list_last (filter->pending_events); l; l = l->prev) {
      GST_LOG_OBJECT (trans, "Forwarding %s event",
          GST_EVENT_TYPE_NAME (l->data));
      GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, l->data);
    }
    g_list_free (filter->pending_events);
    filter->pending_events = NULL;
  } else if (!gst_pad_has_current_caps (trans->sinkpad)) {
    GST_LOG_OBJECT (trans, "Got %s event before caps, queueing",
        GST_EVENT_TYPE_NAME (event));

    filter->pending_events = g_list_prepend (filter->pending_events, event);

    return TRUE;
  }

done:

  GST_LOG_OBJECT (trans, "Forwarding %s event", GST_EVENT_TYPE_NAME (event));
  return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
}
Esempio n. 10
0
static GstCaps *
gst_capsfilter_transform_caps (GstBaseTransform * base,
    GstPadDirection direction, GstCaps * caps)
{
  GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
  GstCaps *ret, *filter_caps;

  GST_OBJECT_LOCK (capsfilter);
  filter_caps = gst_caps_ref (capsfilter->filter_caps);
  GST_OBJECT_UNLOCK (capsfilter);

  ret = gst_caps_intersect (caps, filter_caps);
  GST_DEBUG_OBJECT (capsfilter, "filter:    %" GST_PTR_FORMAT, filter_caps);
  GST_DEBUG_OBJECT (capsfilter, "intersect: %" GST_PTR_FORMAT, ret);

  gst_caps_unref (filter_caps);

  return ret;
}
Esempio n. 11
0
static void
gst_capsfilter_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstCapsFilter *capsfilter = GST_CAPSFILTER (object);

  switch (prop_id) {
    case PROP_FILTER_CAPS:{
      GstCaps *new_caps;
      GstCaps *old_caps;
      const GstCaps *new_caps_val = gst_value_get_caps (value);

      if (new_caps_val == NULL) {
        new_caps = gst_caps_new_any ();
      } else {
        new_caps = (GstCaps *) new_caps_val;
        gst_caps_ref (new_caps);
      }

      GST_OBJECT_LOCK (capsfilter);
      old_caps = capsfilter->filter_caps;
      capsfilter->filter_caps = new_caps;
      GST_OBJECT_UNLOCK (capsfilter);

      gst_caps_unref (old_caps);

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

      gst_base_transform_reconfigure_sink (GST_BASE_TRANSFORM (object));
      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
Esempio n. 12
0
static void
gst_capsfilter_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstCapsFilter *capsfilter = GST_CAPSFILTER (object);

  switch (prop_id) {
    case PROP_FILTER_CAPS:{
      GstCaps *new_caps;
      GstCaps *old_caps, *suggest, *nego;
      const GstCaps *new_caps_val = gst_value_get_caps (value);

      if (new_caps_val == NULL) {
        new_caps = gst_caps_new_any ();
      } else {
        new_caps = (GstCaps *) new_caps_val;
        gst_caps_ref (new_caps);
      }

      GST_OBJECT_LOCK (capsfilter);
      old_caps = capsfilter->filter_caps;
      capsfilter->filter_caps = new_caps;
      GST_OBJECT_UNLOCK (capsfilter);

      gst_caps_unref (old_caps);

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

      /* filter the currently negotiated format against the new caps */
      GST_OBJECT_LOCK (GST_BASE_TRANSFORM_SINK_PAD (object));
      nego = GST_PAD_CAPS (GST_BASE_TRANSFORM_SINK_PAD (object));
      if (nego) {
        GST_DEBUG_OBJECT (capsfilter, "we had negotiated caps %" GST_PTR_FORMAT,
            nego);

        if (G_UNLIKELY (gst_caps_is_any (new_caps))) {
          GST_DEBUG_OBJECT (capsfilter, "not settings any suggestion");

          suggest = NULL;
        } else {
          GstStructure *s1, *s2;

          /* first check if the name is the same */
          s1 = gst_caps_get_structure (nego, 0);
          s2 = gst_caps_get_structure (new_caps, 0);

          if (gst_structure_get_name_id (s1) == gst_structure_get_name_id (s2)) {
            /* same name, copy all fields from the new caps into the previously
             * negotiated caps */
            suggest = gst_caps_copy (nego);
            s1 = gst_caps_get_structure (suggest, 0);
            gst_structure_foreach (s2, (GstStructureForeachFunc) copy_func, s1);
            GST_DEBUG_OBJECT (capsfilter, "copied structure fields");
          } else {
            GST_DEBUG_OBJECT (capsfilter, "different structure names");
            /* different names, we can only suggest the complete caps */
            suggest = gst_caps_copy (new_caps);
          }
        }
      } else {
        GST_DEBUG_OBJECT (capsfilter, "no negotiated caps");
        /* no previous caps, the getcaps function will be used to find suitable
         * caps */
        suggest = NULL;
      }
      GST_OBJECT_UNLOCK (GST_BASE_TRANSFORM_SINK_PAD (object));

      GST_DEBUG_OBJECT (capsfilter, "suggesting new caps %" GST_PTR_FORMAT,
          suggest);
      gst_base_transform_suggest (GST_BASE_TRANSFORM (object), suggest, 0);
      if (suggest)
        gst_caps_unref (suggest);

      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
Esempio n. 13
0
/* Ouput buffer preparation ... if the buffer has no caps, and our allowed
 * output caps is fixed, then send the caps downstream, making sure caps are
 * sent before segment event.
 *
 * This ensures that caps event is sent if we can, so that pipelines like:
 *   gst-launch filesrc location=rawsamples.raw !
 *       audio/x-raw,format=S16LE,rate=48000,channels=2 ! alsasink
 * will work.
 */
static GstFlowReturn
gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
    GstBuffer ** buf)
{
  GstFlowReturn ret = GST_FLOW_OK;

  /* always return the input as output buffer */
  *buf = input;

  if (!gst_pad_has_current_caps (trans->sinkpad)) {
    /* No caps. See if the output pad only supports fixed caps */
    GstCapsFilter *filter = GST_CAPSFILTER (trans);
    GstCaps *out_caps;
    GList *pending_events = filter->pending_events;

    GST_LOG_OBJECT (trans, "Input pad does not have caps");

    filter->pending_events = NULL;

    out_caps = gst_pad_get_current_caps (trans->srcpad);
    if (out_caps == NULL) {
      out_caps = gst_pad_get_allowed_caps (trans->srcpad);
      g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR);
    }

    out_caps = gst_caps_simplify (out_caps);

    if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) {
      GST_DEBUG_OBJECT (trans, "Have fixed output caps %"
          GST_PTR_FORMAT " to apply to srcpad", out_caps);

      if (!gst_pad_has_current_caps (trans->srcpad)) {
        if (gst_pad_set_caps (trans->srcpad, out_caps)) {
          if (pending_events) {
            GList *l;

            for (l = g_list_last (pending_events); l; l = l->prev) {
              GST_LOG_OBJECT (trans, "Forwarding %s event",
                  GST_EVENT_TYPE_NAME (l->data));
              GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans,
                  l->data);
            }
            g_list_free (pending_events);
            pending_events = NULL;
          }
        } else {
          ret = GST_FLOW_NOT_NEGOTIATED;
        }
      }

      g_list_free_full (pending_events, (GDestroyNotify) gst_event_unref);
      gst_caps_unref (out_caps);
    } else {
      gchar *caps_str = gst_caps_to_string (out_caps);

      GST_DEBUG_OBJECT (trans, "Cannot choose caps. Have unfixed output caps %"
          GST_PTR_FORMAT, out_caps);
      gst_caps_unref (out_caps);

      GST_ELEMENT_ERROR (trans, STREAM, FORMAT,
          ("Filter caps do not completely specify the output format"),
          ("Output caps are unfixed: %s", caps_str));

      g_free (caps_str);
      g_list_free_full (pending_events, (GDestroyNotify) gst_event_unref);

      ret = GST_FLOW_ERROR;
    }
  }

  return ret;
}