mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 02:03:56 -06:00
paaudio: try to drain the recording stream
There is no guarantee a single call to pa_stream_peek every timer_period microseconds can read a recording stream faster than the data gets produced at the source. Let qpa_read try to drain the recording stream. To reproduce the problem: Start qemu with -audiodev pa,id=audio0,in.mixing-engine=off On the host connect the qemu recording stream to the monitor of a hardware output device. While the problem can also be seen with a hardware input device, it's obvious with the monitor of a hardware output device. In the guest start audio recording with audacity and notice the slow recording data rate. Signed-off-by: Volker Rümelin <vr_qemu@t-online.de> Message-id: 20200104091122.13971-4-vr_qemu@t-online.de Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
4db3e634c7
commit
acc3b63e1b
1 changed files with 25 additions and 16 deletions
|
@ -156,34 +156,43 @@ static size_t qpa_read(HWVoiceIn *hw, void *data, size_t length)
|
||||||
{
|
{
|
||||||
PAVoiceIn *p = (PAVoiceIn *) hw;
|
PAVoiceIn *p = (PAVoiceIn *) hw;
|
||||||
PAConnection *c = p->g->conn;
|
PAConnection *c = p->g->conn;
|
||||||
size_t l;
|
size_t total = 0;
|
||||||
int r;
|
|
||||||
|
|
||||||
pa_threaded_mainloop_lock(c->mainloop);
|
pa_threaded_mainloop_lock(c->mainloop);
|
||||||
|
|
||||||
CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
|
CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
|
||||||
"pa_threaded_mainloop_lock failed\n");
|
"pa_threaded_mainloop_lock failed\n");
|
||||||
|
|
||||||
if (!p->read_length) {
|
while (total < length) {
|
||||||
r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
|
size_t l;
|
||||||
CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
|
int r;
|
||||||
"pa_stream_peek failed\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
l = MIN(p->read_length, length);
|
if (!p->read_length) {
|
||||||
memcpy(data, p->read_data, l);
|
r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
|
||||||
|
CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
|
||||||
|
"pa_stream_peek failed\n");
|
||||||
|
if (!p->read_length) {
|
||||||
|
/* buffer is empty */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p->read_data += l;
|
l = MIN(p->read_length, length - total);
|
||||||
p->read_length -= l;
|
memcpy((char *)data + total, p->read_data, l);
|
||||||
|
|
||||||
if (!p->read_length) {
|
p->read_data += l;
|
||||||
r = pa_stream_drop(p->stream);
|
p->read_length -= l;
|
||||||
CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
|
total += l;
|
||||||
"pa_stream_drop failed\n");
|
|
||||||
|
if (!p->read_length) {
|
||||||
|
r = pa_stream_drop(p->stream);
|
||||||
|
CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
|
||||||
|
"pa_stream_drop failed\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_threaded_mainloop_unlock(c->mainloop);
|
pa_threaded_mainloop_unlock(c->mainloop);
|
||||||
return l;
|
return total;
|
||||||
|
|
||||||
unlock_and_fail:
|
unlock_and_fail:
|
||||||
pa_threaded_mainloop_unlock(c->mainloop);
|
pa_threaded_mainloop_unlock(c->mainloop);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue