At Wed, 4 Jul 2007 22:18:24 +0800, Roy Huang wrote:
Record doesn't work if enabling mmap emulation and rate conversion needed, this patch fix this bug.
Thanks for the patch. I need to check your changes in detail as it's not so obvious. What is the problem with rate plugin and mmap-emulation? From what I find in your patch, it's something to do with the hw_ptr update mismatch.
Takashi
diff -uNr alsa-lib-1.0.14a/src/pcm/pcm_hw.c alsa-lib-new/src/pcm/pcm_hw.c --- alsa-lib-1.0.14a/src/pcm/pcm_hw.c 2007-06-11 16:53:13.000000000 +0800 +++ alsa-lib-new/src/pcm/pcm_hw.c 2007-07-04 12:16:31.000000000 +0800 @@ -96,6 +96,7 @@ int shadow_appl_ptr: 1, avail_update_flag: 1, mmap_shm: 1;
snd_pcm_uframes_t hw_ptr; snd_pcm_uframes_t appl_ptr; /* restricted parameters */ snd_pcm_format_t format;@@ -373,7 +374,9 @@ if (pcm->stream == SND_PCM_STREAM_CAPTURE) { if (hw->mmap_shm) { hw->shadow_appl_ptr = 1;
hw->hw_ptr = 0; hw->appl_ptr = 0;snd_pcm_set_hw_ptr(pcm, &hw->hw_ptr, -1, 0); snd_pcm_set_appl_ptr(pcm, &hw->appl_ptr, -1, 0); } else { hw->shadow_appl_ptr = 0;@@ -949,28 +952,91 @@ return size; }
+static inline snd_pcm_uframes_t snd_pcm_hw_capture_avail(snd_pcm_t *pcm) +{
snd_pcm_sframes_t avail;snd_pcm_hw_t *hw = pcm->private_data;avail = hw->mmap_status->hw_ptr - hw->mmap_control->appl_ptr;if (avail < 0)avail += pcm->boundary;return avail;+}
+static snd_pcm_sframes_t snd_pcm_hw_read_mmap(snd_pcm_t *pcm, snd_pcm_uframes_t size) +{
snd_pcm_uframes_t xfer = 0;snd_pcm_sframes_t err = 0;snd_pcm_hw_t *hw = pcm->private_data;if (! size)return 0;while (xfer < size) {snd_pcm_uframes_t frames = size - xfer;snd_pcm_uframes_t appl_offset = hw->mmap_control->appl_ptr %pcm->buffer_size;
snd_pcm_uframes_t cont = pcm->buffer_size - appl_offset;if (cont < frames)frames = cont;switch (pcm->access) {case SND_PCM_ACCESS_MMAP_INTERLEAVED:{const snd_pcm_channel_area_t *a =snd_pcm_mmap_areas(pcm);
char *buf = snd_pcm_channel_area_addr(a, appl_offset);err = _snd_pcm_readi(pcm, buf, frames);if (err >= 0)frames = err;break;}case SND_PCM_ACCESS_MMAP_NONINTERLEAVED:{snd_pcm_uframes_t channels = pcm->channels;unsigned int c;void *bufs[channels];const snd_pcm_channel_area_t *areas =snd_pcm_mmap_areas(pcm);
for (c = 0; c < channels; ++c) {const snd_pcm_channel_area_t *a = &areas[c];bufs[c] = snd_pcm_channel_area_addr(a,appl_offset);
}err = _snd_pcm_readn(pcm->fast_op_arg, bufs, frames);if (err >= 0)frames = err;}default:SNDMSG("invalid access type %d", pcm->access);return -EINVAL;}if (err < 0)break;xfer += frames;}if (xfer > 0)return xfer;return err;+}
static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm) { snd_pcm_hw_t *hw = pcm->private_data;
snd_pcm_uframes_t avail;
snd_pcm_uframes_t avail, xfer_avail; sync_ptr(hw, 0); if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { avail = snd_pcm_mmap_playback_avail(pcm); } else { avail = snd_pcm_mmap_capture_avail(pcm);
if (avail > 0 && hw->mmap_shm) {
if (avail < pcm->avail_min && hw->mmap_shm) { snd_pcm_sframes_t err;
snd_pcm_hw_t *hw = pcm->private_data;hw->avail_update_flag = 1;err = snd_pcm_read_mmap(pcm, avail);hw->avail_update_flag = 0;if (err < 0)return err;if ((snd_pcm_uframes_t)err != avail)SNDMSG("short read %ld for avail %ld",err, avail);
return err;}
xfer_avail = snd_pcm_hw_capture_avail(pcm);xfer_avail -= xfer_avail % pcm->xfer_align;if (xfer_avail > 0) {hw->avail_update_flag = 1;err = snd_pcm_hw_read_mmap(pcm, xfer_avail);hw->avail_update_flag = 0;if (err < 0)return err;hw->hw_ptr += err;avail = snd_pcm_mmap_capture_avail(pcm);}} } switch (FAST_PCM_STATE(hw)) { case SNDRV_PCM_STATE_RUNNING:
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel