mediastream.c 17.9 KB
Newer Older
Ghislain MARY's avatar
Ghislain MARY committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2006-2013 Belledonne Communications, Grenoble

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.
*/


jehan's avatar
jehan committed
21 22 23
#ifdef HAVE_CONFIG_H
#include "mediastreamer-config.h"
#endif
24

jehan's avatar
jehan committed
25
#include "ortp/port.h"
Ghislain MARY's avatar
Ghislain MARY committed
26 27
#include "mediastreamer2/mediastream.h"
#include "private.h"
Ghislain MARY's avatar
Ghislain MARY committed
28 29
#include <ctype.h>

30 31


32 33 34
#ifndef MS_MINIMAL_MTU
/*this is used for determining the minimum size of recv buffers for RTP packets
 Keep 1500 for maximum interoparibility*/
35
#define MS_MINIMAL_MTU 1500
36 37
#endif

Ghislain MARY's avatar
Ghislain MARY committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59

#if defined(_WIN32_WCE)
time_t
ms_time(time_t *t) {
	DWORD timemillis = GetTickCount();
	if (timemillis > 0) {
		if (t != NULL) *t = timemillis / 1000;
	}
	return timemillis / 1000;
}
#endif


static void disable_checksums(ortp_socket_t sock) {
#if defined(DISABLE_CHECKSUMS) && defined(SO_NO_CHECK)
	int option = 1;
	if (setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &option, sizeof(option)) == -1) {
		ms_warning("Could not disable udp checksum: %s", strerror(errno));
	}
#endif
}

60 61 62 63 64 65
/**
 * This function must be called from the MSTicker thread:
 * it replaces one filter by another one.
 * This is a dirty hack that works anyway.
 * It would be interesting to have something that does the job
 * more easily within the MSTicker API.
66
 * return TRUE if the decoder was changed, FALSE otherwise.
67
 */
68
static bool_t media_stream_change_decoder(MediaStream *stream, int payload) {
69
	RtpSession *session = stream->sessions.rtp_session;
70 71
	RtpProfile *prof = rtp_session_get_profile(session);
	PayloadType *pt = rtp_profile_get_payload(prof, payload);
72

73 74
	if (stream->decoder == NULL){
		ms_message("media_stream_change_decoder(): ignored, no decoder.");
75
		return FALSE;
76
	}
77

78 79 80
	if (pt != NULL){
		MSFilter *dec;

Simon Morlat's avatar
Simon Morlat committed
81
		if (stream->type == MSVideo){
Simon Morlat's avatar
Simon Morlat committed
82
			/* Q: why only video ? A: because an audio format can be used at different rates: ex: speex/16000 speex/8000*/
83
			if ((stream->decoder != NULL) && (stream->decoder->desc->enc_fmt != NULL)
84
			&& (strcasecmp(pt->mime_type, stream->decoder->desc->enc_fmt) == 0)) {
85
				/* Same formats behind different numbers, nothing to do. */
86
				return FALSE;
87
			}
88 89 90 91 92 93 94 95 96 97 98 99 100 101
		}

		dec = ms_filter_create_decoder(pt->mime_type);
		if (dec != NULL) {
			MSFilter *nextFilter = stream->decoder->outputs[0]->next.filter;
			ms_filter_unlink(stream->rtprecv, 0, stream->decoder, 0);
			ms_filter_unlink(stream->decoder, 0, nextFilter, 0);
			ms_filter_postprocess(stream->decoder);
			ms_filter_destroy(stream->decoder);
			stream->decoder = dec;
			if (pt->recv_fmtp != NULL)
				ms_filter_call_method(stream->decoder, MS_FILTER_ADD_FMTP, (void *)pt->recv_fmtp);
			ms_filter_link(stream->rtprecv, 0, stream->decoder, 0);
			ms_filter_link(stream->decoder, 0, nextFilter, 0);
102
			ms_filter_preprocess(stream->decoder,stream->sessions.ticker);
103
			return TRUE;
104 105 106 107 108 109
		} else {
			ms_warning("No decoder found for %s", pt->mime_type);
		}
	} else {
		ms_warning("No payload defined with number %i", payload);
	}
110
	return FALSE;
111 112
}

