All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Wischer, Timo (ADITG/ESB)" <twischer@de.adit-jv.com>
To: "patch@alsa-project.org" <patch@alsa-project.org>
Cc: Takashi Iwai <tiwai@suse.de>,
	"alsa-devel@alsa-project.org" <alsa-devel@alsa-project.org>
Subject: Re: [PATCH - JACK PCM plugin] jack: Do not Xrun the ALSA buffer
Date: Mon, 26 Feb 2018 08:14:11 +0000	[thread overview]
Message-ID: <B0FB33DC1499054591F62C0EF1E013D7684FB83A@HI2EXCH01.adit-jv.com> (raw)
In-Reply-To: <1516794784-9993-1-git-send-email-twischer@de.adit-jv.com>

Hello all,

Due to merged [1] (see [2]) [3] can be merged without conflicts, now.

@Takashi: Thanks for merging [2].

Please give a feedback if there is anything which has to be changed.

The biggest change in snd_pcm_jack_process_cb() occurs 
due to the movement of the snd_pcm_area_silence() call to the end of this function.
This is required to fill the buffer with silence if there is not enough audio data available for JACK.

[1] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-January/130986.html
[2] http://git.alsa-project.org/?p=alsa-plugins.git;a=commit;h=3e6ace6fe045c580dc5490d87eff6b616f7769ef
[3] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-January/130987.html

Best regards

Timo Wischer

Advanced Driver Information Technology GmbH
Engineering Software Base (ADITG/ESB)
Robert-Bosch-Str. 200
31139 Hildesheim
Germany

Tel. +49 5121 49 6938
Fax +49 5121 49 6999
twischer@de.adit-jv.com

ADIT is a joint venture company of Robert Bosch GmbH/Robert Bosch Car Multimedia GmbH and DENSO Corporation
Sitz: Hildesheim, Registergericht: Amtsgericht Hildesheim HRB 3438
Geschäftsführung: Wilhelm Grabow, Ken Yaguchi

________________________________________
From: Wischer, Timo (ADITG/ESB)
Sent: Wednesday, January 24, 2018 12:53 PM
To: patch@alsa-project.org
Cc: alsa-devel@alsa-project.org; Wischer, Timo (ADITG/ESB)
Subject: [PATCH - JACK PCM plugin] jack: Do not Xrun the ALSA buffer

From: Timo Wischer <twischer@de.adit-jv.com>

when the JACK thread is requesting too many audio frames

Playback:
Without this commit the ALSA audio buffer
will be played with endless repeats as long as the user application
has not provided new audio data.
Therefore this garbage will be played as long as the user application
has not called snd_pcm_stop() after an Xrun.
With this fix the rest of the JACK buffer will be filled
with silence.

Capture:
Without this commit the audio data in the ALSA buffer would be
overwritten.
With this commit the new data from the JACK buffer
will not be copied.
Therefore the existing data in the ALSA buffer
will not be overwritten.

Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
---

This patch is depending on
http://mailman.alsa-project.org/pipermail/alsa-devel/2018-January/130986.html


