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; }
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; }
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; } }
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; }
/** * 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); } }
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; } }
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; }
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); }
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); }
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; }
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; }
/* 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); }
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); }
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; }
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; } }
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; }
/* 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; } }