mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 16:34:18 +09:00
rdpsnd: add manual latency control for ALSA.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user