Fork me on GitHub
Data Structures | Macros | Typedefs | Functions
janus_audiobridge.c File Reference

Janus AudioBridge plugin. More...

#include "plugin.h"
#include <jansson.h>
#include <opus/opus.h>
#include <sys/time.h>
#include "../debug.h"
#include "../apierror.h"
#include "../config.h"
#include "../mutex.h"
#include "../rtp.h"
#include "../rtpsrtp.h"
#include "../rtcp.h"
#include "../record.h"
#include "../sdp-utils.h"
#include "../utils.h"
Include dependency graph for janus_audiobridge.c:

Data Structures

struct  janus_audiobridge_message
 
struct  janus_audiobridge_room
 
struct  janus_audiobridge_session
 
struct  janus_audiobridge_participant
 
struct  janus_audiobridge_rtp_relay_packet
 
struct  janus_audiobridge_rtp_forwarder
 
struct  wav_header
 

Macros

#define JANUS_AUDIOBRIDGE_VERSION   10
 
#define JANUS_AUDIOBRIDGE_VERSION_STRING   "0.0.10"
 
#define JANUS_AUDIOBRIDGE_DESCRIPTION   "This is a plugin implementing an audio conference bridge for Janus, mixing Opus streams."
 
#define JANUS_AUDIOBRIDGE_NAME   "JANUS AudioBridge plugin"
 
#define JANUS_AUDIOBRIDGE_AUTHOR   "Meetecho s.r.l."
 
#define JANUS_AUDIOBRIDGE_PACKAGE   "janus.plugin.audiobridge"
 
#define DEFAULT_PREBUFFERING   6
 
#define BUFFER_SAMPLES   8000
 
#define OPUS_SAMPLES   160
 
#define USE_FEC   0
 
#define DEFAULT_COMPLEXITY   4
 
#define JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR   499
 
#define JANUS_AUDIOBRIDGE_ERROR_NO_MESSAGE   480
 
#define JANUS_AUDIOBRIDGE_ERROR_INVALID_JSON   481
 
#define JANUS_AUDIOBRIDGE_ERROR_INVALID_REQUEST   482
 
#define JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT   483
 
#define JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT   484
 
#define JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_ROOM   485
 
#define JANUS_AUDIOBRIDGE_ERROR_ROOM_EXISTS   486
 
#define JANUS_AUDIOBRIDGE_ERROR_NOT_JOINED   487
 
#define JANUS_AUDIOBRIDGE_ERROR_LIBOPUS_ERROR   488
 
#define JANUS_AUDIOBRIDGE_ERROR_UNAUTHORIZED   489
 
#define JANUS_AUDIOBRIDGE_ERROR_ID_EXISTS   490
 
#define JANUS_AUDIOBRIDGE_ERROR_ALREADY_JOINED   491
 
#define JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_USER   492
 
#define JANUS_AUDIOBRIDGE_ERROR_INVALID_SDP   493
 

Typedefs

typedef struct janus_audiobridge_message janus_audiobridge_message
 
typedef struct janus_audiobridge_room janus_audiobridge_room
 
typedef struct janus_audiobridge_session janus_audiobridge_session
 
typedef struct janus_audiobridge_participant janus_audiobridge_participant
 
typedef struct janus_audiobridge_rtp_relay_packet janus_audiobridge_rtp_relay_packet
 
typedef struct janus_audiobridge_rtp_forwarder janus_audiobridge_rtp_forwarder
 
typedef struct wav_header wav_header
 

Functions

janus_plugincreate (void)
 
int janus_audiobridge_init (janus_callbacks *callback, const char *config_path)
 
void janus_audiobridge_destroy (void)
 
int janus_audiobridge_get_api_compatibility (void)
 
int janus_audiobridge_get_version (void)
 
const char * janus_audiobridge_get_version_string (void)
 
const char * janus_audiobridge_get_description (void)
 
const char * janus_audiobridge_get_name (void)
 
const char * janus_audiobridge_get_author (void)
 
const char * janus_audiobridge_get_package (void)
 
void janus_audiobridge_create_session (janus_plugin_session *handle, int *error)
 
