#define DEFAULT_NUM_ACTIVE_SOURCES 0
#define DEFAULT_USE_PIPELINE_CLOCK FALSE
#define DEFAULT_RTCP_MIN_INTERVAL (RTP_STATS_MIN_INTERVAL * GST_SECOND)
+#define DEFAULT_PROBATION RTP_DEFAULT_PROBATION
enum
{
PROP_INTERNAL_SESSION,
PROP_USE_PIPELINE_CLOCK,
PROP_RTCP_MIN_INTERVAL,
+ PROP_PROBATION,
PROP_LAST
};
0, G_MAXUINT64, DEFAULT_RTCP_MIN_INTERVAL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_PROBATION,
+ g_param_spec_uint ("probation", "Number of probations",
+ "Consecutive packet sequence numbers to accept the source",
+ 0, G_MAXUINT, DEFAULT_PROBATION,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_rtp_session_change_state);
gstelement_class->request_new_pad =
g_object_set_property (G_OBJECT (priv->session), "rtcp-min-interval",
value);
break;
+ case PROP_PROBATION:
+ g_object_set_property (G_OBJECT (priv->session), "probation", value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_object_get_property (G_OBJECT (priv->session), "rtcp-min-interval",
value);
break;
+ case PROP_PROBATION:
+ g_object_get_property (G_OBJECT (priv->session), "probation", value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
#define DEFAULT_RTCP_MIN_INTERVAL (RTP_STATS_MIN_INTERVAL * GST_SECOND)
#define DEFAULT_RTCP_FEEDBACK_RETENTION_WINDOW (2 * GST_SECOND)
#define DEFAULT_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD (3)
+#define DEFAULT_PROBATION RTP_DEFAULT_PROBATION
enum
{
PROP_RTCP_MIN_INTERVAL,
PROP_RTCP_FEEDBACK_RETENTION_WINDOW,
PROP_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD,
+ PROP_PROBATION,
PROP_LAST
};
0, G_MAXUINT, DEFAULT_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_PROBATION,
+ g_param_spec_uint ("probation", "Number of probations",
+ "Consecutive packet sequence numbers to accept the source",
+ 0, G_MAXUINT, DEFAULT_PROBATION,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
klass->get_source_by_ssrc =
GST_DEBUG_FUNCPTR (rtp_session_get_source_by_ssrc);
klass->on_sending_rtcp = GST_DEBUG_FUNCPTR (rtp_session_on_sending_rtcp);
sess->header_len = 28;
sess->mtu = DEFAULT_RTCP_MTU;
+ sess->probation = DEFAULT_PROBATION;
+
/* some default SDES entries */
/* we do not want to leak details like the username or hostname here */
case PROP_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD:
sess->rtcp_immediate_feedback_threshold = g_value_get_uint (value);
break;
+ case PROP_PROBATION:
+ sess->probation = g_value_get_uint (value);
+ g_object_set_property (G_OBJECT (sess->source), "probation", value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD:
g_value_set_uint (value, sess->rtcp_immediate_feedback_threshold);
break;
+ case PROP_PROBATION:
+ g_value_set_uint (value, sess->probation);
+ g_object_get_property (G_OBJECT (sess->source), "probation", value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
* packets of an SSRC, on the other hand, is a strong indication that we
* are dealing with a valid source. */
if (rtp)
- source->probation = RTP_DEFAULT_PROBATION;
+ g_object_set (source, "probation", sess->probation, NULL);
else
- source->probation = 0;
+ g_object_set (source, "probation", 0, NULL);
/* store from address, if any */
if (arrival->address) {
*
* Returns: a #GstFlowReturn.
*/
-typedef GstFlowReturn (*RTPSessionSendRTCP) (RTPSession *sess, RTPSource *src, GstBuffer *buffer,
+typedef GstFlowReturn (*RTPSessionSendRTCP) (RTPSession *sess, RTPSource *src, GstBuffer *buffer,
gboolean eos, gpointer user_data);
/**
* @sess: an #RTPSession
* @user_data: user data specified when registering
*
- * This callback will be called when @sess needs to cancel the current timeout.
+ * This callback will be called when @sess needs to cancel the current timeout.
* The currently running timeout should be canceled and a new reporting interval
* should be requested from @sess.
*/
guint header_len;
guint mtu;
+ guint probation;
+
/* bandwidths */
gboolean recalc_bandwidth;
guint bandwidth;
#define DEFAULT_IS_VALIDATED FALSE
#define DEFAULT_IS_SENDER FALSE
#define DEFAULT_SDES NULL
+#define DEFAULT_PROBATION RTP_DEFAULT_PROBATION
enum
{
PROP_IS_SENDER,
PROP_SDES,
PROP_STATS,
+ PROP_PROBATION,
PROP_LAST
};
"The stats of this source", GST_TYPE_STRUCTURE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_PROBATION,
+ g_param_spec_uint ("probation", "Number of probations",
+ "Consecutive packet sequence numbers to accept the source",
+ 0, G_MAXUINT, DEFAULT_PROBATION,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
GST_DEBUG_CATEGORY_INIT (rtp_source_debug, "rtpsource", 0, "RTP Source");
}
* packets or a valid RTCP packet */
src->validated = FALSE;
src->internal = FALSE;
- src->probation = RTP_DEFAULT_PROBATION;
+ src->probation = DEFAULT_PROBATION;
+ src->curr_probation = src->probation;
src->closing = FALSE;
src->sdes = gst_structure_new_empty ("application/x-rtp-source-sdes");
case PROP_SSRC:
src->ssrc = g_value_get_uint (value);
break;
+ case PROP_PROBATION:
+ src->probation = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_STATS:
g_value_take_boxed (value, rtp_source_create_stats (src));
break;
+ case PROP_PROBATION:
+ g_value_set_uint (value, src->probation);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
/* first time we heard of this source */
init_seq (src, seqnr);
src->stats.max_seq = seqnr - 1;
- src->probation = RTP_DEFAULT_PROBATION;
+ src->curr_probation = src->probation;
}
udelta = seqnr - stats->max_seq;
/* if we are still on probation, check seqnum */
- if (src->probation) {
+ if (src->curr_probation) {
expected = src->stats.max_seq + 1;
/* when in probation, we require consecutive seqnums */
if (seqnr == expected) {
/* expected packet */
GST_DEBUG ("probation: seqnr %d == expected %d", seqnr, expected);
- src->probation--;
+ src->curr_probation--;
src->stats.max_seq = seqnr;
- if (src->probation == 0) {
+ if (src->curr_probation == 0) {
GST_DEBUG ("probation done!");
init_seq (src, seqnr);
} else {
GstBuffer *q;
- GST_DEBUG ("probation %d: queue buffer", src->probation);
+ GST_DEBUG ("probation %d: queue buffer", src->curr_probation);
/* when still in probation, keep packets in a list. */
g_queue_push_tail (src->packets, buffer);
/* remove packets from queue if there are too many */
}
} else {
/* duplicate or reordered packet, will be filtered by jitterbuffer. */
- GST_WARNING ("duplicate or reordered packet");
+ GST_WARNING ("duplicate or reordered packet (seqnr %d)", seqnr);
}
src->stats.octets_received += arrival->payload_len;
probation_seqnum:
{
GST_WARNING ("probation: seqnr %d != expected %d", seqnr, expected);
- src->probation = RTP_DEFAULT_PROBATION;
+ src->curr_probation = src->probation;
src->stats.max_seq = seqnr;
gst_buffer_unref (buffer);
return GST_FLOW_OK;
*
* Returns: a #GstFlowReturn.
*/
-typedef GstFlowReturn (*RTPSourcePushRTP) (RTPSource *src, GstBuffer *buffer,
+typedef GstFlowReturn (*RTPSourcePushRTP) (RTPSource *src, GstBuffer *buffer,
gpointer user_data);
/**
/*< private >*/
guint32 ssrc;
- gint probation;
+ guint probation;
+ guint curr_probation;
gboolean validated;
gboolean internal;
gboolean is_csrc;
#define DEFAULT_BUFFER_MODE BUFFER_MODE_AUTO
#define DEFAULT_PORT_RANGE NULL
#define DEFAULT_SHORT_HEADER FALSE
+#define DEFAULT_PROBATION 2
enum
{
PROP_PORT_RANGE,
PROP_UDP_BUFFER_SIZE,
PROP_SHORT_HEADER,
+ PROP_PROBATION,
PROP_LAST
};
"Only send the basic RTSP headers for broken encoders",
DEFAULT_SHORT_HEADER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_PROBATION,
+ g_param_spec_uint ("probation", "Number of probations",
+ "Consecutive packet sequence numbers to accept the source",
+ 0, G_MAXUINT, DEFAULT_PROBATION,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gstelement_class->send_event = gst_rtspsrc_send_event;
gstelement_class->change_state = gst_rtspsrc_change_state;
src->client_port_range.max = 0;
src->udp_buffer_size = DEFAULT_UDP_BUFFER_SIZE;
src->short_header = DEFAULT_SHORT_HEADER;
+ src->probation = DEFAULT_PROBATION;
/* get a list of all extensions */
src->extensions = gst_rtsp_ext_list_get ();
case PROP_SHORT_HEADER:
rtspsrc->short_header = g_value_get_boolean (value);
break;
+ case PROP_PROBATION:
+ rtspsrc->probation = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_SHORT_HEADER:
g_value_set_boolean (value, rtspsrc->short_header);
break;
+ case PROP_PROBATION:
+ g_value_set_uint (value, rtspsrc->probation);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_object_set (rtpsession, "rtcp-rs-bandwidth", stream->rs_bandwidth,
NULL);
}
+
+ g_object_set (rtpsession, "probation", src->probation, NULL);
+
g_signal_connect (rtpsession, "on-bye-ssrc", (GCallback) on_bye_ssrc,
stream);
g_signal_connect (rtpsession, "on-bye-timeout", (GCallback) on_timeout,
GstRTSPRange client_port_range;
gint udp_buffer_size;
gboolean short_header;
+ guint probation;
/* state */
GstRTSPState state;