Ghislain MARY's avatar
Ghislain MARY committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
MSTickerPrio __ms_get_default_prio(bool_t is_video) {
	const char *penv;

	if (is_video) {
#ifdef __ios
		return MS_TICKER_PRIO_HIGH;
#else
		return MS_TICKER_PRIO_NORMAL;
#endif
	}

	penv = getenv("MS_AUDIO_PRIO");
	if (penv) {
		if (strcasecmp(penv, "NORMAL") == 0) return MS_TICKER_PRIO_NORMAL;
		if (strcasecmp(penv, "HIGH") == 0) return MS_TICKER_PRIO_HIGH;
		if (strcasecmp(penv, "REALTIME") == 0) return MS_TICKER_PRIO_REALTIME;
		ms_error("Undefined priority %s", penv);
	}
#ifdef __linux
	return MS_TICKER_PRIO_REALTIME;
#else
	return MS_TICKER_PRIO_HIGH;
#endif
}

jehan's avatar
jehan committed
138
RtpSession * create_duplex_rtpsession(const char* local_ip, int loc_rtp_port, int loc_rtcp_port) {
Ghislain MARY's avatar
Ghislain MARY committed
139 140 141
	RtpSession *rtpr;

	rtpr = rtp_session_new(RTP_SESSION_SENDRECV);
142
	rtp_session_set_recv_buf_size(rtpr, MAX(ms_get_mtu() , MS_MINIMAL_MTU));
Ghislain MARY's avatar
Ghislain MARY committed
143 144 145 146
	rtp_session_set_scheduling_mode(rtpr, 0);
	rtp_session_set_blocking_mode(rtpr, 0);
	rtp_session_enable_adaptive_jitter_compensation(rtpr, TRUE);
	rtp_session_set_symmetric_rtp(rtpr, TRUE);
jehan's avatar
jehan committed
147
	rtp_session_set_local_addr(rtpr, local_ip, loc_rtp_port, loc_rtcp_port);
Ghislain MARY's avatar
Ghislain MARY committed
148 149
	rtp_session_signal_connect(rtpr, "timestamp_jump", (RtpCallback)rtp_session_resync, NULL);
	rtp_session_signal_connect(rtpr, "ssrc_changed", (RtpCallback)rtp_session_resync, NULL);
Ghislain MARY's avatar
Ghislain MARY committed
150
	rtp_session_set_ssrc_changed_threshold(rtpr, 0);
151
	rtp_session_set_rtcp_report_interval(rtpr, 2500);	/* At the beginning of the session send more reports. */
jehan's avatar
jehan committed
152
	rtp_session_set_multicast_loopback(rtpr,TRUE); /*very useful, specially for testing purposes*/
Ghislain MARY's avatar
Ghislain MARY committed
153 154 155 156
	disable_checksums(rtp_session_get_rtp_socket(rtpr));
	return rtpr;
}

157
void media_stream_start_ticker(MediaStream *stream) {
Ghislain MARY's avatar
Ghislain MARY committed
158
	MSTickerParams params = {0};
159
	char name[32] = {0};
Ghislain MARY's avatar
Ghislain MARY committed
160

161
	if (stream->sessions.ticker) return;
Ghislain MARY's avatar
Ghislain MARY committed
162 163 164
	snprintf(name, sizeof(name) - 1, "%s MSTicker", media_stream_type_str(stream));
	name[0] = toupper(name[0]);
	params.name = name;
Simon Morlat's avatar
Simon Morlat committed
165
	params.prio = __ms_get_default_prio((stream->type == MSVideo) ? TRUE : FALSE);
166
	stream->sessions.ticker = ms_ticker_new_with_params(&params);
Ghislain MARY's avatar
Ghislain MARY committed
167 168
}

