msrtp.c 18.2 KB
Newer Older
aymeric's avatar
aymeric committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

Simon Morlat's avatar
Simon Morlat committed
20

aymeric's avatar
aymeric committed
21 22 23 24
#include "mediastreamer2/msrtp.h"
#include "mediastreamer2/msticker.h"

#include "ortp/telephonyevents.h"
aymeric's avatar
aymeric committed
25 26 27
#if defined(__cplusplus)
#define B64_NO_NAMESPACE
#endif
aymeric's avatar
aymeric committed
28
#include "ortp/b64.h"
jehan's avatar
jehan committed
29
#include "mediastreamer2/stun.h"
aymeric's avatar
aymeric committed
30

31
static const int default_dtmf_duration_ms=100; /*in milliseconds*/
aymeric's avatar
aymeric committed
32

aymeric's avatar
aymeric committed
33 34 35
struct SenderData {
	RtpSession *session;
	uint32_t tsoff;
36 37
	uint32_t last_ts;
	int64_t last_sent_time;
38
	int64_t last_stun_sent_time;
aymeric's avatar
aymeric committed
39 40
	uint32_t skip_until;
	int rate;
41
	int dtmf_duration;
42 43
	int dtmf_ts_step;
	uint32_t dtmf_ts_cur;
aymeric's avatar
aymeric committed
44 45
	char relay_session_id[64];
	int relay_session_id_size;
aymeric's avatar
aymeric committed
46
	uint64_t last_rsi_time;
47
	char dtmf;
Simon Morlat's avatar
Simon Morlat committed
48
	MSCngData cng_data;
49
	bool_t dtmf_start;
aymeric's avatar
aymeric committed
50
	bool_t skip;
51
	bool_t mute;
52
	bool_t use_task;
aymeric's avatar
aymeric committed
53 54 55 56
};

typedef struct SenderData SenderData;

57 58 59 60
/* Send dummy STUN packet to open NAT ports ASAP. */
static void send_stun_packet(RtpSession *s)
{
	StunMessage msg;
61
	mblk_t *mp;
62 63
	char buf[STUN_MAX_MESSAGE_SIZE];
	int len = STUN_MAX_MESSAGE_SIZE;
jehan's avatar
jehan committed
64 65 66 67
	if (ms_is_multicast_addr((const struct sockaddr *)&s->rtcp.gs.loc_addr)) {
		ms_debug("Stun packet not sent for session [%p] because of multicast",s);
		return;
	}
68 69 70 71
	memset(&msg, 0, sizeof(StunMessage));
	stunBuildReqSimple(&msg, NULL, FALSE, FALSE, 1);
	len = stunEncodeMessage(&msg, buf, len, NULL);
	if (len > 0) {
72 73 74
		mp = allocb(len, BPRI_MED);
		memcpy(mp->b_wptr, buf, len);
		mp->b_wptr += len;
75
		ms_message("Stun packet sent for session [%p]",s);
76
		rtp_session_sendm_with_ts(s, mp, 0);
77 78 79
	}
}

aymeric's avatar
aymeric committed
80 81
static void sender_init(MSFilter * f)
{
82
	SenderData *d = (SenderData *)ms_new0(SenderData, 1);
83 84
	const char *tmp=getenv("MS2_RTP_FIXED_DELAY");
	
aymeric's avatar
aymeric committed
85 86 87 88 89 90
	d->session = NULL;
	d->tsoff = 0;
	d->skip_until = 0;
	d->skip = FALSE;
	d->rate = 8000;
	d->dtmf = 0;
91
	d->dtmf_duration = 800;
92
	d->dtmf_ts_step=160;
93
	d->mute=FALSE;
aymeric's avatar
aymeric committed
94 95
	d->relay_session_id_size=0;
	d->last_rsi_time=0;
96
	d->last_sent_time=-1;
97
	d->last_stun_sent_time = -1;
98
	d->last_ts=0;
99 100
	d->use_task= tmp ? (!!atoi(tmp)) : FALSE;
	if (d->use_task) ms_message("MSRtpSend will use tasks to send out packet at the beginning of ticks.");
aymeric's avatar
aymeric committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
	f->data = d;
}

static void sender_uninit(MSFilter * f)
{
	SenderData *d = (SenderData *) f->data;

	ms_free(d);
}

