예제 #1
0
/**
 * gst_segment_to_running_time:
 * @segment: a #GstSegment structure.
 * @format: the format of the segment.
 * @position: the position in the segment
 *
 * Translate @position to the total running time using the currently configured
 * segment. Position is a value between @segment start and stop time.
 *
 * This function is typically used by elements that need to synchronize to the
 * global clock in a pipeline. The running time is a constantly increasing value
 * starting from 0. When gst_segment_init() is called, this value will reset to
 * 0.
 *
 * This function returns -1 if the position is outside of @segment start and stop.
 *
 * Returns: the position as the total running time or -1 when an invalid position
 * was given.
 */
guint64
gst_segment_to_running_time (const GstSegment * segment, GstFormat format,
    guint64 position)
{
  guint64 result;

  g_return_val_if_fail (segment != NULL, -1);
  g_return_val_if_fail (segment->format == format, -1);

  /* before the segment boundary */
  if (G_UNLIKELY (position < segment->start)) {
    GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT
        ")", position, segment->start);
    return -1;
  }
  /* after the segment boundary */
  if (G_UNLIKELY (segment->stop != -1 && position > segment->stop)) {
    GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
        ")", position, segment->stop);
    return -1;
  }

  if (gst_segment_to_running_time_full (segment, format, position,
          &result) == 1)
    return result;

  return -1;
}
static GstFlowReturn
gst_timecodewait_asink_chain (GstPad * pad, GstObject * parent,
    GstBuffer * inbuf)
{
  GstClockTime timestamp;
  GstTimeCodeWait *self = GST_TIMECODEWAIT (parent);
  GstClockTime current_running_time;
  GstClockTime video_running_time = GST_CLOCK_TIME_NONE;
  GstClockTime duration;
  GstClockTime running_time_at_end = GST_CLOCK_TIME_NONE;
  gint asign, vsign = 1, esign = 1;

  timestamp = GST_BUFFER_TIMESTAMP (inbuf);
  if (timestamp == GST_CLOCK_TIME_NONE) {
    gst_buffer_unref (inbuf);
    return GST_FLOW_ERROR;
  }
  g_mutex_lock (&self->mutex);
  self->asegment.position = timestamp;
  asign =
      gst_segment_to_running_time_full (&self->asegment, GST_FORMAT_TIME,
      self->asegment.position, &current_running_time);
  if (asign == 0) {
    g_mutex_unlock (&self->mutex);
    gst_buffer_unref (inbuf);
    GST_ERROR_OBJECT (self, "Could not get current running time");
    return GST_FLOW_ERROR;
  }
  if (self->vsegment.format == GST_FORMAT_TIME) {
    vsign =
        gst_segment_to_running_time_full (&self->vsegment, GST_FORMAT_TIME,
        self->vsegment.position, &video_running_time);
    if (vsign == 0) {
      video_running_time = GST_CLOCK_TIME_NONE;
    }
  }
  while (!(self->video_eos_flag || self->audio_flush_flag
          || self->shutdown_flag) && (video_running_time == GST_CLOCK_TIME_NONE
          || gst_timecodewait_compare_guint64_with_signs (asign,
              current_running_time, vsign, video_running_time) == 1)
      && self->running_time_of_timecode == GST_CLOCK_TIME_NONE) {
    g_cond_wait (&self->cond, &self->mutex);
    vsign =
        gst_segment_to_running_time_full (&self->vsegment, GST_FORMAT_TIME,
        self->vsegment.position, &video_running_time);
    if (vsign == 0) {
      video_running_time = GST_CLOCK_TIME_NONE;
    }
  }
  if (self->audio_flush_flag || self->shutdown_flag) {
    GST_DEBUG_OBJECT (self, "Shutting down, ignoring frame");
    gst_buffer_unref (inbuf);
    return GST_FLOW_FLUSHING;
  }
  duration = GST_BUFFER_DURATION (inbuf);
  if (duration != GST_CLOCK_TIME_NONE) {
    esign =
        gst_segment_to_running_time_full (&self->asegment, GST_FORMAT_TIME,
        self->asegment.position + duration, &running_time_at_end);
    if (esign == 0) {
      g_mutex_unlock (&self->mutex);
      GST_ERROR_OBJECT (self, "Could not get running time at end");
      gst_buffer_unref (inbuf);
      return GST_FLOW_ERROR;
    }
  }
  if (self->running_time_of_timecode == GST_CLOCK_TIME_NONE
      || gst_timecodewait_compare_guint64_with_signs (esign,
          running_time_at_end, 1, self->running_time_of_timecode) == -1) {
    GST_DEBUG_OBJECT (self,
        "Dropped an audio buf at %" GST_TIME_FORMAT " with timecode %"
        GST_TIME_FORMAT " video timecode %" GST_TIME_FORMAT,
        GST_TIME_ARGS (current_running_time),
        GST_TIME_ARGS (self->running_time_of_timecode),
        GST_TIME_ARGS (video_running_time));
    gst_buffer_unref (inbuf);
    inbuf = NULL;
  } else if (current_running_time < self->running_time_of_timecode
      && running_time_at_end > self->running_time_of_timecode) {
    GstSegment asegment2 = self->asegment;

    gst_segment_set_running_time (&asegment2, GST_FORMAT_TIME,
        self->running_time_of_timecode);
    inbuf =
        gst_audio_buffer_clip (inbuf, &asegment2, self->ainfo.rate,
        self->ainfo.bpf);
  }
  g_mutex_unlock (&self->mutex);
  if (inbuf)
    return gst_pad_push (self->asrcpad, inbuf);
  else
    return GST_FLOW_OK;
}