chansrv: added opus audio compression for playback

ulab-next-nosound
Jay Sorg 9 years ago
parent 46215e36d1
commit 2f5b84b712

@ -69,6 +69,10 @@ AC_ARG_ENABLE(rfxcodec, AS_HELP_STRING([--enable-rfxcodec],
[Build using librfxcodec (default: no)]),
[], [enable_rfxcodec=no])
AM_CONDITIONAL(XRDP_RFXCODEC, [test x$enable_rfxcodec = xyes])
AC_ARG_ENABLE(opus, AS_HELP_STRING([--enable-opus],
[Build opus(audio codec) (default: no)]),
[], [enable_opus=no])
AM_CONDITIONAL(XRDP_OPUS, [test x$enable_opus = xyes])
AM_CONDITIONAL(GOT_PREFIX, test "x${prefix}" != "xNONE"])
@ -122,6 +126,13 @@ then
[#define _FILE_OFFSET_BITS 64])
fi
# checking for opus
if test "x$enable_opus" = "xyes"
then
AC_CHECK_HEADER([opus/opus.h], [],
[AC_MSG_ERROR([please install libopus-dev or opus-devel])])
fi
# checking for TurboJPEG
if test "x$enable_tjpeg" = "xyes"
then

@ -22,6 +22,11 @@ EXTRA_DEFINES += -DXRDP_FUSE
EXTRA_LIBS += -lfuse
endif
if XRDP_OPUS
EXTRA_DEFINES += -DXRDP_OPUS
EXTRA_LIBS += -lopus
endif
AM_CFLAGS = \
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
-DXRDP_SBIN_PATH=\"${sbindir}\" \

@ -30,6 +30,11 @@
#include "file_loc.h"
#include "chansrv_common.h"
#if defined(XRDP_OPUS)
#include <opus/opus.h>
static OpusEncoder *g_opus_encoder = 0;
#endif
extern int g_rdpsnd_chan_id; /* in chansrv.c */
extern int g_display_num; /* in chansrv.c */
@ -50,11 +55,13 @@ static int g_bytes_in_fifo = 0;
static struct stream *g_stream_inp = NULL;
static struct stream *g_stream_incoming_packet = NULL;
#define BBUF_SIZE (1024 * 8)
char g_buffer[BBUF_SIZE];
int g_buf_index = 0;
int g_sent_time[256];
int g_sent_flag[256];
#define MAX_BBUF_SIZE (1024 * 16)
static char g_buffer[MAX_BBUF_SIZE];
static int g_buf_index = 0;
static int g_sent_time[256];
static int g_sent_flag[256];
static int g_bbuf_size = 1024 * 8; /* may change later */
struct xr_wave_format_ex
{
@ -96,12 +103,39 @@ static struct xr_wave_format_ex g_pcm_44100 =
g_pcm_44100_data /* data */
};
static char g_opus_44100_data[] = { 0 };
static struct xr_wave_format_ex g_opus_44100 =
{
0x0069, /* wFormatTag - WAVE_FORMAT_OPUS */
2, /* num of channels */
44100, /* samples per sec */
176400, /* avg bytes per sec */
4, /* block align */
16, /* bits per sample */
0, /* data size */
g_opus_44100_data /* data */
};
#if defined(XRDP_OPUS)
#define SND_NUM_OUTP_FORMATS 3
static struct xr_wave_format_ex *g_wave_outp_formats[SND_NUM_OUTP_FORMATS] =
{
&g_pcm_44100,
&g_pcm_22050,
&g_opus_44100
};
#else
#define SND_NUM_OUTP_FORMATS 2
static struct xr_wave_format_ex *g_wave_outp_formats[SND_NUM_OUTP_FORMATS] =
{
&g_pcm_44100,
&g_pcm_22050
};
#endif
static int g_client_does_opus = 0;
static int g_client_opus_index = 0;
/* index into list from client */
static int g_current_client_format_index = 0;
@ -302,6 +336,14 @@ sound_process_output_format(int aindex, int wFormatTag, int nChannels,
}
}
#endif
if (wFormatTag == 0x0069)
{
g_client_does_opus = 1;
g_client_opus_index = aindex;
g_bbuf_size = 11520;
}
return 0;
}
@ -355,6 +397,72 @@ sound_process_output_formats(struct stream *s, int size)
return 0;
}
#if defined(XRDP_OPUS)
/*****************************************************************************/
static int
sound_wave_compress(char *data, int data_bytes, int *format_index)
{
unsigned char *cdata;
int cdata_bytes;
int rv;
int error;
opus_int16 *os16;
if (g_client_does_opus == 0)
{
return data_bytes;
}
if (g_opus_encoder == 0)
{
// NB (narrowband) 8 kHz
// MB (medium-band) 12 kHz
// WB (wideband) 16 kHz
// SWB (super-wideband) 24 kHz
// FB (fullband) 48 kHz
g_opus_encoder = opus_encoder_create(48000, 2,
OPUS_APPLICATION_AUDIO,
&error);
if (g_opus_encoder == 0)
{
LOG(0, ("sound_wave_compress: opus_encoder_create failed"));
return data_bytes;
}
}
rv = data_bytes;
cdata_bytes = data_bytes;
cdata = (unsigned char *) g_malloc(cdata_bytes, 0);
os16 = (opus_int16 *) data;
// at 48000 we have
// 2.5 ms 480
// 5 ms 960
// 10 ms 1920
// 20 ms 3840
// 40 ms 7680
// 60 ms 11520
cdata_bytes = opus_encode(g_opus_encoder, os16, data_bytes / 4,
cdata, cdata_bytes);
if ((cdata_bytes > 0) && (cdata_bytes < data_bytes))
{
*format_index = g_client_opus_index;
g_memcpy(data, cdata, cdata_bytes);
rv = cdata_bytes;
}
g_free(cdata);
return rv;
}
#else
/*****************************************************************************/
static int
sound_wave_compress(char *data, int data_bytes, int *format_index)
{
return data_bytes;
}
#endif
/*****************************************************************************/
/* send wave message to client */
static int
@ -363,6 +471,7 @@ sound_send_wave_data_chunk(char *data, int data_bytes)
struct stream *s;
int bytes;
int time;
int format_index;
char *size_ptr;
LOG(10, ("sound_send_wave_data_chunk: data_bytes %d", data_bytes));
@ -385,6 +494,10 @@ sound_send_wave_data_chunk(char *data, int data_bytes)
LOG(10, ("sound_send_wave_data_chunk: got room"));
}
/* compress, if available */
format_index = g_current_client_format_index;
data_bytes = sound_wave_compress(data, data_bytes, &format_index);
/* part one of 2 PDU wave info */
LOG(10, ("sound_send_wave_data_chunk: sending %d bytes", data_bytes));
@ -396,7 +509,7 @@ sound_send_wave_data_chunk(char *data, int data_bytes)
out_uint16_le(s, 0); /* size, set later */
time = g_time2();
out_uint16_le(s, time);
out_uint16_le(s, g_current_client_format_index); /* wFormatNo */
out_uint16_le(s, format_index); /* wFormatNo */
g_cBlockNo++;
out_uint8(s, g_cBlockNo);
g_sent_time[g_cBlockNo & 0xff] = time;
@ -445,7 +558,7 @@ sound_send_wave_data(char *data, int data_bytes)
error = 0;
while (data_bytes > 0)
{
space_left = BBUF_SIZE - g_buf_index;
space_left = g_bbuf_size - g_buf_index;
chunk_bytes = MIN(space_left, data_bytes);
if (chunk_bytes < 1)
{
@ -455,10 +568,10 @@ sound_send_wave_data(char *data, int data_bytes)
}
g_memcpy(g_buffer + g_buf_index, data + data_index, chunk_bytes);
g_buf_index += chunk_bytes;
if (g_buf_index >= BBUF_SIZE)
if (g_buf_index >= g_bbuf_size)
{
g_buf_index = 0;
res = sound_send_wave_data_chunk(g_buffer, BBUF_SIZE);
res = sound_send_wave_data_chunk(g_buffer, g_bbuf_size);
if (res == 2)
{
/* don't need to error on this */

Loading…
Cancel
Save