Statistics
| Branch: | Revision:

janus-gateway / plugins / janus_audiobridge.c @ 47576630

History | View | Annotate | Download (40.9 KB)

1
/*! \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

    
45

    
46
/* Plugin information */
47
#define JANUS_AUDIOBRIDGE_VERSION                        1
48
#define JANUS_AUDIOBRIDGE_VERSION_STRING        "0.0.1"
49
#define JANUS_AUDIOBRIDGE_DESCRIPTION                "This is a plugin implementing an audio conference bridge for Janus, mixing Opus streams."
50
#define JANUS_AUDIOBRIDGE_NAME                                "JANUS AudioBridge plugin"
51
#define JANUS_AUDIOBRIDGE_PACKAGE                        "janus.plugin.audiobridge"
52

    
53
/* Plugin methods */
54
janus_plugin *create(void);
55
int janus_audiobridge_init(janus_callbacks *callback, const char *config_path);
56
void janus_audiobridge_destroy(void);
57
int janus_audiobridge_get_version(void);
58
const char *janus_audiobridge_get_version_string(void);
59
const char *janus_audiobridge_get_description(void);
60
const char *janus_audiobridge_get_name(void);
61
const char *janus_audiobridge_get_package(void);
62
void janus_audiobridge_create_session(janus_pluginession *handle, int *error);
63
void janus_audiobridge_handle_message(janus_pluginession *handle, char *transaction, char *message, char *sdp_type, char *sdp);
64
void janus_audiobridge_setup_media(janus_pluginession *handle);
65
void janus_audiobridge_incoming_rtp(janus_pluginession *handle, int video, char *buf, int len);
66
void janus_audiobridge_incoming_rtcp(janus_pluginession *handle, int video, char *buf, int len);
67
void janus_audiobridge_hangup_media(janus_pluginession *handle);
68
void janus_audiobridge_destroy_session(janus_pluginession *handle, int *error);
69

    
70
/* Plugin setup */
71
static janus_plugin janus_audiobridge_plugin =
72
        {
73
                .init = janus_audiobridge_init,
74
                .destroy = janus_audiobridge_destroy,
75

    
76
                .get_version = janus_audiobridge_get_version,
77
                .get_version_string = janus_audiobridge_get_version_string,
78
                .get_description = janus_audiobridge_get_description,
79
                .get_name = janus_audiobridge_get_name,
80
                .get_package = janus_audiobridge_get_package,
81
                
82
                .create_session = janus_audiobridge_create_session,
83
                .handle_message = janus_audiobridge_handle_message,
84
                .setup_media = janus_audiobridge_setup_media,
85
                .incoming_rtp = janus_audiobridge_incoming_rtp,
86
                .incoming_rtcp = janus_audiobridge_incoming_rtcp,
87
                .hangup_media = janus_audiobridge_hangup_media,
88
                .destroy_session = janus_audiobridge_destroy_session,
89
        }; 
90

    
91
/* Plugin creator */
92
janus_plugin *create(void) {
93
        JANUS_PRINT("%s created!\n", JANUS_AUDIOBRIDGE_NAME);
94
        return &janus_audiobridge_plugin;
95
}
96

    
97

    
98
/* Useful stuff */
99
static int initialized = 0, stopping = 0;
100
static janus_callbacks *gateway = NULL;
101
static GThread *handler_thread;
102
static void *janus_audiobridge_handler(void *data);
103
static void janus_audiobridge_relay_rtp_packet(gpointer data, gpointer user_data);
104
static void *janus_audiobridge_mixer_thread(void *data);
105

    
106
typedef struct janus_audiobridge_message {
107
        janus_pluginession *handle;
108
        char *transaction;
109
        char *message;
110
        char *sdp_type;
111
        char *sdp;
112
} janus_audiobridge_message;
113
GQueue *messages;
114

    
115
typedef struct janus_audiobridge_room {
116
        guint64 room_id;        /* Unique room ID */
117
        gchar *room_name;        /* Room description */
118
        uint32_t sampling_rate;        /* Sampling rate of the mix (e.g., 16000 for wideband) */
119
        gboolean record;
120
        FILE *recording;
121
        gboolean destroy;
122
        GHashTable *participants;        /* Map of participants */
123
        janus_mutex mutex;
124
} janus_audiobridge_room;
125
GHashTable *rooms;
126

    
127
typedef struct janus_audiobridge_session {
128
        janus_pluginession *handle;
129
        gpointer participant;
130
        gboolean started;
131
        gboolean stopping;
132
        gboolean destroy;
133
} janus_audiobridge_session;
134
GHashTable *sessions;
135

    
136
typedef struct janus_audiobridge_participant {
137
        janus_audiobridge_session *session;
138
        janus_audiobridge_room *room;        /* Room */
139
        guint64 user_id;        /* Unique ID in the room */
140
        gchar *display;        /* Display name (just for fun) */
141
        gboolean audio_active;
142
        /* RTP stuff */
143
        GQueue *inbuf;
144
        int opus_pt;
145
        /* Opus stuff */
146
        OpusEncoder *encoder;
147
        OpusDecoder *decoder;
148
} janus_audiobridge_participant;
149

    
150
/* Packets we get from gstreamer and relay */
151
typedef struct janus_audiobridge_rtp_relay_packet {
152
        rtp_header *data;
153
        gint length;
154
} janus_audiobridge_rtp_relay_packet;
155

    
156
/* SDP offer/answer template */
157
static const char *sdp_template =
158
                "v=0\r\n"
159
                "o=- %"SCNu64" %"SCNu64" IN IP4 127.0.0.1\r\n"        /* We need current time here */
160
                "s=%s\r\n"                                                        /* Audio bridge name */
161
                "t=0 0\r\n"
162
                "m=audio 1 RTP/SAVPF %d\r\n"                /* Opus payload type */
163
                "c=IN IP4 1.1.1.1\r\n"
164
                "a=rtpmap:%d opus/48000/2\r\n"                /* Opus payload type */
165
                "a=fmtp:%d maxplaybackrate=%d; stereo=0; sprop-stereo=0; useinbandfec=0\r\n"
166
                                                                                        /* Opus payload type and room sampling rate */
167
                "a=mid:audio\r\n";
