Merge pull request #4758 from akallabeth/dsp_fix

Audio/microphone fixes
This commit is contained in:
MartinHaimberger 2018-07-31 10:22:22 +02:00 committed by GitHub
commit 2d7499b7c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 362 additions and 244 deletions

View File

@ -31,6 +31,7 @@
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/cmdline.h>
#include <winpr/wlog.h>
#include <alsa/asoundlib.h>
@ -54,6 +55,8 @@ typedef struct _AudinALSADevice
void* user_data;
rdpContext* rdpcontext;
wLog* log;
int bytes_per_frame;
} AudinALSADevice;
static snd_pcm_format_t audin_alsa_format(UINT32 wFormatTag, UINT32 bitPerChannel)
@ -94,8 +97,8 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa,
if ((error = snd_pcm_hw_params_malloc(&hw_params)) < 0)
{
WLog_ERR(TAG, "snd_pcm_hw_params_malloc (%s)",
snd_strerror(error));
WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_hw_params_malloc (%s)",
snd_strerror(error));
return FALSE;
}
@ -111,6 +114,7 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa,
snd_pcm_hw_params_free(hw_params);
snd_pcm_prepare(capture_handle);
alsa->aformat.nChannels = channels;
alsa->bytes_per_frame = snd_pcm_format_size(format, 1) * channels;
return TRUE;
}
@ -120,47 +124,51 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg)
BYTE* buffer;
snd_pcm_t* capture_handle = NULL;
AudinALSADevice* alsa = (AudinALSADevice*) arg;
const size_t rbytes_per_frame = alsa->aformat.nChannels * 4;
DWORD status;
DEBUG_DVC("in");
buffer = (BYTE*) calloc(alsa->frames_per_packet, rbytes_per_frame);
if (!buffer)
{
WLog_ERR(TAG, "calloc failed!");
error = CHANNEL_RC_NO_MEMORY;
goto out;
}
WLog_Print(alsa->log, WLOG_DEBUG, "in");
if ((error = snd_pcm_open(&capture_handle, alsa->device_name,
SND_PCM_STREAM_CAPTURE, 0)) < 0)
{
WLog_ERR(TAG, "snd_pcm_open (%s)", snd_strerror(error));
WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_open (%s)", snd_strerror(error));
error = CHANNEL_RC_INITIALIZATION_ERROR;
goto out;
}
if (!audin_alsa_set_params(alsa, capture_handle))
{
WLog_ERR(TAG, "audin_alsa_set_params failed");
WLog_Print(alsa->log, WLOG_ERROR, "audin_alsa_set_params failed");
goto out;
}
buffer = (BYTE*) calloc(alsa->frames_per_packet + alsa->aformat.nBlockAlign, alsa->bytes_per_frame);
if (!buffer)
{
WLog_Print(alsa->log, WLOG_ERROR, "calloc failed!");
error = CHANNEL_RC_NO_MEMORY;
goto out;
}
while (1)
{
size_t frames = alsa->frames_per_packet;
status = WaitForSingleObject(alsa->stopEvent, 0);
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %ld!", error);
WLog_Print(alsa->log, WLOG_ERROR, "WaitForSingleObject failed with error %ld!", error);
break;
}
if (status == WAIT_OBJECT_0)
break;
error = snd_pcm_readi(capture_handle, buffer, alsa->frames_per_packet);
error = snd_pcm_readi(capture_handle, buffer, frames);
if (error == 0)
continue;
if (error == -EPIPE)
{
@ -169,16 +177,16 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg)
}
else if (error < 0)
{
WLog_ERR(TAG, "snd_pcm_readi (%s)", snd_strerror(error));
WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_readi (%s)", snd_strerror(error));
break;
}
error = alsa->receive(&alsa->aformat,
buffer, error, alsa->user_data);
buffer, error * alsa->bytes_per_frame, alsa->user_data);
if (error)
{
WLog_ERR(TAG, "audin_alsa_thread_receive failed with error %ld", error);
WLog_Print(alsa->log, WLOG_ERROR, "audin_alsa_thread_receive failed with error %ld", error);
break;
}
}
@ -189,7 +197,7 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg)
snd_pcm_close(capture_handle);
out:
DEBUG_DVC("out");
WLog_Print(alsa->log, WLOG_DEBUG, "out");
if (error && alsa->rdpcontext)
setChannelError(alsa->rdpcontext, error,
@ -207,7 +215,10 @@ out:
static UINT audin_alsa_free(IAudinDevice* device)
{
AudinALSADevice* alsa = (AudinALSADevice*) device;
free(alsa->device_name);
if (alsa)
free(alsa->device_name);
free(alsa);
return CHANNEL_RC_OK;
}
@ -215,6 +226,9 @@ static UINT audin_alsa_free(IAudinDevice* device)
static BOOL audin_alsa_format_supported(IAudinDevice* device,
const AUDIO_FORMAT* format)
{
if (!device || !format)
return FALSE;
switch (format->wFormatTag)
{
case WAVE_FORMAT_PCM:
@ -248,6 +262,10 @@ static UINT audin_alsa_set_format(IAudinDevice* device, const AUDIO_FORMAT* form
UINT32 FramesPerPacket)
{
AudinALSADevice* alsa = (AudinALSADevice*) device;
if (!alsa || !format)
return ERROR_INVALID_PARAMETER;
alsa->aformat = *format;
alsa->frames_per_packet = FramesPerPacket;
@ -266,19 +284,23 @@ static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive,
void* user_data)
{
AudinALSADevice* alsa = (AudinALSADevice*) device;
if (!device || !receive || !user_data)
return ERROR_INVALID_PARAMETER;
alsa->receive = receive;
alsa->user_data = user_data;
if (!(alsa->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
WLog_Print(alsa->log, WLOG_ERROR, "CreateEvent failed!");
goto error_out;
}
if (!(alsa->thread = CreateThread(NULL, 0,
audin_alsa_thread_func, alsa, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
WLog_Print(alsa->log, WLOG_ERROR, "CreateThread failed!");
goto error_out;
}
@ -299,6 +321,9 @@ static UINT audin_alsa_close(IAudinDevice* device)
UINT error = CHANNEL_RC_OK;
AudinALSADevice* alsa = (AudinALSADevice*) device;
if (!alsa)
return ERROR_INVALID_PARAMETER;
if (alsa->stopEvent)
{
SetEvent(alsa->stopEvent);
@ -306,7 +331,7 @@ static UINT audin_alsa_close(IAudinDevice* device)
if (WaitForSingleObject(alsa->thread, INFINITE) == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error);
WLog_Print(alsa->log, WLOG_ERROR, "WaitForSingleObject failed with error %"PRIu32"", error);
return error;
}
@ -361,7 +386,7 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device,
if (!alsa->device_name)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(alsa->log, WLOG_ERROR, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY;
}
}
@ -397,6 +422,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS
return CHANNEL_RC_NO_MEMORY;
}
alsa->log = WLog_Get(TAG);
alsa->iface.Open = audin_alsa_open;
alsa->iface.FormatSupported = audin_alsa_format_supported;
alsa->iface.SetFormat = audin_alsa_set_format;
@ -407,7 +433,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS
if ((error = audin_alsa_parse_addin_args(alsa, args)))
{
WLog_ERR(TAG, "audin_alsa_parse_addin_args failed with errorcode %"PRIu32"!", error);
WLog_Print(alsa->log, WLOG_ERROR, "audin_alsa_parse_addin_args failed with errorcode %"PRIu32"!",
error);
goto error_out;
}
@ -417,7 +444,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS
if (!alsa->device_name)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(alsa->log, WLOG_ERROR, "_strdup failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
@ -432,7 +459,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin,
(IAudinDevice*) alsa)))
{
WLog_ERR(TAG, "RegisterAudinDevice failed with error %"PRIu32"!", error);
WLog_Print(alsa->log, WLOG_ERROR, "RegisterAudinDevice failed with error %"PRIu32"!", error);
goto error_out;
}

View File

@ -32,6 +32,7 @@
#include <winpr/crt.h>
#include <winpr/cmdline.h>
#include <winpr/wlog.h>
#include <freerdp/addin.h>
@ -100,6 +101,7 @@ struct _AUDIN_PLUGIN
UINT32 FramesPerPacket;
FREERDP_DSP_CONTEXT* dsp_context;
wLog* log;
};
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
@ -132,23 +134,23 @@ static UINT audin_channel_write_and_free(AUDIN_CHANNEL_CALLBACK* callback, wStre
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
static UINT audin_process_version(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
{
wStream* out;
const UINT32 ClientVersion = 0x01;
UINT32 ServerVersion;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, ServerVersion);
DEBUG_DVC("ServerVersion=%"PRIu32", ClientVersion=%"PRIu32, ServerVersion, ClientVersion);
WLog_Print(audin->log, WLOG_DEBUG, "ServerVersion=%"PRIu32", ClientVersion=%"PRIu32, ServerVersion,
ClientVersion);
out = Stream_New(NULL, 5);
if (!out)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
return ERROR_OUTOFMEMORY;
}
@ -162,11 +164,13 @@ static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback,
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCallback)
static UINT audin_send_incoming_data_pdu(AUDIN_CHANNEL_CALLBACK* callback)
{
BYTE out_data[1];
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
out_data[0] = MSG_SNDIN_DATA_INCOMING;
BYTE out_data[1] = { MSG_SNDIN_DATA_INCOMING };
if (!callback || !callback->channel || !callback->channel->Write)
return ERROR_INTERNAL_ERROR;
return callback->channel->Write(callback->channel, 1, out_data, NULL);
}
@ -175,10 +179,8 @@ static UINT audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCal
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
{
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
UINT32 i;
UINT error;
wStream* out;
@ -189,11 +191,11 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, NumFormats);
DEBUG_DVC("NumFormats %"PRIu32"", NumFormats);
WLog_Print(audin->log, WLOG_DEBUG, "NumFormats %"PRIu32"", NumFormats);
if ((NumFormats < 1) || (NumFormats > 1000))
{
WLog_ERR(TAG, "bad NumFormats %"PRIu32"", NumFormats);
WLog_Print(audin->log, WLOG_ERROR, "bad NumFormats %"PRIu32"", NumFormats);
return ERROR_INVALID_DATA;
}
@ -202,7 +204,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
if (!callback->formats)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(audin->log, WLOG_ERROR, "calloc failed!");
return ERROR_INVALID_DATA;
}
@ -211,7 +213,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
if (!out)
{
error = CHANNEL_RC_NO_MEMORY;
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
goto out;
}
@ -247,10 +249,11 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
Stream_Seek(s, format.cbSize);
}
DEBUG_DVC("wFormatTag=%"PRIu16" nChannels=%"PRIu16" nSamplesPerSec=%"PRIu32" "
"nBlockAlign=%"PRIu16" wBitsPerSample=%"PRIu16" cbSize=%"PRIu16"",
format.wFormatTag, format.nChannels, format.nSamplesPerSec,
format.nBlockAlign, format.wBitsPerSample, format.cbSize);
WLog_Print(audin->log, WLOG_DEBUG,
"wFormatTag=%s nChannels=%"PRIu16" nSamplesPerSec=%"PRIu32" "
"nBlockAlign=%"PRIu16" wBitsPerSample=%"PRIu16" cbSize=%"PRIu16"",
rdpsnd_get_audio_tag_string(format.wFormatTag), format.nChannels, format.nSamplesPerSec,
format.nBlockAlign, format.wBitsPerSample, format.cbSize);
if (audin->fixed_format > 0 && audin->fixed_format != format.wFormatTag)
continue;
@ -271,7 +274,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
if (!Stream_EnsureRemainingCapacity(out, 18 + format.cbSize))
{
error = CHANNEL_RC_NO_MEMORY;
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
goto out;
}
@ -284,9 +287,9 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
}
}
if ((error = audin_send_incoming_data_pdu(pChannelCallback)))
if ((error = audin_send_incoming_data_pdu(callback)))
{
WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!");
WLog_Print(audin->log, WLOG_ERROR, "audin_send_incoming_data_pdu failed!");
goto out;
}
@ -321,16 +324,14 @@ out:
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback,
static UINT audin_send_format_change_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback,
UINT32 NewFormat)
{
wStream* out;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
out = Stream_New(NULL, 5);
wStream* out = Stream_New(NULL, 5);
if (!out)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_OK;
}
@ -344,15 +345,14 @@ static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCal
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallback, UINT32 Result)
static UINT audin_send_open_reply_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback,
UINT32 Result)
{
wStream* out;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
out = Stream_New(NULL, 5);
wStream* out = Stream_New(NULL, 5);
if (!out)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -398,15 +398,27 @@ static UINT audin_receive_wave_data(const AUDIO_FORMAT* format,
Stream_Write(audin->data, data, size);
}
else if (!freerdp_dsp_encode(audin->dsp_context, format, data, size, audin->data))
return ERROR_INTERNAL_ERROR;
else
{
if (!freerdp_dsp_encode(audin->dsp_context, format, data, size, audin->data))
return ERROR_INTERNAL_ERROR;
}
/* Did not encode anything, skip this, the codec is not ready for output. */
if (Stream_GetPosition(audin->data) <= 1)
return CHANNEL_RC_OK;
if ((error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback*) callback)))
WLog_Print(audin->log, WLOG_TRACE,
"%s: nChannels: %"PRIu16" nSamplesPerSec: %"PRIu32" "
"nAvgBytesPerSec: %"PRIu32" nBlockAlign: %"PRIu16" wBitsPerSample: %"PRIu16" cbSize: %"PRIu16" [%"PRIdz"/%"PRIdz"]",
rdpsnd_get_audio_tag_string(audin->format->wFormatTag),
audin->format->nChannels, audin->format->nSamplesPerSec, audin->format->nAvgBytesPerSec,
audin->format->nBlockAlign, audin->format->wBitsPerSample, audin->format->cbSize, size,
Stream_GetPosition(audin->data) - 1);
if ((error = audin_send_incoming_data_pdu(callback)))
{
WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!");
WLog_Print(audin->log, WLOG_ERROR, "audin_send_incoming_data_pdu failed!");
return error;
}
@ -424,8 +436,8 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb
format = *audin->format;
supported = IFCALLRESULT(FALSE, audin->device->FormatSupported, audin->device, &format);
WLog_DBG(TAG, "microphone uses %s codec",
rdpsnd_get_audio_tag_string(format.wFormatTag));
WLog_Print(audin->log, WLOG_DEBUG, "microphone uses %s codec",
rdpsnd_get_audio_tag_string(format.wFormatTag));
if (!supported)
{
@ -443,7 +455,7 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb
return FALSE;
}
if (!audin->device->FormatSupported(audin->device, audin->format))
if (!supported)
{
if (!freerdp_dsp_context_reset(audin->dsp_context, audin->format))
return FALSE;
@ -465,10 +477,8 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
static UINT audin_process_open(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
{
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
UINT32 initialFormat;
UINT32 FramesPerPacket;
UINT error = CHANNEL_RC_OK;
@ -478,14 +488,14 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
Stream_Read_UINT32(s, FramesPerPacket);
Stream_Read_UINT32(s, initialFormat);
DEBUG_DVC("FramesPerPacket=%"PRIu32" initialFormat=%"PRIu32"",
FramesPerPacket, initialFormat);
WLog_Print(audin->log, WLOG_DEBUG, "FramesPerPacket=%"PRIu32" initialFormat=%"PRIu32"",
FramesPerPacket, initialFormat);
audin->FramesPerPacket = FramesPerPacket;
if (initialFormat >= callback->formats_count)
{
WLog_ERR(TAG, "invalid format index %"PRIu32" (total %d)",
initialFormat, callback->formats_count);
WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)",
initialFormat, callback->formats_count);
return ERROR_INVALID_DATA;
}
@ -494,14 +504,14 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
if (!audin_open_device(audin, callback))
return ERROR_INTERNAL_ERROR;
if ((error = audin_send_format_change_pdu(pChannelCallback, initialFormat)))
if ((error = audin_send_format_change_pdu(audin, callback, initialFormat)))
{
WLog_ERR(TAG, "audin_send_format_change_pdu failed!");
WLog_Print(audin->log, WLOG_ERROR, "audin_send_format_change_pdu failed!");
return error;
}
if ((error = audin_send_open_reply_pdu(pChannelCallback, 0)))
WLog_ERR(TAG, "audin_send_open_reply_pdu failed!");
if ((error = audin_send_open_reply_pdu(audin, callback, 0)))
WLog_Print(audin->log, WLOG_ERROR, "audin_send_open_reply_pdu failed!");
return error;
}
@ -511,10 +521,9 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
static UINT audin_process_format_change(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback,
wStream* s)
{
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
UINT32 NewFormat;
UINT error = CHANNEL_RC_OK;
@ -522,12 +531,12 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, NewFormat);
DEBUG_DVC("NewFormat=%"PRIu32"", NewFormat);
WLog_Print(audin->log, WLOG_DEBUG, "NewFormat=%"PRIu32"", NewFormat);
if (NewFormat >= callback->formats_count)
{
WLog_ERR(TAG, "invalid format index %"PRIu32" (total %d)",
NewFormat, callback->formats_count);
WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)",
NewFormat, callback->formats_count);
return ERROR_INVALID_DATA;
}
@ -547,7 +556,7 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
if (!audin_open_device(audin, callback))
return ERROR_INTERNAL_ERROR;
if ((error = audin_send_format_change_pdu(pChannelCallback, NewFormat)))
if ((error = audin_send_format_change_pdu(audin, callback, NewFormat)))
WLog_ERR(TAG, "audin_send_format_change_pdu failed!");
return error;
@ -562,33 +571,43 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
{
UINT error;
BYTE MessageId;
AUDIN_PLUGIN* audin;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
if (Stream_GetRemainingLength(data) < 1)
return ERROR_INVALID_DATA;
if (!callback || !data)
return ERROR_INVALID_PARAMETER;
audin = (AUDIN_PLUGIN*) callback->plugin;
if (!audin)
return ERROR_INTERNAL_ERROR;
if (Stream_GetRemainingCapacity(data) < 1)
return ERROR_NO_DATA;
Stream_Read_UINT8(data, MessageId);
DEBUG_DVC("MessageId=0x%02"PRIx8"", MessageId);
WLog_Print(audin->log, WLOG_DEBUG, "MessageId=0x%02"PRIx8"", MessageId);
switch (MessageId)
{
case MSG_SNDIN_VERSION:
error = audin_process_version(pChannelCallback, data);
error = audin_process_version(audin, callback, data);
break;
case MSG_SNDIN_FORMATS:
error = audin_process_formats(pChannelCallback, data);
error = audin_process_formats(audin, callback, data);
break;
case MSG_SNDIN_OPEN:
error = audin_process_open(pChannelCallback, data);
error = audin_process_open(audin, callback, data);
break;
case MSG_SNDIN_FORMATCHANGE:
error = audin_process_format_change(pChannelCallback, data);
error = audin_process_format_change(audin, callback, data);
break;
default:
WLog_ERR(TAG, "unknown MessageId=0x%02"PRIx8"", MessageId);
WLog_Print(audin->log, WLOG_ERROR, "unknown MessageId=0x%02"PRIx8"", MessageId);
error = ERROR_INVALID_DATA;
break;
}
@ -607,14 +626,14 @@ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback)
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
UINT error = CHANNEL_RC_OK;
DEBUG_DVC("...");
WLog_Print(audin->log, WLOG_TRACE, "...");
if (audin->device)
{
IFCALLRET(audin->device->Close, error, audin->device);
if (error != CHANNEL_RC_OK)
WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error);
WLog_Print(audin->log, WLOG_ERROR, "Close failed with errorcode %"PRIu32"", error);
}
audin->format = NULL;
@ -644,13 +663,19 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
IWTSVirtualChannelCallback** ppCallback)
{
AUDIN_CHANNEL_CALLBACK* callback;
AUDIN_PLUGIN* audin;
AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback;
DEBUG_DVC("...");
if (!listener_callback || !listener_callback->plugin)
return ERROR_INTERNAL_ERROR;
audin = (AUDIN_PLUGIN*) listener_callback->plugin;
WLog_Print(audin->log, WLOG_TRACE, "...");
callback = (AUDIN_CHANNEL_CALLBACK*) calloc(1, sizeof(AUDIN_CHANNEL_CALLBACK));
if (!callback)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(audin->log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -671,12 +696,19 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
DEBUG_DVC("...");
if (!audin)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
if (!pChannelMgr)
return ERROR_INVALID_PARAMETER;
WLog_Print(audin->log, WLOG_TRACE, "...");
audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) calloc(1, sizeof(AUDIN_LISTENER_CALLBACK));
if (!audin->listener_callback)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(audin->log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -696,7 +728,11 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin)
{
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
UINT error = CHANNEL_RC_OK;
DEBUG_DVC("...");
if (!audin)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
WLog_Print(audin->log, WLOG_TRACE, "...");
if (audin->device)
{
@ -704,7 +740,7 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin)
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "Free failed with errorcode %"PRIu32"", error);
WLog_Print(audin->log, WLOG_ERROR, "Free failed with errorcode %"PRIu32"", error);
// dont stop on error
}
@ -755,11 +791,11 @@ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
if (audin->device)
{
WLog_ERR(TAG, "existing device, abort.");
WLog_Print(audin->log, WLOG_ERROR, "existing device, abort.");
return ERROR_ALREADY_EXISTS;
}
DEBUG_DVC("device registered.");
WLog_Print(audin->log, WLOG_DEBUG, "device registered.");
audin->device = device;
return CHANNEL_RC_OK;
}
@ -769,7 +805,7 @@ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args)
static UINT audin_load_device_plugin(AUDIN_PLUGIN* audin, char* name, ADDIN_ARGV* args)
{
PFREERDP_AUDIN_DEVICE_ENTRY entry;
FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints;
@ -779,23 +815,24 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
if (entry == NULL)
{
WLog_ERR(TAG, "freerdp_load_channel_addin_entry did not return any function pointers for %s ",
name);
WLog_Print(audin->log, WLOG_ERROR,
"freerdp_load_channel_addin_entry did not return any function pointers for %s ",
name);
return ERROR_INVALID_FUNCTION;
}
entryPoints.plugin = pPlugin;
entryPoints.plugin = (IWTSPlugin*) audin;
entryPoints.pRegisterAudinDevice = audin_register_device_plugin;
entryPoints.args = args;
entryPoints.rdpcontext = ((AUDIN_PLUGIN*)pPlugin)->rdpcontext;
entryPoints.rdpcontext = audin->rdpcontext;
if ((error = entry(&entryPoints)))
{
WLog_ERR(TAG, "%s entry returned error %"PRIu32".", name, error);
WLog_Print(audin->log, WLOG_ERROR, "%s entry returned error %"PRIu32".", name, error);
return error;
}
WLog_INFO(TAG, "Loaded %s backend for audin", name);
WLog_Print(audin->log, WLOG_INFO, "Loaded %s backend for audin", name);
return CHANNEL_RC_OK;
}
@ -811,7 +848,7 @@ static UINT audin_set_subsystem(AUDIN_PLUGIN* audin, const char* subsystem)
if (!audin->subsystem)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(audin->log, WLOG_ERROR, "_strdup failed!");
return ERROR_NOT_ENOUGH_MEMORY;
}
@ -830,7 +867,7 @@ static UINT audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name)
if (!audin->device_name)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(audin->log, WLOG_ERROR, "_strdup failed!");
return ERROR_NOT_ENOUGH_MEMORY;
}
@ -877,7 +914,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
{
if ((error = audin_set_subsystem(audin, arg->Value)))
{
WLog_ERR(TAG, "audin_set_subsystem failed with error %"PRIu32"!", error);
WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem failed with error %"PRIu32"!", error);
return FALSE;
}
}
@ -885,7 +922,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
{
if ((error = audin_set_device_name(audin, arg->Value)))
{
WLog_ERR(TAG, "audin_set_device_name failed with error %"PRIu32"!", error);
WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name failed with error %"PRIu32"!", error);
return FALSE;
}
}
@ -983,6 +1020,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
return CHANNEL_RC_NO_MEMORY;
}
audin->log = WLog_Get(TAG);
audin->data = Stream_New(NULL, 4096);
if (!audin->data)
@ -1012,10 +1050,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
if (audin->subsystem)
{
if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
if ((error = audin_load_device_plugin(audin, audin->subsystem, args)))
{
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %"PRIu32"!",
audin->subsystem, error);
WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!",
audin->subsystem, error);
goto out;
}
}
@ -1025,18 +1063,18 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
if ((error = audin_set_subsystem(audin, entry->subsystem)))
{
WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %"PRIu32"!",
entry->subsystem, error);
WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem for %s failed with error %"PRIu32"!",
entry->subsystem, error);
}
else if ((error = audin_set_device_name(audin, entry->device)))
{
WLog_ERR(TAG, "audin_set_device_name for %s failed with error %"PRIu32"!",
entry->subsystem, error);
WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name for %s failed with error %"PRIu32"!",
entry->subsystem, error);
}
else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
else if ((error = audin_load_device_plugin(audin, audin->subsystem, args)))
{
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %"PRIu32"!",
entry->subsystem, error);
WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!",
entry->subsystem, error);
}
entry++;
@ -1044,7 +1082,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
}
if (audin->device == NULL)
WLog_ERR(TAG, "no sound device.");
WLog_Print(audin->log, WLOG_ERROR, "no sound device.");
error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
out:

