channels/rdpsnd: refactor scheduling of sending of sound PDUs

This commit is contained in:
Marc-André Moreau 2013-02-20 21:34:47 -05:00
parent 41fbdbeb0d
commit 7a289423c0
8 changed files with 90 additions and 94 deletions
channels
audin/client/alsa
client
rdpsnd/client
sample/client
include/freerdp/utils
libfreerdp

View File

@ -33,6 +33,7 @@
#include <freerdp/addin.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/utils/thread.h>
#include <freerdp/channels/rdpsnd.h>
#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;
}

View File

@ -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);

View File

@ -40,16 +40,18 @@
#include <freerdp/addin.h>
#include <freerdp/constants.h>
#include <freerdp/utils/stream.h>
#include <freerdp/utils/list.h>
#include <freerdp/utils/svc_plugin.h>
#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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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");