static gboolean gst_base_video_parse_sink_event (GstPad * pad, GstEvent * event) { GstBaseVideoParse *base_video_parse; gboolean ret = FALSE; base_video_parse = GST_BASE_VIDEO_PARSE (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: ret = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), event); break; case GST_EVENT_FLUSH_STOP: gst_base_video_parse_reset (base_video_parse); ret = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), event); break; case GST_EVENT_EOS: if (gst_base_video_parse_push_all (base_video_parse, FALSE) == GST_FLOW_ERROR) { gst_event_unref (event); return FALSE; } ret = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), event); break; case GST_EVENT_NEWSEGMENT: { gboolean update; GstFormat format; gdouble rate; gint64 start, stop, time; gst_event_parse_new_segment (event, &update, &rate, &format, &start, &stop, &time); if (format != GST_FORMAT_TIME) goto newseg_wrong_format; if (rate <= 0.0) goto newseg_wrong_rate; GST_DEBUG ("newsegment %" GST_TIME_FORMAT " %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (time)); gst_segment_set_newsegment (&base_video_parse->segment, update, rate, format, start, stop, time); ret = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), event); break; } default: ret = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), event); break; } done: gst_object_unref (base_video_parse); return ret; newseg_wrong_format: GST_DEBUG_OBJECT (base_video_parse, "received non TIME newsegment"); gst_event_unref (event); goto done; newseg_wrong_rate: GST_DEBUG_OBJECT (base_video_parse, "negative rates not supported"); gst_event_unref (event); goto done; }
static gboolean gst_base_rtp_depayload_handle_sink_event (GstPad * pad, GstEvent * event) { GstBaseRTPDepayload *filter; gboolean res = TRUE; gboolean forward = TRUE; filter = GST_BASE_RTP_DEPAYLOAD (GST_OBJECT_PARENT (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: gst_segment_init (&filter->segment, GST_FORMAT_UNDEFINED); filter->need_newsegment = TRUE; filter->priv->next_seqnum = -1; break; case GST_EVENT_NEWSEGMENT: { gboolean update; gdouble rate; GstFormat fmt; gint64 start, stop, position; gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop, &position); gst_segment_set_newsegment (&filter->segment, update, rate, fmt, start, stop, position); /* don't pass the event downstream, we generate our own segment including * the NTP time and other things we receive in caps */ forward = FALSE; break; } case GST_EVENT_CUSTOM_DOWNSTREAM: { GstBaseRTPDepayloadClass *bclass; bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); if (gst_event_has_name (event, "GstRTPPacketLost")) { /* we get this event from the jitterbuffer when it considers a packet as * being lost. We send it to our packet_lost vmethod. The default * implementation will make time progress by pushing out a NEWSEGMENT * update event. Subclasses can override and to one of the following: * - Adjust timestamp/duration to something more accurate before * calling the parent (default) packet_lost method. * - do some more advanced error concealing on the already received * (fragmented) packets. * - ignore the packet lost. */ if (bclass->packet_lost) res = bclass->packet_lost (filter, event); forward = FALSE; } break; } default: break; } if (forward) res = gst_pad_push_event (filter->srcpad, event); else gst_event_unref (event); return res; }
static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event) { GstIdentity *identity; gboolean ret = TRUE; identity = GST_IDENTITY (trans); if (!identity->silent) { const GstStructure *s; gchar *sstr; GST_OBJECT_LOCK (identity); g_free (identity->last_message); if ((s = gst_event_get_structure (event))) sstr = gst_structure_to_string (s); else sstr = g_strdup (""); identity->last_message = g_strdup_printf ("event ******* (%s:%s) E (type: %d, %s) %p", GST_DEBUG_PAD_NAME (trans->sinkpad), GST_EVENT_TYPE (event), sstr, event); g_free (sstr); GST_OBJECT_UNLOCK (identity); gst_identity_notify_last_message (identity); } if (identity->single_segment && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) { if (trans->have_newsegment == FALSE) { GstEvent *news; GstFormat format; gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL, NULL); /* This is the first newsegment, send out a (0, -1) newsegment */ news = gst_event_new_new_segment (TRUE, 1.0, format, 0, -1, 0); gst_pad_event_default (trans->sinkpad, news); } } /* Reset previous timestamp, duration and offsets on NEWSEGMENT * to prevent false warnings when checking for perfect streams */ if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { identity->prev_timestamp = identity->prev_duration = GST_CLOCK_TIME_NONE; identity->prev_offset = identity->prev_offset_end = GST_BUFFER_OFFSET_NONE; } ret = parent_class->event (trans, event); if (identity->single_segment && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) { /* eat up segments */ ret = FALSE; } return ret; }
static gboolean gst_sub_parse_sink_event (GstPad * pad, GstEvent * event) { GstSubParse *self = GST_SUBPARSE (gst_pad_get_parent (pad)); gboolean ret = FALSE; GST_DEBUG ("Handling %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS:{ /* Make sure the last subrip chunk is pushed out even * if the file does not have an empty line at the end */ if (self->parser_type == GST_SUB_PARSE_FORMAT_SUBRIP || self->parser_type == GST_SUB_PARSE_FORMAT_TMPLAYER || self->parser_type == GST_SUB_PARSE_FORMAT_MPL2) { GstBuffer *buf = gst_buffer_new_and_alloc (2 + 1); GST_DEBUG ("EOS. Pushing remaining text (if any)"); GST_BUFFER_DATA (buf)[0] = '\n'; GST_BUFFER_DATA (buf)[1] = '\n'; GST_BUFFER_DATA (buf)[2] = '\0'; /* play it safe */ GST_BUFFER_SIZE (buf) = 2; GST_BUFFER_OFFSET (buf) = self->offset; gst_sub_parse_chain (pad, buf); } ret = gst_pad_event_default (pad, event); break; } case GST_EVENT_NEWSEGMENT: { GstFormat format; gdouble rate; gint64 start, stop, time; gboolean update; gst_event_parse_new_segment (event, &update, &rate, &format, &start, &stop, &time); GST_DEBUG_OBJECT (self, "newsegment (%s)", gst_format_get_name (format)); if (format == GST_FORMAT_TIME) { gst_segment_set_newsegment (&self->segment, update, rate, format, start, stop, time); } else { /* if not time format, we'll either start with a 0 timestamp anyway or * it's following a seek in which case we'll have saved the requested * seek segment and don't want to overwrite it (remember that on a seek * we always just seek back to the start in BYTES format and just throw * away all text that's before the requested position; if the subtitles * come from an upstream demuxer, it won't be able to handle our BYTES * seek request and instead send us a newsegment from the seek request * it received via its video pads instead, so all is fine then too) */ } ret = TRUE; gst_event_unref (event); break; } case GST_EVENT_FLUSH_START: { self->flushing = TRUE; ret = gst_pad_event_default (pad, event); break; } case GST_EVENT_FLUSH_STOP: { self->flushing = FALSE; ret = gst_pad_event_default (pad, event); break; } default: ret = gst_pad_event_default (pad, event); break; } gst_object_unref (self); return ret; }
/*============================================================================= FUNCTION: mfw_gst_spdifrx_sink_event DESCRIPTION: Handles an event on the sink pad. ARGUMENTS PASSED: pad - pointer to pad event - pointer to event RETURN VALUE: TRUE - if event is sent to sink properly FALSE - if event is not sent to sink properly PRE-CONDITIONS: None POST-CONDITIONS: None IMPORTANT NOTES: None =============================================================================*/ static gboolean mfw_gst_spdifrx_sink_event(GstPad * pad, GstEvent * event) { MfwGstSpdifRX *filter = MFW_GST_SPDIFRX (GST_PAD_PARENT(pad)); gboolean result = TRUE; switch (GST_EVENT_TYPE(event)) { case GST_EVENT_NEWSEGMENT: { GstFormat format; gint64 start, stop, position; gint64 nstart, nstop; gst_event_parse_new_segment(event, NULL, NULL, &format, &start, &stop, &position); if (format == GST_FORMAT_TIME) { result = gst_pad_push_event(filter->srcpad, event); if (TRUE != result) { GST_ERROR ("\n Error in pushing the event,result is %d\n", result); } GST_DEBUG("\nCame to the FORMAT_TIME call\n"); } else { g_print("Newsegment event in format %s", gst_format_get_name(format)); result = gst_pad_push_event(filter->srcpad, event); if (TRUE != result) { GST_ERROR ("\n Error in pushing the event,result is %d\n", result); } } break; } case GST_EVENT_EOS: { gboolean ret; GST_DEBUG("\nSPDIF Receiver converter: Get EOS event\n"); if (filter->format == SPDIF_FORMAT_NONPCM) { mfw_gst_spdifrx_push(filter); while(ret == TRUE) { ret = mfw_gst_spdifrx_push(filter); }; mfw_gst_spdifrx_pushavail(filter); } result = gst_pad_event_default(pad, event); if (result != TRUE) { GST_ERROR("\n Error in pushing the event, result is %d\n",result); } break; } default: { result = gst_pad_event_default(pad, event); break; } } GST_DEBUG("Out of mfw_gst_spdifrx_sink_event() function \n "); return result; }
static gboolean gst_kate_enc_sink_event (GstPad * pad, GstEvent * event) { GstKateEnc *ke = GST_KATE_ENC (gst_pad_get_parent (pad)); GstStructure *structure; gboolean ret; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: GST_LOG_OBJECT (ke, "Got newsegment event"); if (ke->initialized) { GST_LOG_OBJECT (ke, "ensuring all headers are in"); if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { GST_WARNING_OBJECT (ke, "Failed to flush headers"); } else { GstFormat format; gint64 timestamp; gst_event_parse_new_segment (event, NULL, NULL, &format, ×tamp, NULL, NULL); if (format != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (timestamp)) { GST_WARNING_OBJECT (ke, "No time in newsegment event %p, format %d, timestamp %" G_GINT64_FORMAT, event, (int) format, timestamp); /* to be safe, we'd need to generate a keepalive anyway, but we'd have to guess at the timestamp to use; a good guess would be the last known timestamp plus the keepalive time, but if we then get a packet with a timestamp less than this, it would fail to encode, which would be Bad. If we don't encode a keepalive, we run the risk of stalling the pipeline and hanging, which is Very Bad. Oh dear. We can't exit(-1), can we ? */ } else { float t = timestamp / (double) GST_SECOND; if (ke->delayed_spu && t - ke->delayed_start / (double) GST_SECOND >= ke->default_spu_duration) { if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke, timestamp) != GST_FLOW_OK)) { GST_WARNING_OBJECT (ke, "Failed to encode delayed packet"); /* continue with new segment handling anyway */ } } GST_LOG_OBJECT (ke, "ts %f, last %f (min %f)", t, ke->last_timestamp / (double) GST_SECOND, ke->keepalive_min_time); if (ke->keepalive_min_time > 0.0f && t - ke->last_timestamp / (double) GST_SECOND >= ke->keepalive_min_time) { /* we only generate a keepalive if there is no SPU waiting, as it would mean out of sequence start times - and granulepos */ if (!ke->delayed_spu) { gst_kate_enc_generate_keepalive (ke, timestamp); } } } } } ret = gst_pad_push_event (ke->srcpad, event); break; case GST_EVENT_CUSTOM_DOWNSTREAM: GST_LOG_OBJECT (ke, "Got custom downstream event"); /* adapted from the dvdsubdec element */ structure = event->structure; if (structure != NULL && gst_structure_has_name (structure, "application/x-gst-dvd")) { if (ke->initialized) { GST_LOG_OBJECT (ke, "ensuring all headers are in"); if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { GST_WARNING_OBJECT (ke, "Failed to flush headers"); } else { const gchar *event_name = gst_structure_get_string (structure, "event"); if (event_name) { if (!strcmp (event_name, "dvd-spu-clut-change")) { gchar name[16]; int idx; gboolean found; gint value; GST_INFO_OBJECT (ke, "New CLUT received"); for (idx = 0; idx < 16; ++idx) { g_snprintf (name, sizeof (name), "clut%02d", idx); found = gst_structure_get_int (structure, name, &value); if (found) { ke->spu_clut[idx] = value; } else { GST_WARNING_OBJECT (ke, "DVD CLUT event did not contain %s field", name); } } } else if (!strcmp (event_name, "dvd-lang-codes")) { /* we can't know which stream corresponds to us */ } } else { GST_WARNING_OBJECT (ke, "custom downstream event with no name"); } } } } ret = gst_pad_push_event (ke->srcpad, event); break; case GST_EVENT_TAG: GST_LOG_OBJECT (ke, "Got tag event"); if (ke->tags) { GstTagList *list; gst_event_parse_tag (event, &list); gst_tag_list_insert (ke->tags, list, gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (ke))); } else { g_assert_not_reached (); } ret = gst_pad_event_default (pad, event); break; case GST_EVENT_EOS: GST_INFO_OBJECT (ke, "Got EOS event"); if (ke->initialized) { GST_LOG_OBJECT (ke, "ensuring all headers are in"); if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { GST_WARNING_OBJECT (ke, "Failed to flush headers"); } else { kate_packet kp; int ret; GstClockTime delayed_end = ke->delayed_start + ke->default_spu_duration * GST_SECOND; if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke, delayed_end) != GST_FLOW_OK)) { GST_WARNING_OBJECT (ke, "Failed to encode delayed packet"); /* continue with EOS handling anyway */ } ret = kate_encode_finish (&ke->k, -1, &kp); if (ret < 0) { GST_WARNING_OBJECT (ke, "Failed to encode EOS packet: %d", ret); } else { kate_int64_t granpos = kate_encode_get_granule (&ke->k); GST_LOG_OBJECT (ke, "EOS packet encoded"); if (gst_kate_enc_push_and_free_kate_packet (ke, &kp, granpos, ke->latest_end_time, 0, FALSE)) { GST_WARNING_OBJECT (ke, "Failed to push EOS packet"); } } } } ret = gst_pad_event_default (pad, event); break; default: GST_LOG_OBJECT (ke, "Got unhandled event"); ret = gst_pad_event_default (pad, event); break; } gst_object_unref (ke); return ret; }
/* 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_NEWSEGMENT: { gint64 start, stop, pos; GstFormat format; gst_event_parse_new_segment (event, NULL, NULL, &format, &start, &stop, &pos); if (format == GST_FORMAT_BYTES) { /* only try to seek and fail when we are going to a different * position */ if (filesink->current_pos != 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) start)) goto seek_failed; } else { GST_DEBUG_OBJECT (filesink, "Ignored NEWSEGMENT, no seek needed"); } } else { GST_DEBUG_OBJECT (filesink, "Ignored NEWSEGMENT event of format %u (%s)", (guint) format, gst_format_get_name (format)); } break; } case GST_EVENT_EOS: if (fflush (filesink->file)) goto flush_failed; break; default: break; } return TRUE; /* ERRORS */ seek_failed: { GST_ELEMENT_ERROR (filesink, RESOURCE, SEEK, (_("Error while seeking in file \"%s\"."), filesink->filename), GST_ERROR_SYSTEM); return FALSE; } flush_failed: { GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE, (_("Error while writing to file \"%s\"."), filesink->filename), GST_ERROR_SYSTEM); return FALSE; } }