static int sender_send_dtmf(MSFilter * f, void *arg)
{
	const char *dtmf = (const char *) arg;
	SenderData *d = (SenderData *) f->data;

aymeric's avatar
aymeric committed
116
	ms_filter_lock(f);
117 118 119
	if (d->skip==TRUE)
	{
		ms_filter_unlock(f);
120
		ms_warning("MSRtpSend: already sending a dtmf.");
121 122
		return -1;
	}
aymeric's avatar
aymeric committed
123
	d->dtmf = dtmf[0];
aymeric's avatar
aymeric committed
124
	ms_filter_unlock(f);
aymeric's avatar
aymeric committed
125 126 127
	return 0;
}

128 129 130 131 132 133 134
static int sender_set_dtmf_duration(MSFilter * f, void *arg)
{
	SenderData *d = (SenderData *) f->data;
	d->dtmf_duration = *((int*)arg);
	return 0;
}

aymeric's avatar
aymeric committed
135 136 137 138 139 140 141 142
static int sender_set_session(MSFilter * f, void *arg)
{
	SenderData *d = (SenderData *) f->data;
	RtpSession *s = (RtpSession *) arg;
	PayloadType *pt =
		rtp_profile_get_payload(rtp_session_get_profile(s),
								rtp_session_get_send_payload_type(s));
	if (pt != NULL) {
143
		d->rate = pt->clock_rate;
144 145
		d->dtmf_duration=(default_dtmf_duration_ms*d->rate)/1000;
		d->dtmf_ts_step=(20*d->rate)/1000;
146
		send_stun_packet(s);
aymeric's avatar
aymeric committed
147 148 149 150 151 152 153
	} else {
		ms_warning("Sending undefined payload type ?");
	}
	d->session = s;
	return 0;
}

154
static int sender_mute(MSFilter * f, void *arg)
aymeric's avatar
aymeric committed
155 156 157
{
	SenderData *d = (SenderData *) f->data;
	ms_filter_lock(f);
158
	d->mute=TRUE;
aymeric's avatar
aymeric committed
159 160 161 162
	ms_filter_unlock(f);
	return 0;
}

163
static int sender_unmute(MSFilter * f, void *arg)
aymeric's avatar
aymeric committed
164 165 166
{
	SenderData *d = (SenderData *) f->data;
	ms_filter_lock(f);
167
	d->mute=FALSE;
aymeric's avatar
aymeric committed
168 169 170 171 172 173 174
	ms_filter_unlock(f);
	return 0;
}

static int sender_set_relay_session_id(MSFilter *f, void*arg){
	SenderData *d = (SenderData *) f->data;
	const char *tmp=(const char *)arg;
aymeric's avatar
aymeric committed
175
	d->relay_session_id_size=b64_decode(tmp, strlen(tmp), (void*)d->relay_session_id, (unsigned int)sizeof(d->relay_session_id));
aymeric's avatar
aymeric committed
176 177 178
	return 0;
}

179 180
static int sender_get_sr(MSFilter *f, void *arg){
	SenderData *d = (SenderData *) f->data;
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
	PayloadType *pt;
	if (d->session==NULL) {
		ms_warning("Could not obtain sample rate, session is not set.");
		return -1;
	}
	pt=rtp_profile_get_payload(rtp_session_get_profile(d->session),
									rtp_session_get_recv_payload_type(d->session));
	if (pt != NULL) {
		if (strcasecmp(pt->mime_type,"G722")==0)
			*(int*)arg=16000;
		else
			*(int*)arg=pt->clock_rate;
	}else{
		ms_warning("MSRtpSend: Could not obtain sample rate, payload type is unknown.");
		return -1;
	}
197 198 199
	return 0;
}

200 201
static int sender_get_ch(MSFilter *f, void *arg) {
	SenderData *d = (SenderData *)f->data;
202 203 204 205 206 207 208 209 210 211 212
	PayloadType *pt;
	if (d->session==NULL) {
		ms_warning("Could not obtain number of channels, session is not set.");
		return -1;
	}
	pt=rtp_profile_get_payload(rtp_session_get_profile(d->session), rtp_session_get_recv_payload_type(d->session));
	if (pt==NULL){
		ms_warning("MSRtpSend: Could not obtain number of channels, payload type is unknown.");
		return -1;
	}
	*(int *)arg = pt->channels;
213 214 215
	return 0;
}

