chansrv: sound, add aac

This commit is contained in:
Jay Sorg 2017-07-27 22:02:04 -07:00 committed by jsorg71
parent 8ac35d7ed1
commit bf0d56c314
4 changed files with 258 additions and 2 deletions

View File

@ -401,6 +401,7 @@
#define WAVE_FORMAT_MULAW 0x0007
#define WAVE_FORMAT_MPEGLAYER3 0x0055
#define WAVE_FORMAT_OPUS 0x0069
#define WAVE_FORMAT_AAC_MS 0xA106
/* Virtual channel options */
#define XR_CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000

View File

@ -116,6 +116,10 @@ AC_ARG_ENABLE(xrdpvr, AS_HELP_STRING([--enable-xrdpvr],
[Build xrdpvr module (default: no)]),
[], [enable_xrdpvr=no])
AM_CONDITIONAL(XRDP_XRDPVR, [test x$enable_xrdpvr = xyes])
AC_ARG_ENABLE(fdkaac, AS_HELP_STRING([--enable-fdkaac],
[Build aac(audio codec) (default: no)]),
[], [enable_fdkaac=no])
AM_CONDITIONAL(XRDP_FDK_AAC, [test x$enable_fdkaac = xyes])
AC_ARG_ENABLE(opus, AS_HELP_STRING([--enable-opus],
[Build opus(audio codec) (default: no)]),
[], [enable_opus=no])
@ -230,6 +234,13 @@ then
[AC_MSG_ERROR([please install libfuse-dev or fuse-devel])])
fi
# checking for fdk aac
if test "x$enable_fdkaac" = "xyes"
then
AC_CHECK_HEADER([fdk-aac/aacenc_lib.h], [],
[AC_MSG_ERROR([please install libfdk-aac-dev or dontknow-devel])])
fi
# checking for opus
if test "x$enable_opus" = "xyes"
then

View File

@ -23,6 +23,11 @@ AM_CPPFLAGS += -DXRDP_FUSE $(FUSE_CFLAGS)
CHANSRV_EXTRA_LIBS += $(FUSE_LIBS)
endif
if XRDP_FDK_AAC
AM_CPPFLAGS += -DXRDP_FDK_AAC
CHANSRV_EXTRA_LIBS += -lfdk-aac
endif
if XRDP_OPUS
AM_CPPFLAGS += -DXRDP_OPUS
CHANSRV_EXTRA_LIBS += -lopus

View File