168

    
169
/* Helper struct to generate and parse WAVE headers */
170
typedef struct wav_header {
171
        char riff[4];
172
        uint32_t len;
173
        char wave[4];
174
        char fmt[4];
175
        uint32_t formatsize;
176
        uint16_t format;
177
        uint16_t channels;
178
        uint32_t samplerate;
179
        uint32_t avgbyterate;
180
        uint16_t samplebytes;
181
        uint16_t channelbits;
182
        char data[4];
183
        uint32_t blocksize;
184
} wav_header;
185

    
186

    
187
/* Opus settings */                
188
#define        BUFFER_SAMPLES        8000
189
#define        OPUS_SAMPLES        160
190
#define USE_FEC                        0
191
#define DEFAULT_COMPLEXITY        4
192

    
193

    
194
/* Plugin implementation */
195
int janus_audiobridge_init(janus_callbacks *callback, const char *config_path) {
196
        if(stopping) {
197
                /* Still stopping from before */
198
                return -1;
199
        }
200
        if(callback == NULL || config_path == NULL) {
201
                /* Invalid arguments */
202
                return -1;
203
        }
204

    
205
        /* Read configuration */
206
        char filename[255];
207
        sprintf(filename, "%s/%s.cfg", config_path, JANUS_AUDIOBRIDGE_PACKAGE);
208
        JANUS_PRINT("Configuration file: %s\n", filename);
209
        janus_config *config = janus_config_parse(filename);
210
        if(config != NULL)
211
                janus_config_print(config);
212
        
213
        rooms = g_hash_table_new(NULL, NULL);
214
        sessions = g_hash_table_new(NULL, NULL);
215
        messages = g_queue_new();
216
        /* This is the callback we'll need to invoke to contact the gateway */
217
        gateway = callback;
218

    
219
        /* Parse configuration to populate the rooms list */
220
        if(config != NULL) {
221
                janus_config_category *cat = janus_config_get_categories(config);
222
                while(cat != NULL) {
223
                        if(cat->name == NULL) {
224
                                cat = cat->next;
225
                                continue;
226
                        }
227
                        JANUS_PRINT("Adding audio room '%s'\n", cat->name);
228
                        janus_config_item *desc = janus_config_get_item(cat, "description");
229
                        janus_config_item *sampling = janus_config_get_item(cat, "sampling_rate");
230
                        janus_config_item *record = janus_config_get_item(cat, "record");
231
                        if(sampling == NULL || sampling->value == NULL) {
232
                                JANUS_DEBUG("Can't add the audio room, missing mandatory information...\n");
233
                                cat = cat->next;
234
                                continue;
235
                        }
236
                        /* Create the audio bridge room */
237
                        janus_audiobridge_room *audiobridge = calloc(1, sizeof(janus_audiobridge_room));
238
                        if(audiobridge == NULL) {
239
                                JANUS_DEBUG("Memory error!\n");
240
                                continue;
241
                        }
242
                        audiobridge->room_id = atoi(cat->name);
243
                        char *description = NULL;
244
                        if(desc != NULL && desc->value != NULL)
245
                                description = g_strdup(desc->value);
246
                        else
247
                                description = g_strdup(cat->name);
248
                        if(description == NULL) {
249
                                JANUS_DEBUG("Memory error!\n");
250
                                continue;
251
                        }
252
                        audiobridge->room_name = description;
253
                        audiobridge->sampling_rate = atoi(sampling->value);
254
                        if(audiobridge->sampling_rate != 16000) {
255
                                JANUS_DEBUG("We currently only support 16kHz (wideband) as a sampling rate for audio rooms, changing %"SCNu32" to 16000...\n", audiobridge->sampling_rate);
256
                                audiobridge->sampling_rate = 16000;
257
                        }
258
                        audiobridge->record = FALSE;
259
                        if(record && record->value && !strcasecmp(record->value, "yes"))
260
                                audiobridge->record = TRUE;
261
                        audiobridge->recording = NULL;
262
                        audiobridge->destroy = 0;
263
                        audiobridge->participants = g_hash_table_new(NULL, NULL);
264
                        janus_mutex_init(&audiobridge->mutex);
265
                        g_hash_table_insert(rooms, GUINT_TO_POINTER(audiobridge->room_id), audiobridge);
266
                        JANUS_PRINT("Created audiobridge: %"SCNu64" (%s)\n", audiobridge->room_id, audiobridge->room_name);
267
                        /* We need a thread for the mix */
268
                        g_thread_new("audiobridge mixer thread", &janus_audiobridge_mixer_thread, audiobridge);
269
                        cat = cat->next;
270
                }
271
                /* Done */
272
                janus_config_destroy(config);
273
                config = NULL;
274
        }
275

    
276
        /* Show available rooms */
277
        GList *rooms_list = g_hash_table_get_values(rooms);
278
        GList *r = rooms_list;
279
        while(r) {
280
                janus_audiobridge_room *ar = (janus_audiobridge_room *)r->data;
281
                JANUS_PRINT("  ::: [%"SCNu64"][%s] %"SCNu32" (%s be recorded)\n",
282
                        ar->room_id, ar->room_name, ar->sampling_rate, ar->record ? "will" : "will NOT");
283
                r = r->next;
284
        }
285
        g_list_free(rooms_list);
286

    
287
        initialized = 1;
288
        /* Launch the thread that will handle incoming messages */
289
        GError *error = NULL;
290
        handler_thread = g_thread_try_new("janus audiobridge handler", janus_audiobridge_handler, NULL, &error);
291
        if(error != NULL) {
292
                initialized = 0;
293
                /* Something went wrong... */
294
                JANUS_DEBUG("Got error %d (%s) trying to launch thread...\n", error->code, error->message ? error->message : "??");
295
                return -1;
296
        }
297
        JANUS_PRINT("%s initialized!\n", JANUS_AUDIOBRIDGE_NAME);
298
        return 0;
299
}
300

    
301
void janus_audiobridge_destroy() {
302
        if(!initialized)
303
                return;
304
        stopping = 1;
305
        if(handler_thread != NULL) {
306
                g_thread_join(handler_thread);
307
        }
308
        handler_thread = NULL;
309
        /* TODO Actually remove rooms and its participants */
310
        g_hash_table_destroy(sessions);
311
        g_hash_table_destroy(rooms);
312
        g_queue_free(messages);
313
        sessions = NULL;
314
        initialized = 0;
315
        JANUS_PRINT("%s destroyed!\n", JANUS_AUDIOBRIDGE_NAME);
316
}
317

    
318
int janus_audiobridge_get_version() {
319
        return JANUS_AUDIOBRIDGE_VERSION;
320
}
321

    
322
const char *janus_audiobridge_get_version_string() {
323
        return JANUS_AUDIOBRIDGE_VERSION_STRING;
324
}
325

    
326
const char *janus_audiobridge_get_description() {
327
        return JANUS_AUDIOBRIDGE_DESCRIPTION;
328
}
329

    
330
const char *janus_audiobridge_get_name() {
331
        return JANUS_AUDIOBRIDGE_NAME;
332
}
333

    
334
const char *janus_audiobridge_get_package() {
335
        return JANUS_AUDIOBRIDGE_PACKAGE;
336
}
337

    
338
void janus_audiobridge_create_session(janus_pluginession *handle, int *error) {
339
        if(stopping || !initialized) {
340
                *error = -1;
341
                return;
342
        }        
343
        janus_audiobridge_session *session = (janus_audiobridge_session *)calloc(1, sizeof(janus_audiobridge_session));
344
        if(session == NULL) {
345
                JANUS_DEBUG("Memory error!\n");
346
                *error = -2;
347
                return;
348
        }
349
        session->handle = handle;
350
        session->started = FALSE;
351
        session->stopping = FALSE;
352
        session->destroy = FALSE;
353
        handle->plugin_handle = session;
354
        g_hash_table_insert(sessions, handle, session);
355

    
356
        return;
357
}
358

    
359
void janus_audiobridge_destroy_session(janus_pluginession *handle, int *error) {
360
        if(stopping || !initialized) {
361
                *error = -1;
362
                return;
363
        }        
364
        janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle; 
365
        if(!session) {
366
                JANUS_DEBUG("No session associated with this handle...\n");
367
                *error = -2;
368
                return;
369
        }
370
        if(session->destroy) {
371
                JANUS_PRINT("Session already destroyed...\n");
372
                g_free(session);
373
                return;
374
        }
375
        JANUS_PRINT("Removing Audio Bridge session...\n");
376
        g_hash_table_remove(sessions, handle);
377
        janus_audiobridge_hangup_media(handle);
378
        session->destroy = TRUE;
379
        g_free(session);
380

    
381
        return;
382
}
383

    
384
void janus_audiobridge_handle_message(janus_pluginession *handle, char *transaction, char *message, char *sdp_type, char *sdp) {
385
        if(stopping || !initialized)
386
                return;
387
        JANUS_PRINT("%s\n", message);
388
        janus_audiobridge_message *msg = calloc(1, sizeof(janus_audiobridge_message));
389
        if(msg == NULL) {
390
                JANUS_DEBUG("Memory error!\n");
391
                return;
392
        }
393
        msg->handle = handle;
394
        msg->transaction = transaction ? g_strdup(transaction) : NULL;
395
        msg->message = message;
396
        msg->sdp_type = sdp_type;
397
        msg->sdp = sdp;
398
        g_queue_push_tail(messages, msg);
399
}
400

    
401
void janus_audiobridge_setup_media(janus_pluginession *handle) {
402
        JANUS_DEBUG("WebRTC media is now available\n");
403
        if(stopping || !initialized)
404
                return;
405
        janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;        
406
        if(!session) {
407
                JANUS_DEBUG("No session associated with this handle...\n");
408
                return;
409
        }
410
        if(session->destroy)
411
                return;
412
        /* TODO Only send this peer the audio mix when we get this event */
413
}
414

    
415
void janus_audiobridge_incoming_rtp(janus_pluginession *handle, int video, char *buf, int len) {
416
        if(stopping || !initialized)
417
                return;
418
        janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;        
419
        if(!session || session->destroy || session->stopping || !session->participant)
420
                return;
421
        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
422
        if(!participant->audio_active)
423
                return;
424
        /* Decode frame (Opus -> slinear) */
425
        janus_audiobridge_rtp_relay_packet *pkt = calloc(1, sizeof(janus_audiobridge_rtp_relay_packet));
426
        if(pkt == NULL) {
427
                JANUS_DEBUG("Memory error!\n");
428
                return;
429
        }
430
        pkt->data = calloc(BUFFER_SAMPLES, sizeof(opus_int16));
431
        if(pkt->data == NULL) {
432
                JANUS_DEBUG("Memory error!\n");
433
                g_free(pkt);
434
                return;
435
        }
436
        pkt->length = opus_decode(participant->decoder, (const unsigned char *)buf+12, len-12, (opus_int16 *)pkt->data, BUFFER_SAMPLES, USE_FEC);
437
        if(pkt->length < 0) {
438
                JANUS_PRINT("[Opus] Ops! got an error decoding the Opus frame: %d (%s)\n", pkt->length, opus_strerror(pkt->length));
439
                g_free(pkt->data);
440
                g_free(pkt);
441
                return;
442
        }
443
        /* Enqueue the decoded frame */
444
        g_queue_push_tail(participant->inbuf, pkt);
445
}
446

    
447
void janus_audiobridge_incoming_rtcp(janus_pluginession *handle, int video, char *buf, int len) {
448
        if(stopping || !initialized)
449
                return;
450
        /* FIXME Should we care? */
451
}
452

    
453
void janus_audiobridge_hangup_media(janus_pluginession *handle) {
454
        JANUS_PRINT("No WebRTC media anymore\n");
455
        if(stopping || !initialized)
456
                return;
457
        janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;
458
        if(!session) {
459
                JANUS_DEBUG("No session associated with this handle...\n");
460
                return;
461
        }
462
        if(session->destroy || !session->participant)
463
                return;
464
        /* Get rid of participant */
465
        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
466
        janus_audiobridge_room *audiobridge = participant->room;
467
        janus_mutex_lock(&audiobridge->mutex);
468
        json_t *event = json_object();
469
        json_object_set(event, "audiobridge", json_string("event"));
470
        json_object_set(event, "room", json_integer(audiobridge->room_id));
471
        json_object_set(event, "leaving", json_integer(participant->user_id));
472
        char *leaving_text = json_dumps(event, JSON_INDENT(3));
473
        json_decref(event);
474
        g_hash_table_remove(audiobridge->participants, GUINT_TO_POINTER(participant->user_id));
475
        GList *participants_list = g_hash_table_get_values(audiobridge->participants);
476
        GList *ps = participants_list;
477
        while(ps) {
478
                janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
479
                if(p == participant) {
480
                        ps = ps->next;
481
                        continue;        /* Skip the leaving participant itself */
482
                }
483
                JANUS_PRINT("Notifying participant %"SCNu64" (%s)\n", p->user_id, p->display);
484
                JANUS_PRINT("  >> %d\n", gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, leaving_text, NULL, NULL));
485
                ps = ps->next;
486
        }
