Exemple #1
1
static gboolean
gst_deinterleave_src_query (GstPad * pad, GstQuery * query)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));

  gboolean res;

  res = gst_pad_query_default (pad, query);

  if (res && GST_QUERY_TYPE (query) == GST_QUERY_DURATION) {
    GstFormat format;

    gint64 dur;

    gst_query_parse_duration (query, &format, &dur);

    /* Need to divide by the number of channels in byte format
     * to get the correct value. All other formats should be fine
     */
    if (format == GST_FORMAT_BYTES && dur != -1)
      gst_query_set_duration (query, format, dur / self->channels);
  } else if (res && GST_QUERY_TYPE (query) == GST_QUERY_POSITION) {
    GstFormat format;

    gint64 pos;

    gst_query_parse_position (query, &format, &pos);

    /* Need to divide by the number of channels in byte format
     * to get the correct value. All other formats should be fine
     */
    if (format == GST_FORMAT_BYTES && pos != -1)
      gst_query_set_position (query, format, pos / self->channels);
  }

  gst_object_unref (self);
  return res;
}
Exemple #2
0
static gboolean
gst_deinterleave_sink_activate_push (GstPad * pad, gboolean active)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));

  /* Reset everything when the pad is deactivated */
  if (!active) {
    gst_deinterleave_remove_pads (self);
    if (self->pos) {
      g_free (self->pos);
      self->pos = NULL;
    }
    self->channels = 0;
    self->width = 0;
    self->func = NULL;

    if (self->pending_events) {
      g_list_foreach (self->pending_events, (GFunc) gst_mini_object_unref,
          NULL);
      g_list_free (self->pending_events);
      self->pending_events = NULL;
    }
  }

  gst_object_unref (self);

  return TRUE;
}
Exemple #3
0
static void
gst_deinterleave_finalize (GObject * obj)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (obj);

  if (self->pending_events) {
    g_list_foreach (self->pending_events, (GFunc) gst_mini_object_unref, NULL);
    g_list_free (self->pending_events);
    self->pending_events = NULL;
  }

  G_OBJECT_CLASS (parent_class)->finalize (obj);
}
Exemple #4
0
static GstStateChangeReturn
gst_deinterleave_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret;
  GstDeinterleave *self = GST_DEINTERLEAVE (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      gst_deinterleave_remove_pads (self);

      self->func = NULL;

      if (self->pending_events) {
        g_list_foreach (self->pending_events, (GFunc) gst_mini_object_unref,
            NULL);
        g_list_free (self->pending_events);
        self->pending_events = NULL;
      }
      break;
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_deinterleave_remove_pads (self);

      self->func = NULL;

      if (self->pending_events) {
        g_list_foreach (self->pending_events, (GFunc) gst_mini_object_unref,
            NULL);
        g_list_free (self->pending_events);
        self->pending_events = NULL;
      }
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      break;
    default:
      break;
  }
  return ret;
}
Exemple #5
0
static void
gst_deinterleave_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (object);

  switch (prop_id) {
    case PROP_KEEP_POSITIONS:
      g_value_set_boolean (value, self->keep_positions);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
Exemple #6
0
static gboolean
gst_deinterleave_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (parent);

  gboolean res;

  res = gst_pad_query_default (pad, parent, query);

  if (res && GST_QUERY_TYPE (query) == GST_QUERY_DURATION) {
    GstFormat format;

    gint64 dur;

    gst_query_parse_duration (query, &format, &dur);

    /* Need to divide by the number of channels in byte format
     * to get the correct value. All other formats should be fine
     */
    if (format == GST_FORMAT_BYTES && dur != -1)
      gst_query_set_duration (query, format,
          dur / GST_AUDIO_INFO_CHANNELS (&self->audio_info));
  } else if (res && GST_QUERY_TYPE (query) == GST_QUERY_POSITION) {
    GstFormat format;

    gint64 pos;

    gst_query_parse_position (query, &format, &pos);

    /* Need to divide by the number of channels in byte format
     * to get the correct value. All other formats should be fine
     */
    if (format == GST_FORMAT_BYTES && pos != -1)
      gst_query_set_position (query, format,
          pos / GST_AUDIO_INFO_CHANNELS (&self->audio_info));
  } else if (res && GST_QUERY_TYPE (query) == GST_QUERY_CAPS) {
    GstCaps *filter, *caps;

    gst_query_parse_caps (query, &filter);
    caps = gst_deinterleave_sink_getcaps (pad, parent, filter);
    gst_query_set_caps_result (query, caps);
    gst_caps_unref (caps);
  }

  return res;
}
Exemple #7
0
static GstFlowReturn
gst_deinterleave_chain (GstPad * pad, GstBuffer * buffer)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (GST_PAD_PARENT (pad));

  GstFlowReturn ret;

  g_return_val_if_fail (self->func != NULL, GST_FLOW_NOT_NEGOTIATED);
  g_return_val_if_fail (self->width > 0, GST_FLOW_NOT_NEGOTIATED);
  g_return_val_if_fail (self->channels > 0, GST_FLOW_NOT_NEGOTIATED);

  ret = gst_deinterleave_process (self, buffer);

  if (ret != GST_FLOW_OK)
    GST_DEBUG_OBJECT (self, "flow return: %s", gst_flow_get_name (ret));

  return ret;
}
Exemple #8
0
static gboolean
gst_deinterleave_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (parent);
  gboolean ret;

  GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
      GST_DEBUG_PAD_NAME (pad));

  /* Send FLUSH_STOP, FLUSH_START and EOS immediately, no matter if
   * we have src pads already or not. Queue all other events and
   * push them after we have src pads
   */
  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_FLUSH_STOP:
    case GST_EVENT_FLUSH_START:
    case GST_EVENT_EOS:
      ret = gst_pad_event_default (pad, parent, event);
      break;
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      ret = gst_deinterleave_sink_setcaps (self, caps);
      gst_event_unref (event);
      break;
    }

    default:
      if (!self->srcpads && !GST_EVENT_IS_STICKY (event)) {
        /* Sticky events are copied when creating a new pad */
        GST_OBJECT_LOCK (self);
        self->pending_events = g_list_append (self->pending_events, event);
        GST_OBJECT_UNLOCK (self);
        ret = TRUE;
      } else {
        ret = gst_pad_event_default (pad, parent, event);
      }
      break;
  }

  return ret;
}
Exemple #9
0
static GstFlowReturn
gst_deinterleave_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (parent);
  GstFlowReturn ret;

  g_return_val_if_fail (self->func != NULL, GST_FLOW_NOT_NEGOTIATED);
  g_return_val_if_fail (GST_AUDIO_INFO_WIDTH (&self->audio_info) > 0,
      GST_FLOW_NOT_NEGOTIATED);
  g_return_val_if_fail (GST_AUDIO_INFO_CHANNELS (&self->audio_info) > 0,
      GST_FLOW_NOT_NEGOTIATED);

  ret = gst_deinterleave_process (self, buffer);

  if (ret != GST_FLOW_OK)
    GST_DEBUG_OBJECT (self, "flow return: %s", gst_flow_get_name (ret));

  return ret;
}
Exemple #10
0
static gboolean
gst_deinterleave_sink_event (GstPad * pad, GstEvent * event)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));

  gboolean ret;

  GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
      GST_DEBUG_PAD_NAME (pad));

  /* Send FLUSH_STOP, FLUSH_START and EOS immediately, no matter if
   * we have src pads already or not. Queue all other events and
   * push them after we have src pads
   */
  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_FLUSH_STOP:
    case GST_EVENT_FLUSH_START:
    case GST_EVENT_EOS:
      ret = gst_pad_event_default (pad, event);
      break;
    default:
      if (self->srcpads) {
        ret = gst_pad_event_default (pad, event);
      } else {
        GST_OBJECT_LOCK (self);
        self->pending_events = g_list_append (self->pending_events, event);
        GST_OBJECT_UNLOCK (self);
        ret = TRUE;
      }
      break;
  }

  gst_object_unref (self);

  return ret;
}
Exemple #11
0
static GstCaps *
gst_deinterleave_sink_getcaps (GstPad * pad)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));

  GstCaps *ret;

  GList *l;

  GST_OBJECT_LOCK (self);
  /* Intersect all of our pad template caps with the peer caps of the pad
   * to get all formats that are possible up- and downstream.
   *
   * For the pad for which the caps are requested we don't remove the channel
   * informations as they must be in the returned caps and incompatibilities
   * will be detected here already
   */
  ret = gst_caps_new_any ();
  for (l = GST_ELEMENT (self)->pads; l != NULL; l = l->next) {
    GstPad *ourpad = GST_PAD (l->data);

    GstCaps *peercaps = NULL, *ourcaps;

    ourcaps = gst_caps_copy (gst_pad_get_pad_template_caps (ourpad));

    if (pad == ourpad) {
      if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK)
        __set_channels (ourcaps, self->channels);
      else
        __set_channels (ourcaps, 1);
    } else {
      __remove_channels (ourcaps);
      /* Only ask for peer caps for other pads than pad
       * as otherwise gst_pad_peer_get_caps() might call
       * back into this function and deadlock
       */
      peercaps = gst_pad_peer_get_caps (ourpad);
    }

    /* If the peer exists and has caps add them to the intersection,
     * otherwise assume that the peer accepts everything */
    if (peercaps) {
      GstCaps *intersection;

      GstCaps *oldret = ret;

      __remove_channels (peercaps);

      intersection = gst_caps_intersect (peercaps, ourcaps);

      ret = gst_caps_intersect (ret, intersection);
      gst_caps_unref (intersection);
      gst_caps_unref (peercaps);
      gst_caps_unref (oldret);
    } else {
      GstCaps *oldret = ret;

      ret = gst_caps_intersect (ret, ourcaps);
      gst_caps_unref (oldret);
    }
    gst_caps_unref (ourcaps);
  }
  GST_OBJECT_UNLOCK (self);

  gst_object_unref (self);

  GST_DEBUG_OBJECT (pad, "Intersected caps to %" GST_PTR_FORMAT, ret);

  return ret;
}
Exemple #12
0
static gboolean
gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps)
{
  GstDeinterleave *self;

  GstCaps *srccaps;

  GstStructure *s;

  self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));

  GST_DEBUG_OBJECT (self, "got caps: %" GST_PTR_FORMAT, caps);

  if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) {
    gint new_channels, i;

    GstAudioChannelPosition *pos;

    gboolean same_layout = TRUE;

    s = gst_caps_get_structure (caps, 0);

    /* We allow caps changes as long as the number of channels doesn't change
     * and the channel positions stay the same. _getcaps() should've cared
     * for this already but better be safe.
     */
    if (!gst_structure_get_int (s, "channels", &new_channels) ||
        new_channels != self->channels ||
        !gst_deinterleave_set_process_function (self, caps))
      goto cannot_change_caps;

    /* Now check the channel positions. If we had no channel positions
     * and get them or the other way around things have changed.
     * If we had channel positions and get different ones things have
     * changed too of course
     */
    pos = gst_audio_get_channel_positions (s);
    if ((pos && !self->pos) || (!pos && self->pos))
      goto cannot_change_caps;

    if (pos) {
      for (i = 0; i < self->channels; i++) {
        if (self->pos[i] != pos[i]) {
          same_layout = FALSE;
          break;
        }
      }
      g_free (pos);
      if (!same_layout)
        goto cannot_change_caps;
    }

  } else {
    s = gst_caps_get_structure (caps, 0);

    if (!gst_structure_get_int (s, "channels", &self->channels))
      goto no_channels;

    if (!gst_deinterleave_set_process_function (self, caps))
      goto unsupported_caps;

    self->pos = gst_audio_get_channel_positions (s);
  }

  gst_caps_replace (&self->sinkcaps, caps);

  /* Get srcpad caps */
  srccaps = gst_caps_copy (caps);
  s = gst_caps_get_structure (srccaps, 0);
  gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
  gst_structure_remove_field (s, "channel-positions");

  /* If we already have pads, update the caps otherwise
   * add new pads */
  if (self->srcpads) {
    gst_deinterleave_set_pads_caps (self, srccaps);
  } else {
    gst_deinterleave_add_new_pads (self, srccaps);
  }

  gst_caps_unref (srccaps);
  gst_object_unref (self);

  return TRUE;

cannot_change_caps:
  {
    GST_ERROR_OBJECT (self, "can't set new caps: %" GST_PTR_FORMAT, caps);
    gst_object_unref (self);
    return FALSE;
  }
unsupported_caps:
  {
    GST_ERROR_OBJECT (self, "caps not supported: %" GST_PTR_FORMAT, caps);
    gst_object_unref (self);
    return FALSE;
  }
no_channels:
  {
    GST_ERROR_OBJECT (self, "invalid caps");
    gst_object_unref (self);
    return FALSE;
  }
}