X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Frtsp-server%2Frtsp-stream.c;h=fb200901a7d9a70dad0cb7c44aa5ba86136e7031;hb=48b6b8e3e60369347972298aa96546912970ada5;hp=046ca5c72fd2ad55ee710234c78c0ce08e4a5c96;hpb=e5332535a738d90f234710b822cfe9a8bbbb23cf;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst/rtsp-server/rtsp-stream.c b/gst/rtsp-server/rtsp-stream.c index 046ca5c..fb20090 100644 --- a/gst/rtsp-server/rtsp-stream.c +++ b/gst/rtsp-server/rtsp-stream.c @@ -68,6 +68,7 @@ struct _GstRTSPStreamPrivate gboolean is_joined; gchar *control; + GstRTSPProfile profiles; GstRTSPLowerTrans protocols; /* pads on the rtpbin */ @@ -120,9 +121,14 @@ struct _GstRTSPStreamPrivate GList *transports; gint dscp_qos; + + /* stream blocking */ + gulong blocked_id; + gboolean blocking; }; #define DEFAULT_CONTROL NULL +#define DEFAULT_PROFILES GST_RTSP_PROFILE_AVP #define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \ GST_RTSP_LOWER_TRANS_TCP @@ -130,6 +136,7 @@ enum { PROP_0, PROP_CONTROL, + PROP_PROFILES, PROP_PROTOCOLS, PROP_LAST }; @@ -166,6 +173,11 @@ gst_rtsp_stream_class_init (GstRTSPStreamClass * klass) "The control string for this stream", DEFAULT_CONTROL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PROFILES, + g_param_spec_flags ("profiles", "Profiles", + "Allowed transfer profiles", GST_TYPE_RTSP_PROFILE, + DEFAULT_PROFILES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PROTOCOLS, g_param_spec_flags ("protocols", "Protocols", "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS, @@ -187,6 +199,7 @@ gst_rtsp_stream_init (GstRTSPStream * stream) priv->dscp_qos = -1; priv->control = g_strdup (DEFAULT_CONTROL); + priv->profiles = DEFAULT_PROFILES; priv->protocols = DEFAULT_PROTOCOLS; g_mutex_init (&priv->lock); @@ -234,6 +247,9 @@ gst_rtsp_stream_get_property (GObject * object, guint propid, case PROP_CONTROL: g_value_take_string (value, gst_rtsp_stream_get_control (stream)); break; + case PROP_PROFILES: + g_value_set_flags (value, gst_rtsp_stream_get_profiles (stream)); + break; case PROP_PROTOCOLS: g_value_set_flags (value, gst_rtsp_stream_get_protocols (stream)); break; @@ -252,6 +268,9 @@ gst_rtsp_stream_set_property (GObject * object, guint propid, case PROP_CONTROL: gst_rtsp_stream_set_control (stream, g_value_get_string (value)); break; + case PROP_PROFILES: + gst_rtsp_stream_set_profiles (stream, g_value_get_flags (value)); + break; case PROP_PROTOCOLS: gst_rtsp_stream_set_protocols (stream, g_value_get_flags (value)); break; @@ -417,8 +436,11 @@ gst_rtsp_stream_has_control (GstRTSPStream * stream, const gchar * control) res = (g_strcmp0 (priv->control, control) == 0); else { guint streamid; - sscanf (control, "stream=%u", &streamid); - res = (streamid == priv->idx); + + if (sscanf (control, "stream=%u", &streamid) > 0) + res = (streamid == priv->idx); + else + res = FALSE; } g_mutex_unlock (&priv->lock); @@ -539,6 +561,106 @@ gst_rtsp_stream_get_dscp_qos (GstRTSPStream * stream) } /** + * gst_rtsp_stream_is_transport_supported: + * @stream: a #GstRTSPStream + * @transport: a #GstRTSPTransport + * + * Check if @transport can be handled by stream + * + * Returns: %TRUE if @transport can be handled by @stream. + */ +gboolean +gst_rtsp_stream_is_transport_supported (GstRTSPStream * stream, + GstRTSPTransport * transport) +{ + GstRTSPStreamPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if (transport->trans != GST_RTSP_TRANS_RTP) + goto unsupported_transmode; + + if (!(transport->profile & priv->profiles)) + goto unsupported_profile; + + if (!(transport->lower_transport & priv->protocols)) + goto unsupported_ltrans; + + g_mutex_unlock (&priv->lock); + + return TRUE; + + /* ERRORS */ +unsupported_transmode: + { + GST_DEBUG ("unsupported transport mode %d", transport->trans); + g_mutex_unlock (&priv->lock); + return FALSE; + } +unsupported_profile: + { + GST_DEBUG ("unsupported profile %d", transport->profile); + g_mutex_unlock (&priv->lock); + return FALSE; + } +unsupported_ltrans: + { + GST_DEBUG ("unsupported lower transport %d", transport->lower_transport); + g_mutex_unlock (&priv->lock); + return FALSE; + } +} + +/** + * gst_rtsp_stream_set_profiles: + * @stream: a #GstRTSPStream + * @profiles: the new profiles + * + * Configure the allowed profiles for @stream. + */ +void +gst_rtsp_stream_set_profiles (GstRTSPStream * stream, GstRTSPProfile profiles) +{ + GstRTSPStreamPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + priv->profiles = profiles; + g_mutex_unlock (&priv->lock); +} + +/** + * gst_rtsp_stream_get_profiles: + * @stream: a #GstRTSPStream + * + * Get the allowed profiles of @stream. + * + * Returns: a #GstRTSPProfile + */ +GstRTSPProfile +gst_rtsp_stream_get_profiles (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + GstRTSPProfile res; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), GST_RTSP_PROFILE_UNKNOWN); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + res = priv->profiles; + g_mutex_unlock (&priv->lock); + + return res; +} + +/** * gst_rtsp_stream_set_protocols: * @stream: a #GstRTSPStream * @protocols: the new flags @@ -1028,10 +1150,6 @@ cleanup: gst_element_set_state (udpsink0, GST_STATE_NULL); gst_object_unref (udpsink0); } - if (udpsink1) { - gst_element_set_state (udpsink1, GST_STATE_NULL); - gst_object_unref (udpsink1); - } if (inetaddr) g_object_unref (inetaddr); g_list_free_full (rejected_addresses, @@ -1739,6 +1857,7 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin, was_not_joined: { + g_mutex_unlock (&priv->lock); return TRUE; } } @@ -1746,36 +1865,78 @@ was_not_joined: /** * gst_rtsp_stream_get_rtpinfo: * @stream: a #GstRTSPStream - * @rtptime: result RTP timestamp - * @seq: result RTP seqnum + * @rtptime: (allow-none): result RTP timestamp + * @seq: (allow-none): result RTP seqnum + * @clock_rate: the clock rate + * @running_time: (allow-none): result running-time * - * Retrieve the current rtptime and seq. This is used to + * Retrieve the current rtptime, seq and running-time. This is used to * construct a RTPInfo reply header. * - * Returns: %TRUE when rtptime and seq could be determined. + * Returns: %TRUE when rtptime, seq and running-time could be determined. */ gboolean gst_rtsp_stream_get_rtpinfo (GstRTSPStream * stream, - guint * rtptime, guint * seq) + guint * rtptime, guint * seq, guint * clock_rate, + GstClockTime * running_time) { GstRTSPStreamPrivate *priv; + GstStructure *stats; GObjectClass *payobjclass; g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); - g_return_val_if_fail (rtptime != NULL, FALSE); - g_return_val_if_fail (seq != NULL, FALSE); priv = stream->priv; payobjclass = G_OBJECT_GET_CLASS (priv->payloader); - if (!g_object_class_find_property (payobjclass, "seqnum") || - !g_object_class_find_property (payobjclass, "timestamp")) - return FALSE; + g_mutex_lock (&priv->lock); - g_object_get (priv->payloader, "seqnum", seq, "timestamp", rtptime, NULL); + if (g_object_class_find_property (payobjclass, "stats")) { + g_object_get (priv->payloader, "stats", &stats, NULL); + if (stats == NULL) + goto no_stats; + + if (seq) + gst_structure_get_uint (stats, "seqnum", seq); + + if (rtptime) + gst_structure_get_uint (stats, "timestamp", rtptime); + + if (running_time) + gst_structure_get_clock_time (stats, "running-time", running_time); + + if (clock_rate) { + gst_structure_get_uint (stats, "clock-rate", clock_rate); + if (*clock_rate == 0 && running_time) + *running_time = GST_CLOCK_TIME_NONE; + } + gst_structure_free (stats); + } else { + if (!g_object_class_find_property (payobjclass, "seqnum") || + !g_object_class_find_property (payobjclass, "timestamp")) + goto no_stats; + + if (seq) + g_object_get (priv->payloader, "seqnum", seq, NULL); + + if (rtptime) + g_object_get (priv->payloader, "timestamp", rtptime, NULL); + + if (running_time) + *running_time = GST_CLOCK_TIME_NONE; + } + g_mutex_unlock (&priv->lock); return TRUE; + + /* ERRORS */ +no_stats: + { + GST_WARNING ("Could not get payloader stats"); + g_mutex_unlock (&priv->lock); + return FALSE; + } } /** @@ -1914,14 +2075,14 @@ update_transport (GstRTSPStream * stream, GstRTSPStreamTransport * trans, } if (add) { - GST_INFO ("adding %s:%d-%d", dest, min, max); - g_signal_emit_by_name (priv->udpsink[0], "add", dest, min, NULL); - g_signal_emit_by_name (priv->udpsink[1], "add", dest, max, NULL); if (ttl > 0) { GST_INFO ("setting ttl-mc %d", ttl); g_object_set (G_OBJECT (priv->udpsink[0]), "ttl-mc", ttl, NULL); g_object_set (G_OBJECT (priv->udpsink[1]), "ttl-mc", ttl, NULL); } + GST_INFO ("adding %s:%d-%d", dest, min, max); + g_signal_emit_by_name (priv->udpsink[0], "add", dest, min, NULL); + g_signal_emit_by_name (priv->udpsink[1], "add", dest, max, NULL); priv->transports = g_list_prepend (priv->transports, trans); } else { GST_INFO ("removing %s:%d-%d", dest, min, max); @@ -2029,15 +2190,15 @@ gst_rtsp_stream_remove_transport (GstRTSPStream * stream, * * @stream must be joined to a bin. * - * Returns: the RTP socket or %NULL if no socket could be allocated for @family. - * Unref after usage + * Returns: (transfer full): the RTP socket or %NULL if no socket could be + * allocated for @family. Unref after usage */ GSocket * gst_rtsp_stream_get_rtp_socket (GstRTSPStream * stream, GSocketFamily family) { GstRTSPStreamPrivate *priv = GST_RTSP_STREAM_GET_PRIVATE (stream); GSocket *socket; - gchar *name; + const gchar *name; g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); g_return_val_if_fail (family == G_SOCKET_FAMILY_IPV4 || @@ -2063,15 +2224,15 @@ gst_rtsp_stream_get_rtp_socket (GstRTSPStream * stream, GSocketFamily family) * * @stream must be joined to a bin. * - * Returns: the RTCP socket or %NULL if no socket could be allocated for - * @family. Unref after usage + * Returns: (transfer full): the RTCP socket or %NULL if no socket could be + * allocated for @family. Unref after usage */ GSocket * gst_rtsp_stream_get_rtcp_socket (GstRTSPStream * stream, GSocketFamily family) { GstRTSPStreamPrivate *priv = GST_RTSP_STREAM_GET_PRIVATE (stream); GSocket *socket; - gchar *name; + const gchar *name; g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), NULL); g_return_val_if_fail (family == G_SOCKET_FAMILY_IPV4 || @@ -2154,3 +2315,89 @@ gst_rtsp_stream_transport_filter (GstRTSPStream * stream, return result; } + +static GstPadProbeReturn +pad_blocking (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + GstRTSPStreamPrivate *priv; + GstRTSPStream *stream; + + stream = user_data; + priv = stream->priv; + + GST_DEBUG_OBJECT (pad, "now blocking"); + + g_mutex_lock (&priv->lock); + priv->blocking = TRUE; + g_mutex_unlock (&priv->lock); + + gst_element_post_message (priv->payloader, + gst_message_new_element (GST_OBJECT_CAST (priv->payloader), + gst_structure_new_empty ("GstRTSPStreamBlocking"))); + + return GST_PAD_PROBE_OK; +} + +/** + * gst_rtsp_stream_set_blocked: + * @stream: a #GstRTSPStream + * @blocked: boolean indicating we should block or unblock + * + * Blocks or unblocks the dataflow on @stream. + * + * Returns: %TRUE on success + */ +gboolean +gst_rtsp_stream_set_blocked (GstRTSPStream * stream, gboolean blocked) +{ + GstRTSPStreamPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + if (blocked) { + priv->blocking = FALSE; + if (priv->blocked_id == 0) { + priv->blocked_id = gst_pad_add_probe (priv->srcpad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER | + GST_PAD_PROBE_TYPE_BUFFER_LIST, pad_blocking, + g_object_ref (stream), g_object_unref); + } + } else { + if (priv->blocked_id != 0) { + gst_pad_remove_probe (priv->srcpad, priv->blocked_id); + priv->blocked_id = 0; + priv->blocking = FALSE; + } + } + g_mutex_unlock (&priv->lock); + + return TRUE; +} + +/** + * gst_rtsp_stream_is_blocking: + * @stream: a #GstRTSPStream + * + * Check if @stream is blocking on a #GstBuffer. + * + * Returns: %TRUE if @stream is blocking + */ +gboolean +gst_rtsp_stream_is_blocking (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + gboolean result; + + g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE); + + priv = stream->priv; + + g_mutex_lock (&priv->lock); + result = priv->blocking; + g_mutex_unlock (&priv->lock); + + return result; +}