예제 #1
0
GstPadProbeReturn GstEnginePipeline::EventHandoffCallback(GstPad*,
                                                          GstPadProbeInfo* info,
                                                          gpointer self) {
  GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);
  GstEvent* e = gst_pad_probe_info_get_event(info);

  qLog(Debug) << instance->id() << "event" << GST_EVENT_TYPE_NAME(e);

  if (GST_EVENT_TYPE(e) == GST_EVENT_SEGMENT &&
      !instance->segment_start_received_) {
    // The segment start time is used to calculate the proper offset of data
    // buffers from the start of the stream
    const GstSegment* segment = nullptr;
    gst_event_parse_segment(e, &segment);
    instance->segment_start_ = segment->start;
    instance->segment_start_received_ = true;

    if (instance->emit_track_ended_on_segment_start_) {
      qLog(Debug) << "New segment started, EOS will signal on next buffer "
                     "discontinuity";
      instance->emit_track_ended_on_segment_start_ = false;
      instance->emit_track_ended_on_time_discontinuity_ = true;
    }
  }

  return GST_PAD_PROBE_OK;
}
예제 #2
0
static gboolean
gst_audio_aggregator_sink_event (GstAggregator * agg,
    GstAggregatorPad * aggpad, GstEvent * event)
{
  gboolean res = TRUE;

  GST_DEBUG_OBJECT (aggpad, "Got %s event on sink pad",
      GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEGMENT:
    {
      const GstSegment *segment;
      gst_event_parse_segment (event, &segment);

      if (segment->format != GST_FORMAT_TIME) {
        GST_ERROR_OBJECT (agg, "Segment of type %s are not supported,"
            " only TIME segments are supported",
            gst_format_get_name (segment->format));
        gst_event_unref (event);
        event = NULL;
        res = FALSE;
        break;
      }

      GST_OBJECT_LOCK (agg);
      if (segment->rate != agg->segment.rate) {
        GST_ERROR_OBJECT (aggpad,
            "Got segment event with wrong rate %lf, expected %lf",
            segment->rate, agg->segment.rate);
        res = FALSE;
        gst_event_unref (event);
        event = NULL;
      } else if (segment->rate < 0.0) {
        GST_ERROR_OBJECT (aggpad, "Negative rates not supported yet");
        res = FALSE;
        gst_event_unref (event);
        event = NULL;
      } else {
        GstAudioAggregatorPad *pad = GST_AUDIO_AGGREGATOR_PAD (aggpad);

        GST_OBJECT_LOCK (pad);
        pad->priv->new_segment = TRUE;
        GST_OBJECT_UNLOCK (pad);
      }
      GST_OBJECT_UNLOCK (agg);

      break;
    }
    default:
      break;
  }

  if (event != NULL)
    return
        GST_AGGREGATOR_CLASS (gst_audio_aggregator_parent_class)->sink_event
        (agg, aggpad, event);

  return res;
}
/* callback called when demux receives events from GstFakeSoupHTTPSrc */
static GstPadProbeReturn
on_demuxReceivesEvent (GstPad * pad, GstPadProbeInfo * info, gpointer data)
{
  GstAdaptiveDemuxTestEnginePrivate *priv =
      (GstAdaptiveDemuxTestEnginePrivate *) data;
  GstAdaptiveDemuxTestOutputStream *stream = NULL;
  GstEvent *event;
  const GstSegment *segment;

  event = GST_PAD_PROBE_INFO_EVENT (info);
  GST_DEBUG ("Received event %" GST_PTR_FORMAT " on pad %" GST_PTR_FORMAT,
      event, pad);

  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
    /* a new segment will start arriving
     * update segment_start used by pattern validation
     */
    gst_event_parse_segment (event, &segment);

    GST_TEST_LOCK (priv);
    stream = getTestOutputDataByPad (priv, pad, TRUE);
    stream->total_received_size += stream->segment_received_size;
    stream->segment_received_size = 0;
    stream->segment_start = segment->start;
    GST_TEST_UNLOCK (priv);
  }

  return GST_PAD_PROBE_OK;
}
예제 #4
0
static gboolean
gst_gio_base_sink_event (GstBaseSink * base_sink, GstEvent * event)
{
  GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
  GstFlowReturn ret = GST_FLOW_OK;

  if (sink->stream == NULL)
    return TRUE;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEGMENT:
      if (G_IS_OUTPUT_STREAM (sink->stream)) {
        const GstSegment *segment;

        gst_event_parse_segment (event, &segment);

        if (segment->format != GST_FORMAT_BYTES) {
          GST_WARNING_OBJECT (sink, "ignored SEGMENT event in %s format",
              gst_format_get_name (segment->format));
          break;
        }

        if (GST_GIO_STREAM_IS_SEEKABLE (sink->stream)) {
          ret = gst_gio_seek (sink, G_SEEKABLE (sink->stream), segment->start,
              sink->cancel);
          if (ret == GST_FLOW_OK)
            sink->position = segment->start;
        } else {
          ret = GST_FLOW_NOT_SUPPORTED;
        }
      }
      break;

    case GST_EVENT_EOS:
    case GST_EVENT_FLUSH_START:
      if (G_IS_OUTPUT_STREAM (sink->stream)) {
        gboolean success;
        GError *err = NULL;

        success = g_output_stream_flush (sink->stream, sink->cancel, &err);

        if (!success && !gst_gio_error (sink, "g_output_stream_flush", &err,
                &ret)) {
          GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL),
              ("flush failed: %s", err->message));
          g_clear_error (&err);
        }
      }
      break;

    default:
      break;
  }
  if (ret == GST_FLOW_OK)
    return GST_BASE_SINK_CLASS (parent_class)->event (base_sink, event);
  else {
    gst_event_unref (event);
    return FALSE;
  }
}
예제 #5
0
GstPadProbeReturn GstEnginePipeline::EventHandoffCallback(GstPad*,
        GstPadProbeInfo* info,
        gpointer self) {
    GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);
    GstEvent* e = gst_pad_probe_info_get_event(info);

    qLog(Debug) << instance->id() << "event" << GST_EVENT_TYPE_NAME(e);

    switch (GST_EVENT_TYPE(e)) {
    case GST_EVENT_SEGMENT:
        if (!instance->segment_start_received_) {
            // The segment start time is used to calculate the proper offset of data
            // buffers from the start of the stream
            const GstSegment* segment = nullptr;
            gst_event_parse_segment(e, &segment);
            instance->segment_start_ = segment->start;
            instance->segment_start_received_ = true;
        }
        break;

    default:
        break;
    }

    return GST_PAD_PROBE_OK;
}
/* return TRUE to discard the Segment */
static gboolean
compare_segments (CollectStructure * collect, Segment * segment,
    GstEvent * event)
{
  const GstSegment *received_segment;
  guint64 running_stop, running_start, running_duration;

  gst_event_parse_segment (event, &received_segment);

  GST_DEBUG ("Got Segment rate:%f, format:%s, start:%" GST_TIME_FORMAT
      ", stop:%" GST_TIME_FORMAT ", time:%" GST_TIME_FORMAT
      ", base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT,
      received_segment->rate, gst_format_get_name (received_segment->format),
      GST_TIME_ARGS (received_segment->start),
      GST_TIME_ARGS (received_segment->stop),
      GST_TIME_ARGS (received_segment->time),
      GST_TIME_ARGS (received_segment->base),
      GST_TIME_ARGS (received_segment->offset));
  GST_DEBUG ("[RUNNING] start:%" GST_TIME_FORMAT " [STREAM] start:%"
      GST_TIME_FORMAT,
      GST_TIME_ARGS (gst_segment_to_running_time (received_segment,
              GST_FORMAT_TIME, received_segment->start)),
      GST_TIME_ARGS (gst_segment_to_stream_time (received_segment,
              GST_FORMAT_TIME, received_segment->start)));

  GST_DEBUG ("Expecting rate:%f, format:%s, start:%" GST_TIME_FORMAT
      ", stop:%" GST_TIME_FORMAT ", position:%" GST_TIME_FORMAT ", base:%"
      GST_TIME_FORMAT, segment->rate, gst_format_get_name (segment->format),
      GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop),
      GST_TIME_ARGS (segment->position),
      GST_TIME_ARGS (collect->expected_base));

  running_start =
      gst_segment_to_running_time (received_segment, GST_FORMAT_TIME,
      received_segment->start);
  running_stop =
      gst_segment_to_running_time (received_segment, GST_FORMAT_TIME,
      received_segment->stop);
  running_duration = running_stop - running_start;
  fail_if (received_segment->rate != segment->rate);
  fail_if (received_segment->format != segment->format);
  fail_unless_equals_int64 (received_segment->time, segment->position);
  fail_unless_equals_int64 (received_segment->base, collect->expected_base);
  fail_unless_equals_uint64 (received_segment->stop - received_segment->start,
      segment->stop - segment->start);

  collect->expected_base += running_duration;

  GST_DEBUG ("Segment was valid, discarding expected Segment");

  return TRUE;
}
예제 #7
0
/**
 * gst_event_copy_segment:
 * @event: The event to parse
 * @segment: a pointer to a #GstSegment
 *
 * Parses a segment @event and copies the #GstSegment into the location
 * given by @segment.
 */
