GUACAMOLE-179: Use non-owner users of connection to determine audio encoding if necessary.
This commit is contained in:
parent
48ebbe95ea
commit
440668a78a
@ -30,16 +30,38 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the encoder associated with the given guac_audio_stream, automatically
|
||||||
|
* invoking its begin_handler. The guac_audio_stream MUST NOT already be
|
||||||
|
* associated with an encoder.
|
||||||
|
*
|
||||||
|
* @param audio
|
||||||
|
* The guac_audio_stream whose encoder is being set.
|
||||||
|
*
|
||||||
|
* @param encoder
|
||||||
|
* The encoder to associate with the given guac_audio_stream.
|
||||||
|
*/
|
||||||
|
static void guac_audio_stream_set_encoder(guac_audio_stream* audio,
|
||||||
|
guac_audio_encoder* encoder) {
|
||||||
|
|
||||||
|
/* Call handler, if defined */
|
||||||
|
if (encoder != NULL && encoder->begin_handler)
|
||||||
|
encoder->begin_handler(audio);
|
||||||
|
|
||||||
|
/* Assign encoder, which may be NULL */
|
||||||
|
audio->encoder = encoder;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns a new audio encoder to the given guac_audio_stream based on the
|
* Assigns a new audio encoder to the given guac_audio_stream based on the
|
||||||
* audio mimetypes declared as supported by the given user. If no audio encoder
|
* audio mimetypes declared as supported by the given user. If no audio encoder
|
||||||
* can be found, no new audio encoder is assigned, and the existing encoder is
|
* can be found, no new audio encoder is assigned, and the existing encoder is
|
||||||
* left untouched (if any).
|
* left untouched (if any).
|
||||||
*
|
*
|
||||||
* @param owner
|
* @param user
|
||||||
* The user whose supported audio mimetypes should determine the audio
|
* The user whose supported audio mimetypes should determine the audio
|
||||||
* encoder selected. It is expected that this user will be the owner of
|
* encoder selected.
|
||||||
* the connection.
|
|
||||||
*
|
*
|
||||||
* @param data
|
* @param data
|
||||||
* The guac_audio_stream to which the new encoder should be assigned.
|
* The guac_audio_stream to which the new encoder should be assigned.
|
||||||
@ -50,31 +72,32 @@
|
|||||||
* The assigned audio encoder. If no new audio encoder can be assigned,
|
* The assigned audio encoder. If no new audio encoder can be assigned,
|
||||||
* this will be the currently-assigned audio encoder (which may be NULL).
|
* this will be the currently-assigned audio encoder (which may be NULL).
|
||||||
*/
|
*/
|
||||||
static void* guac_audio_assign_encoder(guac_user* owner, void* data) {
|
static void* guac_audio_assign_encoder(guac_user* user, void* data) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
guac_audio_stream* audio = (guac_audio_stream*) data;
|
guac_audio_stream* audio = (guac_audio_stream*) data;
|
||||||
int bps = audio->bps;
|
int bps = audio->bps;
|
||||||
|
|
||||||
/* If there is no owner, do not attempt to assign a new encoder */
|
/* If no user is provided, or an encoder has already been assigned,
|
||||||
if (owner == NULL)
|
* do not attempt to assign a new encoder */
|
||||||
|
if (user == NULL || audio->encoder != NULL)
|
||||||
return audio->encoder;
|
return audio->encoder;
|
||||||
|
|
||||||
/* For each supported mimetype, check for an associated encoder */
|
/* For each supported mimetype, check for an associated encoder */
|
||||||
for (i=0; owner->info.audio_mimetypes[i] != NULL; i++) {
|
for (i=0; user->info.audio_mimetypes[i] != NULL; i++) {
|
||||||
|
|
||||||
const char* mimetype = owner->info.audio_mimetypes[i];
|
const char* mimetype = user->info.audio_mimetypes[i];
|
||||||
|
|
||||||
/* If 16-bit raw audio is supported, done. */
|
/* If 16-bit raw audio is supported, done. */
|
||||||
if (bps == 16 && strcmp(mimetype, raw16_encoder->mimetype) == 0) {
|
if (bps == 16 && strcmp(mimetype, raw16_encoder->mimetype) == 0) {
|
||||||
audio->encoder = raw16_encoder;
|
guac_audio_stream_set_encoder(audio, raw16_encoder);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If 8-bit raw audio is supported, done. */
|
/* If 8-bit raw audio is supported, done. */
|
||||||
if (bps == 8 && strcmp(mimetype, raw8_encoder->mimetype) == 0) {
|
if (bps == 8 && strcmp(mimetype, raw8_encoder->mimetype) == 0) {
|
||||||
audio->encoder = raw8_encoder;
|
guac_audio_stream_set_encoder(audio, raw8_encoder);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,16 +123,17 @@ guac_audio_stream* guac_audio_stream_alloc(guac_client* client,
|
|||||||
audio->channels = channels;
|
audio->channels = channels;
|
||||||
audio->bps = bps;
|
audio->bps = bps;
|
||||||
|
|
||||||
/* Assign encoder for owner, abort if no encoder can be found */
|
/* Assign encoder if explicitly provided */
|
||||||
if (!guac_client_for_owner(client, guac_audio_assign_encoder, audio)) {
|
if (encoder != NULL)
|
||||||
guac_client_free_stream(client, audio->stream);
|
guac_audio_stream_set_encoder(audio, encoder);
|
||||||
free(audio);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call handler, if defined */
|
/* Otherwise, attempt to automatically assign encoder for owner */
|
||||||
if (audio->encoder->begin_handler)
|
if (audio->encoder == NULL)
|
||||||
audio->encoder->begin_handler(audio);
|
guac_client_for_owner(client, guac_audio_assign_encoder, audio);
|
||||||
|
|
||||||
|
/* Failing that, attempt to assign encoder for ANY connected user */
|
||||||
|
if (audio->encoder == NULL)
|
||||||
|
guac_client_foreach_user(client, guac_audio_assign_encoder, audio);
|
||||||
|
|
||||||
return audio;
|
return audio;
|
||||||
|
|
||||||
@ -118,8 +142,12 @@ guac_audio_stream* guac_audio_stream_alloc(guac_client* client,
|
|||||||
void guac_audio_stream_reset(guac_audio_stream* audio,
|
void guac_audio_stream_reset(guac_audio_stream* audio,
|
||||||
guac_audio_encoder* encoder, int rate, int channels, int bps) {
|
guac_audio_encoder* encoder, int rate, int channels, int bps) {
|
||||||
|
|
||||||
|
/* Pull assigned encoder if no other encoder is requested */
|
||||||
|
if (encoder == NULL)
|
||||||
|
encoder = audio->encoder;
|
||||||
|
|
||||||
/* Do nothing if nothing is changing */
|
/* Do nothing if nothing is changing */
|
||||||
if ((encoder == NULL || encoder == audio->encoder)
|
if (encoder == audio->encoder
|
||||||
&& rate == audio->rate
|
&& rate == audio->rate
|
||||||
&& channels == audio->channels
|
&& channels == audio->channels
|
||||||
&& bps == audio->bps) {
|
&& bps == audio->bps) {
|
||||||
@ -127,31 +155,28 @@ void guac_audio_stream_reset(guac_audio_stream* audio,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Free old encoder data */
|
/* Free old encoder data */
|
||||||
if (audio->encoder->end_handler)
|
if (audio->encoder != NULL && audio->encoder->end_handler)
|
||||||
audio->encoder->end_handler(audio);
|
audio->encoder->end_handler(audio);
|
||||||
|
|
||||||
/* Assign new encoder, if changed */
|
|
||||||
if (encoder != NULL)
|
|
||||||
audio->encoder = encoder;
|
|
||||||
|
|
||||||
/* Set PCM properties */
|
/* Set PCM properties */
|
||||||
audio->rate = rate;
|
audio->rate = rate;
|
||||||
audio->channels = channels;
|
audio->channels = channels;
|
||||||
audio->bps = bps;
|
audio->bps = bps;
|
||||||
|
|
||||||
/* Init encoder with new data */
|
/* Re-init encoder */
|
||||||
if (audio->encoder->begin_handler)
|
guac_audio_stream_set_encoder(audio, encoder);
|
||||||
audio->encoder->begin_handler(audio);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_audio_stream_add_user(guac_audio_stream* audio, guac_user* user) {
|
void guac_audio_stream_add_user(guac_audio_stream* audio, guac_user* user) {
|
||||||
|
|
||||||
guac_audio_encoder* encoder = audio->encoder;
|
/* Attempt to assign encoder if no encoder has yet been assigned */
|
||||||
|
if (audio->encoder == NULL)
|
||||||
|
guac_audio_assign_encoder(user, audio);
|
||||||
|
|
||||||
/* Notify encoder that a new user is present */
|
/* Notify encoder that a new user is present */
|
||||||
if (encoder->join_handler)
|
if (audio->encoder != NULL && audio->encoder->join_handler)
|
||||||
encoder->join_handler(audio, user);
|
audio->encoder->join_handler(audio, user);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +186,7 @@ void guac_audio_stream_free(guac_audio_stream* audio) {
|
|||||||
guac_audio_stream_flush(audio);
|
guac_audio_stream_flush(audio);
|
||||||
|
|
||||||
/* Clean up encoder */
|
/* Clean up encoder */
|
||||||
if (audio->encoder->end_handler)
|
if (audio->encoder != NULL && audio->encoder->end_handler)
|
||||||
audio->encoder->end_handler(audio);
|
audio->encoder->end_handler(audio);
|
||||||
|
|
||||||
/* Free associated data */
|
/* Free associated data */
|
||||||
@ -173,7 +198,7 @@ void guac_audio_stream_write_pcm(guac_audio_stream* audio,
|
|||||||
const unsigned char* data, int length) {
|
const unsigned char* data, int length) {
|
||||||
|
|
||||||
/* Write data */
|
/* Write data */
|
||||||
if (audio->encoder->write_handler)
|
if (audio->encoder != NULL && audio->encoder->write_handler)
|
||||||
audio->encoder->write_handler(audio, data, length);
|
audio->encoder->write_handler(audio, data, length);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -181,7 +206,7 @@ void guac_audio_stream_write_pcm(guac_audio_stream* audio,
|
|||||||
void guac_audio_stream_flush(guac_audio_stream* audio) {
|
void guac_audio_stream_flush(guac_audio_stream* audio) {
|
||||||
|
|
||||||
/* Flush any buffered data */
|
/* Flush any buffered data */
|
||||||
if (audio->encoder->flush_handler)
|
if (audio->encoder != NULL && audio->encoder->flush_handler)
|
||||||
audio->encoder->flush_handler(audio);
|
audio->encoder->flush_handler(audio);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ struct guac_audio_stream {
|
|||||||
* Allocates a new audio stream at the client level which encodes audio data
|
* Allocates a new audio stream at the client level which encodes audio data
|
||||||
* using the given encoder. If NULL is specified for the encoder, an
|
* using the given encoder. If NULL is specified for the encoder, an
|
||||||
* appropriate encoder will be selected based on the encoders built into
|
* appropriate encoder will be selected based on the encoders built into
|
||||||
* libguac and the level of support declared by the owner associated with the
|
* libguac and the level of support declared by users associated with the
|
||||||
* given guac_client. The PCM format specified here (via rate, channels, and
|
* given guac_client. The PCM format specified here (via rate, channels, and
|
||||||
* bps) must be the format used for all PCM data provided to the audio stream.
|
* bps) must be the format used for all PCM data provided to the audio stream.
|
||||||
* The format may only be changed using guac_audio_stream_reset().
|
* The format may only be changed using guac_audio_stream_reset().
|
||||||
@ -125,10 +125,10 @@ struct guac_audio_stream {
|
|||||||
* for the new user.
|
* for the new user.
|
||||||
*
|
*
|
||||||
* @param client
|
* @param client
|
||||||
* The guac_client for which this audio stream is being allocated. Only the
|
* The guac_client for which this audio stream is being allocated. The
|
||||||
* connection owner is used to determine the level of audio support, and it
|
* connection owner is given priority when determining the level of audio
|
||||||
* is currently assumed that all other joining users on the connection will
|
* support. It is currently assumed that all other joining users on the
|
||||||
* have the same level of audio support.
|
* connection will have the same level of audio support.
|
||||||
*
|
*
|
||||||
* @param encoder
|
* @param encoder
|
||||||
* The guac_audio_encoder to use when encoding audio, or NULL if libguac
|
* The guac_audio_encoder to use when encoding audio, or NULL if libguac
|
||||||
|
@ -236,9 +236,6 @@ guac_pa_stream* guac_pa_stream_alloc(guac_client* client,
|
|||||||
if (audio == NULL)
|
if (audio == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
guac_client_log(client, GUAC_LOG_INFO, "Audio will be encoded as %s",
|
|
||||||
audio->encoder->mimetype);
|
|
||||||
|
|
||||||
/* Init main loop */
|
/* Init main loop */
|
||||||
guac_pa_stream* stream = malloc(sizeof(guac_pa_stream));
|
guac_pa_stream* stream = malloc(sizeof(guac_pa_stream));
|
||||||
stream->client = client;
|
stream->client = client;
|
||||||
|
Loading…
Reference in New Issue
Block a user