Ghislain MARY's avatar
Ghislain MARY committed
169
const char * media_stream_type_str(MediaStream *stream) {
Simon Morlat's avatar
Simon Morlat committed
170
	return ms_format_type_to_string(stream->type);
Ghislain MARY's avatar
Ghislain MARY committed
171 172
}

173 174
void ms_media_stream_sessions_uninit(MSMediaStreamSessions *sessions){
	if (sessions->srtp_session) {
johan's avatar
johan committed
175
		ms_srtp_dealloc(sessions->srtp_session);
176 177
		sessions->srtp_session=NULL;
	}
178 179 180 181
	if (sessions->srtp_rtcp_session) {
		ms_srtp_dealloc(sessions->srtp_rtcp_session);
		sessions->srtp_rtcp_session=NULL;
	}
182 183 184 185
	if (sessions->rtp_session) {
		rtp_session_destroy(sessions->rtp_session);
		sessions->rtp_session=NULL;
	}
186
	if (sessions->zrtp_context != NULL) {
187
		ms_zrtp_context_destroy(sessions->zrtp_context);
188 189
		sessions->zrtp_context = NULL;
	}
johan's avatar
johan committed
190 191 192 193
	if (sessions->dtls_context != NULL) {
		ms_dtls_srtp_context_destroy(sessions->dtls_context);
		sessions->dtls_context = NULL;
	}
194 195 196 197 198 199
	if (sessions->ticker){
		ms_ticker_destroy(sessions->ticker);
		sessions->ticker=NULL;
	}
}

Ghislain MARY's avatar
Ghislain MARY committed
200
void media_stream_free(MediaStream *stream) {
201 202
	if (stream->sessions.rtp_session != NULL){
		rtp_session_unregister_event_queue(stream->sessions.rtp_session, stream->evq);
Ghislain MARY's avatar
Ghislain MARY committed
203
	}
204 205
	if (stream->owns_sessions){
		ms_media_stream_sessions_uninit(&stream->sessions);
Ghislain MARY's avatar
Ghislain MARY committed
206 207 208 209 210 211 212 213
	}
	if (stream->evq) ortp_ev_queue_destroy(stream->evq);
	if (stream->rc != NULL) ms_bitrate_controller_destroy(stream->rc);
	if (stream->rtpsend != NULL) ms_filter_destroy(stream->rtpsend);
	if (stream->rtprecv != NULL) ms_filter_destroy(stream->rtprecv);
	if (stream->encoder != NULL) ms_filter_destroy(stream->encoder);
	if (stream->decoder != NULL) ms_filter_destroy(stream->decoder);
	if (stream->voidsink != NULL) ms_filter_destroy(stream->voidsink);
214
	if (stream->qi) ms_quality_indicator_destroy(stream->qi);
215

Ghislain MARY's avatar
Ghislain MARY committed
216 217 218
}

void media_stream_set_rtcp_information(MediaStream *stream, const char *cname, const char *tool) {
219 220
	if (stream->sessions.rtp_session != NULL) {
		rtp_session_set_source_description(stream->sessions.rtp_session, cname, NULL, NULL, NULL, NULL, tool, NULL);
Ghislain MARY's avatar
Ghislain MARY committed
221 222 223 224
	}
}

void media_stream_get_local_rtp_stats(MediaStream *stream, rtp_stats_t *lstats) {
225 226
	if (stream->sessions.rtp_session) {
		const rtp_stats_t *stats = rtp_session_get_stats(stream->sessions.rtp_session);
Ghislain MARY's avatar
Ghislain MARY committed
227 228 229 230 231 232
		memcpy(lstats, stats, sizeof(*stats));
	} else memset(lstats, 0, sizeof(rtp_stats_t));
}