aymeric's avatar
aymeric committed
216
/* 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*/
217
static uint32_t get_cur_timestamp(MSFilter * f, mblk_t *im){
aymeric's avatar
aymeric committed
218
	SenderData *d = (SenderData *) f->data;
smorlat's avatar
smorlat committed
219
	uint32_t curts = (uint32_t)( (f->ticker->time*(uint64_t)d->rate)/(uint64_t)1000) ;
220
	int diffts;
aymeric's avatar
aymeric committed
221
	uint32_t netts;
222
	int difftime_ts;
aymeric's avatar
aymeric committed
223

224
	if (im && d->dtmf==0){ /*do not perform timestamp adjustment while a dtmf is being sent, otherwise durations are erroneous */
225 226 227 228 229 230 231 232 233 234 235 236
		uint32_t packet_ts=mblk_get_timestamp_info(im);
		if (d->last_sent_time==-1){
			d->tsoff = curts - packet_ts;
		}else{
			diffts=packet_ts-d->last_ts;
			difftime_ts=((f->ticker->time-d->last_sent_time)*d->rate)/1000;
			/* detect timestamp jump in the stream and adjust so that they become continuous on the network*/
			if (abs(diffts-difftime_ts)>(d->rate/5)){
				uint32_t tsoff=curts - packet_ts;
				ms_message("Adjusting output timestamp by %i",(tsoff-d->tsoff));
				d->tsoff = tsoff;
			}
237
		}
238 239 240 241
		netts = packet_ts + d->tsoff;
		d->last_sent_time=f->ticker->time;
		d->last_ts=packet_ts;
	}else netts=curts;
aymeric's avatar
aymeric committed
242 243 244
	return netts;
}

245
static int send_dtmf(MSFilter * f, uint32_t timestamp_start)
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
{
	SenderData *d = (SenderData *) f->data;
	mblk_t *m1;
	int tev_type;

	/* create the first telephony event packet */
	switch (d->dtmf){
		case '1':
			tev_type=TEV_DTMF_1;
		break;
		case '2':
			tev_type=TEV_DTMF_2;
		break;
		case '3':
			tev_type=TEV_DTMF_3;
		break;
		case '4':
			tev_type=TEV_DTMF_4;
		break;
		case '5':
			tev_type=TEV_DTMF_5;
		break;
		case '6':
			tev_type=TEV_DTMF_6;
		break;
		case '7':
			tev_type=TEV_DTMF_7;
		break;
		case '8':
			tev_type=TEV_DTMF_8;
		break;
		case '9':
			tev_type=TEV_DTMF_9;
		break;
		case '*':
			tev_type=TEV_DTMF_STAR;
		break;
		case '0':
			tev_type=TEV_DTMF_0;
		break;
		case '#':
			tev_type=TEV_DTMF_POUND;
		break;

		case 'A':
		case 'a':
		  tev_type=TEV_DTMF_A;
		  break;

		case 'B':
		case 'b':
		  tev_type=TEV_DTMF_B;
		  break;

		case 'C':
		case 'c':
		  tev_type=TEV_DTMF_C;
		  break;

		case 'D':
		case 'd':
		  tev_type=TEV_DTMF_D;
		  break;

		case '!':
		  tev_type=TEV_FLASH;
		  break;


		default:
		ms_warning("Bad dtmf: %c.",d->dtmf);
317 318
		d->skip = FALSE; /*reset dtmf*/
		d->dtmf = 0;
319 320 321 322
		return -1;
	}


323 324 325
	
	m1=rtp_session_create_telephone_event_packet(d->session,timestamp_start==d->dtmf_ts_cur);
	
326 327
	if (m1==NULL) return -1;

328 329
	d->dtmf_ts_cur+=d->dtmf_ts_step;
	if (RTP_TIMESTAMP_IS_NEWER_THAN(d->dtmf_ts_cur, d->skip_until)) {
330 331
		//retransmit end of rtp dtmf event
		mblk_t *tmp;
332
		rtp_session_add_telephone_event(d->session,m1,tev_type,1,10,(d->dtmf_ts_cur-timestamp_start));
333 334 335 336 337 338 339
		tmp=copymsg(m1);
		rtp_session_sendm_with_ts(d->session,tmp,timestamp_start);
		d->session->rtp.snd_seq--;
		tmp=copymsg(m1);
		rtp_session_sendm_with_ts(d->session,tmp,timestamp_start);
		d->session->rtp.snd_seq--;
		rtp_session_sendm_with_ts(d->session,m1,timestamp_start);
340 341
		d->skip = FALSE;
		d->dtmf = 0;
342
		ms_message("Finished sending RFC2833 dtmf %c",d->dtmf);
343
	}else {
344
		rtp_session_add_telephone_event(d->session,m1,tev_type,0,10,(d->dtmf_ts_cur-timestamp_start));
345 346 347 348 349
		rtp_session_sendm_with_ts(d->session,m1,timestamp_start);
	}
	return 0;
}

