From f417f37f5f490ff7740f02e3e165234609133423 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 27 Oct 2012 20:52:48 -0700 Subject: [PATCH] Add audio encoding API. --- protocols/rdp/Makefile.am | 21 +++- protocols/rdp/include/audio.h | 156 ++++++++++++++++++++++++++++ protocols/rdp/include/ogg_encoder.h | 46 ++++++++ protocols/rdp/src/audio.c | 115 ++++++++++++++++++++ protocols/rdp/src/ogg_encoder.c | 74 +++++++++++++ 5 files changed, 407 insertions(+), 5 deletions(-) create mode 100644 protocols/rdp/include/audio.h create mode 100644 protocols/rdp/include/ogg_encoder.h create mode 100644 protocols/rdp/src/audio.c create mode 100644 protocols/rdp/src/ogg_encoder.c diff --git a/protocols/rdp/Makefile.am b/protocols/rdp/Makefile.am index cca4ebf0..2ffadb87 100644 --- a/protocols/rdp/Makefile.am +++ b/protocols/rdp/Makefile.am @@ -42,18 +42,29 @@ AM_CFLAGS = -Werror -Wall -Iinclude lib_LTLIBRARIES = libguac-client-rdp.la freerdp_LTLIBRARIES = guac_rdpsnd.la -libguac_client_rdp_la_SOURCES = src/client.c src/rdp_bitmap.c src/rdp_glyph.c src/rdp_pointer.c src/rdp_gdi.c src/guac_handlers.c src/rdp_cliprdr.c \ - src/rdp_keymap.c \ - src/rdp_keymap_base.c \ - src/rdp_keymap_en_us.c \ - src/default_pointer.c +libguac_client_rdp_la_SOURCES = \ + src/audio.c \ + src/client.c \ + src/rdp_bitmap.c \ + src/rdp_glyph.c \ + src/rdp_pointer.c \ + src/rdp_gdi.c \ + src/guac_handlers.c \ + src/ogg_encoder.c \ + src/rdp_cliprdr.c \ + src/rdp_keymap.c \ + src/rdp_keymap_base.c \ + src/rdp_keymap_en_us.c \ + src/default_pointer.c guac_rdpsnd_la_SOURCES = guac_rdpsnd/messages.c guac_rdpsnd/service.c noinst_HEADERS = \ + include/audio.h \ include/client.h \ include/default_pointer.h \ include/guac_handlers.h \ + include/ogg_encoder.h \ include/rdp_bitmap.h \ include/rdp_cliprdr.h \ include/rdp_gdi.h \ diff --git a/protocols/rdp/include/audio.h b/protocols/rdp/include/audio.h new file mode 100644 index 00000000..dadd04d1 --- /dev/null +++ b/protocols/rdp/include/audio.h @@ -0,0 +1,156 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-rdp. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __GUAC_TEST_AUDIO_H +#define __GUAC_TEST_AUDIO_H + +#include +#include + +typedef struct audio_stream audio_stream; + +/** + * Handler which is called when the audio stream is opened. + */ +typedef void audio_encoder_begin_handler(audio_stream* audio); + +/** + * Handler which is called when the audio stream is closed. + */ +typedef void audio_encoder_end_handler(audio_stream* audio); + +/** + * Handler which is called when the audio stream is flushed. + */ +typedef void audio_encoder_write_handler(audio_stream* audio, + int* pcm_data, int length); + +/** + * Arbitrary audio codec encoder. + */ +typedef struct audio_encoder { + + /** + * Handler which will be called when the audio stream is opened. + */ + audio_encoder_begin_handler* begin_handler; + + /** + * Handler which will be called when the audio stream is flushed. + */ + audio_encoder_write_handler* write_handler; + + /** + * Handler which will be called when the audio stream is closed. + */ + audio_encoder_end_handler* end_handler; + +} audio_encoder; + +/** + * Basic audio stream. PCM data is added to the stream. When the stream is + * flushed, a write handler receives PCM data packets and, presumably, streams + * them to the guac_stream provided. + */ +struct audio_stream { + + /** + * PCM data buffer, 16-bit samples, 2-channel. + */ + int* pcm_data; + + /** + * Number of samples in buffer. + */ + int used; + + /** + * Maximum number of samples in buffer. + */ + int length; + + /** + * Arbitrary codec encoder. When the PCM buffer is flushed, PCM data will be sent + * to this encoder. + */ + audio_encoder* encoder; + + /** + * The client associated with this audio stream. + */ + guac_client* client; + + /** + * The actual stream associated with this audio stream. + */ + guac_stream* stream; + +}; + +/** + * Allocates a new audio stream. + */ +audio_stream* audio_stream_alloc(guac_client* client, + audio_encoder* encoder); + +/** + * Frees the given audio stream. + */ +void audio_stream_free(audio_stream* stream); + +/** + * Begins a new audio stream. + */ +void audio_stream_begin(audio_stream* stream); + +/** + * Ends the current audio stream. + */ +void audio_stream_end(audio_stream* stream); + +/** + * Writes PCM data to the given audio stream. + */ +void audio_stream_write_pcm(audio_stream* stream, const int* data, int length); + +/** + * Flushes the given audio stream. + */ +void audio_stream_flush(audio_stream* stream); + +#endif + diff --git a/protocols/rdp/include/ogg_encoder.h b/protocols/rdp/include/ogg_encoder.h new file mode 100644 index 00000000..8a1048cc --- /dev/null +++ b/protocols/rdp/include/ogg_encoder.h @@ -0,0 +1,46 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-rdp. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __GUAC_OGG_ENCODER_H +#define __GUAC_OGG_ENCODER_H + +#include "audio.h" + +extern audio_encoder* ogg_encoder; + +#endif + diff --git a/protocols/rdp/src/audio.c b/protocols/rdp/src/audio.c new file mode 100644 index 00000000..eaf7f5ed --- /dev/null +++ b/protocols/rdp/src/audio.c @@ -0,0 +1,115 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-rdp. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include +#include + +#include "audio.h" + +audio_stream* audio_stream_alloc(guac_client* client, audio_encoder* encoder) { + + /* Allocate stream */ + audio_stream* audio = (audio_stream*) malloc(sizeof(audio_stream)); + + /* Reset buffer stats */ + audio->used = 0; + audio->length = 0x40000; + + /* Allocate buffer */ + audio->pcm_data = malloc(sizeof(int) * audio->length); + + /* Assign encoder */ + audio->encoder = encoder; + audio->stream = guac_client_alloc_stream(client); + + return audio; +} + +void audio_stream_begin(audio_stream* audio) { + audio->encoder->begin_handler(audio); +} + +void audio_stream_end(audio_stream* audio) { + audio_stream_flush(audio); + audio->encoder->end_handler(audio); +} + +void audio_stream_free(audio_stream* audio) { + free(audio->pcm_data); + free(audio); +} + +void audio_stream_write_pcm(audio_stream* audio, const int* data, int length) { + + /* Resize audio buffer if necessary */ + if (length > audio->length) { + + /* Resize to double provided length */ + audio->length = length*2; + audio->pcm_data = realloc(audio, sizeof(int) * audio->length); + + } + + /* Flush if necessary */ + if (audio->used + length > audio->length) + audio_stream_flush(audio); + + /* Append to buffer */ + memcpy(&(audio->pcm_data[audio->used]), data, sizeof(int) * length); + audio->used += length; + +} + +void audio_stream_flush(audio_stream* audio) { + + /* If data in buffer */ + if (audio->used != 0) { + + /* Write data */ + audio->encoder->write_handler(audio, + audio->pcm_data, audio->used); + + /* Reset buffer */ + audio->used = 0; + + } + +} + diff --git a/protocols/rdp/src/ogg_encoder.c b/protocols/rdp/src/ogg_encoder.c new file mode 100644 index 00000000..36790c3c --- /dev/null +++ b/protocols/rdp/src/ogg_encoder.c @@ -0,0 +1,74 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-rdp. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include + +#include "audio.h" + +void ogg_encoder_begin_handler(audio_stream* audio) { + + guac_client_log_info(audio->client, + "OGG: Beginning audio stream."); + +} + +void ogg_encoder_end_handler(audio_stream* audio) { + + guac_client_log_info(audio->client, + "OGG: Ending audio stream."); + +} + +void ogg_encoder_write_handler(audio_stream* audio, int* pcm_data, int length) { + + guac_client_log_info(audio->client, + "OGG: Writing data to stream, length=%i", + length); + +} + +/* Encoder handlers */ +audio_encoder _ogg_encoder = { + .begin_handler = ogg_encoder_begin_handler, + .write_handler = ogg_encoder_write_handler, + .end_handler = ogg_encoder_end_handler +}; + +/* Actual encoder */ +audio_encoder* ogg_encoder = &_ogg_encoder; +