int media_stream_set_dscp(MediaStream *stream, int dscp) {
	ms_message("Setting DSCP to %i for %s stream.", dscp, media_stream_type_str(stream));
233
	return rtp_session_set_dscp(stream->sessions.rtp_session, dscp);
Ghislain MARY's avatar
Ghislain MARY committed
234 235 236
}

void media_stream_enable_adaptive_bitrate_control(MediaStream *stream, bool_t enabled) {
237 238 239 240 241
	stream->rc_enable = enabled;
}

void media_stream_set_adaptive_bitrate_algorithm(MediaStream *stream, MSQosAnalyzerAlgorithm algorithm) {
	stream->rc_algorithm = algorithm;
Ghislain MARY's avatar
Ghislain MARY committed
242 243 244
}

void media_stream_enable_adaptive_jittcomp(MediaStream *stream, bool_t enabled) {
245
	rtp_session_enable_adaptive_jitter_compensation(stream->sessions.rtp_session, enabled);
Ghislain MARY's avatar
Ghislain MARY committed
246 247
}

johan's avatar
johan committed
248
bool_t media_stream_dtls_supported(void){
johan's avatar
johan committed
249
	return ms_dtls_srtp_available();
johan's avatar
johan committed
250 251
}

252
/*deprecated*/
jehan's avatar
jehan committed
253
bool_t media_stream_enable_srtp(MediaStream *stream, MSCryptoSuite suite, const char *snd_key, const char *rcv_key) {
254
	return media_stream_set_srtp_recv_key_b64(&(stream->sessions),suite,rcv_key)==0 && media_stream_set_srtp_send_key_b64(&(stream->sessions),suite,snd_key)==0;
Ghislain MARY's avatar
Ghislain MARY committed
255 256
}

257 258 259 260
const MSQualityIndicator *media_stream_get_quality_indicator(MediaStream *stream){
	return stream->qi;
}

Ghislain MARY's avatar
Ghislain MARY committed
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
bool_t ms_is_ipv6(const char *remote) {
	bool_t ret = FALSE;
	struct addrinfo hints, *res0;
	int err;

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;
	err = getaddrinfo(remote,"8000", &hints, &res0);
	if (err != 0) {
		ms_warning("get_local_addr_for: %s", gai_strerror(err));
		return FALSE;
	}
	ret = (res0->ai_addr->sa_family == AF_INET6);
	freeaddrinfo(res0);
	return ret;
}
278

jehan's avatar
jehan committed
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
bool_t ms_is_multicast_addr(const struct sockaddr *addr) {

	switch (addr->sa_family) {
		case AF_INET:
			return IN_MULTICAST(ntohl(((struct sockaddr_in *) addr)->sin_addr.s_addr));
		case AF_INET6:
			return IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) addr)->sin6_addr));
		default:
			return FALSE;
	}

}
bool_t ms_is_multicast(const char *address) {
	bool_t ret = FALSE;
	struct addrinfo hints, *res0;
	int err;

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;
	err = getaddrinfo(address,"8000", &hints, &res0);
	if (err != 0) {
		ms_warning("get_local_addr_for: %s", gai_strerror(err));
		return FALSE;
	}
	ret = ms_is_multicast_addr(res0->ai_addr);

	freeaddrinfo(res0);
	return ret;

}
310
bool_t mediastream_payload_type_changed(RtpSession *session, unsigned long data) {
311
	MediaStream *stream = (MediaStream *)data;
312
	int pt = rtp_session_get_recv_payload_type(stream->sessions.rtp_session);
313
	return media_stream_change_decoder(stream, pt);
314
}
315