struct janus_plugin_resultjanus_audiobridge_handle_message (janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep)
 
void janus_audiobridge_setup_media (janus_plugin_session *handle)
 
void janus_audiobridge_incoming_rtp (janus_plugin_session *handle, int video, char *buf, int len)
 
void janus_audiobridge_incoming_rtcp (janus_plugin_session *handle, int video, char *buf, int len)
 
void janus_audiobridge_hangup_media (janus_plugin_session *handle)
 
void janus_audiobridge_destroy_session (janus_plugin_session *handle, int *error)
 
json_tjanus_audiobridge_query_session (janus_plugin_session *handle)
 

Detailed Description

Janus AudioBridge plugin.

Author
Lorenzo Miniero loren.nosp@m.zo@m.nosp@m.eetec.nosp@m.ho.c.nosp@m.om

This is a plugin implementing an audio conference bridge for Janus, specifically mixing Opus streams. This means that it replies by providing in the SDP only support for Opus, and disabling video. Opus encoding and decoding is implemented using libopus (http://opus.codec.org). The plugin provides an API to allow peers to join and leave conference rooms. Peers can then mute/unmute themselves by sending specific messages to the plugin: any way a peer mutes/unmutes, an event is triggered to the other participants, so that it can be rendered in the UI accordingly.

Rooms to make available are listed in the plugin configuration file. A pre-filled configuration file is provided in conf/janus.plugin.audiobridge.cfg and includes a demo room for testing.

To add more rooms or modify the existing one, you can use the following syntax:

[<unique room ID>]
description = This is my awesome room
is_private = yes|no (private rooms don't appear when you do a 'list' request)
secret = <optional password needed for manipulating (e.g. destroying) the room>
pin = <optional password needed for joining the room>
sampling_rate = <sampling rate> (e.g., 16000 for wideband mixing)
audiolevel_ext = yes|no (whether the ssrc-audio-level RTP extension must be
        negotiated/used or not for new joins, default=yes)
record = true|false (whether this room should be recorded, default=false)
record_file =   /path/to/recording.wav (where to save the recording)

        [The following lines are only needed if you want the mixed audio
        to be automatically forwarded via plain RTP to an external component
        (e.g., an ffmpeg script, or a gstreamer pipeline) for processing]
        By default plain RTP is used, SRTP must be configured if needed
rtp_forward_id = numeric RTP forwarder ID for referencing it via API (optional: random ID used if missing)
rtp_forward_host = host address to forward RTP packets of mixed audio to
rtp_forward_port = port to forward RTP packets of mixed audio to
rtp_forward_ssrc = SSRC to use to use when streaming (optional: stream_id used if missing)
rtp_forward_ptype = payload type to use when streaming (optional: 100 used if missing)
rtp_forward_srtp_suite = length of authentication tag (32 or 80)
rtp_forward_srtp_crypto = key to use as crypto (base64 encoded key as in SDES)
rtp_forward_always_on = true|false, whether silence should be forwarded when the room is empty (optional: false used if missing)

Audio Bridge API

The Audio Bridge API supports several requests, some of which are synchronous and some asynchronous. There are some situations, though, (invalid JSON, invalid request) which will always result in a synchronous error response even for asynchronous requests.

create , edit , destroy , exists, allowed, kick, list, listparticipants and resetdecoder are synchronous requests, which means you'll get a response directly within the context of the transaction. create allows you to create a new audio conference bridge dynamically, as an alternative to using the configuration file; edit allows you to dynamically edit some room properties (e.g., the PIN); destroy removes an audio conference bridge and destroys it, kicking all the users out as part of the process; exists allows you to check whether a specific audio conference exists; allowed allows you to edit who's allowed to join a room via ad-hoc tokens; list lists all the available rooms, while listparticipants lists all the participants of a specific room and their details; finally, resetdecoder marks the Opus decoder for the participant as invalid, and forces it to be recreated (which might be needed if the audio for generated by the participant becomes garbled).

The join , configure , changeroom and leave requests instead are all asynchronous, which means you'll get a notification about their success or failure in an event. join allows you to join a specific audio conference bridge; configure can be used to modify some of the participation settings (e.g., mute/unmute); changeroom can be used to leave the current room and move to a different one without having to tear down the PeerConnection and recreate it again (useful for sidebars and "waiting rooms"); finally, leave allows you to leave an audio conference bridge for good.

The AudioBridge plugin also allows you to forward the mix to an external listener, e.g., a gstreamer/ffmpeg pipeline waiting to process the mixer audio stream. You can add new RTP forwarders with the rtp_forward request; a stop_rtp_forward request removes an existing RTP forwarder; listforwarders lists all the current RTP forwarders on a specific AudioBridge room instance. As an alternative, you can configure a single static RTP forwarder in the plugin configuration file.

create can be used to create a new audio room, and has to be formatted as follows:

{
        "request" : "create",
        "room" : <unique numeric ID, optional, chosen by plugin if missing>,
        "permanent" : <true|false, whether the room should be saved in the config file, default false>,
        "description" : "<pretty name of the room, optional>",
        "secret" : "<password required to edit/destroy the room, optional>",
        "pin" : "<password required to join the room, optional>",
        "is_private" : <true|false, whether the room should appear in a list request>,
        "allowed" : [ array of string tokens users can use to join this room, optional],
        "sampling" : <sampling rate of the room, optional, 16000 by default>,
        "audiolevel_ext" : <true|false, whether the ssrc-audio-level RTP extension must be negotiated for new joins, default true>,
        "audiolevel_event" : yes|no (whether to emit event to other users or not),
        "audio_active_packets" : 100 (number of packets with audio level, default=100, 2 seconds),
        "audio_level_average" : 25 (average value of audio level, 127=muted, 0='too loud', default=25),
        "record" : <true|false, whether to record the room or not, default false>,
        "record_file" : "</path/to/the/recording.wav, optional>",
}

A successful creation procedure will result in a created response:

{
        "audiobridge" : "created",
        "room" : <unique numeric ID>,
        "permanent" : <true if saved to config file, false if not>
}

If you requested a permanent room but a false value is returned instead, good chances are that there are permission problems.

An error instead (and the same applies to all other requests, so this won't be repeated) would provide both an error code and a more verbose description of the cause of the issue:

{
        "audiobridge" : "event",
        "error_code" : <numeric ID, check Macros below>,
        "error" : "<error description as a string>"
}

Notice that, in general, all users can create rooms. If you want to limit this functionality, you can configure an admin admin_key in the plugin settings. When configured, only "create" requests that include the correct admin_key value in an "admin_key" property will succeed, and will be rejected otherwise.

Once a room has been created, you can still edit some (but not all) of its properties using the edit request. This allows you to modify the room description, secret, pin and whether it's private or not: you won't be able to modify other more static properties, like the room ID, the sampling rate, the extensions-related stuff and so on. If you're interested in changing the ACL, instead, check the allowed message. An edit request has to be formatted as follows:

{
        "request" : "edit",
        "room" : <unique numeric ID of the room to edit>,
        "secret" : "<room secret, mandatory if configured>",
        "new_description" : "<new pretty name of the room, optional>",
        "new_secret" : "<new password required to edit/destroy the room, optional>",
        "new_pin" : "<new password required to join the room, optional>",
        "new_is_private" : <true|false, whether the room should appear in a list request>,
        "permanent" : <true|false, whether the room should be also removed from the config file, default false>
}

A successful destruction procedure will result in an edited response:

{
        "audiobridge" : "edited",
        "room" : <unique numeric ID>
}

On the other hand, destroy can be used to destroy an existing audio room, whether created dynamically or statically, and has to be formatted as follows:

{
        "request" : "destroy",
        "room" : <unique numeric ID of the room to destroy>,
        "secret" : "<room secret, mandatory if configured>",
        "permanent" : <true|false, whether the room should be also removed from the config file, default false>
}

A successful destruction procedure will result in a destroyed response:

{
        "audiobridge" : "created",
        "room" : <unique numeric ID>
}

You can check whether a room exists using the exists request, which has to be formatted as follows:

{
        "request" : "exists",
        "room" : <unique numeric ID of the room to check>
}

A successful request will result in a success response:

{
        "audiobridge" : "success",
        "room" : <unique numeric ID>,
        "exists" : <true|false>
}

You can configure whether to check tokens or add/remove people who can join a room using the allowed request, which has to be formatted as follows:

{
        "request" : "allowed",
        "secret" : "<room secret, mandatory if configured>",
        "action" : "enable|disable|add|remove",
        "room" : <unique numeric ID of the room to update>,
        "allowed" : [
                // Array of strings (tokens users might pass in "join", only for add|remove)
        ]
}

A successful request will result in a success response:

{
        "audiobridge" : "success",
        "room" : <unique numeric ID>,
        "allowed" : [
                // Updated, complete, list of allowed tokens (only for enable|add|remove)
        ]
}

If you're the administrator of a room (that is, you created it and have access to the secret) you can kick participants using the kick request. Notice that this only kicks the user out of the room, but does not prevent them from re-joining: to ban them, you need to first remove them from the list of authorized users (see allowed request) and then kick them. The kick request has to be formatted as follows:

{
        "request" : "kick",
        "secret" : "<room secret, mandatory if configured>",
        "room" : <unique numeric ID of the room>,
        "id" : <unique numeric ID of the participant to kick>
}

A successful request will result in a success response:

{
        "audiobridge" : "success",
}

To get a list of the available rooms (excluded those configured or created as private rooms) you can make use of the list request, which has to be formatted as follows:

{
        "request" : "list"
}

A successful request will produce a list of rooms in a success response:

{
        "audiobridge" : "success",
        "rooms" : [             // Array of room objects
                {       // Room #1
                        "room" : <unique numeric ID>,
                        "description" : "<Name of the room>",
                        "sampling_rate" : <sampling rate of the mixer>,
                        "record" : <true|false, whether the room is being recorded>,
                        "num_participants" : <count of the participants>
                },
                // Other rooms
        ]
}

To get a list of the participants in a specific room, instead, you can make use of the listparticipants request, which has to be formatted as follows:

{
        "request" : "listparticipants",
        "room" : <unique numeric ID of the room>
}

A successful request will produce a list of participants in a participants response:

{
        "audiobridge" : "participants",
        "room" : <unique numeric ID of the room>,
        "participants" : [              // Array of participant objects
                {       // Participant #1
                        "id" : <unique numeric ID of the participant>,
                        "display" : "<display name of the participant, if any; optional>",
                        "setup" : <true|false, whether user successfully negotiate a WebRTC PeerConnection or not>,
                        "muted" : <true|false, whether user is muted or not>,
                        "talking" : <true|false, whether user is talking or not (only if audio levels are used)>,
                },
                // Other participants
        ]
}

To mark the Opus decoder context for the current participant as invalid and force it to be recreated, use the resetdecoder request:

{
        "request" : "resetdecoder"
}

A successful request will produce a success response:

{
        "audiobridge" : "success"
}

You can add a new RTP forwarder for an existing room exists using the rtp_forward request, which has to be formatted as follows:

{
        "request" : "rtp_forward",
        "room" : <unique numeric ID of the room to add the forwarder to>,
        "ssrc" : <SSRC to use to use when streaming (optional: stream_id used if missing)>,
        "ptype" : <payload type to use when streaming (optional: 100 used if missing)>,
        "host" : "<host address to forward the RTP packets to>",
        "port" : <port to forward the RTP packets to>,
        "srtp_suite" : <length of authentication tag (32 or 80)>,
        "srtp_crypto" : "<key to use as crypto (base64 encoded key as in SDES)>",
        "always_on" : <true|false, whether silence should be forwarded when the room is empty>
}

A successful request will result in a success response:

{
        "audiobridge" : "success",
        "room" : <unique numeric ID, same as request>,
        "stream_id" : <unique numeric ID assigned to the new RTP forwarder>
}

To stop a previously created RTP forwarder and stop it, you can use the stop_rtp_forward request, which has to be formatted as follows:

{
        "request" : "stop_rtp_forward",
        "room" : <unique numeric ID of the room to remove the forwarder from>,
        "stream_id" : <unique numeric ID of the RTP forwarder>
}

A successful request will result in a success response:

{
        "audiobridge" : "success",
        "room" : <unique numeric ID, same as request>,
        "stream_id" : <unique numeric ID, same as request>
}

To get a list of the forwarders in a specific room, instead, you can make use of the listforwarders request, which has to be formatted as follows:

{
        "request" : "listforwarders",
        "room" : <unique numeric ID of the room>
}

A successful request will produce a list of RTP forwarders in a forwarders response:

{
        "audiobridge" : "forwarders",
        "room" : <unique numeric ID of the room>,
        "rtp_forwarders" : [            // Array of RTP forwarder objects
                {       // RTP forwarder #1
                        "stream_id" : <unique numeric ID of the forwarder>,
                        "ip" : "<IP this forwarder is streaming to>",
                        "port" : <port this forwarder is streaming to>,
                        "ssrc" : <SSRC this forwarder is using, if any>,
                        "ptype" : <payload type this forwarder is using, if any>
                },
                // Other forwarders
        ]
}

That completes the list of synchronous requests you can send to the AudioBridge plugin. As anticipated, though, there are also several asynchronous requests you can send, specifically those related to joining and updating one's presence as a participant in an audio room.

The way you'd interact with the plugin is usually as follows:

  1. you use a join request to join an audio room, and wait for the joined event; this event will also include a list of the other participants, if any;
  2. you send a configure request attached to an audio-only JSEP offer to start configuring your participation in the room (e.g., join unmuted or muted), and wait for a configured event, which will be attached to a JSEP answer by the plugin to complete the setup of the WebRTC PeerConnection;
  3. you send other configure requests (without any JSEP-related attachment) to mute/unmute yourself during the audio conference;
  4. you intercept events originated by the plugin (joined , leaving ) to notify you about users joining/leaving/muting/unmuting;
  5. you eventually send a leave request to leave a room; if you leave the PeerConnection instance intact, you can subsequently join a different room without requiring a new negotiation (and so just use a join + JSEP-less configure to join).

Notice that there's also a changeroom request available: you can use this request to immediately leave the room you're in and join a different one, without requiring you to do a leave + join + configure round. Of course remember not to pass any JSEP-related payload when doing a changeroom as the same pre-existing PeerConnection will be re-used for the purpose.

About the syntax of all the above mentioned requests, join has to be formatted as follows:

{
        "request" : "join",
        "room" : <numeric ID of the room to join>,
        "id" : <unique ID to assign to the participant; optional, assigned by the plugin if missing>,
        "pin" : "<password required to join the room, if any; optional>",
        "display" : "<display name to have in the room; optional>",
        "token" : "<invitation token, in case the room has an ACL; optional>",
        "muted" : <true|false, whether to start unmuted or muted>,
        "quality" : <0-10, Opus-related complexity to use, the higher the value, the better the quality (but more CPU); optional, default is 4>,
        "volume" : <percent value, <100 reduces volume, >100 increases volume; optional, default is 100 (no volume change)>
}

A successful request will produce a joined event:

{
        "audiobridge" : "joined",
        "room" : <numeric ID of the room>,
        "id" : <unique ID assigned to the participant>,
        "display" : "<display name of the new participant>",
        "participants" : [
                // Array of existing participants in the room
        ]
}

The other participants in the room will be notified about the new participant by means of a different joined event, which will only include the room and the new participant as the only object in a participants array.

At this point, the media-related settings of the participant can be modified by means of a configure request. The configure request has to be formatted as follows (notice that all parameters except request are optional, depending on what you want to change):

{
        "request" : "configure",
        "muted" : <true|false, whether to unmute or mute>,
        "display" : "<new display name to have in the room>",
        "quality" : <0-10, Opus-related complexity to use, lower is higher quality; optional, default is 4>,
        "volume" : <percent value, <100 reduces volume, >100 increases volume; optional, default is 100 (no volume change)>,
        "record": <true|false, whether to record this user's contribution to a .mjr file (mixer not involved),
        "filename": "<basename of the file to record to, -audio.mjr will be added by the plugin>"
}

muted instructs the plugin to mute or unmute the participant; quality changes the complexity of the Opus encoder for the participant; record can be used to record this participant's contribution to a Janus .mjr file, and filename to provide a basename for the path to save the file to (notice that this is different from the recording of a whole room: this feature only records the packets this user is sending, and is not related to the mixer stuff). A successful request will result in a ok event:

{
        "audiobridge" : "event",
        "room" : <numeric ID of the room>,
        "result" : "ok"
}

In case the muted property was modified, the other participants in the room will be notified about this by means of a event notification, which will only include the room and the updated participant as the only object in a participants array.

As anticipated, you can leave an audio room using the leave request, which has to be formatted as follows:

{
        "request" : "leave"
}

All the participants will receive an event notification with the ID of the participant who just left:

{
        "audiobridge" : "event",
        "room" : <numeric ID of the room>,
        "leaving" : <numeric ID of the participant who left>
}

For what concerns the changeroom request, instead, it's pretty much the same as a join request and as such has to be formatted as follows:

{
        "request" : "changeroom",
        "room" : <numeric ID of the room to move to>,
        "id" : <unique ID to assign to the participant; optional, assigned by the plugin if missing>,
        "display" : "<display name to have in the room; optional>",
        "token" : "<invitation token, in case the new room has an ACL; optional>",
        "muted" : <true|false, whether to start unmuted or muted>,
        "quality" : <0-10, Opus-related complexity to use, lower is higher quality; optional, default is 4>
}

Such a request will trigger all the above-described leaving/joined events to the other participants, as it is indeed wrapping a leave followed by a join and as such the other participants in both rooms need to be updated accordingly. The participant who switched room instead will be sent a roomchanged event which is pretty similar to what joined looks like:

A successful request will produce a joined event:

{
        "audiobridge" : "roomchanged",
        "room" : <numeric ID of the new room>,
        "id" : <unique ID assigned to the participant in the new room>,
        "display" : "<display name of the new participant>",
        "participants" : [
                // Array of existing participants in the new room
        ]
}

Plugins

Macro Definition Documentation

◆ BUFFER_SAMPLES

#define BUFFER_SAMPLES   8000

◆ DEFAULT_COMPLEXITY

#define DEFAULT_COMPLEXITY   4

◆ DEFAULT_PREBUFFERING

#define DEFAULT_PREBUFFERING   6

◆ JANUS_AUDIOBRIDGE_AUTHOR

#define JANUS_AUDIOBRIDGE_AUTHOR   "Meetecho s.r.l."

◆ JANUS_AUDIOBRIDGE_DESCRIPTION

#define JANUS_AUDIOBRIDGE_DESCRIPTION   "This is a plugin implementing an audio conference bridge for Janus, mixing Opus streams."

◆ JANUS_AUDIOBRIDGE_ERROR_ALREADY_JOINED

#define JANUS_AUDIOBRIDGE_ERROR_ALREADY_JOINED   491

◆ JANUS_AUDIOBRIDGE_ERROR_ID_EXISTS

#define JANUS_AUDIOBRIDGE_ERROR_ID_EXISTS   490

◆ JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT

#define JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT   484

◆ JANUS_AUDIOBRIDGE_ERROR_INVALID_JSON

#define JANUS_AUDIOBRIDGE_ERROR_INVALID_JSON   481

◆ JANUS_AUDIOBRIDGE_ERROR_INVALID_REQUEST

#define JANUS_AUDIOBRIDGE_ERROR_INVALID_REQUEST   482

◆ JANUS_AUDIOBRIDGE_ERROR_INVALID_SDP

#define JANUS_AUDIOBRIDGE_ERROR_INVALID_SDP   493

◆ JANUS_AUDIOBRIDGE_ERROR_LIBOPUS_ERROR

#define JANUS_AUDIOBRIDGE_ERROR_LIBOPUS_ERROR   488

◆ JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT

#define JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT   483

◆ JANUS_AUDIOBRIDGE_ERROR_NO_MESSAGE

#define JANUS_AUDIOBRIDGE_ERROR_NO_MESSAGE   480

◆ JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_ROOM

#define JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_ROOM   485

◆ JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_USER

#define JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_USER   492

◆ JANUS_AUDIOBRIDGE_ERROR_NOT_JOINED

#define JANUS_AUDIOBRIDGE_ERROR_NOT_JOINED   487

◆ JANUS_AUDIOBRIDGE_ERROR_ROOM_EXISTS

#define JANUS_AUDIOBRIDGE_ERROR_ROOM_EXISTS   486

◆ JANUS_AUDIOBRIDGE_ERROR_UNAUTHORIZED

#define JANUS_AUDIOBRIDGE_ERROR_UNAUTHORIZED   489

◆ JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR

#define JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR   499

◆ JANUS_AUDIOBRIDGE_NAME

#define JANUS_AUDIOBRIDGE_NAME   "JANUS AudioBridge plugin"

◆ JANUS_AUDIOBRIDGE_PACKAGE

#define JANUS_AUDIOBRIDGE_PACKAGE   "janus.plugin.audiobridge"

◆ JANUS_AUDIOBRIDGE_VERSION

#define JANUS_AUDIOBRIDGE_VERSION   10

◆ JANUS_AUDIOBRIDGE_VERSION_STRING

#define JANUS_AUDIOBRIDGE_VERSION_STRING   "0.0.10"

◆ OPUS_SAMPLES

#define OPUS_SAMPLES   160

◆ USE_FEC

#define USE_FEC   0

Typedef Documentation

◆ janus_audiobridge_message

◆ janus_audiobridge_participant

◆ janus_audiobridge_room

◆ janus_audiobridge_rtp_forwarder

◆ janus_audiobridge_rtp_relay_packet

◆ janus_audiobridge_session

◆ wav_header

typedef struct wav_header wav_header

Function Documentation

◆ create()

janus_eventhandler * create ( void  )

◆ janus_audiobridge_create_session()

void janus_audiobridge_create_session ( janus_plugin_session handle,
int *  error 
)

◆ janus_audiobridge_destroy()

void janus_audiobridge_destroy ( void  )

◆ janus_audiobridge_destroy_session()

void janus_audiobridge_destroy_session ( janus_plugin_session handle,
int *  error 
)

◆ janus_audiobridge_get_api_compatibility()

int janus_audiobridge_get_api_compatibility ( void  )

◆ janus_audiobridge_get_author()

const char * janus_audiobridge_get_author ( void  )

◆ janus_audiobridge_get_description()

const char * janus_audiobridge_get_description ( void  )

◆ janus_audiobridge_get_name()

const char * janus_audiobridge_get_name ( void  )

◆ janus_audiobridge_get_package()

const char * janus_audiobridge_get_package ( void  )

◆ janus_audiobridge_get_version()

int janus_audiobridge_get_version ( void  )

◆ janus_audiobridge_get_version_string()

const char * janus_audiobridge_get_version_string ( void  )

◆ janus_audiobridge_handle_message()

struct janus_plugin_result * janus_audiobridge_handle_message ( janus_plugin_session handle,
char *  transaction,
json_t message,
json_t jsep 
)

◆ janus_audiobridge_hangup_media()

void janus_audiobridge_hangup_media ( janus_plugin_session handle)

◆ janus_audiobridge_incoming_rtcp()

void janus_audiobridge_incoming_rtcp ( janus_plugin_session handle,
int  video,
char *  buf,
int  len 
)

◆ janus_audiobridge_incoming_rtp()

void janus_audiobridge_incoming_rtp ( janus_plugin_session handle,
int  video,
char *  buf,
int  len 
)

◆ janus_audiobridge_init()

int janus_audiobridge_init ( janus_callbacks callback,
const char *  config_path 
)

◆ janus_audiobridge_query_session()

json_t * janus_audiobridge_query_session ( janus_plugin_session handle)

◆ janus_audiobridge_setup_media()

void janus_audiobridge_setup_media ( janus_plugin_session handle)