View File

@ -32,11 +32,5 @@
#define TAG CHANNELS_TAG("audin.client")
#ifdef WITH_DEBUG_DVC
#define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__)
#else
#define DEBUG_DVC(...) do { } while (0)
#endif
#endif /* FREERDP_CHANNEL_AUDIN_CLIENT_MAIN_H */

View File

@ -62,6 +62,7 @@ typedef struct _AudinOpenSLESDevice
void* user_data;
rdpContext* rdpcontext;
wLog* log;
} AudinOpenSLESDevice;
static DWORD WINAPI audin_opensles_thread_func(LPVOID arg)
@ -77,7 +78,7 @@ static DWORD WINAPI audin_opensles_thread_func(LPVOID arg)
int rc = CHANNEL_RC_OK;
UINT error = CHANNEL_RC_OK;
DWORD status;
DEBUG_DVC("opensles=%p", (void*) opensles);
WLog_Print(opensles->log, WLOG_DEBUG, "opensles=%p", (void*) opensles);
assert(opensles);
assert(opensles->frames_per_packet > 0);
assert(opensles->stopEvent);
@ -87,7 +88,7 @@ static DWORD WINAPI audin_opensles_thread_func(LPVOID arg)
if (!buffer.v)
{
error = CHANNEL_RC_NO_MEMORY;
WLog_ERR(TAG, "calloc failed!");
WLog_Print(opensles->log, WLOG_ERROR, "calloc failed!");
if (opensles->rdpcontext)
setChannelError(opensles->rdpcontext, CHANNEL_RC_NO_MEMORY,
@ -103,7 +104,7 @@ static DWORD WINAPI audin_opensles_thread_func(LPVOID arg)
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error);
WLog_Print(opensles->log, WLOG_ERROR, "WaitForSingleObject failed with error %"PRIu32"!", error);
break;
}
@ -114,7 +115,7 @@ static DWORD WINAPI audin_opensles_thread_func(LPVOID arg)
if (rc < 0)
{
WLog_ERR(TAG, "android_RecIn %d", rc);
WLog_Print(opensles->log, WLOG_ERROR, "android_RecIn %d", rc);
continue;
}
@ -127,7 +128,7 @@ static DWORD WINAPI audin_opensles_thread_func(LPVOID arg)
free(buffer.v);
out:
DEBUG_DVC("thread shutdown.");
WLog_Print(opensles->log, WLOG_DEBUG, "thread shutdown.");
if (error && opensles->rdpcontext)
setChannelError(opensles->rdpcontext, error, "audin_opensles_thread_func reported an error");
@ -144,7 +145,11 @@ out:
static UINT audin_opensles_free(IAudinDevice* device)
{
AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device;
DEBUG_DVC("device=%p", (void*) device);
if (!opensles)
return ERROR_INVALID_PARAMETER;
WLog_Print(opensles->log, WLOG_DEBUG, "device=%p", (void*) device);
/* The function may have been called out of order,
* ignore duplicate requests. */
@ -161,10 +166,12 @@ static UINT audin_opensles_free(IAudinDevice* device)
static BOOL audin_opensles_format_supported(IAudinDevice* device,
const AUDIO_FORMAT* format)
{
#ifdef WITH_DEBUG_DVC
AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device;
#endif
DEBUG_DVC("device=%p, format=%p", (void*) opensles, (void*) format);
if (!opensles || !format)
return FALSE;
WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, format=%p", (void*) opensles, (void*) format);
assert(format);
switch (format->wFormatTag)
@ -181,9 +188,9 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device,
break;
default:
DEBUG_DVC("Encoding '%s' [0x%04X"PRIX16"] not supported",
rdpsnd_get_audio_tag_string(format->wFormatTag),
format->wFormatTag);
WLog_Print(opensles->log, WLOG_DEBUG, "Encoding '%s' [0x%04X"PRIX16"] not supported",
rdpsnd_get_audio_tag_string(format->wFormatTag),
format->wFormatTag);
break;
}
@ -199,8 +206,12 @@ static UINT audin_opensles_set_format(IAudinDevice* device,
const AUDIO_FORMAT* format, UINT32 FramesPerPacket)
{
AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device;
DEBUG_DVC("device=%p, format=%p, FramesPerPacket=%"PRIu32"",
(void*) device, (void*) format, FramesPerPacket);
if (!opensles || !format)
return ERROR_INVALID_PARAMETER;
WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, format=%p, FramesPerPacket=%"PRIu32"",
(void*) device, (void*) format, FramesPerPacket);
assert(format);
/* The function may have been called out of order, ignore
@ -236,14 +247,14 @@ static UINT audin_opensles_set_format(IAudinDevice* device,
break;
default:
WLog_ERR(TAG, "Encoding '%"PRIu16"' [%04"PRIX16"] not supported",
format->wFormatTag,
format->wFormatTag);
WLog_Print(opensles->log, WLOG_ERROR, "Encoding '%"PRIu16"' [%04"PRIX16"] not supported",
format->wFormatTag,
format->wFormatTag);
return ERROR_UNSUPPORTED_TYPE;
}
DEBUG_DVC("aligned frames_per_packet=%"PRIu32", block_size=%"PRIu32"",
opensles->frames_per_packet, opensles->block_size);
WLog_Print(opensles->log, WLOG_DEBUG, "frames_per_packet=%"PRIu32,
opensles->frames_per_packet);
return CHANNEL_RC_OK;
}
@ -256,8 +267,13 @@ static UINT audin_opensles_open(IAudinDevice* device, AudinReceive receive,
void* user_data)
{
AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device;
DEBUG_DVC("device=%p, receive=%p, user_data=%p", (void*) device, (void*) receive,
(void*) user_data);
if (!opensles || !receive || !user_data)
return ERROR_INVALID_PARAMETER;
WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, receive=%p, user_data=%p", (void*) device,
(void*) receive,
(void*) user_data);
assert(opensles);
/* The function may have been called out of order,
@ -272,7 +288,7 @@ static UINT audin_opensles_open(IAudinDevice* device, AudinReceive receive,
opensles->frames_per_packet,
opensles->format.wBitsPerSample)))
{
WLog_ERR(TAG, "android_OpenRecDevice failed!");
WLog_Print(opensles->log, WLOG_ERROR, "android_OpenRecDevice failed!");
return ERROR_INTERNAL_ERROR;
}
@ -281,14 +297,14 @@ static UINT audin_opensles_open(IAudinDevice* device, AudinReceive receive,
if (!(opensles->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
WLog_Print(opensles->log, WLOG_ERROR, "CreateEvent failed!");
goto error_out;
}
if (!(opensles->thread = CreateThread(NULL, 0,
audin_opensles_thread_func, opensles, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
WLog_Print(opensles->log, WLOG_ERROR, "CreateThread failed!");
goto error_out;
}
@ -310,14 +326,14 @@ static UINT audin_opensles_close(IAudinDevice* device)
{
UINT error;
AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device;
DEBUG_DVC("device=%p", (void*) device);
WLog_Print(opensles->log, WLOG_DEBUG, "device=%p", (void*) device);
assert(opensles);
/* The function may have been called out of order,
* ignore duplicate requests. */
if (!opensles->stopEvent)
{
WLog_ERR(TAG, "[ERROR] function called without matching open.");
WLog_Print(opensles->log, WLOG_ERROR, "[ERROR] function called without matching open.");
return ERROR_REQUEST_OUT_OF_SEQUENCE;
}
@ -329,7 +345,7 @@ static UINT audin_opensles_close(IAudinDevice* device)
if (WaitForSingleObject(opensles->thread, INFINITE) == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error);
WLog_Print(opensles->log, WLOG_ERROR, "WaitForSingleObject failed with error %"PRIu32"", error);
return error;
}
@ -365,7 +381,7 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device,
DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg;
AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device;
DEBUG_DVC("device=%p, args=%p", (void*) device, (void*) args);
WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, args=%p", (void*) device, (void*) args);
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
status = CommandLineParseArgumentsA(args->argc, args->argv,
audin_opensles_args, flags, opensles, NULL, NULL);
@ -387,7 +403,7 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device,
if (!opensles->device_name)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(opensles->log, WLOG_ERROR, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY;
}
}
@ -417,7 +433,6 @@ UINT freerdp_audin_client_subsystem_entry(
ADDIN_ARGV* args;
AudinOpenSLESDevice* opensles;
UINT error;
DEBUG_DVC("pEntryPoints=%p", (void*) pEntryPoints);
opensles = (AudinOpenSLESDevice*) calloc(1, sizeof(AudinOpenSLESDevice));
if (!opensles)
@ -426,6 +441,7 @@ UINT freerdp_audin_client_subsystem_entry(
return CHANNEL_RC_NO_MEMORY;
}
opensles->log = WLog_Get(TAG);
opensles->iface.Open = audin_opensles_open;
opensles->iface.FormatSupported = audin_opensles_format_supported;
opensles->iface.SetFormat = audin_opensles_set_format;
@ -436,13 +452,14 @@ UINT freerdp_audin_client_subsystem_entry(
if ((error = audin_opensles_parse_addin_args(opensles, args)))
{
WLog_ERR(TAG, "audin_opensles_parse_addin_args failed with errorcode %"PRIu32"!", error);
WLog_Print(opensles->log, WLOG_ERROR,
"audin_opensles_parse_addin_args failed with errorcode %"PRIu32"!", error);
goto error_out;
}
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) opensles)))
{
WLog_ERR(TAG, "RegisterAudinDevice failed with error %"PRIu32"!", error);
WLog_Print(opensles->log, WLOG_ERROR, "RegisterAudinDevice failed with error %"PRIu32"!", error);
goto error_out;
}