487
        g_free(leaving_text);
488
        g_list_free(participants_list);
489
        participant->audio_active = 0;
490
        session->started = FALSE;
491
        session->destroy = 1;
492
        janus_mutex_unlock(&audiobridge->mutex);
493
}
494

    
495
/* Thread to handle incoming messages */
496
static void *janus_audiobridge_handler(void *data) {
497
        JANUS_DEBUG("Joining thread\n");
498
        janus_audiobridge_message *msg = NULL;
499
        char *error_cause = calloc(512, sizeof(char));        /* FIXME 512 should be enough, but anyway... */
500
        if(error_cause == NULL) {
501
                JANUS_DEBUG("Memory error!\n");
502
                return NULL;
503
        }
504
        while(initialized && !stopping) {
505
                if(!messages || (msg = g_queue_pop_head(messages)) == NULL) {
506
                        usleep(50000);
507
                        continue;
508
                }
509
                janus_audiobridge_session *session = (janus_audiobridge_session *)msg->handle->plugin_handle;        
510
                if(!session) {
511
                        JANUS_DEBUG("No session associated with this handle...\n");
512
                        continue;
513
                }
514
                if(session->destroy)
515
                        continue;
516
                /* Handle request */
517
                JANUS_PRINT("Handling message: %s\n", msg->message);
518
                if(msg->message == NULL) {
519
                        JANUS_DEBUG("No message??\n");
520
                        sprintf(error_cause, "%s", "No message??");
521
                        goto error;
522
                }
523
                json_error_t error;
524
                json_t *root = json_loads(msg->message, 0, &error);
525
                if(!root) {
526
                        JANUS_DEBUG("JSON error: on line %d: %s\n", error.line, error.text);
527
                        sprintf(error_cause, "JSON error: on line %d: %s", error.line, error.text);
528
                        goto error;
529
                }
530
                if(!json_is_object(root)) {
531
                        JANUS_DEBUG("JSON error: not an object\n");
532
                        sprintf(error_cause, "JSON error: not an object");
533
                        goto error;
534
                }
535
                /* Get the request first */
536
                json_t *request = json_object_get(root, "request");
537
                if(!request || !json_is_string(request)) {
538
                        JANUS_DEBUG("JSON error: invalid element (request)\n");
539
                        sprintf(error_cause, "JSON error: invalid element (request)");
540
                        goto error;
541
                }
542
                const char *request_text = json_string_value(request);
543
                json_t *event = NULL;
544
                if(!strcasecmp(request_text, "create")) {
545
                        /* Create a new audiobridge */
546
                        JANUS_PRINT("Creating a new audiobridge\n");
547
                        json_t *desc = json_object_get(root, "description");
548
                        if(desc && !json_is_string(desc)) {
549
                                JANUS_DEBUG("JSON error: invalid element (desc)\n");
550
                                sprintf(error_cause, "JSON error: invalid element (desc)");
551
                                goto error;
552
                        }
553
                        json_t *sampling = json_object_get(root, "sampling");
554
                        if(sampling && !json_is_integer(sampling)) {
555
                                JANUS_DEBUG("JSON error: invalid element (sampling)\n");
556
                                sprintf(error_cause, "JSON error: invalid element (sampling)");
557
                                goto error;
558
                        }
559
                        json_t *record = json_object_get(root, "record");
560
                        if(record && !json_is_boolean(record)) {
561
                                JANUS_DEBUG("JSON error: invalid element (record)\n");
562
                                sprintf(error_cause, "JSON error: invalid value (record)");
563
                                goto error;
564
                        }
565
                        /* Create the audio bridge room */
566
                        janus_audiobridge_room *audiobridge = calloc(1, sizeof(janus_audiobridge_room));
567
                        if(audiobridge == NULL) {
568
                                JANUS_DEBUG("Memory error!\n");
569
                                sprintf(error_cause, "Memory error");
570
                                goto error;
571
                        }
572
                        /* Generate a random ID */
573
                        guint64 room_id = 0;
574
                        while(room_id == 0) {
575
                                room_id = g_random_int();
576
                                if(g_hash_table_lookup(rooms, GUINT_TO_POINTER(room_id)) != NULL) {
577
                                        /* Room ID already taken, try another one */
578
                                        room_id = 0;
579
                                }
580
                        }
581
                        audiobridge->room_id = room_id;
582
                        char *description = NULL;
583
                        if(desc != NULL) {
584
                                description = g_strdup(json_string_value(desc));
585
                        } else {
586
                                char roomname[255];
587
                                sprintf(roomname, "Room %"SCNu64"", audiobridge->room_id);
588
                                description = g_strdup(roomname);
589
                        }
590
                        if(description == NULL) {
591
                                JANUS_DEBUG("Memory error!\n");
592
                                continue;
593
                        }
594
                        audiobridge->room_name = description;
595
                        if(sampling)
596
                                audiobridge->sampling_rate = json_integer_value(sampling);
597
                        else
598
                                audiobridge->sampling_rate = 16000;
599
                        if(audiobridge->sampling_rate != 16000) {
600
                                JANUS_DEBUG("We currently only support 16kHz (wideband) as a sampling rate for audio rooms, changing %"SCNu32" to 16000...\n", audiobridge->sampling_rate);
601
                                audiobridge->sampling_rate = 16000;
602
                        }
603
                        audiobridge->record = FALSE;
604
                        if(record && json_is_true(record))
605
                                audiobridge->record = TRUE;
606
                        audiobridge->recording = NULL;
607
                        audiobridge->destroy = 0;
608
                        audiobridge->participants = g_hash_table_new(NULL, NULL);
609
                        janus_mutex_init(&audiobridge->mutex);
610
                        g_hash_table_insert(rooms, GUINT_TO_POINTER(audiobridge->room_id), audiobridge);
611
                        JANUS_PRINT("Created audiobridge: %"SCNu64" (%s)\n", audiobridge->room_id, audiobridge->room_name);
612
                        /* We need a thread for the mix */
613
                        g_thread_new("audiobridge mixer thread", &janus_audiobridge_mixer_thread, audiobridge);
614
                        /* Show updated rooms list */
615
                        GList *rooms_list = g_hash_table_get_values(rooms);
616
                        GList *r = rooms_list;
617
                        while(r) {
618
                                janus_audiobridge_room *ar = (janus_audiobridge_room *)r->data;
619
                                JANUS_PRINT("  ::: [%"SCNu64"][%s] %"SCNu32" (%s be recorded)\n",
620
                                        ar->room_id, ar->room_name, ar->sampling_rate, ar->record ? "will" : "will NOT");
621
                                r = r->next;
622
                        }
623
                        g_list_free(rooms_list);
624
                        /* Send info back */
625
                        event = json_object();
626
                        json_object_set(event, "audiobridge", json_string("created"));
627
                        json_object_set(event, "room", json_integer(audiobridge->room_id));
628
                } else if(!strcasecmp(request_text, "join")) {
629
                        JANUS_PRINT("Configuring new participant\n");
630
                        json_t *room = json_object_get(root, "room");
631
                        if(!room || !json_is_integer(room)) {
632
                                JANUS_DEBUG("JSON error: invalid element (room)\n");
633
                                sprintf(error_cause, "JSON error: invalid element (room)");
634
                                goto error;
635
                        }
636
                        guint64 room_id = json_integer_value(room);
637
                        janus_audiobridge_room *audiobridge = g_hash_table_lookup(rooms, GUINT_TO_POINTER(room_id));
638
                        if(audiobridge == NULL) {
639
                                JANUS_DEBUG("No such room (%"SCNu64")\n", room_id);
640
                                sprintf(error_cause, "No such room (%"SCNu64")", room_id);
641
                                goto error;
642
                        }
643
                        json_t *display = json_object_get(root, "display");
644
                        if(!display || !json_is_string(display)) {
645
                                JANUS_DEBUG("JSON error: invalid element (display)\n");
646
                                sprintf(error_cause, "JSON error: invalid element (display)");
647
                                goto error;
648
                        }
649
                        const char *display_text = json_string_value(display);
650
                        /* Generate a random ID */
651
                        guint64 user_id = 0;
652
                        while(user_id == 0) {
653
                                user_id = g_random_int();
654
                                if(g_hash_table_lookup(audiobridge->participants, GUINT_TO_POINTER(user_id)) != NULL) {
655
                                        /* User ID already taken, try another one */
656
                                        user_id = 0;
657
                                }
658
                        }
659
                        JANUS_PRINT("  -- Participant ID: %"SCNu64"\n", user_id);
660
                        janus_audiobridge_participant *participant = calloc(1, sizeof(janus_audiobridge_participant));
661
                        if(participant == NULL) {
662
                                JANUS_DEBUG("Memory error!\n");
663
                                sprintf(error_cause, "Memory error");
664
                                goto error;
665
                        }
666
                        participant->session = session;
667
                        participant->room = audiobridge;
668
                        participant->user_id = user_id;
669
                        participant->display = g_strdup(display_text);
670
                        if(participant->display == NULL) {
671
                                JANUS_DEBUG("Memory error!\n");
672
                                sprintf(error_cause, "Memory error");
673
                                g_free(participant);
674
                                goto error;
675
                        }
676
                        participant->audio_active = FALSE;
677
                        participant->inbuf = g_queue_new();
678
                        participant->opus_pt = 0;
679
                        JANUS_PRINT("Creating Opus encoder/decoder (sampling rate %d)\n", audiobridge->sampling_rate);
680
                        /* Opus encoder */
681
                        int error = 0;
682
                        participant->encoder = opus_encoder_create(audiobridge->sampling_rate, 1, OPUS_APPLICATION_VOIP, &error);
683
                        if(error != OPUS_OK) {
684
                                g_free(participant->display);
685
                                g_free(participant);
686
                                JANUS_DEBUG("Error creating Opus encoder\n");
687
                                sprintf(error_cause, "Error creating Opus decoder");
688
                                goto error;
689
                        }
690
                        if(audiobridge->sampling_rate == 8000)
691
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
692
                        else if(audiobridge->sampling_rate == 12000)
693
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_MEDIUMBAND));
694
                        else if(audiobridge->sampling_rate == 16000)
695
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
696
                        else if(audiobridge->sampling_rate == 24000)
697
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
698
                        else if(audiobridge->sampling_rate == 48000)
699
                                opus_encoder_ctl(participant->encoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
700
                        else
701
                                JANUS_PRINT("Unsupported sampling rate %d\n", audiobridge->sampling_rate);
702
                        /* FIXME This settings should be configurable */
703
                        opus_encoder_ctl(participant->encoder, OPUS_SET_INBAND_FEC(USE_FEC));
704
                        opus_encoder_ctl(participant->encoder, OPUS_SET_COMPLEXITY(DEFAULT_COMPLEXITY));
705
                        /* Opus decoder */
706
                        error = 0;
707
                        participant->decoder = opus_decoder_create(audiobridge->sampling_rate, 1, &error);
708
                        if(error != OPUS_OK) {
709
                                g_free(participant->display);
710
                                if(participant->encoder)
711
                                        opus_encoder_destroy(participant->encoder);
712
                                if(participant->decoder)
713
                                        opus_decoder_destroy(participant->decoder);
714
                                g_free(participant);
715
                                JANUS_DEBUG("Error creating Opus encoder\n");
716
                                sprintf(error_cause, "Error creating Opus decoder");
717
                                goto error;
718
                        }
719

    
720
                        /* Done */
721
                        janus_mutex_lock(&audiobridge->mutex);
722
                        session->participant = participant;
723
                        g_hash_table_insert(audiobridge->participants, GUINT_TO_POINTER(user_id), participant);
724
                        /* Return a list of all available participants (those with an SDP available, that is) */
725
                        json_t *list = json_array();
726
                        GList *participants_list = g_hash_table_get_values(audiobridge->participants);
727
                        GList *ps = participants_list;
728
                        while(ps) {
729
                                janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
730
                                if(p == participant) {
731
                                        ps = ps->next;
732
                                        continue;
733
                                }
734
                                json_t *pl = json_object();
735
                                json_object_set_new(pl, "id", json_integer(p->user_id));
736
                                json_object_set_new(pl, "display", json_string(p->display));
737
                                //~ json_object_set_new(pl, "muted", json_boolean(!p->audio_active));
738
                                json_object_set_new(pl, "muted", json_string(p->audio_active ? "false" : "true"));
739
                                json_array_append_new(list, pl);
740
                                ps = ps->next;
741
                        }
742
                        event = json_object();
743
                        json_object_set(event, "audiobridge", json_string("joined"));
744
                        json_object_set(event, "room", json_integer(audiobridge->room_id));
745
                        json_object_set(event, "id", json_integer(user_id));
746
                        json_object_set_new(event, "participants", list);
747
                        g_list_free(participants_list);
748
                        janus_mutex_unlock(&audiobridge->mutex);
749
                } else if(!strcasecmp(request_text, "configure")) {
750
                        /* Handle this participant */
751
                        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
752
                        if(participant == NULL || participant->room == NULL) {
753
                                JANUS_DEBUG("Can't configure (not in a room)\n");
754
                                sprintf(error_cause, "Can't configure (not in a room)");
755
                                goto error;
756
                        }
757
                        /* Configure settings for this participant */
758
                        json_t *audio = json_object_get(root, "audio");
759
                        if(audio && !json_is_boolean(audio)) {
760
                                JANUS_DEBUG("JSON error: invalid element (audio)\n");
761
                                sprintf(error_cause, "JSON error: invalid value (audio)");
762
                                goto error;
763
                        }
764
                        if(audio) {
765
                                participant->audio_active = json_is_true(audio);
766
                                JANUS_PRINT("Setting audio property: %s (room %"SCNu64", user %"SCNu64")\n", participant->audio_active ? "true" : "false", participant->room->room_id, participant->user_id);
767
                                if(!participant->audio_active) {
768
                                        /* Clear the queued packets waiting to be handled */
769
                                        while(!g_queue_is_empty(participant->inbuf)) {
770
                                                janus_audiobridge_rtp_relay_packet *pkt = g_queue_pop_head(participant->inbuf);
771
                                                if(pkt == NULL)
772
                                                        continue;
773
                                                if(pkt->data)
774
                                                        g_free(pkt->data);
775
                                                g_free(pkt);
776
                                        }
777
                                }
778
                                /* Notify all other participants about the mute/unmute */
779
                                janus_audiobridge_room *audiobridge = participant->room;
780
                                janus_mutex_lock(&audiobridge->mutex);
781
                                json_t *list = json_array();
782
                                json_t *pl = json_object();
783
                                json_object_set_new(pl, "id", json_integer(participant->user_id));
784
                                json_object_set_new(pl, "display", json_string(participant->display));
785
                                //~ json_object_set_new(pl, "muted", json_boolean(!participant->audio_active));
786
                                json_object_set_new(pl, "muted", json_string(participant->audio_active ? "false" : "true"));
787
                                json_array_append_new(list, pl);
788
                                json_t *pub = json_object();
789
                                json_object_set(pub, "audiobridge", json_string("event"));
790
                                json_object_set(pub, "room", json_integer(participant->room->room_id));
791
                                json_object_set_new(pub, "participants", list);
792
                                char *pub_text = json_dumps(pub, JSON_INDENT(3));
793
                                json_decref(list);
794
                                json_decref(pub);
795
                                GList *participants_list = g_hash_table_get_values(participant->room->participants);
796
                                GList *ps = participants_list;
797
                                while(ps) {
798
                                        janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
799
                                        if(p == participant) {
800
                                                ps = ps->next;
801
                                                continue;        /* Skip the new participant itself */
802
                                        }
803
                                        JANUS_PRINT("Notifying participant %"SCNu64" (%s)\n", p->user_id, p->display);
804
                                        JANUS_PRINT("  >> %d\n", gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, pub_text, NULL, NULL));
805
                                        ps = ps->next;
806
                                }
807
                                g_list_free(participants_list);
808
                                janus_mutex_unlock(&audiobridge->mutex);
809
                        }
810
                        /* Done */
811
                        event = json_object();
812
                        json_object_set(event, "audiobridge", json_string("event"));
813
                        json_object_set(event, "room", json_integer(participant->room->room_id));
814
                        json_object_set(event, "result", json_string("ok"));
815
                } else if(!strcasecmp(request_text, "leave")) {
816
                        /* This participant is leaving */
817
                        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
818
                        if(participant == NULL || participant->room == NULL) {
819
                                JANUS_DEBUG("Can't leave (not in a room)\n");
820
                                sprintf(error_cause, "Can't leave (not in a room)");
821
                                goto error;
822
                        }
823
                        /* Tell everybody */
824
                        janus_audiobridge_room *audiobridge = participant->room;
825
                        janus_mutex_lock(&audiobridge->mutex);
826
                        event = json_object();
827
                        json_object_set(event, "audiobridge", json_string("event"));
828
                        json_object_set(event, "room", json_integer(audiobridge->room_id));
829
                        json_object_set(event, "leaving", json_integer(participant->user_id));
830
                        char *leaving_text = json_dumps(event, JSON_INDENT(3));
831
                        GList *participants_list = g_hash_table_get_values(audiobridge->participants);
832
                        GList *ps = participants_list;
833
                        while(ps) {
834
                                janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
835
                                if(p == participant) {
836
                                        ps = ps->next;
837
                                        continue;        /* Skip the new participant itself */
838
                                }
839
                                JANUS_PRINT("Notifying participant %"SCNu64" (%s)\n", p->user_id, p->display);
840
                                JANUS_PRINT("  >> %d\n", gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, leaving_text, NULL, NULL));
841
                                ps = ps->next;
842
                        }
