source: mediastreamer2/linphone/mediastreamer2/src/msrtp.c @ 147:d77374cdb9eb

Last change on this file since 147:d77374cdb9eb was 147:d77374cdb9eb, checked in by aymeric <aymeric@…>, 5 years ago

use macro: no change

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@150 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 10.3 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20#include "mediastreamer2/msrtp.h"
21#include "mediastreamer2/msticker.h"
22
23#include "ortp/telephonyevents.h"
24#if defined(__cplusplus)
25#define B64_NO_NAMESPACE
26#endif
27#include "ortp/b64.h"
28
29
30struct SenderData {
31        RtpSession *session;
32        struct CandidatePair *cpair;    /* table of 10 cpair */
33        int round;
34        uint32_t tsoff;
35        uint32_t skip_until;
36        int rate;
37        char dtmf;
38        char relay_session_id[64];
39        int relay_session_id_size;
40        unsigned int last_rsi_time;
41        bool_t skip;
42        bool_t mute_mic;
43};
44
45typedef struct SenderData SenderData;
46
47static void sender_init(MSFilter * f)
48{
49        SenderData *d = (SenderData *)ms_new(SenderData, 1);
50
51        d->session = NULL;
52        d->cpair = NULL;
53        d->round = 0;
54        d->tsoff = 0;
55        d->skip_until = 0;
56        d->skip = FALSE;
57        d->rate = 8000;
58        d->dtmf = 0;
59        d->mute_mic=FALSE;
60        d->relay_session_id_size=0;
61        d->last_rsi_time=0;
62        f->data = d;
63}
64
65static void sender_uninit(MSFilter * f)
66{
67        SenderData *d = (SenderData *) f->data;
68
69        ms_free(d);
70}
71
72static int sender_send_dtmf(MSFilter * f, void *arg)
73{
74        const char *dtmf = (const char *) arg;
75        SenderData *d = (SenderData *) f->data;
76
77        ms_filter_lock(f);
78        d->dtmf = dtmf[0];
79        ms_filter_unlock(f);
80        return 0;
81}
82
83static int sender_set_sdpcandidates(MSFilter * f, void *arg)
84{
85        SenderData *d = (SenderData *) f->data;
86        struct CandidatePair *scs = NULL;
87
88        if (d == NULL)
89                return -1;
90
91        scs = (struct CandidatePair *) arg;
92        d->cpair = scs;
93        return 0;
94}
95
96static int sender_set_session(MSFilter * f, void *arg)
97{
98        SenderData *d = (SenderData *) f->data;
99        RtpSession *s = (RtpSession *) arg;
100        PayloadType *pt =
101                rtp_profile_get_payload(rtp_session_get_profile(s),
102                                                                rtp_session_get_send_payload_type(s));
103        if (pt != NULL) {
104                d->rate = pt->clock_rate;
105        } else {
106                ms_warning("Sending undefined payload type ?");
107        }
108        d->session = s;
109        return 0;
110}
111
112static int sender_mute_mic(MSFilter * f, void *arg)
113{
114        SenderData *d = (SenderData *) f->data;
115        ms_filter_lock(f);
116        d->mute_mic=TRUE;
117        ms_filter_unlock(f);
118        return 0;
119}
120
121static int sender_unmute_mic(MSFilter * f, void *arg)
122{
123        SenderData *d = (SenderData *) f->data;
124        ms_filter_lock(f);
125        d->mute_mic=FALSE;
126        ms_filter_unlock(f);
127        return 0;
128}
129
130static int sender_set_relay_session_id(MSFilter *f, void*arg){
131        SenderData *d = (SenderData *) f->data;
132        const char *tmp=(const char *)arg;
133        d->relay_session_id_size=b64_decode(tmp, strlen(tmp), (void*)d->relay_session_id, (unsigned int)sizeof(d->relay_session_id));
134        return 0;
135}
136
137/* the goal of that function is to return a absolute timestamp closest to real time, with respect of given packet_ts, which is a relative to an undefined origin*/
138static uint32_t get_cur_timestamp(MSFilter * f, uint32_t packet_ts)
139{
140        SenderData *d = (SenderData *) f->data;
141#if !defined(_WIN32_WCE)
142        uint32_t curts = (f->ticker->time * d->rate) / 1000LL;
143#else
144        uint32_t curts = (f->ticker->time * d->rate) / ((uint64_t)1000);
145#endif
146        int diff;
147        int delta = d->rate / 50;       /*20 ms at 8000Hz */
148        uint32_t netts;
149
150        netts = packet_ts + d->tsoff;
151        diff = curts - netts;
152
153#ifdef AMD_HACK
154        if (diff > delta) {
155                d->tsoff = curts - packet_ts;
156                netts = packet_ts + d->tsoff;
157                ms_message("synchronizing timestamp, diff=%i", diff);
158        }
159        else if (diff < -delta) {
160                /* d->tsoff = curts - packet_ts; */
161                /* hardware clock is going slower than sound card on my PDA... */
162        }
163#else
164        if ((diff > delta) || (diff < -(delta * 5))) {
165                d->tsoff = curts - packet_ts;
166                netts = packet_ts + d->tsoff;
167                ms_message("synchronizing timestamp, diff=%i", diff);
168        }
169#endif
170
171        /*ms_message("returned ts=%u, orig_ts=%u",netts,packet_ts); */
172        return netts;
173}
174
175static void sender_process(MSFilter * f)
176{
177        SenderData *d = (SenderData *) f->data;
178        RtpSession *s = d->session;
179
180        struct CandidatePair *cp = d->cpair;
181        mblk_t *im;
182        uint32_t timestamp;
183
184        if (s == NULL){
185                ms_queue_flush(f->inputs[0]);
186                return;
187        }
188
189        if (d->relay_session_id_size>0 && 
190                ( (f->ticker->time-d->last_rsi_time)>5000 || d->last_rsi_time==0) ) {
191                ms_message("relay session id sent in RTCP APP");
192                rtp_session_send_rtcp_APP(s,0,"RSID",(const uint8_t *)d->relay_session_id,d->relay_session_id_size);
193                d->last_rsi_time=f->ticker->time;
194        }
195
196        while ((im = ms_queue_get(f->inputs[0])) != NULL) {
197                mblk_t *header;
198
199                timestamp = get_cur_timestamp(f, mblk_get_timestamp_info(im));
200                ms_filter_lock(f);
201                if (d->dtmf != 0) {
202                        rtp_session_send_dtmf(s, d->dtmf, timestamp);
203                        ms_debug("RFC2833 dtmf sent.");
204                        d->dtmf = 0;
205                        d->skip_until = timestamp + (3 * 160);
206                        d->skip = TRUE;
207                        freemsg(im);
208                }else if (d->skip) {
209                        ms_debug("skipping..");
210                        if (RTP_TIMESTAMP_IS_NEWER_THAN(timestamp, d->skip_until)) {
211                                d->skip = FALSE;
212                        }
213                        freemsg(im);
214                }else{
215                  if (d->mute_mic==FALSE)
216                    {
217                        int pt = mblk_get_payload_type(im);
218                        header = rtp_session_create_packet(s, 12, NULL, 0);
219                        if (pt>0)
220                                rtp_set_payload_type(header, pt);
221                        rtp_set_markbit(header, mblk_get_marker_info(im));
222                        header->b_cont = im;
223                        rtp_session_sendm_with_ts(s, header, timestamp);
224                    }
225                  else
226                    {
227                        freemsg(im);
228                    }
229                }
230                ms_filter_unlock(f);
231        }
232
233        /* regularly send STUN request */
234        ice_sound_send_stun_request(s, cp, d->round);
235        d->round++;
236}
237
238static MSFilterMethod sender_methods[] = {
239        {MS_RTP_SEND_MUTE_MIC, sender_mute_mic},
240        {MS_RTP_SEND_UNMUTE_MIC, sender_unmute_mic},
241        {MS_RTP_SEND_SET_SESSION, sender_set_session},
242        {MS_RTP_SEND_SEND_DTMF, sender_send_dtmf},
243        {MS_RTP_SEND_SET_CANDIDATEPAIRS, sender_set_sdpcandidates},
244        {MS_RTP_SEND_SET_RELAY_SESSION_ID, sender_set_relay_session_id},
245        {0, NULL}
246};
247
248#ifdef _MSC_VER
249
250MSFilterDesc ms_rtp_send_desc = {
251        MS_RTP_SEND_ID,
252        "MSRtpSend",
253        "RTP output filter",
254        MS_FILTER_OTHER,
255        NULL,
256        1,
257        0,
258        sender_init,
259        NULL,
260        sender_process,
261        NULL,
262        sender_uninit,
263        sender_methods
264};
265
266#else
267
268MSFilterDesc ms_rtp_send_desc = {
269        .id = MS_RTP_SEND_ID,
270        .name = "MSRtpSend",
271        .text = "RTP output filter",
272        .category = MS_FILTER_OTHER,
273        .ninputs = 1,
274        .noutputs = 0,
275        .init = sender_init,
276        .process = sender_process,
277        .uninit = sender_uninit,
278        .methods = sender_methods
279};
280
281#endif
282
283struct ReceiverData {
284        RtpSession *session;
285        OrtpEvQueue *ortp_event;
286        struct CandidatePair *cpair;    /* table of 10 cpair */
287        int rate;
288};
289
290typedef struct ReceiverData ReceiverData;
291
292static void receiver_init(MSFilter * f)
293{
294        ReceiverData *d = (ReceiverData *)ms_new(ReceiverData, 1);
295
296        d->ortp_event = ortp_ev_queue_new();
297        d->session = NULL;
298        d->cpair = NULL;
299        d->rate = 8000;
300        f->data = d;
301}
302
303static void receiver_postprocess(MSFilter * f)
304{
305        ReceiverData *d = (ReceiverData *) f->data;
306        if (d->session!=NULL && d->ortp_event!=NULL)
307          rtp_session_unregister_event_queue(d->session, d->ortp_event);
308}
309
310static void receiver_uninit(MSFilter * f)
311{
312        ReceiverData *d = (ReceiverData *) f->data;
313        if (d->ortp_event!=NULL)
314          ortp_ev_queue_destroy(d->ortp_event);
315        ms_free(f->data);
316}
317
318static int receiver_set_session(MSFilter * f, void *arg)
319{
320        ReceiverData *d = (ReceiverData *) f->data;
321        RtpSession *s = (RtpSession *) arg;
322        PayloadType *pt = rtp_profile_get_payload(rtp_session_get_profile(s),
323                                                                                          rtp_session_get_recv_payload_type
324                                                                                          (s));
325        if (pt != NULL) {
326                d->rate = pt->clock_rate;
327        } else {
328                ms_warning("Receiving undefined payload type ?");
329        }
330        d->session = s;
331
332        return 0;
333}
334
335static int receiver_set_sdpcandidates(MSFilter * f, void *arg)
336{
337        ReceiverData *d = (ReceiverData *) f->data;
338        struct CandidatePair *scs = NULL;
339
340        if (d == NULL)
341                return -1;
342
343        scs = (struct CandidatePair *) arg;
344        d->cpair = scs;
345        return 0;
346}
347
348static void receiver_preprocess(MSFilter * f){
349        ReceiverData *d = (ReceiverData *) f->data;
350        if (d->session){
351                PayloadType *pt=rtp_profile_get_payload(
352                        rtp_session_get_profile(d->session),
353                        rtp_session_get_recv_payload_type(d->session));
354                if (pt){
355                        if (pt->type!=PAYLOAD_VIDEO)
356                                rtp_session_flush_sockets(d->session);
357                }
358        }
359        if (d->session!=NULL && d->ortp_event!=NULL)
360                rtp_session_register_event_queue(d->session, d->ortp_event);
361}
362
363static void receiver_process(MSFilter * f)
364{
365        ReceiverData *d = (ReceiverData *) f->data;
366        mblk_t *m;
367        uint32_t timestamp;
368
369        if (d->session == NULL)
370                return;
371
372        timestamp = (f->ticker->time * d->rate) / ((uint64_t)1000);
373        while ((m = rtp_session_recvm_with_ts(d->session, timestamp)) != NULL) {
374                mblk_set_timestamp_info(m, rtp_get_timestamp(m));
375                mblk_set_marker_info(m, rtp_get_markbit(m));
376                mblk_set_payload_type(m, rtp_get_payload_type(m));
377                rtp_get_payload(m,&m->b_rptr);
378                ms_queue_put(f->outputs[0], m);
379        }
380
381        /* check received STUN request */
382        if (d->ortp_event!=NULL)
383        {
384                OrtpEvent *evt = ortp_ev_queue_get(d->ortp_event);
385
386                while (evt != NULL) {
387                        if (ortp_event_get_type(evt) ==
388                                ORTP_EVENT_STUN_PACKET_RECEIVED) {
389                                ice_process_stun_message(d->session, d->cpair, evt);
390                        }
391                        if (ortp_event_get_type(evt) ==
392                                ORTP_EVENT_TELEPHONE_EVENT) {
393                        }
394
395                        ortp_event_destroy(evt);
396                        evt = ortp_ev_queue_get(d->ortp_event);
397                }
398        }
399}
400
401static MSFilterMethod receiver_methods[] = {
402        {MS_RTP_RECV_SET_SESSION, receiver_set_session},
403        {MS_RTP_RECV_SET_CANDIDATEPAIRS, receiver_set_sdpcandidates},
404        {0, NULL}
405};
406
407#ifdef _MSC_VER
408
409MSFilterDesc ms_rtp_recv_desc = {
410        MS_RTP_RECV_ID,
411        "MSRtpRecv",
412        "RTP input filter",
413        MS_FILTER_OTHER,
414        NULL,
415        0,
416        1,
417        receiver_init,
418        receiver_preprocess,
419        receiver_process,
420        receiver_postprocess,
421        receiver_uninit,
422        receiver_methods
423};
424
425#else
426
427MSFilterDesc ms_rtp_recv_desc = {
428        .id = MS_RTP_RECV_ID,
429        .name = "MSRtpRecv",
430        .text = "RTP input filter",
431        .category = MS_FILTER_OTHER,
432        .ninputs = 0,
433        .noutputs = 1,
434        .init = receiver_init,
435        .preprocess = receiver_preprocess,
436        .process = receiver_process,
437        .postprocess=receiver_postprocess,
438        .uninit = receiver_uninit,
439        .methods = receiver_methods
440};
441
442#endif
443
444MS_FILTER_DESC_EXPORT(ms_rtp_send_desc)
445MS_FILTER_DESC_EXPORT(ms_rtp_recv_desc)
Note: See TracBrowser for help on using the repository browser.