View File

@ -42,27 +42,23 @@ static SLresult openSLCreateEngine(OPENSL_STREAM* p)
SLresult result;
// create engine
result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
DEBUG_DVC("engineObject=%p", (void*) p->engineObject);
if (result != SL_RESULT_SUCCESS) goto engine_end;
// realize the engine
result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
DEBUG_DVC("Realize=%"PRIu32"", result);
if (result != SL_RESULT_SUCCESS) goto engine_end;
// get the engine interface, which is needed in order to create other objects
result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE,
&(p->engineEngine));
DEBUG_DVC("engineEngine=%p", (void*) p->engineEngine);
if (result != SL_RESULT_SUCCESS) goto engine_end;
// get the volume interface - important, this is optional!
result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_DEVICEVOLUME,
&(p->deviceVolume));
DEBUG_DVC("deviceVolume=%p", (void*) p->deviceVolume);
if (result != SL_RESULT_SUCCESS)
{
@ -180,14 +176,12 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p)
const SLboolean req[] = {SL_BOOLEAN_TRUE};
result = (*p->engineEngine)->CreateAudioRecorder(p->engineEngine,
&(p->recorderObject), &audioSrc, &audioSnk, 1, id, req);
DEBUG_DVC("p->recorderObject=%p", (void*) p->recorderObject);
assert(!result);
if (SL_RESULT_SUCCESS != result) goto end_recopen;
// realize the audio recorder
result = (*p->recorderObject)->Realize(p->recorderObject, SL_BOOLEAN_FALSE);
DEBUG_DVC("Realize=%"PRIu32"", result);
assert(!result);
if (SL_RESULT_SUCCESS != result) goto end_recopen;
@ -195,7 +189,6 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p)
// get the record interface
result = (*p->recorderObject)->GetInterface(p->recorderObject,
SL_IID_RECORD, &(p->recorderRecord));
DEBUG_DVC("p->recorderRecord=%p", (void*) p->recorderRecord);
assert(!result);
if (SL_RESULT_SUCCESS != result) goto end_recopen;
@ -204,7 +197,6 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p)
result = (*p->recorderObject)->GetInterface(p->recorderObject,
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
&(p->recorderBufferQueue));
DEBUG_DVC("p->recorderBufferQueue=%p", (void*) p->recorderBufferQueue);
assert(!result);
if (SL_RESULT_SUCCESS != result) goto end_recopen;
@ -212,7 +204,6 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p)
// register callback on the buffer queue
result = (*p->recorderBufferQueue)->RegisterCallback(p->recorderBufferQueue,
bqRecorderCallback, p);
DEBUG_DVC("p->recorderBufferQueue=%p", (void*) p->recorderBufferQueue);
assert(!result);
if (SL_RESULT_SUCCESS != result)
@ -227,8 +218,6 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p)
// close the OpenSL IO and destroy the audio engine
static void openSLDestroyEngine(OPENSL_STREAM* p)
{
DEBUG_DVC("p=%p", (void*) p);
// destroy audio recorder object, and invalidate all associated interfaces
if (p->recorderObject != NULL)
{
@ -288,8 +277,6 @@ OPENSL_STREAM* android_OpenRecDevice(char* name, int sr, int inchannels,
// close the android audio device
void android_CloseRecDevice(OPENSL_STREAM* p)
{
DEBUG_DVC("p=%p", (void*) p);
if (p == NULL)
return;
@ -326,7 +313,6 @@ static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
{
queue_element* e;
OPENSL_STREAM* p = (OPENSL_STREAM*) context;
DEBUG_DVC("p=%p", (void*) p);
assert(p);
assert(p->next);
assert(p->prep);

View File

@ -29,6 +29,7 @@
#include <winpr/crt.h>
#include <winpr/cmdline.h>
#include <winpr/wlog.h>
#include <pulse/pulseaudio.h>
@ -58,6 +59,7 @@ typedef struct _AudinPulseDevice
void* user_data;
rdpContext* rdpcontext;
wLog* log;
} AudinPulseDevice;
static void audin_pulse_context_state_callback(pa_context* context, void* userdata)
@ -69,18 +71,18 @@ static void audin_pulse_context_state_callback(pa_context* context, void* userda
switch (state)
{
case PA_CONTEXT_READY:
DEBUG_DVC("PA_CONTEXT_READY");
WLog_Print(pulse->log, WLOG_DEBUG, "PA_CONTEXT_READY");
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
DEBUG_DVC("state %d", state);
WLog_Print(pulse->log, WLOG_DEBUG, "state %d", state);
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
default:
DEBUG_DVC("state %d", state);
WLog_Print(pulse->log, WLOG_DEBUG, "state %d", state);
break;
}
}
@ -100,8 +102,8 @@ static UINT audin_pulse_connect(IAudinDevice* device)
if (pa_context_connect(pulse->context, NULL, 0, NULL))
{
WLog_ERR(TAG, "pa_context_connect failed (%d)",
pa_context_errno(pulse->context));
WLog_Print(pulse->log, WLOG_ERROR, "pa_context_connect failed (%d)",
pa_context_errno(pulse->context));
return ERROR_INTERNAL_ERROR;
}
@ -110,8 +112,8 @@ static UINT audin_pulse_connect(IAudinDevice* device)
if (pa_threaded_mainloop_start(pulse->mainloop) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
WLog_ERR(TAG, "pa_threaded_mainloop_start failed (%d)",
pa_context_errno(pulse->context));
WLog_Print(pulse->log, WLOG_ERROR, "pa_threaded_mainloop_start failed (%d)",
pa_context_errno(pulse->context));
return ERROR_INTERNAL_ERROR;
}
@ -124,8 +126,8 @@ static UINT audin_pulse_connect(IAudinDevice* device)
if (!PA_CONTEXT_IS_GOOD(state))
{
WLog_ERR(TAG, "bad context state (%d)",
pa_context_errno(pulse->context));
WLog_Print(pulse->log, WLOG_ERROR, "bad context state (%d)",
pa_context_errno(pulse->context));
pa_context_disconnect(pulse->context);
return ERROR_INVALID_STATE;
}
@ -134,7 +136,7 @@ static UINT audin_pulse_connect(IAudinDevice* device)
}
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_DVC("connected");
WLog_Print(pulse->log, WLOG_DEBUG, "connected");
return CHANNEL_RC_OK;
}
@ -176,6 +178,9 @@ static BOOL audin_pulse_format_supported(IAudinDevice* device, const AUDIO_FORMA
{
AudinPulseDevice* pulse = (AudinPulseDevice*) device;
if (!pulse || !format)
return FALSE;
if (!pulse->context)
return 0;
@ -222,6 +227,9 @@ static UINT audin_pulse_set_format(IAudinDevice* device, const AUDIO_FORMAT* for
pa_sample_spec sample_spec = { 0 };
AudinPulseDevice* pulse = (AudinPulseDevice*) device;
if (!pulse || !format)
return ERROR_INVALID_PARAMETER;
if (!pulse->context)
return ERROR_INVALID_PARAMETER;
@ -276,18 +284,18 @@ static void audin_pulse_stream_state_callback(pa_stream* stream, void* userdata)
switch (state)
{
case PA_STREAM_READY:
DEBUG_DVC("PA_STREAM_READY");
WLog_Print(pulse->log, WLOG_DEBUG, "PA_STREAM_READY");
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
DEBUG_DVC("state %d", state);
WLog_Print(pulse->log, WLOG_DEBUG, "state %d", state);
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
default:
DEBUG_DVC("state %d", state);
WLog_Print(pulse->log, WLOG_DEBUG, "state %d", state);
break;
}
}
@ -315,6 +323,9 @@ static UINT audin_pulse_close(IAudinDevice* device)
{
AudinPulseDevice* pulse = (AudinPulseDevice*) device;
if (!pulse)
return ERROR_INVALID_PARAMETER;
if (pulse->stream)
{
pa_threaded_mainloop_lock(pulse->mainloop);
@ -340,6 +351,9 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
pa_buffer_attr buffer_attr = { 0 };
AudinPulseDevice* pulse = (AudinPulseDevice*) device;
if (!pulse || !receive || !user_data)
return ERROR_INVALID_PARAMETER;
if (!pulse->context)
return ERROR_INVALID_PARAMETER;
@ -355,8 +369,8 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
if (!pulse->stream)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_DVC("pa_stream_new failed (%d)",
pa_context_errno(pulse->context));
WLog_Print(pulse->log, WLOG_DEBUG, "pa_stream_new failed (%d)",
pa_context_errno(pulse->context));
return pa_context_errno(pulse->context);
}
@ -370,15 +384,19 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
buffer_attr.prebuf = (UINT32) - 1;
buffer_attr.minreq = (UINT32) - 1;
/* 500ms latency */
buffer_attr.fragsize = pa_usec_to_bytes(500000, &pulse->sample_spec);
buffer_attr.fragsize = pulse->bytes_per_frame * pulse->frames_per_packet;
if (buffer_attr.fragsize % pulse->format.nBlockAlign)
buffer_attr.fragsize += pulse->format.nBlockAlign - buffer_attr.fragsize %
pulse->format.nBlockAlign;
if (pa_stream_connect_record(pulse->stream,
pulse->device_name,
&buffer_attr, PA_STREAM_ADJUST_LATENCY) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
WLog_ERR(TAG, "pa_stream_connect_playback failed (%d)",
pa_context_errno(pulse->context));
WLog_Print(pulse->log, WLOG_ERROR, "pa_stream_connect_playback failed (%d)",
pa_context_errno(pulse->context));
return pa_context_errno(pulse->context);
}
@ -392,8 +410,8 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
if (!PA_STREAM_IS_GOOD(state))
{
audin_pulse_close(device);
WLog_ERR(TAG, "bad stream state (%d)",
pa_context_errno(pulse->context));
WLog_Print(pulse->log, WLOG_ERROR, "bad stream state (%d)",
pa_context_errno(pulse->context));
pa_threaded_mainloop_unlock(pulse->mainloop);
return pa_context_errno(pulse->context);
}
@ -403,7 +421,7 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
pa_threaded_mainloop_unlock(pulse->mainloop);
pulse->buffer_frames = 0;
DEBUG_DVC("connected");
WLog_Print(pulse->log, WLOG_DEBUG, "connected");
return CHANNEL_RC_OK;
}
@ -445,7 +463,7 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a
if (!pulse->device_name)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(pulse->log, WLOG_ERROR, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY;
}
}
@ -480,6 +498,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
return CHANNEL_RC_NO_MEMORY;
}
pulse->log = WLog_Get(TAG);
pulse->iface.Open = audin_pulse_open;
pulse->iface.FormatSupported = audin_pulse_format_supported;
pulse->iface.SetFormat = audin_pulse_set_format;
@ -490,7 +509,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
if ((error = audin_pulse_parse_addin_args(pulse, args)))
{
WLog_ERR(TAG, "audin_pulse_parse_addin_args failed with error %"PRIu32"!", error);
WLog_Print(pulse->log, WLOG_ERROR, "audin_pulse_parse_addin_args failed with error %"PRIu32"!",
error);
goto error_out;
}
@ -498,7 +518,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
if (!pulse->mainloop)
{
WLog_ERR(TAG, "pa_threaded_mainloop_new failed");
WLog_Print(pulse->log, WLOG_ERROR, "pa_threaded_mainloop_new failed");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
@ -507,7 +527,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
if (!pulse->context)
{
WLog_ERR(TAG, "pa_context_new failed");
WLog_Print(pulse->log, WLOG_ERROR, "pa_context_new failed");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
@ -516,13 +536,13 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
if ((error = audin_pulse_connect((IAudinDevice*) pulse)))
{
WLog_ERR(TAG, "audin_pulse_connect failed");
WLog_Print(pulse->log, WLOG_ERROR, "audin_pulse_connect failed");
goto error_out;
}
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) pulse)))
{
WLog_ERR(TAG, "RegisterAudinDevice failed with error %"PRIu32"!", error);
WLog_Print(pulse->log, WLOG_ERROR, "RegisterAudinDevice failed with error %"PRIu32"!", error);
goto error_out;
}

