rdpsnd: add manual latency control for ALSA.

This commit is contained in:
Vic Lee
2011-09-25 11:41:37 +08:00
parent 123398c419
commit e5060dcaee
4 changed files with 42 additions and 21 deletions

View File

@@ -44,6 +44,7 @@ struct rdpsnd_alsa_plugin
int bytes_per_channel;
int wformat;
int block_size;
int latency;
ADPCM adpcm;
};
@@ -53,6 +54,7 @@ static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa)
snd_pcm_sw_params_t* sw_params;
int error;
snd_pcm_uframes_t frames;
snd_pcm_uframes_t start_threshold;
snd_pcm_drop(alsa->out_handle);
@@ -84,8 +86,13 @@ static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa)
return;
}
snd_pcm_sw_params_current(alsa->out_handle, sw_params);
snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params,
frames / 2);
if (alsa->latency < 0)
start_threshold = frames / 2;
else
start_threshold = alsa->latency * alsa->actual_rate / 1000;
if (start_threshold > frames)
start_threshold = frames;
snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, start_threshold);
snd_pcm_sw_params(alsa->out_handle, sw_params);
snd_pcm_sw_params_free(sw_params);
@@ -101,7 +108,7 @@ static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa)
}
}
static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format)
static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency)
{
rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device;
@@ -136,10 +143,12 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* for
alsa->block_size = format->nBlockAlign;
}
alsa->latency = latency;
rdpsnd_alsa_set_params(alsa);
}
static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, rdpsndFormat* format)
static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency)
{
rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device;
int error;
@@ -158,7 +167,7 @@ static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, rdpsndFormat* format)
else
{
memset(&alsa->adpcm, 0, sizeof(ADPCM));
rdpsnd_alsa_set_format(device, format);
rdpsnd_alsa_set_format(device, format, latency);
}
}
@@ -286,7 +295,7 @@ static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, uint8* data, int size)
DEBUG_WARN("error %d", error);
snd_pcm_close(alsa->out_handle);
alsa->out_handle = 0;
rdpsnd_alsa_open(device, NULL);
rdpsnd_alsa_open(device, NULL, alsa->latency);
break;
}
pindex += error * rbytes_per_frame;

View File

@@ -40,6 +40,7 @@ struct rdpsnd_pulse_plugin
pa_stream *stream;
int format;
int block_size;
int latency;
ADPCM adpcm;
};
@@ -220,23 +221,26 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, rdpsndFormat*
pulse->block_size = format->nBlockAlign;
}
static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format)
static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency)
{
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device;
pa_stream_state_t state;
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
if (!pulse->context || pulse->stream) {
DEBUG_WARN("pulse stream has been created.");
if (!pulse->context || pulse->stream)
{
DEBUG_WARN("pulse stream has been created.");
return;
}
rdpsnd_pulse_set_format_spec(pulse, format);
pulse->latency = latency;
if (pa_sample_spec_valid(&pulse->sample_spec) == 0) {
pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec);
DEBUG_WARN("Invalid sample spec %s", ss);
return;
if (pa_sample_spec_valid(&pulse->sample_spec) == 0)
{
pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec);
DEBUG_WARN("Invalid sample spec %s", ss);
return;
}
pa_threaded_mainloop_lock(pulse->mainloop);
@@ -358,7 +362,7 @@ static boolean rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndF
return False;
}
static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format)
static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency)
{
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device;
@@ -370,7 +374,7 @@ static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, rdpsndFormat* fo
pulse->stream = NULL;
pa_threaded_mainloop_unlock(pulse->mainloop);
}
rdpsnd_pulse_open(device, format);
rdpsnd_pulse_open(device, format, latency);
}
static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, uint32 value)
@@ -458,8 +462,8 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
data = pEntryPoints->plugin_data;
if (data && strcmp((char*)data->data[0], "pulse") == 0)
{
if(strlen((char*)data->data[1]) > 0)
pulse->device_name = xstrdup((char*)data->data[1]);
if(strlen((char*)data->data[1]) > 0)
pulse->device_name = xstrdup((char*)data->data[1]);
else
pulse->device_name = NULL;
}

View File

@@ -79,6 +79,7 @@ struct rdpsnd_plugin
uint16 fixed_format;
uint16 fixed_channel;
uint32 fixed_rate;
int latency;
/* Device plugin */
rdpsndDevicePlugin* device;
@@ -315,13 +316,15 @@ static void rdpsnd_process_message_wave_info(rdpsndPlugin* rdpsnd, STREAM* data_
rdpsnd->current_format = wFormatNo;
rdpsnd->is_open = True;
if (rdpsnd->device)
IFCALL(rdpsnd->device->Open, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo]);
IFCALL(rdpsnd->device->Open, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo],
rdpsnd->latency);
}
else if (wFormatNo != rdpsnd->current_format)
{
rdpsnd->current_format = wFormatNo;
if (rdpsnd->device)
IFCALL(rdpsnd->device->SetFormat, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo]);
IFCALL(rdpsnd->device->SetFormat, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo],
rdpsnd->latency);
}
}
@@ -480,6 +483,10 @@ static void rdpsnd_process_plugin_data(rdpsndPlugin* rdpsnd, RDP_PLUGIN_DATA* da
{
rdpsnd->fixed_channel = atoi(data->data[1]);
}
else if (strcmp((char*)data->data[0], "latency") == 0)
{
rdpsnd->latency = atoi(data->data[1]);
}
else
{
rdpsnd_load_device_plugin(rdpsnd, (char*)data->data[0], data);
@@ -497,6 +504,7 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
plugin->interval_callback = rdpsnd_process_interval;
rdpsnd->data_out_list = list_new();
rdpsnd->latency = -1;
data = (RDP_PLUGIN_DATA*)plugin->channel_entry_points.pExtendedData;
while (data && data->size > 0)

View File

@@ -37,8 +37,8 @@ struct rdpsnd_format
typedef struct rdpsnd_device_plugin rdpsndDevicePlugin;
typedef boolean (*pcFormatSupported) (rdpsndDevicePlugin* device, rdpsndFormat* format);
typedef void (*pcOpen) (rdpsndDevicePlugin* device, rdpsndFormat* format);
typedef void (*pcSetFormat) (rdpsndDevicePlugin* device, rdpsndFormat* format);
typedef void (*pcOpen) (rdpsndDevicePlugin* device, rdpsndFormat* format, int latency);
typedef void (*pcSetFormat) (rdpsndDevicePlugin* device, rdpsndFormat* format, int latency);
typedef void (*pcSetVolume) (rdpsndDevicePlugin* device, uint32 value);
typedef void (*pcPlay) (rdpsndDevicePlugin* device, uint8* data, int size);
typedef void (*pcStart) (rdpsndDevicePlugin* device);