void
gst_event_copy_segment (GstEvent * event, GstSegment * segment)
{
  const GstSegment *src;

  g_return_if_fail (GST_IS_EVENT (event));
  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);

  if (segment) {
    gst_event_parse_segment (event, &src);
    gst_segment_copy_into (src, segment);
  }
}
예제 #8
0
static gboolean
gst_fd_sink_event (GstBaseSink * sink, GstEvent * event)
{
  GstEventType type;
  GstFdSink *fdsink;

  fdsink = GST_FD_SINK (sink);

  type = GST_EVENT_TYPE (event);

  switch (type) {
    case GST_EVENT_SEGMENT:
    {
      const GstSegment *segment;

      gst_event_parse_segment (event, &segment);

      if (segment->format == GST_FORMAT_BYTES) {
        /* only try to seek and fail when we are going to a different
         * position */
        if (fdsink->current_pos != segment->start) {
          /* FIXME, the seek should be performed on the pos field, start/stop are
           * just boundaries for valid bytes offsets. We should also fill the file
           * with zeroes if the new position extends the current EOF (sparse streams
           * and segment accumulation). */
          if (!gst_fd_sink_do_seek (fdsink, (guint64) segment->start))
            goto seek_failed;
        }
      } else {
        GST_DEBUG_OBJECT (fdsink,
            "Ignored SEGMENT event of format %u (%s)", (guint) segment->format,
            gst_format_get_name (segment->format));
      }
      break;
    }
    default:
      break;
  }

  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);

