Merge pull request #4758 from akallabeth/dsp_fix
Audio/microphone fixes
This commit is contained in:
commit
2d7499b7c0
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user