843
                        g_free(leaving_text);
844
                        g_list_free(participants_list);
845
                        /* Done */
846
                        participant->audio_active = 0;
847
                        session->started = FALSE;
848
                        session->destroy = 1;
849
                        janus_mutex_unlock(&audiobridge->mutex);
850
                } else {
851
                        JANUS_DEBUG("Unknown request '%s'\n", request_text);
852
                        sprintf(error_cause, "Unknown request '%s'", request_text);
853
                        goto error;
854
                }
855

    
856
                /* Prepare JSON event */
857
                JANUS_PRINT("Preparing JSON event as a reply\n");
858
                char *event_text = json_dumps(event, JSON_INDENT(3));
859
                json_decref(event);
860
                /* Any SDP to handle? */
861
                if(!msg->sdp) {
862
                        JANUS_PRINT("  >> %d\n", gateway->push_event(msg->handle, &janus_audiobridge_plugin, msg->transaction, event_text, NULL, NULL));
863
                } else {
864
                        JANUS_PRINT("This is involving a negotiation (%s) as well:\n%s\n", msg->sdp_type, msg->sdp);
865
                        char *type = NULL;
866
                        if(!strcasecmp(msg->sdp_type, "offer"))
867
                                type = "answer";
868
                        if(!strcasecmp(msg->sdp_type, "answer"))
869
                                type = "offer";
870
                        /* Fill the SDP template and use that as our answer */
871
                        janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
872
                        char sdp[1024];
873
                        /* What is the Opus payload type? */
874
                        participant->opus_pt = 0;
875
                        char *fmtp = strstr(msg->sdp, "opus/48000");
876
                        if(fmtp != NULL) {
877
                                fmtp -= 5;
878
                                fmtp = strstr(fmtp, ":");
879
                                if(fmtp)
880
                                        fmtp++;
881
                                participant->opus_pt = atoi(fmtp);
882
                        }
883
                        JANUS_PRINT("Opus payload type is %d\n", participant->opus_pt);
884
                        g_sprintf(sdp, sdp_template,
885
                                g_get_monotonic_time(),                        /* We need current time here */
886
                                g_get_monotonic_time(),                        /* We need current time here */
887
                                participant->room->room_name,        /* Audio bridge name */
888
                                participant->opus_pt,                        /* Opus payload type */
889
                                participant->opus_pt,                        /* Opus payload type */
890
                                participant->opus_pt,                         /* Opus payload type and room sampling rate */
891
                                participant->room->sampling_rate);
892
                        /* Did the peer negotiate video? */
893
                        if(strstr(msg->sdp, "m=video") != NULL) {
894
                                /* If so, reject it */
895
                                g_strlcat(sdp, "m=video 0 RTP/SAVPF 0\r\n", 1024);                                
896
                        }
897
                        /* How long will the gateway take to push the event? */
898
                        gint64 start = g_get_monotonic_time();
899
                        int res = gateway->push_event(msg->handle, &janus_audiobridge_plugin, msg->transaction, event_text, type, sdp);
900
                        JANUS_PRINT("  >> Pushing event: %d (took %"SCNu64" ms)\n", res, g_get_monotonic_time()-start);
901
                        if(res != JANUS_OK) {
902
                                /* TODO Failed to negotiate? We should remove this participant */
903
                        } else {
904
                                /* Notify all other participants that there's a new boy in town */
905
                                janus_audiobridge_room *audiobridge = participant->room;
906
                                janus_mutex_lock(&audiobridge->mutex);
907
                                json_t *list = json_array();
908
                                json_t *pl = json_object();
909
                                json_object_set_new(pl, "id", json_integer(participant->user_id));
910
                                json_object_set_new(pl, "display", json_string(participant->display));
911
                                //~ json_object_set_new(pl, "muted", json_boolean(!participant->audio_active));
912
                                json_object_set_new(pl, "muted", json_string(participant->audio_active ? "false" : "true"));
913
                                json_array_append_new(list, pl);
914
                                json_t *pub = json_object();
915
                                json_object_set(pub, "audiobridge", json_string("event"));
916
                                json_object_set(pub, "room", json_integer(participant->room->room_id));
917
                                json_object_set_new(pub, "participants", list);
918
                                char *pub_text = json_dumps(pub, JSON_INDENT(3));
919
                                json_decref(list);
920
                                json_decref(pub);
921
                                GList *participants_list = g_hash_table_get_values(participant->room->participants);
922
                                GList *ps = participants_list;
923
                                while(ps) {
924
                                        janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
925
                                        if(p == participant) {
926
                                                ps = ps->next;
927
                                                continue;        /* Skip the new participant itself */
928
                                        }
929
                                        JANUS_PRINT("Notifying participant %"SCNu64" (%s)\n", p->user_id, p->display);
930
                                        JANUS_PRINT("  >> %d\n", gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, pub_text, NULL, NULL));
931
                                        ps = ps->next;
932
                                }
933
                                g_list_free(participants_list);
934
                                session->started = TRUE;
935
                                janus_mutex_unlock(&audiobridge->mutex);
936
                        }