350 351 352 353
static void check_stun_sending(MSFilter *f) {
	SenderData *d = (SenderData *) f->data;
	RtpSession *s = d->session;

354
	if ((d->last_stun_sent_time == -1) || ((f->ticker->time- d->last_sent_time>2000) /*no need to send stun packets if media sent during last 2s*/
jehan's avatar
jehan committed
355
											&& (f->ticker->time - d->last_stun_sent_time) >= 500)) {
356 357 358 359 360
		d->last_stun_sent_time = f->ticker->time;
		send_stun_packet(s);
	}
}

361
static void process_cn(MSFilter *f, SenderData *d, uint32_t timestamp){
362
	if (d->cng_data.datasize>0){
363 364 365 366 367
		rtp_header_t *rtp;
		/* get CN payload type number */
		int cn_pt=rtp_profile_find_payload_number(d->session->snd.profile, "CN", 8000, 1);

		/* create the packet, payload type number is the one used for current codec */
368
		mblk_t *m=rtp_session_create_packet(d->session, 12, d->cng_data.data, d->cng_data.datasize);
369 370 371 372
		/* replace payload type in RTP header */
		rtp=(rtp_header_t*)m->b_rptr;
		rtp->paytype = cn_pt;

373
		rtp_session_sendm_with_ts(d->session,m,timestamp);
374 375 376 377
		d->cng_data.datasize=0;
	}
}

378
static void _sender_process(MSFilter * f)
aymeric's avatar
aymeric committed
379 380 381 382 383 384 385 386 387 388
{
	SenderData *d = (SenderData *) f->data;
	RtpSession *s = d->session;
	mblk_t *im;
	uint32_t timestamp;


	if (d->relay_session_id_size>0 && 
		( (f->ticker->time-d->last_rsi_time)>5000 || d->last_rsi_time==0) ) {
		ms_message("relay session id sent in RTCP APP");
aymeric's avatar
aymeric committed
389
		rtp_session_send_rtcp_APP(s,0,"RSID",(const uint8_t *)d->relay_session_id,d->relay_session_id_size);
aymeric's avatar
aymeric committed
390 391
		d->last_rsi_time=f->ticker->time;
	}
392

393 394 395
	ms_filter_lock(f);
	im = ms_queue_get(f->inputs[0]);
	do {
aymeric's avatar
aymeric committed
396 397
		mblk_t *header;

398 399
		timestamp = get_cur_timestamp(f, im);
		
400 401 402
		if (d->dtmf != 0 && !d->skip) {
			ms_debug("prepare to send RFC2833 dtmf.");
			d->skip_until = timestamp + d->dtmf_duration;
403
			d->dtmf_ts_cur=timestamp;
404 405
			d->skip = TRUE;
		}
406
		if (d->skip) {
407
			uint32_t origin_ts=d->skip_until-d->dtmf_duration;
408 409 410
			if (RTP_TIMESTAMP_IS_NEWER_THAN(timestamp,d->dtmf_ts_cur)){
				ms_debug("Sending RFC2833 packet, start_timestamp=%u, dtmf_ts_cur=%u",origin_ts,d->dtmf_ts_cur);
				send_dtmf(f, origin_ts);
smorlat's avatar
smorlat committed
411
			}
412
		}
413
		if (im){
414
			if (d->skip == FALSE && d->mute==FALSE){
415 416 417 418
				header = rtp_session_create_packet(s, 12, NULL, 0);
				rtp_set_markbit(header, mblk_get_marker_info(im));
				header->b_cont = im;
				rtp_session_sendm_with_ts(s, header, timestamp);
419 420
			} else if (d->mute==TRUE && d->skip == FALSE) {
				freemsg(im);
421
				process_cn(f, d, timestamp);
422 423 424

				//Send STUN packet as RTP keep alive
				check_stun_sending(f);
425 426 427
			}else{
				freemsg(im);
			}
428 429 430
		} else if (d->skip == FALSE) {
			// Send STUN packet as RTP keep alive even if there is no input
			check_stun_sending(f);
431
		}
432
	}while ((im = ms_queue_get(f->inputs[0])) != NULL);
433 434

	if (d->last_sent_time == -1) {
435
		check_stun_sending(f);
436
	}
437

Simon Morlat's avatar
Simon Morlat committed
438 439
	/*every second, compute output bandwidth*/
	if (f->ticker->time % 1000 == 0) rtp_session_compute_send_bandwidth(d->session);
440
	ms_filter_unlock(f);
aymeric's avatar
aymeric committed
441 442
}

