Statistics
| Branch: | Revision:

janus-gateway / plugins / janus_audiobridge.c @ 5e9e29e0

History | View | Annotate | Download (40.9 KB)

1 be35facb meetecho
/*! \file   janus_audiobridge.c
2
 * \author Lorenzo Miniero <lorenzo@meetecho.com>
3
 * \copyright GNU Affero General Public License v3
4
 * \brief  Janus AudioBridge plugin
5
 * \details  This is a plugin implementing an audio conference bridge for
6
 * Janus, specifically mixing Opus streams. This means that it replies
7
 * by providing in the SDP only support for Opus, and disabling video.
8
 * Opus encoding and decoding is implemented using libopus (http://opus.codec.org).
9
 * The plugin provides an API to allow peers to join and leave conference
10
 * rooms. Peers can then mute/unmute themselves by sending specific messages
11
 * to the plugin: any way a peer mutes/unmutes, an event is triggered
12
 * to the other participants, so that it can be rendered in the UI
13
 * accordingly.
14
 * 
15
 * \todo Right now only wideband (16kHz) mixing is implemented.
16
 * 
17
 * Rooms to make available are listed in the plugin configuration file.
18
 * A pre-filled configuration file is provided in \c conf/janus.plugin.audiobridge.cfg
19
 * and includes a demo room for testing.
20
 * 
21
 * To add more rooms or modify the existing one, you can use the following
22
 * syntax:
23
 * 
24
 * \verbatim
25
[<unique room ID>]
26
description = This is my awesome room
27
sampling_rate = <sampling rate> (e.g., 16000 for wideband mixing)
28
\endverbatim
29
 *
30
 * \ingroup plugins
31
 * \ref plugins
32
 */
33
34
#include "plugin.h"
35
36
#include <jansson.h>
37
#include <opus/opus.h>
38
#include <sys/time.h>
39
40
#include "../config.h"
41
#include "../mutex.h"
42
#include "../rtp.h"
43
#include "../rtcp.h"
44 5e9e29e0 meetecho
#include "../utils.h"
45 be35facb meetecho
46
47
/* Plugin information */
48
#define JANUS_AUDIOBRIDGE_VERSION                        1
49
#define JANUS_AUDIOBRIDGE_VERSION_STRING        "0.0.1"
50
#define JANUS_AUDIOBRIDGE_DESCRIPTION                "This is a plugin implementing an audio conference bridge for Janus, mixing Opus streams."
51
#define JANUS_AUDIOBRIDGE_NAME                                "JANUS AudioBridge plugin"
52
#define JANUS_AUDIOBRIDGE_PACKAGE                        "janus.plugin.audiobridge"
53
54
/* Plugin methods */
55
janus_plugin *create(void);
56
int janus_audiobridge_init(janus_callbacks *callback, const char *config_path);
57
void janus_audiobridge_destroy(void);
58
int janus_audiobridge_get_version(void);
59
const char *janus_audiobridge_get_version_string(void);
60
const char *janus_audiobridge_get_description(void);
61
const char *janus_audiobridge_get_name(void);
62
const char *janus_audiobridge_get_package(void);
63
void janus_audiobridge_create_session(janus_pluginession *handle, int *error);
64
void janus_audiobridge_handle_message(janus_pluginession *handle, char *transaction, char *message, char *sdp_type, char *sdp);
65
void janus_audiobridge_setup_media(janus_pluginession *handle);
66
void janus_audiobridge_incoming_rtp(janus_pluginession *handle, int video, char *buf, int len);
67
void janus_audiobridge_incoming_rtcp(janus_pluginession *handle, int video, char *buf, int len);
68
void janus_audiobridge_hangup_media(janus_pluginession *handle);
69
void janus_audiobridge_destroy_session(janus_pluginession *handle, int *error);
70
71
/* Plugin setup */
72
static janus_plugin janus_audiobridge_plugin =
73
        {
74
                .init = janus_audiobridge_init,
75
                .destroy = janus_audiobridge_destroy,
76
77
                .get_version = janus_audiobridge_get_version,
78
                .get_version_string = janus_audiobridge_get_version_string,
79
                .get_description = janus_audiobridge_get_description,
80
                .get_name = janus_audiobridge_get_name,
81
                .get_package = janus_audiobridge_get_package,
82
                
83
                .create_session = janus_audiobridge_create_session,
84
                .handle_message = janus_audiobridge_handle_message,
85
                .setup_media = janus_audiobridge_setup_media,
86
                .incoming_rtp = janus_audiobridge_incoming_rtp,
87
                .incoming_rtcp = janus_audiobridge_incoming_rtcp,
88
                .hangup_media = janus_audiobridge_hangup_media,
89
                .destroy_session = janus_audiobridge_destroy_session,
90
        }; 
91
92
/* Plugin creator */
93
janus_plugin *create(void) {
94
        JANUS_PRINT("%s created!\n", JANUS_AUDIOBRIDGE_NAME);
95
        return &janus_audiobridge_plugin;
96
}
97
98
99
/* Useful stuff */
100
static int initialized = 0, stopping = 0;
101
static janus_callbacks *gateway = NULL;
102
static GThread *handler_thread;
103
static void *janus_audiobridge_handler(void *data);
104
static void janus_audiobridge_relay_rtp_packet(gpointer data, gpointer user_data);
105
static void *janus_audiobridge_mixer_thread(void *data);
106
107
typedef struct janus_audiobridge_message {
108
        janus_pluginession *handle;
109
        char *transaction;
110
        char *message;
111
        char *sdp_type;
112
        char *sdp;
113
} janus_audiobridge_message;
114
GQueue *messages;
115
116
typedef struct janus_audiobridge_room {
117
        guint64 room_id;        /* Unique room ID */
118
        gchar *room_name;        /* Room description */
119
        uint32_t sampling_rate;        /* Sampling rate of the mix (e.g., 16000 for wideband) */
120
        gboolean record;
121
        FILE *recording;
122
        gboolean destroy;
123
        GHashTable *participants;        /* Map of participants */
124
        janus_mutex mutex;
125
} janus_audiobridge_room;
126
GHashTable *rooms;
127
128
typedef struct janus_audiobridge_session {
129
        janus_pluginession *handle;
130
        gpointer participant;
131
        gboolean started;
132
        gboolean stopping;
133
        gboolean destroy;
134
} janus_audiobridge_session;
135
GHashTable *sessions;
136
137
typedef struct janus_audiobridge_participant {
138
        janus_audiobridge_session *session;
139
        janus_audiobridge_room *room;        /* Room */
140
        guint64 user_id;        /* Unique ID in the room */
141
        gchar *display;        /* Display name (just for fun) */
142
        gboolean audio_active;
143
        /* RTP stuff */
144
        GQueue *inbuf;
145
        int opus_pt;
146
        /* Opus stuff */
147
        OpusEncoder *encoder;
148
        OpusDecoder *decoder;
149
} janus_audiobridge_participant;
150
151
/* Packets we get from gstreamer and relay */
152
typedef struct janus_audiobridge_rtp_relay_packet {
153
        rtp_header *data;
154
        gint length;
155
} janus_audiobridge_rtp_relay_packet;
156
157
/* SDP offer/answer template */
158
static const char *sdp_template =
159
                "v=0\r\n"
