Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1 | /* GStreamer |
Wim Taymans | 49e501a | 2007-12-10 15:34:19 +0000 | [diff] [blame] | 2 | * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com> |
Miguel París Díaz | f321bfe | 2015-10-07 13:03:02 +0200 | [diff] [blame] | 3 | * Copyright (C) 2015 Kurento (http://kurento.org/) |
| 4 | * @author: Miguel París <mparisdiaz@gmail.com> |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Library General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Library General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Library General Public |
| 17 | * License along with this library; if not, write to the |
Tim-Philipp Müller | 230cf41 | 2012-11-04 00:07:18 +0000 | [diff] [blame] | 18 | * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
| 19 | * Boston, MA 02110-1301, USA. |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 20 | */ |
| 21 | #include <string.h> |
| 22 | |
| 23 | #include <gst/rtp/gstrtpbuffer.h> |
| 24 | #include <gst/rtp/gstrtcpbuffer.h> |
| 25 | |
| 26 | #include "rtpsource.h" |
| 27 | |
| 28 | GST_DEBUG_CATEGORY_STATIC (rtp_source_debug); |
| 29 | #define GST_CAT_DEFAULT rtp_source_debug |
| 30 | |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 31 | #define RTP_MAX_PROBATION_LEN 32 |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 32 | |
| 33 | /* signals and args */ |
| 34 | enum |
| 35 | { |
| 36 | LAST_SIGNAL |
| 37 | }; |
| 38 | |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 39 | #define DEFAULT_SSRC 0 |
| 40 | #define DEFAULT_IS_CSRC FALSE |
| 41 | #define DEFAULT_IS_VALIDATED FALSE |
| 42 | #define DEFAULT_IS_SENDER FALSE |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 43 | #define DEFAULT_SDES NULL |
Aleix Conchillo Flaque | 4a200b6 | 2012-08-22 16:36:21 -0700 | [diff] [blame] | 44 | #define DEFAULT_PROBATION RTP_DEFAULT_PROBATION |
Miguel París Díaz | 4c96094 | 2015-10-07 13:02:12 +0200 | [diff] [blame] | 45 | #define DEFAULT_MAX_DROPOUT_TIME 60000 |
| 46 | #define DEFAULT_MAX_MISORDER_TIME 2000 |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 47 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 48 | enum |
| 49 | { |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 50 | PROP_0, |
| 51 | PROP_SSRC, |
| 52 | PROP_IS_CSRC, |
| 53 | PROP_IS_VALIDATED, |
| 54 | PROP_IS_SENDER, |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 55 | PROP_SDES, |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 56 | PROP_STATS, |
Miguel París Díaz | 4c96094 | 2015-10-07 13:02:12 +0200 | [diff] [blame] | 57 | PROP_PROBATION, |
| 58 | PROP_MAX_DROPOUT_TIME, |
| 59 | PROP_MAX_MISORDER_TIME |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 60 | }; |
| 61 | |
| 62 | /* GObject vmethods */ |
| 63 | static void rtp_source_finalize (GObject * object); |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 64 | static void rtp_source_set_property (GObject * object, guint prop_id, |
| 65 | const GValue * value, GParamSpec * pspec); |
| 66 | static void rtp_source_get_property (GObject * object, guint prop_id, |
| 67 | GValue * value, GParamSpec * pspec); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 68 | |
| 69 | /* static guint rtp_source_signals[LAST_SIGNAL] = { 0 }; */ |
| 70 | |
| 71 | G_DEFINE_TYPE (RTPSource, rtp_source, G_TYPE_OBJECT); |
| 72 | |
| 73 | static void |
| 74 | rtp_source_class_init (RTPSourceClass * klass) |
| 75 | { |
| 76 | GObjectClass *gobject_class; |
| 77 | |
| 78 | gobject_class = (GObjectClass *) klass; |
| 79 | |
| 80 | gobject_class->finalize = rtp_source_finalize; |
| 81 | |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 82 | gobject_class->set_property = rtp_source_set_property; |
| 83 | gobject_class->get_property = rtp_source_get_property; |
| 84 | |
| 85 | g_object_class_install_property (gobject_class, PROP_SSRC, |
| 86 | g_param_spec_uint ("ssrc", "SSRC", |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 87 | "The SSRC of this source", 0, G_MAXUINT, DEFAULT_SSRC, |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 88 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 89 | |
| 90 | g_object_class_install_property (gobject_class, PROP_IS_CSRC, |
| 91 | g_param_spec_boolean ("is-csrc", "Is CSRC", |
| 92 | "If this SSRC is acting as a contributing source", |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 93 | DEFAULT_IS_CSRC, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 94 | |
| 95 | g_object_class_install_property (gobject_class, PROP_IS_VALIDATED, |
| 96 | g_param_spec_boolean ("is-validated", "Is Validated", |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 97 | "If this SSRC is validated", DEFAULT_IS_VALIDATED, |
| 98 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 99 | |
| 100 | g_object_class_install_property (gobject_class, PROP_IS_SENDER, |
| 101 | g_param_spec_boolean ("is-sender", "Is Sender", |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 102 | "If this SSRC is a sender", DEFAULT_IS_SENDER, |
| 103 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 104 | |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 105 | /** |
| 106 | * RTPSource::sdes |
| 107 | * |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 108 | * The current SDES items of the source. Returns a structure with name |
| 109 | * application/x-rtp-source-sdes and may contain the following fields: |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 110 | * |
Nirbheek Chauhan | 78847d0 | 2016-03-15 03:26:14 +0530 | [diff] [blame] | 111 | * 'cname' G_TYPE_STRING : The canonical name in the form user@host |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 112 | * 'name' G_TYPE_STRING : The user name |
| 113 | * 'email' G_TYPE_STRING : The user's electronic mail address |
| 114 | * 'phone' G_TYPE_STRING : The user's phone number |
| 115 | * 'location' G_TYPE_STRING : The geographic user location |
| 116 | * 'tool' G_TYPE_STRING : The name of application or tool |
| 117 | * 'note' G_TYPE_STRING : A notice about the source |
| 118 | * |
Ilya Konstantinov | c7e168e | 2015-06-10 14:49:50 +0300 | [diff] [blame] | 119 | * Other fields may be present and these represent private items in |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 120 | * the SDES where the field name is the prefix. |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 121 | */ |
| 122 | g_object_class_install_property (gobject_class, PROP_SDES, |
| 123 | g_param_spec_boxed ("sdes", "SDES", |
| 124 | "The SDES information for this source", |
| 125 | GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 126 | |
| 127 | /** |
| 128 | * RTPSource::stats |
| 129 | * |
Ilya Konstantinov | c7e168e | 2015-06-10 14:49:50 +0300 | [diff] [blame] | 130 | * This property returns a GstStructure named application/x-rtp-source-stats with |
| 131 | * fields useful for statistics and diagnostics. |
| 132 | * |
| 133 | * Take note of each respective field's units: |
| 134 | * |
| 135 | * - NTP times are in the appropriate 32-bit or 64-bit fixed-point format |
| 136 | * starting from January 1, 1970 (except for timespans). |
| 137 | * - RTP times are in clock rate units (i.e. clock rate = 1 second) |
| 138 | * starting at a random offset. |
| 139 | * - For fields indicating packet loss, note that late packets are not considered lost, |
| 140 | * and duplicates are not taken into account. Hence, the loss may be negative |
| 141 | * if there are duplicates. |
| 142 | * |
| 143 | * The following fields are always present. |
Wim Taymans | 3fcde44 | 2009-09-03 19:12:39 +0200 | [diff] [blame] | 144 | * |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 145 | * "ssrc" G_TYPE_UINT the SSRC of this source |
| 146 | * "internal" G_TYPE_BOOLEAN this source is a source of the session |
| 147 | * "validated" G_TYPE_BOOLEAN the source is validated |
| 148 | * "received-bye" G_TYPE_BOOLEAN we received a BYE from this source |
| 149 | * "is-csrc" G_TYPE_BOOLEAN this source was found as CSRC |
| 150 | * "is-sender" G_TYPE_BOOLEAN this source is a sender |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 151 | * "seqnum-base" G_TYPE_INT first seqnum if known |
| 152 | * "clock-rate" G_TYPE_INT the clock rate of the media |
| 153 | * |
Ilya Konstantinov | c7e168e | 2015-06-10 14:49:50 +0300 | [diff] [blame] | 154 | * The following fields are only present when known. |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 155 | * |
| 156 | * "rtp-from" G_TYPE_STRING where we received the last RTP packet from |
| 157 | * "rtcp-from" G_TYPE_STRING where we received the last RTCP packet from |
| 158 | * |
| 159 | * The following fields make sense for internal sources and will only increase |
Ilya Konstantinov | c7e168e | 2015-06-10 14:49:50 +0300 | [diff] [blame] | 160 | * when "is-sender" is TRUE. |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 161 | * |
| 162 | * "octets-sent" G_TYPE_UINT64 number of bytes we sent |
| 163 | * "packets-sent" G_TYPE_UINT64 number of packets we sent |
| 164 | * |
| 165 | * The following fields make sense for non-internal sources and will only |
| 166 | * increase when "is-sender" is TRUE. |
| 167 | * |
| 168 | * "octets-received" G_TYPE_UINT64 total number of bytes received |
| 169 | * "packets-received" G_TYPE_UINT64 total number of packets received |
| 170 | * |
| 171 | * Following fields are updated when "is-sender" is TRUE. |
| 172 | * |
| 173 | * "bitrate" G_TYPE_UINT64 bitrate in bits per second |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 174 | * "jitter" G_TYPE_UINT estimated jitter (in clock rate units) |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 175 | * "packets-lost" G_TYPE_INT estimated amount of packets lost |
| 176 | * |
| 177 | * The last SR report this source sent. This only updates when "is-sender" is |
| 178 | * TRUE. |
| 179 | * |
| 180 | * "have-sr" G_TYPE_BOOLEAN the source has sent SR |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 181 | * "sr-ntptime" G_TYPE_UINT64 NTP time of SR (in NTP Timestamp Format, 32.32 fixed point) |
| 182 | * "sr-rtptime" G_TYPE_UINT RTP time of SR (in clock rate units) |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 183 | * "sr-octet-count" G_TYPE_UINT the number of bytes in the SR |
| 184 | * "sr-packet-count" G_TYPE_UINT the number of packets in the SR |
| 185 | * |
Wim Taymans | 7caad21 | 2010-12-23 13:55:31 +0100 | [diff] [blame] | 186 | * The following fields are only present for non-internal sources and |
| 187 | * represent the content of the last RB packet that was sent to this source. |
| 188 | * These values are only updated when the source is sending. |
| 189 | * |
| 190 | * "sent-rb" G_TYPE_BOOLEAN we have sent an RB |
Nirbheek Chauhan | 78847d0 | 2016-03-15 03:26:14 +0530 | [diff] [blame] | 191 | * "sent-rb-fractionlost" G_TYPE_UINT calculated lost 8-bit fraction |
Wim Taymans | 7caad21 | 2010-12-23 13:55:31 +0100 | [diff] [blame] | 192 | * "sent-rb-packetslost" G_TYPE_INT lost packets |
| 193 | * "sent-rb-exthighestseq" G_TYPE_UINT last seen seqnum |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 194 | * "sent-rb-jitter" G_TYPE_UINT jitter (in clock rate units) |
Nirbheek Chauhan | 78847d0 | 2016-03-15 03:26:14 +0530 | [diff] [blame] | 195 | * "sent-rb-lsr" G_TYPE_UINT last SR time (seconds in NTP Short Format, 16.16 fixed point) |
| 196 | * "sent-rb-dlsr" G_TYPE_UINT delay since last SR (seconds in NTP Short Format, 16.16 fixed point) |
Wim Taymans | 7caad21 | 2010-12-23 13:55:31 +0100 | [diff] [blame] | 197 | * |
| 198 | * The following fields are only present for non-internal sources and |
| 199 | * represents the last RB that this source sent. This is only updated |
| 200 | * when the source is receiving data and sending RB blocks. |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 201 | * |
| 202 | * "have-rb" G_TYPE_BOOLEAN the source has sent RB |
Nirbheek Chauhan | 78847d0 | 2016-03-15 03:26:14 +0530 | [diff] [blame] | 203 | * "rb-fractionlost" G_TYPE_UINT lost 8-bit fraction |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 204 | * "rb-packetslost" G_TYPE_INT lost packets |
| 205 | * "rb-exthighestseq" G_TYPE_UINT highest received seqnum |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 206 | * "rb-jitter" G_TYPE_UINT reception jitter (in clock rate units) |
Nirbheek Chauhan | 78847d0 | 2016-03-15 03:26:14 +0530 | [diff] [blame] | 207 | * "rb-lsr" G_TYPE_UINT last SR time (seconds in NTP Short Format, 16.16 fixed point) |
| 208 | * "rb-dlsr" G_TYPE_UINT delay since last SR (seconds in NTP Short Format, 16.16 fixed point) |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 209 | * |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 210 | * The round trip of this source is calculated from the last RB |
| 211 | * values and the reception time of the last RB packet. It is only present for |
Wim Taymans | 7caad21 | 2010-12-23 13:55:31 +0100 | [diff] [blame] | 212 | * non-internal sources. |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 213 | * |
Nirbheek Chauhan | 78847d0 | 2016-03-15 03:26:14 +0530 | [diff] [blame] | 214 | * "rb-round-trip" G_TYPE_UINT the round-trip time (seconds in NTP Short Format, 16.16 fixed point) |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 215 | * |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 216 | */ |
| 217 | g_object_class_install_property (gobject_class, PROP_STATS, |
| 218 | g_param_spec_boxed ("stats", "Stats", |
| 219 | "The stats of this source", GST_TYPE_STRUCTURE, |
| 220 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 221 | |
Aleix Conchillo Flaque | 4a200b6 | 2012-08-22 16:36:21 -0700 | [diff] [blame] | 222 | g_object_class_install_property (gobject_class, PROP_PROBATION, |
| 223 | g_param_spec_uint ("probation", "Number of probations", |
| 224 | "Consecutive packet sequence numbers to accept the source", |
| 225 | 0, G_MAXUINT, DEFAULT_PROBATION, |
| 226 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| 227 | |
Miguel París Díaz | 4c96094 | 2015-10-07 13:02:12 +0200 | [diff] [blame] | 228 | g_object_class_install_property (gobject_class, PROP_MAX_DROPOUT_TIME, |
| 229 | g_param_spec_uint ("max-dropout-time", "Max dropout time", |
| 230 | "The maximum time (milliseconds) of missing packets tolerated.", |
| 231 | 0, G_MAXUINT, DEFAULT_MAX_DROPOUT_TIME, |
| 232 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| 233 | |
| 234 | g_object_class_install_property (gobject_class, PROP_MAX_MISORDER_TIME, |
| 235 | g_param_spec_uint ("max-misorder-time", "Max misorder time", |
| 236 | "The maximum time (milliseconds) of misordered packets tolerated.", |
| 237 | 0, G_MAXUINT, DEFAULT_MAX_MISORDER_TIME, |
| 238 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| 239 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 240 | GST_DEBUG_CATEGORY_INIT (rtp_source_debug, "rtpsource", 0, "RTP Source"); |
| 241 | } |
| 242 | |
Olivier Crete | 3f58847 | 2008-03-11 12:40:58 +0000 | [diff] [blame] | 243 | /** |
| 244 | * rtp_source_reset: |
| 245 | * @src: an #RTPSource |
| 246 | * |
| 247 | * Reset the stats of @src. |
| 248 | */ |
| 249 | void |
| 250 | rtp_source_reset (RTPSource * src) |
| 251 | { |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 252 | src->marked_bye = FALSE; |
| 253 | if (src->bye_reason) |
| 254 | g_free (src->bye_reason); |
| 255 | src->bye_reason = NULL; |
Wim Taymans | 93d0729 | 2013-07-25 17:15:37 +0200 | [diff] [blame] | 256 | src->sent_bye = FALSE; |
George Kiagiadakis | 6a2de91 | 2013-11-14 16:19:29 +0200 | [diff] [blame] | 257 | g_hash_table_remove_all (src->reported_in_sr_of); |
Olivier Crete | 3f58847 | 2008-03-11 12:40:58 +0000 | [diff] [blame] | 258 | |
| 259 | src->stats.cycles = -1; |
| 260 | src->stats.jitter = 0; |
| 261 | src->stats.transit = -1; |
| 262 | src->stats.curr_sr = 0; |
Wim Taymans | 0c9c143 | 2013-07-25 17:06:22 +0200 | [diff] [blame] | 263 | src->stats.sr[0].is_valid = FALSE; |
Olivier Crete | 3f58847 | 2008-03-11 12:40:58 +0000 | [diff] [blame] | 264 | src->stats.curr_rr = 0; |
Wim Taymans | 0c9c143 | 2013-07-25 17:06:22 +0200 | [diff] [blame] | 265 | src->stats.rr[0].is_valid = FALSE; |
| 266 | src->stats.prev_rtptime = GST_CLOCK_TIME_NONE; |
| 267 | src->stats.prev_rtcptime = GST_CLOCK_TIME_NONE; |
| 268 | src->stats.last_rtptime = GST_CLOCK_TIME_NONE; |
| 269 | src->stats.last_rtcptime = GST_CLOCK_TIME_NONE; |
Wim Taymans | 4379ed1 | 2013-08-05 23:22:16 +0200 | [diff] [blame] | 270 | g_array_set_size (src->nacks, 0); |
Santiago Carot-Nemesio | 2279141 | 2015-03-03 16:01:53 +0100 | [diff] [blame] | 271 | |
| 272 | src->stats.sent_pli_count = 0; |
Santiago Carot-Nemesio | e05378e | 2015-03-03 16:23:15 +0100 | [diff] [blame] | 273 | src->stats.sent_fir_count = 0; |
Santiago Carot-Nemesio | a1e4249 | 2017-01-02 13:42:04 +0100 | [diff] [blame] | 274 | src->stats.sent_nack_count = 0; |
| 275 | src->stats.recv_nack_count = 0; |
Olivier Crete | 3f58847 | 2008-03-11 12:40:58 +0000 | [diff] [blame] | 276 | } |
| 277 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 278 | static void |
| 279 | rtp_source_init (RTPSource * src) |
| 280 | { |
| 281 | /* sources are initialy on probation until we receive enough valid RTP |
| 282 | * packets or a valid RTCP packet */ |
| 283 | src->validated = FALSE; |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 284 | src->internal = FALSE; |
Aleix Conchillo Flaque | 4a200b6 | 2012-08-22 16:36:21 -0700 | [diff] [blame] | 285 | src->probation = DEFAULT_PROBATION; |
| 286 | src->curr_probation = src->probation; |
Pascal Buhler | ca6a512 | 2010-09-24 15:33:40 +0200 | [diff] [blame] | 287 | src->closing = FALSE; |
Miguel París Díaz | 4c96094 | 2015-10-07 13:02:12 +0200 | [diff] [blame] | 288 | src->max_dropout_time = DEFAULT_MAX_DROPOUT_TIME; |
| 289 | src->max_misorder_time = DEFAULT_MAX_MISORDER_TIME; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 290 | |
Wim Taymans | 9a8a8e7 | 2011-10-29 09:09:45 +0200 | [diff] [blame] | 291 | src->sdes = gst_structure_new_empty ("application/x-rtp-source-sdes"); |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 292 | |
Wim Taymans | 3fe87f7 | 2008-12-29 14:21:47 +0000 | [diff] [blame] | 293 | src->payload = -1; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 294 | src->clock_rate = -1; |
| 295 | src->packets = g_queue_new (); |
Olivier Crête | 51a8bed | 2014-10-10 18:30:07 -0400 | [diff] [blame] | 296 | src->seqnum_offset = -1; |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 297 | src->last_rtptime = -1; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 298 | |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 299 | src->retained_feedback = g_queue_new (); |
Wim Taymans | 4379ed1 | 2013-08-05 23:22:16 +0200 | [diff] [blame] | 300 | src->nacks = g_array_new (FALSE, FALSE, sizeof (guint32)); |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 301 | |
George Kiagiadakis | 6a2de91 | 2013-11-14 16:19:29 +0200 | [diff] [blame] | 302 | src->reported_in_sr_of = g_hash_table_new (g_direct_hash, g_direct_equal); |
| 303 | |
Miguel París Díaz | 3aa69ca | 2017-02-02 12:55:25 +0100 | [diff] [blame] | 304 | src->last_keyframe_request = GST_CLOCK_TIME_NONE; |
| 305 | |
Olivier Crete | 3f58847 | 2008-03-11 12:40:58 +0000 | [diff] [blame] | 306 | rtp_source_reset (src); |
Miguel París Díaz | 54a2f33 | 2017-03-15 18:58:55 +0100 | [diff] [blame] | 307 | |
| 308 | src->pt_set = FALSE; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 309 | } |
| 310 | |
Olivier Crête | 2e54d38 | 2014-05-03 18:30:20 -0400 | [diff] [blame] | 311 | void |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 312 | rtp_conflicting_address_free (RTPConflictingAddress * addr) |
| 313 | { |
| 314 | g_object_unref (addr->address); |
Olivier Crête | 2e54d38 | 2014-05-03 18:30:20 -0400 | [diff] [blame] | 315 | g_slice_free (RTPConflictingAddress, addr); |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 316 | } |
| 317 | |
| 318 | static void |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 319 | rtp_source_finalize (GObject * object) |
| 320 | { |
| 321 | RTPSource *src; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 322 | |
| 323 | src = RTP_SOURCE_CAST (object); |
| 324 | |
Sebastian Dröge | 9f18a27 | 2015-05-18 17:38:14 +0300 | [diff] [blame] | 325 | g_queue_foreach (src->packets, (GFunc) gst_buffer_unref, NULL); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 326 | g_queue_free (src->packets); |
| 327 | |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 328 | gst_structure_free (src->sdes); |
Wim Taymans | df55cf2 | 2007-12-12 12:11:53 +0000 | [diff] [blame] | 329 | |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 330 | g_free (src->bye_reason); |
| 331 | |
Peter Kjellerstedt | b1ef039 | 2008-05-09 07:41:58 +0000 | [diff] [blame] | 332 | gst_caps_replace (&src->caps, NULL); |
| 333 | |
Olivier Crête | 2e54d38 | 2014-05-03 18:30:20 -0400 | [diff] [blame] | 334 | g_list_free_full (src->conflicting_addresses, |
| 335 | (GDestroyNotify) rtp_conflicting_address_free); |
Sebastian Dröge | 9f18a27 | 2015-05-18 17:38:14 +0300 | [diff] [blame] | 336 | g_queue_foreach (src->retained_feedback, (GFunc) gst_buffer_unref, NULL); |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 337 | g_queue_free (src->retained_feedback); |
| 338 | |
Wim Taymans | 4379ed1 | 2013-08-05 23:22:16 +0200 | [diff] [blame] | 339 | g_array_free (src->nacks, TRUE); |
| 340 | |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 341 | if (src->rtp_from) |
| 342 | g_object_unref (src->rtp_from); |
| 343 | if (src->rtcp_from) |
| 344 | g_object_unref (src->rtcp_from); |
| 345 | |
George Kiagiadakis | 6a2de91 | 2013-11-14 16:19:29 +0200 | [diff] [blame] | 346 | g_hash_table_unref (src->reported_in_sr_of); |
| 347 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 348 | G_OBJECT_CLASS (rtp_source_parent_class)->finalize (object); |
| 349 | } |
| 350 | |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 351 | static GstStructure * |
| 352 | rtp_source_create_stats (RTPSource * src) |
| 353 | { |
| 354 | GstStructure *s; |
| 355 | gboolean is_sender = src->is_sender; |
| 356 | gboolean internal = src->internal; |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 357 | gchar *address_str; |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 358 | gboolean have_rb; |
| 359 | guint8 fractionlost = 0; |
| 360 | gint32 packetslost = 0; |
| 361 | guint32 exthighestseq = 0; |
| 362 | guint32 jitter = 0; |
| 363 | guint32 lsr = 0; |
| 364 | guint32 dlsr = 0; |
| 365 | guint32 round_trip = 0; |
| 366 | gboolean have_sr; |
| 367 | GstClockTime time = 0; |
| 368 | guint64 ntptime = 0; |
| 369 | guint32 rtptime = 0; |
| 370 | guint32 packet_count = 0; |
| 371 | guint32 octet_count = 0; |
| 372 | |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 373 | |
| 374 | /* common data for all types of sources */ |
| 375 | s = gst_structure_new ("application/x-rtp-source-stats", |
| 376 | "ssrc", G_TYPE_UINT, (guint) src->ssrc, |
| 377 | "internal", G_TYPE_BOOLEAN, internal, |
| 378 | "validated", G_TYPE_BOOLEAN, src->validated, |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 379 | "received-bye", G_TYPE_BOOLEAN, src->marked_bye, |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 380 | "is-csrc", G_TYPE_BOOLEAN, src->is_csrc, |
Havard Graff | 0fa589a | 2009-08-31 18:34:08 +0200 | [diff] [blame] | 381 | "is-sender", G_TYPE_BOOLEAN, is_sender, |
Olivier Crête | 51a8bed | 2014-10-10 18:30:07 -0400 | [diff] [blame] | 382 | "seqnum-base", G_TYPE_INT, src->seqnum_offset, |
Havard Graff | 0fa589a | 2009-08-31 18:34:08 +0200 | [diff] [blame] | 383 | "clock-rate", G_TYPE_INT, src->clock_rate, NULL); |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 384 | |
Wim Taymans | 0ae6e36 | 2009-05-22 13:47:30 +0200 | [diff] [blame] | 385 | /* add address and port */ |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 386 | if (src->rtp_from) { |
| 387 | address_str = __g_socket_address_to_string (src->rtp_from); |
Wim Taymans | 0ae6e36 | 2009-05-22 13:47:30 +0200 | [diff] [blame] | 388 | gst_structure_set (s, "rtp-from", G_TYPE_STRING, address_str, NULL); |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 389 | g_free (address_str); |
Wim Taymans | 0ae6e36 | 2009-05-22 13:47:30 +0200 | [diff] [blame] | 390 | } |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 391 | if (src->rtcp_from) { |
| 392 | address_str = __g_socket_address_to_string (src->rtcp_from); |
Wim Taymans | 0ae6e36 | 2009-05-22 13:47:30 +0200 | [diff] [blame] | 393 | gst_structure_set (s, "rtcp-from", G_TYPE_STRING, address_str, NULL); |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 394 | g_free (address_str); |
Wim Taymans | 0ae6e36 | 2009-05-22 13:47:30 +0200 | [diff] [blame] | 395 | } |
| 396 | |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 397 | gst_structure_set (s, |
| 398 | "octets-sent", G_TYPE_UINT64, src->stats.octets_sent, |
| 399 | "packets-sent", G_TYPE_UINT64, src->stats.packets_sent, |
| 400 | "octets-received", G_TYPE_UINT64, src->stats.octets_received, |
| 401 | "packets-received", G_TYPE_UINT64, src->stats.packets_received, |
| 402 | "bitrate", G_TYPE_UINT64, src->bitrate, |
| 403 | "packets-lost", G_TYPE_INT, |
| 404 | (gint) rtp_stats_get_packets_lost (&src->stats), "jitter", G_TYPE_UINT, |
Santiago Carot-Nemesio | 2279141 | 2015-03-03 16:01:53 +0100 | [diff] [blame] | 405 | (guint) (src->stats.jitter >> 4), |
| 406 | "sent-pli-count", G_TYPE_UINT, src->stats.sent_pli_count, |
Santiago Carot-Nemesio | e05378e | 2015-03-03 16:23:15 +0100 | [diff] [blame] | 407 | "recv-pli-count", G_TYPE_UINT, src->stats.recv_pli_count, |
| 408 | "sent-fir-count", G_TYPE_UINT, src->stats.sent_fir_count, |
Santiago Carot-Nemesio | a1e4249 | 2017-01-02 13:42:04 +0100 | [diff] [blame] | 409 | "recv-fir-count", G_TYPE_UINT, src->stats.recv_fir_count, |
| 410 | "sent-nack-count", G_TYPE_UINT, src->stats.sent_nack_count, |
| 411 | "recv-nack-count", G_TYPE_UINT, src->stats.recv_nack_count, NULL); |
Havard Graff | 0fa589a | 2009-08-31 18:34:08 +0200 | [diff] [blame] | 412 | |
Wim Taymans | 6035ee0 | 2010-12-23 13:00:49 +0100 | [diff] [blame] | 413 | /* get the last SR. */ |
| 414 | have_sr = rtp_source_get_last_sr (src, &time, &ntptime, &rtptime, |
| 415 | &packet_count, &octet_count); |
| 416 | gst_structure_set (s, |
| 417 | "have-sr", G_TYPE_BOOLEAN, have_sr, |
| 418 | "sr-ntptime", G_TYPE_UINT64, ntptime, |
| 419 | "sr-rtptime", G_TYPE_UINT, (guint) rtptime, |
| 420 | "sr-octet-count", G_TYPE_UINT, (guint) octet_count, |
| 421 | "sr-packet-count", G_TYPE_UINT, (guint) packet_count, NULL); |
Havard Graff | 0fa589a | 2009-08-31 18:34:08 +0200 | [diff] [blame] | 422 | |
Wim Taymans | 7caad21 | 2010-12-23 13:55:31 +0100 | [diff] [blame] | 423 | if (!internal) { |
| 424 | /* get the last RB we sent */ |
| 425 | gst_structure_set (s, |
Wim Taymans | b564768 | 2010-12-27 13:11:59 +0100 | [diff] [blame] | 426 | "sent-rb", G_TYPE_BOOLEAN, src->last_rr.is_valid, |
Wim Taymans | 7caad21 | 2010-12-23 13:55:31 +0100 | [diff] [blame] | 427 | "sent-rb-fractionlost", G_TYPE_UINT, (guint) src->last_rr.fractionlost, |
| 428 | "sent-rb-packetslost", G_TYPE_INT, (gint) src->last_rr.packetslost, |
| 429 | "sent-rb-exthighestseq", G_TYPE_UINT, |
| 430 | (guint) src->last_rr.exthighestseq, "sent-rb-jitter", G_TYPE_UINT, |
| 431 | (guint) src->last_rr.jitter, "sent-rb-lsr", G_TYPE_UINT, |
| 432 | (guint) src->last_rr.lsr, "sent-rb-dlsr", G_TYPE_UINT, |
| 433 | (guint) src->last_rr.dlsr, NULL); |
Havard Graff | 0fa589a | 2009-08-31 18:34:08 +0200 | [diff] [blame] | 434 | |
Wim Taymans | 7caad21 | 2010-12-23 13:55:31 +0100 | [diff] [blame] | 435 | /* get the last RB */ |
| 436 | have_rb = rtp_source_get_last_rb (src, &fractionlost, &packetslost, |
| 437 | &exthighestseq, &jitter, &lsr, &dlsr, &round_trip); |
| 438 | |
| 439 | gst_structure_set (s, |
| 440 | "have-rb", G_TYPE_BOOLEAN, have_rb, |
| 441 | "rb-fractionlost", G_TYPE_UINT, (guint) fractionlost, |
| 442 | "rb-packetslost", G_TYPE_INT, (gint) packetslost, |
| 443 | "rb-exthighestseq", G_TYPE_UINT, (guint) exthighestseq, |
| 444 | "rb-jitter", G_TYPE_UINT, (guint) jitter, |
| 445 | "rb-lsr", G_TYPE_UINT, (guint) lsr, |
| 446 | "rb-dlsr", G_TYPE_UINT, (guint) dlsr, |
| 447 | "rb-round-trip", G_TYPE_UINT, (guint) round_trip, NULL); |
| 448 | } |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 449 | |
| 450 | return s; |
| 451 | } |
| 452 | |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 453 | /** |
| 454 | * rtp_source_get_sdes_struct: |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 455 | * @src: an #RTPSource |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 456 | * |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 457 | * Get the SDES from @src. See the SDES property for more details. |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 458 | * |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 459 | * Returns: %GstStructure of type "application/x-rtp-source-sdes". The result is |
| 460 | * valid until the SDES items of @src are modified. |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 461 | */ |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 462 | const GstStructure * |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 463 | rtp_source_get_sdes_struct (RTPSource * src) |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 464 | { |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 465 | g_return_val_if_fail (RTP_IS_SOURCE (src), NULL); |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 466 | |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 467 | return src->sdes; |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 468 | } |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 469 | |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 470 | static gboolean |
| 471 | sdes_struct_compare_func (GQuark field_id, const GValue * value, |
| 472 | gpointer user_data) |
| 473 | { |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 474 | GstStructure *old; |
| 475 | const gchar *field; |
| 476 | |
| 477 | old = GST_STRUCTURE (user_data); |
| 478 | field = g_quark_to_string (field_id); |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 479 | |
| 480 | if (!gst_structure_has_field (old, field)) |
| 481 | return FALSE; |
| 482 | |
| 483 | g_assert (G_VALUE_HOLDS_STRING (value)); |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 484 | |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 485 | return strcmp (g_value_get_string (value), gst_structure_get_string (old, |
| 486 | field)) == 0; |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 487 | } |
| 488 | |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 489 | /** |
Wim Taymans | 0c9c143 | 2013-07-25 17:06:22 +0200 | [diff] [blame] | 490 | * rtp_source_set_sdes_struct: |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 491 | * @src: an #RTPSource |
| 492 | * @sdes: the SDES structure |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 493 | * |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 494 | * Store the @sdes in @src. @sdes must be a structure of type |
| 495 | * "application/x-rtp-source-sdes", see the SDES property for more details. |
| 496 | * |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 497 | * This function takes ownership of @sdes. |
| 498 | * |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 499 | * Returns: %FALSE if the SDES was unchanged. |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 500 | */ |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 501 | gboolean |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 502 | rtp_source_set_sdes_struct (RTPSource * src, GstStructure * sdes) |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 503 | { |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 504 | gboolean changed; |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 505 | |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 506 | g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 507 | g_return_val_if_fail (strcmp (gst_structure_get_name (sdes), |
| 508 | "application/x-rtp-source-sdes") == 0, FALSE); |
| 509 | |
| 510 | changed = !gst_structure_foreach (sdes, sdes_struct_compare_func, src->sdes); |
| 511 | |
| 512 | if (changed) { |
| 513 | gst_structure_free (src->sdes); |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 514 | src->sdes = sdes; |
| 515 | } else { |
| 516 | gst_structure_free (sdes); |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 517 | } |
Pascal Buhler | c3448f9 | 2009-08-31 18:42:25 +0200 | [diff] [blame] | 518 | return changed; |
Wim Taymans | 9f33099 | 2009-06-29 16:21:05 +0200 | [diff] [blame] | 519 | } |
| 520 | |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 521 | static void |
| 522 | rtp_source_set_property (GObject * object, guint prop_id, |
| 523 | const GValue * value, GParamSpec * pspec) |
| 524 | { |
| 525 | RTPSource *src; |
| 526 | |
| 527 | src = RTP_SOURCE (object); |
| 528 | |
| 529 | switch (prop_id) { |
Wim Taymans | 95d1f62 | 2007-12-10 14:03:32 +0000 | [diff] [blame] | 530 | case PROP_SSRC: |
| 531 | src->ssrc = g_value_get_uint (value); |
| 532 | break; |
Aleix Conchillo Flaque | 4a200b6 | 2012-08-22 16:36:21 -0700 | [diff] [blame] | 533 | case PROP_PROBATION: |
| 534 | src->probation = g_value_get_uint (value); |
| 535 | break; |
Miguel París Díaz | 4c96094 | 2015-10-07 13:02:12 +0200 | [diff] [blame] | 536 | case PROP_MAX_DROPOUT_TIME: |
| 537 | src->max_dropout_time = g_value_get_uint (value); |
| 538 | break; |
| 539 | case PROP_MAX_MISORDER_TIME: |
| 540 | src->max_misorder_time = g_value_get_uint (value); |
| 541 | break; |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 542 | default: |
| 543 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| 544 | break; |
| 545 | } |
| 546 | } |
| 547 | |
| 548 | static void |
| 549 | rtp_source_get_property (GObject * object, guint prop_id, |
| 550 | GValue * value, GParamSpec * pspec) |
| 551 | { |
| 552 | RTPSource *src; |
| 553 | |
| 554 | src = RTP_SOURCE (object); |
| 555 | |
| 556 | switch (prop_id) { |
| 557 | case PROP_SSRC: |
| 558 | g_value_set_uint (value, rtp_source_get_ssrc (src)); |
| 559 | break; |
| 560 | case PROP_IS_CSRC: |
| 561 | g_value_set_boolean (value, rtp_source_is_as_csrc (src)); |
| 562 | break; |
| 563 | case PROP_IS_VALIDATED: |
| 564 | g_value_set_boolean (value, rtp_source_is_validated (src)); |
| 565 | break; |
| 566 | case PROP_IS_SENDER: |
| 567 | g_value_set_boolean (value, rtp_source_is_sender (src)); |
| 568 | break; |
Wim Taymans | 55bb4d5 | 2008-11-22 15:24:47 +0000 | [diff] [blame] | 569 | case PROP_SDES: |
Wim Taymans | 05418f1 | 2009-12-22 22:27:21 +0100 | [diff] [blame] | 570 | g_value_set_boxed (value, rtp_source_get_sdes_struct (src)); |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 571 | break; |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 572 | case PROP_STATS: |
| 573 | g_value_take_boxed (value, rtp_source_create_stats (src)); |
| 574 | break; |
Aleix Conchillo Flaque | 4a200b6 | 2012-08-22 16:36:21 -0700 | [diff] [blame] | 575 | case PROP_PROBATION: |
| 576 | g_value_set_uint (value, src->probation); |
| 577 | break; |
Miguel París Díaz | 4c96094 | 2015-10-07 13:02:12 +0200 | [diff] [blame] | 578 | case PROP_MAX_DROPOUT_TIME: |
| 579 | g_value_set_uint (value, src->max_dropout_time); |
| 580 | break; |
| 581 | case PROP_MAX_MISORDER_TIME: |
| 582 | g_value_set_uint (value, src->max_misorder_time); |
| 583 | break; |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 584 | default: |
| 585 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| 586 | break; |
| 587 | } |
| 588 | } |
| 589 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 590 | /** |
| 591 | * rtp_source_new: |
| 592 | * @ssrc: an SSRC |
| 593 | * |
| 594 | * Create a #RTPSource with @ssrc. |
| 595 | * |
| 596 | * Returns: a new #RTPSource. Use g_object_unref() after usage. |
| 597 | */ |
| 598 | RTPSource * |
| 599 | rtp_source_new (guint32 ssrc) |
| 600 | { |
| 601 | RTPSource *src; |
| 602 | |
| 603 | src = g_object_new (RTP_TYPE_SOURCE, NULL); |
| 604 | src->ssrc = ssrc; |
| 605 | |
| 606 | return src; |
| 607 | } |
| 608 | |
| 609 | /** |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 610 | * rtp_source_set_callbacks: |
| 611 | * @src: an #RTPSource |
| 612 | * @cb: callback functions |
| 613 | * @user_data: user data |
| 614 | * |
| 615 | * Set the callbacks for the source. |
| 616 | */ |
| 617 | void |
| 618 | rtp_source_set_callbacks (RTPSource * src, RTPSourceCallbacks * cb, |
| 619 | gpointer user_data) |
| 620 | { |
| 621 | g_return_if_fail (RTP_IS_SOURCE (src)); |
| 622 | |
| 623 | src->callbacks.push_rtp = cb->push_rtp; |
| 624 | src->callbacks.clock_rate = cb->clock_rate; |
| 625 | src->user_data = user_data; |
| 626 | } |
| 627 | |
| 628 | /** |
| 629 | * rtp_source_get_ssrc: |
| 630 | * @src: an #RTPSource |
| 631 | * |
| 632 | * Get the SSRC of @source. |
| 633 | * |
| 634 | * Returns: the SSRC of src. |
| 635 | */ |
| 636 | guint32 |
| 637 | rtp_source_get_ssrc (RTPSource * src) |
| 638 | { |
| 639 | guint32 result; |
| 640 | |
| 641 | g_return_val_if_fail (RTP_IS_SOURCE (src), 0); |
| 642 | |
| 643 | result = src->ssrc; |
| 644 | |
| 645 | return result; |
| 646 | } |
| 647 | |
| 648 | /** |
| 649 | * rtp_source_set_as_csrc: |
| 650 | * @src: an #RTPSource |
| 651 | * |
| 652 | * Configure @src as a CSRC, this will also validate @src. |
| 653 | */ |
| 654 | void |
| 655 | rtp_source_set_as_csrc (RTPSource * src) |
| 656 | { |
| 657 | g_return_if_fail (RTP_IS_SOURCE (src)); |
| 658 | |
| 659 | src->validated = TRUE; |
| 660 | src->is_csrc = TRUE; |
| 661 | } |
| 662 | |
| 663 | /** |
| 664 | * rtp_source_is_as_csrc: |
| 665 | * @src: an #RTPSource |
| 666 | * |
| 667 | * Check if @src is a contributing source. |
| 668 | * |
| 669 | * Returns: %TRUE if @src is acting as a contributing source. |
| 670 | */ |
| 671 | gboolean |
| 672 | rtp_source_is_as_csrc (RTPSource * src) |
| 673 | { |
| 674 | gboolean result; |
| 675 | |
| 676 | g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); |
| 677 | |
| 678 | result = src->is_csrc; |
| 679 | |
| 680 | return result; |
| 681 | } |
| 682 | |
| 683 | /** |
| 684 | * rtp_source_is_active: |
| 685 | * @src: an #RTPSource |
| 686 | * |
| 687 | * Check if @src is an active source. A source is active if it has been |
| 688 | * validated and has not yet received a BYE packet |
| 689 | * |
| 690 | * Returns: %TRUE if @src is an qactive source. |
| 691 | */ |
| 692 | gboolean |
| 693 | rtp_source_is_active (RTPSource * src) |
| 694 | { |
| 695 | gboolean result; |
| 696 | |
| 697 | g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); |
| 698 | |
| 699 | result = RTP_SOURCE_IS_ACTIVE (src); |
| 700 | |
| 701 | return result; |
| 702 | } |
| 703 | |
| 704 | /** |
| 705 | * rtp_source_is_validated: |
| 706 | * @src: an #RTPSource |
| 707 | * |
| 708 | * Check if @src is a validated source. |
| 709 | * |
| 710 | * Returns: %TRUE if @src is a validated source. |
| 711 | */ |
| 712 | gboolean |
| 713 | rtp_source_is_validated (RTPSource * src) |
| 714 | { |
| 715 | gboolean result; |
| 716 | |
| 717 | g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); |
| 718 | |
| 719 | result = src->validated; |
| 720 | |
| 721 | return result; |
| 722 | } |
| 723 | |
| 724 | /** |
| 725 | * rtp_source_is_sender: |
| 726 | * @src: an #RTPSource |
| 727 | * |
| 728 | * Check if @src is a sending source. |
| 729 | * |
| 730 | * Returns: %TRUE if @src is a sending source. |
| 731 | */ |
| 732 | gboolean |
| 733 | rtp_source_is_sender (RTPSource * src) |
| 734 | { |
| 735 | gboolean result; |
| 736 | |
| 737 | g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); |
| 738 | |
| 739 | result = RTP_SOURCE_IS_SENDER (src); |
| 740 | |
| 741 | return result; |
| 742 | } |
| 743 | |
| 744 | /** |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 745 | * rtp_source_is_marked_bye: |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 746 | * @src: an #RTPSource |
| 747 | * |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 748 | * Check if @src is marked as leaving the session with a BYE packet. |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 749 | * |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 750 | * Returns: %TRUE if @src has been marked BYE. |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 751 | */ |
| 752 | gboolean |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 753 | rtp_source_is_marked_bye (RTPSource * src) |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 754 | { |
| 755 | gboolean result; |
| 756 | |
| 757 | g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); |
| 758 | |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 759 | result = RTP_SOURCE_IS_MARKED_BYE (src); |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 760 | |
| 761 | return result; |
| 762 | } |
| 763 | |
| 764 | |
| 765 | /** |
| 766 | * rtp_source_get_bye_reason: |
| 767 | * @src: an #RTPSource |
| 768 | * |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 769 | * Get the BYE reason for @src. Check if the source is marked as leaving the |
| 770 | * session with a BYE message first with rtp_source_is_marked_bye(). |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 771 | * |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 772 | * Returns: The BYE reason or NULL when no reason was given or the source was |
| 773 | * not marked BYE yet. g_free() after usage. |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 774 | */ |
| 775 | gchar * |
| 776 | rtp_source_get_bye_reason (RTPSource * src) |
| 777 | { |
| 778 | gchar *result; |
| 779 | |
| 780 | g_return_val_if_fail (RTP_IS_SOURCE (src), NULL); |
| 781 | |
| 782 | result = g_strdup (src->bye_reason); |
| 783 | |
| 784 | return result; |
| 785 | } |
| 786 | |
| 787 | /** |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 788 | * rtp_source_update_caps: |
| 789 | * @src: an #RTPSource |
| 790 | * @caps: a #GstCaps |
| 791 | * |
| 792 | * Parse @caps and store all relevant information in @source. |
| 793 | */ |
| 794 | void |
| 795 | rtp_source_update_caps (RTPSource * src, GstCaps * caps) |
| 796 | { |
| 797 | GstStructure *s; |
| 798 | guint val; |
| 799 | gint ival; |
Sebastian Dröge | 80268e7 | 2015-04-16 15:31:25 +0200 | [diff] [blame] | 800 | gboolean rtx; |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 801 | |
| 802 | /* nothing changed, return */ |
Wim Taymans | 9f68303 | 2009-07-28 18:18:20 +0200 | [diff] [blame] | 803 | if (caps == NULL || src->caps == caps) |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 804 | return; |
| 805 | |
| 806 | s = gst_caps_get_structure (caps, 0); |
| 807 | |
Sebastian Dröge | 80268e7 | 2015-04-16 15:31:25 +0200 | [diff] [blame] | 808 | rtx = (gst_structure_get_uint (s, "rtx-ssrc", &val) && val == src->ssrc); |
| 809 | |
| 810 | if (gst_structure_get_int (s, rtx ? "rtx-payload" : "payload", &ival)) |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 811 | src->payload = ival; |
Wim Taymans | 3fe87f7 | 2008-12-29 14:21:47 +0000 | [diff] [blame] | 812 | else |
| 813 | src->payload = -1; |
Sebastian Dröge | 80268e7 | 2015-04-16 15:31:25 +0200 | [diff] [blame] | 814 | |
| 815 | GST_DEBUG ("got %spayload %d", rtx ? "rtx " : "", src->payload); |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 816 | |
Wim Taymans | 3fe87f7 | 2008-12-29 14:21:47 +0000 | [diff] [blame] | 817 | if (gst_structure_get_int (s, "clock-rate", &ival)) |
| 818 | src->clock_rate = ival; |
| 819 | else |
| 820 | src->clock_rate = -1; |
| 821 | |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 822 | GST_DEBUG ("got clock-rate %d", src->clock_rate); |
| 823 | |
Sebastian Dröge | 80268e7 | 2015-04-16 15:31:25 +0200 | [diff] [blame] | 824 | if (gst_structure_get_uint (s, rtx ? "rtx-seqnum-offset" : "seqnum-offset", |
| 825 | &val)) |
Olivier Crête | 51a8bed | 2014-10-10 18:30:07 -0400 | [diff] [blame] | 826 | src->seqnum_offset = val; |
Wim Taymans | 3fe87f7 | 2008-12-29 14:21:47 +0000 | [diff] [blame] | 827 | else |
Olivier Crête | 51a8bed | 2014-10-10 18:30:07 -0400 | [diff] [blame] | 828 | src->seqnum_offset = -1; |
Wim Taymans | 3fe87f7 | 2008-12-29 14:21:47 +0000 | [diff] [blame] | 829 | |
Sebastian Dröge | 80268e7 | 2015-04-16 15:31:25 +0200 | [diff] [blame] | 830 | GST_DEBUG ("got %sseqnum-offset %" G_GINT32_FORMAT, rtx ? "rtx " : "", |
| 831 | src->seqnum_offset); |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 832 | |
| 833 | gst_caps_replace (&src->caps, caps); |
| 834 | } |
| 835 | |
| 836 | /** |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 837 | * rtp_source_set_rtp_from: |
| 838 | * @src: an #RTPSource |
| 839 | * @address: the RTP address to set |
| 840 | * |
| 841 | * Set that @src is receiving RTP packets from @address. This is used for |
| 842 | * collistion checking. |
| 843 | */ |
| 844 | void |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 845 | rtp_source_set_rtp_from (RTPSource * src, GSocketAddress * address) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 846 | { |
| 847 | g_return_if_fail (RTP_IS_SOURCE (src)); |
| 848 | |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 849 | if (src->rtp_from) |
| 850 | g_object_unref (src->rtp_from); |
| 851 | src->rtp_from = G_SOCKET_ADDRESS (g_object_ref (address)); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 852 | } |
| 853 | |
| 854 | /** |
| 855 | * rtp_source_set_rtcp_from: |
| 856 | * @src: an #RTPSource |
| 857 | * @address: the RTCP address to set |
| 858 | * |
| 859 | * Set that @src is receiving RTCP packets from @address. This is used for |
| 860 | * collistion checking. |
| 861 | */ |
| 862 | void |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 863 | rtp_source_set_rtcp_from (RTPSource * src, GSocketAddress * address) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 864 | { |
| 865 | g_return_if_fail (RTP_IS_SOURCE (src)); |
| 866 | |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 867 | if (src->rtcp_from) |
| 868 | g_object_unref (src->rtcp_from); |
| 869 | src->rtcp_from = G_SOCKET_ADDRESS (g_object_ref (address)); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 870 | } |
| 871 | |
| 872 | static GstFlowReturn |
| 873 | push_packet (RTPSource * src, GstBuffer * buffer) |
| 874 | { |
| 875 | GstFlowReturn ret = GST_FLOW_OK; |
| 876 | |
| 877 | /* push queued packets first if any */ |
| 878 | while (!g_queue_is_empty (src->packets)) { |
| 879 | GstBuffer *buffer = GST_BUFFER_CAST (g_queue_pop_head (src->packets)); |
| 880 | |
Peter Kjellerstedt | e2f49d9 | 2008-07-03 14:31:10 +0000 | [diff] [blame] | 881 | GST_LOG ("pushing queued packet"); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 882 | if (src->callbacks.push_rtp) |
| 883 | src->callbacks.push_rtp (src, buffer, src->user_data); |
| 884 | else |
| 885 | gst_buffer_unref (buffer); |
| 886 | } |
Peter Kjellerstedt | e2f49d9 | 2008-07-03 14:31:10 +0000 | [diff] [blame] | 887 | GST_LOG ("pushing new packet"); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 888 | /* push packet */ |
| 889 | if (src->callbacks.push_rtp) |
| 890 | ret = src->callbacks.push_rtp (src, buffer, src->user_data); |
| 891 | else |
| 892 | gst_buffer_unref (buffer); |
| 893 | |
| 894 | return ret; |
| 895 | } |
| 896 | |
| 897 | static gint |
| 898 | get_clock_rate (RTPSource * src, guint8 payload) |
| 899 | { |
Wim Taymans | 3fe87f7 | 2008-12-29 14:21:47 +0000 | [diff] [blame] | 900 | if (src->payload == -1) { |
| 901 | /* first payload received, nothing was in the caps, lock on to this payload */ |
| 902 | src->payload = payload; |
| 903 | GST_DEBUG ("first payload %d", payload); |
| 904 | } else if (payload != src->payload) { |
| 905 | /* we have a different payload than before, reset the clock-rate */ |
Wim Taymans | 5ab3e10 | 2008-11-17 15:17:52 +0000 | [diff] [blame] | 906 | GST_DEBUG ("new payload %d", payload); |
| 907 | src->payload = payload; |
| 908 | src->clock_rate = -1; |
| 909 | src->stats.transit = -1; |
| 910 | } |
| 911 | |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 912 | if (src->clock_rate == -1) { |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 913 | gint clock_rate = -1; |
| 914 | |
| 915 | if (src->callbacks.clock_rate) |
| 916 | clock_rate = src->callbacks.clock_rate (src, payload, src->user_data); |
| 917 | |
Sebastian Dröge | c364523 | 2008-11-17 19:47:32 +0000 | [diff] [blame] | 918 | GST_DEBUG ("got clock-rate %d", clock_rate); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 919 | |
| 920 | src->clock_rate = clock_rate; |
Miguel París Díaz | f321bfe | 2015-10-07 13:03:02 +0200 | [diff] [blame] | 921 | gst_rtp_packet_rate_ctx_reset (&src->packet_rate_ctx, clock_rate); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 922 | } |
| 923 | return src->clock_rate; |
| 924 | } |
| 925 | |
Wim Taymans | b2aa36c | 2007-09-16 19:40:31 +0000 | [diff] [blame] | 926 | /* Jitter is the variation in the delay of received packets in a flow. It is |
| 927 | * measured by comparing the interval when RTP packets were sent to the interval |
| 928 | * at which they were received. For instance, if packet #1 and packet #2 leave |
| 929 | * 50 milliseconds apart and arrive 60 milliseconds apart, then the jitter is 10 |
| 930 | * milliseconds. */ |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 931 | static void |
Wim Taymans | a02c947 | 2013-09-13 12:22:36 +0200 | [diff] [blame] | 932 | calculate_jitter (RTPSource * src, RTPPacketInfo * pinfo) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 933 | { |
Wim Taymans | 74241e5 | 2010-01-20 18:19:34 +0100 | [diff] [blame] | 934 | GstClockTime running_time; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 935 | guint32 rtparrival, transit, rtptime; |
| 936 | gint32 diff; |
| 937 | gint clock_rate; |
| 938 | guint8 pt; |
| 939 | |
| 940 | /* get arrival time */ |
Wim Taymans | 47662f9 | 2013-09-13 11:08:55 +0200 | [diff] [blame] | 941 | if ((running_time = pinfo->running_time) == GST_CLOCK_TIME_NONE) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 942 | goto no_time; |
| 943 | |
Wim Taymans | a02c947 | 2013-09-13 12:22:36 +0200 | [diff] [blame] | 944 | pt = pinfo->pt; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 945 | |
Peter Kjellerstedt | e2f49d9 | 2008-07-03 14:31:10 +0000 | [diff] [blame] | 946 | GST_LOG ("SSRC %08x got payload %d", src->ssrc, pt); |
Wim Taymans | 56d5832 | 2007-09-17 02:01:41 +0000 | [diff] [blame] | 947 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 948 | /* get clockrate */ |
Wim Taymans | a02c947 | 2013-09-13 12:22:36 +0200 | [diff] [blame] | 949 | if ((clock_rate = get_clock_rate (src, pt)) == -1) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 950 | goto no_clock_rate; |
| 951 | |
Wim Taymans | a02c947 | 2013-09-13 12:22:36 +0200 | [diff] [blame] | 952 | rtptime = pinfo->rtptime; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 953 | |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 954 | /* convert arrival time to RTP timestamp units, truncate to 32 bits, we don't |
| 955 | * care about the absolute value, just the difference. */ |
Wim Taymans | 74241e5 | 2010-01-20 18:19:34 +0100 | [diff] [blame] | 956 | rtparrival = gst_util_uint64_scale_int (running_time, clock_rate, GST_SECOND); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 957 | |
| 958 | /* transit time is difference with RTP timestamp */ |
| 959 | transit = rtparrival - rtptime; |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 960 | |
| 961 | /* get ABS diff with previous transit time */ |
| 962 | if (src->stats.transit != -1) { |
| 963 | if (transit > src->stats.transit) |
| 964 | diff = transit - src->stats.transit; |
| 965 | else |
| 966 | diff = src->stats.transit - transit; |
| 967 | } else |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 968 | diff = 0; |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 969 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 970 | src->stats.transit = transit; |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 971 | |
| 972 | /* update jitter, the value we store is scaled up so we can keep precision. */ |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 973 | src->stats.jitter += diff - ((src->stats.jitter + 8) >> 4); |
| 974 | |
| 975 | src->stats.prev_rtptime = src->stats.last_rtptime; |
| 976 | src->stats.last_rtptime = rtparrival; |
| 977 | |
Peter Kjellerstedt | e2f49d9 | 2008-07-03 14:31:10 +0000 | [diff] [blame] | 978 | GST_LOG ("rtparrival %u, rtptime %u, clock-rate %d, diff %d, jitter: %f", |
Wim Taymans | eb86865 | 2007-08-28 20:30:16 +0000 | [diff] [blame] | 979 | rtparrival, rtptime, clock_rate, diff, (src->stats.jitter) / 16.0); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 980 | |
| 981 | return; |
| 982 | |
| 983 | /* ERRORS */ |
| 984 | no_time: |
| 985 | { |
Wim Taymans | 74241e5 | 2010-01-20 18:19:34 +0100 | [diff] [blame] | 986 | GST_WARNING ("cannot get current running_time"); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 987 | return; |
| 988 | } |
| 989 | no_clock_rate: |
| 990 | { |
| 991 | GST_WARNING ("cannot get clock-rate for pt %d", pt); |
| 992 | return; |
| 993 | } |
| 994 | } |
| 995 | |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 996 | static void |
| 997 | init_seq (RTPSource * src, guint16 seq) |
| 998 | { |
| 999 | src->stats.base_seq = seq; |
| 1000 | src->stats.max_seq = seq; |
| 1001 | src->stats.bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */ |
| 1002 | src->stats.cycles = 0; |
| 1003 | src->stats.packets_received = 0; |
| 1004 | src->stats.octets_received = 0; |
| 1005 | src->stats.bytes_received = 0; |
| 1006 | src->stats.prev_received = 0; |
| 1007 | src->stats.prev_expected = 0; |
Santiago Carot-Nemesio | 2279141 | 2015-03-03 16:01:53 +0100 | [diff] [blame] | 1008 | src->stats.recv_pli_count = 0; |
Santiago Carot-Nemesio | e05378e | 2015-03-03 16:23:15 +0100 | [diff] [blame] | 1009 | src->stats.recv_fir_count = 0; |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1010 | |
| 1011 | GST_DEBUG ("base_seq %d", seq); |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1012 | } |
| 1013 | |
Wim Taymans | c5203a4 | 2010-09-24 13:48:50 +0200 | [diff] [blame] | 1014 | #define BITRATE_INTERVAL (2 * GST_SECOND) |
| 1015 | |
Wim Taymans | c971d1a | 2010-03-02 12:39:20 +0100 | [diff] [blame] | 1016 | static void |
| 1017 | do_bitrate_estimation (RTPSource * src, GstClockTime running_time, |
| 1018 | guint64 * bytes_handled) |
| 1019 | { |
| 1020 | guint64 elapsed; |
| 1021 | |
| 1022 | if (src->prev_rtime) { |
| 1023 | elapsed = running_time - src->prev_rtime; |
| 1024 | |
Wim Taymans | c5203a4 | 2010-09-24 13:48:50 +0200 | [diff] [blame] | 1025 | if (elapsed > BITRATE_INTERVAL) { |
Wim Taymans | c971d1a | 2010-03-02 12:39:20 +0100 | [diff] [blame] | 1026 | guint64 rate; |
| 1027 | |
Wim Taymans | c5203a4 | 2010-09-24 13:48:50 +0200 | [diff] [blame] | 1028 | rate = gst_util_uint64_scale (*bytes_handled, 8 * GST_SECOND, elapsed); |
Wim Taymans | c971d1a | 2010-03-02 12:39:20 +0100 | [diff] [blame] | 1029 | |
| 1030 | GST_LOG ("Elapsed %" G_GUINT64_FORMAT ", bytes %" G_GUINT64_FORMAT |
| 1031 | ", rate %" G_GUINT64_FORMAT, elapsed, *bytes_handled, rate); |
| 1032 | |
| 1033 | if (src->bitrate == 0) |
| 1034 | src->bitrate = rate; |
| 1035 | else |
| 1036 | src->bitrate = ((src->bitrate * 3) + rate) / 4; |
| 1037 | |
| 1038 | src->prev_rtime = running_time; |
| 1039 | *bytes_handled = 0; |
| 1040 | } |
| 1041 | } else { |
| 1042 | GST_LOG ("Reset bitrate measurement"); |
| 1043 | src->prev_rtime = running_time; |
| 1044 | src->bitrate = 0; |
| 1045 | } |
| 1046 | } |
| 1047 | |
Wim Taymans | 268a75e | 2013-11-07 16:13:16 +0100 | [diff] [blame] | 1048 | static gboolean |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1049 | update_receiver_stats (RTPSource * src, RTPPacketInfo * pinfo, |
| 1050 | gboolean is_receive) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1051 | { |
Sebastian Dröge | 3386de7 | 2015-05-18 17:07:23 +0300 | [diff] [blame] | 1052 | guint16 seqnr, expected; |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1053 | RTPSourceStats *stats; |
Sebastian Dröge | 3386de7 | 2015-05-18 17:07:23 +0300 | [diff] [blame] | 1054 | gint16 delta; |
Miguel París Díaz | f321bfe | 2015-10-07 13:03:02 +0200 | [diff] [blame] | 1055 | gint32 packet_rate, max_dropout, max_misorder; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1056 | |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1057 | stats = &src->stats; |
| 1058 | |
Wim Taymans | a02c947 | 2013-09-13 12:22:36 +0200 | [diff] [blame] | 1059 | seqnr = pinfo->seqnum; |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1060 | |
Miguel París Díaz | f321bfe | 2015-10-07 13:03:02 +0200 | [diff] [blame] | 1061 | packet_rate = |
| 1062 | gst_rtp_packet_rate_ctx_update (&src->packet_rate_ctx, pinfo->seqnum, |
| 1063 | pinfo->rtptime); |
| 1064 | max_dropout = |
| 1065 | gst_rtp_packet_rate_ctx_get_max_dropout (&src->packet_rate_ctx, |
| 1066 | src->max_dropout_time); |
| 1067 | max_misorder = |
| 1068 | gst_rtp_packet_rate_ctx_get_max_misorder (&src->packet_rate_ctx, |
| 1069 | src->max_misorder_time); |
| 1070 | GST_TRACE ("SSRC %08x, packet_rate: %d, max_dropout: %d, max_misorder: %d", |
| 1071 | src->ssrc, packet_rate, max_dropout, max_misorder); |
| 1072 | |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1073 | if (stats->cycles == -1) { |
Wim Taymans | a02c947 | 2013-09-13 12:22:36 +0200 | [diff] [blame] | 1074 | GST_DEBUG ("received first packet"); |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1075 | /* first time we heard of this source */ |
| 1076 | init_seq (src, seqnr); |
| 1077 | src->stats.max_seq = seqnr - 1; |
Aleix Conchillo Flaque | 4a200b6 | 2012-08-22 16:36:21 -0700 | [diff] [blame] | 1078 | src->curr_probation = src->probation; |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1079 | } |
| 1080 | |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1081 | if (is_receive) { |
| 1082 | expected = src->stats.max_seq + 1; |
| 1083 | delta = gst_rtp_buffer_compare_seqnum (expected, seqnr); |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1084 | |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1085 | /* if we are still on probation, check seqnum */ |
| 1086 | if (src->curr_probation) { |
| 1087 | /* when in probation, we require consecutive seqnums */ |
| 1088 | if (delta == 0) { |
| 1089 | /* expected packet */ |
| 1090 | GST_DEBUG ("probation: seqnr %d == expected %d", seqnr, expected); |
| 1091 | src->curr_probation--; |
| 1092 | if (seqnr < stats->max_seq) { |
| 1093 | /* sequence number wrapped - count another 64K cycle. */ |
| 1094 | stats->cycles += RTP_SEQ_MOD; |
| 1095 | } |
| 1096 | src->stats.max_seq = seqnr; |
| 1097 | |
| 1098 | if (src->curr_probation == 0) { |
| 1099 | GST_DEBUG ("probation done!"); |
| 1100 | init_seq (src, seqnr); |
| 1101 | } else { |
| 1102 | GstBuffer *q; |
| 1103 | |
| 1104 | GST_DEBUG ("probation %d: queue packet", src->curr_probation); |
| 1105 | /* when still in probation, keep packets in a list. */ |
| 1106 | g_queue_push_tail (src->packets, pinfo->data); |
| 1107 | pinfo->data = NULL; |
| 1108 | /* remove packets from queue if there are too many */ |
| 1109 | while (g_queue_get_length (src->packets) > RTP_MAX_PROBATION_LEN) { |
| 1110 | q = g_queue_pop_head (src->packets); |
| 1111 | gst_buffer_unref (q); |
| 1112 | } |
| 1113 | goto done; |
| 1114 | } |
| 1115 | } else { |
| 1116 | /* unexpected seqnum in probation */ |
| 1117 | goto probation_seqnum; |
| 1118 | } |
Miguel París Díaz | f321bfe | 2015-10-07 13:03:02 +0200 | [diff] [blame] | 1119 | } else if (delta >= 0 && delta < max_dropout) { |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1120 | /* Clear bad packets */ |
| 1121 | stats->bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */ |
| 1122 | g_queue_foreach (src->packets, (GFunc) gst_buffer_unref, NULL); |
| 1123 | g_queue_clear (src->packets); |
| 1124 | |
| 1125 | /* in order, with permissible gap */ |
Sebastian Dröge | 1974b24 | 2015-05-18 17:08:53 +0300 | [diff] [blame] | 1126 | if (seqnr < stats->max_seq) { |
| 1127 | /* sequence number wrapped - count another 64K cycle. */ |
| 1128 | stats->cycles += RTP_SEQ_MOD; |
| 1129 | } |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1130 | stats->max_seq = seqnr; |
Miguel París Díaz | f321bfe | 2015-10-07 13:03:02 +0200 | [diff] [blame] | 1131 | } else if (delta < -max_misorder || delta >= max_dropout) { |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1132 | /* the sequence number made a very large jump */ |
| 1133 | if (seqnr == stats->bad_seq && src->packets->head) { |
| 1134 | /* two sequential packets -- assume that the other side |
| 1135 | * restarted without telling us so just re-sync |
| 1136 | * (i.e., pretend this was the first packet). */ |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1137 | init_seq (src, seqnr); |
| 1138 | } else { |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1139 | /* unacceptable jump */ |
| 1140 | stats->bad_seq = (seqnr + 1) & (RTP_SEQ_MOD - 1); |
| 1141 | g_queue_foreach (src->packets, (GFunc) gst_buffer_unref, NULL); |
| 1142 | g_queue_clear (src->packets); |
Wim Taymans | a02c947 | 2013-09-13 12:22:36 +0200 | [diff] [blame] | 1143 | g_queue_push_tail (src->packets, pinfo->data); |
| 1144 | pinfo->data = NULL; |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1145 | goto bad_sequence; |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1146 | } |
Miguel París Díaz | f321bfe | 2015-10-07 13:03:02 +0200 | [diff] [blame] | 1147 | } else { /* delta < 0 && delta >= -max_misorder */ |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1148 | /* Clear bad packets */ |
| 1149 | stats->bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */ |
Sebastian Dröge | c60038f | 2015-05-18 17:38:31 +0300 | [diff] [blame] | 1150 | g_queue_foreach (src->packets, (GFunc) gst_buffer_unref, NULL); |
| 1151 | g_queue_clear (src->packets); |
Sebastian Dröge | c60038f | 2015-05-18 17:38:31 +0300 | [diff] [blame] | 1152 | |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1153 | /* duplicate or reordered packet, will be filtered by jitterbuffer. */ |
Havard Graff | b33470f | 2016-03-31 00:10:49 +0200 | [diff] [blame] | 1154 | GST_INFO ("duplicate or reordered packet (seqnr %u, expected %u)", |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1155 | seqnr, expected); |
| 1156 | } |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1157 | } |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1158 | |
Wim Taymans | 47662f9 | 2013-09-13 11:08:55 +0200 | [diff] [blame] | 1159 | src->stats.octets_received += pinfo->payload_len; |
| 1160 | src->stats.bytes_received += pinfo->bytes; |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1161 | src->stats.packets_received++; |
Wim Taymans | c971d1a | 2010-03-02 12:39:20 +0100 | [diff] [blame] | 1162 | /* for the bitrate estimation */ |
Wim Taymans | 47662f9 | 2013-09-13 11:08:55 +0200 | [diff] [blame] | 1163 | src->bytes_received += pinfo->payload_len; |
Wim Taymans | 268a75e | 2013-11-07 16:13:16 +0100 | [diff] [blame] | 1164 | |
Sebastian Dröge | 54e9243 | 2015-05-18 17:19:31 +0300 | [diff] [blame] | 1165 | GST_LOG ("seq %u, PC: %" G_GUINT64_FORMAT ", OC: %" G_GUINT64_FORMAT, |
Wim Taymans | 268a75e | 2013-11-07 16:13:16 +0100 | [diff] [blame] | 1166 | seqnr, src->stats.packets_received, src->stats.octets_received); |
| 1167 | |
| 1168 | return TRUE; |
| 1169 | |
| 1170 | /* ERRORS */ |
| 1171 | done: |
| 1172 | { |
| 1173 | return FALSE; |
| 1174 | } |
| 1175 | bad_sequence: |
| 1176 | { |
Miguel París Díaz | f321bfe | 2015-10-07 13:03:02 +0200 | [diff] [blame] | 1177 | GST_WARNING |
| 1178 | ("unacceptable seqnum received (seqnr %u, delta %d, packet_rate: %d, max_dropout: %d, max_misorder: %d)", |
| 1179 | seqnr, delta, packet_rate, max_dropout, max_misorder); |
Wim Taymans | 268a75e | 2013-11-07 16:13:16 +0100 | [diff] [blame] | 1180 | return FALSE; |
| 1181 | } |
| 1182 | probation_seqnum: |
| 1183 | { |
| 1184 | GST_WARNING ("probation: seqnr %d != expected %d", seqnr, expected); |
| 1185 | src->curr_probation = src->probation; |
| 1186 | src->stats.max_seq = seqnr; |
| 1187 | return FALSE; |
| 1188 | } |
| 1189 | } |
| 1190 | |
| 1191 | /** |
| 1192 | * rtp_source_process_rtp: |
| 1193 | * @src: an #RTPSource |
| 1194 | * @pinfo: an #RTPPacketInfo |
| 1195 | * |
| 1196 | * Let @src handle the incomming RTP packet described in @pinfo. |
| 1197 | * |
| 1198 | * Returns: a #GstFlowReturn. |
| 1199 | */ |
| 1200 | GstFlowReturn |
| 1201 | rtp_source_process_rtp (RTPSource * src, RTPPacketInfo * pinfo) |
| 1202 | { |
| 1203 | GstFlowReturn result; |
| 1204 | |
| 1205 | g_return_val_if_fail (RTP_IS_SOURCE (src), GST_FLOW_ERROR); |
| 1206 | g_return_val_if_fail (pinfo != NULL, GST_FLOW_ERROR); |
| 1207 | |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1208 | if (!update_receiver_stats (src, pinfo, TRUE)) |
Wim Taymans | 268a75e | 2013-11-07 16:13:16 +0100 | [diff] [blame] | 1209 | return GST_FLOW_OK; |
| 1210 | |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1211 | /* the source that sent the packet must be a sender */ |
| 1212 | src->is_sender = TRUE; |
| 1213 | src->validated = TRUE; |
| 1214 | |
Wim Taymans | 47662f9 | 2013-09-13 11:08:55 +0200 | [diff] [blame] | 1215 | do_bitrate_estimation (src, pinfo->running_time, &src->bytes_received); |
Tristan Matthews | a0a6d4f | 2010-03-01 16:40:27 -0500 | [diff] [blame] | 1216 | |
Wim Taymans | bd1e0eb | 2008-05-26 10:09:29 +0000 | [diff] [blame] | 1217 | /* calculate jitter for the stats */ |
Wim Taymans | a02c947 | 2013-09-13 12:22:36 +0200 | [diff] [blame] | 1218 | calculate_jitter (src, pinfo); |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1219 | |
| 1220 | /* we're ready to push the RTP packet now */ |
Wim Taymans | a02c947 | 2013-09-13 12:22:36 +0200 | [diff] [blame] | 1221 | result = push_packet (src, pinfo->data); |
| 1222 | pinfo->data = NULL; |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1223 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1224 | return result; |
| 1225 | } |
| 1226 | |
| 1227 | /** |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 1228 | * rtp_source_mark_bye: |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1229 | * @src: an #RTPSource |
| 1230 | * @reason: the reason for leaving |
| 1231 | * |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 1232 | * Mark @src in the BYE state. This can happen when the source wants to |
| 1233 | * leave the sesssion or when a BYE packets has been received. |
| 1234 | * |
| 1235 | * This will make the source inactive. |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1236 | */ |
| 1237 | void |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 1238 | rtp_source_mark_bye (RTPSource * src, const gchar * reason) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1239 | { |
| 1240 | g_return_if_fail (RTP_IS_SOURCE (src)); |
| 1241 | |
| 1242 | GST_DEBUG ("marking SSRC %08x as BYE, reason: %s", src->ssrc, |
| 1243 | GST_STR_NULL (reason)); |
| 1244 | |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 1245 | /* copy the reason and mark as bye */ |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1246 | g_free (src->bye_reason); |
| 1247 | src->bye_reason = g_strdup (reason); |
Wim Taymans | 1d02496 | 2013-07-25 16:49:41 +0200 | [diff] [blame] | 1248 | src->marked_bye = TRUE; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1249 | } |
| 1250 | |
| 1251 | /** |
| 1252 | * rtp_source_send_rtp: |
| 1253 | * @src: an #RTPSource |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 1254 | * @data: an RTP buffer or a list of RTP buffers |
| 1255 | * @is_list: if @data is a buffer or list |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1256 | * @running_time: the running time of @data |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1257 | * |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 1258 | * Send @data (an RTP buffer or list of buffers) originating from @src. |
| 1259 | * This will make @src a sender. This function takes ownership of @data and |
| 1260 | * modifies the SSRC in the RTP packet to that of @src when needed. |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1261 | * |
| 1262 | * Returns: a #GstFlowReturn. |
| 1263 | */ |
| 1264 | GstFlowReturn |
Wim Taymans | 28e5f90 | 2013-09-13 12:40:41 +0200 | [diff] [blame] | 1265 | rtp_source_send_rtp (RTPSource * src, RTPPacketInfo * pinfo) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1266 | { |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 1267 | GstFlowReturn result; |
Wim Taymans | 28e5f90 | 2013-09-13 12:40:41 +0200 | [diff] [blame] | 1268 | GstClockTime running_time; |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 1269 | guint32 rtptime; |
| 1270 | guint64 ext_rtptime; |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1271 | guint64 rt_diff, rtp_diff; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1272 | |
| 1273 | g_return_val_if_fail (RTP_IS_SOURCE (src), GST_FLOW_ERROR); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1274 | |
| 1275 | /* we are a sender now */ |
| 1276 | src->is_sender = TRUE; |
| 1277 | |
Jose Antonio Santos Cadenas | 11f298a | 2015-06-22 11:28:13 +0200 | [diff] [blame] | 1278 | /* we are also a receiver of our packets */ |
Hyunjun Ko | b814d7e | 2015-10-02 16:18:15 +0900 | [diff] [blame] | 1279 | if (!update_receiver_stats (src, pinfo, FALSE)) |
Jose Antonio Santos Cadenas | 11f298a | 2015-06-22 11:28:13 +0200 | [diff] [blame] | 1280 | return GST_FLOW_OK; |
| 1281 | |
Miguel París Díaz | 54a2f33 | 2017-03-15 18:58:55 +0100 | [diff] [blame] | 1282 | if (src->pt_set && src->pt != pinfo->pt) { |
Patrick Radizi | 23f7739 | 2017-09-14 11:20:17 +0200 | [diff] [blame] | 1283 | GST_WARNING ("Changing pt from %u to %u for SSRC %u", src->pt, pinfo->pt, |
| 1284 | src->ssrc); |
Miguel París Díaz | 54a2f33 | 2017-03-15 18:58:55 +0100 | [diff] [blame] | 1285 | } |
| 1286 | |
| 1287 | src->pt = pinfo->pt; |
| 1288 | src->pt_set = TRUE; |
| 1289 | |
Wim Taymans | 600afaa | 2007-04-30 13:41:30 +0000 | [diff] [blame] | 1290 | /* update stats for the SR */ |
Wim Taymans | 28e5f90 | 2013-09-13 12:40:41 +0200 | [diff] [blame] | 1291 | src->stats.packets_sent += pinfo->packets; |
| 1292 | src->stats.octets_sent += pinfo->payload_len; |
| 1293 | src->bytes_sent += pinfo->payload_len; |
| 1294 | |
| 1295 | running_time = pinfo->running_time; |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 1296 | |
Wim Taymans | c971d1a | 2010-03-02 12:39:20 +0100 | [diff] [blame] | 1297 | do_bitrate_estimation (src, running_time, &src->bytes_sent); |
Wim Taymans | 600afaa | 2007-04-30 13:41:30 +0000 | [diff] [blame] | 1298 | |
Wim Taymans | 28e5f90 | 2013-09-13 12:40:41 +0200 | [diff] [blame] | 1299 | rtptime = pinfo->rtptime; |
Wim Taymans | c795b72 | 2013-09-13 10:55:31 +0200 | [diff] [blame] | 1300 | |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 1301 | ext_rtptime = src->last_rtptime; |
| 1302 | ext_rtptime = gst_rtp_buffer_ext_timestamp (&ext_rtptime, rtptime); |
| 1303 | |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1304 | GST_LOG ("SSRC %08x, RTP %" G_GUINT64_FORMAT ", running_time %" |
| 1305 | GST_TIME_FORMAT, src->ssrc, ext_rtptime, GST_TIME_ARGS (running_time)); |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 1306 | |
| 1307 | if (ext_rtptime > src->last_rtptime) { |
| 1308 | rtp_diff = ext_rtptime - src->last_rtptime; |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1309 | rt_diff = running_time - src->last_rtime; |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 1310 | |
| 1311 | /* calc the diff so we can detect drift at the sender. This can also be used |
| 1312 | * to guestimate the clock rate if the NTP time is locked to the RTP |
| 1313 | * timestamps (as is the case when the capture device is providing the clock). */ |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1314 | GST_LOG ("SSRC %08x, diff RTP %" G_GUINT64_FORMAT ", diff running_time %" |
| 1315 | GST_TIME_FORMAT, src->ssrc, rtp_diff, GST_TIME_ARGS (rt_diff)); |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 1316 | } |
| 1317 | |
Wim Taymans | 325dac0 | 2007-08-29 01:22:43 +0000 | [diff] [blame] | 1318 | /* we keep track of the last received RTP timestamp and the corresponding |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1319 | * buffer running_time so that we can use this info when constructing SR reports */ |
| 1320 | src->last_rtime = running_time; |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 1321 | src->last_rtptime = ext_rtptime; |
Wim Taymans | c576bce | 2007-08-29 16:56:27 +0000 | [diff] [blame] | 1322 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1323 | /* push packet */ |
Wim Taymans | c795b72 | 2013-09-13 10:55:31 +0200 | [diff] [blame] | 1324 | if (!src->callbacks.push_rtp) |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 1325 | goto no_callback; |
Mark Nauwelaerts | ef02634 | 2011-07-06 10:11:52 +0200 | [diff] [blame] | 1326 | |
Wim Taymans | 28e5f90 | 2013-09-13 12:40:41 +0200 | [diff] [blame] | 1327 | GST_LOG ("pushing RTP %s %" G_GUINT64_FORMAT, |
| 1328 | pinfo->is_list ? "list" : "packet", src->stats.packets_sent); |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 1329 | |
Wim Taymans | 28e5f90 | 2013-09-13 12:40:41 +0200 | [diff] [blame] | 1330 | result = src->callbacks.push_rtp (src, pinfo->data, src->user_data); |
| 1331 | pinfo->data = NULL; |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 1332 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1333 | return result; |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 1334 | |
| 1335 | /* ERRORS */ |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 1336 | no_callback: |
| 1337 | { |
| 1338 | GST_WARNING ("no callback installed, dropping packet"); |
Branko Subasic | 779f67a | 2009-06-19 19:09:19 +0200 | [diff] [blame] | 1339 | return GST_FLOW_OK; |
| 1340 | } |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1341 | } |
| 1342 | |
| 1343 | /** |
| 1344 | * rtp_source_process_sr: |
| 1345 | * @src: an #RTPSource |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1346 | * @time: time of packet arrival |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1347 | * @ntptime: the NTP time (in NTP Timestamp Format, 32.32 fixed point) |
| 1348 | * @rtptime: the RTP time (in clock rate units) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1349 | * @packet_count: the packet count |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1350 | * @octet_count: the octet count |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1351 | * |
| 1352 | * Update the sender report in @src. |
| 1353 | */ |
| 1354 | void |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1355 | rtp_source_process_sr (RTPSource * src, GstClockTime time, guint64 ntptime, |
| 1356 | guint32 rtptime, guint32 packet_count, guint32 octet_count) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1357 | { |
| 1358 | RTPSenderReport *curr; |
| 1359 | gint curridx; |
| 1360 | |
| 1361 | g_return_if_fail (RTP_IS_SOURCE (src)); |
| 1362 | |
Stefan Kost | 15b54ec | 2007-05-10 14:02:07 +0000 | [diff] [blame] | 1363 | GST_DEBUG ("got SR packet: SSRC %08x, NTP %08x:%08x, RTP %" G_GUINT32_FORMAT |
| 1364 | ", PC %" G_GUINT32_FORMAT ", OC %" G_GUINT32_FORMAT, src->ssrc, |
| 1365 | (guint32) (ntptime >> 32), (guint32) (ntptime & 0xffffffff), rtptime, |
| 1366 | packet_count, octet_count); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1367 | |
| 1368 | curridx = src->stats.curr_sr ^ 1; |
| 1369 | curr = &src->stats.sr[curridx]; |
| 1370 | |
Wim Taymans | 23883be | 2007-04-25 08:30:48 +0000 | [diff] [blame] | 1371 | /* this is a sender now */ |
| 1372 | src->is_sender = TRUE; |
| 1373 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1374 | /* update current */ |
| 1375 | curr->is_valid = TRUE; |
| 1376 | curr->ntptime = ntptime; |
| 1377 | curr->rtptime = rtptime; |
| 1378 | curr->packet_count = packet_count; |
| 1379 | curr->octet_count = octet_count; |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1380 | curr->time = time; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1381 | |
| 1382 | /* make current */ |
| 1383 | src->stats.curr_sr = curridx; |
Mark Nauwelaerts | e2179cb | 2011-09-02 13:41:41 +0200 | [diff] [blame] | 1384 | |
| 1385 | src->stats.prev_rtcptime = src->stats.last_rtcptime; |
| 1386 | src->stats.last_rtcptime = time; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1387 | } |
| 1388 | |
| 1389 | /** |
| 1390 | * rtp_source_process_rb: |
| 1391 | * @src: an #RTPSource |
Wim Taymans | 8598aaf | 2011-02-02 18:21:26 +0100 | [diff] [blame] | 1392 | * @ntpnstime: the current time in nanoseconds since 1970 |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1393 | * @fractionlost: fraction lost since last SR/RR |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1394 | * @packetslost: the cumulative number of packets lost |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1395 | * @exthighestseq: the extended last sequence number received |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1396 | * @jitter: the interarrival jitter (in clock rate units) |
| 1397 | * @lsr: the time of the last SR packet on this source |
| 1398 | * (in NTP Short Format, 16.16 fixed point) |
| 1399 | * @dlsr: the delay since the last SR packet |
| 1400 | * (in NTP Short Format, 16.16 fixed point) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1401 | * |
| 1402 | * Update the report block in @src. |
| 1403 | */ |
| 1404 | void |
Wim Taymans | 61382aa | 2011-02-02 18:27:52 +0100 | [diff] [blame] | 1405 | rtp_source_process_rb (RTPSource * src, guint64 ntpnstime, |
Wim Taymans | 8598aaf | 2011-02-02 18:21:26 +0100 | [diff] [blame] | 1406 | guint8 fractionlost, gint32 packetslost, guint32 exthighestseq, |
| 1407 | guint32 jitter, guint32 lsr, guint32 dlsr) |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1408 | { |
| 1409 | RTPReceiverReport *curr; |
| 1410 | gint curridx; |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1411 | guint32 ntp, A; |
Wim Taymans | 8598aaf | 2011-02-02 18:21:26 +0100 | [diff] [blame] | 1412 | guint64 f_ntp; |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1413 | |
| 1414 | g_return_if_fail (RTP_IS_SOURCE (src)); |
| 1415 | |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1416 | GST_DEBUG ("got RB packet: SSRC %08x, FL %2x, PL %d, HS %" G_GUINT32_FORMAT |
| 1417 | ", jitter %" G_GUINT32_FORMAT ", LSR %04x:%04x, DLSR %04x:%04x", |
| 1418 | src->ssrc, fractionlost, packetslost, exthighestseq, jitter, lsr >> 16, |
| 1419 | lsr & 0xffff, dlsr >> 16, dlsr & 0xffff); |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1420 | |
| 1421 | curridx = src->stats.curr_rr ^ 1; |
| 1422 | curr = &src->stats.rr[curridx]; |
| 1423 | |
| 1424 | /* update current */ |
| 1425 | curr->is_valid = TRUE; |
| 1426 | curr->fractionlost = fractionlost; |
| 1427 | curr->packetslost = packetslost; |
| 1428 | curr->exthighestseq = exthighestseq; |
| 1429 | curr->jitter = jitter; |
| 1430 | curr->lsr = lsr; |
| 1431 | curr->dlsr = dlsr; |
| 1432 | |
Wim Taymans | 8598aaf | 2011-02-02 18:21:26 +0100 | [diff] [blame] | 1433 | /* convert the NTP time in nanoseconds to 32.32 fixed point */ |
| 1434 | f_ntp = gst_util_uint64_scale (ntpnstime, (1LL << 32), GST_SECOND); |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 1435 | /* calculate round trip, round the time up */ |
Wim Taymans | 8598aaf | 2011-02-02 18:21:26 +0100 | [diff] [blame] | 1436 | ntp = ((f_ntp + 0xffff) >> 16) & 0xffffffff; |
| 1437 | |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 1438 | A = dlsr + lsr; |
| 1439 | if (A > 0 && ntp > A) |
| 1440 | A = ntp - A; |
| 1441 | else |
| 1442 | A = 0; |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1443 | curr->round_trip = A; |
| 1444 | |
| 1445 | GST_DEBUG ("NTP %04x:%04x, round trip %04x:%04x", ntp >> 16, ntp & 0xffff, |
| 1446 | A >> 16, A & 0xffff); |
| 1447 | |
Wim Taymans | 54b3dec | 2007-04-18 18:58:53 +0000 | [diff] [blame] | 1448 | /* make current */ |
| 1449 | src->stats.curr_rr = curridx; |
| 1450 | } |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1451 | |
| 1452 | /** |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1453 | * rtp_source_get_new_sr: |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1454 | * @src: an #RTPSource |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 1455 | * @ntpnstime: the current time in nanoseconds since 1970 |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1456 | * @running_time: the current running_time of the pipeline |
| 1457 | * @ntptime: the NTP time (in NTP Timestamp Format, 32.32 fixed point) |
| 1458 | * @rtptime: the RTP time corresponding to @ntptime (in clock rate units) |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1459 | * @packet_count: the packet count |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1460 | * @octet_count: the octet count |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1461 | * |
| 1462 | * Get new values to put into a new SR report from this source. |
| 1463 | * |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1464 | * @running_time and @ntpnstime are captured at the same time and represent the |
| 1465 | * running time of the pipeline clock and the absolute current system time in |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1466 | * nanoseconds respectively. Together with the last running_time and RTP timestamp |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1467 | * we have observed in the source, we can generate @ntptime and @rtptime for an SR |
| 1468 | * packet. @ntptime is basically the fixed point representation of @ntpnstime |
| 1469 | * and @rtptime the associated RTP timestamp. |
| 1470 | * |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1471 | * Returns: %TRUE on success. |
| 1472 | */ |
| 1473 | gboolean |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 1474 | rtp_source_get_new_sr (RTPSource * src, guint64 ntpnstime, |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1475 | GstClockTime running_time, guint64 * ntptime, guint32 * rtptime, |
| 1476 | guint32 * packet_count, guint32 * octet_count) |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1477 | { |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 1478 | guint64 t_rtp; |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1479 | guint64 t_current_ntp; |
| 1480 | GstClockTimeDiff diff; |
| 1481 | |
| 1482 | g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); |
| 1483 | |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1484 | /* We last saw a buffer with last_rtptime at last_rtime. Given a running_time |
| 1485 | * and an NTP time, we can scale the RTP timestamps so that they match the |
| 1486 | * given NTP time. for scaling, we assume that the slope of the rtptime vs |
| 1487 | * running_time vs ntptime curve is close to 1, which is certainly |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1488 | * sufficient for the frequency at which we report SR and the rate we send |
| 1489 | * out RTP packets. */ |
| 1490 | t_rtp = src->last_rtptime; |
| 1491 | |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1492 | GST_DEBUG ("last_rtime %" GST_TIME_FORMAT ", last_rtptime %" |
| 1493 | G_GUINT64_FORMAT, GST_TIME_ARGS (src->last_rtime), t_rtp); |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1494 | |
Miguel París Díaz | 54a2f33 | 2017-03-15 18:58:55 +0100 | [diff] [blame] | 1495 | if (src->clock_rate == -1 && src->pt_set) { |
| 1496 | GST_INFO ("no clock-rate, getting for pt %u and SSRC %u", src->pt, |
| 1497 | src->ssrc); |
| 1498 | get_clock_rate (src, src->pt); |
| 1499 | } |
| 1500 | |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1501 | if (src->clock_rate != -1) { |
Wim Taymans | 83cb1ae | 2010-01-20 17:04:03 +0100 | [diff] [blame] | 1502 | /* get the diff between the clock running_time and the buffer running_time. |
| 1503 | * This is the elapsed time, as measured against the pipeline clock, between |
| 1504 | * when the rtp timestamp was observed and the current running_time. |
| 1505 | * |
| 1506 | * We need to apply this diff to the RTP timestamp to get the RTP timestamp |
| 1507 | * for the given ntpnstime. */ |
| 1508 | diff = GST_CLOCK_DIFF (src->last_rtime, running_time); |
Luis de Bethencourt | d4f094f | 2015-11-03 14:26:29 +0000 | [diff] [blame] | 1509 | GST_DEBUG ("running_time %" GST_TIME_FORMAT ", diff %" GST_STIME_FORMAT, |
| 1510 | GST_TIME_ARGS (running_time), GST_STIME_ARGS (diff)); |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1511 | |
| 1512 | /* now translate the diff to RTP time, handle positive and negative cases. |
| 1513 | * If there is no diff, we already set rtptime correctly above. */ |
| 1514 | if (diff > 0) { |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1515 | t_rtp += gst_util_uint64_scale_int (diff, src->clock_rate, GST_SECOND); |
| 1516 | } else { |
| 1517 | diff = -diff; |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1518 | t_rtp -= gst_util_uint64_scale_int (diff, src->clock_rate, GST_SECOND); |
| 1519 | } |
| 1520 | } else { |
Miguel París Díaz | 389e0ab | 2016-06-03 13:09:35 +0200 | [diff] [blame] | 1521 | GST_WARNING ("no clock-rate, cannot interpolate rtp time for SSRC %u", |
| 1522 | src->ssrc); |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1523 | } |
| 1524 | |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 1525 | /* convert the NTP time in nanoseconds to 32.32 fixed point */ |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1526 | t_current_ntp = gst_util_uint64_scale (ntpnstime, (1LL << 32), GST_SECOND); |
| 1527 | |
| 1528 | GST_DEBUG ("NTP %08x:%08x, RTP %" G_GUINT32_FORMAT, |
| 1529 | (guint32) (t_current_ntp >> 32), (guint32) (t_current_ntp & 0xffffffff), |
Wim Taymans | 919deb4 | 2007-09-12 18:04:32 +0000 | [diff] [blame] | 1530 | (guint32) t_rtp); |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1531 | |
| 1532 | if (ntptime) |
| 1533 | *ntptime = t_current_ntp; |
| 1534 | if (rtptime) |
| 1535 | *rtptime = t_rtp; |
| 1536 | if (packet_count) |
| 1537 | *packet_count = src->stats.packets_sent; |
| 1538 | if (octet_count) |
| 1539 | *octet_count = src->stats.octets_sent; |
| 1540 | |
| 1541 | return TRUE; |
| 1542 | } |
| 1543 | |
| 1544 | /** |
| 1545 | * rtp_source_get_new_rb: |
| 1546 | * @src: an #RTPSource |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 1547 | * @time: the current time of the system clock |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1548 | * @fractionlost: fraction lost since last SR/RR |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1549 | * @packetslost: the cumulative number of packets lost |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1550 | * @exthighestseq: the extended last sequence number received |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1551 | * @jitter: the interarrival jitter (in clock rate units) |
| 1552 | * @lsr: the time of the last SR packet on this source |
Ilya Konstantinov | c7e168e | 2015-06-10 14:49:50 +0300 | [diff] [blame] | 1553 | * (in NTP Short Format, 16.16 fixed point) |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1554 | * @dlsr: the delay since the last SR packet |
Ilya Konstantinov | c7e168e | 2015-06-10 14:49:50 +0300 | [diff] [blame] | 1555 | * (in NTP Short Format, 16.16 fixed point) |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1556 | * |
Wim Taymans | 1971ae0 | 2007-12-10 11:08:11 +0000 | [diff] [blame] | 1557 | * Get new values to put into a new report block from this source. |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1558 | * |
| 1559 | * Returns: %TRUE on success. |
| 1560 | */ |
| 1561 | gboolean |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 1562 | rtp_source_get_new_rb (RTPSource * src, GstClockTime time, |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1563 | guint8 * fractionlost, gint32 * packetslost, guint32 * exthighestseq, |
| 1564 | guint32 * jitter, guint32 * lsr, guint32 * dlsr) |
| 1565 | { |
| 1566 | RTPSourceStats *stats; |
| 1567 | guint64 extended_max, expected; |
| 1568 | guint64 expected_interval, received_interval, ntptime; |
| 1569 | gint64 lost, lost_interval; |
| 1570 | guint32 fraction, LSR, DLSR; |
| 1571 | GstClockTime sr_time; |
| 1572 | |
| 1573 | stats = &src->stats; |
| 1574 | |
| 1575 | extended_max = stats->cycles + stats->max_seq; |
| 1576 | expected = extended_max - stats->base_seq + 1; |
| 1577 | |
| 1578 | GST_DEBUG ("ext_max %" G_GUINT64_FORMAT ", expected %" G_GUINT64_FORMAT |
| 1579 | ", received %" G_GUINT64_FORMAT ", base_seq %" G_GUINT32_FORMAT, |
| 1580 | extended_max, expected, stats->packets_received, stats->base_seq); |
| 1581 | |
| 1582 | lost = expected - stats->packets_received; |
| 1583 | lost = CLAMP (lost, -0x800000, 0x7fffff); |
| 1584 | |
| 1585 | expected_interval = expected - stats->prev_expected; |
| 1586 | stats->prev_expected = expected; |
| 1587 | received_interval = stats->packets_received - stats->prev_received; |
| 1588 | stats->prev_received = stats->packets_received; |
| 1589 | |
| 1590 | lost_interval = expected_interval - received_interval; |
| 1591 | |
| 1592 | if (expected_interval == 0 || lost_interval <= 0) |
| 1593 | fraction = 0; |
| 1594 | else |
| 1595 | fraction = (lost_interval << 8) / expected_interval; |
| 1596 | |
| 1597 | GST_DEBUG ("add RR for SSRC %08x", src->ssrc); |
| 1598 | /* we scaled the jitter up for additional precision */ |
| 1599 | GST_DEBUG ("fraction %" G_GUINT32_FORMAT ", lost %" G_GINT64_FORMAT |
| 1600 | ", extseq %" G_GUINT64_FORMAT ", jitter %d", fraction, lost, |
| 1601 | extended_max, stats->jitter >> 4); |
| 1602 | |
| 1603 | if (rtp_source_get_last_sr (src, &sr_time, &ntptime, NULL, NULL, NULL)) { |
| 1604 | GstClockTime diff; |
| 1605 | |
| 1606 | /* LSR is middle 32 bits of the last ntptime */ |
| 1607 | LSR = (ntptime >> 16) & 0xffffffff; |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 1608 | diff = time - sr_time; |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1609 | GST_DEBUG ("last SR time diff %" GST_TIME_FORMAT, GST_TIME_ARGS (diff)); |
| 1610 | /* DLSR, delay since last SR is expressed in 1/65536 second units */ |
| 1611 | DLSR = gst_util_uint64_scale_int (diff, 65536, GST_SECOND); |
| 1612 | } else { |
| 1613 | /* No valid SR received, LSR/DLSR are set to 0 then */ |
| 1614 | GST_DEBUG ("no valid SR received"); |
| 1615 | LSR = 0; |
| 1616 | DLSR = 0; |
| 1617 | } |
| 1618 | GST_DEBUG ("LSR %04x:%04x, DLSR %04x:%04x", LSR >> 16, LSR & 0xffff, |
| 1619 | DLSR >> 16, DLSR & 0xffff); |
| 1620 | |
| 1621 | if (fractionlost) |
| 1622 | *fractionlost = fraction; |
| 1623 | if (packetslost) |
| 1624 | *packetslost = lost; |
| 1625 | if (exthighestseq) |
| 1626 | *exthighestseq = extended_max; |
| 1627 | if (jitter) |
| 1628 | *jitter = stats->jitter >> 4; |
| 1629 | if (lsr) |
| 1630 | *lsr = LSR; |
| 1631 | if (dlsr) |
| 1632 | *dlsr = DLSR; |
| 1633 | |
| 1634 | return TRUE; |
| 1635 | } |
| 1636 | |
| 1637 | /** |
| 1638 | * rtp_source_get_last_sr: |
| 1639 | * @src: an #RTPSource |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1640 | * @time: time of packet arrival |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1641 | * @ntptime: the NTP time (in NTP Timestamp Format, 32.32 fixed point) |
| 1642 | * @rtptime: the RTP time (in clock rate units) |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1643 | * @packet_count: the packet count |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1644 | * @octet_count: the octet count |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1645 | * |
| 1646 | * Get the values of the last sender report as set with rtp_source_process_sr(). |
| 1647 | * |
| 1648 | * Returns: %TRUE if there was a valid SR report. |
| 1649 | */ |
| 1650 | gboolean |
Wim Taymans | e7b6212 | 2007-09-03 21:19:34 +0000 | [diff] [blame] | 1651 | rtp_source_get_last_sr (RTPSource * src, GstClockTime * time, guint64 * ntptime, |
| 1652 | guint32 * rtptime, guint32 * packet_count, guint32 * octet_count) |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1653 | { |
| 1654 | RTPSenderReport *curr; |
| 1655 | |
| 1656 | g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); |
| 1657 | |
| 1658 | curr = &src->stats.sr[src->stats.curr_sr]; |
| 1659 | if (!curr->is_valid) |
| 1660 | return FALSE; |
| 1661 | |
| 1662 | if (ntptime) |
| 1663 | *ntptime = curr->ntptime; |
| 1664 | if (rtptime) |
| 1665 | *rtptime = curr->rtptime; |
| 1666 | if (packet_count) |
| 1667 | *packet_count = curr->packet_count; |
| 1668 | if (octet_count) |
| 1669 | *octet_count = curr->octet_count; |
| 1670 | if (time) |
| 1671 | *time = curr->time; |
| 1672 | |
| 1673 | return TRUE; |
| 1674 | } |
| 1675 | |
| 1676 | /** |
| 1677 | * rtp_source_get_last_rb: |
| 1678 | * @src: an #RTPSource |
| 1679 | * @fractionlost: fraction lost since last SR/RR |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1680 | * @packetslost: the cumulative number of packets lost |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1681 | * @exthighestseq: the extended last sequence number received |
Ilya Konstantinov | 0a578c2 | 2015-06-09 19:02:55 +0300 | [diff] [blame] | 1682 | * @jitter: the interarrival jitter (in clock rate units) |
| 1683 | * @lsr: the time of the last SR packet on this source |
| 1684 | * (in NTP Short Format, 16.16 fixed point) |
| 1685 | * @dlsr: the delay since the last SR packet |
| 1686 | * (in NTP Short Format, 16.16 fixed point) |
| 1687 | * @round_trip: the round-trip time |
| 1688 | * (in NTP Short Format, 16.16 fixed point) |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1689 | * |
| 1690 | * Get the values of the last RB report set with rtp_source_process_rb(). |
| 1691 | * |
| 1692 | * Returns: %TRUE if there was a valid SB report. |
| 1693 | */ |
| 1694 | gboolean |
| 1695 | rtp_source_get_last_rb (RTPSource * src, guint8 * fractionlost, |
| 1696 | gint32 * packetslost, guint32 * exthighestseq, guint32 * jitter, |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 1697 | guint32 * lsr, guint32 * dlsr, guint32 * round_trip) |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1698 | { |
| 1699 | RTPReceiverReport *curr; |
| 1700 | |
| 1701 | g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); |
| 1702 | |
| 1703 | curr = &src->stats.rr[src->stats.curr_rr]; |
| 1704 | if (!curr->is_valid) |
| 1705 | return FALSE; |
| 1706 | |
| 1707 | if (fractionlost) |
| 1708 | *fractionlost = curr->fractionlost; |
| 1709 | if (packetslost) |
| 1710 | *packetslost = curr->packetslost; |
| 1711 | if (exthighestseq) |
| 1712 | *exthighestseq = curr->exthighestseq; |
| 1713 | if (jitter) |
| 1714 | *jitter = curr->jitter; |
| 1715 | if (lsr) |
| 1716 | *lsr = curr->lsr; |
| 1717 | if (dlsr) |
| 1718 | *dlsr = curr->dlsr; |
Wim Taymans | 2f5b130 | 2008-11-20 18:41:34 +0000 | [diff] [blame] | 1719 | if (round_trip) |
| 1720 | *round_trip = curr->round_trip; |
Wim Taymans | ae536e0 | 2007-04-25 13:19:36 +0000 | [diff] [blame] | 1721 | |
| 1722 | return TRUE; |
| 1723 | } |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1724 | |
Olivier Crête | 2e54d38 | 2014-05-03 18:30:20 -0400 | [diff] [blame] | 1725 | gboolean |
| 1726 | find_conflicting_address (GList * conflicting_addresses, |
| 1727 | GSocketAddress * address, GstClockTime time) |
| 1728 | { |
| 1729 | GList *item; |
| 1730 | |
| 1731 | for (item = conflicting_addresses; item; item = g_list_next (item)) { |
| 1732 | RTPConflictingAddress *known_conflict = item->data; |
| 1733 | |
| 1734 | if (__g_socket_address_equal (address, known_conflict->address)) { |
| 1735 | known_conflict->time = time; |
| 1736 | return TRUE; |
| 1737 | } |
| 1738 | } |
| 1739 | |
| 1740 | return FALSE; |
| 1741 | } |
| 1742 | |
| 1743 | GList * |
| 1744 | add_conflicting_address (GList * conflicting_addresses, |
| 1745 | GSocketAddress * address, GstClockTime time) |
| 1746 | { |
| 1747 | RTPConflictingAddress *new_conflict; |
| 1748 | |
| 1749 | new_conflict = g_slice_new (RTPConflictingAddress); |
| 1750 | |
| 1751 | new_conflict->address = G_SOCKET_ADDRESS (g_object_ref (address)); |
| 1752 | new_conflict->time = time; |
| 1753 | |
| 1754 | return g_list_prepend (conflicting_addresses, new_conflict); |
| 1755 | } |
| 1756 | |
| 1757 | GList * |
| 1758 | timeout_conflicting_addresses (GList * conflicting_addresses, |
| 1759 | GstClockTime current_time) |
| 1760 | { |
| 1761 | GList *item; |
| 1762 | /* "a relatively long time" -- RFC 3550 section 8.2 */ |
| 1763 | const GstClockTime collision_timeout = |
| 1764 | RTP_STATS_MIN_INTERVAL * GST_SECOND * 10; |
| 1765 | |
| 1766 | item = g_list_first (conflicting_addresses); |
| 1767 | while (item) { |
| 1768 | RTPConflictingAddress *known_conflict = item->data; |
| 1769 | GList *next_item = g_list_next (item); |
| 1770 | |
| 1771 | if (known_conflict->time < current_time - collision_timeout) { |
| 1772 | gchar *buf; |
| 1773 | |
| 1774 | conflicting_addresses = g_list_delete_link (conflicting_addresses, item); |
| 1775 | buf = __g_socket_address_to_string (known_conflict->address); |
| 1776 | GST_DEBUG ("collision %p timed out: %s", known_conflict, buf); |
| 1777 | g_free (buf); |
| 1778 | rtp_conflicting_address_free (known_conflict); |
| 1779 | } |
| 1780 | item = next_item; |
| 1781 | } |
| 1782 | |
| 1783 | return conflicting_addresses; |
| 1784 | } |
| 1785 | |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1786 | /** |
Olivier Crête | a6dfe96 | 2010-03-05 16:08:45 +0100 | [diff] [blame] | 1787 | * rtp_source_find_conflicting_address: |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1788 | * @src: The source the packet came in |
| 1789 | * @address: address to check for |
Olivier Crête | a6dfe96 | 2010-03-05 16:08:45 +0100 | [diff] [blame] | 1790 | * @time: The time when the packet that is possibly in conflict arrived |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1791 | * |
Olivier Crête | a6dfe96 | 2010-03-05 16:08:45 +0100 | [diff] [blame] | 1792 | * Checks if an address which has a conflict is already known. If it is |
| 1793 | * a known conflict, remember the time |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1794 | * |
| 1795 | * Returns: TRUE if it was a known conflict, FALSE otherwise |
| 1796 | */ |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1797 | gboolean |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 1798 | rtp_source_find_conflicting_address (RTPSource * src, GSocketAddress * address, |
Olivier Crête | a6dfe96 | 2010-03-05 16:08:45 +0100 | [diff] [blame] | 1799 | GstClockTime time) |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1800 | { |
Olivier Crête | 2e54d38 | 2014-05-03 18:30:20 -0400 | [diff] [blame] | 1801 | return find_conflicting_address (src->conflicting_addresses, address, time); |
Olivier Crête | a6dfe96 | 2010-03-05 16:08:45 +0100 | [diff] [blame] | 1802 | } |
| 1803 | |
| 1804 | /** |
| 1805 | * rtp_source_add_conflicting_address: |
| 1806 | * @src: The source the packet came in |
| 1807 | * @address: address to remember |
| 1808 | * @time: The time when the packet that is in conflict arrived |
| 1809 | * |
| 1810 | * Adds a new conflict address |
| 1811 | */ |
Olivier Crête | a6dfe96 | 2010-03-05 16:08:45 +0100 | [diff] [blame] | 1812 | void |
| 1813 | rtp_source_add_conflicting_address (RTPSource * src, |
Sebastian Dröge | cb789e3 | 2012-01-17 13:08:42 +0100 | [diff] [blame] | 1814 | GSocketAddress * address, GstClockTime time) |
Olivier Crête | a6dfe96 | 2010-03-05 16:08:45 +0100 | [diff] [blame] | 1815 | { |
Olivier Crête | 2e54d38 | 2014-05-03 18:30:20 -0400 | [diff] [blame] | 1816 | src->conflicting_addresses = |
| 1817 | add_conflicting_address (src->conflicting_addresses, address, time); |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1818 | } |
| 1819 | |
| 1820 | /** |
| 1821 | * rtp_source_timeout: |
| 1822 | * @src: The #RTPSource |
| 1823 | * @current_time: The current time |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 1824 | * @feedback_retention_window: The running time before which retained feedback |
| 1825 | * packets have to be discarded |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1826 | * |
| 1827 | * This is processed on each RTCP interval. It times out old collisions. |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 1828 | * It also times out old retained feedback packets |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1829 | */ |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1830 | void |
| 1831 | rtp_source_timeout (RTPSource * src, GstClockTime current_time, |
Olivier Crête | 2e54d38 | 2014-05-03 18:30:20 -0400 | [diff] [blame] | 1832 | GstClockTime feedback_retention_window) |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1833 | { |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 1834 | GstRTCPPacket *pkt; |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1835 | |
Olivier Crête | 2e54d38 | 2014-05-03 18:30:20 -0400 | [diff] [blame] | 1836 | src->conflicting_addresses = |
| 1837 | timeout_conflicting_addresses (src->conflicting_addresses, current_time); |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 1838 | |
| 1839 | /* Time out AVPF packets that are older than the desired length */ |
| 1840 | while ((pkt = g_queue_peek_tail (src->retained_feedback)) && |
Sebastian Dröge | dc059ef | 2015-06-10 14:33:50 +0200 | [diff] [blame] | 1841 | GST_BUFFER_PTS (pkt) < feedback_retention_window) |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 1842 | gst_buffer_unref (g_queue_pop_tail (src->retained_feedback)); |
| 1843 | } |
| 1844 | |
| 1845 | static gint |
| 1846 | compare_buffers (gconstpointer a, gconstpointer b, gpointer user_data) |
| 1847 | { |
| 1848 | const GstBuffer *bufa = a; |
| 1849 | const GstBuffer *bufb = b; |
| 1850 | |
Sebastian Dröge | dc059ef | 2015-06-10 14:33:50 +0200 | [diff] [blame] | 1851 | return GST_BUFFER_PTS (bufa) - GST_BUFFER_PTS (bufb); |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 1852 | } |
| 1853 | |
| 1854 | void |
| 1855 | rtp_source_retain_rtcp_packet (RTPSource * src, GstRTCPPacket * packet, |
| 1856 | GstClockTime running_time) |
| 1857 | { |
| 1858 | GstBuffer *buffer; |
| 1859 | |
Mark Nauwelaerts | ef02634 | 2011-07-06 10:11:52 +0200 | [diff] [blame] | 1860 | buffer = gst_buffer_copy_region (packet->rtcp->buffer, GST_BUFFER_COPY_MEMORY, |
| 1861 | packet->offset, (gst_rtcp_packet_get_length (packet) + 1) * 4); |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 1862 | |
Sebastian Dröge | dc059ef | 2015-06-10 14:33:50 +0200 | [diff] [blame] | 1863 | GST_BUFFER_PTS (buffer) = running_time; |
Olivier Crête | db5150a | 2010-06-22 13:33:32 -0400 | [diff] [blame] | 1864 | |
| 1865 | g_queue_insert_sorted (src->retained_feedback, buffer, compare_buffers, NULL); |
| 1866 | } |
| 1867 | |
| 1868 | gboolean |
| 1869 | rtp_source_has_retained (RTPSource * src, GCompareFunc func, gconstpointer data) |
| 1870 | { |
| 1871 | if (g_queue_find_custom (src->retained_feedback, data, func)) |
| 1872 | return TRUE; |
| 1873 | else |
| 1874 | return FALSE; |
Olivier Crête | f336ea2 | 2010-03-05 15:46:48 +0100 | [diff] [blame] | 1875 | } |
Wim Taymans | 4379ed1 | 2013-08-05 23:22:16 +0200 | [diff] [blame] | 1876 | |
| 1877 | /** |
Stefan Sauer | 12930c2 | 2015-07-07 16:59:20 +0200 | [diff] [blame] | 1878 | * rtp_source_register_nack: |
Wim Taymans | 4379ed1 | 2013-08-05 23:22:16 +0200 | [diff] [blame] | 1879 | * @src: The #RTPSource |
| 1880 | * @seqnum: a seqnum |
| 1881 | * |
| 1882 | * Register that @seqnum has not been received from @src. |
| 1883 | */ |
| 1884 | void |
| 1885 | rtp_source_register_nack (RTPSource * src, guint16 seqnum) |
| 1886 | { |
| 1887 | guint i, len; |
| 1888 | guint32 dword = seqnum << 16; |
| 1889 | gint diff = 16; |
| 1890 | |
| 1891 | len = src->nacks->len; |
| 1892 | for (i = 0; i < len; i++) { |
| 1893 | guint32 tdword; |
| 1894 | guint16 tseq; |
| 1895 | |
| 1896 | tdword = g_array_index (src->nacks, guint32, i); |
| 1897 | tseq = tdword >> 16; |
| 1898 | |
| 1899 | diff = gst_rtp_buffer_compare_seqnum (tseq, seqnum); |
| 1900 | if (diff < 16) |
| 1901 | break; |
| 1902 | } |
| 1903 | /* we already have this seqnum */ |
| 1904 | if (diff == 0) |
| 1905 | return; |
| 1906 | /* it comes before the recorded seqnum, FIXME, we could merge it |
| 1907 | * if not to far away */ |
| 1908 | if (diff < 0) { |
| 1909 | GST_DEBUG ("insert NACK #%u at %u", seqnum, i); |
| 1910 | g_array_insert_val (src->nacks, i, dword); |
| 1911 | } else if (diff < 16) { |
| 1912 | /* we can merge it */ |
| 1913 | dword = g_array_index (src->nacks, guint32, i); |
| 1914 | dword |= 1 << (diff - 1); |
| 1915 | GST_DEBUG ("merge NACK #%u at %u with NACK #%u -> 0x%08x", seqnum, i, |
| 1916 | dword >> 16, dword); |
| 1917 | g_array_index (src->nacks, guint32, i) = dword; |
| 1918 | } else { |
| 1919 | GST_DEBUG ("append NACK #%u", seqnum); |
| 1920 | g_array_append_val (src->nacks, dword); |
| 1921 | } |
| 1922 | src->send_nack = TRUE; |
| 1923 | } |
| 1924 | |
| 1925 | /** |
Stefan Sauer | 12930c2 | 2015-07-07 16:59:20 +0200 | [diff] [blame] | 1926 | * rtp_source_get_nacks: |
Wim Taymans | 4379ed1 | 2013-08-05 23:22:16 +0200 | [diff] [blame] | 1927 | * @src: The #RTPSource |
| 1928 | * @n_nacks: result number of nacks |
| 1929 | * |
| 1930 | * Get the registered NACKS since the last rtp_source_clear_nacks(). |
| 1931 | * |
| 1932 | * Returns: an array of @n_nacks seqnum values. |
| 1933 | */ |
| 1934 | guint32 * |
| 1935 | rtp_source_get_nacks (RTPSource * src, guint * n_nacks) |
| 1936 | { |
| 1937 | if (n_nacks) |
| 1938 | *n_nacks = src->nacks->len; |
| 1939 | |
| 1940 | return (guint32 *) src->nacks->data; |
| 1941 | } |
| 1942 | |
| 1943 | void |
| 1944 | rtp_source_clear_nacks (RTPSource * src) |
| 1945 | { |
| 1946 | g_array_set_size (src->nacks, 0); |
| 1947 | src->send_nack = FALSE; |
| 1948 | } |