UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
rtp_callback.c
Go to the documentation of this file.
1/*
2 * FILE: rtp_callback.c
3 * AUTHOR: Colin Perkins <csp@csperkins.org>
4 * Ladan Gharai <ladan@isi.edu>
5 * Martin Benes <martinbenesh@gmail.com>
6 * Lukas Hejtmanek <xhejtman@ics.muni.cz>
7 * Petr Holub <hopet@ics.muni.cz>
8 * Milos Liska <xliska@fi.muni.cz>
9 * Jiri Matela <matela@ics.muni.cz>
10 * Dalibor Matura <255899@mail.muni.cz>
11 * Martin Pulec <martin.pulec@cesnet.cz>
12 * Ian Wesley-Smith <iwsmith@cct.lsu.edu>
13 *
14 * Copyright (c) 2005-2019 CESNET z.s.p.o.
15 * Copyright (c) 2001-2003 University of Southern California
16 * Copyright (c) 2003-2004 University of Glasgow
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, is permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 *
29 * 3. All advertising materials mentioning features or use of this software
30 * must display the following acknowledgement:
31 *
32 * This product includes software developed by the University of Southern
33 * California Information Sciences Institute. This product also includes
34 * software developed by CESNET z.s.p.o.
35 *
36 * 4. Neither the name of the University, Institute, CESNET nor the names of
37 * its contributors may be used to endorse or promote products derived from
38 * this software without specific prior written permission.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
41 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
42 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
43 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
44 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
45 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
50 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
51 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 *
53 * $Revision: 1.3.2.2 $
54 * $Date: 2010/01/30 20:07:35 $
55 *
56 */
57
58#include "config.h"
59#include "config_unix.h"
60#include "config_win32.h"
61
62#include <inttypes.h>
63#include <stdint.h>
64
65#include "debug.h"
66#include "host.h"
67#include "pdb.h"
68#include "video_display.h"
69#include "video_codec.h"
70#include "ntp.h"
71#include "tv.h"
72#include "rtp/rtp.h"
73#include "rtp/pbuf.h"
74#include "rtp/rtp_callback.h"
75#include "tfrc.h"
76
77extern char *frame;
78
79char hdr_buf[100];
80struct msghdr msg;
81struct iovec iov[10];
82
83extern uint32_t RTT;
84
85static void process_rr(struct rtp *session, rtp_event * e)
86{
87 float fract_lost, tmp;
88 uint32_t ntp_sec, ntp_frac, now;
89 rtcp_rr *r = (rtcp_rr *) e->data;
90
91 if (e->ssrc == rtp_my_ssrc(session)) {
92 /* Filter out loopback reports */
93 return;
94 }
95
96 if (r->ssrc == rtp_my_ssrc(session)) {
97 /* Received a reception quality report for data we are sending. */
98 /* */
99 /* Check for excessive congestion: exit if it occurs, to protect */
100 /* other users of the network. */
101 fract_lost = (r->fract_lost * 100.0) / 256.0; /* percentage lost packets */
102 if (fract_lost > 20) {
103 printf("Receiver 0x%08x reports excessive congestion\n",
104 e->ssrc);
105 }
106
107 /* Compute network round-trip time: */
108 if (r->lsr != 0) {
109 ntp64_time(&ntp_sec, &ntp_frac);
110 now = ntp64_to_ntp32(ntp_sec, ntp_frac);
111
112 if ((now < r->lsr) || (now - r->lsr < r->dlsr)) {
113 /* Packet arrived before it was sent, ignore. This represents */
114 /* a bug in the remote: either our timestamp was incorrectly */
115 /* echoed back to us, or the remote miscalculated in time for */
116 /* which it held the packet. */
117 debug_msg("Bogus RTT from 0x%08x ignored\n",
118 e->ssrc);
119 } else {
120 tmp = ((float)(now - r->lsr - r->dlsr)) / 65536.0; /* RTT in seconds */
121 RTT = tmp * 1000000; /* RTT in usec */
122 }
123 //debug_msg(" RTT=%d usec\n", RTT);
124 }
125
126 int packet_count = 1;
127 const rtcp_rr *last_rr = rtp_get_rr(session, e->ssrc, r->ssrc);
128 if(last_rr){
129 packet_count = (r->last_seq - last_rr->last_seq);
130 }
131 if(packet_count < 1) packet_count = 1;
132
134 "RR of 0x%08x: RTT=%d usec, loss %.2f%% (of %d pkts)\n",
135 r->ssrc, RTT, fract_lost, packet_count);
136 }
137}
138
139static void
140process_sdes(struct pdb *participants, uint32_t ssrc, rtcp_sdes_item * d)
141{
142 struct pdb_e *e;
143 char *sdes_item;
144
145 e = pdb_get(participants, ssrc);
146 if (e == NULL) {
147 /* We got an SDES packet for a participant we haven't previously seen. */
148 /* This can happen, for example, in a partitioned multicast group. Log */
149 /* the event, and add the new participant to the database. */
151 ("Added previously unseen participant 0x%08" PRIx32 " due to receipt of SDES\n",
152 ssrc);
153 pdb_add(participants, ssrc);
154 e = pdb_get(participants, ssrc);
155 }
156
157 sdes_item = calloc(d->length + 1, 1);
158 strncpy(sdes_item, d->data, d->length);
159
160 switch (d->type) {
161 case RTCP_SDES_END:
162 free(sdes_item);
163 /* This is the end of the SDES list of a packet. */
164 /* Nothing for us to deal with. */
165 break;
166 case RTCP_SDES_CNAME:
167 if (e->sdes_cname != NULL)
168 free(e->sdes_cname);
169 e->sdes_cname = sdes_item;
170 break;
171 case RTCP_SDES_NAME:
172 if (e->sdes_name != NULL)
173 free(e->sdes_name);
174 e->sdes_name = sdes_item;
175 break;
176 case RTCP_SDES_EMAIL:
177 if (e->sdes_email != NULL)
178 free(e->sdes_email);
179 e->sdes_email = sdes_item;
180 break;
181 case RTCP_SDES_PHONE:
182 if (e->sdes_phone != NULL)
183 free(e->sdes_phone);
184 e->sdes_phone = sdes_item;
185 break;
186 case RTCP_SDES_LOC:
187 if (e->sdes_loc != NULL)
188 free(e->sdes_loc);
189 e->sdes_loc = sdes_item;
190 break;
191 case RTCP_SDES_TOOL:
192 if (e->sdes_tool != NULL)
193 free(e->sdes_tool);
194 e->sdes_tool = sdes_item;
195 break;
196 case RTCP_SDES_NOTE:
197 if (e->sdes_note != NULL)
198 free(e->sdes_note);
199 e->sdes_note = sdes_item;
200 break;
201 case RTCP_SDES_PRIV:
202 free(sdes_item);
203 break; /* Ignore private extensions */
204 default:
205 free(sdes_item);
207 ("Ignored unknown SDES item (type=0x%02" PRIx32 ") from 0x%08" PRIx32"\n",
208 d->type, ssrc);
209 }
210}
211
212void rtp_recv_callback(struct rtp *session, rtp_event * e)
213{
214 rtcp_app *pckt_app = (rtcp_app *) e->data;
215 rtp_packet *pckt_rtp = (rtp_packet *) e->data;
216 struct pdb *participants = (struct pdb *)rtp_get_userdata(session);
217 struct pdb_e *state = pdb_get(participants, e->ssrc);
218
219 switch (e->type) {
220 case RX_RTP:
221 tfrc_recv_data(state->tfrc_state, get_time_in_ns(), pckt_rtp->seq,
222 pckt_rtp->data_len + 40);
223 if (pckt_rtp->data_len > 0) { /* Only process packets that contain data... */
224 pbuf_insert(state->playout_buffer, pckt_rtp);
225 }
226 break;
227 case RX_TFRC_RX:
228 /* compute TCP friendly data rate */
229 break;
230 case RX_RTCP_START:
231 break;
232 case RX_RTCP_FINISH:
233 break;
234 case RX_SR:
235 break;
236 case RX_RR:
237 process_rr(session, e);
238 break;
239 case RX_RR_EMPTY:
240 break;
241 case RX_SDES:
242 process_sdes(participants, e->ssrc, (rtcp_sdes_item *) e->data);
243 break;
244 case RX_APP:
245 if (strncmp(pckt_app->name, "RTT_", 4) == 0) {
246 assert(pckt_app->length == 3);
247 assert(pckt_app->subtype == 0);
248// tfrc_recv_rtt(state->tfrc_state, get_time_in_ns(), ntohl(*((int *) pckt_app->data)));
249 }
250 break;
251 case RX_BYE:
252 break;
253 case SOURCE_DELETED:
254 {
255 struct pdb_e *pdb_item = NULL;
256 if(pdb_remove(participants, e->ssrc, &pdb_item) == 0) {
257 pdb_destroy_item(pdb_item);
258 }
259 }
260 break;
261 case SOURCE_CREATED:
262 pdb_add(participants, e->ssrc);
263 break;
264 case RR_TIMEOUT:
265 break;
266 default:
267 debug_msg("Unknown RTP event (type=%d)\n", e->type);
268 }
269}
270
void ** state
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define debug_msg(...)
#define debug_msg(...) log_msg(LOG_LEVEL_DEBUG, "[pid/%d +%d %s] ", getpid(), LINE,...
Definition debug.h:92
void ntp64_time(uint32_t *ntp_sec, uint32_t *ntp_frac)
Definition ntp.c:26
#define ntp64_to_ntp32(ntp_sec, ntp_frac)
Definition ntp.h:23
void pbuf_insert(struct pbuf *playout_buf, rtp_packet *pkt)
Definition pbuf.c:420
int pdb_add(struct pdb *db, uint32_t ssrc)
Definition pdb.c:299
void pdb_destroy_item(struct pdb_e *item)
Definition pdb.c:370
int pdb_remove(struct pdb *db, uint32_t ssrc, struct pdb_e **item)
Definition pdb.c:346
struct pdb_e * pdb_get(struct pdb *db, uint32_t ssrc)
Definition pdb.c:332
const rtcp_rr * rtp_get_rr(struct rtp *session, uint32_t reporter, uint32_t reportee)
Definition rtp.c:2707
uint32_t rtp_my_ssrc(struct rtp *session)
Definition rtp.c:1401
uint8_t * rtp_get_userdata(struct rtp *session)
Definition rtp.c:1386
@ RTCP_SDES_NOTE
Definition rtp.h:216
@ RTCP_SDES_CNAME
Definition rtp.h:210
@ RTCP_SDES_PHONE
Definition rtp.h:213
@ RTCP_SDES_TOOL
Definition rtp.h:215
@ RTCP_SDES_LOC
Definition rtp.h:214
@ RTCP_SDES_EMAIL
Definition rtp.h:212
@ RTCP_SDES_END
Definition rtp.h:209
@ RTCP_SDES_NAME
Definition rtp.h:211
@ RTCP_SDES_PRIV
Definition rtp.h:217
rtp_packet
Definition rtp.h:126
@ RX_RTP
Definition rtp.h:180
@ RR_TIMEOUT
Definition rtp.h:192
@ RX_SDES
Definition rtp.h:185
@ RX_APP
Definition rtp.h:193
@ RX_RTCP_START
Definition rtp.h:190
@ RX_TFRC_RX
Definition rtp.h:184
@ RX_SR
Definition rtp.h:182
@ SOURCE_CREATED
Definition rtp.h:187
@ RX_RTCP_FINISH
Definition rtp.h:191
@ SOURCE_DELETED
Definition rtp.h:188
@ RX_RR_EMPTY
Definition rtp.h:189
@ RX_BYE
Definition rtp.h:186
@ RX_RR
Definition rtp.h:183
uint32_t RTT
Definition host.cpp:171
struct iovec iov[10]
void rtp_recv_callback(struct rtp *session, rtp_event *e)
char hdr_buf[100]
char * frame
static void process_sdes(struct pdb *participants, uint32_t ssrc, rtcp_sdes_item *d)
static void process_rr(struct rtp *session, rtp_event *e)
Definition pdb.h:72
char * sdes_name
Definition pdb.h:75
char * sdes_loc
Definition pdb.h:78
char * sdes_note
Definition pdb.h:80
char * sdes_tool
Definition pdb.h:79
char * sdes_email
Definition pdb.h:76
uint32_t ssrc
Definition pdb.h:73
char * sdes_phone
Definition pdb.h:77
char * sdes_cname
Definition pdb.h:74
Definition pdb.c:84
unsigned short subtype
Definition rtp.h:165
char name[4]
Definition rtp.h:174
uint16_t length
Definition rtp.h:172
Definition rtp.h:139
uint32_t lsr
Definition rtp.h:150
uint32_t dlsr
Definition rtp.h:151
uint32_t fract_lost
Definition rtp.h:142
uint32_t ssrc
Definition rtp.h:140
uint32_t last_seq
Definition rtp.h:148
uint8_t type
Definition rtp.h:221
uint8_t length
Definition rtp.h:222
char data[1]
Definition rtp.h:223
rtp_event_type type
Definition rtp.h:199
uint32_t ssrc
Definition rtp.h:198
void * data
Definition rtp.h:200
Definition rtp.c:274
void tfrc_recv_data(struct tfrc *state, time_ns_t curr_time, uint16_t seqnum, unsigned length)
Definition tfrc.c:436
static time_ns_t get_time_in_ns()
Definition tv.h:101