All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Kővágó, Zoltán" <dirty.ice.hu@gmail.com>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>, KJ Liew <liewkj@yahoo.com>
Subject: [PATCH] audio/dsound: fix invalid parameters error
Date: Mon,  3 Feb 2020 00:02:23 +0100	[thread overview]
Message-ID: <fe9744216d9d421a2dbb09bcf5fa0dbd18f77ac5.1580684275.git.DirtY.iCE.hu@gmail.com> (raw)

Windows (unlike wine) bails out when IDirectSoundBuffer8::Lock is called
with zero length.  Also, hw->pos_emul handling was incorrect when
calling this function for the first time.

Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
Reported-by: KJ Liew <liewkj@yahoo.com>
---

I've tested this patch on wine and a borrowed Windows 8.1 laptop, I
could only test audio playback, not recording.  I've cross-compiled qemu
using the docker image, for 64-bit.

---
 audio/dsound_template.h |  1 +
 audio/audio.c           |  6 ++----
 audio/dsoundaudio.c     | 27 +++++++++++++++++++++++----
 3 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/audio/dsound_template.h b/audio/dsound_template.h
index 7a15f91ce5..9c5ce625ab 100644
--- a/audio/dsound_template.h
+++ b/audio/dsound_template.h
@@ -244,6 +244,7 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
         goto fail0;
     }
 
+    ds->first_time = true;
     obt_as.endianness = 0;
     audio_pcm_init_info (&hw->info, &obt_as);
 
diff --git a/audio/audio.c b/audio/audio.c
index f63f39769a..cb1efc6dc5 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1076,10 +1076,8 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
     while (live) {
         size_t size, decr, proc;
         void *buf = hw->pcm_ops->get_buffer_out(hw, &size);
-        if (!buf) {
-            /* retrying will likely won't help, drop everything. */
-            hw->mix_buf->pos = (hw->mix_buf->pos + live) % hw->mix_buf->size;
-            return clipped + live;
+        if (!buf || size == 0) {
+            break;
         }
 
         decr = MIN(size / hw->info.bytes_per_frame, live);
diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c
index c265c0094b..bd57082a8d 100644
--- a/audio/dsoundaudio.c
+++ b/audio/dsoundaudio.c
@@ -53,12 +53,14 @@ typedef struct {
 typedef struct {
     HWVoiceOut hw;
     LPDIRECTSOUNDBUFFER dsound_buffer;
+    bool first_time;
     dsound *s;
 } DSoundVoiceOut;
 
 typedef struct {
     HWVoiceIn hw;
     LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
+    bool first_time;
     dsound *s;
 } DSoundVoiceIn;
 
@@ -414,21 +416,32 @@ 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, wpos, act_size;
     size_t req_size;
     int err;
     void *ret;
 
-    hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, NULL);
+    hr = IDirectSoundBuffer_GetCurrentPosition(
+        dsb, &ppos, ds->first_time ? &wpos : NULL);
     if (FAILED(hr)) {
         dsound_logerr(hr, "Could not get playback buffer position\n");
         *size = 0;
         return NULL;
     }
 
+    if (ds->first_time) {
+        hw->pos_emul = wpos;
+        ds->first_time = false;
+    }
+
     req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
     req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
 
+    if (req_size == 0) {
+        *size = 0;
+        return NULL;
+    }
+
     err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
                           &act_size, NULL, false, ds->s);
     if (err) {
@@ -508,18 +521,24 @@ static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size)
     DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
     LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
     HRESULT hr;
-    DWORD cpos, act_size;
+    DWORD cpos, rpos, act_size;
     size_t req_size;
     int err;
     void *ret;
 
-    hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, &cpos, NULL);
+    hr = IDirectSoundCaptureBuffer_GetCurrentPosition(
+        dscb, &cpos, ds->first_time ? &rpos : NULL);
     if (FAILED(hr)) {
         dsound_logerr(hr, "Could not get capture buffer position\n");
         *size = 0;
         return NULL;
     }
 
+    if (ds->first_time) {
+        hw->pos_emul = rpos;
+        ds->first_time = false;
+    }
+
     req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul);
     req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
 
-- 
2.25.0



             reply	other threads:[~2020-02-02 23:03 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-02 23:02 Kővágó, Zoltán [this message]
2020-02-03  7:56 ` [PATCH] audio/dsound: fix invalid parameters error Howard Spoelstra
2020-02-03  9:18   ` Philippe Mathieu-Daudé
2020-02-03  9:25     ` Howard Spoelstra
2020-02-06 13:38 ` Gerd Hoffmann
     [not found] <20200117182621.GB13724.ref@chuwi-lt0>
2020-01-17 18:26 ` KJ Liew
2020-01-18  6:30   ` Philippe Mathieu-Daudé
2020-01-27  1:46     ` Zoltán Kővágó
2020-01-31  7:55       ` Gerd Hoffmann
2020-02-01 18:28       ` KJ Liew

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=fe9744216d9d421a2dbb09bcf5fa0dbd18f77ac5.1580684275.git.DirtY.iCE.hu@gmail.com \
    --to=dirty.ice.hu@gmail.com \
    --cc=kraxel@redhat.com \
    --cc=liewkj@yahoo.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.