160
                "o=- %"SCNu64" %"SCNu64" IN IP4 127.0.0.1\r\n"        /* We need current time here */
161
                "s=%s\r\n"                                                        /* Audio bridge name */
162
                "t=0 0\r\n"
163
                "m=audio 1 RTP/SAVPF %d\r\n"                /* Opus payload type */
164
                "c=IN IP4 1.1.1.1\r\n"
165
                "a=rtpmap:%d opus/48000/2\r\n"                /* Opus payload type */
166
                "a=fmtp:%d maxplaybackrate=%d; stereo=0; sprop-stereo=0; useinbandfec=0\r\n"
167
                                                                                        /* Opus payload type and room sampling rate */
168
                "a=mid:audio\r\n";
169
170
/* Helper struct to generate and parse WAVE headers */
171
typedef struct wav_header {
172
        char riff[4];
173
        uint32_t len;
174
        char wave[4];
175
        char fmt[4];
176
        uint32_t formatsize;
177
        uint16_t format;
178
        uint16_t channels;
179
        uint32_t samplerate;
180
        uint32_t avgbyterate;
181
        uint16_t samplebytes;
182
        uint16_t channelbits;
183
        char data[4];
184
        uint32_t blocksize;
185
} wav_header;
186
187
188
/* Opus settings */                
189
#define        BUFFER_SAMPLES        8000
190
#define        OPUS_SAMPLES        160
191
#define USE_FEC                        0
192
#define DEFAULT_COMPLEXITY        4
193
194
195
/* Plugin implementation */
196
int janus_audiobridge_init(janus_callbacks *callback, const char *config_path) {
197
        if(stopping) {
198
                /* Still stopping from before */
199
                return -1;
200
        }
201
        if(callback == NULL || config_path == NULL) {
202
                /* Invalid arguments */
203
                return -1;
204
        }
205
206
        /* Read configuration */
207
        char filename[255];
208
        sprintf(filename, "%s/%s.cfg", config_path, JANUS_AUDIOBRIDGE_PACKAGE);
209
        JANUS_PRINT("Configuration file: %s\n", filename);
210
        janus_config *config = janus_config_parse(filename);
211
        if(config != NULL)
212
                janus_config_print(config);
213
        
214
        rooms = g_hash_table_new(NULL, NULL);
215
        sessions = g_hash_table_new(NULL, NULL);
216
        messages = g_queue_new();
217
        /* This is the callback we'll need to invoke to contact the gateway */
218
        gateway = callback;
219
220
        /* Parse configuration to populate the rooms list */
221
        if(config != NULL) {
222
                janus_config_category *cat = janus_config_get_categories(config);
223
                while(cat != NULL) {
224
                        if(cat->name == NULL) {
225
                                cat = cat->next;
226
                                continue;
227
                        }
228
                        JANUS_PRINT("Adding audio room '%s'\n", cat->name);
229
                        janus_config_item *desc = janus_config_get_item(cat, "description");
230
                        janus_config_item *sampling = janus_config_get_item(cat, "sampling_rate");
231
                        janus_config_item *record = janus_config_get_item(cat, "record");
232
                        if(sampling == NULL || sampling->value == NULL) {
233
                                JANUS_DEBUG("Can't add the audio room, missing mandatory information...\n");
234
                                cat = cat->next;
235
                                continue;
236
                        }
237
                        /* Create the audio bridge room */
238
                        janus_audiobridge_room *audiobridge = calloc(1, sizeof(janus_audiobridge_room));
239
                        if(audiobridge == NULL) {
240
                                JANUS_DEBUG("Memory error!\n");
241
                                continue;
242
                        }
243
                        audiobridge->room_id = atoi(cat->name);
244
                        char *description = NULL;
245
                        if(desc != NULL && desc->value != NULL)
246
                                description = g_strdup(desc->value);
247
                        else
248
                                description = g_strdup(cat->name);
249
                        if(description == NULL) {
250
                                JANUS_DEBUG("Memory error!\n");
251
                                continue;
252
                        }
253
                        audiobridge->room_name = description;
254
                        audiobridge->sampling_rate = atoi(sampling->value);
255
                        if(audiobridge->sampling_rate != 16000) {
256
                                JANUS_DEBUG("We currently only support 16kHz (wideband) as a sampling rate for audio rooms, changing %"SCNu32" to 16000...\n", audiobridge->sampling_rate);
257
                                audiobridge->sampling_rate = 16000;
258
                        }
259
                        audiobridge->record = FALSE;
260
                        if(record && record->value && !strcasecmp(record->value, "yes"))
261
                                audiobridge->record = TRUE;
262
                        audiobridge->recording = NULL;
263
                        audiobridge->destroy = 0;
264
                        audiobridge->participants = g_hash_table_new(NULL, NULL);
265
                        janus_mutex_init(&audiobridge->mutex);
266
                        g_hash_table_insert(rooms, GUINT_TO_POINTER(audiobridge->room_id), audiobridge);
267
                        JANUS_PRINT("Created audiobridge: %"SCNu64" (%s)\n", audiobridge->room_id, audiobridge->room_name);
268
                        /* We need a thread for the mix */
269
                        g_thread_new("audiobridge mixer thread", &janus_audiobridge_mixer_thread, audiobridge);
270
                        cat = cat->next;
271
                }
272
                /* Done */
273
                janus_config_destroy(config);
274
                config = NULL;
275
        }
276
277
        /* Show available rooms */
278
        GList *rooms_list = g_hash_table_get_values(rooms);
279
        GList *r = rooms_list;
280
        while(r) {
281
                janus_audiobridge_room *ar = (janus_audiobridge_room *)r->data;
282
                JANUS_PRINT("  ::: [%"SCNu64"][%s] %"SCNu32" (%s be recorded)\n",
283
                        ar->room_id, ar->room_name, ar->sampling_rate, ar->record ? "will" : "will NOT");
284
                r = r->next;
285
        }
286
        g_list_free(rooms_list);
287
288
        initialized = 1;
289
        /* Launch the thread that will handle incoming messages */
290
        GError *error = NULL;
291
        handler_thread = g_thread_try_new("janus audiobridge handler", janus_audiobridge_handler, NULL, &error);
292
        if(error != NULL) {
293
                initialized = 0;
294
                /* Something went wrong... */
295
                JANUS_DEBUG("Got error %d (%s) trying to launch thread...\n", error->code, error->message ? error->message : "??");
296
                return -1;
297
        }
298
        JANUS_PRINT("%s initialized!\n", JANUS_AUDIOBRIDGE_NAME);
299
        return 0;
300
}
301
302
void janus_audiobridge_destroy() {
303
        if(!initialized)
304
                return;
305
        stopping = 1;
306
        if(handler_thread != NULL) {
307
                g_thread_join(handler_thread);
308
        }
309
        handler_thread = NULL;
310
        /* TODO Actually remove rooms and its participants */
311
        g_hash_table_destroy(sessions);
312
        g_hash_table_destroy(rooms);
313
        g_queue_free(messages);
314
        sessions = NULL;
315
        initialized = 0;
316
        JANUS_PRINT("%s destroyed!\n", JANUS_AUDIOBRIDGE_NAME);
317
}
318
319
int janus_audiobridge_get_version() {
320
        return JANUS_AUDIOBRIDGE_VERSION;
321
}
322
323
const char *janus_audiobridge_get_version_string() {
324
        return JANUS_AUDIOBRIDGE_VERSION_STRING;
325
}
326
327
const char *janus_audiobridge_get_description() {
328
        return JANUS_AUDIOBRIDGE_DESCRIPTION;
329
}
330
331
const char *janus_audiobridge_get_name() {
332
        return JANUS_AUDIOBRIDGE_NAME;
333
}
334
335
const char *janus_audiobridge_get_package() {
336
        return JANUS_AUDIOBRIDGE_PACKAGE;
337
}
338
339
void janus_audiobridge_create_session(janus_pluginession *handle, int *error) {
340
        if(stopping || !initialized) {
341
                *error = -1;
342
                return;
343
        }        
344
        janus_audiobridge_session *session = (janus_audiobridge_session *)calloc(1, sizeof(janus_audiobridge_session));
345
        if(session == NULL) {
346
                JANUS_DEBUG("Memory error!\n");
347
                *error = -2;
348
                return;
349
        }
350
        session->handle = handle;
351
        session->started = FALSE;
352
        session->stopping = FALSE;
353
        session->destroy = FALSE;
354
        handle->plugin_handle = session;
355
        g_hash_table_insert(sessions, handle, session);
356
357
        return;
358
}
359
360
void janus_audiobridge_destroy_session(janus_pluginession *handle, int *error) {
361
        if(stopping || !initialized) {
362
                *error = -1;
363
                return;
364
        }        
365
        janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle; 
366
        if(!session) {
367
                JANUS_DEBUG("No session associated with this handle...\n");
368
                *error = -2;
369
                return;
370
        }
371
        if(session->destroy) {
372
                JANUS_PRINT("Session already destroyed...\n");
373
                g_free(session);
374
                return;
375
        }
376
        JANUS_PRINT("Removing Audio Bridge session...\n");
377
        g_hash_table_remove(sessions, handle);
378
        janus_audiobridge_hangup_media(handle);
379
        session->destroy = TRUE;
380
        g_free(session);
381
382
        return;
383
}
384
385
void janus_audiobridge_handle_message(janus_pluginession *handle, char *transaction, char *message, char *sdp_type, char *sdp) {
386
        if(stopping || !initialized)
387
                return;
388
        JANUS_PRINT("%s\n", message);
389
        janus_audiobridge_message *msg = calloc(1, sizeof(janus_audiobridge_message));
390
        if(msg == NULL) {
391
                JANUS_DEBUG("Memory error!\n");
392
                return;
393
        }
394
        msg->handle = handle;
395
        msg->transaction = transaction ? g_strdup(transaction) : NULL;
396
        msg->message = message;
397
        msg->sdp_type = sdp_type;
398
        msg->sdp = sdp;
399
        g_queue_push_tail(messages, msg);
400
}
401
402
void janus_audiobridge_setup_media(janus_pluginession *handle) {
403
        JANUS_DEBUG("WebRTC media is now available\n");
404
        if(stopping || !initialized)
405
                return;
406
        janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;        
407
        if(!session) {
408
                JANUS_DEBUG("No session associated with this handle...\n");
409
                return;
410
        }
411
        if(session->destroy)
412
                return;
413
        /* TODO Only send this peer the audio mix when we get this event */
414
}
415
416
void janus_audiobridge_incoming_rtp(janus_pluginession *handle, int video, char *buf, int len) {
417
        if(stopping || !initialized)
418
                return;
419
        janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;        
420
        if(!session || session->destroy || session->stopping || !session->participant)
421
                return;
422
        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
423
        if(!participant->audio_active)
424
                return;
425
        /* Decode frame (Opus -> slinear) */
426
        janus_audiobridge_rtp_relay_packet *pkt = calloc(1, sizeof(janus_audiobridge_rtp_relay_packet));
427
        if(pkt == NULL) {
428
                JANUS_DEBUG("Memory error!\n");
429
                return;
430
        }
431
        pkt->data = calloc(BUFFER_SAMPLES, sizeof(opus_int16));
432
        if(pkt->data == NULL) {
433
                JANUS_DEBUG("Memory error!\n");
434
                g_free(pkt);
435
                return;
436
        }
437
        pkt->length = opus_decode(participant->decoder, (const unsigned char *)buf+12, len-12, (opus_int16 *)pkt->data, BUFFER_SAMPLES, USE_FEC);
438
        if(pkt->length < 0) {
439
                JANUS_PRINT("[Opus] Ops! got an error decoding the Opus frame: %d (%s)\n", pkt->length, opus_strerror(pkt->length));
440
                g_free(pkt->data);
441
                g_free(pkt);
442
                return;
443
        }
444
        /* Enqueue the decoded frame */
445
        g_queue_push_tail(participant->inbuf, pkt);
446
}
447
448
void janus_audiobridge_incoming_rtcp(janus_pluginession *handle, int video, char *buf, int len) {
449
        if(stopping || !initialized)
450
                return;
451
        /* FIXME Should we care? */
452
}
453
454
void janus_audiobridge_hangup_media(janus_pluginession *handle) {
455
        JANUS_PRINT("No WebRTC media anymore\n");
456
        if(stopping || !initialized)
457
                return;
458
        janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;
459
        if(!session) {
460
                JANUS_DEBUG("No session associated with this handle...\n");
461
                return;
462
        }
463
        if(session->destroy || !session->participant)
464
                return;
465
        /* Get rid of participant */
466
        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
467
        janus_audiobridge_room *audiobridge = participant->room;
468
        janus_mutex_lock(&audiobridge->mutex);
469
        json_t *event = json_object();
470
        json_object_set(event, "audiobridge", json_string("event"));
471
        json_object_set(event, "room", json_integer(audiobridge->room_id));
472
        json_object_set(event, "leaving", json_integer(participant->user_id));
473
        char *leaving_text = json_dumps(event, JSON_INDENT(3));
474
        json_decref(event);
475
        g_hash_table_remove(audiobridge->participants, GUINT_TO_POINTER(participant->user_id));
476
        GList *participants_list = g_hash_table_get_values(audiobridge->participants);
477
        GList *ps = participants_list;
478
        while(ps) {
479
                janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
480
                if(p == participant) {
481
                        ps = ps->next;
482
                        continue;        /* Skip the leaving participant itself */
483
                }
484
                JANUS_PRINT("Notifying participant %"SCNu64" (%s)\n", p->user_id, p->display);
485
                JANUS_PRINT("  >> %d\n", gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, leaving_text, NULL, NULL));
486
                ps = ps->next;
487
        }
