diff --git a/src/protocols/rdp/audio_input.c b/src/protocols/rdp/audio_input.c index 9e88fb5c..0eb757d8 100644 --- a/src/protocols/rdp/audio_input.c +++ b/src/protocols/rdp/audio_input.c @@ -250,28 +250,49 @@ void guac_rdp_audio_buffer_set_stream(guac_rdp_audio_buffer* audio_buffer, guac_rdp_audio_buffer_ack(audio_buffer, "OK", GUAC_PROTOCOL_STATUS_SUCCESS); + guac_user_log(user, GUAC_LOG_DEBUG, "User is requesting to provide audio " + "input as %i-channel, %i Hz PCM audio at %i bytes/sample.", + audio_buffer->in_format.channels, + audio_buffer->in_format.rate, + audio_buffer->in_format.bps); + + pthread_mutex_unlock(&(audio_buffer->lock)); + +} + +void guac_rdp_audio_buffer_set_output(guac_rdp_audio_buffer* audio_buffer, + int rate, int channels, int bps) { + + pthread_mutex_lock(&(audio_buffer->lock)); + + /* Set output format */ + audio_buffer->out_format.rate = rate; + audio_buffer->out_format.channels = channels; + audio_buffer->out_format.bps = bps; + pthread_mutex_unlock(&(audio_buffer->lock)); } void guac_rdp_audio_buffer_begin(guac_rdp_audio_buffer* audio_buffer, - int rate, int channels, int bps, int packet_size, - guac_rdp_audio_buffer_flush_handler* flush_handler, void* data) { + int packet_frames, guac_rdp_audio_buffer_flush_handler* flush_handler, + void* data) { pthread_mutex_lock(&(audio_buffer->lock)); /* Reset buffer state to provided values */ audio_buffer->bytes_written = 0; - audio_buffer->out_format.rate = rate; - audio_buffer->out_format.channels = channels; - audio_buffer->out_format.bps = bps; - audio_buffer->packet_size = packet_size; audio_buffer->flush_handler = flush_handler; audio_buffer->data = data; + /* Calculate size of each packet in bytes */ + audio_buffer->packet_size = packet_frames + * audio_buffer->out_format.channels + * audio_buffer->out_format.bps; + /* Allocate new buffer */ free(audio_buffer->packet); - audio_buffer->packet = malloc(packet_size); + audio_buffer->packet = malloc(audio_buffer->packet_size); /* Acknowledge stream creation (if stream is ready to receive) */ guac_rdp_audio_buffer_ack(audio_buffer, diff --git a/src/protocols/rdp/audio_input.h b/src/protocols/rdp/audio_input.h index 0970671b..87eee9a9 100644 --- a/src/protocols/rdp/audio_input.h +++ b/src/protocols/rdp/audio_input.h @@ -180,29 +180,43 @@ guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc(); void guac_rdp_audio_buffer_set_stream(guac_rdp_audio_buffer* audio_buffer, guac_user* user, guac_stream* stream, int rate, int channels, int bps); +/** + * Defines the output format that should be used by the audio buffer when + * flushing packets of audio data received via guac_rdp_audio_buffer_write(). + * As this format determines how the underlying packet buffer will be + * allocated, this function MUST be called prior to the call to + * guac_rdp_audio_buffer_begin(). + * + * @param audio_buffer + * The audio buffer to set the output format of. + * + * @param rate + * The rate of the audio stream expected by RDP, in samples per second. + * + * @param channels + * The number of channels included in the audio stream expected by RDP. + * + * @param bps + * The size of each sample within the audio stream expected by RDP, in + * bytes. + */ +void guac_rdp_audio_buffer_set_output(guac_rdp_audio_buffer* audio_buffer, + int rate, int channels, int bps); + /** * Begins handling of audio data received via guac_rdp_audio_buffer_write() and - * allocates the necessary underlying packet buffer. Audio packets of exactly - * packet_size bytes will be flushed as available using the provided - * flush_handler. + * allocates the necessary underlying packet buffer. Audio packets having + * exactly packet_frames frames will be flushed as available using the provided + * flush_handler. An audio frame is a set of single samples, one sample per + * channel. The guac_rdp_audio_buffer_set_output() function MUST have + * been invoked first. * * @param audio_buffer * The audio buffer to begin. * - * @param rate - * The rate of the audio stream expected by RDP, if any, in samples per - * second. - * - * @param channels - * The number of channels included in the audio stream expected by RDP, if - * any. - * - * @param bps - * The size of each sample within the audio stream expected by RDP, if any, - * in bytes. - * - * @param packet_size - * The number of bytes to include in all audio packets provided to the + * @param packet_frames + * The exact number of frames (a set of samples, one for each channel) + * which MUST be included in all audio packets provided to the * given flush_handler. * * @param flush_handler @@ -213,8 +227,8 @@ void guac_rdp_audio_buffer_set_stream(guac_rdp_audio_buffer* audio_buffer, * needs to be flushed. */ void guac_rdp_audio_buffer_begin(guac_rdp_audio_buffer* audio_buffer, - int rate, int channels, int bps, int packet_size, - guac_rdp_audio_buffer_flush_handler* flush_handler, void* data); + int packet_frames, guac_rdp_audio_buffer_flush_handler* flush_handler, + void* data); /** * Writes the given buffer of audio data to the given audio buffer. A new diff --git a/src/protocols/rdp/guac_ai/ai_messages.c b/src/protocols/rdp/guac_ai/ai_messages.c index eeb3e287..c3465878 100644 --- a/src/protocols/rdp/guac_ai/ai_messages.c +++ b/src/protocols/rdp/guac_ai/ai_messages.c @@ -251,6 +251,9 @@ void guac_rdp_ai_process_version(guac_client* client, void guac_rdp_ai_process_formats(guac_client* client, IWTSVirtualChannel* channel, wStream* stream) { + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input; + UINT32 num_formats; Stream_Read_UINT32(stream, num_formats); /* NumFormats */ Stream_Seek_UINT32(stream); /* cbSizeFormatsPacket (MUST BE IGNORED) */ @@ -265,6 +268,10 @@ void guac_rdp_ai_process_formats(guac_client* client, if (format.tag != GUAC_RDP_WAVE_FORMAT_PCM) continue; + /* Set output format of internal audio buffer to match RDP server */ + guac_rdp_audio_buffer_set_output(audio_buffer, format.rate, + format.channels, format.bps / 8); + /* Accept single format */ guac_rdp_ai_send_incoming_data(channel); guac_rdp_ai_send_formats(channel, &format, 1); @@ -301,18 +308,19 @@ void guac_rdp_ai_process_open(guac_client* client, Stream_Read_UINT32(stream, packet_frames); /* FramesPerPacket */ Stream_Read_UINT32(stream, initial_format); /* InitialFormat */ - /* STUB */ - guac_client_log(client, GUAC_LOG_DEBUG, "AUDIO_INPUT: open: " - "packet_frames=%i, initial_format=%i", - packet_frames, initial_format); + guac_client_log(client, GUAC_LOG_DEBUG, "RDP server is accepting audio " + "input as %i-channel, %i Hz PCM audio at %i bytes/sample.", + audio_buffer->out_format.channels, + audio_buffer->out_format.rate, + audio_buffer->out_format.bps); /* Success */ guac_rdp_ai_send_formatchange(channel, initial_format); guac_rdp_ai_send_open_reply(channel, 0); - /* FIXME: Assuming mimetype of 16-bit 44100 Hz stereo PCM */ - guac_rdp_audio_buffer_begin(audio_buffer, packet_frames * 2 * 2, - 44100, 2, 2, guac_rdp_ai_flush_packet, channel); + /* Begin receiving audio data */ + guac_rdp_audio_buffer_begin(audio_buffer, packet_frames, + guac_rdp_ai_flush_packet, channel); }