+
+/**
+ * rtp_source_register_nack:
+ * @src: The #RTPSource
+ * @seqnum: a seqnum
+ * @deadline: the deadline before which RTX is still possible
+ *
+ * Register that @seqnum has not been received from @src.
+ */
+void
+rtp_source_register_nack (RTPSource * src, guint16 seqnum,
+ GstClockTime deadline)
+{
+ gint i;
+ guint len;
+ gint diff = -1;
+ guint16 tseq;
+
+ len = src->nacks->len;
+ for (i = len - 1; i >= 0; i--) {
+ tseq = g_array_index (src->nacks, guint16, i);
+ diff = gst_rtp_buffer_compare_seqnum (tseq, seqnum);
+
+ GST_TRACE ("[%u] %u %u diff %i len %u", i, tseq, seqnum, diff, len);
+
+ if (diff >= 0)
+ break;
+ }
+
+ if (diff == 0) {
+ GST_DEBUG ("update NACK #%u deadline to %" GST_TIME_FORMAT, seqnum,
+ GST_TIME_ARGS (deadline));
+ g_array_index (src->nack_deadlines, GstClockTime, i) = deadline;
+ } else if (i == len - 1) {
+ GST_DEBUG ("append NACK #%u with deadline %" GST_TIME_FORMAT, seqnum,
+ GST_TIME_ARGS (deadline));
+ g_array_append_val (src->nacks, seqnum);
+ g_array_append_val (src->nack_deadlines, deadline);
+ } else {
+ GST_DEBUG ("insert NACK #%u with deadline %" GST_TIME_FORMAT, seqnum,
+ GST_TIME_ARGS (deadline));
+ g_array_insert_val (src->nacks, i + 1, seqnum);
+ g_array_insert_val (src->nack_deadlines, i + 1, deadline);
+ }
+
+ src->send_nack = TRUE;
+}
+
+/**
+ * rtp_source_get_nacks:
+ * @src: The #RTPSource
+ * @n_nacks: result number of nacks
+ *
+ * Get the registered NACKS since the last rtp_source_clear_nacks().
+ *
+ * Returns: an array of @n_nacks seqnum values.
+ */
+guint16 *
+rtp_source_get_nacks (RTPSource * src, guint * n_nacks)
+{
+ if (n_nacks)
+ *n_nacks = src->nacks->len;
+
+ return (guint16 *) src->nacks->data;
+}
+
+/**
+ * rtp_source_get_nacks:
+ * @src: The #RTPSource
+ * @n_nacks: result number of nacks
+ *
+ * Get the registered NACKS deadlines.
+ *
+ * Returns: an array of @n_nacks deadline values.
+ */
+GstClockTime *
+rtp_source_get_nack_deadlines (RTPSource * src, guint * n_nacks)
+{
+ if (n_nacks)
+ *n_nacks = src->nack_deadlines->len;
+
+ return (GstClockTime *) src->nack_deadlines->data;
+}
+
+/**
+ * rtp_source_clear_nacks:
+ * @src: The #RTPSource
+ * @n_nacks: number of nacks
+ *
+ * Remove @n_nacks oldest NACKS form array.
+ */
+void
+rtp_source_clear_nacks (RTPSource * src, guint n_nacks)
+{
+ g_return_if_fail (n_nacks <= src->nacks->len);
+
+ if (src->nacks->len == n_nacks) {
+ g_array_set_size (src->nacks, 0);
+ g_array_set_size (src->nack_deadlines, 0);
+ src->send_nack = FALSE;
+ } else {
+ g_array_remove_range (src->nacks, 0, n_nacks);
+ g_array_remove_range (src->nack_deadlines, 0, n_nacks);
+ }
+}