488
        g_free(leaving_text);
489
        g_list_free(participants_list);
490
        participant->audio_active = 0;
491
        session->started = FALSE;
492
        session->destroy = 1;
493
        janus_mutex_unlock(&audiobridge->mutex);
494
}
495
496
/* Thread to handle incoming messages */
497
static void *janus_audiobridge_handler(void *data) {
498
        JANUS_DEBUG("Joining thread\n");
499
        janus_audiobridge_message *msg = NULL;
500
        char *error_cause = calloc(512, sizeof(char));        /* FIXME 512 should be enough, but anyway... */
501
        if(error_cause == NULL) {
502
                JANUS_DEBUG("Memory error!\n");
503
                return NULL;
504
        }
505
        while(initialized && !stopping) {
506
                if(!messages || (msg = g_queue_pop_head(messages)) == NULL) {
507
                        usleep(50000);
508
                        continue;
509
                }
510
                janus_audiobridge_session *session = (janus_audiobridge_session *)msg->handle->plugin_handle;        
511
                if(!session) {
512
                        JANUS_DEBUG("No session associated with this handle...\n");
513
                        continue;
514
                }
515
                if(session->destroy)
516
                        continue;
517
                /* Handle request */
518
                JANUS_PRINT("Handling message: %s\n", msg->message);
519
                if(msg->message == NULL) {
520
                        JANUS_DEBUG("No message??\n");
521
                        sprintf(error_cause, "%s", "No message??");
522
                        goto error;
523
                }
524
                json_error_t error;
525
                json_t *root = json_loads(msg->message, 0, &error);
526
                if(!root) {
527
                        JANUS_DEBUG("JSON error: on line %d: %s\n", error.line, error.text);
528
                        sprintf(error_cause, "JSON error: on line %d: %s", error.line, error.text);
529
                        goto error;
530
                }
531
                if(!json_is_object(root)) {
532
                        JANUS_DEBUG("JSON error: not an object\n");
533
                        sprintf(error_cause, "JSON error: not an object");
534
                        goto error;
535
                }
536
                /* Get the request first */
537
                json_t *request = json_object_get(root, "request");
538
                if(!request || !json_is_string(request)) {
539
                        JANUS_DEBUG("JSON error: invalid element (request)\n");
540
                        sprintf(error_cause, "JSON error: invalid element (request)");
541
                        goto error;
542
                }
543
                const char *request_text = json_string_value(request);
544
                json_t *event = NULL;
545 47576630 meetecho
                if(!strcasecmp(request_text, "create")) {
546
                        /* Create a new audiobridge */
547
                        JANUS_PRINT("Creating a new audiobridge\n");
548
                        json_t *desc = json_object_get(root, "description");
549
                        if(desc && !json_is_string(desc)) {
550
                                JANUS_DEBUG("JSON error: invalid element (desc)\n");
551
                                sprintf(error_cause, "JSON error: invalid element (desc)");
552
                                goto error;
553
                        }
554
                        json_t *sampling = json_object_get(root, "sampling");
555
                        if(sampling && !json_is_integer(sampling)) {
556
                                JANUS_DEBUG("JSON error: invalid element (sampling)\n");
557
                                sprintf(error_cause, "JSON error: invalid element (sampling)");
558
                                goto error;
559
                        }
560
                        json_t *record = json_object_get(root, "record");
561
                        if(record && !json_is_boolean(record)) {
562
                                JANUS_DEBUG("JSON error: invalid element (record)\n");
563
                                sprintf(error_cause, "JSON error: invalid value (record)");
564
                                goto error;
565
                        }
566
                        /* Create the audio bridge room */
567
                        janus_audiobridge_room *audiobridge = calloc(1, sizeof(janus_audiobridge_room));
568
                        if(audiobridge == NULL) {
569
                                JANUS_DEBUG("Memory error!\n");
570
                                sprintf(error_cause, "Memory error");
571
                                goto error;
572
                        }
573
                        /* Generate a random ID */
574
                        guint64 room_id = 0;
575
                        while(room_id == 0) {
576
                                room_id = g_random_int();
577
                                if(g_hash_table_lookup(rooms, GUINT_TO_POINTER(room_id)) != NULL) {
578
                                        /* Room ID already taken, try another one */
579
                                        room_id = 0;
580
                                }
581
                        }
582
                        audiobridge->room_id = room_id;
583
                        char *description = NULL;
584
                        if(desc != NULL) {
585
                                description = g_strdup(json_string_value(desc));
586
                        } else {
587
                                char roomname[255];
588
                                sprintf(roomname, "Room %"SCNu64"", audiobridge->room_id);
589
                                description = g_strdup(roomname);
590
                        }
591
                        if(description == NULL) {
592
                                JANUS_DEBUG("Memory error!\n");
593
                                continue;
594
                        }
595
                        audiobridge->room_name = description;
596
                        if(sampling)
597
                                audiobridge->sampling_rate = json_integer_value(sampling);
598
                        else
599
                                audiobridge->sampling_rate = 16000;
600
                        if(audiobridge->sampling_rate != 16000) {
601
                                JANUS_DEBUG("We currently only support 16kHz (wideband) as a sampling rate for audio rooms, changing %"SCNu32" to 16000...\n", audiobridge->sampling_rate);
602
                                audiobridge->sampling_rate = 16000;
603
                        }
604
                        audiobridge->record = FALSE;
605
                        if(record && json_is_true(record))
606
                                audiobridge->record = TRUE;
607
                        audiobridge->recording = NULL;
608
                        audiobridge->destroy = 0;
609
                        audiobridge->participants = g_hash_table_new(NULL, NULL);
610
                        janus_mutex_init(&audiobridge->mutex);
611
                        g_hash_table_insert(rooms, GUINT_TO_POINTER(audiobridge->room_id), audiobridge);
612
                        JANUS_PRINT("Created audiobridge: %"SCNu64" (%s)\n", audiobridge->room_id, audiobridge->room_name);
613
                        /* We need a thread for the mix */
614
                        g_thread_new("audiobridge mixer thread", &janus_audiobridge_mixer_thread, audiobridge);
615
                        /* Show updated rooms list */
616
                        GList *rooms_list = g_hash_table_get_values(rooms);
617
                        GList *r = rooms_list;
618
                        while(r) {
619
                                janus_audiobridge_room *ar = (janus_audiobridge_room *)r->data;
620
                                JANUS_PRINT("  ::: [%"SCNu64"][%s] %"SCNu32" (%s be recorded)\n",
621
                                        ar->room_id, ar->room_name, ar->sampling_rate, ar->record ? "will" : "will NOT");
622
                                r = r->next;
623
                        }
624
                        g_list_free(rooms_list);
625
                        /* Send info back */
626
                        event = json_object();
627
                        json_object_set(event, "audiobridge", json_string("created"));
628
                        json_object_set(event, "room", json_integer(audiobridge->room_id));
629
                } else if(!strcasecmp(request_text, "join")) {
630 be35facb meetecho
                        JANUS_PRINT("Configuring new participant\n");
631
                        json_t *room = json_object_get(root, "room");
632
                        if(!room || !json_is_integer(room)) {
633
                                JANUS_DEBUG("JSON error: invalid element (room)\n");
634
                                sprintf(error_cause, "JSON error: invalid element (room)");
635
                                goto error;
636
                        }
637
                        guint64 room_id = json_integer_value(room);
638
                        janus_audiobridge_room *audiobridge = g_hash_table_lookup(rooms, GUINT_TO_POINTER(room_id));
639
                        if(audiobridge == NULL) {
640
                                JANUS_DEBUG("No such room (%"SCNu64")\n", room_id);
641
                                sprintf(error_cause, "No such room (%"SCNu64")", room_id);
642
                                goto error;
643
                        }
644
                        json_t *display = json_object_get(root, "display");
645
                        if(!display || !json_is_string(display)) {
646
                                JANUS_DEBUG("JSON error: invalid element (display)\n");
647
                                sprintf(error_cause, "JSON error: invalid element (display)");
648
                                goto error;
649
                        }
650
                        const char *display_text = json_string_value(display);
651
                        /* Generate a random ID */
652
                        guint64 user_id = 0;
653
                        while(user_id == 0) {
654
                                user_id = g_random_int();
655
                                if(g_hash_table_lookup(audiobridge->participants, GUINT_TO_POINTER(user_id)) != NULL) {
656
                                        /* User ID already taken, try another one */
657
                                        user_id = 0;
658
                                }
659
                        }
660
                        JANUS_PRINT("  -- Participant ID: %"SCNu64"\n", user_id);
661
                        janus_audiobridge_participant *participant = calloc(1, sizeof(janus_audiobridge_participant));
662
                        if(participant == NULL) {
663
                                JANUS_DEBUG("Memory error!\n");
664
                                sprintf(error_cause, "Memory error");
665
                                goto error;
666
                        }
667
                        participant->session = session;
668
                        participant->room = audiobridge;
669
                        participant->user_id = user_id;
670
                        participant->display = g_strdup(display_text);
671
                        if(participant->display == NULL) {
672
                                JANUS_DEBUG("Memory error!\n");
673
                                sprintf(error_cause, "Memory error");
674
                                g_free(participant);
675
                                goto error;
676
                        }
677
                        participant->audio_active = FALSE;
678
                        participant->inbuf = g_queue_new();
679
                        participant->opus_pt = 0;
680
                        JANUS_PRINT("Creating Opus encoder/decoder (sampling rate %d)\n", audiobridge->sampling_rate);
681
                        /* Opus encoder */
682
                        int error = 0;
683
                        participant->encoder = opus_encoder_create(audiobridge->sampling_rate, 1, OPUS_APPLICATION_VOIP, &error);
684
                        if(error != OPUS_OK) {
685
                                g_free(participant->display);
686
                                g_free(participant);
687
                                JANUS_DEBUG("Error creating Opus encoder\n");
688
                                sprintf(error_cause, "Error creating Opus decoder");
689
                                goto error;
690
                        }
691
                        if(audiobridge->sampling_rate == 8000)
692
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
693
                        else if(audiobridge->sampling_rate == 12000)
694
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_MEDIUMBAND));
695
                        else if(audiobridge->sampling_rate == 16000)
696
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
697
                        else if(audiobridge->sampling_rate == 24000)
698
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
699
                        else if(audiobridge->sampling_rate == 48000)
700
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
701
                        else
702
                                JANUS_PRINT("Unsupported sampling rate %d\n", audiobridge->sampling_rate);
703
                        /* FIXME This settings should be configurable */
704
                        opus_encoder_ctl(participant->encoder, OPUS_SET_INBAND_FEC(USE_FEC));
705
                        opus_encoder_ctl(participant->encoder, OPUS_SET_COMPLEXITY(DEFAULT_COMPLEXITY));
706
                        /* Opus decoder */
707
                        error = 0;
708
                        participant->decoder = opus_decoder_create(audiobridge->sampling_rate, 1, &error);
709
                        if(error != OPUS_OK) {
710
                                g_free(participant->display);
711
                                if(participant->encoder)
712
                                        opus_encoder_destroy(participant->encoder);
713
                                if(participant->decoder)
714
                                        opus_decoder_destroy(participant->decoder);
715
                                g_free(participant);
716
                                JANUS_DEBUG("Error creating Opus encoder\n");
717
                                sprintf(error_cause, "Error creating Opus decoder");
718
                                goto error;
719
                        }
720
721
                        /* Done */
722
                        janus_mutex_lock(&audiobridge->mutex);
723
                        session->participant = participant;
724
                        g_hash_table_insert(audiobridge->participants, GUINT_TO_POINTER(user_id), participant);
725
                        /* Return a list of all available participants (those with an SDP available, that is) */
726
                        json_t *list = json_array();
727
                        GList *participants_list = g_hash_table_get_values(audiobridge->participants);
728
                        GList *ps = participants_list;
729
                        while(ps) {
730
                                janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
731
                                if(p == participant) {
732
                                        ps = ps->next;
733
                                        continue;
734
                                }
735
                                json_t *pl = json_object();
736
                                json_object_set_new(pl, "id", json_integer(p->user_id));
737
                                json_object_set_new(pl, "display", json_string(p->display));
738
                                //~ json_object_set_new(pl, "muted", json_boolean(!p->audio_active));
739
                                json_object_set_new(pl, "muted", json_string(p->audio_active ? "false" : "true"));
740
                                json_array_append_new(list, pl);
741
                                ps = ps->next;
742
                        }
743
                        event = json_object();
744
                        json_object_set(event, "audiobridge", json_string("joined"));
745
                        json_object_set(event, "room", json_integer(audiobridge->room_id));
746
                        json_object_set(event, "id", json_integer(user_id));
747
                        json_object_set_new(event, "participants", list);
748
                        g_list_free(participants_list);
749
                        janus_mutex_unlock(&audiobridge->mutex);
750
                } else if(!strcasecmp(request_text, "configure")) {
751
                        /* Handle this participant */
752
                        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
753
                        if(participant == NULL || participant->room == NULL) {
754
                                JANUS_DEBUG("Can't configure (not in a room)\n");
755
                                sprintf(error_cause, "Can't configure (not in a room)");
756
                                goto error;
757
                        }
758
                        /* Configure settings for this participant */
759
                        json_t *audio = json_object_get(root, "audio");
760
                        if(audio && !json_is_boolean(audio)) {
761
                                JANUS_DEBUG("JSON error: invalid element (audio)\n");
762
                                sprintf(error_cause, "JSON error: invalid value (audio)");
763
                                goto error;
764
                        }
765
                        if(audio) {
766
                                participant->audio_active = json_is_true(audio);
767
                                JANUS_PRINT("Setting audio property: %s (room %"SCNu64", user %"SCNu64")\n", participant->audio_active ? "true" : "false", participant->room->room_id, participant->user_id);
768
                                if(!participant->audio_active) {
769
                                        /* Clear the queued packets waiting to be handled */
770
                                        while(!g_queue_is_empty(participant->inbuf)) {
771
                                                janus_audiobridge_rtp_relay_packet *pkt = g_queue_pop_head(participant->inbuf);
772
                                                if(pkt == NULL)
773
                                                        continue;
774
                                                if(pkt->data)
775
                                                        g_free(pkt->data);
776
                                                g_free(pkt);
777
                                        }
778
                                }
779
                                /* Notify all other participants about the mute/unmute */
780
                                janus_audiobridge_room *audiobridge = participant->room;
781
                                janus_mutex_lock(&audiobridge->mutex);
782
                                json_t *list = json_array();
783
                                json_t *pl = json_object();
784
                                json_object_set_new(pl, "id", json_integer(participant->user_id));
785
                                json_object_set_new(pl, "display", json_string(participant->display));
786
                                //~ json_object_set_new(pl, "muted", json_boolean(!participant->audio_active));
787
                                json_object_set_new(pl, "muted", json_string(participant->audio_active ? "false" : "true"));
788
                                json_array_append_new(list, pl);
789
                                json_t *pub = json_object();
790
                                json_object_set(pub, "audiobridge", json_string("event"));
791
                                json_object_set(pub, "room", json_integer(participant->room->room_id));
792
                                json_object_set_new(pub, "participants", list);
793
                                char *pub_text = json_dumps(pub, JSON_INDENT(3));
794
                                json_decref(list);
795
                                json_decref(pub);
796
                                GList *participants_list = g_hash_table_get_values(participant->room->participants);
797
                                GList *ps = participants_list;
798
                                while(ps) {
799
                                        janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
800
                                        if(p == participant) {
801
                                                ps = ps->next;
802
                                                continue;        /* Skip the new participant itself */
803
                                        }
804
                                        JANUS_PRINT("Notifying participant %"SCNu64" (%s)\n", p->user_id, p->display);
805
                                        JANUS_PRINT("  >> %d\n", gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, pub_text, NULL, NULL));
806
                                        ps = ps->next;
807
                                }
808
                                g_list_free(participants_list);
809
                                janus_mutex_unlock(&audiobridge->mutex);
810
                        }
