|
|
@ -35,6 +35,11 @@
|
|
|
|
#include "xrdp_sockets.h"
|
|
|
|
#include "xrdp_sockets.h"
|
|
|
|
#include "chansrv_common.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)
|
|
|
|
#if defined(XRDP_OPUS)
|
|
|
|
#include <opus/opus.h>
|
|
|
|
#include <opus/opus.h>
|
|
|
|
static OpusEncoder *g_opus_encoder = 0;
|
|
|
|
static OpusEncoder *g_opus_encoder = 0;
|
|
|
@ -114,6 +119,21 @@ static struct xr_wave_format_ex g_pcm_44100 =
|
|
|
|
g_pcm_44100_data /* data */
|
|
|
|
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)
|
|
|
|
#if defined(XRDP_OPUS)
|
|
|
|
static tui8 g_opus_44100_data[] = { 0 };
|
|
|
|
static tui8 g_opus_44100_data[] = { 0 };
|
|
|
|
static struct xr_wave_format_ex g_opus_44100 =
|
|
|
|
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_44100,
|
|
|
|
&g_pcm_22050,
|
|
|
|
&g_pcm_22050,
|
|
|
|
|
|
|
|
#if defined(XRDP_FDK_AAC)
|
|
|
|
|
|
|
|
&g_fdk_aac_44100,
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#if defined(XRDP_OPUS)
|
|
|
|
#if defined(XRDP_OPUS)
|
|
|
|
&g_opus_44100,
|
|
|
|
&g_opus_44100,
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
@ -157,6 +180,9 @@ static struct xr_wave_format_ex *g_wave_outp_formats[] =
|
|
|
|
0
|
|
|
|
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_does_opus = 0;
|
|
|
|
static int g_client_opus_index = 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 tui8 g_pcm_inp_44100_data[] = { 0 };
|
|
|
|
static struct xr_wave_format_ex g_pcm_inp_44100 =
|
|
|
|
static struct xr_wave_format_ex g_pcm_inp_44100 =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
1, /* wFormatTag */
|
|
|
|
WAVE_FORMAT_PCM, /* wFormatTag */
|
|
|
|
2, /* num of channels */
|
|
|
|
2, /* num of channels */
|
|
|
|
44100, /* samples per sec */
|
|
|
|
44100, /* samples per sec */
|
|
|
|
176400, /* avg bytes per sec */
|
|
|
|
176400, /* avg bytes per sec */
|
|
|
@ -370,6 +396,12 @@ sound_process_output_format(int aindex, int wFormatTag, int nChannels,
|
|
|
|
|
|
|
|
|
|
|
|
switch(wFormatTag)
|
|
|
|
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:
|
|
|
|
case WAVE_FORMAT_MPEGLAYER3:
|
|
|
|
LOG(0, ("wFormatTag, mp3"));
|
|
|
|
LOG(0, ("wFormatTag, mp3"));
|
|
|
|
g_client_does_mp3lame = 1;
|
|
|
|
g_client_does_mp3lame = 1;
|
|
|
@ -437,6 +469,206 @@ sound_process_output_formats(struct stream *s, int size)
|
|
|
|
return 0;
|
|
|
|
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)
|
|
|
|
#if defined(XRDP_OPUS)
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
|
@ -602,7 +834,11 @@ sound_wave_compress_mp3lame(char *data, int data_bytes, int *format_index)
|
|
|
|
static int
|
|
|
|
static int
|
|
|
|
sound_wave_compress(char *data, int data_bytes, int *format_index)
|
|
|
|
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);
|
|
|
|
return sound_wave_compress_opus(data, data_bytes, format_index);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -982,6 +1218,9 @@ sound_init(void)
|
|
|
|
/* save data from sound_server_source */
|
|
|
|
/* save data from sound_server_source */
|
|
|
|
fifo_init(&g_in_fifo, 100);
|
|
|
|
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_does_opus = 0;
|
|
|
|
g_client_opus_index = 0;
|
|
|
|
g_client_opus_index = 0;
|
|
|
|
|
|
|
|
|
|
|
|