Revision 5e9e29e0 plugins/janus_videoroom.c

View differences:

plugins/janus_videoroom.c
39 39
publishers = <max number of concurrent senders> (e.g., 6 for a video
40 40
             conference or 1 for a webinar)
41 41
bitrate = <max video bitrate for senders> (e.g., 128000)
42
fir_freq = <send a FIR to publishers every fir_freq seconds> (0=disable)
42 43
\endverbatim
43 44
 *
44 45
 * \ingroup plugins
......
51 52

  
52 53
#include "../config.h"
53 54
#include "../rtcp.h"
55
#include "../utils.h"
54 56

  
55 57

  
56 58
/* Plugin information */
......
133 135
	gchar *room_name;	/* Room description */
134 136
	int max_publishers;	/* Maximum number of concurrent publishers */
135 137
	uint64_t bitrate;	/* Global bitrate limit */
138
	uint16_t fir_freq;	/* Regular FIR frequency (0=disabled) */
136 139
	gboolean destroy;
137 140
	GHashTable *participants;	/* Map of potential publishers (we get listeners from them) */
138 141
} janus_videoroom;
......
156 159
	gchar *sdp;			/* The SDP this publisher negotiated, if any */
157 160
	gboolean audio_active;
158 161
	gboolean video_active;
162
	gboolean firefox;	/* We send Firefox users a different kind of FIR */
159 163
	uint64_t bitrate;
160 164
	gint64 fir_latest;	/* Time of latest sent FIR (to avoid flooding) */
161 165
	gint fir_seq;		/* FIR sequence number */
......
213 217
			janus_config_item *desc = janus_config_get_item(cat, "description");
214 218
			janus_config_item *bitrate = janus_config_get_item(cat, "bitrate");
215 219
			janus_config_item *maxp = janus_config_get_item(cat, "publishers");
220
			janus_config_item *firfreq = janus_config_get_item(cat, "fir_freq");
216 221
			/* Create the video mcu room */
217 222
			janus_videoroom *videoroom = calloc(1, sizeof(janus_videoroom));
