On 2014-11-12 14:31, Peter Meerwald wrote:
Hi,

snd_pcm_mmap_commit() actually transfers the memory area prepared by
snd_pcm_mmap_begin(),
it returns the 'count of transferred frames' which should be equal to the
number of frames
returned by snd_pcm_mmap_begin()

however, this identify is not checked and the number of frames prepared are
accounted for,
not the number of frames commited -- this is wrong; the ALSA example codes
bothers to
check snd_pcm_mmap_commit()'s returned number of frames

this patch outputs a warning and uses the commited number of frames to
update the bytes
read or written, resp.

It's not that easy, I think...
In case you get fewer frames written, you should retry the mmap_begin +
mmap_commit cycle but *without* calling pa_sink_render_into_full, and
only with the remaining frames. Right?

ah, yes

I think the question is: does it ever happen?

currently, the code won't notice any glitches and does the wrong thing if
sframes != frames

the proposed code logs a warning and does the wrong thing if sframes !=
frames

the ALSA example just treats sframes != frames as an error -- probably
that's the best thing to do (with some logging)?

Since we don't know if this ever happens, and if so, why, I think maybe act conservatively and just write something to the log?

And if this actually happens, we'll try to analyze it? Instead of guessing.


regards, p.

---
   src/modules/alsa/alsa-sink.c   |   11 +++++++++--
   src/modules/alsa/alsa-source.c |   17 +++++++++++++----
   2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index e256bbd..fc05232 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -639,8 +639,7 @@ static int mmap_write(struct userdata *u, pa_usec_t
*sleep_usec, bool polled, bo

               p = (uint8_t*) areas[0].addr + (offset * u->frame_size);

-            written = frames * u->frame_size;
-            chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p,
written, true);
+            chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p,
frames * u->frame_size, true);
               chunk.length = pa_memblock_get_length(chunk.memblock);
               chunk.index = 0;

@@ -660,6 +659,14 @@ static int mmap_write(struct userdata *u, pa_usec_t
*sleep_usec, bool polled, bo

               work_done = true;

+            if (PA_UNLIKELY((snd_pcm_uframes_t) sframes != frames)) {
+                PA_ONCE_BEGIN {
+                    pa_log_warn("ALSA mmap write was set up up for %lu
frames, but unexpectedly commited %lu frames.\n",
+                        (unsigned long) frames, (unsigned long) sframes);
+                } PA_ONCE_END;
+            }
+
+            written = sframes * u->frame_size;
               u->write_count += written;
               u->since_start += written;

diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 111c517..36e7585 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -562,6 +562,7 @@ static int mmap_read(struct userdata *u, pa_usec_t
*sleep_usec, bool polled, boo
               const snd_pcm_channel_area_t *areas;
               snd_pcm_uframes_t offset, frames;
               snd_pcm_sframes_t sframes;
+            size_t got;

               frames = (snd_pcm_uframes_t) (n_bytes / u->frame_size);
   /*             pa_log_debug("%lu frames to read", (unsigned long) frames);
*/
@@ -613,16 +614,24 @@ static int mmap_read(struct userdata *u, pa_usec_t
*sleep_usec, bool polled, boo

               work_done = true;

-            u->read_count += frames * u->frame_size;
+            if (PA_UNLIKELY((snd_pcm_uframes_t) sframes != frames)) {
+                PA_ONCE_BEGIN {
+                    pa_log_warn("ALSA mmap read was set up up for %lu
frames, but unexpectedly commited %lu frames.\n",
+                        (unsigned long) frames, (unsigned long) sframes);
+                } PA_ONCE_END;
+            }
+
+            got = sframes * u->frame_size;
+            u->read_count += got;

   #ifdef DEBUG_TIMING
-            pa_log_debug("Read %lu bytes (of possible %lu bytes)",
(unsigned long) (frames * u->frame_size), (unsigned long) n_bytes);
+            pa_log_debug("Read %lu bytes (of possible %lu bytes)",
(unsigned long) got, (unsigned long) n_bytes);
   #endif

-            if ((size_t) frames * u->frame_size >= n_bytes)
+            if (got >= n_bytes)
                   break;

-            n_bytes -= (size_t) frames * u->frame_size;
+            n_bytes -= got;
           }
       }






--
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic
_______________________________________________
pulseaudio-discuss mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

Reply via email to