static GstStateChangeReturn gst_rtp_mux_change_state (GstElement * element, GstStateChange transition) { GstRTPMux *rtp_mux; GstStateChangeReturn ret; rtp_mux = GST_RTP_MUX (element); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: gst_rtp_mux_ready_to_paused (rtp_mux); break; default: break; } ret = GST_ELEMENT_CLASS (gst_rtp_mux_parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: g_clear_object (&rtp_mux->last_pad); break; default: break; } return ret; }
static void gst_rtp_mux_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstRTPMux *rtp_mux; rtp_mux = GST_RTP_MUX (object); switch (prop_id) { case PROP_TIMESTAMP_OFFSET: rtp_mux->ts_offset = g_value_get_int (value); break; case PROP_SEQNUM_OFFSET: rtp_mux->seqnum_offset = g_value_get_int (value); break; case PROP_SSRC: GST_OBJECT_LOCK (rtp_mux); rtp_mux->ssrc = g_value_get_uint (value); rtp_mux->current_ssrc = rtp_mux->ssrc; rtp_mux->have_ssrc = TRUE; rtp_mux->ssrc_random = FALSE; GST_OBJECT_UNLOCK (rtp_mux); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static gboolean gst_rtp_mux_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstRTPMux *mux = GST_RTP_MUX (parent); gboolean res = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CAPS: { GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); GST_LOG_OBJECT (pad, "Received caps-query with filter-caps: %" GST_PTR_FORMAT, filter); caps = gst_rtp_mux_getcaps (pad, mux, filter); gst_query_set_caps_result (query, caps); GST_LOG_OBJECT (mux, "Answering caps-query with caps: %" GST_PTR_FORMAT, caps); gst_caps_unref (caps); res = TRUE; break; } default: res = gst_pad_query_default (pad, parent, query); break; } return res; }
static void gst_rtp_mux_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstRTPMux *rtp_mux; rtp_mux = GST_RTP_MUX (object); GST_OBJECT_LOCK (rtp_mux); switch (prop_id) { case PROP_TIMESTAMP_OFFSET: g_value_set_int (value, rtp_mux->ts_offset); break; case PROP_SEQNUM_OFFSET: g_value_set_int (value, rtp_mux->seqnum_offset); break; case PROP_SEQNUM: g_value_set_uint (value, rtp_mux->seqnum); break; case PROP_SSRC: g_value_set_uint (value, rtp_mux->ssrc); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } GST_OBJECT_UNLOCK (rtp_mux); }
static GstPad * gst_rtp_mux_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps) { GstRTPMux *rtp_mux; GstPad *newpad; g_return_val_if_fail (templ != NULL, NULL); g_return_val_if_fail (GST_IS_RTP_MUX (element), NULL); rtp_mux = GST_RTP_MUX (element); if (templ->direction != GST_PAD_SINK) { GST_WARNING_OBJECT (rtp_mux, "request pad that is not a SINK pad"); return NULL; } newpad = gst_pad_new_from_template (templ, req_name); if (newpad) gst_rtp_mux_setup_sinkpad (rtp_mux, newpad); else GST_WARNING_OBJECT (rtp_mux, "failed to create request pad"); return newpad; }
static gboolean gst_rtp_mux_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstRTPMux *mux = GST_RTP_MUX (parent); gboolean res = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CAPS: { GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); caps = gst_rtp_mux_getcaps (pad, mux, filter); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); res = TRUE; break; } default: res = gst_pad_query_default (pad, parent, query); break; } return res; }
static gboolean gst_rtp_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstRTPMux *mux = GST_RTP_MUX (parent); gboolean is_pad; gboolean ret; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); GST_LOG_OBJECT (pad, "Received caps-event with caps: %" GST_PTR_FORMAT, caps); ret = gst_rtp_mux_setcaps (pad, mux, caps); gst_event_unref (event); return ret; } case GST_EVENT_FLUSH_STOP: { GST_OBJECT_LOCK (mux); mux->last_stop = GST_CLOCK_TIME_NONE; GST_OBJECT_UNLOCK (mux); break; } case GST_EVENT_SEGMENT: { GstRTPMuxPadPrivate *padpriv; GST_OBJECT_LOCK (mux); padpriv = gst_pad_get_element_private (pad); if (padpriv) { gst_event_copy_segment (event, &padpriv->segment); } GST_OBJECT_UNLOCK (mux); break; } default: break; } GST_OBJECT_LOCK (mux); is_pad = (pad == mux->last_pad); GST_OBJECT_UNLOCK (mux); if (is_pad) { return gst_pad_push_event (mux->srcpad, event); } else { gst_event_unref (event); return TRUE; } }
static gboolean gst_rtp_mux_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstRTPMux *rtp_mux = GST_RTP_MUX (parent); GstRTPMuxClass *klass; gboolean ret; klass = GST_RTP_MUX_GET_CLASS (rtp_mux); ret = klass->src_event (rtp_mux, event); return ret; }
static void gst_rtp_mux_dispose (GObject * object) { GstRTPMux *rtp_mux = GST_RTP_MUX (object); GList *item; g_clear_object (&rtp_mux->last_pad); restart: for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { GstPad *pad = GST_PAD (item->data); if (GST_PAD_IS_SINK (pad)) { gst_element_release_request_pad (GST_ELEMENT (object), pad); goto restart; } } G_OBJECT_CLASS (gst_rtp_mux_parent_class)->dispose (object); }
static GstFlowReturn gst_rtp_mux_chain_list (GstPad * pad, GstObject * parent, GstBufferList * bufferlist) { GstRTPMux *rtp_mux; GstFlowReturn ret; GstRTPMuxPadPrivate *padpriv; struct BufferListData bd; rtp_mux = GST_RTP_MUX (parent); GST_OBJECT_LOCK (rtp_mux); padpriv = gst_pad_get_element_private (pad); if (!padpriv) { GST_OBJECT_UNLOCK (rtp_mux); ret = GST_FLOW_NOT_LINKED; gst_buffer_list_unref (bufferlist); goto out; } bd.rtp_mux = rtp_mux; bd.padpriv = padpriv; bd.drop = FALSE; bufferlist = gst_buffer_list_make_writable (bufferlist); gst_buffer_list_foreach (bufferlist, process_list_item, &bd); GST_OBJECT_UNLOCK (rtp_mux); if (bd.drop) { gst_buffer_list_unref (bufferlist); ret = GST_FLOW_OK; } else { ret = gst_pad_push_list (rtp_mux->srcpad, bufferlist); } out: return ret; }
static GstFlowReturn gst_rtp_mux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstRTPMux *rtp_mux; GstFlowReturn ret; GstRTPMuxPadPrivate *padpriv; gboolean drop; gboolean changed = FALSE; GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; rtp_mux = GST_RTP_MUX (parent); if (gst_pad_check_reconfigure (rtp_mux->srcpad)) { GstCaps *current_caps = gst_pad_get_current_caps (pad); if (!gst_rtp_mux_setcaps (pad, rtp_mux, current_caps)) { ret = GST_FLOW_NOT_NEGOTIATED; gst_buffer_unref (buffer); goto out; } gst_caps_unref (current_caps); } GST_OBJECT_LOCK (rtp_mux); padpriv = gst_pad_get_element_private (pad); if (!padpriv) { GST_OBJECT_UNLOCK (rtp_mux); gst_buffer_unref (buffer); return GST_FLOW_NOT_LINKED; } buffer = gst_buffer_make_writable (buffer); if (!gst_rtp_buffer_map (buffer, GST_MAP_READWRITE, &rtpbuffer)) { GST_OBJECT_UNLOCK (rtp_mux); gst_buffer_unref (buffer); GST_ERROR_OBJECT (rtp_mux, "Invalid RTP buffer"); return GST_FLOW_ERROR; } drop = !process_buffer_locked (rtp_mux, padpriv, &rtpbuffer); gst_rtp_buffer_unmap (&rtpbuffer); if (!drop) { if (pad != rtp_mux->last_pad) { changed = TRUE; g_clear_object (&rtp_mux->last_pad); rtp_mux->last_pad = g_object_ref (pad); } if (GST_BUFFER_DURATION_IS_VALID (buffer) && GST_BUFFER_PTS_IS_VALID (buffer)) rtp_mux->last_stop = GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer); else rtp_mux->last_stop = GST_CLOCK_TIME_NONE; } GST_OBJECT_UNLOCK (rtp_mux); if (changed) gst_pad_sticky_events_foreach (pad, resend_events, rtp_mux); if (drop) { gst_buffer_unref (buffer); ret = GST_FLOW_OK; } else { ret = gst_pad_push (rtp_mux->srcpad, buffer); } out: return ret; }
static GstFlowReturn gst_rtp_mux_chain_list (GstPad * pad, GstObject * parent, GstBufferList * bufferlist) { GstRTPMux *rtp_mux; GstFlowReturn ret; GstRTPMuxPadPrivate *padpriv; gboolean changed = FALSE; struct BufferListData bd; rtp_mux = GST_RTP_MUX (parent); if (gst_pad_check_reconfigure (rtp_mux->srcpad)) { GstCaps *current_caps = gst_pad_get_current_caps (pad); if (!gst_rtp_mux_setcaps (pad, rtp_mux, current_caps)) { ret = GST_FLOW_NOT_NEGOTIATED; gst_buffer_list_unref (bufferlist); goto out; } gst_caps_unref (current_caps); } GST_OBJECT_LOCK (rtp_mux); padpriv = gst_pad_get_element_private (pad); if (!padpriv) { GST_OBJECT_UNLOCK (rtp_mux); ret = GST_FLOW_NOT_LINKED; gst_buffer_list_unref (bufferlist); goto out; } bd.rtp_mux = rtp_mux; bd.padpriv = padpriv; bd.drop = FALSE; bufferlist = gst_buffer_list_make_writable (bufferlist); gst_buffer_list_foreach (bufferlist, process_list_item, &bd); if (!bd.drop && pad != rtp_mux->last_pad) { changed = TRUE; g_clear_object (&rtp_mux->last_pad); rtp_mux->last_pad = g_object_ref (pad); } GST_OBJECT_UNLOCK (rtp_mux); if (changed) gst_pad_sticky_events_foreach (pad, resend_events, rtp_mux); if (bd.drop) { gst_buffer_list_unref (bufferlist); ret = GST_FLOW_OK; } else { ret = gst_pad_push_list (rtp_mux->srcpad, bufferlist); } out: return ret; }