Some fixes for audin redirection (#7231)
* Fixed research for native PCM format * Fixed compatibility detection for resampling * dsp: Makes channel mix and encoding process use separated buffers * Give FramesPerPacket to freerdp_dsp_context_reset function * dsp: Fix DVI_ADPCM codec by respecting the required packet size * Forbid mono channel in macos * Fix audin command line channel option * Disable ADPCM codec as it does not work * Refactor valid native codec research * Native codec research: Try different channels number * Fix dsp channel mix * Fix dsp resample
This commit is contained in:
parent
a7cdd03809
commit
e42696bb2e
@ -416,22 +416,24 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb
|
||||
if (!supported)
|
||||
{
|
||||
/* Default sample rates supported by most backends. */
|
||||
const UINT32 samplerates[] = { 96000, 48000, 44100, 22050 };
|
||||
const UINT32 samplerates[] = { format.nSamplesPerSec, 96000, 48000, 44100, 22050 };
|
||||
BOOL test = FALSE;
|
||||
size_t x;
|
||||
|
||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
format.wBitsPerSample = 16;
|
||||
test = IFCALLRESULT(FALSE, audin->device->FormatSupported, audin->device, &format);
|
||||
if (!test)
|
||||
format.cbSize = 0;
|
||||
for (x = 0; x < ARRAYSIZE(samplerates); x++)
|
||||
{
|
||||
size_t x;
|
||||
for (x = 0; x < ARRAYSIZE(samplerates); x++)
|
||||
{
|
||||
format.nSamplesPerSec = samplerates[x];
|
||||
test = IFCALLRESULT(FALSE, audin->device->FormatSupported, audin->device, &format);
|
||||
if (test)
|
||||
break;
|
||||
}
|
||||
format.nSamplesPerSec = samplerates[x];
|
||||
format.nChannels = audin->format->nChannels;
|
||||
test = IFCALLRESULT(FALSE, audin->device->FormatSupported, audin->device, &format);
|
||||
if (test)
|
||||
break;
|
||||
format.nChannels = 3 - format.nChannels;
|
||||
test = IFCALLRESULT(FALSE, audin->device->FormatSupported, audin->device, &format);
|
||||
if (test)
|
||||
break;
|
||||
}
|
||||
if (!test)
|
||||
return FALSE;
|
||||
@ -447,7 +449,7 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb
|
||||
|
||||
if (!supported)
|
||||
{
|
||||
if (!freerdp_dsp_context_reset(audin->dsp_context, audin->format))
|
||||
if (!freerdp_dsp_context_reset(audin->dsp_context, audin->format, audin->FramesPerPacket))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -943,7 +945,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, const ADDIN_ARGV* args)
|
||||
{
|
||||
unsigned long val = strtoul(arg->Value, NULL, 0);
|
||||
|
||||
if ((errno != 0) || (val > UINT16_MAX))
|
||||
if ((errno != 0) || (val < UINT16_MAX))
|
||||
audin->fixed_format->nChannels = val;
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
|
@ -120,6 +120,9 @@ static BOOL audin_mac_format_supported(IAudinDevice *device, const AUDIO_FORMAT
|
||||
if (device == NULL || format == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (format->nChannels != 2)
|
||||
return FALSE;
|
||||
|
||||
req_fmt = audin_mac_get_format(format);
|
||||
|
||||
if (req_fmt == 0)
|
||||
|
@ -86,7 +86,7 @@ static UINT audin_server_select_format(audin_server_context* context, size_t cli
|
||||
context->selected_client_format = (SSIZE_T)client_format_index;
|
||||
|
||||
if (!freerdp_dsp_context_reset(audin->dsp_context,
|
||||
&audin->context.client_formats[client_format_index]))
|
||||
&audin->context.client_formats[client_format_index], 0u))
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to reset dsp context format!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
@ -237,6 +237,9 @@ static BOOL rdpsnd_mac_format_supported(rdpsndDevicePlugin *device, const AUDIO_
|
||||
case WAVE_FORMAT_PCM:
|
||||
if (format->wBitsPerSample != 16)
|
||||
return FALSE;
|
||||
|
||||
if (format->nChannels != 2)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
|
@ -407,7 +407,7 @@ static BOOL rdpsnd_ensure_device_is_open(rdpsndPlugin* rdpsnd, UINT32 wFormatNo,
|
||||
|
||||
if (!supported)
|
||||
{
|
||||
if (!freerdp_dsp_context_reset(rdpsnd->dsp_context, format))
|
||||
if (!freerdp_dsp_context_reset(rdpsnd->dsp_context, format, 0u))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -365,7 +365,7 @@ static UINT rdpsnd_server_select_format(RdpsndServerContext* context, UINT16 cli
|
||||
context->priv->out_buffer_size = out_buffer_size;
|
||||
}
|
||||
|
||||
freerdp_dsp_context_reset(context->priv->dsp_context, format);
|
||||
freerdp_dsp_context_reset(context->priv->dsp_context, format, 0u);
|
||||
out:
|
||||
LeaveCriticalSection(&context->priv->lock);
|
||||
return error;
|
||||
|
@ -40,7 +40,8 @@ extern "C"
|
||||
const BYTE* data, size_t length, wStream* out);
|
||||
FREERDP_API void freerdp_dsp_context_free(FREERDP_DSP_CONTEXT* context);
|
||||
FREERDP_API BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* context,
|
||||
const AUDIO_FORMAT* targetFormat);
|
||||
const AUDIO_FORMAT* targetFormat,
|
||||
UINT32 FramesPerPacket);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -64,6 +64,7 @@
|
||||
union _ADPCM {
|
||||
struct
|
||||
{
|
||||
size_t packet_size;
|
||||
INT16 last_sample[2];
|
||||
INT16 last_step[2];
|
||||
} ima;
|
||||
@ -84,8 +85,9 @@ struct _FREERDP_DSP_CONTEXT
|
||||
ADPCM adpcm;
|
||||
AUDIO_FORMAT format;
|
||||
|
||||
wStream* buffer;
|
||||
wStream* channelmix;
|
||||
wStream* resample;
|
||||
wStream* buffer;
|
||||
|
||||
#if defined(WITH_GSM)
|
||||
gsm gsm;
|
||||
@ -136,7 +138,7 @@ static BOOL freerdp_dsp_channel_mix(FREERDP_DSP_CONTEXT* context, const BYTE* sr
|
||||
return FALSE;
|
||||
|
||||
bpp = srcFormat->wBitsPerSample > 8 ? 2 : 1;
|
||||
samples = size / bpp;
|
||||
samples = size / bpp / srcFormat->nChannels;
|
||||
|
||||
if (context->format.nChannels == srcFormat->nChannels)
|
||||
{
|
||||
@ -145,7 +147,7 @@ static BOOL freerdp_dsp_channel_mix(FREERDP_DSP_CONTEXT* context, const BYTE* sr
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Stream_SetPosition(context->buffer, 0);
|
||||
Stream_SetPosition(context->channelmix, 0);
|
||||
|
||||
/* Destination has more channels than source */
|
||||
if (context->format.nChannels > srcFormat->nChannels)
|
||||
@ -153,21 +155,21 @@ static BOOL freerdp_dsp_channel_mix(FREERDP_DSP_CONTEXT* context, const BYTE* sr
|
||||
switch (srcFormat->nChannels)
|
||||
{
|
||||
case 1:
|
||||
if (!Stream_EnsureCapacity(context->buffer, size * 2))
|
||||
if (!Stream_EnsureCapacity(context->channelmix, size * 2))
|
||||
return FALSE;
|
||||
|
||||
for (x = 0; x < samples; x++)
|
||||
{
|
||||
for (y = 0; y < bpp; y++)
|
||||
Stream_Write_UINT8(context->buffer, src[x * bpp + y]);
|
||||
Stream_Write_UINT8(context->channelmix, src[x * bpp + y]);
|
||||
|
||||
for (y = 0; y < bpp; y++)
|
||||
Stream_Write_UINT8(context->buffer, src[x * bpp + y]);
|
||||
Stream_Write_UINT8(context->channelmix, src[x * bpp + y]);
|
||||
}
|
||||
|
||||
Stream_SealLength(context->buffer);
|
||||
*data = Stream_Buffer(context->buffer);
|
||||
*length = Stream_Length(context->buffer);
|
||||
Stream_SealLength(context->channelmix);
|
||||
*data = Stream_Buffer(context->channelmix);
|
||||
*length = Stream_Length(context->channelmix);
|
||||
return TRUE;
|
||||
|
||||
case 2: /* We only support stereo, so we can not handle this case. */
|
||||
@ -180,7 +182,7 @@ static BOOL freerdp_dsp_channel_mix(FREERDP_DSP_CONTEXT* context, const BYTE* sr
|
||||
switch (srcFormat->nChannels)
|
||||
{
|
||||
case 2:
|
||||
if (!Stream_EnsureCapacity(context->buffer, size / 2))
|
||||
if (!Stream_EnsureCapacity(context->channelmix, size / 2))
|
||||
return FALSE;
|
||||
|
||||
/* Simply drop second channel.
|
||||
@ -188,12 +190,12 @@ static BOOL freerdp_dsp_channel_mix(FREERDP_DSP_CONTEXT* context, const BYTE* sr
|
||||
for (x = 0; x < samples; x++)
|
||||
{
|
||||
for (y = 0; y < bpp; y++)
|
||||
Stream_Write_UINT8(context->buffer, src[2 * x * bpp + y]);
|
||||
Stream_Write_UINT8(context->channelmix, src[2 * x * bpp + y]);
|
||||
}
|
||||
|
||||
Stream_SealLength(context->buffer);
|
||||
*data = Stream_Buffer(context->buffer);
|
||||
*length = Stream_Length(context->buffer);
|
||||
Stream_SealLength(context->channelmix);
|
||||
*data = Stream_Buffer(context->channelmix);
|
||||
*length = Stream_Length(context->channelmix);
|
||||
return TRUE;
|
||||
|
||||
case 1: /* Invalid, do we want to use a 0 channel sound? */
|
||||
@ -238,9 +240,14 @@ static BOOL freerdp_dsp_resample(FREERDP_DSP_CONTEXT* context, const BYTE* src,
|
||||
/* We want to ignore differences of source and destination format. */
|
||||
format = *srcFormat;
|
||||
format.wFormatTag = WAVE_FORMAT_UNKNOWN;
|
||||
format.wBitsPerSample = 0;
|
||||
|
||||
if (audio_format_compatible(&format, &context->format))
|
||||
{
|
||||
*data = src;
|
||||
*length = size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined(WITH_SOXR)
|
||||
sbytes = srcChannels * srcBytesPerFrame;
|
||||
@ -261,10 +268,6 @@ static BOOL freerdp_dsp_resample(FREERDP_DSP_CONTEXT* context, const BYTE* src,
|
||||
*length = Stream_Length(context->resample);
|
||||
return (error == 0) ? TRUE : FALSE;
|
||||
#else
|
||||
WINPR_UNUSED(src);
|
||||
WINPR_UNUSED(size);
|
||||
WINPR_UNUSED(data);
|
||||
WINPR_UNUSED(length);
|
||||
WLog_ERR(TAG, "Missing resample support, recompile -DWITH_SOXR=ON or -DWITH_DSP_FFMPEG=ON");
|
||||
return FALSE;
|
||||
#endif
|
||||
@ -720,10 +723,11 @@ static BOOL freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* context, const BYT
|
||||
if (!Stream_EnsureRemainingCapacity(out, size))
|
||||
return FALSE;
|
||||
|
||||
start = dst = Stream_Pointer(out);
|
||||
start = Stream_Buffer(context->buffer);
|
||||
dst = Stream_Pointer(context->buffer);
|
||||
align = (context->format.nChannels > 1) ? 32 : 4;
|
||||
|
||||
while (size > align)
|
||||
while (size >= align)
|
||||
{
|
||||
if ((dst - start) % context->format.nBlockAlign == 0)
|
||||
{
|
||||
@ -768,9 +772,15 @@ static BOOL freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* context, const BYT
|
||||
*dst++ = encoded;
|
||||
size -= 4;
|
||||
}
|
||||
|
||||
if (dst - start == context->adpcm.ima.packet_size)
|
||||
{
|
||||
Stream_Write(out, start, context->adpcm.ima.packet_size);
|
||||
dst = Stream_Buffer(context->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
Stream_SetPointer(out, dst);
|
||||
Stream_SetPointer(context->buffer, dst);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1025,9 +1035,9 @@ FREERDP_DSP_CONTEXT* freerdp_dsp_context_new(BOOL encoder)
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
||||
context->buffer = Stream_New(NULL, 4096);
|
||||
context->channelmix = Stream_New(NULL, 4096);
|
||||
|
||||
if (!context->buffer)
|
||||
if (!context->channelmix)
|
||||
goto fail;
|
||||
|
||||
context->resample = Stream_New(NULL, 4096);
|
||||
@ -1035,6 +1045,11 @@ FREERDP_DSP_CONTEXT* freerdp_dsp_context_new(BOOL encoder)
|
||||
if (!context->resample)
|
||||
goto fail;
|
||||
|
||||
context->buffer = Stream_New(NULL, 4096);
|
||||
|
||||
if (!context->buffer)
|
||||
goto fail;
|
||||
|
||||
context->encoder = encoder;
|
||||
#if defined(WITH_GSM)
|
||||
context->gsm = gsm_create();
|
||||
@ -1095,8 +1110,9 @@ void freerdp_dsp_context_free(FREERDP_DSP_CONTEXT* context)
|
||||
|
||||
if (context)
|
||||
{
|
||||
Stream_Free(context->buffer, TRUE);
|
||||
Stream_Free(context->channelmix, TRUE);
|
||||
Stream_Free(context->resample, TRUE);
|
||||
Stream_Free(context->buffer, TRUE);
|
||||
#if defined(WITH_GSM)
|
||||
gsm_destroy(context->gsm);
|
||||
#endif
|
||||
@ -1254,6 +1270,7 @@ BOOL freerdp_dsp_supports_format(const AUDIO_FORMAT* format, BOOL encode)
|
||||
#if defined(WITH_DSP_EXPERIMENTAL)
|
||||
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
return FALSE;
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
return TRUE;
|
||||
#endif
|
||||
@ -1297,7 +1314,8 @@ BOOL freerdp_dsp_supports_format(const AUDIO_FORMAT* format, BOOL encode)
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT* targetFormat)
|
||||
BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT* targetFormat,
|
||||
UINT32 FramesPerPacket)
|
||||
{
|
||||
#if defined(WITH_DSP_FFMPEG)
|
||||
return freerdp_dsp_ffmpeg_context_reset(context, targetFormat);
|
||||
@ -1307,6 +1325,22 @@ BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT*
|
||||
return FALSE;
|
||||
|
||||
context->format = *targetFormat;
|
||||
|
||||
if (context->format.wFormatTag == WAVE_FORMAT_DVI_ADPCM)
|
||||
{
|
||||
size_t min_frame_data =
|
||||
context->format.wBitsPerSample * context->format.nChannels * FramesPerPacket * 1ULL;
|
||||
size_t data_per_block = (context->format.nBlockAlign - 4 * context->format.nChannels) * 8;
|
||||
size_t nb_block_per_packet = min_frame_data / data_per_block;
|
||||
|
||||
if (min_frame_data % data_per_block)
|
||||
nb_block_per_packet++;
|
||||
|
||||
context->adpcm.ima.packet_size = nb_block_per_packet * context->format.nBlockAlign;
|
||||
Stream_EnsureCapacity(context->buffer, context->adpcm.ima.packet_size);
|
||||
Stream_SetPosition(context->buffer, 0);
|
||||
}
|
||||
|
||||
#if defined(WITH_FAAD2)
|
||||
context->faadSetup = FALSE;
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user