937
                }
938

    
939
                continue;
940
                
941
error:
942
                {
943
                        if(root != NULL)
944
                                json_decref(root);
945
                        /* Prepare JSON error event */
946
                        json_t *event = json_object();
947
                        json_object_set(event, "audiobridge", json_string("event"));
948
                        json_object_set(event, "error", json_string(error_cause));
949
                        char *event_text = json_dumps(event, JSON_INDENT(3));
950
                        json_decref(event);
951
                        JANUS_PRINT("Pushing event: %s\n", event_text);
952
                        JANUS_PRINT("  >> %d\n", gateway->push_event(msg->handle, &janus_audiobridge_plugin, msg->transaction, event_text, NULL, NULL));
953
                }
954
        }
955
        JANUS_DEBUG("Leaving thread\n");
956
        return NULL;
957
}
958

    
959
/* FIXME Thread to send RTP packets from the mix */
960
static void *janus_audiobridge_mixer_thread(void *data) {
961
        JANUS_PRINT("Audio bridge thread starting...\n");
962
        janus_audiobridge_room *audiobridge = (janus_audiobridge_room *)data;
963
        if(!audiobridge) {
964
                JANUS_PRINT("Invalid room!\n");
965
                return NULL;
966
        }
967
        JANUS_PRINT("Thread is for mixing room %"SCNu64" (%s)...\n", audiobridge->room_id, audiobridge->room_name);
968
        /* Do we need to record the mix? */
969
        if(audiobridge->record) {
970
                char filename[255];
971
                sprintf(filename, "/tmp/janus-audioroom-%"SCNu64".wav", audiobridge->room_id);
972
                audiobridge->recording = fopen(filename, "wb");
973
                if(audiobridge->recording == NULL) {
974
                        JANUS_DEBUG("Recording requested, but could NOT open file %s for writing...\n", filename);
975
                } else {
976
                        JANUS_PRINT("Recording requested, opened file %s for writing\n", filename);
977
                        /* Write WAV header */
978
                        wav_header header = {
979
                                {'R', 'I', 'F', 'F'},
980
                                0,
981
                                {'W', 'A', 'V', 'E'},
982
                                {'f', 'm', 't', ' '},
983
                                16,
984
                                1,
985
                                1,
986
                                16000,
987
                                16000,
988
                                2,
989
                                16,
990
                                {'d', 'a', 't', 'a'},
991
                                0
992
                        };
993
                        if(fwrite(&header, 1, sizeof(header), audiobridge->recording) != sizeof(header)) {
994
                                JANUS_DEBUG("Error writing WAV header...\n");
995
                        }
996
                }
997
        }
998
        /* Buffer (wideband) */
999
        opus_int32 buffer[320], sumBuffer[320];
1000
        opus_int16 outBuffer[320], *curBuffer = NULL;
1001
        memset(buffer, 0, 1280);
1002
        memset(sumBuffer, 0, 1280);
1003
        memset(outBuffer, 0, 640);
1004
        /* Timer */
1005
        struct timeval now, before;
1006
        gettimeofday(&before, NULL);
1007
        now.tv_sec = before.tv_sec;
1008
        now.tv_usec = before.tv_usec;
1009
        time_t passed, d_s, d_us;
1010
        /* Output buffer */
1011
        janus_audiobridge_rtp_relay_packet *outpkt = calloc(1, sizeof(janus_audiobridge_rtp_relay_packet));
1012
        if(outpkt == NULL) {
1013
                JANUS_DEBUG("Memory error!\n");
1014
                return NULL;
1015
        }
1016
        outpkt->data = (rtp_header *)calloc(BUFFER_SAMPLES, sizeof(unsigned char));
1017
        if(outpkt->data == NULL) {
1018
                JANUS_DEBUG("Memory error!\n");
1019
                g_free(outpkt);
1020
                return NULL;
1021
        }
1022
        unsigned char *payload = (unsigned char *)outpkt->data;
1023
        memset(payload, 0, BUFFER_SAMPLES);
1024
        /* RTP */
1025
        gint16 seq = 0;
1026
        gint32 ts = 0;
1027
        /* Loop */
1028
        int i=0;
1029
        while(!stopping) {        /* FIXME We need a per-mountpoint watchdog as well */
1030
                /* See if it's time to prepare a frame */
1031
                gettimeofday(&now, NULL);
1032
                d_s = now.tv_sec - before.tv_sec;
1033
                d_us = now.tv_usec - before.tv_usec;
1034
                if(d_us < 0) {
1035
                        d_us += 1000000;
1036
                        --d_s;
1037
                }
1038
                passed = d_s*1000000 + d_us;
1039
                if(passed < 15000) {        /* Let's wait about 15ms at max */
1040
                        usleep(1000);
1041
                        continue;
1042
                }
1043
                /* Update the reference time */
1044
                before.tv_usec += 20000;
1045
                if(before.tv_usec > 1000000) {
1046
                        before.tv_sec++;
1047
                        before.tv_usec -= 1000000;
1048
                }
1049
                /* Update RTP header */
1050
                outpkt->data->version = 2;
1051
                outpkt->data->markerbit = 0;        /* FIXME Should be 1 for the first packet */
1052
                seq++;
1053
                outpkt->data->seq_number = htons(seq);
1054
                ts += 960;
1055
                outpkt->data->timestamp = htonl(ts);
1056
                outpkt->data->ssrc = htonl(1);        /* The gateway will fix this anyway */
1057
                /* Mix all contributions */
1058
                janus_mutex_lock(&audiobridge->mutex);
1059
                GList *participants_list = g_hash_table_get_values(audiobridge->participants);
1060
                janus_mutex_unlock(&audiobridge->mutex);
1061
                for(i=0; i<320; i++)
1062
                        buffer[i] = 0;
1063
                GList *ps = participants_list;
1064
                while(ps) {
1065
                        janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
1066
                        if(!p->audio_active || g_queue_is_empty(p->inbuf)) {
1067
                                ps = ps->next;
1068
                                continue;
1069
                        }
1070
                        janus_audiobridge_rtp_relay_packet *pkt = g_queue_peek_head(p->inbuf);
1071
                        curBuffer = (opus_int16 *)pkt->data;
1072
                        for(i=0; i<320; i++)
1073
                                buffer[i] += curBuffer[i];
1074
                        ps = ps->next;
1075
                }
1076
                /* Are we recording the mix? (only do it if there's someone in, though...) */ 
1077
                if(audiobridge->recording != NULL && g_list_length(participants_list) > 0) { 
1078
                        for(i=0; i<320; i++) { 
1079
                                /* FIXME Smoothen/Normalize instead of truncating? */ 
1080
                                outBuffer[i] = buffer[i]; 
1081
                        } 
1082
                        fwrite(outBuffer, sizeof(opus_int16), 320, audiobridge->recording); 
1083
                } 
1084
                /* Send proper packet to each participant (remove own contribution) */
1085
                ps = participants_list;
1086
                while(ps) {
1087
                        janus_audiobridge_participant *p = (janus_audiobridge_participant *)ps->data;
1088
                        janus_audiobridge_rtp_relay_packet *pkt = NULL;
1089
                        if(p->audio_active && !g_queue_is_empty(p->inbuf))
1090
                                pkt = g_queue_pop_head(p->inbuf);
1091
                        curBuffer = (opus_int16 *)(pkt ? pkt->data : NULL);
1092
                        for(i=0; i<320; i++)
1093
                                sumBuffer[i] = buffer[i] - (curBuffer ? (curBuffer[i]) : 0);
1094
                        for(i=0; i<320; i++)
1095
                                /* FIXME Smoothen/Normalize instead of truncating? */
1096
                                outBuffer[i] = sumBuffer[i];
1097
                        /* Encode raw frame to Opus */
1098
                        outpkt->length = opus_encode(p->encoder, outBuffer, 320, payload+12, BUFFER_SAMPLES-12);
1099
                        if(outpkt->length < 0) {
1100
                                JANUS_PRINT("[Opus] Ops! got an error encoding the Opus frame: %d (%s)\n", outpkt->length, opus_strerror(outpkt->length));
1101
                        } else {
1102
                                outpkt->length += 12;        /* Take the RTP header into consideration */
1103
                                janus_audiobridge_relay_rtp_packet(p->session, outpkt);
1104
                        }
1105
                        if(pkt) {
1106
                                if(pkt->data)
1107
                                        g_free(pkt->data);
1108
                                g_free(pkt);
1109
                        }
1110
                        ps = ps->next;
1111
                }
1112
                g_list_free(participants_list);
1113
        }
1114
        if(audiobridge->recording)
1115
                fclose(audiobridge->recording);
1116
        JANUS_PRINT("Leaving mixer thread for room %"SCNu64" (%s)...\n", audiobridge->room_id, audiobridge->room_name);
1117
        return NULL;
1118
}
1119

    
1120
static void janus_audiobridge_relay_rtp_packet(gpointer data, gpointer user_data) {
1121
        janus_audiobridge_rtp_relay_packet *packet = (janus_audiobridge_rtp_relay_packet *)user_data;
1122
        if(!packet || !packet->data || packet->length < 1) {
1123
                JANUS_PRINT("Invalid packet...\n");
1124
                return;
1125
        }
1126
        janus_audiobridge_session *session = (janus_audiobridge_session *)data;
1127
        if(!session || !session->handle) {
1128
                // JANUS_PRINT("Invalid session...\n");
1129
                return;
1130
        }
1131
        if(!session->started) {
1132
                // JANUS_PRINT("Streaming not started yet for this session...\n");
1133
                return;
1134
        }
1135
        janus_audiobridge_participant *participant = session->participant;
1136
        packet->data->type = participant->opus_pt;
1137
        /* Go */
1138
        if(gateway != NULL)        /* FIXME What about RTCP? */
1139
                gateway->relay_rtp(session->handle, 0, (char *)packet->data, packet->length);
1140
        return;
1141
}