gboolean all_headers, gpointer user_data);
static GstClockTime gst_rtp_session_request_time (RTPSession * session,
gpointer user_data);
+static void gst_rtp_session_notify_nack (RTPSession * sess,
+ guint16 seqnum, guint16 blp, gpointer user_data);
static RTPSessionCallbacks callbacks = {
gst_rtp_session_process_rtp,
gst_rtp_session_clock_rate,
gst_rtp_session_reconsider,
gst_rtp_session_request_key_unit,
- gst_rtp_session_request_time
+ gst_rtp_session_request_time,
+ gst_rtp_session_notify_nack
};
/* GObject vmethods */
return gst_clock_get_time (rtpsession->priv->sysclock);
}
+
+static void
+gst_rtp_session_notify_nack (RTPSession * sess, guint16 seqnum,
+ guint16 blp, gpointer user_data)
+{
+ GstRtpSession *rtpsession = GST_RTP_SESSION (user_data);
+ GstEvent *event;
+ GstPad *send_rtp_sink;
+
+ GST_RTP_SESSION_LOCK (rtpsession);
+ if ((send_rtp_sink = rtpsession->send_rtp_sink))
+ gst_object_ref (send_rtp_sink);
+ GST_RTP_SESSION_UNLOCK (rtpsession);
+
+ if (send_rtp_sink) {
+ while (TRUE) {
+ event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
+ gst_structure_new ("GstRTPRetransmissionRequest",
+ "seqnum", G_TYPE_UINT, (guint) seqnum, NULL));
+ gst_pad_push_event (send_rtp_sink, event);
+
+ if (blp == 0)
+ break;
+
+ seqnum++;
+ while ((blp & 1) == 0) {
+ seqnum++;
+ blp >>= 1;
+ }
+ }
+ gst_object_unref (send_rtp_sink);
+ }
+}
sess->callbacks.request_time = callbacks->request_time;
sess->request_time_user_data = user_data;
}
+ if (callbacks->notify_nack) {
+ sess->callbacks.notify_nack = callbacks->notify_nack;
+ sess->notify_nack_user_data = user_data;
+ }
}
/**
}
static void
+rtp_session_process_nack (RTPSession * sess, guint32 sender_ssrc,
+ guint32 media_ssrc, guint8 * fci_data, guint fci_length,
+ GstClockTime current_time)
+{
+ if (!sess->callbacks.notify_nack)
+ return;
+
+ while (fci_length > 0) {
+ guint16 seqnum, blp;
+
+ seqnum = GST_READ_UINT16_BE (fci_data);
+ blp = GST_READ_UINT16_BE (fci_data + 2);
+
+ GST_DEBUG ("NACK #%u, blp %04x", seqnum, blp);
+
+ RTP_SESSION_UNLOCK (sess);
+ sess->callbacks.notify_nack (sess, seqnum, blp,
+ sess->notify_nack_user_data);
+ RTP_SESSION_LOCK (sess);
+
+ fci_data += 4;
+ fci_length -= 4;
+ }
+}
+
+static void
rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet,
RTPArrivalStats * arrival, GstClockTime current_time)
{
}
break;
case GST_RTCP_TYPE_RTPFB:
+ switch (fbtype) {
+ case GST_RTCP_RTPFB_TYPE_NACK:
+ rtp_session_process_nack (sess, sender_ssrc, media_ssrc,
+ fci_data, fci_length, current_time);
+ break;
+ default:
+ break;
+ }
default:
break;
}
* @all_headers: %TRUE if "all-headers" property should be set on the key unit
* request
* @user_data: user data specified when registering
-*
+ *
* Asks the encoder to produce a key unit as soon as possibly within the
* bandwidth constraints
*/
gpointer user_data);
/**
+ * RTPSessionNotifyNACK:
+ * @sess: an #RTPSession
+ * @seqnum: the missing seqnum
+ * @blp: other missing seqnums
+ * @user_data: user data specified when registering
+ *
+ * Notifies of NACKed frames.
+ */
+typedef void (*RTPSessionNotifyNACK) (RTPSession *sess,
+ guint16 seqnum, guint16 blp, gpointer user_data);
+
+/**
* RTPSessionCallbacks:
* @RTPSessionProcessRTP: callback to process RTP packets
* @RTPSessionSendRTP: callback for sending RTP packets
* @RTPSessionSyncRTCP: callback for handling SR packets
* @RTPSessionReconsider: callback for reconsidering the timeout
* @RTPSessionRequestKeyUnit: callback for requesting a new key unit
+ * @RTPSessionRequestTime: callback for requesting the current time
+ * @RTPSessionNotifyNACK: callback for notifying NACK
*
* These callbacks can be installed on the session manager to get notification
* when RTP and RTCP packets are ready for further processing. These callbacks
RTPSessionReconsider reconsider;
RTPSessionRequestKeyUnit request_key_unit;
RTPSessionRequestTime request_time;
+ RTPSessionNotifyNACK notify_nack;
} RTPSessionCallbacks;
/**
gpointer reconsider_user_data;
gpointer request_key_unit_user_data;
gpointer request_time_user_data;
+ gpointer notify_nack_user_data;
RTPSessionStats stats;