source: mediastreamer2/src/msrtp.c @ 905:26898a4fad44

Last change on this file since 905:26898a4fad44 was 905:26898a4fad44, checked in by Simon Morlat <simon.morlat@…>, 3 years ago

improve tracing, try to fix specfile.

File size: 11.9 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        uint32_t tsoff;
33        uint32_t skip_until;
34        int rate;
35        char dtmf;
36        bool_t dtmf_start;
37        int dtmf_duration;
38        char relay_session_id[64];
39        int relay_session_id_size;
40        uint64_t 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->tsoff = 0;
53        d->skip_until = 0;
54        d->skip = FALSE;
55        d->rate = 8000;
56        d->dtmf = 0;
57        d->dtmf_start = FALSE;
58        d->dtmf_duration = 800;
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        if (d->skip==TRUE)
79        {
80                ms_filter_unlock(f);
81                return -1;
82        }
83        d->dtmf = dtmf[0];
84        ms_filter_unlock(f);
85        return 0;
86}
87
88static int sender_set_dtmf_duration(MSFilter * f, void *arg)
89{
90        SenderData *d = (SenderData *) f->data;
91        d->dtmf_duration = *((int*)arg);
92        return 0;
93}
94
95static int sender_set_session(MSFilter * f, void *arg)
96{
97        SenderData *d = (SenderData *) f->data;
98        RtpSession *s = (RtpSession *) arg;
99        PayloadType *pt =
100                rtp_profile_get_payload(rtp_session_get_profile(s),
101                                                                rtp_session_get_send_payload_type(s));
102        if (pt != NULL) {
103                if (strcasecmp("g722", pt->mime_type)==0 )
104                        d->rate=8000;
105                else d->rate = pt->clock_rate;
106        } else {
107                ms_warning("Sending undefined payload type ?");
108        }
109        d->session = s;
110        return 0;
111}
112
113static int sender_mute_mic(MSFilter * f, void *arg)
114{
115        SenderData *d = (SenderData *) f->data;
116        ms_filter_lock(f);
117        d->mute_mic=TRUE;
118        ms_filter_unlock(f);
119        return 0;
120}
121
122static int sender_unmute_mic(MSFilter * f, void *arg)
123{
124        SenderData *d = (SenderData *) f->data;
125        ms_filter_lock(f);
126        d->mute_mic=FALSE;
127        ms_filter_unlock(f);
128        return 0;
129}
130
131static int sender_set_relay_session_id(MSFilter *f, void*arg){
132        SenderData *d = (SenderData *) f->data;
133        const char *tmp=(const char *)arg;
134        d->relay_session_id_size=b64_decode(tmp, strlen(tmp), (void*)d->relay_session_id, (unsigned int)sizeof(d->relay_session_id));
135        return 0;
136}
137
138static int sender_get_sr(MSFilter *f, void *arg){
139        SenderData *d = (SenderData *) f->data;
140        *(int*)arg=d->rate;
141        return 0;
142}
143
144/* 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*/
145static uint32_t get_cur_timestamp(MSFilter * f, uint32_t packet_ts)
146{
147        SenderData *d = (SenderData *) f->data;
148        uint32_t curts = (uint32_t)( (f->ticker->time*(uint64_t)d->rate)/(uint64_t)1000) ;
149        int diff;
150        int delta = d->rate / 50;       /*20 ms at 8000Hz */
151        uint32_t netts;
152
153        netts = packet_ts + d->tsoff;
154        diff = curts - netts;
155
156#ifdef AMD_HACK
157        if (diff > delta) {
158                d->tsoff = curts - packet_ts;
159                netts = packet_ts + d->tsoff;
160                ms_message("synchronizing timestamp, diff=%i", diff);
161        }
162        else if (diff < -delta) {
163                /* d->tsoff = curts - packet_ts; */
164                /* hardware clock is going slower than sound card on my PDA... */
165        }
166#else
167        if ((diff > delta) || (diff < -(delta * 5))) {
168                d->tsoff = curts - packet_ts;
169                netts = packet_ts + d->tsoff;
170                ms_message("synchronizing timestamp, diff=%i", diff);
171        }
172#endif
173
174        /*ms_message("returned ts=%u, orig_ts=%u",netts,packet_ts); */
175        return netts;
176}
177
178static int send_dtmf(MSFilter * f, uint32_t timestamp_start, uint32_t current_timestamp)
179{
180        SenderData *d = (SenderData *) f->data;
181        mblk_t *m1;
182        int tev_type;
183
184        /* create the first telephony event packet */
185        switch (d->dtmf){
186                case '1':
187                        tev_type=TEV_DTMF_1;
188                break;
189                case '2':
190                        tev_type=TEV_DTMF_2;
191                break;
192                case '3':
193                        tev_type=TEV_DTMF_3;
194                break;
195                case '4':
196                        tev_type=TEV_DTMF_4;
197                break;
198                case '5':
199                        tev_type=TEV_DTMF_5;
200                break;
201                case '6':
202                        tev_type=TEV_DTMF_6;
203                break;
204                case '7':
205                        tev_type=TEV_DTMF_7;
206                break;
207                case '8':
208                        tev_type=TEV_DTMF_8;
209                break;
210                case '9':
211                        tev_type=TEV_DTMF_9;
212                break;
213                case '*':
214                        tev_type=TEV_DTMF_STAR;
215                break;
216                case '0':
217                        tev_type=TEV_DTMF_0;
218                break;
219                case '#':
220                        tev_type=TEV_DTMF_POUND;
221                break;
222
223                case 'A':
224                case 'a':
225                  tev_type=TEV_DTMF_A;
226                  break;
227
228
229                case 'B':
230                case 'b':
231                  tev_type=TEV_DTMF_B;
232                  break;
233
234                case 'C':
235                case 'c':
236                  tev_type=TEV_DTMF_C;
237                  break;
238
239                case 'D':
240                case 'd':
241                  tev_type=TEV_DTMF_D;
242                  break;
243
244                case '!':
245                  tev_type=TEV_FLASH;
246                  break;
247
248
249                default:
250                ms_warning("Bad dtmf: %c.",d->dtmf);
251                return -1;
252        }
253
254
255        if (d->dtmf_start == TRUE)
256                m1=rtp_session_create_telephone_event_packet(d->session,1);
257        else
258                m1=rtp_session_create_telephone_event_packet(d->session,0);
259        if (m1==NULL) return -1;
260
261
262        if (RTP_TIMESTAMP_IS_NEWER_THAN(current_timestamp, d->skip_until)) {
263                //retransmit end of rtp dtmf event
264                mblk_t *tmp;
265                rtp_session_add_telephone_event(d->session,m1,tev_type,1,10, (current_timestamp-timestamp_start));
266                tmp=copymsg(m1);
267                rtp_session_sendm_with_ts(d->session,tmp,timestamp_start);
268                d->session->rtp.snd_seq--;
269                tmp=copymsg(m1);
270                rtp_session_sendm_with_ts(d->session,tmp,timestamp_start);
271                d->session->rtp.snd_seq--;
272                rtp_session_sendm_with_ts(d->session,m1,timestamp_start);
273        }
274        else {
275                rtp_session_add_telephone_event(d->session,m1,tev_type,0,10, (current_timestamp-timestamp_start));
276                rtp_session_sendm_with_ts(d->session,m1,timestamp_start);
277        }
278        return 0;
279}
280
281static void sender_process(MSFilter * f)
282{
283        SenderData *d = (SenderData *) f->data;
284        RtpSession *s = d->session;
285
286        mblk_t *im;
287        uint32_t timestamp;
288
289        if (s == NULL){
290                ms_queue_flush(f->inputs[0]);
291                return;
292        }
293
294        if (d->relay_session_id_size>0 && 
295                ( (f->ticker->time-d->last_rsi_time)>5000 || d->last_rsi_time==0) ) {
296                ms_message("relay session id sent in RTCP APP");
297                rtp_session_send_rtcp_APP(s,0,"RSID",(const uint8_t *)d->relay_session_id,d->relay_session_id_size);
298                d->last_rsi_time=f->ticker->time;
299        }
300
301        while ((im = ms_queue_get(f->inputs[0])) != NULL) {
302                mblk_t *header;
303
304                timestamp = get_cur_timestamp(f, mblk_get_timestamp_info(im));
305                ms_filter_lock(f);
306                if (d->skip) {
307                        ms_debug("skipping..");
308                        send_dtmf(f, d->skip_until-d->dtmf_duration, timestamp);
309                        d->dtmf_start = FALSE;
310                        if (!RTP_TIMESTAMP_IS_NEWER_THAN(timestamp, d->skip_until)) {
311                                freemsg(im);
312                                ms_filter_unlock(f);
313                                continue;
314                        }
315                        d->skip = FALSE;
316                        d->dtmf = 0;
317                }
318
319                if (d->skip == FALSE && d->mute_mic==FALSE){
320                        int pt = mblk_get_payload_type(im);
321                        header = rtp_session_create_packet(s, 12, NULL, 0);
322                        if (pt>0)
323                                rtp_set_payload_type(header, pt);
324                        rtp_set_markbit(header, mblk_get_marker_info(im));
325                        header->b_cont = im;
326                        rtp_session_sendm_with_ts(s, header, timestamp);
327                }
328                else{
329                        freemsg(im);
330                }
331
332                if (d->dtmf != 0) {
333                        ms_debug("prepare to send RFC2833 dtmf.");
334                        d->skip_until = timestamp + d->dtmf_duration;
335                        d->skip = TRUE;
336                        d->dtmf_start = TRUE;
337                }
338                ms_filter_unlock(f);
339        }
340}
341
342static MSFilterMethod sender_methods[] = {
343        {MS_RTP_SEND_MUTE_MIC, sender_mute_mic},
344        {MS_RTP_SEND_UNMUTE_MIC, sender_unmute_mic},
345        {MS_RTP_SEND_SET_SESSION, sender_set_session},
346        {MS_RTP_SEND_SEND_DTMF, sender_send_dtmf},
347        {MS_RTP_SEND_SET_RELAY_SESSION_ID, sender_set_relay_session_id},
348        {MS_FILTER_GET_SAMPLE_RATE, sender_get_sr },
349        {MS_RTP_SEND_SET_DTMF_DURATION, sender_set_dtmf_duration },
350        {0, NULL}
351};
352
353#ifdef _MSC_VER
354
355MSFilterDesc ms_rtp_send_desc = {
356        MS_RTP_SEND_ID,
357        "MSRtpSend",
358        N_("RTP output filter"),
359        MS_FILTER_OTHER,
360        NULL,
361        1,
362        0,
363        sender_init,
364        NULL,
365        sender_process,
366        NULL,
367        sender_uninit,
368        sender_methods
369};
370
371#else
372
373MSFilterDesc ms_rtp_send_desc = {
374        .id = MS_RTP_SEND_ID,
375        .name = "MSRtpSend",
376        .text = N_("RTP output filter"),
377        .category = MS_FILTER_OTHER,
378        .ninputs = 1,
379        .noutputs = 0,
380        .init = sender_init,
381        .process = sender_process,
382        .uninit = sender_uninit,
383        .methods = sender_methods
384};
385
386#endif
387
388struct ReceiverData {
389        RtpSession *session;
390        int rate;
391};
392
393typedef struct ReceiverData ReceiverData;
394
395static void receiver_init(MSFilter * f)
396{
397        ReceiverData *d = (ReceiverData *)ms_new(ReceiverData, 1);
398        d->session = NULL;
399        d->rate = 8000;
400        f->data = d;
401}
402
403static void receiver_postprocess(MSFilter * f){
404        /*ReceiverData *d = (ReceiverData *) f->data;*/
405}
406
407static void receiver_uninit(MSFilter * f){
408        ReceiverData *d = (ReceiverData *) f->data;
409        ms_free(d);
410}
411
412static int receiver_set_session(MSFilter * f, void *arg)
413{
414        ReceiverData *d = (ReceiverData *) f->data;
415        RtpSession *s = (RtpSession *) arg;
416        PayloadType *pt = rtp_profile_get_payload(rtp_session_get_profile(s),
417                                                                                          rtp_session_get_recv_payload_type
418                                                                                          (s));
419        if (pt != NULL) {
420                if (strcasecmp("g722", pt->mime_type)==0 )
421                        d->rate=8000;
422                else d->rate = pt->clock_rate;
423        } else {
424                ms_warning("Receiving undefined payload type %i ?",
425                    rtp_session_get_recv_payload_type(s));
426        }
427        d->session = s;
428
429        return 0;
430}
431
432static int receiver_get_sr(MSFilter *f, void *arg){
433        ReceiverData *d = (ReceiverData *) f->data;
434        PayloadType *pt;
435        if (d->session==NULL) {
436                ms_warning("Could not obtain sample rate, session is not set.");
437                return -1;
438        }
439        pt=rtp_profile_get_payload(rtp_session_get_profile(d->session),
440                                                                        rtp_session_get_recv_payload_type(d->session));
441        if (pt != NULL) {
442                *(int*)arg=pt->clock_rate;
443        }else{
444                ms_warning("Could not obtain sample rate, payload type is unknown.");
445                return -1;
446        }
447        return 0;
448}
449
450static void receiver_preprocess(MSFilter * f){
451        ReceiverData *d = (ReceiverData *) f->data;
452        if (d->session){
453                PayloadType *pt=rtp_profile_get_payload(
454                        rtp_session_get_profile(d->session),
455                        rtp_session_get_recv_payload_type(d->session));
456                if (pt){
457                        if (pt->type!=PAYLOAD_VIDEO)
458                                rtp_session_flush_sockets(d->session);
459                }
460        }
461}
462
463static void receiver_process(MSFilter * f)
464{
465        ReceiverData *d = (ReceiverData *) f->data;
466        mblk_t *m;
467        uint32_t timestamp;
468
469        if (d->session == NULL)
470                return;
471
472        timestamp = (uint32_t) (f->ticker->time * (d->rate/1000));
473        while ((m = rtp_session_recvm_with_ts(d->session, timestamp)) != NULL) {
474                mblk_set_timestamp_info(m, rtp_get_timestamp(m));
475                mblk_set_marker_info(m, rtp_get_markbit(m));
476                mblk_set_payload_type(m, rtp_get_payload_type(m));
477                rtp_get_payload(m,&m->b_rptr);
478                ms_queue_put(f->outputs[0], m);
479        }
480}
481
482static MSFilterMethod receiver_methods[] = {
483        {       MS_RTP_RECV_SET_SESSION , receiver_set_session  },
484        {       MS_FILTER_GET_SAMPLE_RATE       , receiver_get_sr               },
485        {       0, NULL}
486};
487
488#ifdef _MSC_VER
489
490MSFilterDesc ms_rtp_recv_desc = {
491        MS_RTP_RECV_ID,
492        "MSRtpRecv",
493        N_("RTP input filter"),
494        MS_FILTER_OTHER,
495        NULL,
496        0,
497        1,
498        receiver_init,
499        receiver_preprocess,
500        receiver_process,
501        receiver_postprocess,
502        receiver_uninit,
503        receiver_methods
504};
505
506#else
507
508MSFilterDesc ms_rtp_recv_desc = {
509        .id = MS_RTP_RECV_ID,
510        .name = "MSRtpRecv",
511        .text = N_("RTP input filter"),
512        .category = MS_FILTER_OTHER,
513        .ninputs = 0,
514        .noutputs = 1,
515        .init = receiver_init,
516        .preprocess = receiver_preprocess,
517        .process = receiver_process,
518        .postprocess=receiver_postprocess,
519        .uninit = receiver_uninit,
520        .methods = receiver_methods
521};
522
523#endif
524
525MS_FILTER_DESC_EXPORT(ms_rtp_send_desc)
526MS_FILTER_DESC_EXPORT(ms_rtp_recv_desc)
Note: See TracBrowser for help on using the repository browser.