811
                        /* Done */
812
                        event = json_object();
813
                        json_object_set(event, "audiobridge", json_string("event"));
814
                        json_object_set(event, "room", json_integer(participant->room->room_id));
815
                        json_object_set(event, "result", json_string("ok"));
816
                } else if(!strcasecmp(request_text, "leave")) {
817
                        /* This participant is leaving */
818
                        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
819
                        if(participant == NULL || participant->room == NULL) {
820
                                JANUS_DEBUG("Can't leave (not in a room)\n");
821
                                sprintf(error_cause, "Can't leave (not in a room)");
822
                                goto error;
823
                        }
824
                        /* Tell everybody */
825
                        janus_audiobridge_room *audiobridge = participant->room;
826
                        janus_mutex_lock(&audiobridge->mutex);
827
                        event = json_object();
828
                        json_object_set(event, "audiobridge", json_string("event"));
829
                        json_object_set(event, "room", json_integer(audiobridge->room_id));
830
                        json_object_set(event, "leaving", json_integer(participant->user_id));
831
                        char *leaving_text = json_dumps(event, JSON_INDENT(3));
832
                        GList *participants_list = g_hash_table_get_values(audiobridge->participants);
833
                        GList *ps = participants_list;
834
                        while(ps) {
835
                                janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
836
                                if(p == participant) {
837
                                        ps = ps->next;
838
                                        continue;        /* Skip the new participant itself */
839
                                }
840
                                JANUS_PRINT("Notifying participant %"SCNu64" (%s)\n", p->user_id, p->display);
841
                                JANUS_PRINT("  >> %d\n", gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, leaving_text, NULL, NULL));
842
                                ps = ps->next;
843
                        }