View File

@ -53,6 +53,7 @@ typedef struct _AudinWinmmDevice
UINT32 cFormats;
UINT32 frames_per_packet;
rdpContext* rdpcontext;
wLog* log;
} AudinWinmmDevice;
static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance,
@ -148,7 +149,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
if (MMSYSERR_NOERROR != rc)
{
DEBUG_DVC("waveInPrepareHeader failed. %"PRIu32"", rc);
WLog_Print(winmm->log, WLOG_DEBUG, "waveInPrepareHeader failed. %"PRIu32"", rc);
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR,
@ -159,7 +160,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
if (MMSYSERR_NOERROR != rc)
{
DEBUG_DVC("waveInAddBuffer failed. %"PRIu32"", rc);
WLog_Print(winmm->log, WLOG_DEBUG, "waveInAddBuffer failed. %"PRIu32"", rc);
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR,
@ -171,7 +172,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
if (MMSYSERR_NOERROR != rc)
{
DEBUG_DVC("waveInStart failed. %"PRIu32"", rc);
WLog_Print(winmm->log, WLOG_DEBUG, "waveInStart failed. %"PRIu32"", rc);
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR,
@ -182,7 +183,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
if (status == WAIT_FAILED)
{
DEBUG_DVC("WaitForSingleObject failed.");
WLog_Print(winmm->log, WLOG_DEBUG, "WaitForSingleObject failed.");
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR,
@ -193,7 +194,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
if (MMSYSERR_NOERROR != rc)
{
DEBUG_DVC("waveInReset failed. %"PRIu32"", rc);
WLog_Print(winmm->log, WLOG_DEBUG, "waveInReset failed. %"PRIu32"", rc);
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR,
@ -206,7 +207,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
if (MMSYSERR_NOERROR != rc)
{
DEBUG_DVC("waveInUnprepareHeader failed. %"PRIu32"", rc);
WLog_Print(winmm->log, WLOG_DEBUG, "waveInUnprepareHeader failed. %"PRIu32"", rc);
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR,
@ -220,7 +221,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
if (MMSYSERR_NOERROR != rc)
{
DEBUG_DVC("waveInClose failed. %"PRIu32"", rc);
WLog_Print(winmm->log, WLOG_DEBUG, "waveInClose failed. %"PRIu32"", rc);
if (winmm->rdpcontext)
setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR,
@ -241,6 +242,9 @@ static UINT audin_winmm_free(IAudinDevice* device)
UINT32 i;
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
if (!winmm)
return ERROR_INVALID_PARAMETER;
for (i = 0; i < winmm->cFormats; i++)
{
free(winmm->ppwfx[i]);
@ -262,13 +266,17 @@ static UINT audin_winmm_close(IAudinDevice* device)
DWORD status;
UINT error = CHANNEL_RC_OK;
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
if (!winmm)
return ERROR_INVALID_PARAMETER;
SetEvent(winmm->stopEvent);
status = WaitForSingleObject(winmm->thread, INFINITE);
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error);
WLog_Print(winmm->log, WLOG_ERROR, "WaitForSingleObject failed with error %"PRIu32"!", error);
return error;
}
@ -291,6 +299,10 @@ static UINT audin_winmm_set_format(IAudinDevice* device, const AUDIO_FORMAT* for
{
UINT32 i;
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
if (!winmm || !format)
return ERROR_INVALID_PARAMETER;
winmm->frames_per_packet = FramesPerPacket;
for (i = 0; i < winmm->cFormats; i++)
@ -312,6 +324,10 @@ static BOOL audin_winmm_format_supported(IAudinDevice* device, const AUDIO_FORMA
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
PWAVEFORMATEX pwfx;
BYTE* data;
if (!winmm || !format)
return FALSE;
pwfx = (PWAVEFORMATEX)malloc(sizeof(WAVEFORMATEX) + format->cbSize);
if (!pwfx)
@ -361,19 +377,23 @@ static BOOL audin_winmm_format_supported(IAudinDevice* device, const AUDIO_FORMA
static UINT audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* user_data)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
if (!winmm || !receive || !user_data)
return ERROR_INVALID_PARAMETER;
winmm->receive = receive;
winmm->user_data = user_data;
if (!(winmm->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
WLog_Print(winmm->log, WLOG_ERROR, "CreateEvent failed!");
return ERROR_INTERNAL_ERROR;
}
if (!(winmm->thread = CreateThread(NULL, 0,
audin_winmm_thread_func, winmm, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
WLog_Print(winmm->log, WLOG_ERROR, "CreateThread failed!");
CloseHandle(winmm->stopEvent);
winmm->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
@ -416,7 +436,7 @@ static UINT audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a
if (!winmm->device_name)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(winmm->log, WLOG_ERROR, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY;
}
}
@ -451,6 +471,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
return CHANNEL_RC_NO_MEMORY;
}
winmm->log = WLog_Get(TAG);
winmm->iface.Open = audin_winmm_open;
winmm->iface.FormatSupported = audin_winmm_format_supported;
winmm->iface.SetFormat = audin_winmm_set_format;
@ -461,7 +482,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
if ((error = audin_winmm_parse_addin_args(winmm, args)))
{
WLog_ERR(TAG, "audin_winmm_parse_addin_args failed with error %"PRIu32"!", error);
WLog_Print(winmm->log, WLOG_ERROR, "audin_winmm_parse_addin_args failed with error %"PRIu32"!",
error);
goto error_out;
}
@ -471,7 +493,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
if (!winmm->device_name)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(winmm->log, WLOG_ERROR, "_strdup failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
@ -482,14 +504,14 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
if (!winmm->ppwfx)
{
WLog_ERR(TAG, "malloc failed!");
WLog_Print(winmm->log, WLOG_ERROR, "malloc failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) winmm)))
{
WLog_ERR(TAG, "RegisterAudinDevice failed with error %"PRIu32"!", error);
WLog_Print(winmm->log, WLOG_ERROR, "RegisterAudinDevice failed with error %"PRIu32"!", error);
goto error_out;
}

View File

@ -157,8 +157,8 @@ static BOOL freerdp_dsp_resample(FREERDP_DSP_CONTEXT* context,
static const INT16 ima_step_index_table[] =
{
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
-1, -1, -1, -1, 2, 4, 6, 8
};
static const INT16 ima_step_size_table[] =
{
@ -226,7 +226,7 @@ static BOOL freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* context,
if (!Stream_EnsureCapacity(out, out_size))
return FALSE;
dst = Stream_Buffer(out);
dst = Stream_Pointer(out);
while (size > 0)
{
@ -602,19 +602,22 @@ static BOOL freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* context,
{
int i;
BYTE* dst;
BYTE* start;
INT16 sample;
BYTE encoded;
UINT32 out_size;
size_t align;
out_size = size / 2;
if (!Stream_EnsureRemainingCapacity(out, out_size))
if (!Stream_EnsureRemainingCapacity(out, size))
return FALSE;
dst = Stream_Buffer(out);
start = dst = Stream_Pointer(out);
align = (context->format.nChannels > 1) ? 32 : 4;
while (size > 0)
while (size > align)
{
if ((dst - Stream_Buffer(out)) % context->format.nBlockAlign == 0)
if ((dst - start) % context->format.nBlockAlign == 0)
{
*dst++ = context->adpcm.ima.last_sample[0] & 0xFF;
*dst++ = (context->adpcm.ima.last_sample[0] >> 8) & 0xFF;
@ -720,7 +723,7 @@ static BOOL freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* context,
if (!Stream_EnsureCapacity(out, out_size))
return FALSE;
dst = Stream_Buffer(out);
dst = Stream_Pointer(out);
while (size > 0)
{
@ -837,15 +840,16 @@ static BOOL freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* context, const BYTE
wStream* out)
{
BYTE* dst;
BYTE* start;
INT32 sample;
UINT32 out_size;
const size_t step = 8 + (context->format.nChannels > 1) ? 4 : 0;
out_size = size / 2;
if (!Stream_EnsureRemainingCapacity(out, out_size))
if (!Stream_EnsureRemainingCapacity(out, size))
return FALSE;
dst = Stream_Buffer(out);
start = dst = Stream_Pointer(out);
if (context->adpcm.ms.delta[0] < 16)
context->adpcm.ms.delta[0] = 16;
@ -855,7 +859,7 @@ static BOOL freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* context, const BYTE
while (size >= step)
{
if ((dst - Stream_Buffer(out)) % context->format.nBlockAlign == 0)
if ((dst - start) % context->format.nBlockAlign == 0)
{
if (context->format.nChannels > 1)
{

View File

@ -55,16 +55,14 @@ struct _FREERDP_DSP_CONTEXT
static BOOL ffmpeg_codec_is_filtered(enum AVCodecID id, BOOL encoder)
{
if (!encoder)
return FALSE;
switch (id)
{
#if !defined(WITH_DSP_EXPERIMENTAL)
case AV_CODEC_ID_ADPCM_IMA_OKI:
case AV_CODEC_ID_MP3:
case AV_CODEC_ID_GSM_MS:
case AV_CODEC_ID_AAC:
case AV_CODEC_ID_ADPCM_MS:
case AV_CODEC_ID_G723_1:
return TRUE;
#endif
@ -104,7 +102,7 @@ static enum AVCodecID ffmpeg_get_avcodec(const AUDIO_FORMAT* format)
}
case WAVE_FORMAT_DVI_ADPCM:
return AV_CODEC_ID_ADPCM_MS;
return AV_CODEC_ID_ADPCM_IMA_OKI;
case WAVE_FORMAT_ADPCM:
return AV_CODEC_ID_ADPCM_MS;
@ -118,6 +116,9 @@ static enum AVCodecID ffmpeg_get_avcodec(const AUDIO_FORMAT* format)
case WAVE_FORMAT_GSM610:
return AV_CODEC_ID_GSM_MS;
case WAVE_FORMAT_MSG723:
return AV_CODEC_ID_G723_1;
case WAVE_FORMAT_AAC_MS:
return AV_CODEC_ID_AAC;
@ -152,6 +153,7 @@ static int ffmpeg_sample_format(const AUDIO_FORMAT* format)
case WAVE_FORMAT_AAC_MS:
return AV_SAMPLE_FMT_FLTP;
case WAVE_FORMAT_MSG723:
case WAVE_FORMAT_GSM610:
return AV_SAMPLE_FMT_S16P;
@ -195,6 +197,7 @@ static void ffmpeg_close_context(FREERDP_DSP_CONTEXT* context)
context->rcontext = NULL;
}
}
static BOOL ffmpeg_open_context(FREERDP_DSP_CONTEXT* context)
{
int ret;
@ -235,6 +238,10 @@ static BOOL ffmpeg_open_context(FREERDP_DSP_CONTEXT* context)
context->context->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
break;
case AV_CODEC_ID_AAC:
context->context->profile = FF_PROFILE_AAC_MAIN;
break;
default:
break;
}
@ -366,7 +373,7 @@ static BOOL ffmpeg_encode_frame(AVCodecContext* context, AVFrame* in,
{
ret = avcodec_receive_packet(context, packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
if ((ret == AVERROR(EAGAIN)) || (ret == AVERROR_EOF))
return TRUE;
else if (ret < 0)
{
@ -522,7 +529,6 @@ BOOL freerdp_dsp_ffmpeg_encode(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT*
const BYTE* data, size_t length, wStream* out)
{
int rc;
int samples, rest;
if (!context || !format || !data || !out || !context->encoder)
return FALSE;
@ -547,18 +553,22 @@ BOOL freerdp_dsp_ffmpeg_encode(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT*
}
else
{
rest = samples = context->resampled->nb_samples;
int copied = 0;
int rest = context->resampled->nb_samples;
do
{
if (samples + context->bufferedSamples > context->context->frame_size)
samples = context->context->frame_size - context->bufferedSamples;
int inSamples = rest;
if (inSamples + context->bufferedSamples > context->context->frame_size)
inSamples = context->context->frame_size - context->bufferedSamples;
rc = av_samples_copy(context->buffered->extended_data, context->resampled->extended_data,
context->bufferedSamples, 0, samples,
context->bufferedSamples, copied, inSamples,
context->context->channels, context->context->sample_fmt);
rest -= samples;
context->bufferedSamples += samples;
rest -= inSamples;
copied += inSamples;
context->bufferedSamples += inSamples;
if (context->context->frame_size <= context->bufferedSamples)
{