diff --git a/jack/pcm_jack.c b/jack/pcm_jack.c
index c22a5d0..a4f35f4 100644
--- a/jack/pcm_jack.c
+++ b/jack/pcm_jack.c
@@ -54,6 +54,68 @@ typedef struct {

 static int snd_pcm_jack_stop(snd_pcm_ioplug_t *io);

+
+static inline snd_pcm_uframes_t snd_pcm_jack_playback_avail(const snd_pcm_ioplug_t* const io,
+                                                            const snd_pcm_uframes_t hw_ptr,
+                                                            const snd_pcm_uframes_t appl_ptr)
+{
+       const snd_pcm_jack_t* const jack = io->private_data;
+
+       /* cannot use io->hw_ptr without calling snd_pcm_avail_update()
+        * because it is not guranteed that snd_pcm_jack_pointer() was already
+        * called
+        */
+       snd_pcm_sframes_t avail;
+       avail = hw_ptr + io->buffer_size - appl_ptr;
+       if (avail < 0)
+               avail += jack->boundary;
+       else if ((snd_pcm_uframes_t) avail >= jack->boundary)
+               avail -= jack->boundary;
+       return avail;
+}
+
+static inline snd_pcm_uframes_t snd_pcm_jack_capture_avail(const snd_pcm_ioplug_t* const io,
+                                                           const snd_pcm_uframes_t hw_ptr,
+                                                           const snd_pcm_uframes_t appl_ptr)
+{
+       const snd_pcm_jack_t* const jack = io->private_data;
+
+       /* cannot use io->hw_ptr without calling snd_pcm_avail_update()
+        * because it is not guranteed that snd_pcm_jack_pointer() was already
+        * called
+        */
+       snd_pcm_sframes_t avail;
+       avail = hw_ptr - appl_ptr;
+       if (avail < 0)
+               avail += jack->boundary;
+       return avail;
+}
+
+static inline snd_pcm_uframes_t snd_pcm_jack_avail(const snd_pcm_ioplug_t* const io,
+                                                   const snd_pcm_uframes_t hw_ptr,
+                                                   const snd_pcm_uframes_t appl_ptr)
+{
+       return (io->stream == SND_PCM_STREAM_PLAYBACK) ?
+                               snd_pcm_jack_playback_avail(io, hw_ptr, appl_ptr) :
+                               snd_pcm_jack_capture_avail(io, hw_ptr, appl_ptr);
+}
+
+static inline snd_pcm_uframes_t snd_pcm_jack_hw_avail(const snd_pcm_ioplug_t* const io,
+                                                      const snd_pcm_uframes_t hw_ptr,
+                                                      const snd_pcm_uframes_t appl_ptr)
+{
+       /* available data/space which can be transfered by the user application */
+       const snd_pcm_uframes_t user_avail = snd_pcm_jack_avail(io, hw_ptr,
+                                                               appl_ptr);
+
+       if (user_avail > io->buffer_size) {
+               /* there was an Xrun */
+               return 0;
+       }
+       /* available data/space which can be transfered by the DMA */
+       return io->buffer_size - user_avail;
+}
+
 static int pcm_poll_block_check(snd_pcm_ioplug_t *io)
 {
        static char buf[32];
@@ -154,7 +216,6 @@ snd_pcm_jack_process_cb(jack_nframes_t nframes, snd_pcm_ioplug_t *io)
 {
        snd_pcm_jack_t *jack = io->private_data;
        snd_pcm_uframes_t hw_ptr;
-       const snd_pcm_channel_area_t *areas;
        snd_pcm_uframes_t xfer = 0;
        unsigned int channel;

@@ -164,40 +225,57 @@ snd_pcm_jack_process_cb(jack_nframes_t nframes, snd_pcm_ioplug_t *io)
                jack->areas[channel].first = 0;
                jack->areas[channel].step = jack->sample_bits;
        }
-
-       if (io->state != SND_PCM_STATE_RUNNING) {
-               if (io->stream == SND_PCM_STREAM_PLAYBACK) {
-                       for (channel = 0; channel < io->channels; channel++)
-                               snd_pcm_area_silence(&jack->areas[channel], 0, nframes, io->format);
-                       return 0;
-               }
-       }

        hw_ptr = jack->hw_ptr;
-       areas = snd_pcm_ioplug_mmap_areas(io);
-
-       while (xfer < nframes) {
-               snd_pcm_uframes_t frames = nframes - xfer;
-               snd_pcm_uframes_t offset = hw_ptr % io->buffer_size;
-               snd_pcm_uframes_t cont = io->buffer_size - offset;
-
-               if (cont < frames)
-                       frames = cont;
+       if (io->state == SND_PCM_STATE_RUNNING) {
+               const snd_pcm_channel_area_t *areas = snd_pcm_ioplug_mmap_areas(io);
+
+               while (xfer < nframes) {
+                       snd_pcm_uframes_t frames = nframes - xfer;
+                       snd_pcm_uframes_t offset = hw_ptr % io->buffer_size;
+                       snd_pcm_uframes_t cont = io->buffer_size - offset;
+                       snd_pcm_uframes_t hw_avail =
+                                       snd_pcm_jack_hw_avail(io, hw_ptr,
+                                                             io->appl_ptr);
+
+                       /* stop copying if there is no more data available */
+                       if (hw_avail <= 0)
+                               break;
+
+                       /* split the snd_pcm_area_copy() function into two parts
+                        * if the data to copy passes the buffer wrap around
+                        */
+                       if (cont < frames)
+                               frames = cont;
+
+                       if (hw_avail < frames)
+                               frames = hw_avail;
+
+                       for (channel = 0; channel < io->channels; channel++) {
+                               if (io->stream == SND_PCM_STREAM_PLAYBACK)
+                                       snd_pcm_area_copy(&jack->areas[channel], xfer, &areas[channel], offset, frames, io->format);
+                               else
+                                       snd_pcm_area_copy(&areas[channel], offset, &jack->areas[channel], xfer, frames, io->format);
+                       }

-               for (channel = 0; channel < io->channels; channel++) {
-                       if (io->stream == SND_PCM_STREAM_PLAYBACK)
-                               snd_pcm_area_copy(&jack->areas[channel], xfer, &areas[channel], offset, frames, io->format);
-                       else
-                               snd_pcm_area_copy(&areas[channel], offset, &jack->areas[channel], xfer, frames, io->format);
+                       hw_ptr += frames;
+                       if (hw_ptr >= jack->boundary)
+                               hw_ptr -= jack->boundary;
+                       xfer += frames;
                }
-
-               hw_ptr += frames;
-               if (hw_ptr >= jack->boundary)
-                       hw_ptr -= jack->boundary;
-               xfer += frames;
        }
        jack->hw_ptr = hw_ptr;

+       /* check if requested frames were copied */
+       if (xfer < nframes) {
+               /* always fill the not yet written JACK buffer with silence */
+               if (io->stream == SND_PCM_STREAM_PLAYBACK) {
+                       const snd_pcm_uframes_t samples = nframes - xfer;
+                       for (channel = 0; channel < io->channels; channel++)
+                               snd_pcm_area_silence(&jack->areas[channel], xfer, samples, io->format);
+               }
+       }
+
        pcm_poll_unblock_check(io); /* unblock socket for polling if needed */

        return 0;
--
2.7.4

  reply	other threads:[~2018-02-26  8:14 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-24 11:53 [PATCH - JACK PCM plugin] jack: Do not Xrun the ALSA buffer twischer
2018-02-26  8:14 ` Wischer, Timo (ADITG/ESB) [this message]
2018-02-27  8:48   ` Takashi Iwai
2018-03-01 13:14     ` [PATCH - JACK PCM plugin] Xrun handling twischer
2018-03-01 13:14       ` [PATCH - JACK plugin 1/4] jack: Do not Xrun the ALSA buffer twischer
2018-03-01 15:24         ` Takashi Iwai
2018-03-02 16:21           ` twischer
2018-03-02 16:21             ` [PATCH - PCM 2/3] pcm: ioplug: Provide hw_avail helper function for plugins twischer
2018-03-02 16:21             ` [PATCH - PCM 3/3] pcm: Provide areas_copy function which handles buffer wrap around twischer
2018-03-02 16:21             ` [PATCH - JACK 1/1] jack: Do not Xrun the ALSA buffer twischer
2018-03-13  8:34               ` [PATCH - JACK plugin] " twischer
2018-03-13  8:34                 ` [PATCH - PCM 1/2] pcm: ioplug: Provide hw_avail helper function for plugins twischer
2018-03-13  8:34                 ` [PATCH - PCM 2/2] pcm: Provide areas_copy function which handles buffer wrap around twischer
2018-03-13  8:34                 ` [PATCH - JACK 1/1] jack: Do not Xrun the ALSA buffer twischer
2018-03-13 21:20                 ` [PATCH - JACK plugin] " Takashi Iwai
2018-03-15 15:09                   ` Wischer, Timo (ADITG/ESB)
2018-03-15 15:13                     ` Takashi Iwai
2018-03-01 13:14       ` [PATCH - JACK plugin 2/4] jack: Use internal snd_pcm_state to reduce amount of additional variables twischer
2018-03-01 15:26         ` Takashi Iwai
2018-03-15 12:56           ` [PATCH - JACK plugin] " twischer
2018-03-15 12:56             ` [PATCH - JACK 1/1] " twischer
2018-03-15 13:14               ` Takashi Iwai
2018-03-15 14:05                 ` Wischer, Timo (ADITG/ESB)
2018-03-15 14:20                   ` Takashi Iwai
2018-03-15 15:07                     ` Wischer, Timo (ADITG/ESB)
2018-03-15 15:49                       ` Takashi Iwai
2018-03-16 10:02                         ` [PATCH - IOPLUG] Update prepare and draining state correctly twischer
2018-03-16 10:02                           ` [PATCH - IOPLUG 1/1] pcm: ioplug: update Prepare " twischer
2018-03-16 10:08                             ` Takashi Iwai
2018-03-16 10:20                               ` [PATCH - IOPLUG 1/1] pcm: ioplug: update prepare " twischer
2018-03-16 10:30                                 ` Takashi Iwai
2018-03-01 13:14       ` [PATCH - JACK plugin 3/4] jack: Report Xruns to user application twischer
2018-03-16 14:23         ` twischer
2018-03-16 14:23           ` [PATCH - JACK 1/1] " twischer
2018-03-16 14:41             ` Takashi Iwai
2018-03-16 14:47               ` Wischer, Timo (ADITG/ESB)
2018-03-16 14:57                 ` Takashi Iwai
2018-03-01 13:14       ` [PATCH - JACK plugin 4/4] jack: Support snd_pcm_drain() twischer
2018-03-01 13:41         ` Jaroslav Kysela
2018-03-16 14:44           ` Wischer, Timo (ADITG/ESB)
2018-03-16 15:11             ` Jaroslav Kysela
2018-03-16 15:52               ` Wischer, Timo (ADITG/ESB)
2018-03-21 16:22                 ` Wischer, Timo (ADITG/ESB)
2018-03-21 16:34                   ` Takashi Iwai
2018-03-21 16:47                     ` Wischer, Timo (ADITG/ESB)
2018-03-21 16:52                       ` Takashi Iwai
2018-03-21 17:02                         ` Wischer, Timo (ADITG/ESB)
2018-03-21 17:07                           ` Takashi Iwai
2018-03-01 15:19       ` [PATCH - JACK PCM plugin] Xrun handling Takashi Iwai

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=B0FB33DC1499054591F62C0EF1E013D7684FB83A@HI2EXCH01.adit-jv.com \
    --to=twischer@de.adit-jv.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=patch@alsa-project.org \
    --cc=tiwai@suse.de \
    /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.