root/rat/trunk/rtp_callback.c @ 3128

Revision 3128, 10.0 KB (checked in by ucacoxh, 14 years ago)

- Remove debug message.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * FILE:    rtp_callback.c
3 * PROGRAM: RAT
4 * AUTHOR:  Colin Perkins / Orion Hodson
5 *
6 * Copyright (c) 1999-2000 University College London
7 * All rights reserved.
8 */
9 
10#ifndef HIDE_SOURCE_STRINGS
11static const char cvsid[] =
12        "$Id$";
13#endif /* HIDE_SOURCE_STRINGS */
14
15#include "config_unix.h"
16#include "config_win32.h"
17#include "debug.h"
18#include "audio_types.h"
19#include "auddev.h"
20#include "channel.h"
21#include "codec.h"
22#include "rtp.h"
23#include "ntp.h"
24#include "session.h"
25#include "cushion.h"
26#include "pdb.h"
27#include "source.h"
28#include "playout_calc.h"
29#include "util.h"
30#include "ui.h"
31
32#include "rtp_callback.h"
33
34/* We need to be able to resolve the rtp session to a rat session in */
35/* order to get persistent participant information, etc.  We use a   */
36/* double linked list with sentinel for this.  We normally don't     */
37/* expect to have more than 2 sessions (i.e. transcoder mode), but   */
38/* layered codecs may require more.                                  */
39
40typedef struct s_rtp_assoc {
41        struct s_rtp_assoc *next;
42        struct s_rtp_assoc *prev;
43        struct rtp         *rtps;
44        struct s_session   *rats;
45} rtp_assoc_t;
46
47/* Sentinel for linked list that is used as small associative array */
48static rtp_assoc_t rtp_as;
49static int rtp_as_inited;
50
51void 
52rtp_callback_init(struct rtp *rtps, struct s_session *rats)
53{
54        rtp_assoc_t *cur, *sentinel;
55
56        if (!rtp_as_inited) {
57                /* First pass sentinel initialization */
58                rtp_as.next = &rtp_as;
59                rtp_as.prev = &rtp_as;
60                rtp_as_inited = 1;
61        }
62
63        sentinel = &rtp_as;
64        cur   = sentinel->next;
65
66        while (cur != sentinel) {
67                if (cur->rtps == rtps) {
68                        /* Association already exists, over-riding */
69                        cur->rats = rats;
70                        return;
71                }
72        }
73
74        cur = (rtp_assoc_t*)xmalloc(sizeof(rtp_assoc_t));
75        cur->rtps   = rtps;
76        cur->rats   = rats;
77
78        cur->next       = sentinel->next;
79        cur->prev       = sentinel;
80        cur->next->prev = cur;
81        cur->prev->next = cur;
82}
83
84void rtp_callback_exit(struct rtp *rtps)
85{
86        rtp_assoc_t *cur, *sentinel;
87       
88        sentinel = &rtp_as;
89        cur = sentinel->next;
90        while(cur != sentinel) {
91                if (cur->rtps == rtps) {
92                        cur->prev->next = cur->next;
93                        cur->next->prev = cur->prev;
94                        xfree(cur);
95                        return;
96                }
97                cur = cur->next;
98        }
99}
100
101/* get_session maps an rtp_session to a rat session */
102static struct s_session *
103get_session(struct rtp *rtps)
104{
105        rtp_assoc_t *cur, *sentinel;
106
107        if (!rtp_as_inited) {
108                return NULL;
109        }
110       
111        sentinel = &rtp_as;
112        cur = sentinel->next;
113        while(cur != sentinel) {
114                if (cur->rtps == rtps) {
115                        return cur->rats;
116                }
117                cur = cur->next;
118        }       
119        return NULL;
120}
121
122/* Callback utility functions                                                */
123
124/* rtp_rtt_calc return rtt estimate in seconds */
125static double 
126rtp_rtt_calc(uint32_t arr, uint32_t dep, uint32_t delay)
127{
128        uint32_t delta;
129
130        /* rtt = arr - dep - delay */
131        delta = ntp32_sub(arr,   dep);
132        delta = ntp32_sub(delta, delay);
133        /*
134         * 16 high order bits are seconds
135         * 16 low order bits are 1/65536 of sec
136         */
137        return  (double)((delta >> 16) & 0xffff) +
138                (double)(delta & 0xffff) / 65536.0;
139}
140
141static void
142process_rtp_data(session_t *sp, uint32_t ssrc, rtp_packet *p)
143{
144        struct s_source *s;
145        pdb_entry_t     *e;
146
147        if (sp->filter_loopback && ssrc == rtp_my_ssrc(sp->rtp_session[0])) {
148                /* This packet is from us and we are filtering our own       */
149                /* packets.                                                  */
150                xfree(p);
151                return;
152        }
153
154        if (pdb_item_get(sp->pdb, ssrc, &e) == FALSE) {
155                debug_msg("Packet discarded: unknown source (0x%08x).\n", ssrc);
156                xfree(p);
157                return;
158        }
159        e->received++;
160       
161        s = source_get_by_ssrc(sp->active_sources, ssrc);
162        if (s == NULL) {
163                s = source_create(sp->active_sources, ssrc, sp->pdb);
164                ui_info_activate(sp, ssrc);
165                debug_msg("Source created\n");
166        }
167
168        /* Calculate the relative playout delay, for this source. Needed for lip-sync. */
169
170        /* Discard packet if output is muted... no point wasting time decoding it... */
171        if ((sp->playing_audio == FALSE) || (e->mute)) {
172                debug_msg("Packet discarded since output muted\n");
173                xfree(p);
174                return;
175        }
176
177        /* Remove any padding */
178        if (p->p) {
179                p->data_len -= p->data[p->data_len - 1];
180                p->p = 0;
181        }
182        source_add_packet(s, p);
183}
184
185static void
186process_rr(session_t *sp, uint32_t ssrc, rtcp_rr *r)
187{
188        pdb_entry_t  *e;
189        uint32_t fract_lost, my_ssrc;
190
191        /* Calculate rtt estimate */
192        my_ssrc =  rtp_my_ssrc(sp->rtp_session[0]);
193        if (r->ssrc == my_ssrc &&
194            r->ssrc != ssrc    && /* filter self reports */
195            pdb_item_get(sp->pdb, ssrc, &e) &&
196            r->lsr != 0) {
197                uint32_t ntp_sec, ntp_frac, ntp32;
198                double rtt;
199                ntp64_time(&ntp_sec, &ntp_frac);
200                ntp32 = ntp64_to_ntp32(ntp_sec, ntp_frac);
201               
202                rtt = rtp_rtt_calc(ntp32, r->lsr, r->dlsr);
203                /*
204                 * Filter out blatantly wrong rtt values.  Some tools might not
205                 * implement dlsr and lsr (broken) or forget to do byte-swapping (grr)
206                 */
207                if (rtt < 100.0) {
208                        e->last_rtt = rtt;
209                } else {
210                        debug_msg("Junk rtt (%f secs) - receiver rtp misimplementation?\n");
211                }
212                if (e->avg_rtt == 0.0) {
213                        e->avg_rtt = e->last_rtt;
214                } else {
215                        e->avg_rtt += (e->last_rtt - e->avg_rtt) / 8.0;
216                }
217                if (sp->mbus_engine != NULL) {
218                        ui_update_rtt(sp, ssrc, e->avg_rtt);
219                }
220        }
221
222        /* Update loss stats */
223        if (sp->mbus_engine != NULL) {
224                fract_lost = (r->fract_lost * 100) >> 8;
225                ui_update_loss(sp, ssrc, r->ssrc, fract_lost);
226        }
227}
228
229static void
230process_rr_timeout(session_t *sp, uint32_t ssrc, rtcp_rr *r)
231{
232        /* Just update loss statistic in UI for this report if there */
233        /* is somewhere to send them.                                */
234        if (sp->mbus_engine != NULL) {
235                ui_update_loss(sp, ssrc, r->ssrc, 101);
236        }
237}
238
239static void
240process_sdes(session_t *sp, uint32_t ssrc, rtcp_sdes_item *d)
241{
242        pdb_entry_t *e;
243
244        assert(pdb_item_get(sp->pdb, ssrc, &e) == TRUE);
245
246        if (sp->mbus_engine == NULL) {
247                /* Nowhere to send updates to, so ignore them.               */
248                return;
249        }
250
251        switch(d->type) {
252        case RTCP_SDES_END:
253                /* This is the end of the SDES list of a packet.  Nothing    */
254                /* for us to deal with.                                      */
255                break;
256        case RTCP_SDES_CNAME:
257                ui_info_update_cname(sp, ssrc);
258                break;
259        case RTCP_SDES_NAME:
260                ui_info_update_name(sp, ssrc);
261                break;
262        case RTCP_SDES_EMAIL:
263                ui_info_update_email(sp, ssrc);
264                break;
265        case RTCP_SDES_PHONE:
266                ui_info_update_phone(sp, ssrc);
267                break;
268        case RTCP_SDES_LOC:
269                ui_info_update_loc(sp, ssrc);
270                break;
271        case RTCP_SDES_TOOL:
272                ui_info_update_tool(sp, ssrc);
273                break;
274        case RTCP_SDES_NOTE:
275                ui_info_update_note(sp, ssrc);
276                break;
277        case RTCP_SDES_PRIV:
278                debug_msg("Discarding private data from (0x%08x)", ssrc);
279                break;
280        default:
281                debug_msg("Ignoring SDES type (0x%02x) from (0x%08x).\n", ssrc);
282        }
283}
284
285static void
286process_create(session_t *sp, uint32_t ssrc)
287{
288        if (pdb_item_create(sp->pdb, sp->clock, (uint16_t)get_freq(sp->device_clock), ssrc) == FALSE) {
289                debug_msg("Unable to create source 0x%08lx\n", ssrc);
290        }
291}
292
293static void
294process_delete(session_t *sp, uint32_t ssrc)
295{
296        if (ssrc != rtp_my_ssrc(sp->rtp_session[0]) &&
297            sp->mbus_engine != NULL) {
298                ui_info_remove(sp, ssrc);
299        }
300}
301
302void 
303rtp_callback(struct rtp *s, rtp_event *e)
304{
305        struct s_session *sp;
306       
307        assert(s != NULL);
308        assert(e != NULL);
309
310        sp = get_session(s);
311        if (sp == NULL) {
312                /* Should only happen when SOURCE_CREATED is generated in */
313                /* rtp_init.                                              */
314                debug_msg("Could not find session (0x%08x)\n", (uint32_t)s);
315                return;
316        }
317
318        switch (e->type) {
319        case RX_RTP:
320                process_rtp_data(sp, e->ssrc, (rtp_packet*)e->data);
321                break;
322        case RX_RTCP_START:
323                break;
324        case RX_RTCP_FINISH:
325                break;
326        case RX_SR:
327                break;
328        case RX_RR:
329                process_rr(sp, e->ssrc, (rtcp_rr*)e->data);
330                break;
331        case RX_RR_EMPTY:
332                break;
333        case RX_SDES:
334                process_sdes(sp, e->ssrc, (rtcp_sdes_item*)e->data);
335                break;
336        case RX_BYE:
337        case SOURCE_DELETED:
338                process_delete(sp, e->ssrc);
339                break;
340        case SOURCE_CREATED:
341                debug_msg("Source create (0x%08x)\n", e->ssrc);
342                process_create(sp, e->ssrc);
343                break;
344        case RR_TIMEOUT:
345                process_rr_timeout(sp, e->ssrc, (rtcp_rr*)e->data);
346                break;
347        default:
348                debug_msg("Unknown RTP event (type=%d)\n", e->type);
349                abort();
350        }
351}
Note: See TracBrowser for help on using the browser.