443 444 445 446 447 448 449 450 451 452 453 454
static void sender_process(MSFilter * f){
	SenderData *d = (SenderData *) f->data;
	RtpSession *s = d->session;
	if (s == NULL){
		ms_queue_flush(f->inputs[0]);
		return;
	}
	if (d->use_task)
		ms_filter_postpone_task(f,_sender_process);
	else _sender_process(f);
}

Simon Morlat's avatar
Simon Morlat committed
455 456 457 458 459 460 461
static int sender_send_generic_cn(MSFilter *f, void *data){
	SenderData *d = (SenderData *) f->data;
	ms_filter_lock(f);
	memcpy(&d->cng_data, data, sizeof(MSCngData));
	ms_filter_unlock(f);
	return 0;
}
462

aymeric's avatar
aymeric committed
463
static MSFilterMethod sender_methods[] = {
464 465
	{MS_RTP_SEND_MUTE, sender_mute},
	{MS_RTP_SEND_UNMUTE, sender_unmute},
aymeric's avatar
aymeric committed
466 467 468
	{MS_RTP_SEND_SET_SESSION, sender_set_session},
	{MS_RTP_SEND_SEND_DTMF, sender_send_dtmf},
	{MS_RTP_SEND_SET_RELAY_SESSION_ID, sender_set_relay_session_id},
469
	{MS_FILTER_GET_SAMPLE_RATE, sender_get_sr },
470
	{MS_FILTER_GET_NCHANNELS, sender_get_ch },
471
	{MS_RTP_SEND_SET_DTMF_DURATION, sender_set_dtmf_duration },
Simon Morlat's avatar
Simon Morlat committed
472
	{MS_RTP_SEND_SEND_GENERIC_CN, sender_send_generic_cn },
aymeric's avatar
aymeric committed
473 474 475 476 477 478 479 480
	{0, NULL}
};

#ifdef _MSC_VER

MSFilterDesc ms_rtp_send_desc = {
	MS_RTP_SEND_ID,
	"MSRtpSend",
481
	N_("RTP output filter"),
aymeric's avatar
aymeric committed
482 483 484 485 486 487 488 489 490
	MS_FILTER_OTHER,
	NULL,
	1,
	0,
	sender_init,
	NULL,
	sender_process,
	NULL,
	sender_uninit,
491 492
	sender_methods,
	MS_FILTER_IS_PUMP
aymeric's avatar
aymeric committed
493 494 495 496 497 498 499
};

#else

MSFilterDesc ms_rtp_send_desc = {
	.id = MS_RTP_SEND_ID,
	.name = "MSRtpSend",
500
	.text = N_("RTP output filter"),
aymeric's avatar
aymeric committed
501 502 503 504 505 506
	.category = MS_FILTER_OTHER,
	.ninputs = 1,
	.noutputs = 0,
	.init = sender_init,
	.process = sender_process,
	.uninit = sender_uninit,
507 508
	.methods = sender_methods,
	.flags=MS_FILTER_IS_PUMP
aymeric's avatar
aymeric committed
509 510 511 512 513 514
};

#endif

struct ReceiverData {
	RtpSession *session;
515
	int current_pt;
aymeric's avatar
aymeric committed
516
	int rate;
Simon Morlat's avatar
Simon Morlat committed
517
	bool_t starting;
518
	bool_t reset_jb;
aymeric's avatar
aymeric committed
519 520 521 522 523 524
};

typedef struct ReceiverData ReceiverData;