seek_failed:
  {
    GST_ELEMENT_ERROR (fdsink, RESOURCE, SEEK, (NULL),
        ("Error while seeking on file descriptor %d: %s",
            fdsink->fd, g_strerror (errno)));
    gst_event_unref (event);
    return FALSE;
  }

}
예제 #9
0
static gboolean
gst_dvdec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstDVDec *dvdec;
  gboolean res = TRUE;

  dvdec = GST_DVDEC (parent);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_FLUSH_STOP:
      gst_segment_init (&dvdec->segment, GST_FORMAT_UNDEFINED);
      dvdec->need_segment = FALSE;
      break;
    case GST_EVENT_SEGMENT:{
      const GstSegment *segment;

      gst_event_parse_segment (event, &segment);

      GST_DEBUG_OBJECT (dvdec, "Got SEGMENT %" GST_SEGMENT_FORMAT, &segment);

      gst_segment_copy_into (segment, &dvdec->segment);
      if (!gst_pad_has_current_caps (dvdec->srcpad)) {
        dvdec->need_segment = TRUE;
        gst_event_unref (event);
        event = NULL;
        res = TRUE;
      } else {
        dvdec->need_segment = FALSE;
      }
      break;
    }
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      res = gst_dvdec_sink_setcaps (dvdec, caps);
      gst_event_unref (event);
      event = NULL;
      break;
    }

    default:
      break;
  }

  if (event)
    res = gst_pad_push_event (dvdec->srcpad, event);

  return res;
}
예제 #10
0
static gboolean
sink_event_func (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GList **expected = GST_PAD_ELEMENT_PRIVATE (pad), *l;
  GstEvent *exp;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:{
      GstCaps *recvcaps, *expectcaps;

      l = g_list_first (*expected);
      exp = GST_EVENT (l->data);

      gst_event_parse_caps (event, &recvcaps);
      gst_event_parse_caps (exp, &expectcaps);

      fail_unless (gst_caps_is_equal (recvcaps, expectcaps));
      break;
    }
    case GST_EVENT_SEGMENT:{
      const GstSegment *recvseg, *expectseg;

      l = g_list_last (*expected);
      exp = GST_EVENT (l->data);

      gst_event_parse_segment (event, &recvseg);
      gst_event_parse_segment (exp, &expectseg);

      fail_unless_equals_uint64 (recvseg->position, expectseg->position);
      break;
    }
    default:
      break;
  }

  return gst_pad_event_default (pad, parent, event);
}
예제 #11
0
static gboolean
gst_pngdec_sink_event (GstVideoDecoder * bdec, GstEvent * event)
{
  const GstSegment *segment;

  if (GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT)
    goto done;

  gst_event_parse_segment (event, &segment);

  if (segment->format == GST_FORMAT_TIME)
    gst_video_decoder_set_packetized (bdec, TRUE);
  else
    gst_video_decoder_set_packetized (bdec, FALSE);

done:
  return GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (bdec, event);
}
예제 #12
0
static gboolean
gst_segment_clip_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstSegmentClip *self = GST_SEGMENT_CLIP (parent);
  gboolean ret = TRUE;

  GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      /* should be only downstream */
      g_assert (pad == self->sinkpad);
      gst_event_parse_caps (event, &caps);
      ret = gst_segment_clip_sink_setcaps (self, caps);
      break;
    }
    case GST_EVENT_SEGMENT:
    {
      const GstSegment *segment;

      gst_event_parse_segment (event, &segment);
      GST_DEBUG_OBJECT (pad, "Got NEWSEGMENT event %" GST_SEGMENT_FORMAT,
          segment);
      gst_segment_copy_into (segment, &self->segment);
      break;
    }
    case GST_EVENT_FLUSH_STOP:
      gst_segment_clip_reset (self);
      break;
    default:
      break;
  }

  if (ret)
    ret = gst_pad_event_default (pad, parent, event);
  else
    gst_event_unref (event);

  return ret;
}
예제 #13
0
static GstPadProbeReturn
dvdbin_dump_timing_info (GstPad * opad,
    GstPadProbeInfo * info, gpointer userdata)
{
  if (GST_PAD_PROBE_INFO_TYPE (info) & (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM |
          GST_PAD_PROBE_TYPE_EVENT_FLUSH)) {
    GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
    if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
      const GstSegment *seg;

      gst_event_parse_segment (event, &seg);

      g_print ("%s:%s segment: rate %g format %d, start: %"
          GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT ", time: %"
          GST_TIME_FORMAT " base: %" GST_TIME_FORMAT "\n",
          GST_DEBUG_PAD_NAME (opad),
          seg->rate, seg->format, GST_TIME_ARGS (seg->start),
          GST_TIME_ARGS (seg->stop), GST_TIME_ARGS (seg->time),
          GST_TIME_ARGS (seg->base));
    } else if (GST_EVENT_TYPE (event) == GST_EVENT_GAP) {
      GstClockTime ts, dur, end;
      gst_event_parse_gap (event, &ts, &dur);
      end = ts;
      if (ts != GST_CLOCK_TIME_NONE && dur != GST_CLOCK_TIME_NONE)
        end += dur;
      g_print ("%s:%s Gap TS: %" GST_TIME_FORMAT " dur %" GST_TIME_FORMAT
          " (to %" GST_TIME_FORMAT ")\n", GST_DEBUG_PAD_NAME (opad),
          GST_TIME_ARGS (ts), GST_TIME_ARGS (dur), GST_TIME_ARGS (end));
    } else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
      g_print ("%s:%s FLUSHED\n", GST_DEBUG_PAD_NAME (opad));
    }
  }
  if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_BUFFER) {
    GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER (info);
    g_print ("%s:%s Buffer PTS %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT
        "\n", GST_DEBUG_PAD_NAME (opad), GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
  }
  return GST_PAD_PROBE_OK;
}
예제 #14
0
/* sink and src pad event handlers */
static gboolean
gst_ivtc_sink_event (GstBaseTransform * trans, GstEvent * event)
{
    GstIvtc *ivtc = GST_IVTC (trans);

    GST_DEBUG_OBJECT (ivtc, "sink_event");

    if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
        const GstSegment *seg;

        gst_ivtc_flush (ivtc);

        /* FIXME this should handle update events */

        gst_event_parse_segment (event, &seg);
        gst_segment_copy_into (seg, &ivtc->segment);
        ivtc->current_ts = ivtc->segment.start;
    }

    return GST_BASE_TRANSFORM_CLASS (gst_ivtc_parent_class)->sink_event (trans,
            event);
}
예제 #15
0
GstPadProbeReturn GStreamerReader::EventProbe(GstPad *aPad, GstEvent *aEvent)
{
  GstElement* parent = GST_ELEMENT(gst_pad_get_parent(aPad));

  LOG(PR_LOG_DEBUG, "event probe %s", GST_EVENT_TYPE_NAME (aEvent));

  switch(GST_EVENT_TYPE(aEvent)) {
    case GST_EVENT_SEGMENT:
    {
      const GstSegment *newSegment;
      GstSegment* segment;

      /* Store the segments so we can convert timestamps to stream time, which
       * is what the upper layers sync on.
       */
      ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
#if GST_VERSION_MINOR <= 1 && GST_VERSION_MICRO < 1
      ResetDecode();
#endif
      gst_event_parse_segment(aEvent, &newSegment);
      if (parent == GST_ELEMENT(mVideoAppSink))
        segment = &mVideoSegment;
      else
        segment = &mAudioSegment;
      gst_segment_copy_into (newSegment, segment);
      break;
    }
    case GST_EVENT_FLUSH_STOP:
      /* Reset on seeks */
      ResetDecode();
      break;
    default:
      break;
  }
  gst_object_unref(parent);

  return GST_PAD_PROBE_OK;
}
static gboolean
gst_decklink_audio_sink_event (GstBaseSink * bsink, GstEvent * event)
{
  GstDecklinkAudioSink *self = GST_DECKLINK_AUDIO_SINK_CAST (bsink);

  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
    const GstSegment *new_segment;

    gst_event_parse_segment (event, &new_segment);

    if (ABS (new_segment->rate) != 1.0) {
      guint out_rate = self->info.rate / ABS (new_segment->rate);

      if (self->resampler && (self->resampler_out_rate != out_rate
              || self->resampler_in_rate != (guint) self->info.rate))
        gst_audio_resampler_update (self->resampler, self->info.rate, out_rate,
            NULL);
      else if (!self->resampler)
        self->resampler =
            gst_audio_resampler_new (GST_AUDIO_RESAMPLER_METHOD_LINEAR,
            GST_AUDIO_RESAMPLER_FLAG_NONE, self->info.finfo->format,
            self->info.channels, self->info.rate, out_rate, NULL);

      self->resampler_in_rate = self->info.rate;
      self->resampler_out_rate = out_rate;
    } else if (self->resampler) {
      gst_audio_resampler_free (self->resampler);
      self->resampler = NULL;
    }

    if (new_segment->rate < 0)
      gst_audio_stream_align_set_rate (self->stream_align, -48000);
  }

  return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
}
예제 #17
0
static gboolean
gst_gdk_pixbuf_dec_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstFlowReturn res = GST_FLOW_OK;
  gboolean ret = TRUE, forward = TRUE;
  GstGdkPixbufDec *pixbuf;

  pixbuf = GST_GDK_PIXBUF_DEC (parent);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      ret = gst_gdk_pixbuf_dec_sink_setcaps (pixbuf, caps);
      forward = FALSE;
      break;
    }
    case GST_EVENT_EOS:
      if (pixbuf->pixbuf_loader != NULL) {
        gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL);
        res = gst_gdk_pixbuf_dec_flush (pixbuf);
        g_object_unref (G_OBJECT (pixbuf->pixbuf_loader));
        pixbuf->pixbuf_loader = NULL;
        /* as long as we don't have flow returns for event functions we need
         * to post an error here, or the application might never know that
         * things failed */
        if (res != GST_FLOW_OK && res != GST_FLOW_FLUSHING
            && res != GST_FLOW_EOS && res != GST_FLOW_NOT_LINKED) {
          GST_ELEMENT_ERROR (pixbuf, STREAM, FAILED, (NULL), ("Flow: %s",
                  gst_flow_get_name (res)));
          forward = FALSE;
          ret = FALSE;
        }
      }
      break;
    case GST_EVENT_FLUSH_STOP:
      g_list_free_full (pixbuf->pending_events,
          (GDestroyNotify) gst_event_unref);
      pixbuf->pending_events = NULL;
      /* Fall through */
    case GST_EVENT_SEGMENT:
    {
      const GstSegment *segment;
      gst_event_parse_segment (event, &segment);
      if (segment->format == GST_FORMAT_BYTES)
        pixbuf->packetized = FALSE;
      else
        pixbuf->packetized = TRUE;
      if (pixbuf->pixbuf_loader != NULL) {
        gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL);
        g_object_unref (G_OBJECT (pixbuf->pixbuf_loader));
        pixbuf->pixbuf_loader = NULL;
      }
      break;
    }
    default:
      break;
  }
  if (forward) {
    if (!gst_pad_has_current_caps (pixbuf->srcpad) &&
        GST_EVENT_IS_SERIALIZED (event)
        && GST_EVENT_TYPE (event) > GST_EVENT_CAPS
        && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP
        && GST_EVENT_TYPE (event) != GST_EVENT_EOS) {
      ret = TRUE;
      pixbuf->pending_events = g_list_prepend (pixbuf->pending_events, event);
    } else {
      ret = gst_pad_event_default (pad, parent, event);
    }
  } else {
    gst_event_unref (event);
  }
  return ret;
}
예제 #18
0
static gboolean
gst_video_rate_sink_event (GstBaseTransform * trans, GstEvent * event)
{
  GstVideoRate *videorate;

  videorate = GST_VIDEO_RATE (trans);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEGMENT:
    {
      const GstSegment *segment;

      gst_event_parse_segment (event, &segment);

      if (segment->format != GST_FORMAT_TIME)
        goto format_error;

      GST_DEBUG_OBJECT (videorate, "handle NEWSEGMENT");

      /* close up the previous segment, if appropriate */
      if (videorate->prevbuf) {
        gint count = 0;
        GstFlowReturn res;

        res = GST_FLOW_OK;
        /* fill up to the end of current segment,
         * or only send out the stored buffer if there is no specific stop.
         * regardless, prevent going loopy in strange cases */
        while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
            ((GST_CLOCK_TIME_IS_VALID (videorate->segment.stop) &&
                    videorate->next_ts - videorate->segment.base
                    < videorate->segment.stop)
                || count < 1)) {
          res = gst_video_rate_flush_prev (videorate, count > 0);
          count++;
        }
        if (count > 1) {
          videorate->dup += count - 1;
          if (!videorate->silent)
            gst_video_rate_notify_duplicate (videorate);
        } else if (count == 0) {
          videorate->drop++;
          if (!videorate->silent)
            gst_video_rate_notify_drop (videorate);
        }
        /* clean up for the new one; _chain will resume from the new start */
        gst_video_rate_swap_prev (videorate, NULL, 0);
      }

      videorate->base_ts = 0;
      videorate->out_frame_count = 0;
      videorate->next_ts = GST_CLOCK_TIME_NONE;

      /* We just want to update the accumulated stream_time  */
      gst_segment_copy_into (segment, &videorate->segment);

      GST_DEBUG_OBJECT (videorate, "updated segment: %" GST_SEGMENT_FORMAT,
          &videorate->segment);
      break;
    }
    case GST_EVENT_EOS:{
      gint count = 0;
      GstFlowReturn res = GST_FLOW_OK;

      GST_DEBUG_OBJECT (videorate, "Got EOS");

      /* If the segment has a stop position, fill the segment */
      if (GST_CLOCK_TIME_IS_VALID (videorate->segment.stop)) {
        /* fill up to the end of current segment,
         * or only send out the stored buffer if there is no specific stop.
         * regardless, prevent going loopy in strange cases */
        while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
            ((videorate->next_ts - videorate->segment.base <
                    videorate->segment.stop)
                || count < 1)) {
          res = gst_video_rate_flush_prev (videorate, count > 0);
          count++;
        }
      } else if (videorate->prevbuf) {
        /* Output at least one frame but if the buffer duration is valid, output
         * enough frames to use the complete buffer duration */
        if (GST_BUFFER_DURATION_IS_VALID (videorate->prevbuf)) {
          GstClockTime end_ts =
              videorate->next_ts + GST_BUFFER_DURATION (videorate->prevbuf);

          while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
              ((videorate->next_ts - videorate->segment.base < end_ts)
                  || count < 1)) {
            res = gst_video_rate_flush_prev (videorate, count > 0);
            count++;
          }
        } else {
          res = gst_video_rate_flush_prev (videorate, FALSE);
          count = 1;
        }
      }

      if (count > 1) {
        videorate->dup += count - 1;
        if (!videorate->silent)
          gst_video_rate_notify_duplicate (videorate);
      } else if (count == 0) {
        videorate->drop++;
        if (!videorate->silent)
          gst_video_rate_notify_drop (videorate);
      }

      break;
    }
    case GST_EVENT_FLUSH_STOP:
      /* also resets the segment */
      GST_DEBUG_OBJECT (videorate, "Got FLUSH_STOP");
      gst_video_rate_reset (videorate);
      break;
    case GST_EVENT_GAP:
      /* no gaps after videorate, ignore the event */
      gst_event_unref (event);
      return TRUE;
    default:
      break;
  }

  return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);

  /* ERRORS */