844
                        g_free(leaving_text);
845
                        g_list_free(participants_list);
846
                        /* Done */
847
                        participant->audio_active = 0;
848
                        session->started = FALSE;
849
                        session->destroy = 1;
850
                        janus_mutex_unlock(&audiobridge->mutex);
851
                } else {
852
                        JANUS_DEBUG("Unknown request '%s'\n", request_text);
853
                        sprintf(error_cause, "Unknown request '%s'", request_text);
854
                        goto error;
855
                }
856
857
                /* Prepare JSON event */
858
                JANUS_PRINT("Preparing JSON event as a reply\n");
859
                char *event_text = json_dumps(event, JSON_INDENT(3));
860
                json_decref(event);
861
                /* Any SDP to handle? */
862
                if(!msg->sdp) {
863
                        JANUS_PRINT("  >> %d\n", gateway->push_event(msg->handle, &janus_audiobridge_plugin, msg->transaction, event_text, NULL, NULL));
864
                } else {
865
                        JANUS_PRINT("This is involving a negotiation (%s) as well:\n%s\n", msg->sdp_type, msg->sdp);
866
                        char *type = NULL;
867
                        if(!strcasecmp(msg->sdp_type, "offer"))
868
                                type = "answer";
869
                        if(!strcasecmp(msg->sdp_type, "answer"))
870
                                type = "offer";
871
                        /* Fill the SDP template and use that as our answer */
872
                        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
873
                        char sdp[1024];
874
                        /* What is the Opus payload type? */
875
                        participant->opus_pt = 0;
876
                        char *fmtp = strstr(msg->sdp, "opus/48000");
877
                        if(fmtp != NULL) {
878
                                fmtp -= 5;
879
                                fmtp = strstr(fmtp, ":");
880
                                if(fmtp)
881
                                        fmtp++;
882
                                participant->opus_pt = atoi(fmtp);
883
                        }
884
                        JANUS_PRINT("Opus payload type is %d\n", participant->opus_pt);
885
                        g_sprintf(sdp, sdp_template,
886 5e9e29e0 meetecho
                                janus_get_monotonic_time(),                /* We need current time here */
887
                                janus_get_monotonic_time(),                /* We need current time here */
888 be35facb meetecho
                                participant->room->room_name,        /* Audio bridge name */
889
                                participant->opus_pt,                        /* Opus payload type */
890
                                participant->opus_pt,                        /* Opus payload type */
891
                                participant->opus_pt,                         /* Opus payload type and room sampling rate */
892
                                participant->room->sampling_rate);
893
                        /* Did the peer negotiate video? */
894
                        if(strstr(msg->sdp, "m=video") != NULL) {
895
                                /* If so, reject it */
896
                                g_strlcat(sdp, "m=video 0 RTP/SAVPF 0\r\n", 1024);                                
897
                        }
898
                        /* How long will the gateway take to push the event? */
899 5e9e29e0 meetecho
                        gint64 start = janus_get_monotonic_time();
900 be35facb meetecho
                        int res = gateway->push_event(msg->handle, &janus_audiobridge_plugin, msg->transaction, event_text, type, sdp);
901 5e9e29e0 meetecho
                        JANUS_PRINT("  >> Pushing event: %d (took %"SCNu64" ms)\n", res, janus_get_monotonic_time()-start);
902 be35facb meetecho
                        if(res != JANUS_OK) {
903
                                /* TODO Failed to negotiate? We should remove this participant */
904
                        } else {
905
                                /* Notify all other participants that there's a new boy in town */
906
                                janus_audiobridge_room *audiobridge = participant->room;
907
                                janus_mutex_lock(&audiobridge->mutex);
908
                                json_t *list = json_array();
909
                                json_t *pl = json_object();
910
                                json_object_set_new(pl, "id", json_integer(participant->user_id));
911
                                json_object_set_new(pl, "display", json_string(participant->display));
912
                                //~ json_object_set_new(pl, "muted", json_boolean(!participant->audio_active));
913
                                json_object_set_new(pl, "muted", json_string(participant->audio_active ? "false" : "true"));
914
                                json_array_append_new(list, pl);
915
                                json_t *pub = json_object();
916
                                json_object_set(pub, "audiobridge", json_string("event"));
917
                                json_object_set(pub, "room", json_integer(participant->room->room_id));
918
                                json_object_set_new(pub, "participants", list);
919
                                char *pub_text = json_dumps(pub, JSON_INDENT(3));
920
                                json_decref(list);
921
                                json_decref(pub);
922
                                GList *participants_list = g_hash_table_get_values(participant->room->participants);
923
                                GList *ps = participants_list;
924
                                while(ps) {
925
                                        janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
926
                                        if(p == participant) {
927
                                                ps = ps->next;
928
                                                continue;        /* Skip the new participant itself */
929
                                        }
930
                                        JANUS_PRINT("Notifying participant %"SCNu64" (%s)\n", p->user_id, p->display);
931
                                        JANUS_PRINT("  >> %d\n", gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, pub_text, NULL, NULL));
932
                                        ps = ps->next;
933
                                }
934
                                g_list_free(participants_list);
935
                                session->started = TRUE;
936
                                janus_mutex_unlock(&audiobridge->mutex);
937
                        }
