chansrv: added opus audio compression for playback
This commit is contained in:
parent
46215e36d1
commit
2f5b84b712
11
configure.ac
11
configure.ac
@ -69,6 +69,10 @@ AC_ARG_ENABLE(rfxcodec, AS_HELP_STRING([--enable-rfxcodec],
|
|||||||
[Build using librfxcodec (default: no)]),
|
[Build using librfxcodec (default: no)]),
|
||||||
[], [enable_rfxcodec=no])
|
[], [enable_rfxcodec=no])
|
||||||
AM_CONDITIONAL(XRDP_RFXCODEC, [test x$enable_rfxcodec = xyes])
|
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"])
|
AM_CONDITIONAL(GOT_PREFIX, test "x${prefix}" != "xNONE"])
|
||||||
|
|
||||||
@ -122,6 +126,13 @@ then
|
|||||||
[#define _FILE_OFFSET_BITS 64])
|
[#define _FILE_OFFSET_BITS 64])
|
||||||
fi
|
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
|
# checking for TurboJPEG
|
||||||
if test "x$enable_tjpeg" = "xyes"
|
if test "x$enable_tjpeg" = "xyes"
|
||||||
then
|
then
|
||||||
|
@ -22,6 +22,11 @@ EXTRA_DEFINES += -DXRDP_FUSE
|
|||||||
EXTRA_LIBS += -lfuse
|
EXTRA_LIBS += -lfuse
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if XRDP_OPUS
|
||||||
|
EXTRA_DEFINES += -DXRDP_OPUS
|
||||||
|
EXTRA_LIBS += -lopus
|
||||||
|
endif
|
||||||
|
|
||||||
AM_CFLAGS = \
|
AM_CFLAGS = \
|
||||||
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
|
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
|
||||||
-DXRDP_SBIN_PATH=\"${sbindir}\" \
|
-DXRDP_SBIN_PATH=\"${sbindir}\" \
|
||||||
|
@ -30,6 +30,11 @@
|
|||||||
#include "file_loc.h"
|
#include "file_loc.h"
|
||||||
#include "chansrv_common.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_rdpsnd_chan_id; /* in chansrv.c */
|
||||||
extern int g_display_num; /* 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_inp = NULL;
|
||||||
static struct stream *g_stream_incoming_packet = NULL;
|
static struct stream *g_stream_incoming_packet = NULL;
|
||||||
|
|
||||||
#define BBUF_SIZE (1024 * 8)
|
#define MAX_BBUF_SIZE (1024 * 16)
|
||||||
char g_buffer[BBUF_SIZE];
|
static char g_buffer[MAX_BBUF_SIZE];
|
||||||
int g_buf_index = 0;
|
static int g_buf_index = 0;
|
||||||
int g_sent_time[256];
|
static int g_sent_time[256];
|
||||||
int g_sent_flag[256];
|
static int g_sent_flag[256];
|
||||||
|
|
||||||
|
static int g_bbuf_size = 1024 * 8; /* may change later */
|
||||||
|
|
||||||
struct xr_wave_format_ex
|
struct xr_wave_format_ex
|
||||||
{
|
{
|
||||||
@ -96,12 +103,39 @@ static struct xr_wave_format_ex g_pcm_44100 =
|
|||||||
g_pcm_44100_data /* data */
|
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
|
#define SND_NUM_OUTP_FORMATS 2
|
||||||
static struct xr_wave_format_ex *g_wave_outp_formats[SND_NUM_OUTP_FORMATS] =
|
static struct xr_wave_format_ex *g_wave_outp_formats[SND_NUM_OUTP_FORMATS] =
|
||||||
{
|
{
|
||||||
&g_pcm_44100,
|
&g_pcm_44100,
|
||||||
&g_pcm_22050
|
&g_pcm_22050
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int g_client_does_opus = 0;
|
||||||
|
static int g_client_opus_index = 0;
|
||||||
|
|
||||||
/* index into list from client */
|
/* index into list from client */
|
||||||
static int g_current_client_format_index = 0;
|
static int g_current_client_format_index = 0;
|
||||||
@ -302,6 +336,14 @@ sound_process_output_format(int aindex, int wFormatTag, int nChannels,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (wFormatTag == 0x0069)
|
||||||
|
{
|
||||||
|
g_client_does_opus = 1;
|
||||||
|
g_client_opus_index = aindex;
|
||||||
|
g_bbuf_size = 11520;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,6 +397,72 @@ sound_process_output_formats(struct stream *s, int size)
|
|||||||
return 0;
|
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 */
|
/* send wave message to client */
|
||||||
static int
|
static int
|
||||||
@ -363,6 +471,7 @@ sound_send_wave_data_chunk(char *data, int data_bytes)
|
|||||||
struct stream *s;
|
struct stream *s;
|
||||||
int bytes;
|
int bytes;
|
||||||
int time;
|
int time;
|
||||||
|
int format_index;
|
||||||
char *size_ptr;
|
char *size_ptr;
|
||||||
|
|
||||||
LOG(10, ("sound_send_wave_data_chunk: data_bytes %d", data_bytes));
|
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"));
|
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 */
|
/* part one of 2 PDU wave info */
|
||||||
|
|
||||||
LOG(10, ("sound_send_wave_data_chunk: sending %d bytes", data_bytes));
|
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 */
|
out_uint16_le(s, 0); /* size, set later */
|
||||||
time = g_time2();
|
time = g_time2();
|
||||||
out_uint16_le(s, time);
|
out_uint16_le(s, time);
|
||||||
out_uint16_le(s, g_current_client_format_index); /* wFormatNo */
|
out_uint16_le(s, format_index); /* wFormatNo */
|
||||||
g_cBlockNo++;
|
g_cBlockNo++;
|
||||||
out_uint8(s, g_cBlockNo);
|
out_uint8(s, g_cBlockNo);
|
||||||
g_sent_time[g_cBlockNo & 0xff] = time;
|
g_sent_time[g_cBlockNo & 0xff] = time;
|
||||||
@ -445,7 +558,7 @@ sound_send_wave_data(char *data, int data_bytes)
|
|||||||
error = 0;
|
error = 0;
|
||||||
while (data_bytes > 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);
|
chunk_bytes = MIN(space_left, data_bytes);
|
||||||
if (chunk_bytes < 1)
|
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_memcpy(g_buffer + g_buf_index, data + data_index, chunk_bytes);
|
||||||
g_buf_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;
|
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)
|
if (res == 2)
|
||||||
{
|
{
|
||||||
/* don't need to error on this */
|
/* don't need to error on this */
|
||||||
|
Loading…
Reference in New Issue
Block a user