316 317 318 319
static void media_stream_process_rtcp(MediaStream *stream, mblk_t *m, time_t curtime){
	stream->last_packet_time=curtime;
	ms_message("%s stream [%p]: receiving RTCP %s%s",media_stream_type_str(stream),stream,(rtcp_is_SR(m)?"SR":""),(rtcp_is_RR(m)?"RR":""));
	do{
320
		if (stream->rc_enable&&stream->rc) ms_bitrate_controller_process_rtcp(stream->rc,m);
321
		if (stream->qi) ms_quality_indicator_update_from_feedback(stream->qi,m);
322 323
		stream->process_rtcp(stream,m);
	}while(rtcp_next_packet(m));
324

325 326
}

327 328
void media_stream_iterate(MediaStream *stream){
	time_t curtime=ms_time(NULL);
329

330
	if (stream->ice_check_list) ice_check_list_process(stream->ice_check_list,stream->sessions.rtp_session);
331
	/*we choose to update the quality indicator as much as possible, since local statistics can be computed realtime. */
Simon Morlat's avatar
Simon Morlat committed
332
	if (stream->state==MSStreamStarted){
333 334 335 336
		if (stream->is_beginning && (curtime-stream->start_time>15)){
			rtp_session_set_rtcp_report_interval(stream->sessions.rtp_session,5000);
			stream->is_beginning=FALSE;
		}
Simon Morlat's avatar
Simon Morlat committed
337 338
		if (stream->qi && curtime>stream->last_iterate_time) ms_quality_indicator_update_local(stream->qi);
	}
339
	stream->last_iterate_time=curtime;
340 341 342

	if (stream->rc) ms_bitrate_controller_update(stream->rc);

jehan's avatar
jehan committed
343
	if (stream->evq){
jehan's avatar
jehan committed
344 345 346
		OrtpEvent *ev=NULL;

		while ((ev=ortp_ev_queue_get(stream->evq))!=NULL){
jehan's avatar
jehan committed
347 348
			OrtpEventType evt=ortp_event_get_type(ev);
			if (evt==ORTP_EVENT_RTCP_PACKET_RECEIVED){
jehan's avatar
jehan committed
349
				mblk_t *m=ortp_event_get_data(ev)->packet;
350
				media_stream_process_rtcp(stream,m,curtime);
jehan's avatar
jehan committed
351
			}else if (evt==ORTP_EVENT_RTCP_PACKET_EMITTED){
Simon Morlat's avatar
Simon Morlat committed
352
				ms_message("%s_stream_iterate[%p]: local statistics available\n\tLocal's current jitter buffer size:%f ms",
353
					media_stream_type_str(stream), stream, rtp_session_get_jitter_stats(stream->sessions.rtp_session)->jitter_buffer_size_ms);
jehan's avatar
jehan committed
354
			}else if ((evt==ORTP_EVENT_STUN_PACKET_RECEIVED)&&(stream->ice_check_list)){
355
				ice_handle_stun_packet(stream->ice_check_list,stream->sessions.rtp_session,ortp_event_get_data(ev));
jehan's avatar
jehan committed
356 357 358
			} else if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED) {
				OrtpEventData *evd=ortp_event_get_data(ev);
				stream->sessions.is_secured=evd->info.zrtp_stream_encrypted;
359
				ms_message("%s_stream_iterate[%p]: is %s ",media_stream_type_str(stream) , stream, stream->sessions.is_secured ? "encrypted" : "not encrypted");
johan's avatar
johan committed
360 361 362 363
			} else if (evt == ORTP_EVENT_DTLS_ENCRYPTION_CHANGED) {
				OrtpEventData *evd=ortp_event_get_data(ev);
				stream->sessions.is_secured=evd->info.dtls_stream_encrypted;
				ms_message("%s_stream_iterate[%p]: is %s ",media_stream_type_str(stream) , stream, stream->sessions.is_secured ? "encrypted" : "not encrypted");
jehan's avatar
jehan committed
364 365 366 367
			}
			ortp_event_destroy(ev);
		}
	}
368 369
}

