From 7a289423c02b172a75fd06205c866dd2c21bfe1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 20 Feb 2013 21:34:47 -0500 Subject: [PATCH] channels/rdpsnd: refactor scheduling of sending of sound PDUs --- channels/audin/client/alsa/audin_alsa.c | 44 ++++++++++++------- channels/client/channels.c | 30 ++++++------- channels/rdpsnd/client/rdpsnd_main.c | 56 +++++++++++++------------ channels/sample/client/sample_main.c | 28 ++++--------- include/freerdp/utils/svc_plugin.h | 3 -- libfreerdp/core/channel.c | 8 +++- libfreerdp/core/rdp.c | 1 + libfreerdp/utils/svc_plugin.c | 14 +------ 8 files changed, 90 insertions(+), 94 deletions(-) diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c index 6ec44fdc4..11f31e420 100644 --- a/channels/audin/client/alsa/audin_alsa.c +++ b/channels/audin/client/alsa/audin_alsa.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "audin_main.h" @@ -73,15 +74,12 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand snd_strerror(error)); return FALSE; } + snd_pcm_hw_params_any(capture_handle, hw_params); - snd_pcm_hw_params_set_access(capture_handle, hw_params, - SND_PCM_ACCESS_RW_INTERLEAVED); - snd_pcm_hw_params_set_format(capture_handle, hw_params, - alsa->format); - snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, - &alsa->actual_rate, NULL); - snd_pcm_hw_params_set_channels_near(capture_handle, hw_params, - &alsa->actual_channels); + snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_format(capture_handle, hw_params, alsa->format); + snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &alsa->actual_rate, NULL); + snd_pcm_hw_params_set_channels_near(capture_handle, hw_params, &alsa->actual_channels); snd_pcm_hw_params(capture_handle, hw_params); snd_pcm_hw_params_free(hw_params); snd_pcm_prepare(capture_handle); @@ -94,6 +92,7 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand alsa->actual_rate, alsa->actual_channels, alsa->target_rate, alsa->target_channels); } + return TRUE; } @@ -133,20 +132,25 @@ static BOOL audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size break; cframes = alsa->frames_per_packet - alsa->buffer_frames; + if (cframes > frames) cframes = frames; - memcpy(alsa->buffer + alsa->buffer_frames * tbytes_per_frame, - src, cframes * tbytes_per_frame); + + CopyMemory(alsa->buffer + alsa->buffer_frames * tbytes_per_frame, src, cframes * tbytes_per_frame); + alsa->buffer_frames += cframes; + if (alsa->buffer_frames >= alsa->frames_per_packet) { - if (alsa->wformat == 0x11) + if (alsa->wformat == WAVE_FORMAT_DVI_ADPCM) { alsa->dsp_context->encode_ima_adpcm(alsa->dsp_context, alsa->buffer, alsa->buffer_frames * tbytes_per_frame, alsa->target_channels, alsa->block_size); + encoded_data = alsa->dsp_context->adpcm_buffer; encoded_size = alsa->dsp_context->adpcm_size; + DEBUG_DVC("encoded %d to %d", alsa->buffer_frames * tbytes_per_frame, encoded_size); } @@ -162,11 +166,16 @@ static BOOL audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size frames = 0; } else + { ret = alsa->receive(encoded_data, encoded_size, alsa->user_data); + } + alsa->buffer_frames = 0; + if (!ret) break; } + src += cframes * tbytes_per_frame; frames -= cframes; } @@ -225,8 +234,10 @@ static void* audin_alsa_thread_func(void* arg) } while (0); free(buffer); + free(alsa->buffer); alsa->buffer = NULL; + if (capture_handle) snd_pcm_close(capture_handle); @@ -253,7 +264,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma { switch (format->wFormatTag) { - case 1: /* PCM */ + case WAVE_FORMAT_PCM: if (format->cbSize == 0 && (format->nSamplesPerSec <= 48000) && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && @@ -263,7 +274,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma } break; - case 0x11: /* IMA ADPCM */ + case WAVE_FORMAT_DVI_ADPCM: if ((format->nSamplesPerSec <= 48000) && (format->wBitsPerSample == 4) && (format->nChannels == 1 || format->nChannels == 2)) @@ -272,6 +283,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma } break; } + return FALSE; } @@ -284,9 +296,10 @@ static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN alsa->actual_rate = format->nSamplesPerSec; alsa->target_channels = format->nChannels; alsa->actual_channels = format->nChannels; + switch (format->wFormatTag) { - case 1: /* PCM */ + case WAVE_FORMAT_PCM: switch (format->wBitsPerSample) { case 8: @@ -300,7 +313,7 @@ static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN } break; - case 0x11: /* IMA ADPCM */ + case WAVE_FORMAT_DVI_ADPCM: alsa->format = SND_PCM_FORMAT_S16_LE; alsa->bytes_per_channel = 2; bs = (format->nBlockAlign - 4 * format->nChannels) * 4; @@ -310,6 +323,7 @@ static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN alsa->frames_per_packet); break; } + alsa->wformat = format->wFormatTag; alsa->block_size = format->nBlockAlign; } diff --git a/channels/client/channels.c b/channels/client/channels.c index e6038cf47..e31d052b4 100644 --- a/channels/client/channels.c +++ b/channels/client/channels.c @@ -505,6 +505,7 @@ static rdpChannels* freerdp_channels_find_by_instance(freerdp* instance) for (channels_list = g_channels_list; channels_list; channels_list = channels_list->next) { channels = channels_list->channels; + if (channels->instance == instance) { ReleaseMutex(g_mutex_list); @@ -709,13 +710,13 @@ static UINT32 FREERDP_CC MyVirtualChannelOpen(void* pInitHandle, UINT32* pOpenHa channels = ((rdpInitHandle*) pInitHandle)->channels; - if (pOpenHandle == 0) + if (!pOpenHandle) { DEBUG_CHANNELS("error bad channel handle"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } - if (pChannelOpenEventProc == 0) + if (!pChannelOpenEventProc) { DEBUG_CHANNELS("error bad proc"); return CHANNEL_RC_BAD_PROC; @@ -729,7 +730,7 @@ static UINT32 FREERDP_CC MyVirtualChannelOpen(void* pInitHandle, UINT32* pOpenHa lchannel_data = freerdp_channels_find_channel_data_by_name(channels, pChannelName, &index); - if (lchannel_data == 0) + if (!lchannel_data) { DEBUG_CHANNELS("error channel name"); return CHANNEL_RC_UNKNOWN_CHANNEL_NAME; @@ -803,13 +804,13 @@ static UINT32 FREERDP_CC MyVirtualChannelWrite(UINT32 openHandle, void* pData, U return CHANNEL_RC_NOT_CONNECTED; } - if (pData == 0) + if (!pData) { DEBUG_CHANNELS("error bad pData"); return CHANNEL_RC_NULL_DATA; } - if (dataLength == 0) + if (!dataLength) { DEBUG_CHANNELS("error bad dataLength"); return CHANNEL_RC_ZERO_LENGTH; @@ -851,7 +852,7 @@ static UINT32 FREERDP_CC MyVirtualChannelEventPush(UINT32 openHandle, RDP_EVENT* channels = freerdp_channels_find_by_open_handle(openHandle, &index); - if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) + if ((!channels) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) { DEBUG_CHANNELS("error bad channels handle"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; @@ -863,7 +864,7 @@ static UINT32 FREERDP_CC MyVirtualChannelEventPush(UINT32 openHandle, RDP_EVENT* return CHANNEL_RC_NOT_CONNECTED; } - if (event == NULL) + if (!event) { DEBUG_CHANNELS("error bad event"); return CHANNEL_RC_NULL_DATA; @@ -888,6 +889,7 @@ static UINT32 FREERDP_CC MyVirtualChannelEventPush(UINT32 openHandle, RDP_EVENT* } channels->event = event; + /* set the event */ SetEvent(channels->signal); @@ -1144,15 +1146,15 @@ int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int dat channels = freerdp_channels_find_by_instance(instance); - if (channels == 0) + if (!channels) { DEBUG_CHANNELS("could not find channel manager"); return 1; } - lrdp_channel = freerdp_channels_find_channel_by_id(channels, instance->settings, - channel_id, &index); - if (lrdp_channel == 0) + lrdp_channel = freerdp_channels_find_channel_by_id(channels, instance->settings, channel_id, &index); + + if (!lrdp_channel) { DEBUG_CHANNELS("could not find channel id"); return 1; @@ -1160,7 +1162,7 @@ int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int dat lchannel_data = freerdp_channels_find_channel_data_by_name(channels, lrdp_channel->Name, &index); - if (lchannel_data == 0) + if (!lchannel_data) { DEBUG_CHANNELS("could not find channel name"); return 1; @@ -1245,10 +1247,10 @@ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instan lrdp_channel = freerdp_channels_find_channel_by_name(channels, instance->settings, lchannel_data->name, &item->Index); - if (lrdp_channel != NULL) + if (lrdp_channel) instance->SendChannelData(instance, lrdp_channel->ChannelId, item->Data, item->DataLength); - if (lchannel_data->open_event_proc != 0) + if (lchannel_data->open_event_proc) { lchannel_data->open_event_proc(lchannel_data->open_handle, CHANNEL_EVENT_WRITE_COMPLETE, item->UserData, sizeof(void*), sizeof(void*), 0); diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index fd718e881..6327e55b6 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -40,16 +40,18 @@ #include #include #include -#include #include #include "rdpsnd_main.h" +#define TIME_DELAY_MS 250 + struct rdpsnd_plugin { rdpSvcPlugin plugin; wMessagePipe* MsgPipe; + HANDLE thread; BYTE cBlockNo; rdpsndFormat* supported_formats; @@ -77,35 +79,44 @@ struct rdpsnd_plugin rdpsndDevicePlugin* device; }; -/* process the linked list of data that has queued to be sent */ -static void rdpsnd_process_interval(rdpSvcPlugin* plugin) +static void* rdpsnd_schedule_thread(void* arg) { STREAM* data; wMessage message; + UINT16 wTimeDiff; UINT16 wTimeStamp; UINT16 wCurrentTime; - rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin; + rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg; - while (MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, FALSE)) + while (1) { + if (!MessageQueue_Wait(rdpsnd->MsgPipe->Out)) + break; + + if (!MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE)) + break; + if (message.id == WMQ_QUIT) break; wTimeStamp = (UINT16) (size_t) message.lParam; wCurrentTime = (UINT16) GetTickCount(); + //printf("wTimeStamp: %d wCurrentTime: %d\n", wTimeStamp, wCurrentTime); + if (wCurrentTime <= wTimeStamp) - break; - - if (MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE)) { - data = (STREAM*) message.wParam; - svc_plugin_send(plugin, data); - - DEBUG_SVC("processed output data"); + wTimeDiff = wTimeStamp - wCurrentTime; + //printf("Sleeping %d ms\n", wTimeDiff); + Sleep(wTimeDiff); } + + data = (STREAM*) message.wParam; + svc_plugin_send((rdpSvcPlugin*) rdpsnd, data); + DEBUG_SVC("processed output data"); } +#if 0 if (rdpsnd->is_open && (rdpsnd->close_timestamp > 0)) { if (GetTickCount() > rdpsnd->close_timestamp) @@ -119,9 +130,9 @@ static void rdpsnd_process_interval(rdpSvcPlugin* plugin) DEBUG_SVC("processed close"); } } +#endif - if ((MessageQueue_Size(rdpsnd->MsgPipe->Out) == 0) && !rdpsnd->is_open) - rdpsnd->plugin.interval_ms = 0; + return NULL; } static void rdpsnd_free_supported_formats(rdpsndPlugin* rdpsnd) @@ -339,7 +350,6 @@ static void rdpsnd_process_message_wave_info(rdpsndPlugin* rdpsnd, STREAM* data_ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in) { STREAM* data; - UINT32 delay_ms; UINT16 wTimeStamp; rdpsnd->expectingWave = 0; @@ -357,11 +367,7 @@ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in) IFCALL(rdpsnd->device->Play, rdpsnd->device, stream_get_head(data_in), stream_get_size(data_in)); } - delay_ms = 250; - wTimeStamp = rdpsnd->wTimeStamp + delay_ms; - - DEBUG_SVC("data_size %d delay_ms %u process_ms %u", - stream_get_size(data_in), delay_ms, process_ms); + wTimeStamp = rdpsnd->wTimeStamp + TIME_DELAY_MS; data = stream_new(8); stream_write_BYTE(data, SNDC_WAVECONFIRM); @@ -371,10 +377,8 @@ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in) stream_write_BYTE(data, rdpsnd->cBlockNo); /* cConfirmedBlockNo */ stream_write_BYTE(data, 0); /* bPad */ - wTimeStamp = rdpsnd->wave_timestamp + delay_ms; + wTimeStamp = rdpsnd->wave_timestamp + TIME_DELAY_MS; MessageQueue_Post(rdpsnd->MsgPipe->Out, NULL, 0, (void*) data, (void*) (size_t) wTimeStamp); - - rdpsnd->plugin.interval_ms = 10; } static void rdpsnd_process_message_close(rdpsndPlugin* rdpsnd) @@ -387,7 +391,6 @@ static void rdpsnd_process_message_close(rdpsndPlugin* rdpsnd) } rdpsnd->close_timestamp = GetTickCount() + 2000; - rdpsnd->plugin.interval_ms = 10; } static void rdpsnd_process_message_setvolume(rdpsndPlugin* rdpsnd, STREAM* data_in) @@ -405,7 +408,7 @@ static void rdpsnd_process_message_setvolume(rdpsndPlugin* rdpsnd, STREAM* data_ static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) { - rdpsndPlugin* rdpsnd = (rdpsndPlugin*)plugin; + rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin; BYTE msgType; UINT16 BodySize; @@ -573,11 +576,10 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin) DEBUG_SVC("connecting"); - plugin->interval_callback = rdpsnd_process_interval; - rdpsnd->latency = -1; rdpsnd->MsgPipe = MessagePipe_New(); + rdpsnd->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread, (void*) plugin, 0, NULL); args = (ADDIN_ARGV*) plugin->channel_entry_points.pExtendedData; diff --git a/channels/sample/client/sample_main.c b/channels/sample/client/sample_main.c index 77f176ca0..0c8d3571d 100644 --- a/channels/sample/client/sample_main.c +++ b/channels/sample/client/sample_main.c @@ -45,14 +45,8 @@ struct sample_plugin rdpSvcPlugin plugin; /* put your private data here */ - }; -static void sample_process_interval(rdpSvcPlugin* plugin) -{ - printf("sample_process_interval:\n"); -} - static void sample_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) { int bytes; @@ -61,17 +55,18 @@ static void sample_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) printf("sample_process_receive:\n"); - if (sample == NULL) + if (!sample) { printf("sample_process_receive: sample is nil\n"); return; } - /* process data in(from server) here */ + /* process data in (from server) here */ /* here we just send the same data back */ bytes = stream_get_size(data_in); printf("sample_process_receive: got bytes %d\n", bytes); + if (bytes > 0) { data_out = stream_new(bytes); @@ -95,22 +90,15 @@ static void sample_process_connect(rdpSvcPlugin* plugin) printf("sample_process_connect:\n"); - if (sample == NULL) - { + if (!sample) return; - } - - /* if you want a call from channel thread once is a while do this */ - plugin->interval_ms = 1000; - plugin->interval_callback = sample_process_interval; - } static void sample_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { printf("sample_process_event:\n"); - /* events comming from main freerdp window to plugin */ + /* events coming from main freerdp window to plugin */ /* send them back with svc_plugin_send_event */ freerdp_event_free(event); @@ -118,14 +106,12 @@ static void sample_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) static void sample_process_terminate(rdpSvcPlugin* plugin) { - samplePlugin* sample = (samplePlugin*)plugin; + samplePlugin* sample = (samplePlugin*) plugin; printf("sample_process_terminate:\n"); - if (sample == NULL) - { + if (!sample) return; - } /* put your cleanup here */ diff --git a/include/freerdp/utils/svc_plugin.h b/include/freerdp/utils/svc_plugin.h index dcce97530..ca792f8e7 100644 --- a/include/freerdp/utils/svc_plugin.h +++ b/include/freerdp/utils/svc_plugin.h @@ -43,12 +43,9 @@ struct rdp_svc_plugin CHANNEL_ENTRY_POINTS_EX channel_entry_points; CHANNEL_DEF channel_def; - int interval_ms; - void (*connect_callback)(rdpSvcPlugin* plugin); void (*receive_callback)(rdpSvcPlugin* plugin, STREAM* data_in); void (*event_callback)(rdpSvcPlugin* plugin, RDP_EVENT* event); - void (*interval_callback)(rdpSvcPlugin* plugin); void (*terminate_callback)(rdpSvcPlugin* plugin); HANDLE thread; diff --git a/libfreerdp/core/channel.c b/libfreerdp/core/channel.c index b9bccc941..ba9240241 100644 --- a/libfreerdp/core/channel.c +++ b/libfreerdp/core/channel.c @@ -50,7 +50,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) } } - if (channel == NULL) + if (!channel) { printf("freerdp_channel_send: unknown channel_id %d\n", channel_id); return FALSE; @@ -58,6 +58,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) flags = CHANNEL_FLAG_FIRST; left = size; + while (left > 0) { s = rdp_send_stream_init(rdp); @@ -71,6 +72,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) chunk_size = left; flags |= CHANNEL_FLAG_LAST; } + if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL)) { flags |= CHANNEL_FLAG_SHOW_PROTOCOL; @@ -97,14 +99,16 @@ BOOL freerdp_channel_process(freerdp* instance, STREAM* s, UINT16 channel_id) UINT32 flags; int chunk_length; - if(stream_get_left(s) < 8) + if (stream_get_left(s) < 8) return FALSE; + stream_read_UINT32(s, length); stream_read_UINT32(s, flags); chunk_length = stream_get_left(s); IFCALL(instance->ReceiveChannelData, instance, channel_id, stream_get_tail(s), chunk_length, flags, length); + return TRUE; } diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index eb39d6a4c..544a9dd9e 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -420,6 +420,7 @@ BOOL rdp_send(rdpRdp* rdp, STREAM* s, UINT16 channel_id) length += rdp_security_stream_out(rdp, s, length); stream_set_pos(s, length); + if (transport_write(rdp->transport, s) < 0) return FALSE; diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index f03cca1ed..f0ccf6338 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -189,15 +189,8 @@ static void* svc_plugin_thread_func(void* arg) while (1) { - if (plugin->interval_ms > 0) - { - Sleep(plugin->interval_ms); - } - else - { - if (!MessageQueue_Wait(plugin->MsgPipe->In)) - break; - } + if (!MessageQueue_Wait(plugin->MsgPipe->In)) + break; if (MessageQueue_Peek(plugin->MsgPipe->In, &message, TRUE)) { @@ -215,9 +208,6 @@ static void* svc_plugin_thread_func(void* arg) IFCALL(plugin->event_callback, plugin, event); } } - - if (plugin->interval_ms > 0) - IFCALL(plugin->interval_callback, plugin); } DEBUG_SVC("out");