format_error:
  {
    GST_WARNING_OBJECT (videorate,
        "Got segment but doesn't have GST_FORMAT_TIME value");
    return FALSE;
  }
}
예제 #19
0
static gboolean
gst_adder_sink_event (GstCollectPads * pads, GstCollectData * pad,
    GstEvent * event, gpointer user_data)
{
  GstAdder *adder = GST_ADDER (user_data);
  gboolean res = TRUE, discard = FALSE;

  GST_DEBUG_OBJECT (pad->pad, "Got %s event on sink pad",
      GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      res = gst_adder_setcaps (adder, pad->pad, caps);
      gst_event_unref (event);
      event = NULL;
      break;
    }
    case GST_EVENT_FLUSH_START:
      /* ensure that we will send a flush stop */
      res = gst_collect_pads_event_default (pads, pad, event, discard);
      event = NULL;
      GST_COLLECT_PADS_STREAM_LOCK (adder->collect);
      adder->flush_stop_pending = TRUE;
      GST_COLLECT_PADS_STREAM_UNLOCK (adder->collect);
      break;
    case GST_EVENT_FLUSH_STOP:
      /* we received a flush-stop. We will only forward it when
       * flush_stop_pending is set, and we will unset it then.
       */
      g_atomic_int_set (&adder->new_segment_pending, TRUE);
      GST_COLLECT_PADS_STREAM_LOCK (adder->collect);
      if (adder->flush_stop_pending) {
        GST_DEBUG_OBJECT (pad->pad, "forwarding flush stop");
        res = gst_collect_pads_event_default (pads, pad, event, discard);
        adder->flush_stop_pending = FALSE;
        event = NULL;
      } else {
        discard = TRUE;
        GST_DEBUG_OBJECT (pad->pad, "eating flush stop");
      }
      GST_COLLECT_PADS_STREAM_UNLOCK (adder->collect);
      /* Clear pending tags */
      if (adder->pending_events) {
        g_list_foreach (adder->pending_events, (GFunc) gst_event_unref, NULL);
        g_list_free (adder->pending_events);
        adder->pending_events = NULL;
      }
      break;
    case GST_EVENT_TAG:
      /* collect tags here so we can push them out when we collect data */
      adder->pending_events = g_list_append (adder->pending_events, event);
      event = NULL;
      break;
    case GST_EVENT_SEGMENT:{
      const GstSegment *segment;
      gst_event_parse_segment (event, &segment);
      if (segment->rate != adder->segment.rate) {
        GST_ERROR_OBJECT (pad->pad,
            "Got segment event with wrong rate %lf, expected %lf",
            segment->rate, adder->segment.rate);
        res = FALSE;
        gst_event_unref (event);
        event = NULL;
      }
      discard = TRUE;
      break;
    }
    default:
      break;
  }

  if (G_LIKELY (event))
    return gst_collect_pads_event_default (pads, pad, event, discard);
  else
    return res;
}
예제 #20
0
/* handle events (search) */
static gboolean
gst_file_sink_event (GstBaseSink * sink, GstEvent * event)
{
  GstEventType type;
  GstFileSink *filesink;

  filesink = GST_FILE_SINK (sink);

  type = GST_EVENT_TYPE (event);

  switch (type) {
    case GST_EVENT_SEGMENT:
    {
      const GstSegment *segment;

      gst_event_parse_segment (event, &segment);

      if (segment->format == GST_FORMAT_BYTES) {
        /* only try to seek and fail when we are going to a different
         * position */
        if (filesink->current_pos != segment->start) {
          /* FIXME, the seek should be performed on the pos field, start/stop are
           * just boundaries for valid bytes offsets. We should also fill the file
           * with zeroes if the new position extends the current EOF (sparse streams
           * and segment accumulation). */
          if (!gst_file_sink_do_seek (filesink, (guint64) segment->start))
            goto seek_failed;
        } else {
          GST_DEBUG_OBJECT (filesink, "Ignored SEGMENT, no seek needed");
        }
      } else {
        GST_DEBUG_OBJECT (filesink,
            "Ignored SEGMENT event of format %u (%s)", (guint) segment->format,
            gst_format_get_name (segment->format));
      }
      break;
    }
    case GST_EVENT_FLUSH_STOP:
      if (filesink->current_pos != 0 && filesink->seekable) {
        gst_file_sink_do_seek (filesink, 0);
        if (ftruncate (fileno (filesink->file), 0))
          goto flush_failed;
      }
      break;
    case GST_EVENT_EOS:
      if (fflush (filesink->file))
        goto flush_failed;
      break;
    default:
      break;
  }

  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);

  /* ERRORS */
seek_failed:
  {
    GST_ELEMENT_ERROR (filesink, RESOURCE, SEEK,
        (_("Error while seeking in file \"%s\"."), filesink->filename),
        GST_ERROR_SYSTEM);
    gst_event_unref (event);
    return FALSE;
  }
flush_failed:
  {
    GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
        (_("Error while writing to file \"%s\"."), filesink->filename),
        GST_ERROR_SYSTEM);
    gst_event_unref (event);
    return FALSE;
  }
}