370
bool_t media_stream_alive(MediaStream *ms, int timeout){
371 372 373 374 375 376
	const rtp_stats_t *stats;
	
	if (ms->state!=MSStreamStarted){
		return TRUE;
	}
	stats=rtp_session_get_stats(ms->sessions.rtp_session);
377 378 379 380 381 382 383 384 385 386 387 388 389
	if (stats->recv!=0){
		if (stats->recv!=ms->last_packet_count){
			ms->last_packet_count=stats->recv;
			ms->last_packet_time=ms_time(NULL);
		}
	}
	if (ms_time(NULL)-ms->last_packet_time>timeout){
		/* more than timeout seconds of inactivity*/
		return FALSE;
	}
	return TRUE;
}

390 391 392 393 394 395 396 397 398 399 400 401 402 403
float media_stream_get_quality_rating(MediaStream *stream){
	if (stream->qi){
		return ms_quality_indicator_get_rating(stream->qi);
	}
	return -1;
}

float media_stream_get_average_quality_rating(MediaStream *stream){
	if (stream->qi){
		return ms_quality_indicator_get_average_rating(stream->qi);
	}
	return -1;
}

404 405 406 407 408 409 410 411 412 413 414 415 416 417
float media_stream_get_lq_quality_rating(MediaStream *stream) {
	if (stream->qi) {
		return ms_quality_indicator_get_lq_rating(stream->qi);
	}
	return -1;
}

float media_stream_get_average_lq_quality_rating(MediaStream *stream) {
	if (stream->qi) {
		return ms_quality_indicator_get_average_lq_rating(stream->qi);
	}
	return -1;
}

jehan's avatar
jehan committed
418 419 420 421 422 423 424 425
int media_stream_set_target_network_bitrate(MediaStream *stream,int target_bitrate) {
	stream->target_bitrate=target_bitrate;
	return 0;
}

int media_stream_get_target_network_bitrate(const MediaStream *stream) {
	return stream->target_bitrate;
}
426

427
float media_stream_get_up_bw(const MediaStream *stream) {
428
	return rtp_session_get_rtp_send_bandwidth(stream->sessions.rtp_session);
jehan's avatar
jehan committed
429 430
}

431
float media_stream_get_down_bw(const MediaStream *stream) {
432 433 434 435 436 437 438 439 440
	return rtp_session_get_rtp_recv_bandwidth(stream->sessions.rtp_session);
}

float media_stream_get_rtcp_up_bw(const MediaStream *stream) {
	return rtp_session_get_rtcp_send_bandwidth(stream->sessions.rtp_session);
}

float media_stream_get_rtcp_down_bw(const MediaStream *stream) {
	return rtp_session_get_rtcp_recv_bandwidth(stream->sessions.rtp_session);
jehan's avatar
jehan committed
441
}
442 443 444 445 446

void media_stream_reclaim_sessions(MediaStream *stream, MSMediaStreamSessions *sessions){
	memcpy(sessions,&stream->sessions, sizeof(MSMediaStreamSessions));
	stream->owns_sessions=FALSE;
}
447 448

bool_t media_stream_secured (const MediaStream *stream) {
jehan's avatar
jehan committed
449 450
	return stream->sessions.is_secured;
}
451 452 453 454 455

bool_t media_stream_avpf_enabled(const MediaStream *stream) {
	return rtp_session_avpf_enabled(stream->sessions.rtp_session);
}

456
uint16_t media_stream_get_avpf_rr_interval(const MediaStream *stream) {
457 458 459
	return rtp_session_get_avpf_rr_interval(stream->sessions.rtp_session);
}

jehan's avatar
jehan committed
460 461 462
MSStreamState media_stream_get_state(const MediaStream *stream) {
	return stream->state;
}
Simon Morlat's avatar
Simon Morlat committed
463

464 465 466 467
RtpSession * media_stream_get_rtp_session(const MediaStream *stream) {
	return stream->sessions.rtp_session;
}