@ -35,6 +35,11 @@
#include "xrdp_sockets.h"
#include "chansrv_common.h"
#if defined(XRDP_FDK_AAC)
#include <fdk-aac/aacenc_lib.h>
static HANDLE_AACENCODER g_fdk_aac_encoder = 0;
#endif
#if defined(XRDP_OPUS)
#include <opus/opus.h>
static OpusEncoder *g_opus_encoder = 0;
@ -114,6 +119,21 @@ static struct xr_wave_format_ex g_pcm_44100 =
g_pcm_44100_data /* data */
};
#if defined(XRDP_FDK_AAC)
static tui8 g_fdk_aac_44100_data[] = { 0 };
static struct xr_wave_format_ex g_fdk_aac_44100 =
{
WAVE_FORMAT_AAC_MS, /* wFormatTag */
2, /* num of channels */
44100, /* samples per sec */
12000, /* avg bytes per sec */
4, /* block align */
16, /* bits per sample */
0, /* data size */
g_fdk_aac_44100_data /* data */
};
#endif
#if defined(XRDP_OPUS)
static tui8 g_opus_44100_data[] = { 0 };
static struct xr_wave_format_ex g_opus_44100 =
@ -148,6 +168,9 @@ static struct xr_wave_format_ex *g_wave_outp_formats[] =
{
&g_pcm_44100,
&g_pcm_22050,
#if defined(XRDP_FDK_AAC)
&g_fdk_aac_44100,
#endif
#if defined(XRDP_OPUS)
&g_opus_44100,
#endif
@ -157,6 +180,9 @@ static struct xr_wave_format_ex *g_wave_outp_formats[] =
0
};
static int g_client_does_fdk_aac = 0;
static int g_client_fdk_aac_index = 0;
static int g_client_does_opus = 0;
static int g_client_opus_index = 0;
@ -187,7 +213,7 @@ static struct xr_wave_format_ex g_pcm_inp_22050 =
static tui8 g_pcm_inp_44100_data[] = { 0 };
static struct xr_wave_format_ex g_pcm_inp_44100 =
{
1, /* wFormatTag */
WAVE_FORMAT_PCM, /* wFormatTag */
2, /* num of channels */
44100, /* samples per sec */
176400, /* avg bytes per sec */
@ -370,6 +396,12 @@ sound_process_output_format(int aindex, int wFormatTag, int nChannels,
switch(wFormatTag)
{
case WAVE_FORMAT_AAC_MS:
LOG(0, ("wFormatTag, fdk aac"));
g_client_does_fdk_aac = 1;
g_client_fdk_aac_index = aindex;
g_bbuf_size = 4096;
break;
case WAVE_FORMAT_MPEGLAYER3:
LOG(0, ("wFormatTag, mp3"));
g_client_does_mp3lame = 1;
@ -437,6 +469,206 @@ sound_process_output_formats(struct stream *s, int size)
return 0;
}
#if defined(XRDP_FDK_AAC)
/*****************************************************************************/
static int
sound_wave_compress_fdk_aac(char *data, int data_bytes, int *format_index)
{
int rv;
int cdata_bytes;
char *cdata;
AACENC_ERROR error;
int aot;
int sample_rate;
int mode;
int bitrate;
int afterburner;
int channel_order;
AACENC_InfoStruct info = { 0 };
AACENC_BufDesc in_buf = { 0 };
AACENC_BufDesc out_buf = { 0 };
AACENC_InArgs in_args = { 0 };
AACENC_OutArgs out_args = { 0 };
void *in_buffer[1];
int in_identifier[1];
int in_size[1];
int in_elem_size[1];
void *out_buffer[1];
int out_identifier[1];
int out_size[1];
int out_elem_size[1];
rv = data_bytes;
if (g_client_does_fdk_aac == 0)
{
return rv;
}
if (g_fdk_aac_encoder == 0)
{
/* init fdk aac encoder */
LOG(0, ("sound_wave_compress_fdk_aac: using fdk aac"));
error = aacEncOpen(&g_fdk_aac_encoder, 0, 2);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncOpen() failed"));
return rv;
}
aot = 2; /* MPEG-4 AAC Low Complexity. */
//aot = 129; /* MPEG-2 AAC Low Complexity. */
error = aacEncoder_SetParam(g_fdk_aac_encoder, AACENC_AOT, aot);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncoder_SetParam() "
"AACENC_AOT failed"));
}
sample_rate = g_fdk_aac_44100.nSamplesPerSec;
error = aacEncoder_SetParam(g_fdk_aac_encoder, AACENC_SAMPLERATE,
sample_rate);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncoder_SetParam() "
"AACENC_SAMPLERATE failed"));
}
mode = MODE_2;
error = aacEncoder_SetParam(g_fdk_aac_encoder,
AACENC_CHANNELMODE, mode);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncoder_SetParam() "
"AACENC_CHANNELMODE failed"));
}
channel_order = 1; /* WAVE file format channel ordering */
error = aacEncoder_SetParam(g_fdk_aac_encoder, AACENC_CHANNELORDER,
channel_order);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncoder_SetParam() "
"AACENC_CHANNELORDER failed"));
}
/* bytes rate to bit rate */
bitrate = g_fdk_aac_44100.nAvgBytesPerSec * 8;
error = aacEncoder_SetParam(g_fdk_aac_encoder, AACENC_BITRATE,
bitrate);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncoder_SetParam() "
"AACENC_BITRATE failed"));
}
error = aacEncoder_SetParam(g_fdk_aac_encoder, AACENC_TRANSMUX, 0);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncoder_SetParam() "
"AACENC_TRANSMUX failed"));
}
afterburner = 1;
error = aacEncoder_SetParam(g_fdk_aac_encoder, AACENC_AFTERBURNER,
afterburner);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncoder_SetParam() "
"AACENC_AFTERBURNER failed"));
}
error = aacEncEncode(g_fdk_aac_encoder, NULL, NULL, NULL, NULL);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: Unable to initialize "
"the encoder"));
}
error = aacEncInfo(g_fdk_aac_encoder, &info);
if (error != AACENC_OK)
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncInfo failed"));
}
LOG(0, ("sound_wave_compress_fdk_aac:"));
LOG(0, (" AACENC_InfoStruct"));
LOG(0, (" maxOutBufBytes %d", info.maxOutBufBytes));
LOG(0, (" maxAncBytes %d", info.maxAncBytes));
LOG(0, (" inBufFillLevel %d", info.inBufFillLevel));
LOG(0, (" inputChannels %d", info.inputChannels));
LOG(0, (" frameLength %d", info.frameLength));
LOG(0, (" encoderDelay %d", info.encoderDelay));
LOG(0, (" confBuf"));
LOG(0, (" confSize %d", info.confSize));
}
rv = data_bytes;
cdata_bytes = data_bytes;
cdata = (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;
}
in_buffer[0] = data;
in_identifier[0] = IN_AUDIO_DATA;
in_size[0] = data_bytes;
in_elem_size[0] = 2;
in_args.numInSamples = data_bytes / 2;
in_buf.numBufs = 1;
in_buf.bufs = in_buffer;
in_buf.bufferIdentifiers = in_identifier;
in_buf.bufSizes = in_size;
in_buf.bufElSizes = in_elem_size;
out_buffer[0] = cdata;
out_identifier[0] = OUT_BITSTREAM_DATA;
out_size[0] = cdata_bytes;
out_elem_size[0] = 1;
out_buf.numBufs = 1;
out_buf.bufs = out_buffer;
out_buf.bufferIdentifiers = out_identifier;
out_buf.bufSizes = out_size;
out_buf.bufElSizes = out_elem_size;
error = aacEncEncode(g_fdk_aac_encoder, &in_buf, &out_buf,
&in_args, &out_args);
if (error == AACENC_OK)
{
cdata_bytes = out_args.numOutBytes;
LOG(10, ("sound_wave_compress_fdk_aac: aacEncEncode ok "
"cdata_bytes %d", cdata_bytes));
*format_index = g_client_fdk_aac_index;
g_memcpy(data, cdata, cdata_bytes);
rv = cdata_bytes;
}
else
{
LOG(0, ("sound_wave_compress_fdk_aac: aacEncEncode failed"));
}
g_free(cdata);
return rv;
}
#else
/*****************************************************************************/
static int
sound_wave_compress_fdk_aac(char *data, int data_bytes, int *format_index)
{
return data_bytes;
}
#endif
#if defined(XRDP_OPUS)
/*****************************************************************************/
@ -602,7 +834,11 @@ sound_wave_compress_mp3lame(char *data, int data_bytes, int *format_index)
static int
sound_wave_compress(char *data, int data_bytes, int *format_index)
{
if (g_client_does_opus)
if (g_client_does_fdk_aac)
{
return sound_wave_compress_fdk_aac(data, data_bytes, format_index);
}
else if (g_client_does_opus)
{
return sound_wave_compress_opus(data, data_bytes, format_index);
}
@ -982,6 +1218,9 @@ sound_init(void)
/* save data from sound_server_source */
fifo_init(&g_in_fifo, 100);
g_client_does_fdk_aac = 0;
g_client_fdk_aac_index = 0;
g_client_does_opus = 0;
g_client_opus_index = 0;