From: "Zoltán Kővágó" <dirty.ice.hu@gmail.com>
To: "Philippe Mathieu-Daudé" <philmd@redhat.com>,
"KJ Liew" <liewkj@yahoo.com>,
"QEMU Developers" <qemu-devel@nongnu.org>,
"Gerd Hoffmann" <kraxel@redhat.com>
Subject: Re: [PATCH] audio/dsound: fix invalid parameters error
Date: Mon, 27 Jan 2020 02:46:58 +0100 [thread overview]
Message-ID: <2b889c2c-04ac-c6ef-ae3e-2901492a2824@gmail.com> (raw)
In-Reply-To: <29987343-f835-2280-4457-067d970c9c5e@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 4917 bytes --]
On 2020-01-18 07:30, Philippe Mathieu-Daudé wrote:
> On 1/17/20 7:26 PM, KJ Liew wrote:
>> QEMU Windows has broken dsound backend since the rewrite of audio API in
>> version 4.2.0. Both playback and capture buffers failed to lock with
>> invalid parameters error.
>
> Fixes: 7fa9754ac88 (dsoundaudio: port to the new audio backend api)
Hmm, I see the old code specified those parameters, but MSDN reads:
If the application passes NULL for the ppvAudioPtr2 and pdwAudioBytes2
parameters, the lock extends no further than the end of the buffer and
does not wrap.
Looks like this means that if the lock doesn't fit in the buffer it
fails instead of truncating it. I'm sure I tested the code under wine,
and probably in a win8.1 vm too, and it worked there, maybe it's
dependent on the windows version or sound driver?
>
> Cc'ing Zoltán who wrote 7fa9754ac88, and Gerd (the maintainer of this
> file):
>
> $ ./scripts/get_maintainer.pl -f audio/dsoundaudio.c
> Gerd Hoffmann <kraxel@redhat.com> (maintainer:Audio)
>
>> --- ../orig/qemu-4.2.0/audio/dsoundaudio.c 2019-12-12
>> 10:20:47.000000000 -0800
>> +++ ../qemu-4.2.0/audio/dsoundaudio.c 2020-01-17 08:05:46.783966900
>> -0800
>> @@ -53,6 +53,7 @@
>> typedef struct {
>> HWVoiceOut hw;
>> LPDIRECTSOUNDBUFFER dsound_buffer;
>> + void *last_buf;
>> dsound *s;
>> } DSoundVoiceOut;
>> @@ -414,10 +415,10 @@
>> DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
>> LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
>> HRESULT hr;
>> - DWORD ppos, act_size;
>> + DWORD ppos, act_size, last_size;
>> size_t req_size;
>> int err;
>> - void *ret;
>> + void *ret, *last_ret;
>> hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, NULL);
>> if (FAILED(hr)) {
>> @@ -426,17 +427,24 @@
>> return NULL;
>> }
>> + if (ppos == hw->pos_emul) {
>> + *size = 0;
>> + return ds->last_buf;
>> + }
>> +
>> req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
>> req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
>> - err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size,
>> &ret, NULL,
>> - &act_size, NULL, false, ds->s);
>> + err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size,
>> &ret, &last_ret,
>> + &act_size, &last_size, false, ds->s);
>> if (err) {
>> dolog("Failed to lock buffer\n");
>> *size = 0;
>> return NULL;
>> }
>> + ds->last_buf = g_realloc(ds->last_buf, act_size);
>> + memcpy(ds->last_buf, ret, act_size);
>> *size = act_size;
>> return ret;
>> }
I don't really understand what's happening here, why do you need that
memory allocation and memcpy? This function should return a buffer
where the caller will write data, that *size = 0; when returning
ds->last_buf also looks incorrect to me (the calling function won't
write anything into it).
I'm attaching a patch with a probably better (and totally untested) way
to do this (if someone can tell me how to copy-paste a patch into
thunderbird without it messing up long lines, please tell me).
>> @@ -445,6 +453,8 @@
>> {
>> DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
>> LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
>> + if (len == 0)
>> + return 0;
>> int err = dsound_unlock_out(dsb, buf, NULL, len, 0);
>> if (err) {
Msdn says "The second pointer is needed even if nothing was written to
the second pointer." so that NULL doesn't look okay.
>> @@ -508,10 +518,10 @@
>> DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
>> LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
>> HRESULT hr;
>> - DWORD cpos, act_size;
>> + DWORD cpos, act_size, last_size;
>> size_t req_size;
>> int err;
>> - void *ret;
>> + void *ret, *last_ret;
>> hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, &cpos,
>> NULL);
>> if (FAILED(hr)) {
>> @@ -520,11 +530,16 @@
>> return NULL;
>> }
>> + if (cpos == hw->pos_emul) {
>> + *size = 0;
>> + return NULL;
>> + }
>> +
>> req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul);
>> req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
>> - err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size,
>> &ret, NULL,
>> - &act_size, NULL, false, ds->s);
>> + err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size,
>> &ret, &last_ret,
>> + &act_size, &last_size, false, ds->s);
>> if (err) {
>> dolog("Failed to lock buffer\n");
>> *size = 0;
>>
You're completely ignoring last_ret and last_size here. Don't you lose
samples here? I think it's possible to do something like I posted above
with output here.
Regards,
Zoltan
[-- Attachment #2: dsound.patch --]
[-- Type: text/x-patch, Size: 2389 bytes --]
diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c
index c265c0094b..b6bc241faa 100644
--- a/audio/dsoundaudio.c
+++ b/audio/dsoundaudio.c
@@ -53,6 +53,9 @@ typedef struct {
typedef struct {
HWVoiceOut hw;
LPDIRECTSOUNDBUFFER dsound_buffer;
+ void *buffer1, buffer2;
+ DWORD size1, size2;
+ bool has_remaining;
dsound *s;
} DSoundVoiceOut;
@@ -414,10 +417,16 @@ static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
HRESULT hr;
- DWORD ppos, act_size;
+ DWORD ppos, act_size1, act_size2;
size_t req_size;
int err;
- void *ret;
+ void *ret1, *ret2;
+
+ if (ds->has_remaining) {
+ ds->has_remaining = false;
+ *size = ds->size2;
+ return ds->buffer2;
+ }
hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, NULL);
if (FAILED(hr)) {
@@ -429,15 +438,20 @@ static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
- err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
- &act_size, NULL, false, ds->s);
+ err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret1, &ret2,
+ &act_size1, &act_size2, false, ds->s);
if (err) {
dolog("Failed to lock buffer\n");
*size = 0;
return NULL;
}
- *size = act_size;
+ *size = act_size1;
+ ds->buffer1 = ret1;
+ ds->buffer2 = ret2;
+ ds->size1 = act_size1;
+ ds->size2 = act_size2;
+ ds->has_remaining = ret2 != NULL;
return ret;
}
@@ -445,7 +459,16 @@ static size_t dsound_put_buffer_out(HWVoiceOut *hw, void *buf, size_t len)
{
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
- int err = dsound_unlock_out(dsb, buf, NULL, len, 0);
+ int err;
+
+ if (ds->has_remaining) {
+ ds->size1 = len;
+ hw->pos_emul = (hw->pos_emul + len) % hw->size_emul;
+ return len;
+ }
+
+ *(ds->buffer2 ? &ds->size2 : &ds->size1) = len;
+ err = dsound_unlock_out(dsb, ds->buffer1, ds->buffer2, ds->size1, ds->size2);
if (err) {
dolog("Failed to unlock buffer!!\n");
next prev parent reply other threads:[~2020-01-27 1:47 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20200117182621.GB13724.ref@chuwi-lt0>
2020-01-17 18:26 ` [PATCH] audio/dsound: fix invalid parameters error KJ Liew
2020-01-18 6:30 ` Philippe Mathieu-Daudé
2020-01-27 1:46 ` Zoltán Kővágó [this message]
2020-01-31 7:55 ` Gerd Hoffmann
2020-02-01 18:28 ` KJ Liew
2020-02-02 23:02 Kővágó, Zoltán
2020-02-03 7:56 ` Howard Spoelstra
2020-02-03 9:18 ` Philippe Mathieu-Daudé
2020-02-03 9:25 ` Howard Spoelstra
2020-02-06 13:38 ` Gerd Hoffmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2b889c2c-04ac-c6ef-ae3e-2901492a2824@gmail.com \
--to=dirty.ice.hu@gmail.com \
--cc=kraxel@redhat.com \
--cc=liewkj@yahoo.com \
--cc=philmd@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).