Simon Morlat's avatar
Simon Morlat committed
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
#define keywordcmp(key,b) strncmp(key,b,sizeof(key))

/* see  http://www.iana.org/assignments/sdp-security-descriptions/sdp-security-descriptions.xhtml#sdp-security-descriptions-3 */



MSCryptoSuite ms_crypto_suite_build_from_name_params(const MSCryptoSuiteNameParams *descrption){
	const char *name=descrption->name, *parameters=descrption->params;
	if (keywordcmp ( "AES_CM_128_HMAC_SHA1_80",name ) == 0 ){
		if (parameters && strstr(parameters,"UNENCRYPTED_SRTP")) return MS_NO_CIPHER_SHA1_80;
		else if (parameters && strstr(parameters,"UNAUTHENTICATED_SRTP")) return MS_AES_128_NO_AUTH;
		else return MS_AES_128_SHA1_80;
	}else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",name ) == 0 ){
		if (parameters && strstr(parameters,"UNENCRYPTED_SRTP")) goto error;
		if (parameters && strstr(parameters,"UNAUTHENTICATED_SRTP")) return MS_AES_128_NO_AUTH;
		else return MS_AES_128_SHA1_32;
	}else if ( keywordcmp ( "AES_CM_256_HMAC_SHA1_32",name ) == 0 ){
		if (parameters && strstr(parameters,"UNENCRYPTED_SRTP")) goto error;
		if (parameters && strstr(parameters,"UNAUTHENTICATED_SRTP")) goto error;
		return MS_AES_256_SHA1_32;
	}else if ( keywordcmp ( "AES_CM_256_HMAC_SHA1_80",name ) == 0 ){
		if (parameters && strstr(parameters,"UNENCRYPTED_SRTP")) goto error;
		if (parameters && strstr(parameters,"UNAUTHENTICATED_SRTP")) goto error;
		return MS_AES_256_SHA1_80;
	}
error:
	ms_error("Unsupported crypto suite '%s' with parameters '%s'",name, parameters ? parameters : "");
	return MS_CRYPTO_SUITE_INVALID;
}

int ms_crypto_suite_to_name_params(MSCryptoSuite cs, MSCryptoSuiteNameParams *params ){
	params->name=NULL;
	params->params=NULL;
	switch(cs){
		case MS_CRYPTO_SUITE_INVALID:
			break;
		case MS_AES_128_SHA1_80:
			params->name= "AES_CM_128_HMAC_SHA1_80";
			break;
		case MS_AES_128_SHA1_32:
			params->name="AES_CM_128_HMAC_SHA1_32";
509
			break;
Simon Morlat's avatar
Simon Morlat committed
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
		case MS_AES_128_NO_AUTH:
			params->name="AES_CM_128_HMAC_SHA1_80";
			params->params="UNAUTHENTICATED_SRTP";
			break;
		case MS_NO_CIPHER_SHA1_80:
			params->name="AES_CM_128_HMAC_SHA1_80";
			params->params="UNENCRYPTED_SRTP UNENCRYPTED_SRTCP";
			break;
		case MS_AES_256_SHA1_80:
			params->name="AES_CM_256_HMAC_SHA1_80";
			break;
		case MS_AES_256_SHA1_32:
			params->name="AES_CM_256_HMAC_SHA1_32";
			break;
	}
	if (params->name==NULL) return -1;
	return 0;
}
Simon Morlat's avatar
Simon Morlat committed
528

529 530 531 532 533 534 535
/*stubs*/
#ifndef VIDEO_ENABLED
void video_stream_open_player(VideoStream *stream, MSFilter *sink){
}

void video_stream_close_player(VideoStream *stream){
}
Simon Morlat's avatar
Simon Morlat committed
536 537 538 539

const char *video_stream_get_default_video_renderer(void){
	return NULL;
}
540
#endif
Simon Morlat's avatar
Simon Morlat committed
541