summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv/sound.c
diff options
context:
space:
mode:
Diffstat (limited to 'sesman/chansrv/sound.c')
-rw-r--r--sesman/chansrv/sound.c219
1 files changed, 185 insertions, 34 deletions
diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c
index 66108651..e2b6f53b 100644
--- a/sesman/chansrv/sound.c
+++ b/sesman/chansrv/sound.c
@@ -35,6 +35,11 @@
static OpusEncoder *g_opus_encoder = 0;
#endif
+#if defined(XRDP_MP3LAME)
+#include <lame/lame.h>
+static lame_global_flags *g_lame_encoder = 0;
+#endif
+
extern int g_rdpsnd_chan_id; /* in chansrv.c */
extern int g_display_num; /* in chansrv.c */
@@ -72,12 +77,12 @@ struct xr_wave_format_ex
int nBlockAlign;
int wBitsPerSample;
int cbSize;
- char *data;
+ tui8 *data;
};
/* output formats */
-static char g_pcm_22050_data[] = { 0 };
+static tui8 g_pcm_22050_data[] = { 0 };
static struct xr_wave_format_ex g_pcm_22050 =
{
1, /* wFormatTag - WAVE_FORMAT_PCM */
@@ -90,7 +95,7 @@ static struct xr_wave_format_ex g_pcm_22050 =
g_pcm_22050_data /* data */
};
-static char g_pcm_44100_data[] = { 0 };
+static tui8 g_pcm_44100_data[] = { 0 };
static struct xr_wave_format_ex g_pcm_44100 =
{
1, /* wFormatTag - WAVE_FORMAT_PCM */
@@ -104,7 +109,7 @@ static struct xr_wave_format_ex g_pcm_44100 =
};
#if defined(XRDP_OPUS)
-static char g_opus_44100_data[] = { 0 };
+static tui8 g_opus_44100_data[] = { 0 };
static struct xr_wave_format_ex g_opus_44100 =
{
0x0069, /* wFormatTag - WAVE_FORMAT_OPUS */
@@ -118,27 +123,40 @@ static struct xr_wave_format_ex g_opus_44100 =
};
#endif
-
-#if defined(XRDP_OPUS)
-#define SND_NUM_OUTP_FORMATS 3
-static struct xr_wave_format_ex *g_wave_outp_formats[SND_NUM_OUTP_FORMATS] =
+#if defined(XRDP_MP3LAME)
+static tui8 g_mp3lame_44100_data[] = { 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x71, 0x05 };
+static struct xr_wave_format_ex g_mp3lame_44100 =
{
- &g_pcm_44100,
- &g_pcm_22050,
- &g_opus_44100
+ 0x0055, /* wFormatTag - WAVE_FORMAT_MPEGLAYER3 */
+ 2, /* num of channels */
+ 44100, /* samples per sec */
+ 176400, /* avg bytes per sec */
+ 4, /* block align */
+ 0, /* bits per sample */
+ 12, /* data size */
+ g_mp3lame_44100_data /* data */
};
-#else
-#define SND_NUM_OUTP_FORMATS 2
-static struct xr_wave_format_ex *g_wave_outp_formats[SND_NUM_OUTP_FORMATS] =
+#endif
+
+static struct xr_wave_format_ex *g_wave_outp_formats[] =
{
&g_pcm_44100,
- &g_pcm_22050
-};
+ &g_pcm_22050,
+#if defined(XRDP_OPUS)
+ &g_opus_44100,
+#endif
+#if defined(XRDP_MP3LAME)
+ &g_mp3lame_44100,
#endif
+ 0
+};
static int g_client_does_opus = 0;
static int g_client_opus_index = 0;
+static int g_client_does_mp3lame = 0;
+static int g_client_mp3lame_index = 0;
+
/* index into list from client */
static int g_current_client_format_index = 0;
@@ -147,7 +165,7 @@ static int g_current_server_format_index = 0;
/* input formats */
-static char g_pcm_inp_22050_data[] = { 0 };
+static tui8 g_pcm_inp_22050_data[] = { 0 };
static struct xr_wave_format_ex g_pcm_inp_22050 =
{
1, /* wFormatTag - WAVE_FORMAT_PCM */
@@ -160,7 +178,7 @@ static struct xr_wave_format_ex g_pcm_inp_22050 =
g_pcm_inp_22050_data /* data */
};
-static char g_pcm_inp_44100_data[] = { 0 };
+static tui8 g_pcm_inp_44100_data[] = { 0 };
static struct xr_wave_format_ex g_pcm_inp_44100 =
{
1, /* wFormatTag - WAVE_FORMAT_PCM */
@@ -173,11 +191,11 @@ static struct xr_wave_format_ex g_pcm_inp_44100 =
g_pcm_inp_44100_data /* data */
};
-#define SND_NUM_INP_FORMATS 2
-static struct xr_wave_format_ex *g_wave_inp_formats[SND_NUM_INP_FORMATS] =
+static struct xr_wave_format_ex *g_wave_inp_formats[] =
{
&g_pcm_inp_44100,
- &g_pcm_inp_22050
+ &g_pcm_inp_22050,
+ 0
};
static int g_client_input_format_index = 0;
@@ -204,8 +222,13 @@ sound_send_server_output_formats(void)
struct stream *s;
int bytes;
int index;
+ int num_formats;
char *size_ptr;
+ num_formats = sizeof(g_wave_outp_formats) /
+ sizeof(g_wave_outp_formats[0]) - 1;
+ LOG(10, ("sound_send_server_output_formats: num_formats %d", num_formats));
+
make_stream(s);
init_stream(s, 8182);
out_uint16_le(s, SNDC_FORMATS);
@@ -215,9 +238,9 @@ sound_send_server_output_formats(void)
out_uint32_le(s, 0); /* dwVolume */
out_uint32_le(s, 0); /* dwPitch */
out_uint16_le(s, 0); /* wDGramPort */
- out_uint16_le(s, SND_NUM_OUTP_FORMATS); /* wNumberOfFormats */
+ out_uint16_le(s, num_formats); /* wNumberOfFormats */
out_uint8(s, g_cBlockNo); /* cLastBlockConfirmed */
- out_uint16_le(s, 2); /* wVersion */
+ out_uint16_le(s, 5); /* wVersion */
out_uint8(s, 0); /* bPad */
/* sndFormats */
@@ -239,7 +262,7 @@ sound_send_server_output_formats(void)
00 00
*/
- for (index = 0; index < SND_NUM_OUTP_FORMATS; index++)
+ for (index = 0; index < num_formats; index++)
{
out_uint16_le(s, g_wave_outp_formats[index]->wFormatTag);
out_uint16_le(s, g_wave_outp_formats[index]->nChannels);
@@ -341,10 +364,18 @@ sound_process_output_format(int aindex, int wFormatTag, int nChannels,
if (wFormatTag == 0x0069)
{
+ LOG(0, ("wFormatTag, opus"));
g_client_does_opus = 1;
g_client_opus_index = aindex;
g_bbuf_size = 11520;
}
+ else if (wFormatTag == 0x0055)
+ {
+ LOG(0, ("wFormatTag, mp3"));
+ g_client_does_mp3lame = 1;
+ g_client_mp3lame_index = aindex;
+ g_bbuf_size = 11520;
+ }
return 0;
}
@@ -403,7 +434,7 @@ sound_process_output_formats(struct stream *s, int size)
/*****************************************************************************/
static int
-sound_wave_compress(char *data, int data_bytes, int *format_index)
+sound_wave_compress_opus(char *data, int data_bytes, int *format_index)
{
unsigned char *cdata;
int cdata_bytes;
@@ -428,7 +459,7 @@ sound_wave_compress(char *data, int data_bytes, int *format_index)
&error);
if (g_opus_encoder == 0)
{
- LOG(0, ("sound_wave_compress: opus_encoder_create failed"));
+ LOG(0, ("sound_wave_compress_opus: opus_encoder_create failed"));
return data_bytes;
}
}
@@ -465,7 +496,95 @@ sound_wave_compress(char *data, int data_bytes, int *format_index)
/*****************************************************************************/
static int
-sound_wave_compress(char *data, int data_bytes, int *format_index)
+sound_wave_compress_opus(char *data, int data_bytes, int *format_index)
+{
+ return data_bytes;
+}
+
+#endif
+
+#if defined(XRDP_MP3LAME)
+
+/*****************************************************************************/
+static int
+sound_wave_compress_mp3lame(char *data, int data_bytes, int *format_index)
+{
+ int rv;
+ int cdata_bytes;
+ int odata_bytes;
+ unsigned char *cdata;
+
+ cdata = NULL;
+ rv = data_bytes;
+
+ if (g_client_does_mp3lame == 0)
+ {
+ return rv;
+ }
+
+ if (g_lame_encoder == 0)
+ {
+ /* init mp3 lame encoder */
+ LOG(0, ("sound_wave_compress_mp3lame: using mp3lame"));
+
+ g_lame_encoder = lame_init();
+ if (g_lame_encoder == 0)
+ {
+ LOG(0, ("sound_wave_compress_mp3lame: lame_init() failed"));
+ return rv;
+ }
+ lame_set_num_channels(g_lame_encoder, g_mp3lame_44100.nChannels);
+ lame_set_in_samplerate(g_lame_encoder, g_mp3lame_44100.nSamplesPerSec);
+ if (lame_init_params(g_lame_encoder) == -1)
+ {
+ LOG(0, ("sound_wave_compress_mp3lame: lame_init_params() failed"));
+ return rv;
+ }
+
+ LOG(0, ("sound_wave_compress_mp3lame: lame config:"));
+ LOG(0, (" brate : %d", lame_get_brate(g_lame_encoder)));
+ LOG(0, (" compression ratio: %f", lame_get_compression_ratio(g_lame_encoder)));
+ LOG(0, (" encoder delay : %d", lame_get_encoder_delay(g_lame_encoder)));
+ LOG(0, (" frame size : %d", lame_get_framesize(g_lame_encoder)));
+ LOG(0, (" encoder padding : %d", lame_get_encoder_padding(g_lame_encoder)));
+ LOG(0, (" mode : %d", lame_get_mode(g_lame_encoder)));
+ }
+
+ odata_bytes = data_bytes;
+ cdata_bytes = data_bytes;
+ cdata = (unsigned char *) g_malloc(cdata_bytes, 0);
+ if (data_bytes < g_bbuf_size)
+ {
+ g_memset(data + data_bytes, 0, g_bbuf_size - data_bytes);
+ data_bytes = g_bbuf_size;
+ }
+ cdata_bytes = lame_encode_buffer_interleaved(g_lame_encoder,
+ (short int *) data,
+ data_bytes / 4,
+ cdata,
+ cdata_bytes);
+ if (cdata_bytes < 0)
+ {
+ LOG(0, ("sound_wave_compress: lame_encode_buffer_interleaved() "
+ "failed, error %d", cdata_bytes));
+ return rv;
+ }
+ if ((cdata_bytes > 0) && (cdata_bytes < odata_bytes))
+ {
+ *format_index = g_client_mp3lame_index;
+ g_memcpy(data, cdata, cdata_bytes);
+ rv = cdata_bytes;
+ }
+
+ g_free(cdata);
+ return rv;
+}
+
+#else
+
+/*****************************************************************************/
+static int
+sound_wave_compress_mp3lame(char *data, int data_bytes, int *format_index)
{
return data_bytes;
}
@@ -473,6 +592,21 @@ sound_wave_compress(char *data, int data_bytes, int *format_index)
#endif
/*****************************************************************************/
+static int
+sound_wave_compress(char *data, int data_bytes, int *format_index)
+{
+ if (g_client_does_opus)
+ {
+ return sound_wave_compress_opus(data, data_bytes, format_index);
+ }
+ else if (g_client_does_mp3lame)
+ {
+ return sound_wave_compress_mp3lame(data, data_bytes, format_index);
+ }
+ return data_bytes;
+}
+
+/*****************************************************************************/
/* send wave message to client */
static int
sound_send_wave_data_chunk(char *data, int data_bytes)
@@ -820,6 +954,9 @@ sound_init(void)
g_client_does_opus = 0;
g_client_opus_index = 0;
+ g_client_does_mp3lame = 0;
+ g_client_mp3lame_index = 0;
+
return 0;
}
@@ -852,6 +989,15 @@ sound_deinit(void)
g_audio_c_trans_in = 0;
}
+#if defined(XRDP_MP3LAME)
+ if (g_lame_encoder)
+ {
+ lame_close(g_lame_encoder);
+ g_lame_encoder = 0;
+ g_client_does_mp3lame = 0;
+ }
+#endif
+
fifo_deinit(&g_in_fifo);
return 0;
@@ -1014,10 +1160,15 @@ sound_check_wait_objs(void)
static int APP_CC
sound_send_server_input_formats(void)
{
- struct stream* s;
- int bytes;
- int index;
- char* size_ptr;
+ struct stream *s;
+ int bytes;
+ int index;
+ int num_formats;
+ char *size_ptr;
+
+ num_formats = sizeof(g_wave_inp_formats) /
+ sizeof(g_wave_inp_formats[0]) - 1;
+ LOG(10, ("sound_send_server_input_formats: num_formats %d", num_formats));
make_stream(s);
init_stream(s, 8182);
@@ -1026,8 +1177,8 @@ sound_send_server_input_formats(void)
out_uint16_le(s, 0); /* size, set later */
out_uint32_le(s, 0); /* unused */
out_uint32_le(s, 0); /* unused */
- out_uint16_le(s, SND_NUM_INP_FORMATS); /* wNumberOfFormats */
- out_uint16_le(s, 2); /* wVersion */
+ out_uint16_le(s, num_formats); /* wNumberOfFormats */
+ out_uint16_le(s, 5); /* wVersion */
/*
wFormatTag 2 byte offset 0
@@ -1040,7 +1191,7 @@ sound_send_server_input_formats(void)
data variable offset 18
*/
- for (index = 0; index < SND_NUM_INP_FORMATS; index++)
+ for (index = 0; index < num_formats; index++)
{
out_uint16_le(s, g_wave_inp_formats[index]->wFormatTag);
out_uint16_le(s, g_wave_inp_formats[index]->nChannels);