static inline void
_get_nearest_control_points2 (GstTimedValueControlSource * self,
    GstClockTime ts, GstControlPoint ** cp1, GstControlPoint ** cp2,
    GstClockTime * next_ts)
{
  GSequenceIter *iter1, *iter2 = NULL;

  *cp1 = *cp2 = NULL;
  iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts);
  if (iter1) {
    *cp1 = g_sequence_get (iter1);
    iter2 = g_sequence_iter_next (iter1);
  } else {
    if (G_LIKELY (self->values)) {
      /* all values in the control point list come after the given timestamp */
      iter2 = g_sequence_get_begin_iter (self->values);
      /* why this? if !cp1 we don't interpolate anyway
       * if we can eliminate this, we can also use _get_nearest_control_points()
       * here, is this just to set next_ts? */
    } else {
      /* no values */
      iter2 = NULL;
    }
  }

  if (iter2 && !g_sequence_iter_is_end (iter2)) {
    *cp2 = g_sequence_get (iter2);
    *next_ts = (*cp2)->timestamp;
  } else {
    *next_ts = GST_CLOCK_TIME_NONE;
  }
}
static gboolean
interpolate_trigger_get (GstTimedValueControlSource * self,
    GstClockTime timestamp, gdouble * value)
{
  gboolean ret = FALSE;
  GSequenceIter *iter;

  g_mutex_lock (&self->lock);

  iter =
      gst_timed_value_control_source_find_control_point_iter (self, timestamp);
  if (iter) {
    *value = _interpolate_trigger (self, iter, timestamp);
    if (!isnan (*value))
      ret = TRUE;
  }
  g_mutex_unlock (&self->lock);
  return ret;
}
static inline gboolean
_get_nearest_control_points (GstTimedValueControlSource * self,
    GstClockTime ts, GstControlPoint ** cp1, GstControlPoint ** cp2)
{
  GSequenceIter *iter;

  iter = gst_timed_value_control_source_find_control_point_iter (self, ts);
  if (iter) {
    *cp1 = g_sequence_get (iter);
    iter = g_sequence_iter_next (iter);
    if (iter && !g_sequence_iter_is_end (iter)) {
      *cp2 = g_sequence_get (iter);
    } else {
      *cp2 = NULL;
    }
    return TRUE;
  }
  return FALSE;
}
static gboolean
interpolate_none_get (GstTimedValueControlSource * self, GstClockTime timestamp,
    gdouble * value)
{
  gboolean ret = FALSE;
  GSequenceIter *iter;
  GstControlPoint *cp;

  g_mutex_lock (&self->lock);

  iter =
      gst_timed_value_control_source_find_control_point_iter (self, timestamp);
  if (iter) {
    cp = g_sequence_get (iter);
    *value = _interpolate_none (self, cp);
    ret = TRUE;
  }
  g_mutex_unlock (&self->lock);
  return ret;
}
static gboolean
interpolate_trigger_get_value_array (GstTimedValueControlSource * self,
    GstClockTime timestamp, GstClockTime interval, guint n_values,
    gdouble * values)
{
  gboolean ret = FALSE;
  guint i;
  GstClockTime ts = timestamp;
  GstClockTime next_ts = 0;
  gdouble val;
  GSequenceIter *iter1 = NULL, *iter2 = NULL;
  gboolean triggered = FALSE;

  g_mutex_lock (&self->lock);
  for (i = 0; i < n_values; i++) {
    val = NAN;
    if (ts >= next_ts) {
      iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts);
      if (!iter1) {
        if (G_LIKELY (self->values))
          iter2 = g_sequence_get_begin_iter (self->values);
        else
          iter2 = NULL;
      } else {
        iter2 = g_sequence_iter_next (iter1);
      }

      if (iter2 && !g_sequence_iter_is_end (iter2)) {
        GstControlPoint *cp;

        cp = g_sequence_get (iter2);
        next_ts = cp->timestamp;
      } else {
        next_ts = GST_CLOCK_TIME_NONE;
      }

      if (iter1) {
        val = _interpolate_trigger (self, iter1, ts);
        if (!isnan (val))
          ret = TRUE;
      } else {
        g_mutex_unlock (&self->lock);
        return FALSE;
      }
      triggered = TRUE;
    } else if (triggered) {
      if (iter1) {
        val = _interpolate_trigger (self, iter1, ts);
        if (!isnan (val))
          ret = TRUE;
      } else {
        g_mutex_unlock (&self->lock);
        return FALSE;
      }
      triggered = FALSE;
    }
    *values = val;
    ts += interval;
    values++;
  }
  g_mutex_unlock (&self->lock);
  return ret;
}