static void receiver_init(MSFilter * f)
{
525
	ReceiverData *d = (ReceiverData *)ms_new0(ReceiverData, 1);
aymeric's avatar
aymeric committed
526 527 528 529 530
	d->session = NULL;
	d->rate = 8000;
	f->data = d;
}

531 532
static void receiver_postprocess(MSFilter * f){
	/*ReceiverData *d = (ReceiverData *) f->data;*/
aymeric's avatar
aymeric committed
533 534
}

535
static void receiver_uninit(MSFilter * f){
aymeric's avatar
aymeric committed
536
	ReceiverData *d = (ReceiverData *) f->data;
537
	ms_free(d);
aymeric's avatar
aymeric committed
538 539 540 541 542 543
}

static int receiver_set_session(MSFilter * f, void *arg)
{
	ReceiverData *d = (ReceiverData *) f->data;
	RtpSession *s = (RtpSession *) arg;
544 545 546
	PayloadType *pt;
	d->current_pt=rtp_session_get_recv_payload_type(s);
	pt = rtp_profile_get_payload(rtp_session_get_profile(s),d->current_pt);
aymeric's avatar
aymeric committed
547
	if (pt != NULL) {
548
		d->rate = pt->clock_rate;
aymeric's avatar
aymeric committed
549
	} else {
550
		ms_warning("receiver_set_session(): receiving undefined payload type %i ?",
551
		    rtp_session_get_recv_payload_type(s));
aymeric's avatar
aymeric committed
552 553 554 555 556 557
	}
	d->session = s;

	return 0;
}

smorlat's avatar
smorlat committed
558 559 560 561 562 563 564
static int receiver_get_sr(MSFilter *f, void *arg){
	ReceiverData *d = (ReceiverData *) f->data;
	PayloadType *pt;
	if (d->session==NULL) {
		ms_warning("Could not obtain sample rate, session is not set.");
		return -1;
	}
565
	pt=rtp_profile_get_payload(rtp_session_get_profile(d->session), rtp_session_get_recv_payload_type(d->session));
smorlat's avatar
smorlat committed
566
	if (pt != NULL) {
567 568 569 570
		if (strcasecmp(pt->mime_type,"G722")==0)
			*(int*)arg=16000;
		else
			*(int*)arg=pt->clock_rate;
smorlat's avatar
smorlat committed
571 572 573 574 575 576 577
	}else{
		ms_warning("Could not obtain sample rate, payload type is unknown.");
		return -1;
	}
	return 0;
}

578 579
static int receiver_get_ch(MSFilter *f, void *arg) {
	ReceiverData *d = (ReceiverData *)f->data;
580 581 582 583 584 585 586 587 588 589 590
	PayloadType *pt;
	if (d->session==NULL) {
		ms_warning("MSRtpRecv: Could not obtain sample rate, session is not set.");
		return -1;
	}
	pt=rtp_profile_get_payload(rtp_session_get_profile(d->session), rtp_session_get_recv_payload_type(d->session));
	if (pt == NULL) {
		ms_warning("MSRtpRecv: could not obtain number of channels, payload type is unknown.");
		return -1;
	}
	*(int *)arg = pt->channels;
591 592 593
	return 0;
}

594 595 596 597 598 599 600
static int receiver_reset_jitter_buffer(MSFilter *f, void *arg) {
	ReceiverData *d = (ReceiverData *)f->data;
	d->reset_jb = TRUE;
	return 0;
}


aymeric's avatar
aymeric committed
601 602
static void receiver_preprocess(MSFilter * f){
	ReceiverData *d = (ReceiverData *) f->data;
Simon Morlat's avatar
Simon Morlat committed
603
	d->starting=TRUE;
aymeric's avatar
aymeric committed
604 605
}

606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
/*returns TRUE if the packet is ok to be sent to output queue*/
static bool_t receiver_check_payload_type(MSFilter *f, ReceiverData *d, mblk_t *m){
	int ptn=rtp_get_payload_type(m);
	PayloadType *pt;
	if (ptn==d->current_pt) return TRUE;
	pt=rtp_profile_get_payload(rtp_session_get_profile(d->session), ptn);
	if (pt==NULL){
		ms_warning("Discarding packet with unknown payload type %i",ptn);
		return FALSE;
	}
	if (strcasecmp(pt->mime_type,"CN")==0){
		MSCngData cngdata;
		uint8_t *data=NULL;
		int datasize=rtp_get_payload(m, &data);
		if (data){
			if (datasize<= sizeof(cngdata.data)){
				memcpy(cngdata.data, data, datasize);
				cngdata.datasize=datasize;
				ms_filter_notify(f, MS_RTP_RECV_GENERIC_CN_RECEIVED, &cngdata);
			}else{
				ms_warning("CN packet has unexpected size %i", datasize);
			}
		}
629
		return FALSE;
630
	}
631 632
	d->current_pt = ptn;
	return TRUE;
633 634
}

