static gboolean gst_frei0r_mixer_src_query (GstPad * pad, GstObject * object, GstQuery * query) { GstFrei0rMixer *self = GST_FREI0R_MIXER (object); gboolean ret = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: ret = gst_pad_query (self->sink0, query); break; case GST_QUERY_DURATION: ret = gst_frei0r_mixer_src_query_duration (self, query); break; case GST_QUERY_LATENCY: ret = gst_frei0r_mixer_src_query_latency (self, query); break; case GST_QUERY_CAPS: { GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); caps = gst_frei0r_mixer_get_caps (self, pad, filter); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); break; } default: ret = gst_pad_query_default (pad, GST_OBJECT (self), query); break; } return ret; }
static gboolean gst_frei0r_mixer_sink0_event (GstPad * pad, GstEvent * event) { GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); gboolean ret = FALSE; GstEvent **p_ev; GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: p_ev = &self->newseg_event; gst_event_replace (p_ev, event); break; default: break; } /* now GstCollectPads can take care of the rest, e.g. EOS */ ret = self->collect_event (pad, event); gst_object_unref (self); return ret; }
static gboolean gst_frei0r_mixer_src_query (GstPad * pad, GstQuery * query) { GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); gboolean ret = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: ret = gst_pad_query (self->sink0, query); break; case GST_QUERY_DURATION: ret = gst_frei0r_mixer_src_query_duration (self, query); break; case GST_QUERY_LATENCY: ret = gst_frei0r_mixer_src_query_latency (self, query); break; default: ret = gst_pad_query_default (pad, query); break; } gst_object_unref (self); return ret; }
static gboolean gst_frei0r_mixer_set_caps (GstPad * pad, GstCaps * caps) { GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); gboolean ret = TRUE; gst_caps_replace (&self->caps, caps); if (pad != self->src) ret &= gst_pad_set_caps (self->src, caps); if (pad != self->sink0) ret &= gst_pad_set_caps (self->sink0, caps); if (pad != self->sink1) ret &= gst_pad_set_caps (self->sink1, caps); if (pad != self->sink2 && self->sink2) ret &= gst_pad_set_caps (self->sink2, caps); if (ret) { if (!gst_video_format_parse_caps (caps, &self->fmt, &self->width, &self->height)) { ret = FALSE; goto out; } } out: gst_object_unref (self); return ret; }
static gboolean gst_frei0r_mixer_sink_query (GstPad * pad, GstQuery * query) { GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); gboolean ret = gst_pad_query (self->src, query); gst_object_unref (self); return ret; }
static GstCaps * gst_frei0r_mixer_get_caps (GstPad * pad) { GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); GstCaps *caps = NULL; if (self->caps) { caps = gst_caps_ref (self->caps); } else { GstCaps *tmp, *tmp1; tmp = gst_caps_copy (gst_pad_get_pad_template_caps (self->src)); tmp1 = gst_pad_peer_get_caps (pad); if (tmp1) { caps = gst_caps_intersect (tmp, tmp1); gst_caps_unref (tmp1); gst_caps_unref (tmp); } else { caps = tmp; } tmp = caps; tmp1 = gst_pad_peer_get_caps (self->sink0); if (tmp1) { caps = gst_caps_intersect (tmp, tmp1); gst_caps_unref (tmp); gst_caps_unref (tmp1); } tmp = caps; tmp1 = gst_pad_peer_get_caps (self->sink1); if (tmp1) { caps = gst_caps_intersect (tmp, tmp1); gst_caps_unref (tmp); gst_caps_unref (tmp1); } if (self->sink2) { tmp = caps; tmp1 = gst_pad_peer_get_caps (self->sink2); if (tmp1) { caps = gst_caps_intersect (tmp, tmp1); gst_caps_unref (tmp); gst_caps_unref (tmp1); } } } gst_object_unref (self); return caps; }
static void gst_frei0r_mixer_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstFrei0rMixer *self = GST_FREI0R_MIXER (object); GstFrei0rMixerClass *klass = GST_FREI0R_MIXER_GET_CLASS (object); GST_OBJECT_LOCK (self); if (!gst_frei0r_set_property (self->f0r_instance, klass->ftable, klass->properties, klass->n_properties, self->property_cache, prop_id, value)) G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); GST_OBJECT_UNLOCK (self); }
static void gst_frei0r_mixer_finalize (GObject * object) { GstFrei0rMixer *self = GST_FREI0R_MIXER (object); GstFrei0rMixerClass *klass = GST_FREI0R_MIXER_GET_CLASS (object); if (self->property_cache) gst_frei0r_property_cache_free (klass->properties, self->property_cache, klass->n_properties); self->property_cache = NULL; if (self->collect) gst_object_unref (self->collect); self->collect = NULL; G_OBJECT_CLASS (g_type_class_peek_parent (klass))->finalize (object); }
static gboolean gst_frei0r_mixer_src_event (GstPad * pad, GstEvent * event) { GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); gboolean ret = FALSE; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_QOS: /* QoS might be tricky */ ret = FALSE; break; case GST_EVENT_SEEK: { GstSeekFlags flags; /* parse the seek parameters */ gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL); /* check if we are flushing */ if (flags & GST_SEEK_FLAG_FLUSH) { /* make sure we accept nothing anymore and return WRONG_STATE */ gst_collect_pads_set_flushing (self->collect, TRUE); /* flushing seek, start flush downstream, the flush will be done * when all pads received a FLUSH_STOP. */ gst_pad_push_event (self->src, gst_event_new_flush_start ()); } ret = forward_event (self, event); break; } case GST_EVENT_NAVIGATION: /* navigation is rather pointless. */ ret = FALSE; break; default: /* just forward the rest for now */ ret = forward_event (self, event); break; } gst_object_unref (self); return ret; }
static GstStateChangeReturn gst_frei0r_mixer_change_state (GstElement * element, GstStateChange transition) { GstFrei0rMixer *self = GST_FREI0R_MIXER (element); GstFrei0rMixerClass *klass = GST_FREI0R_MIXER_GET_CLASS (self); GstStateChangeReturn ret; switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: gst_collect_pads_start (self->collect); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break; default: break; } /* Stop before calling the parent's state change function as * GstCollectPads might take locks and we would deadlock in that * case */ if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) gst_collect_pads_stop (self->collect); ret = GST_ELEMENT_CLASS (g_type_class_peek_parent (klass))->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_READY: gst_frei0r_mixer_reset (self); break; case GST_STATE_CHANGE_READY_TO_NULL: break; default: break; } return ret; }
static gboolean gst_frei0r_mixer_src_event (GstPad * pad, GstObject * object, GstEvent * event) { GstFrei0rMixer *self = GST_FREI0R_MIXER (object); gboolean ret = FALSE; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_QOS: /* QoS might be tricky */ ret = FALSE; break; case GST_EVENT_SEEK: { GstSeekFlags flags; /* parse the seek parameters */ gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL); /* check if we are flushing */ if (flags & GST_SEEK_FLAG_FLUSH) { /* make sure we accept nothing anymore and return WRONG_STATE */ gst_collect_pads_set_flushing (self->collect, TRUE); /* flushing seek, start flush downstream, the flush will be done * when all pads received a FLUSH_STOP. */ gst_pad_push_event (self->src, gst_event_new_flush_start ()); } ret = gst_pad_event_default (pad, GST_OBJECT (self), event); break; } default: ret = gst_pad_event_default (pad, GST_OBJECT (self), event); break; } return ret; }