rtpbin: add SDES property that takes GstStructure
[platform/upstream/gstreamer.git] / gst / rtpmanager / rtpsource.c
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <string.h>
20
21 #include <gst/rtp/gstrtpbuffer.h>
22 #include <gst/rtp/gstrtcpbuffer.h>
23
24 #include "rtpsource.h"
25
26 GST_DEBUG_CATEGORY_STATIC (rtp_source_debug);
27 #define GST_CAT_DEFAULT rtp_source_debug
28
29 #define RTP_MAX_PROBATION_LEN  32
30
31 /* signals and args */
32 enum
33 {
34   LAST_SIGNAL
35 };
36
37 #define DEFAULT_SSRC                 0
38 #define DEFAULT_IS_CSRC              FALSE
39 #define DEFAULT_IS_VALIDATED         FALSE
40 #define DEFAULT_IS_SENDER            FALSE
41 #define DEFAULT_SDES                 NULL
42
43 enum
44 {
45   PROP_0,
46   PROP_SSRC,
47   PROP_IS_CSRC,
48   PROP_IS_VALIDATED,
49   PROP_IS_SENDER,
50   PROP_SDES,
51   PROP_STATS,
52   PROP_LAST
53 };
54
55 /* GObject vmethods */
56 static void rtp_source_finalize (GObject * object);
57 static void rtp_source_set_property (GObject * object, guint prop_id,
58     const GValue * value, GParamSpec * pspec);
59 static void rtp_source_get_property (GObject * object, guint prop_id,
60     GValue * value, GParamSpec * pspec);
61
62 /* static guint rtp_source_signals[LAST_SIGNAL] = { 0 }; */
63
64 G_DEFINE_TYPE (RTPSource, rtp_source, G_TYPE_OBJECT);
65
66 static void
67 rtp_source_class_init (RTPSourceClass * klass)
68 {
69   GObjectClass *gobject_class;
70
71   gobject_class = (GObjectClass *) klass;
72
73   gobject_class->finalize = rtp_source_finalize;
74
75   gobject_class->set_property = rtp_source_set_property;
76   gobject_class->get_property = rtp_source_get_property;
77
78   g_object_class_install_property (gobject_class, PROP_SSRC,
79       g_param_spec_uint ("ssrc", "SSRC",
80           "The SSRC of this source", 0, G_MAXUINT, DEFAULT_SSRC,
81           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
82
83   g_object_class_install_property (gobject_class, PROP_IS_CSRC,
84       g_param_spec_boolean ("is-csrc", "Is CSRC",
85           "If this SSRC is acting as a contributing source",
86           DEFAULT_IS_CSRC, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
87
88   g_object_class_install_property (gobject_class, PROP_IS_VALIDATED,
89       g_param_spec_boolean ("is-validated", "Is Validated",
90           "If this SSRC is validated", DEFAULT_IS_VALIDATED,
91           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
92
93   g_object_class_install_property (gobject_class, PROP_IS_SENDER,
94       g_param_spec_boolean ("is-sender", "Is Sender",
95           "If this SSRC is a sender", DEFAULT_IS_SENDER,
96           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
97
98   /**
99    * RTPSource::sdes
100    *
101    * The current SDES items of the source. Returns a structure with the
102    * following fields:
103    *
104    *  'cname'    G_TYPE_STRING  : The canonical name 
105    *  'name'     G_TYPE_STRING  : The user name 
106    *  'email'    G_TYPE_STRING  : The user's electronic mail address
107    *  'phone'    G_TYPE_STRING  : The user's phone number
108    *  'location' G_TYPE_STRING  : The geographic user location
109    *  'tool'     G_TYPE_STRING  : The name of application or tool
110    *  'note'     G_TYPE_STRING  : A notice about the source
111    */
112   g_object_class_install_property (gobject_class, PROP_SDES,
113       g_param_spec_boxed ("sdes", "SDES",
114           "The SDES information for this source",
115           GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
116
117   /**
118    * RTPSource::stats
119    *
120    * The statistics of the source. This property returns a GstStructure with
121    * name application/x-rtp-source-stats with the following fields:
122    * 
123    */
124   g_object_class_install_property (gobject_class, PROP_STATS,
125       g_param_spec_boxed ("stats", "Stats",
126           "The stats of this source", GST_TYPE_STRUCTURE,
127           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
128
129   GST_DEBUG_CATEGORY_INIT (rtp_source_debug, "rtpsource", 0, "RTP Source");
130 }
131
132 /**
133  * rtp_source_reset:
134  * @src: an #RTPSource
135  *
136  * Reset the stats of @src.
137  */
138 void
139 rtp_source_reset (RTPSource * src)
140 {
141   src->received_bye = FALSE;
142
143   src->stats.cycles = -1;
144   src->stats.jitter = 0;
145   src->stats.transit = -1;
146   src->stats.curr_sr = 0;
147   src->stats.curr_rr = 0;
148 }
149
150 static void
151 rtp_source_init (RTPSource * src)
152 {
153   /* sources are initialy on probation until we receive enough valid RTP
154    * packets or a valid RTCP packet */
155   src->validated = FALSE;
156   src->internal = FALSE;
157   src->probation = RTP_DEFAULT_PROBATION;
158
159   src->payload = -1;
160   src->clock_rate = -1;
161   src->packets = g_queue_new ();
162   src->seqnum_base = -1;
163   src->last_rtptime = -1;
164
165   rtp_source_reset (src);
166 }
167
168 static void
169 rtp_source_finalize (GObject * object)
170 {
171   RTPSource *src;
172   GstBuffer *buffer;
173   gint i;
174
175   src = RTP_SOURCE_CAST (object);
176
177   while ((buffer = g_queue_pop_head (src->packets)))
178     gst_buffer_unref (buffer);
179   g_queue_free (src->packets);
180
181   for (i = 0; i < 9; i++)
182     g_free (src->sdes[i]);
183
184   g_free (src->bye_reason);
185
186   gst_caps_replace (&src->caps, NULL);
187
188   G_OBJECT_CLASS (rtp_source_parent_class)->finalize (object);
189 }
190
191 #define MAX_ADDRESS  64
192 static void
193 make_address_string (GstNetAddress * addr, gchar * dest, gulong n)
194 {
195   switch (gst_netaddress_get_net_type (addr)) {
196     case GST_NET_TYPE_IP4:
197     {
198       guint32 address;
199       guint16 port;
200
201       gst_netaddress_get_ip4_address (addr, &address, &port);
202       address = g_ntohl (address);
203
204       g_snprintf (dest, n, "%d.%d.%d.%d:%d", (address >> 24) & 0xff,
205           (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff,
206           g_ntohs (port));
207       break;
208     }
209     case GST_NET_TYPE_IP6:
210     {
211       guint8 address[16];
212       guint16 port;
213
214       gst_netaddress_get_ip6_address (addr, address, &port);
215
216       g_snprintf (dest, n, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%d",
217           (address[0] << 8) | address[1], (address[2] << 8) | address[3],
218           (address[4] << 8) | address[5], (address[6] << 8) | address[7],
219           (address[8] << 8) | address[9], (address[10] << 8) | address[11],
220           (address[12] << 8) | address[13], (address[14] << 8) | address[15],
221           g_ntohs (port));
222       break;
223     }
224     default:
225       dest[0] = 0;
226       break;
227   }
228 }
229
230 static GstStructure *
231 rtp_source_create_stats (RTPSource * src)
232 {
233   GstStructure *s;
234   gboolean is_sender = src->is_sender;
235   gboolean internal = src->internal;
236   gchar address_str[MAX_ADDRESS];
237
238   /* common data for all types of sources */
239   s = gst_structure_new ("application/x-rtp-source-stats",
240       "ssrc", G_TYPE_UINT, (guint) src->ssrc,
241       "internal", G_TYPE_BOOLEAN, internal,
242       "validated", G_TYPE_BOOLEAN, src->validated,
243       "received-bye", G_TYPE_BOOLEAN, src->received_bye,
244       "is-csrc", G_TYPE_BOOLEAN, src->is_csrc,
245       "is-sender", G_TYPE_BOOLEAN, is_sender, NULL);
246
247   /* add address and port */
248   if (src->have_rtp_from) {
249     make_address_string (&src->rtp_from, address_str, sizeof (address_str));
250     gst_structure_set (s, "rtp-from", G_TYPE_STRING, address_str, NULL);
251   }
252   if (src->have_rtcp_from) {
253     make_address_string (&src->rtcp_from, address_str, sizeof (address_str));
254     gst_structure_set (s, "rtcp-from", G_TYPE_STRING, address_str, NULL);
255   }
256
257   if (internal) {
258     /* our internal source */
259     if (is_sender) {
260       /* if we are sending, report about how much we sent, other sources will
261        * have a RB with info on reception. */
262       gst_structure_set (s,
263           "octets-sent", G_TYPE_UINT64, src->stats.octets_sent,
264           "packets-sent", G_TYPE_UINT64, src->stats.packets_sent,
265           "bitrate", G_TYPE_UINT64, src->bitrate, NULL);
266     } else {
267       /* if we are not sending we have nothing more to report */
268     }
269   } else {
270     gboolean have_rb;
271     guint8 fractionlost = 0;
272     gint32 packetslost = 0;
273     guint32 exthighestseq = 0;
274     guint32 jitter = 0;
275     guint32 lsr = 0;
276     guint32 dlsr = 0;
277     guint32 round_trip = 0;
278
279     /* other sources */
280     if (is_sender) {
281       gboolean have_sr;
282       GstClockTime time = 0;
283       guint64 ntptime = 0;
284       guint32 rtptime = 0;
285       guint32 packet_count = 0;
286       guint32 octet_count = 0;
287
288       /* this source is sending to us, get the last SR. */
289       have_sr = rtp_source_get_last_sr (src, &time, &ntptime, &rtptime,
290           &packet_count, &octet_count);
291       gst_structure_set (s,
292           "octets-received", G_TYPE_UINT64, src->stats.octets_received,
293           "packets-received", G_TYPE_UINT64, src->stats.packets_received,
294           "have-sr", G_TYPE_BOOLEAN, have_sr,
295           "sr-ntptime", G_TYPE_UINT64, ntptime,
296           "sr-rtptime", G_TYPE_UINT, (guint) rtptime,
297           "sr-octet-count", G_TYPE_UINT, (guint) octet_count,
298           "sr-packet-count", G_TYPE_UINT, (guint) packet_count, NULL);
299     }
300     /* we might be sending to this SSRC so we report about how it is
301      * receiving our data */
302     have_rb = rtp_source_get_last_rb (src, &fractionlost, &packetslost,
303         &exthighestseq, &jitter, &lsr, &dlsr, &round_trip);
304
305     gst_structure_set (s,
306         "have-rb", G_TYPE_BOOLEAN, have_rb,
307         "rb-fractionlost", G_TYPE_UINT, (guint) fractionlost,
308         "rb-packetslost", G_TYPE_INT, (gint) packetslost,
309         "rb-exthighestseq", G_TYPE_UINT, (guint) exthighestseq,
310         "rb-jitter", G_TYPE_UINT, (guint) jitter,
311         "rb-lsr", G_TYPE_UINT, (guint) lsr,
312         "rb-dlsr", G_TYPE_UINT, (guint) dlsr,
313         "rb-round-trip", G_TYPE_UINT, (guint) round_trip, NULL);
314   }
315
316   return s;
317 }
318
319 /**
320  * rtp_source_get_sdes_struct:
321  * @src: an #RTSPSource
322  *
323  * Get the SDES data as a GstStructure
324  *
325  * Returns: a GstStructure with SDES items for @src.
326  */
327 GstStructure *
328 rtp_source_get_sdes_struct (RTPSource * src)
329 {
330   GstStructure *s;
331   gchar *str;
332
333   s = gst_structure_new ("application/x-rtp-source-sdes",
334       "ssrc", G_TYPE_UINT, (guint) src->ssrc, NULL);
335
336   if ((str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_CNAME))) {
337     gst_structure_set (s, "cname", G_TYPE_STRING, str, NULL);
338     g_free (str);
339   }
340   if ((str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_NAME))) {
341     gst_structure_set (s, "name", G_TYPE_STRING, str, NULL);
342     g_free (str);
343   }
344   if ((str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_EMAIL))) {
345     gst_structure_set (s, "email", G_TYPE_STRING, str, NULL);
346     g_free (str);
347   }
348   if ((str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_PHONE))) {
349     gst_structure_set (s, "phone", G_TYPE_STRING, str, NULL);
350     g_free (str);
351   }
352   if ((str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_LOC))) {
353     gst_structure_set (s, "location", G_TYPE_STRING, str, NULL);
354     g_free (str);
355   }
356   if ((str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_TOOL))) {
357     gst_structure_set (s, "tool", G_TYPE_STRING, str, NULL);
358     g_free (str);
359   }
360   if ((str = rtp_source_get_sdes_string (src, GST_RTCP_SDES_NOTE))) {
361     gst_structure_set (s, "note", G_TYPE_STRING, str, NULL);
362     g_free (str);
363   }
364   return s;
365 }
366
367 /**
368  * rtp_source_set_sdes_struct:
369  * @src: an #RTSPSource
370  * @sdes: a #GstStructure with SDES info
371  *
372  * Set the SDES items from @sdes.
373  */
374 void
375 rtp_source_set_sdes_struct (RTPSource * src, const GstStructure * sdes)
376 {
377   const gchar *str;
378
379   if (!gst_structure_has_name (sdes, "application/x-rtp-source-sdes"))
380     return;
381
382   if ((str = gst_structure_get_string (sdes, "cname"))) {
383     rtp_source_set_sdes_string (src, GST_RTCP_SDES_CNAME, str);
384   }
385   if ((str = gst_structure_get_string (sdes, "name"))) {
386     rtp_source_set_sdes_string (src, GST_RTCP_SDES_NAME, str);
387   }
388   if ((str = gst_structure_get_string (sdes, "email"))) {
389     rtp_source_set_sdes_string (src, GST_RTCP_SDES_EMAIL, str);
390   }
391   if ((str = gst_structure_get_string (sdes, "phone"))) {
392     rtp_source_set_sdes_string (src, GST_RTCP_SDES_PHONE, str);
393   }
394   if ((str = gst_structure_get_string (sdes, "location"))) {
395     rtp_source_set_sdes_string (src, GST_RTCP_SDES_LOC, str);
396   }
397   if ((str = gst_structure_get_string (sdes, "tool"))) {
398     rtp_source_set_sdes_string (src, GST_RTCP_SDES_TOOL, str);
399   }
400   if ((str = gst_structure_get_string (sdes, "note"))) {
401     rtp_source_set_sdes_string (src, GST_RTCP_SDES_NOTE, str);
402   }
403 }
404
405 static void
406 rtp_source_set_property (GObject * object, guint prop_id,
407     const GValue * value, GParamSpec * pspec)
408 {
409   RTPSource *src;
410
411   src = RTP_SOURCE (object);
412
413   switch (prop_id) {
414     case PROP_SSRC:
415       src->ssrc = g_value_get_uint (value);
416       break;
417     default:
418       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
419       break;
420   }
421 }
422
423 static void
424 rtp_source_get_property (GObject * object, guint prop_id,
425     GValue * value, GParamSpec * pspec)
426 {
427   RTPSource *src;
428
429   src = RTP_SOURCE (object);
430
431   switch (prop_id) {
432     case PROP_SSRC:
433       g_value_set_uint (value, rtp_source_get_ssrc (src));
434       break;
435     case PROP_IS_CSRC:
436       g_value_set_boolean (value, rtp_source_is_as_csrc (src));
437       break;
438     case PROP_IS_VALIDATED:
439       g_value_set_boolean (value, rtp_source_is_validated (src));
440       break;
441     case PROP_IS_SENDER:
442       g_value_set_boolean (value, rtp_source_is_sender (src));
443       break;
444     case PROP_SDES:
445       g_value_take_boxed (value, rtp_source_get_sdes_struct (src));
446       break;
447     case PROP_STATS:
448       g_value_take_boxed (value, rtp_source_create_stats (src));
449       break;
450     default:
451       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
452       break;
453   }
454 }
455
456 /**
457  * rtp_source_new:
458  * @ssrc: an SSRC
459  *
460  * Create a #RTPSource with @ssrc.
461  *
462  * Returns: a new #RTPSource. Use g_object_unref() after usage.
463  */
464 RTPSource *
465 rtp_source_new (guint32 ssrc)
466 {
467   RTPSource *src;
468
469   src = g_object_new (RTP_TYPE_SOURCE, NULL);
470   src->ssrc = ssrc;
471
472   return src;
473 }
474
475 /**
476  * rtp_source_set_callbacks:
477  * @src: an #RTPSource
478  * @cb: callback functions
479  * @user_data: user data
480  *
481  * Set the callbacks for the source.
482  */
483 void
484 rtp_source_set_callbacks (RTPSource * src, RTPSourceCallbacks * cb,
485     gpointer user_data)
486 {
487   g_return_if_fail (RTP_IS_SOURCE (src));
488
489   src->callbacks.push_rtp = cb->push_rtp;
490   src->callbacks.clock_rate = cb->clock_rate;
491   src->user_data = user_data;
492 }
493
494 /**
495  * rtp_source_get_ssrc:
496  * @src: an #RTPSource
497  *
498  * Get the SSRC of @source.
499  *
500  * Returns: the SSRC of src.
501  */
502 guint32
503 rtp_source_get_ssrc (RTPSource * src)
504 {
505   guint32 result;
506
507   g_return_val_if_fail (RTP_IS_SOURCE (src), 0);
508
509   result = src->ssrc;
510
511   return result;
512 }
513
514 /**
515  * rtp_source_set_as_csrc:
516  * @src: an #RTPSource
517  *
518  * Configure @src as a CSRC, this will also validate @src.
519  */
520 void
521 rtp_source_set_as_csrc (RTPSource * src)
522 {
523   g_return_if_fail (RTP_IS_SOURCE (src));
524
525   src->validated = TRUE;
526   src->is_csrc = TRUE;
527 }
528
529 /**
530  * rtp_source_is_as_csrc:
531  * @src: an #RTPSource
532  *
533  * Check if @src is a contributing source.
534  *
535  * Returns: %TRUE if @src is acting as a contributing source.
536  */
537 gboolean
538 rtp_source_is_as_csrc (RTPSource * src)
539 {
540   gboolean result;
541
542   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
543
544   result = src->is_csrc;
545
546   return result;
547 }
548
549 /**
550  * rtp_source_is_active:
551  * @src: an #RTPSource
552  *
553  * Check if @src is an active source. A source is active if it has been
554  * validated and has not yet received a BYE packet
555  *
556  * Returns: %TRUE if @src is an qactive source.
557  */
558 gboolean
559 rtp_source_is_active (RTPSource * src)
560 {
561   gboolean result;
562
563   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
564
565   result = RTP_SOURCE_IS_ACTIVE (src);
566
567   return result;
568 }
569
570 /**
571  * rtp_source_is_validated:
572  * @src: an #RTPSource
573  *
574  * Check if @src is a validated source.
575  *
576  * Returns: %TRUE if @src is a validated source.
577  */
578 gboolean
579 rtp_source_is_validated (RTPSource * src)
580 {
581   gboolean result;
582
583   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
584
585   result = src->validated;
586
587   return result;
588 }
589
590 /**
591  * rtp_source_is_sender:
592  * @src: an #RTPSource
593  *
594  * Check if @src is a sending source.
595  *
596  * Returns: %TRUE if @src is a sending source.
597  */
598 gboolean
599 rtp_source_is_sender (RTPSource * src)
600 {
601   gboolean result;
602
603   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
604
605   result = RTP_SOURCE_IS_SENDER (src);
606
607   return result;
608 }
609
610 /**
611  * rtp_source_received_bye:
612  * @src: an #RTPSource
613  *
614  * Check if @src has receoved a BYE packet.
615  *
616  * Returns: %TRUE if @src has received a BYE packet.
617  */
618 gboolean
619 rtp_source_received_bye (RTPSource * src)
620 {
621   gboolean result;
622
623   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
624
625   result = src->received_bye;
626
627   return result;
628 }
629
630
631 /**
632  * rtp_source_get_bye_reason:
633  * @src: an #RTPSource
634  *
635  * Get the BYE reason for @src. Check if the source receoved a BYE message first
636  * with rtp_source_received_bye().
637  *
638  * Returns: The BYE reason or NULL when no reason was given or the source did
639  * not receive a BYE message yet. g_fee() after usage.
640  */
641 gchar *
642 rtp_source_get_bye_reason (RTPSource * src)
643 {
644   gchar *result;
645
646   g_return_val_if_fail (RTP_IS_SOURCE (src), NULL);
647
648   result = g_strdup (src->bye_reason);
649
650   return result;
651 }
652
653 /**
654  * rtp_source_update_caps:
655  * @src: an #RTPSource
656  * @caps: a #GstCaps
657  *
658  * Parse @caps and store all relevant information in @source.
659  */
660 void
661 rtp_source_update_caps (RTPSource * src, GstCaps * caps)
662 {
663   GstStructure *s;
664   guint val;
665   gint ival;
666
667   /* nothing changed, return */
668   if (src->caps == caps)
669     return;
670
671   s = gst_caps_get_structure (caps, 0);
672
673   if (gst_structure_get_int (s, "payload", &ival))
674     src->payload = ival;
675   else
676     src->payload = -1;
677   GST_DEBUG ("got payload %d", src->payload);
678
679   if (gst_structure_get_int (s, "clock-rate", &ival))
680     src->clock_rate = ival;
681   else
682     src->clock_rate = -1;
683
684   GST_DEBUG ("got clock-rate %d", src->clock_rate);
685
686   if (gst_structure_get_uint (s, "seqnum-base", &val))
687     src->seqnum_base = val;
688   else
689     src->seqnum_base = -1;
690
691   GST_DEBUG ("got seqnum-base %" G_GINT32_FORMAT, src->seqnum_base);
692
693   gst_caps_replace (&src->caps, caps);
694 }
695
696 /**
697  * rtp_source_set_sdes:
698  * @src: an #RTPSource
699  * @type: the type of the SDES item
700  * @data: the SDES data
701  * @len: the SDES length
702  *
703  * Store an SDES item of @type in @src. 
704  *
705  * Returns: %FALSE if the SDES item was unchanged or @type is unknown.
706  */
707 gboolean
708 rtp_source_set_sdes (RTPSource * src, GstRTCPSDESType type,
709     const guint8 * data, guint len)
710 {
711   guint8 *old;
712
713   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
714
715   if (type < 0 || type > GST_RTCP_SDES_PRIV)
716     return FALSE;
717
718   old = src->sdes[type];
719
720   /* lengths are the same, check if the data is the same */
721   if ((src->sdes_len[type] == len))
722     if (data != NULL && old != NULL && (memcmp (old, data, len) == 0))
723       return FALSE;
724
725   /* NULL data, make sure we store 0 length or if no length is given,
726    * take strlen */
727   if (data == NULL)
728     len = 0;
729
730   g_free (src->sdes[type]);
731   src->sdes[type] = g_memdup (data, len);
732   src->sdes_len[type] = len;
733
734   return TRUE;
735 }
736
737 /**
738  * rtp_source_set_sdes_string:
739  * @src: an #RTPSource
740  * @type: the type of the SDES item
741  * @data: the SDES data
742  *
743  * Store an SDES item of @type in @src. This function is similar to
744  * rtp_source_set_sdes() but takes a null-terminated string for convenience.
745  *
746  * Returns: %FALSE if the SDES item was unchanged or @type is unknown.
747  */
748 gboolean
749 rtp_source_set_sdes_string (RTPSource * src, GstRTCPSDESType type,
750     const gchar * data)
751 {
752   guint len;
753   gboolean result;
754
755   if (data)
756     len = strlen (data);
757   else
758     len = 0;
759
760   result = rtp_source_set_sdes (src, type, (guint8 *) data, len);
761
762   return result;
763 }
764
765 /**
766  * rtp_source_get_sdes:
767  * @src: an #RTPSource
768  * @type: the type of the SDES item
769  * @data: location to store the SDES data or NULL
770  * @len: location to store the SDES length or NULL
771  *
772  * Get the SDES item of @type from @src. Note that @data does not always point
773  * to a null-terminated string, use rtp_source_get_sdes_string() to retrieve a
774  * null-terminated string instead.
775  *
776  * @data remains valid until the next call to rtp_source_set_sdes().
777  *
778  * Returns: %TRUE if @type was valid and @data and @len contain valid
779  * data. @data can be NULL when the item was unset.
780  */
781 gboolean
782 rtp_source_get_sdes (RTPSource * src, GstRTCPSDESType type, guint8 ** data,
783     guint * len)
784 {
785   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
786
787   if (type < 0 || type > GST_RTCP_SDES_PRIV)
788     return FALSE;
789
790   if (data)
791     *data = src->sdes[type];
792   if (len)
793     *len = src->sdes_len[type];
794
795   return TRUE;
796 }
797
798 /**
799  * rtp_source_get_sdes_string:
800  * @src: an #RTPSource
801  * @type: the type of the SDES item
802  *
803  * Get the SDES item of @type from @src. 
804  *
805  * Returns: a null-terminated copy of the SDES item or NULL when @type was not
806  * valid or the SDES item was unset. g_free() after usage.
807  */
808 gchar *
809 rtp_source_get_sdes_string (RTPSource * src, GstRTCPSDESType type)
810 {
811   gchar *result;
812
813   g_return_val_if_fail (RTP_IS_SOURCE (src), NULL);
814
815   if (type < 0 || type > GST_RTCP_SDES_PRIV)
816     return NULL;
817
818   result = g_strndup ((const gchar *) src->sdes[type], src->sdes_len[type]);
819
820   return result;
821 }
822
823 /**
824  * rtp_source_set_rtp_from:
825  * @src: an #RTPSource
826  * @address: the RTP address to set
827  *
828  * Set that @src is receiving RTP packets from @address. This is used for
829  * collistion checking.
830  */
831 void
832 rtp_source_set_rtp_from (RTPSource * src, GstNetAddress * address)
833 {
834   g_return_if_fail (RTP_IS_SOURCE (src));
835
836   src->have_rtp_from = TRUE;
837   memcpy (&src->rtp_from, address, sizeof (GstNetAddress));
838 }
839
840 /**
841  * rtp_source_set_rtcp_from:
842  * @src: an #RTPSource
843  * @address: the RTCP address to set
844  *
845  * Set that @src is receiving RTCP packets from @address. This is used for
846  * collistion checking.
847  */
848 void
849 rtp_source_set_rtcp_from (RTPSource * src, GstNetAddress * address)
850 {
851   g_return_if_fail (RTP_IS_SOURCE (src));
852
853   src->have_rtcp_from = TRUE;
854   memcpy (&src->rtcp_from, address, sizeof (GstNetAddress));
855 }
856
857 static GstFlowReturn
858 push_packet (RTPSource * src, GstBuffer * buffer)
859 {
860   GstFlowReturn ret = GST_FLOW_OK;
861
862   /* push queued packets first if any */
863   while (!g_queue_is_empty (src->packets)) {
864     GstBuffer *buffer = GST_BUFFER_CAST (g_queue_pop_head (src->packets));
865
866     GST_LOG ("pushing queued packet");
867     if (src->callbacks.push_rtp)
868       src->callbacks.push_rtp (src, buffer, src->user_data);
869     else
870       gst_buffer_unref (buffer);
871   }
872   GST_LOG ("pushing new packet");
873   /* push packet */
874   if (src->callbacks.push_rtp)
875     ret = src->callbacks.push_rtp (src, buffer, src->user_data);
876   else
877     gst_buffer_unref (buffer);
878
879   return ret;
880 }
881
882 static gint
883 get_clock_rate (RTPSource * src, guint8 payload)
884 {
885   if (src->payload == -1) {
886     /* first payload received, nothing was in the caps, lock on to this payload */
887     src->payload = payload;
888     GST_DEBUG ("first payload %d", payload);
889   } else if (payload != src->payload) {
890     /* we have a different payload than before, reset the clock-rate */
891     GST_DEBUG ("new payload %d", payload);
892     src->payload = payload;
893     src->clock_rate = -1;
894     src->stats.transit = -1;
895   }
896
897   if (src->clock_rate == -1) {
898     gint clock_rate = -1;
899
900     if (src->callbacks.clock_rate)
901       clock_rate = src->callbacks.clock_rate (src, payload, src->user_data);
902
903     GST_DEBUG ("got clock-rate %d", clock_rate);
904
905     src->clock_rate = clock_rate;
906   }
907   return src->clock_rate;
908 }
909
910 /* Jitter is the variation in the delay of received packets in a flow. It is
911  * measured by comparing the interval when RTP packets were sent to the interval
912  * at which they were received. For instance, if packet #1 and packet #2 leave
913  * 50 milliseconds apart and arrive 60 milliseconds apart, then the jitter is 10
914  * milliseconds. */
915 static void
916 calculate_jitter (RTPSource * src, GstBuffer * buffer,
917     RTPArrivalStats * arrival)
918 {
919   guint64 ntpnstime;
920   guint32 rtparrival, transit, rtptime;
921   gint32 diff;
922   gint clock_rate;
923   guint8 pt;
924
925   /* get arrival time */
926   if ((ntpnstime = arrival->ntpnstime) == GST_CLOCK_TIME_NONE)
927     goto no_time;
928
929   pt = gst_rtp_buffer_get_payload_type (buffer);
930
931   GST_LOG ("SSRC %08x got payload %d", src->ssrc, pt);
932
933   /* get clockrate */
934   if ((clock_rate = get_clock_rate (src, pt)) == -1)
935     goto no_clock_rate;
936
937   rtptime = gst_rtp_buffer_get_timestamp (buffer);
938
939   /* convert arrival time to RTP timestamp units, truncate to 32 bits, we don't
940    * care about the absolute value, just the difference. */
941   rtparrival = gst_util_uint64_scale_int (ntpnstime, clock_rate, GST_SECOND);
942
943   /* transit time is difference with RTP timestamp */
944   transit = rtparrival - rtptime;
945
946   /* get ABS diff with previous transit time */
947   if (src->stats.transit != -1) {
948     if (transit > src->stats.transit)
949       diff = transit - src->stats.transit;
950     else
951       diff = src->stats.transit - transit;
952   } else
953     diff = 0;
954
955   src->stats.transit = transit;
956
957   /* update jitter, the value we store is scaled up so we can keep precision. */
958   src->stats.jitter += diff - ((src->stats.jitter + 8) >> 4);
959
960   src->stats.prev_rtptime = src->stats.last_rtptime;
961   src->stats.last_rtptime = rtparrival;
962
963   GST_LOG ("rtparrival %u, rtptime %u, clock-rate %d, diff %d, jitter: %f",
964       rtparrival, rtptime, clock_rate, diff, (src->stats.jitter) / 16.0);
965
966   return;
967
968   /* ERRORS */
969 no_time:
970   {
971     GST_WARNING ("cannot get current time");
972     return;
973   }
974 no_clock_rate:
975   {
976     GST_WARNING ("cannot get clock-rate for pt %d", pt);
977     return;
978   }
979 }
980
981 static void
982 init_seq (RTPSource * src, guint16 seq)
983 {
984   src->stats.base_seq = seq;
985   src->stats.max_seq = seq;
986   src->stats.bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */
987   src->stats.cycles = 0;
988   src->stats.packets_received = 0;
989   src->stats.octets_received = 0;
990   src->stats.bytes_received = 0;
991   src->stats.prev_received = 0;
992   src->stats.prev_expected = 0;
993
994   GST_DEBUG ("base_seq %d", seq);
995 }
996
997 /**
998  * rtp_source_process_rtp:
999  * @src: an #RTPSource
1000  * @buffer: an RTP buffer
1001  *
1002  * Let @src handle the incomming RTP @buffer.
1003  *
1004  * Returns: a #GstFlowReturn.
1005  */
1006 GstFlowReturn
1007 rtp_source_process_rtp (RTPSource * src, GstBuffer * buffer,
1008     RTPArrivalStats * arrival)
1009 {
1010   GstFlowReturn result = GST_FLOW_OK;
1011   guint16 seqnr, udelta;
1012   RTPSourceStats *stats;
1013
1014   g_return_val_if_fail (RTP_IS_SOURCE (src), GST_FLOW_ERROR);
1015   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
1016
1017   stats = &src->stats;
1018
1019   seqnr = gst_rtp_buffer_get_seq (buffer);
1020
1021   rtp_source_update_caps (src, GST_BUFFER_CAPS (buffer));
1022
1023   if (stats->cycles == -1) {
1024     GST_DEBUG ("received first buffer");
1025     /* first time we heard of this source */
1026     init_seq (src, seqnr);
1027     src->stats.max_seq = seqnr - 1;
1028     src->probation = RTP_DEFAULT_PROBATION;
1029   }
1030
1031   udelta = seqnr - stats->max_seq;
1032
1033   /* if we are still on probation, check seqnum */
1034   if (src->probation) {
1035     guint16 expected;
1036
1037     expected = src->stats.max_seq + 1;
1038
1039     /* when in probation, we require consecutive seqnums */
1040     if (seqnr == expected) {
1041       /* expected packet */
1042       GST_DEBUG ("probation: seqnr %d == expected %d", seqnr, expected);
1043       src->probation--;
1044       src->stats.max_seq = seqnr;
1045       if (src->probation == 0) {
1046         GST_DEBUG ("probation done!");
1047         init_seq (src, seqnr);
1048       } else {
1049         GstBuffer *q;
1050
1051         GST_DEBUG ("probation %d: queue buffer", src->probation);
1052         /* when still in probation, keep packets in a list. */
1053         g_queue_push_tail (src->packets, buffer);
1054         /* remove packets from queue if there are too many */
1055         while (g_queue_get_length (src->packets) > RTP_MAX_PROBATION_LEN) {
1056           q = g_queue_pop_head (src->packets);
1057           gst_buffer_unref (q);
1058         }
1059         goto done;
1060       }
1061     } else {
1062       GST_DEBUG ("probation: seqnr %d != expected %d", seqnr, expected);
1063       src->probation = RTP_DEFAULT_PROBATION;
1064       src->stats.max_seq = seqnr;
1065       goto done;
1066     }
1067   } else if (udelta < RTP_MAX_DROPOUT) {
1068     /* in order, with permissible gap */
1069     if (seqnr < stats->max_seq) {
1070       /* sequence number wrapped - count another 64K cycle. */
1071       stats->cycles += RTP_SEQ_MOD;
1072     }
1073     stats->max_seq = seqnr;
1074   } else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) {
1075     /* the sequence number made a very large jump */
1076     if (seqnr == stats->bad_seq) {
1077       /* two sequential packets -- assume that the other side
1078        * restarted without telling us so just re-sync
1079        * (i.e., pretend this was the first packet).  */
1080       init_seq (src, seqnr);
1081     } else {
1082       /* unacceptable jump */
1083       stats->bad_seq = (seqnr + 1) & (RTP_SEQ_MOD - 1);
1084       goto bad_sequence;
1085     }
1086   } else {
1087     /* duplicate or reordered packet, will be filtered by jitterbuffer. */
1088     GST_WARNING ("duplicate or reordered packet");
1089   }
1090
1091   src->stats.octets_received += arrival->payload_len;
1092   src->stats.bytes_received += arrival->bytes;
1093   src->stats.packets_received++;
1094   /* the source that sent the packet must be a sender */
1095   src->is_sender = TRUE;
1096   src->validated = TRUE;
1097
1098   GST_LOG ("seq %d, PC: %" G_GUINT64_FORMAT ", OC: %" G_GUINT64_FORMAT,
1099       seqnr, src->stats.packets_received, src->stats.octets_received);
1100
1101   /* calculate jitter for the stats */
1102   calculate_jitter (src, buffer, arrival);
1103
1104   /* we're ready to push the RTP packet now */
1105   result = push_packet (src, buffer);
1106
1107 done:
1108   return result;
1109
1110   /* ERRORS */
1111 bad_sequence:
1112   {
1113     GST_WARNING ("unacceptable seqnum received");
1114     return GST_FLOW_OK;
1115   }
1116 }
1117
1118 /**
1119  * rtp_source_process_bye:
1120  * @src: an #RTPSource
1121  * @reason: the reason for leaving
1122  *
1123  * Notify @src that a BYE packet has been received. This will make the source
1124  * inactive.
1125  */
1126 void
1127 rtp_source_process_bye (RTPSource * src, const gchar * reason)
1128 {
1129   g_return_if_fail (RTP_IS_SOURCE (src));
1130
1131   GST_DEBUG ("marking SSRC %08x as BYE, reason: %s", src->ssrc,
1132       GST_STR_NULL (reason));
1133
1134   /* copy the reason and mark as received_bye */
1135   g_free (src->bye_reason);
1136   src->bye_reason = g_strdup (reason);
1137   src->received_bye = TRUE;
1138 }
1139
1140 static GstBufferListItem
1141 set_ssrc (GstBuffer ** buffer, guint group, guint idx, RTPSource * src)
1142 {
1143   *buffer = gst_buffer_make_writable (*buffer);
1144   gst_rtp_buffer_set_ssrc (*buffer, src->ssrc);
1145   return GST_BUFFER_LIST_SKIP_GROUP;
1146 }
1147
1148 /**
1149  * rtp_source_send_rtp:
1150  * @src: an #RTPSource
1151  * @data: an RTP buffer or a list of RTP buffers
1152  * @is_list: if @data is a buffer or list
1153  * @ntpnstime: the NTP time when this buffer was captured in nanoseconds. This
1154  * is the buffer timestamp converted to NTP time.
1155  *
1156  * Send @data (an RTP buffer or list of buffers) originating from @src.
1157  * This will make @src a sender. This function takes ownership of @data and
1158  * modifies the SSRC in the RTP packet to that of @src when needed.
1159  *
1160  * Returns: a #GstFlowReturn.
1161  */
1162 GstFlowReturn
1163 rtp_source_send_rtp (RTPSource * src, gpointer data, gboolean is_list,
1164     guint64 ntpnstime)
1165 {
1166   GstFlowReturn result;
1167   guint len;
1168   guint32 rtptime;
1169   guint64 ext_rtptime;
1170   guint64 ntp_diff, rtp_diff;
1171   guint64 elapsed;
1172   GstBufferList *list = NULL;
1173   GstBuffer *buffer = NULL;
1174   guint packets;
1175   guint32 ssrc;
1176
1177   g_return_val_if_fail (RTP_IS_SOURCE (src), GST_FLOW_ERROR);
1178   g_return_val_if_fail (is_list || GST_IS_BUFFER (data), GST_FLOW_ERROR);
1179
1180   if (is_list) {
1181     list = GST_BUFFER_LIST_CAST (data);
1182
1183     /* We can grab the caps from the first group, since all
1184      * groups of a buffer list have same caps. */
1185     buffer = gst_buffer_list_get (list, 0, 0);
1186     if (!buffer)
1187       goto no_buffer;
1188   } else {
1189     buffer = GST_BUFFER_CAST (data);
1190   }
1191   rtp_source_update_caps (src, GST_BUFFER_CAPS (buffer));
1192
1193   /* we are a sender now */
1194   src->is_sender = TRUE;
1195
1196   if (is_list) {
1197     /* Each group makes up a network packet. */
1198     packets = gst_buffer_list_n_groups (list);
1199     len = gst_rtp_buffer_list_get_payload_len (list);
1200   } else {
1201     packets = 1;
1202     len = gst_rtp_buffer_get_payload_len (buffer);
1203   }
1204
1205   /* update stats for the SR */
1206   src->stats.packets_sent += packets;
1207   src->stats.octets_sent += len;
1208   src->bytes_sent += len;
1209
1210   if (src->prev_ntpnstime) {
1211     elapsed = ntpnstime - src->prev_ntpnstime;
1212
1213     if (elapsed > (G_GINT64_CONSTANT (1) << 31)) {
1214       guint64 rate;
1215
1216       rate =
1217           gst_util_uint64_scale (src->bytes_sent, elapsed,
1218           (G_GINT64_CONSTANT (1) << 29));
1219
1220       GST_LOG ("Elapsed %" G_GUINT64_FORMAT ", bytes %" G_GUINT64_FORMAT
1221           ", rate %" G_GUINT64_FORMAT, elapsed, src->bytes_sent, rate);
1222
1223       if (src->bitrate == 0)
1224         src->bitrate = rate;
1225       else
1226         src->bitrate = ((src->bitrate * 3) + rate) / 4;
1227
1228       src->prev_ntpnstime = ntpnstime;
1229       src->bytes_sent = 0;
1230     }
1231   } else {
1232     GST_LOG ("Reset bitrate measurement");
1233     src->prev_ntpnstime = ntpnstime;
1234     src->bitrate = 0;
1235   }
1236
1237   if (is_list) {
1238     rtptime = gst_rtp_buffer_list_get_timestamp (list);
1239   } else {
1240     rtptime = gst_rtp_buffer_get_timestamp (buffer);
1241   }
1242   ext_rtptime = src->last_rtptime;
1243   ext_rtptime = gst_rtp_buffer_ext_timestamp (&ext_rtptime, rtptime);
1244
1245   GST_LOG ("SSRC %08x, RTP %" G_GUINT64_FORMAT ", NTP %" GST_TIME_FORMAT,
1246       src->ssrc, ext_rtptime, GST_TIME_ARGS (ntpnstime));
1247
1248   if (ext_rtptime > src->last_rtptime) {
1249     rtp_diff = ext_rtptime - src->last_rtptime;
1250     ntp_diff = ntpnstime - src->last_ntpnstime;
1251
1252     /* calc the diff so we can detect drift at the sender. This can also be used
1253      * to guestimate the clock rate if the NTP time is locked to the RTP
1254      * timestamps (as is the case when the capture device is providing the clock). */
1255     GST_LOG ("SSRC %08x, diff RTP %" G_GUINT64_FORMAT ", diff NTP %"
1256         GST_TIME_FORMAT, src->ssrc, rtp_diff, GST_TIME_ARGS (ntp_diff));
1257   }
1258
1259   /* we keep track of the last received RTP timestamp and the corresponding
1260    * NTP timestamp so that we can use this info when constructing SR reports */
1261   src->last_rtptime = ext_rtptime;
1262   src->last_ntpnstime = ntpnstime;
1263
1264   /* push packet */
1265   if (!src->callbacks.push_rtp)
1266     goto no_callback;
1267
1268   if (is_list) {
1269     ssrc = gst_rtp_buffer_list_get_ssrc (list);
1270   } else {
1271     ssrc = gst_rtp_buffer_get_ssrc (buffer);
1272   }
1273
1274   if (ssrc != src->ssrc) {
1275     /* the SSRC of the packet is not correct, make a writable buffer and
1276      * update the SSRC. This could involve a complete copy of the packet when
1277      * it is not writable. Usually the payloader will use caps negotiation to
1278      * get the correct SSRC from the session manager before pushing anything. */
1279
1280     /* FIXME, we don't want to warn yet because we can't inform any payloader
1281      * of the changes SSRC yet because we don't implement pad-alloc. */
1282     GST_LOG ("updating SSRC from %08x to %08x, fix the payloader", ssrc,
1283         src->ssrc);
1284
1285     if (is_list) {
1286       list = gst_buffer_list_make_writable (list);
1287       gst_buffer_list_foreach (list, (GstBufferListFunc) set_ssrc, src);
1288     } else {
1289       set_ssrc (&buffer, 0, 0, src);
1290     }
1291   }
1292   GST_LOG ("pushing RTP %s %" G_GUINT64_FORMAT, is_list ? "list" : "packet",
1293       src->stats.packets_sent);
1294
1295   result = src->callbacks.push_rtp (src, data, src->user_data);
1296
1297   return result;
1298
1299   /* ERRORS */
1300 no_buffer:
1301   {
1302     GST_WARNING ("no buffers in buffer list");
1303     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
1304     return GST_FLOW_OK;
1305   }
1306 no_callback:
1307   {
1308     GST_WARNING ("no callback installed, dropping packet");
1309     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
1310     return GST_FLOW_OK;
1311   }
1312 }
1313
1314 /**
1315  * rtp_source_process_sr:
1316  * @src: an #RTPSource
1317  * @time: time of packet arrival
1318  * @ntptime: the NTP time in 32.32 fixed point
1319  * @rtptime: the RTP time
1320  * @packet_count: the packet count
1321  * @octet_count: the octect count
1322  *
1323  * Update the sender report in @src.
1324  */
1325 void
1326 rtp_source_process_sr (RTPSource * src, GstClockTime time, guint64 ntptime,
1327     guint32 rtptime, guint32 packet_count, guint32 octet_count)
1328 {
1329   RTPSenderReport *curr;
1330   gint curridx;
1331
1332   g_return_if_fail (RTP_IS_SOURCE (src));
1333
1334   GST_DEBUG ("got SR packet: SSRC %08x, NTP %08x:%08x, RTP %" G_GUINT32_FORMAT
1335       ", PC %" G_GUINT32_FORMAT ", OC %" G_GUINT32_FORMAT, src->ssrc,
1336       (guint32) (ntptime >> 32), (guint32) (ntptime & 0xffffffff), rtptime,
1337       packet_count, octet_count);
1338
1339   curridx = src->stats.curr_sr ^ 1;
1340   curr = &src->stats.sr[curridx];
1341
1342   /* this is a sender now */
1343   src->is_sender = TRUE;
1344
1345   /* update current */
1346   curr->is_valid = TRUE;
1347   curr->ntptime = ntptime;
1348   curr->rtptime = rtptime;
1349   curr->packet_count = packet_count;
1350   curr->octet_count = octet_count;
1351   curr->time = time;
1352
1353   /* make current */
1354   src->stats.curr_sr = curridx;
1355 }
1356
1357 /**
1358  * rtp_source_process_rb:
1359  * @src: an #RTPSource
1360  * @time: the current time in nanoseconds since 1970
1361  * @fractionlost: fraction lost since last SR/RR
1362  * @packetslost: the cumululative number of packets lost
1363  * @exthighestseq: the extended last sequence number received
1364  * @jitter: the interarrival jitter
1365  * @lsr: the last SR packet from this source
1366  * @dlsr: the delay since last SR packet
1367  *
1368  * Update the report block in @src.
1369  */
1370 void
1371 rtp_source_process_rb (RTPSource * src, GstClockTime time, guint8 fractionlost,
1372     gint32 packetslost, guint32 exthighestseq, guint32 jitter, guint32 lsr,
1373     guint32 dlsr)
1374 {
1375   RTPReceiverReport *curr;
1376   gint curridx;
1377   guint32 ntp, A;
1378
1379   g_return_if_fail (RTP_IS_SOURCE (src));
1380
1381   GST_DEBUG ("got RB packet: SSRC %08x, FL %2x, PL %d, HS %" G_GUINT32_FORMAT
1382       ", jitter %" G_GUINT32_FORMAT ", LSR %04x:%04x, DLSR %04x:%04x",
1383       src->ssrc, fractionlost, packetslost, exthighestseq, jitter, lsr >> 16,
1384       lsr & 0xffff, dlsr >> 16, dlsr & 0xffff);
1385
1386   curridx = src->stats.curr_rr ^ 1;
1387   curr = &src->stats.rr[curridx];
1388
1389   /* update current */
1390   curr->is_valid = TRUE;
1391   curr->fractionlost = fractionlost;
1392   curr->packetslost = packetslost;
1393   curr->exthighestseq = exthighestseq;
1394   curr->jitter = jitter;
1395   curr->lsr = lsr;
1396   curr->dlsr = dlsr;
1397
1398   /* calculate round trip, round the time up */
1399   ntp = ((gst_rtcp_unix_to_ntp (time) + 0xffff) >> 16) & 0xffffffff;
1400   A = dlsr + lsr;
1401   if (A > 0 && ntp > A)
1402     A = ntp - A;
1403   else
1404     A = 0;
1405   curr->round_trip = A;
1406
1407   GST_DEBUG ("NTP %04x:%04x, round trip %04x:%04x", ntp >> 16, ntp & 0xffff,
1408       A >> 16, A & 0xffff);
1409
1410   /* make current */
1411   src->stats.curr_rr = curridx;
1412 }
1413
1414 /**
1415  * rtp_source_get_new_sr:
1416  * @src: an #RTPSource
1417  * @ntpnstime: the current time in nanoseconds since 1970
1418  * @ntptime: the NTP time in 32.32 fixed point
1419  * @rtptime: the RTP time corresponding to @ntptime
1420  * @packet_count: the packet count
1421  * @octet_count: the octect count
1422  *
1423  * Get new values to put into a new SR report from this source.
1424  *
1425  * Returns: %TRUE on success.
1426  */
1427 gboolean
1428 rtp_source_get_new_sr (RTPSource * src, guint64 ntpnstime,
1429     guint64 * ntptime, guint32 * rtptime, guint32 * packet_count,
1430     guint32 * octet_count)
1431 {
1432   guint64 t_rtp;
1433   guint64 t_current_ntp;
1434   GstClockTimeDiff diff;
1435
1436   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
1437
1438   /* use the sync params to interpolate the date->time member to rtptime. We
1439    * use the last sent timestamp and rtptime as reference points. We assume
1440    * that the slope of the rtptime vs timestamp curve is 1, which is certainly
1441    * sufficient for the frequency at which we report SR and the rate we send
1442    * out RTP packets. */
1443   t_rtp = src->last_rtptime;
1444
1445   GST_DEBUG ("last_ntpnstime %" GST_TIME_FORMAT ", last_rtptime %"
1446       G_GUINT64_FORMAT, GST_TIME_ARGS (src->last_ntpnstime), t_rtp);
1447
1448   if (src->clock_rate != -1) {
1449     /* get the diff with the SR time */
1450     diff = GST_CLOCK_DIFF (src->last_ntpnstime, ntpnstime);
1451
1452     /* now translate the diff to RTP time, handle positive and negative cases.
1453      * If there is no diff, we already set rtptime correctly above. */
1454     if (diff > 0) {
1455       GST_DEBUG ("ntpnstime %" GST_TIME_FORMAT ", diff %" GST_TIME_FORMAT,
1456           GST_TIME_ARGS (ntpnstime), GST_TIME_ARGS (diff));
1457       t_rtp += gst_util_uint64_scale_int (diff, src->clock_rate, GST_SECOND);
1458     } else {
1459       diff = -diff;
1460       GST_DEBUG ("ntpnstime %" GST_TIME_FORMAT ", diff -%" GST_TIME_FORMAT,
1461           GST_TIME_ARGS (ntpnstime), GST_TIME_ARGS (diff));
1462       t_rtp -= gst_util_uint64_scale_int (diff, src->clock_rate, GST_SECOND);
1463     }
1464   } else {
1465     GST_WARNING ("no clock-rate, cannot interpolate rtp time");
1466   }
1467
1468   /* convert the NTP time in nanoseconds to 32.32 fixed point */
1469   t_current_ntp = gst_util_uint64_scale (ntpnstime, (1LL << 32), GST_SECOND);
1470
1471   GST_DEBUG ("NTP %08x:%08x, RTP %" G_GUINT32_FORMAT,
1472       (guint32) (t_current_ntp >> 32), (guint32) (t_current_ntp & 0xffffffff),
1473       (guint32) t_rtp);
1474
1475   if (ntptime)
1476     *ntptime = t_current_ntp;
1477   if (rtptime)
1478     *rtptime = t_rtp;
1479   if (packet_count)
1480     *packet_count = src->stats.packets_sent;
1481   if (octet_count)
1482     *octet_count = src->stats.octets_sent;
1483
1484   return TRUE;
1485 }
1486
1487 /**
1488  * rtp_source_get_new_rb:
1489  * @src: an #RTPSource
1490  * @time: the current time of the system clock
1491  * @fractionlost: fraction lost since last SR/RR
1492  * @packetslost: the cumululative number of packets lost
1493  * @exthighestseq: the extended last sequence number received
1494  * @jitter: the interarrival jitter
1495  * @lsr: the last SR packet from this source
1496  * @dlsr: the delay since last SR packet
1497  *
1498  * Get new values to put into a new report block from this source.
1499  *
1500  * Returns: %TRUE on success.
1501  */
1502 gboolean
1503 rtp_source_get_new_rb (RTPSource * src, GstClockTime time,
1504     guint8 * fractionlost, gint32 * packetslost, guint32 * exthighestseq,
1505     guint32 * jitter, guint32 * lsr, guint32 * dlsr)
1506 {
1507   RTPSourceStats *stats;
1508   guint64 extended_max, expected;
1509   guint64 expected_interval, received_interval, ntptime;
1510   gint64 lost, lost_interval;
1511   guint32 fraction, LSR, DLSR;
1512   GstClockTime sr_time;
1513
1514   stats = &src->stats;
1515
1516   extended_max = stats->cycles + stats->max_seq;
1517   expected = extended_max - stats->base_seq + 1;
1518
1519   GST_DEBUG ("ext_max %" G_GUINT64_FORMAT ", expected %" G_GUINT64_FORMAT
1520       ", received %" G_GUINT64_FORMAT ", base_seq %" G_GUINT32_FORMAT,
1521       extended_max, expected, stats->packets_received, stats->base_seq);
1522
1523   lost = expected - stats->packets_received;
1524   lost = CLAMP (lost, -0x800000, 0x7fffff);
1525
1526   expected_interval = expected - stats->prev_expected;
1527   stats->prev_expected = expected;
1528   received_interval = stats->packets_received - stats->prev_received;
1529   stats->prev_received = stats->packets_received;
1530
1531   lost_interval = expected_interval - received_interval;
1532
1533   if (expected_interval == 0 || lost_interval <= 0)
1534     fraction = 0;
1535   else
1536     fraction = (lost_interval << 8) / expected_interval;
1537
1538   GST_DEBUG ("add RR for SSRC %08x", src->ssrc);
1539   /* we scaled the jitter up for additional precision */
1540   GST_DEBUG ("fraction %" G_GUINT32_FORMAT ", lost %" G_GINT64_FORMAT
1541       ", extseq %" G_GUINT64_FORMAT ", jitter %d", fraction, lost,
1542       extended_max, stats->jitter >> 4);
1543
1544   if (rtp_source_get_last_sr (src, &sr_time, &ntptime, NULL, NULL, NULL)) {
1545     GstClockTime diff;
1546
1547     /* LSR is middle 32 bits of the last ntptime */
1548     LSR = (ntptime >> 16) & 0xffffffff;
1549     diff = time - sr_time;
1550     GST_DEBUG ("last SR time diff %" GST_TIME_FORMAT, GST_TIME_ARGS (diff));
1551     /* DLSR, delay since last SR is expressed in 1/65536 second units */
1552     DLSR = gst_util_uint64_scale_int (diff, 65536, GST_SECOND);
1553   } else {
1554     /* No valid SR received, LSR/DLSR are set to 0 then */
1555     GST_DEBUG ("no valid SR received");
1556     LSR = 0;
1557     DLSR = 0;
1558   }
1559   GST_DEBUG ("LSR %04x:%04x, DLSR %04x:%04x", LSR >> 16, LSR & 0xffff,
1560       DLSR >> 16, DLSR & 0xffff);
1561
1562   if (fractionlost)
1563     *fractionlost = fraction;
1564   if (packetslost)
1565     *packetslost = lost;
1566   if (exthighestseq)
1567     *exthighestseq = extended_max;
1568   if (jitter)
1569     *jitter = stats->jitter >> 4;
1570   if (lsr)
1571     *lsr = LSR;
1572   if (dlsr)
1573     *dlsr = DLSR;
1574
1575   return TRUE;
1576 }
1577
1578 /**
1579  * rtp_source_get_last_sr:
1580  * @src: an #RTPSource
1581  * @time: time of packet arrival
1582  * @ntptime: the NTP time in 32.32 fixed point
1583  * @rtptime: the RTP time
1584  * @packet_count: the packet count
1585  * @octet_count: the octect count
1586  *
1587  * Get the values of the last sender report as set with rtp_source_process_sr().
1588  *
1589  * Returns: %TRUE if there was a valid SR report.
1590  */
1591 gboolean
1592 rtp_source_get_last_sr (RTPSource * src, GstClockTime * time, guint64 * ntptime,
1593     guint32 * rtptime, guint32 * packet_count, guint32 * octet_count)
1594 {
1595   RTPSenderReport *curr;
1596
1597   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
1598
1599   curr = &src->stats.sr[src->stats.curr_sr];
1600   if (!curr->is_valid)
1601     return FALSE;
1602
1603   if (ntptime)
1604     *ntptime = curr->ntptime;
1605   if (rtptime)
1606     *rtptime = curr->rtptime;
1607   if (packet_count)
1608     *packet_count = curr->packet_count;
1609   if (octet_count)
1610     *octet_count = curr->octet_count;
1611   if (time)
1612     *time = curr->time;
1613
1614   return TRUE;
1615 }
1616
1617 /**
1618  * rtp_source_get_last_rb:
1619  * @src: an #RTPSource
1620  * @fractionlost: fraction lost since last SR/RR
1621  * @packetslost: the cumululative number of packets lost
1622  * @exthighestseq: the extended last sequence number received
1623  * @jitter: the interarrival jitter
1624  * @lsr: the last SR packet from this source
1625  * @dlsr: the delay since last SR packet
1626  * @round_trip: the round trip time
1627  *
1628  * Get the values of the last RB report set with rtp_source_process_rb().
1629  *
1630  * Returns: %TRUE if there was a valid SB report.
1631  */
1632 gboolean
1633 rtp_source_get_last_rb (RTPSource * src, guint8 * fractionlost,
1634     gint32 * packetslost, guint32 * exthighestseq, guint32 * jitter,
1635     guint32 * lsr, guint32 * dlsr, guint32 * round_trip)
1636 {
1637   RTPReceiverReport *curr;
1638
1639   g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE);
1640
1641   curr = &src->stats.rr[src->stats.curr_rr];
1642   if (!curr->is_valid)
1643     return FALSE;
1644
1645   if (fractionlost)
1646     *fractionlost = curr->fractionlost;
1647   if (packetslost)
1648     *packetslost = curr->packetslost;
1649   if (exthighestseq)
1650     *exthighestseq = curr->exthighestseq;
1651   if (jitter)
1652     *jitter = curr->jitter;
1653   if (lsr)
1654     *lsr = curr->lsr;
1655   if (dlsr)
1656     *dlsr = curr->dlsr;
1657   if (round_trip)
1658     *round_trip = curr->round_trip;
1659
1660   return TRUE;
1661 }