218 223
			if(videoroom == NULL) {
......
238 243
			videoroom->bitrate = 0;
239 244
			if(bitrate != NULL && bitrate->value != NULL)
240 245
				videoroom->bitrate = atol(bitrate->value);
246
			videoroom->fir_freq = 0;
247
			if(firfreq != NULL && firfreq->value != NULL)
248
				videoroom->fir_freq = atol(firfreq->value);
241 249
			videoroom->destroy = 0;
242 250
			videoroom->participants = g_hash_table_new(NULL, NULL);
243 251
			g_hash_table_insert(rooms, GUINT_TO_POINTER(videoroom->room_id), videoroom);
......
254 262
	GList *r = rooms_list;
255 263
	while(r) {
256 264
		janus_videoroom *vr = (janus_videoroom *)r->data;
257
		JANUS_PRINT("  ::: [%"SCNu64"][%s] %"SCNu64", max %d publishers\n", vr->room_id, vr->room_name, vr->bitrate, vr->max_publishers);
265
		JANUS_PRINT("  ::: [%"SCNu64"][%s] %"SCNu64", max %d publishers, FIR frequency of %d seconds\n", vr->room_id, vr->room_name, vr->bitrate, vr->max_publishers, vr->fir_freq);
258 266
		r = r->next;
259 267
	}
260 268
	g_list_free(rooms_list);
......
401 409
				/* Send a FIR */
402 410
				char buf[20];
403 411
				memset(buf, 0, 20);
404
				janus_rtcp_fir((char *)&buf, 20, &p->fir_seq);
412
				if(!p->firefox)
413
					janus_rtcp_fir((char *)&buf, 20, &p->fir_seq);
414
				else
415
					janus_rtcp_fir_legacy((char *)&buf, 20, &p->fir_seq);
405 416
				JANUS_PRINT("New listener available, sending FIR to %s\n", p->display);
406 417
				gateway->relay_rtcp(p->session->handle, 1, buf, 20);
407 418
				/* Send a PLI too, just in case... */
......
427 438
		packet.length = len;
428 439
		packet.is_video = video;
429 440
		g_slist_foreach(participant->listeners, janus_videoroom_relay_rtp_packet, &packet);
430
		if(video) {
441
		if(video && (participant->room->fir_freq > 0)) {
431 442
			/* FIXME Very ugly hack to generate RTCP every tot seconds/frames */
432
			gint64 now = g_get_monotonic_time();
433
			if((now-participant->fir_latest) >= (10*G_USEC_PER_SEC)) {
434
				/* FIXME We send a FIR every 10 seconds */
443
			gint64 now = janus_get_monotonic_time();
444
			if((now-participant->fir_latest) >= (participant->room->fir_freq*G_USEC_PER_SEC)) {
445
				/* FIXME We send a FIR every tot seconds */
435 446
				participant->fir_latest = now;
436 447
				char buf[20];
437 448
				memset(buf, 0, 20);
438
				janus_rtcp_fir((char *)&buf, 20, &participant->fir_seq);
449
				if(!participant->firefox)
450
					janus_rtcp_fir((char *)&buf, 20, &participant->fir_seq);
451
				else
452
					janus_rtcp_fir_legacy((char *)&buf, 20, &participant->fir_seq);
439 453
				JANUS_PRINT("Sending FIR to %s\n", participant->display);
440 454
				gateway->relay_rtcp(handle, video, buf, 20);
441 455
				/* Send a PLI too, just in case... */
442 456
				memset(buf, 0, 12);
443 457
				janus_rtcp_pli((char *)&buf, 12);
444
				JANUS_PRINT("New listener available, sending PLI to %s\n", participant->display);
458
				JANUS_PRINT("Sending PLI to %s\n", participant->display);
445 459
				gateway->relay_rtcp(handle, video, buf, 12);
446 460
			}
447 461
		}
......
583 597
				sprintf(error_cause, "JSON error: invalid element (bitrate)");
584 598
				goto error;
585 599
			}
600
			json_t *fir_freq = json_object_get(root, "fir_freq");
601
			if(fir_freq && !json_is_integer(fir_freq)) {
602
				JANUS_DEBUG("JSON error: invalid element (fir_freq)\n");
603
				sprintf(error_cause, "JSON error: invalid element (fir_freq)");
604
				goto error;
605
			}
586 606
			json_t *publishers = json_object_get(root, "publishers");
587 607
			if(publishers && !json_is_integer(publishers)) {
588 608
				JANUS_DEBUG("JSON error: invalid element (publishers)\n");
......
627 647
			videoroom->bitrate = 0;
628 648
			if(bitrate)
629 649
				videoroom->bitrate = json_integer_value(bitrate);
650
			videoroom->fir_freq = 0;
651
			if(fir_freq)
652
				videoroom->fir_freq = json_integer_value(fir_freq);
630 653
			videoroom->destroy = 0;
631 654
			videoroom->participants = g_hash_table_new(NULL, NULL);
632 655
			g_hash_table_insert(rooms, GUINT_TO_POINTER(videoroom->room_id), videoroom);
......
636 659
			GList *r = rooms_list;
637 660
			while(r) {
638 661
				janus_videoroom *vr = (janus_videoroom *)r->data;
639
				JANUS_PRINT("  ::: [%"SCNu64"][%s] %"SCNu64", max %d publishers\n", vr->room_id, vr->room_name, vr->bitrate, vr->max_publishers);
662
				JANUS_PRINT("  ::: [%"SCNu64"][%s] %"SCNu64", max %d publishers, FIR frequency of %d seconds\n", vr->room_id, vr->room_name, vr->bitrate, vr->max_publishers, vr->fir_freq);
640 663
				r = r->next;
641 664
			}
642 665
			g_list_free(rooms_list);
......
721 744
				publisher->sdp = NULL;	/* We'll deal with this later */
722 745
				publisher->audio_active = FALSE;
723 746
				publisher->video_active = FALSE;
747
				publisher->firefox = FALSE;
724 748
				publisher->bitrate = videoroom->bitrate;
725 749
				publisher->listeners = NULL;
726 750
				publisher->fir_latest = 0;
......
791 815
					/* Negotiate by sending the selected publisher SDP back */
792 816
					if(publisher->sdp != NULL) {
793 817
						/* How long will the gateway take to push the event? */
794
						gint64 start = g_get_monotonic_time();
818
						gint64 start = janus_get_monotonic_time();
795 819
						int res = gateway->push_event(msg->handle, &janus_videoroom_plugin, msg->transaction, event_text, "offer", publisher->sdp);
796
						JANUS_PRINT("  >> Pushing event: %d (took %"SCNu64" ms)\n", res, g_get_monotonic_time()-start);
820
						JANUS_PRINT("  >> Pushing event: %d (took %"SCNu64" ms)\n", res, janus_get_monotonic_time()-start);
797 821
						if(res != JANUS_OK) {
798 822
							/* TODO Failed to negotiate? We should remove this listener */
799 823
						} else {
......
883 907
			janus_videoroom_listener *listener = (janus_videoroom_listener *)session->participant;
884 908
			if(!strcasecmp(request_text, "start")) {
885 909
				/* Start/restart receiving the publisher streams */
910
				janus_videoroom_participant *publisher = listener->feed;
886 911
				listener->paused = FALSE;
912
				event = json_object();
913
				json_object_set(event, "videoroom", json_string("event"));
914
				json_object_set(event, "room", json_integer(publisher->room->room_id));
915
				json_object_set(event, "result", json_string("ok"));
916
				/* Send a FIR */
917
				char buf[20];
918
				memset(buf, 0, 20);
919
				if(!publisher->firefox)
920
					janus_rtcp_fir((char *)&buf, 20, &publisher->fir_seq);
921
				else
922
					janus_rtcp_fir_legacy((char *)&buf, 20, &publisher->fir_seq);
923
				JANUS_PRINT("Resuming publisher, sending FIR to %s\n", publisher->display);
924
				gateway->relay_rtcp(publisher->session->handle, 1, buf, 20);
925
				/* Send a PLI too, just in case... */
926
				memset(buf, 0, 12);
927
				janus_rtcp_pli((char *)&buf, 12);
928
				JANUS_PRINT("Resuming publisher, sending PLI to %s\n", publisher->display);
929
				gateway->relay_rtcp(publisher->session->handle, 1, buf, 12);
887 930
			} else if(!strcasecmp(request_text, "pause")) {
888 931
				/* Stop receiving the publisher streams for a while */
932
				janus_videoroom_participant *publisher = listener->feed;
889 933
				listener->paused = TRUE;
934
				event = json_object();
935
				json_object_set(event, "videoroom", json_string("event"));
936
				json_object_set(event, "room", json_integer(publisher->room->room_id));
937
				json_object_set(event, "result", json_string("ok"));
890 938
			} else if(!strcasecmp(request_text, "leave")) {
891 939
				janus_videoroom_participant *publisher = listener->feed;
892 940
				if(publisher != NULL) {
......
933 981
				msg->sdp = string_replace(msg->sdp, "sendrecv", "sendonly", &modified);	/* FIXME In case the browser doesn't set it correctly */
934 982
				msg->sdp = string_replace(msg->sdp, "sendonly", "recvonly", &modified);
935 983
				janus_videoroom_participant *participant = (janus_videoroom_participant *)session->participant;
984
				if(strstr(msg->sdp, "Mozilla")) {
985
					participant->firefox = TRUE;
986
				}
936 987
				/* How long will the gateway take to push the event? */
937
				gint64 start = g_get_monotonic_time();
988
				gint64 start = janus_get_monotonic_time();
938 989
				int res = gateway->push_event(msg->handle, &janus_videoroom_plugin, msg->transaction, event_text, type, msg->sdp);
939
				JANUS_PRINT("  >> Pushing event: %d (took %"SCNu64" ms)\n", res, g_get_monotonic_time()-start);
990
				JANUS_PRINT("  >> Pushing event: %d (took %"SCNu64" ms)\n", res, janus_get_monotonic_time()-start);
940 991
				msg->sdp = string_replace(msg->sdp, "recvonly", "sendonly", &modified);
941 992
				if(res != JANUS_OK) {
942 993
					/* TODO Failed to negotiate? We should remove this publisher */
......
979 1030
					janus_videoroom_participant *feed = (janus_videoroom_participant *)listener->feed;
980 1031
					if(feed != NULL && feed->sdp != NULL) {
981 1032
						/* How long will the gateway take to push the event? */
982
						gint64 start = g_get_monotonic_time();
1033
						gint64 start = janus_get_monotonic_time();
983 1034
						int res = gateway->push_event(msg->handle, &janus_videoroom_plugin, msg->transaction, event_text, type, feed->sdp);
984
						JANUS_PRINT("  >> Pushing event: %d (took %"SCNu64" ms)\n", res, g_get_monotonic_time()-start);
1035
						JANUS_PRINT("  >> Pushing event: %d (took %"SCNu64" ms)\n", res, janus_get_monotonic_time()-start);
985 1036
						if(res != JANUS_OK) {
986 1037
							/* TODO Failed to negotiate? We should remove this listener */
987 1038
						} else {

Also available in: Unified diff