static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, uint8* data, int size) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; int len; int ret; uint8* decoded_data; uint8* src; int decoded_size; if (!pulse->stream) return; if (pulse->format == 0x11) { decoded_data = dsp_decode_ima_adpcm(&pulse->adpcm, data, size, pulse->sample_spec.channels, pulse->block_size, &decoded_size); size = decoded_size; src = decoded_data; } else { decoded_data = NULL; src = data; } pa_threaded_mainloop_lock(pulse->mainloop); while (size > 0) { while ((len = pa_stream_writable_size(pulse->stream)) == 0) { pa_threaded_mainloop_wait(pulse->mainloop); } if (len < 0) break; if (len > size) len = size; ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE); if (ret < 0) { DEBUG_WARN("pa_stream_write failed (%d)", pa_context_errno(pulse->context)); break; } src += len; size -= len; } pa_threaded_mainloop_unlock(pulse->mainloop); if (decoded_data) xfree(decoded_data); }
static void rdpsnd_sles_play(rdpsndDevicePlugin* device, uint8* data, int size) { log_debug("rdpsnd_sles_play : data = %X - size = %d", (unsigned int)data, size); rdpsndSlesPlugin* sles = (rdpsndSlesPlugin*)device; if(!sles->bufferQueueItf) return; if(!data) return; pthread_mutex_lock(&sles->mutex); if (sles->formatTag == 0x11) { int decoded_size; //log_debug("rdpsnd_sles_play : decode ImaAdpcm"); uint8* decoded_data = dsp_decode_ima_adpcm(&sles->adpcm, (uint8 *) data, size, sles->format.numChannels, sles->adpcmBlockAlign, &decoded_size); sles->next_size = decoded_size; if (decoded_size > sles->data_max) { log_debug("rdpsnd_sles_play : realloc %d => %d", sles->data_max, decoded_size); sles->data_max = decoded_size; sles->data_next = realloc(sles->data_next, decoded_size); sles->data_play = realloc(sles->data_play, decoded_size); } memcpy(sles->data_next, decoded_data, decoded_size); free(decoded_data); } else { if (size > sles->data_max) { log_debug("rdpsnd_sles_play : realloc %d => %d", sles->data_max, size); sles->data_max = size; sles->data_next = realloc(sles->data_next, size); sles->data_play = realloc(sles->data_play, size); } memcpy(sles->data_next, data, size); sles->next_size = size; } if (!sles->playing) { swap_streams_and_play(sles); } pthread_mutex_unlock(&sles->mutex); }
static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, uint8* data, int size) { rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; uint8* decoded_data; int decoded_size; uint8* src; uint8* resampled_data; int len; int error; int frames; int rbytes_per_frame; int sbytes_per_frame; uint8* pindex; uint8* end; if (alsa->out_handle == 0) return; if (alsa->wformat == 0x11) { decoded_data = dsp_decode_ima_adpcm(&alsa->adpcm, data, size, alsa->source_channels, alsa->block_size, &decoded_size); size = decoded_size; src = decoded_data; } else { decoded_data = NULL; src = data; } sbytes_per_frame = alsa->source_channels * alsa->bytes_per_channel; rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; if ((size % sbytes_per_frame) != 0) { DEBUG_WARN("error len mod"); return; } if ((alsa->source_rate == alsa->actual_rate) && (alsa->source_channels == alsa->actual_channels)) { resampled_data = NULL; } else { resampled_data = dsp_resample(src, alsa->bytes_per_channel, alsa->source_channels, alsa->source_rate, size / sbytes_per_frame, alsa->actual_channels, alsa->actual_rate, &frames); DEBUG_SVC("resampled %d frames at %d to %d frames at %d", size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate); size = frames * rbytes_per_frame; src = resampled_data; } pindex = src; end = pindex + size; while (pindex < end) { len = end - pindex; frames = len / rbytes_per_frame; error = snd_pcm_writei(alsa->out_handle, pindex, frames); if (error == -EPIPE) { snd_pcm_recover(alsa->out_handle, error, 0); error = 0; } else if (error < 0) { DEBUG_WARN("error %d", error); snd_pcm_close(alsa->out_handle); alsa->out_handle = 0; rdpsnd_alsa_open(device, NULL, alsa->latency); break; } pindex += error * rbytes_per_frame; } if (resampled_data) xfree(resampled_data); if (decoded_data) xfree(decoded_data); }