aymeric's avatar
aymeric committed
635 636 637 638 639 640 641 642
static void receiver_process(MSFilter * f)
{
	ReceiverData *d = (ReceiverData *) f->data;
	mblk_t *m;
	uint32_t timestamp;

	if (d->session == NULL)
		return;
643 644 645 646 647 648
	
	if (d->reset_jb){
		ms_message("Reseting jitter buffer");
		rtp_session_resync(d->session);
		d->reset_jb=FALSE;
	}
aymeric's avatar
aymeric committed
649

Simon Morlat's avatar
Simon Morlat committed
650 651 652 653 654 655 656 657 658
	if (d->starting){
		PayloadType *pt=rtp_profile_get_payload(
			rtp_session_get_profile(d->session),
			rtp_session_get_recv_payload_type(d->session));
		if (pt && pt->type!=PAYLOAD_VIDEO)
			rtp_session_flush_sockets(d->session);
		d->starting=FALSE;
	}

aymeric's avatar
aymeric committed
659
	timestamp = (uint32_t) (f->ticker->time * (d->rate/1000));
aymeric's avatar
aymeric committed
660
	while ((m = rtp_session_recvm_with_ts(d->session, timestamp)) != NULL) {
661 662 663 664 665 666 667 668 669
		if (receiver_check_payload_type(f, d, m)){
			mblk_set_timestamp_info(m, rtp_get_timestamp(m));
			mblk_set_marker_info(m, rtp_get_markbit(m));
			mblk_set_cseq(m, rtp_get_seqnumber(m));
			rtp_get_payload(m,&m->b_rptr);
			ms_queue_put(f->outputs[0], m);
		}else{
			freemsg(m);
		}
aymeric's avatar
aymeric committed
670
	}
Simon Morlat's avatar
Simon Morlat committed
671 672
	/*every second compute recv bandwidth*/
	if (f->ticker->time % 1000 == 0) rtp_session_compute_recv_bandwidth(d->session);
aymeric's avatar
aymeric committed
673 674 675
}

static MSFilterMethod receiver_methods[] = {
smorlat's avatar
smorlat committed
676
	{	MS_RTP_RECV_SET_SESSION	, receiver_set_session	},
677
	{	MS_RTP_RECV_RESET_JITTER_BUFFER, receiver_reset_jitter_buffer },
smorlat's avatar
smorlat committed
678
	{	MS_FILTER_GET_SAMPLE_RATE	, receiver_get_sr		},
679
	{	MS_FILTER_GET_NCHANNELS	,	receiver_get_ch	},
smorlat's avatar
smorlat committed
680
	{	0, NULL}
aymeric's avatar
aymeric committed
681 682 683 684 685 686 687
};

#ifdef _MSC_VER

MSFilterDesc ms_rtp_recv_desc = {
	MS_RTP_RECV_ID,
	"MSRtpRecv",
688
	N_("RTP input filter"),
aymeric's avatar
aymeric committed
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
	MS_FILTER_OTHER,
	NULL,
	0,
	1,
	receiver_init,
	receiver_preprocess,
	receiver_process,
	receiver_postprocess,
	receiver_uninit,
	receiver_methods
};

#else

MSFilterDesc ms_rtp_recv_desc = {
	.id = MS_RTP_RECV_ID,
	.name = "MSRtpRecv",
706
	.text = N_("RTP input filter"),
aymeric's avatar
aymeric committed
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
	.category = MS_FILTER_OTHER,
	.ninputs = 0,
	.noutputs = 1,
	.init = receiver_init,
	.preprocess = receiver_preprocess,
	.process = receiver_process,
	.postprocess=receiver_postprocess,
	.uninit = receiver_uninit,
	.methods = receiver_methods
};

#endif

MS_FILTER_DESC_EXPORT(ms_rtp_send_desc)
MS_FILTER_DESC_EXPORT(ms_rtp_recv_desc)