938
                }
939
940
                continue;
941
                
942
error:
943
                {
944
                        if(root != NULL)
945
                                json_decref(root);
946
                        /* Prepare JSON error event */
947
                        json_t *event = json_object();
948
                        json_object_set(event, "audiobridge", json_string("event"));
949
                        json_object_set(event, "error", json_string(error_cause));
950
                        char *event_text = json_dumps(event, JSON_INDENT(3));
951
                        json_decref(event);
952
                        JANUS_PRINT("Pushing event: %s\n", event_text);
953
                        JANUS_PRINT("  >> %d\n", gateway->push_event(msg->handle, &janus_audiobridge_plugin, msg->transaction, event_text, NULL, NULL));
954
                }
955
        }
956
        JANUS_DEBUG("Leaving thread\n");
957
        return NULL;
958
}
959
960
/* FIXME Thread to send RTP packets from the mix */
961
static void *janus_audiobridge_mixer_thread(void *data) {
962
        JANUS_PRINT("Audio bridge thread starting...\n");
963
        janus_audiobridge_room *audiobridge = (janus_audiobridge_room *)data;
964
        if(!audiobridge) {
965
                JANUS_PRINT("Invalid room!\n");
966
                return NULL;
967
        }
968
        JANUS_PRINT("Thread is for mixing room %"SCNu64" (%s)...\n", audiobridge->room_id, audiobridge->room_name);
969
        /* Do we need to record the mix? */
970
        if(audiobridge->record) {
971
                char filename[255];
972
                sprintf(filename, "/tmp/janus-audioroom-%"SCNu64".wav", audiobridge->room_id);
973
                audiobridge->recording = fopen(filename, "wb");
974
                if(audiobridge->recording == NULL) {
975
                        JANUS_DEBUG("Recording requested, but could NOT open file %s for writing...\n", filename);
976
                } else {
977
                        JANUS_PRINT("Recording requested, opened file %s for writing\n", filename);
978
                        /* Write WAV header */
979
                        wav_header header = {
980
                                {'R', 'I', 'F', 'F'},
981
                                0,
982
                                {'W', 'A', 'V', 'E'},
983
                                {'f', 'm', 't', ' '},
984
                                16,
985
                                1,
986
                                1,
987
                                16000,
988
                                16000,
989
                                2,
990
                                16,
991
                                {'d', 'a', 't', 'a'},
992
                                0
993
                        };
994
                        if(fwrite(&header, 1, sizeof(header), audiobridge->recording) != sizeof(header)) {
995
                                JANUS_DEBUG("Error writing WAV header...\n");
996
                        }
997
                }
998
        }
999
        /* Buffer (wideband) */
1000
        opus_int32 buffer[320], sumBuffer[320];
1001
        opus_int16 outBuffer[320], *curBuffer = NULL;
1002
        memset(buffer, 0, 1280);
1003
        memset(sumBuffer, 0, 1280);
1004
        memset(outBuffer, 0, 640);
1005
        /* Timer */
1006
        struct timeval now, before;
1007
        gettimeofday(&before, NULL);
1008
        now.tv_sec = before.tv_sec;
1009
        now.tv_usec = before.tv_usec;
1010
        time_t passed, d_s, d_us;
1011
        /* Output buffer */
1012
        janus_audiobridge_rtp_relay_packet *outpkt = calloc(1, sizeof(janus_audiobridge_rtp_relay_packet));
1013
        if(outpkt == NULL) {
1014
                JANUS_DEBUG("Memory error!\n");
1015
                return NULL;
1016
        }
1017
        outpkt->data = (rtp_header *)calloc(BUFFER_SAMPLES, sizeof(unsigned char));
1018
        if(outpkt->data == NULL) {
1019
                JANUS_DEBUG("Memory error!\n");
1020
                g_free(outpkt);
1021
                return NULL;
1022
        }
1023
        unsigned char *payload = (unsigned char *)outpkt->data;
1024
        memset(payload, 0, BUFFER_SAMPLES);
1025
        /* RTP */
1026
        gint16 seq = 0;
1027
        gint32 ts = 0;
1028
        /* Loop */
1029
        int i=0;
1030
        while(!stopping) {        /* FIXME We need a per-mountpoint watchdog as well */
1031
                /* See if it's time to prepare a frame */
1032
                gettimeofday(&now, NULL);
1033
                d_s = now.tv_sec - before.tv_sec;
1034
                d_us = now.tv_usec - before.tv_usec;
1035
                if(d_us < 0) {
1036
                        d_us += 1000000;
1037
                        --d_s;
1038
                }
1039
                passed = d_s*1000000 + d_us;
1040
                if(passed < 15000) {        /* Let's wait about 15ms at max */
1041
                        usleep(1000);
1042
                        continue;
1043
                }
1044
                /* Update the reference time */
1045
                before.tv_usec += 20000;
1046
                if(before.tv_usec > 1000000) {
1047
                        before.tv_sec++;
1048
                        before.tv_usec -= 1000000;
1049
                }
1050
                /* Update RTP header */
1051
                outpkt->data->version = 2;
1052
                outpkt->data->markerbit = 0;        /* FIXME Should be 1 for the first packet */
1053
                seq++;
1054
                outpkt->data->seq_number = htons(seq);
1055
                ts += 960;
1056
                outpkt->data->timestamp = htonl(ts);
1057
                outpkt->data->ssrc = htonl(1);        /* The gateway will fix this anyway */
1058
                /* Mix all contributions */
1059
                janus_mutex_lock(&audiobridge->mutex);
1060
                GList *participants_list = g_hash_table_get_values(audiobridge->participants);
1061
                janus_mutex_unlock(&audiobridge->mutex);
1062
                for(i=0; i<320; i++)
1063
                        buffer[i] = 0;
1064
                GList *ps = participants_list;
1065
                while(ps) {
1066
                        janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
1067
                        if(!p->audio_active || g_queue_is_empty(p->inbuf)) {
1068
                                ps = ps->next;
1069
                                continue;
1070
                        }
1071
                        janus_audiobridge_rtp_relay_packet *pkt = g_queue_peek_head(p->inbuf);
1072
                        curBuffer = (opus_int16 *)pkt->data;
1073
                        for(i=0; i<320; i++)
1074
                                buffer[i] += curBuffer[i];
1075
                        ps = ps->next;
1076
                }
1077
                /* Are we recording the mix? (only do it if there's someone in, though...) */ 
1078
                if(audiobridge->recording != NULL && g_list_length(participants_list) > 0) { 
1079
                        for(i=0; i<320; i++) { 
1080
                                /* FIXME Smoothen/Normalize instead of truncating? */ 
1081
                                outBuffer[i] = buffer[i]; 
1082
                        } 
1083
                        fwrite(outBuffer, sizeof(opus_int16), 320, audiobridge->recording); 
1084
                } 
1085
                /* Send proper packet to each participant (remove own contribution) */
1086
                ps = participants_list;
1087
                while(ps) {
1088
                        janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
1089
                        janus_audiobridge_rtp_relay_packet *pkt = NULL;
1090
                        if(p->audio_active && !g_queue_is_empty(p->inbuf))
1091
                                pkt = g_queue_pop_head(p->inbuf);
1092
                        curBuffer = (opus_int16 *)(pkt ? pkt->data : NULL);
1093
                        for(i=0; i<320; i++)
1094
                                sumBuffer[i] = buffer[i] - (curBuffer ? (curBuffer[i]) : 0);
1095
                        for(i=0; i<320; i++)
1096
                                /* FIXME Smoothen/Normalize instead of truncating? */
1097
                                outBuffer[i] = sumBuffer[i];
1098
                        /* Encode raw frame to Opus */
1099
                        outpkt->length = opus_encode(p->encoder, outBuffer, 320, payload+12, BUFFER_SAMPLES-12);
1100
                        if(outpkt->length < 0) {
1101
                                JANUS_PRINT("[Opus] Ops! got an error encoding the Opus frame: %d (%s)\n", outpkt->length, opus_strerror(outpkt->length));
1102
                        } else {
1103
                                outpkt->length += 12;        /* Take the RTP header into consideration */
1104
                                janus_audiobridge_relay_rtp_packet(p->session, outpkt);
1105
                        }
1106
                        if(pkt) {
1107
                                if(pkt->data)
1108
                                        g_free(pkt->data);
1109
                                g_free(pkt);
1110
                        }
1111
                        ps = ps->next;
1112
                }
1113
                g_list_free(participants_list);
1114
        }
1115
        if(audiobridge->recording)
1116
                fclose(audiobridge->recording);
1117
        JANUS_PRINT("Leaving mixer thread for room %"SCNu64" (%s)...\n", audiobridge->room_id, audiobridge->room_name);
1118
        return NULL;
1119
}
1120
1121
static void janus_audiobridge_relay_rtp_packet(gpointer data, gpointer user_data) {
1122
        janus_audiobridge_rtp_relay_packet *packet = (janus_audiobridge_rtp_relay_packet *)user_data;
1123
        if(!packet || !packet->data || packet->length < 1) {
1124
                JANUS_PRINT("Invalid packet...\n");
1125
                return;
1126
        }
1127
        janus_audiobridge_session *session = (janus_audiobridge_session *)data;
1128
        if(!session || !session->handle) {
1129
                // JANUS_PRINT("Invalid session...\n");
1130
                return;
1131
        }
1132
        if(!session->started) {
1133
                // JANUS_PRINT("Streaming not started yet for this session...\n");
1134
                return;
1135
        }
1136
        janus_audiobridge_participant *participant = session->participant;
1137
        packet->data->type = participant->opus_pt;
1138
        /* Go */
1139
        if(gateway != NULL)        /* FIXME What about RTCP? */
1140
                gateway->relay_rtp(session->handle, 0, (char *)packet->data, packet->length);
1141
        return;
1142
}