OBS User unknown 2007-11-23 16:15:47 +00:00 committed by Git OBS Bridge
parent a0157ac02c
commit c60f4c823a
5 changed files with 413 additions and 1 deletions

View File

@ -0,0 +1,26 @@
# HG changeset patch
# User tiwai
# Date 1195568950 -3600
# Node ID 39d34d6a4587ffa6462e42308fb3519f55a2781c
# Parent b1d1733e52f8baf293ffa2af1c2b9cf5212006ec
pcm - Limit the avail_min minimum size
Fix avail_min if it's less than period_size. The too small avail_min
is simply useless and the cause of CPU hog with rate plugin.
diff -r b1d1733e52f8 -r 39d34d6a4587 src/pcm/pcm.c
--- a/src/pcm/pcm.c Mon Nov 19 08:07:19 2007 +0100
+++ b/src/pcm/pcm.c Tue Nov 20 15:29:10 2007 +0100
@@ -5577,6 +5577,12 @@ int snd_pcm_sw_params_set_avail_min(snd_
#endif
{
assert(pcm && params);
+ /* Fix avail_min if it's below period size. The period_size
+ * defines the minimal wake-up timing accuracy, so it doesn't
+ * make sense to set below that.
+ */
+ if (val < pcm->period_size)
+ val = pcm->period_size;
params->avail_min = val;
return 0;
}

View File

@ -0,0 +1,298 @@
diff -r 39d34d6a4587 -r 3539f279ec38 src/pcm/pcm_direct.c
--- a/src/pcm/pcm_direct.c Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_direct.c Wed Nov 21 12:19:43 2007 +0100
@@ -1001,6 +1001,17 @@ int snd_pcm_direct_initialize_slave(snd_
return ret;
}
+ /* set timestamp mode to MMAP
+ * the slave timestamp is copied appropriately in dsnoop/dmix/dshare
+ * based on the tstamp_mode of each client
+ */
+ ret = snd_pcm_sw_params_set_tstamp_mode(spcm, sw_params,
+ SND_PCM_TSTAMP_MMAP);
+ if (ret < 0) {
+ SNDERR("unable to tstamp mode MMAP");
+ return ret;
+ }
+
if (dmix->type != SND_PCM_TYPE_DMIX)
goto __skip_silencing;
diff -r 39d34d6a4587 -r 3539f279ec38 src/pcm/pcm_dmix.c
--- a/src/pcm/pcm_dmix.c Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_dmix.c Wed Nov 21 12:19:43 2007 +0100
@@ -367,11 +367,8 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm
if (avail > dmix->avail_max)
dmix->avail_max = avail;
if (avail >= pcm->stop_threshold) {
- struct timeval tv;
snd_timer_stop(dmix->timer);
- gettimeofday(&tv, 0);
- dmix->trigger_tstamp.tv_sec = tv.tv_sec;
- dmix->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&dmix->trigger_tstamp);
if (dmix->state == SND_PCM_STATE_RUNNING) {
dmix->state = SND_PCM_STATE_XRUN;
return -EPIPE;
@@ -420,7 +417,10 @@ static int snd_pcm_dmix_status(snd_pcm_t
memset(status, 0, sizeof(*status));
status->state = snd_pcm_dmix_state(pcm);
status->trigger_tstamp = dmix->trigger_tstamp;
- status->tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
+ if (pcm->tstamp_mode == SND_PCM_TSTAMP_MMAP)
+ status->tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
+ else
+ gettimestamp(&status->tstamp);
status->avail = snd_pcm_mmap_playback_avail(pcm);
status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
dmix->avail_max = 0;
@@ -525,7 +525,6 @@ static int snd_pcm_dmix_start(snd_pcm_t
{
snd_pcm_direct_t *dmix = pcm->private_data;
snd_pcm_sframes_t avail;
- struct timeval tv;
int err;
if (dmix->state != SND_PCM_STATE_PREPARED)
@@ -540,9 +539,7 @@ static int snd_pcm_dmix_start(snd_pcm_t
return err;
snd_pcm_dmix_sync_area(pcm);
}
- gettimeofday(&tv, 0);
- dmix->trigger_tstamp.tv_sec = tv.tv_sec;
- dmix->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&dmix->trigger_tstamp);
return 0;
}
diff -r 39d34d6a4587 -r 3539f279ec38 src/pcm/pcm_dshare.c
--- a/src/pcm/pcm_dshare.c Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_dshare.c Wed Nov 21 12:19:43 2007 +0100
@@ -194,11 +194,8 @@ static int snd_pcm_dshare_sync_ptr(snd_p
if (avail > dshare->avail_max)
dshare->avail_max = avail;
if (avail >= pcm->stop_threshold) {
- struct timeval tv;
snd_timer_stop(dshare->timer);
- gettimeofday(&tv, 0);
- dshare->trigger_tstamp.tv_sec = tv.tv_sec;
- dshare->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&dshare->trigger_tstamp);
if (dshare->state == SND_PCM_STATE_RUNNING) {
dshare->state = SND_PCM_STATE_XRUN;
return -EPIPE;
@@ -229,7 +226,10 @@ static int snd_pcm_dshare_status(snd_pcm
memset(status, 0, sizeof(*status));
status->state = snd_pcm_state(dshare->spcm);
status->trigger_tstamp = dshare->trigger_tstamp;
- status->tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
+ if (pcm->tstamp_mode == SND_PCM_TSTAMP_MMAP)
+ status->tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
+ else
+ gettimestamp(&status->tstamp);
status->avail = snd_pcm_mmap_playback_avail(pcm);
status->avail_max = status->avail > dshare->avail_max ? status->avail : dshare->avail_max;
dshare->avail_max = 0;
@@ -335,7 +335,6 @@ static int snd_pcm_dshare_start(snd_pcm_
{
snd_pcm_direct_t *dshare = pcm->private_data;
snd_pcm_sframes_t avail;
- struct timeval tv;
int err;
if (dshare->state != SND_PCM_STATE_PREPARED)
@@ -350,9 +349,7 @@ static int snd_pcm_dshare_start(snd_pcm_
return err;
snd_pcm_dshare_sync_area(pcm);
}
- gettimeofday(&tv, 0);
- dshare->trigger_tstamp.tv_sec = tv.tv_sec;
- dshare->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&dshare->trigger_tstamp);
return 0;
}
diff -r 39d34d6a4587 -r 3539f279ec38 src/pcm/pcm_dsnoop.c
--- a/src/pcm/pcm_dsnoop.c Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_dsnoop.c Wed Nov 21 12:19:43 2007 +0100
@@ -141,10 +141,7 @@ static int snd_pcm_dsnoop_sync_ptr(snd_p
if (pcm->stop_threshold >= pcm->boundary) /* don't care */
return 0;
if ((avail = snd_pcm_mmap_capture_hw_avail(pcm)) >= pcm->stop_threshold) {
- struct timeval tv;
- gettimeofday(&tv, 0);
- dsnoop->trigger_tstamp.tv_sec = tv.tv_sec;
- dsnoop->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&dsnoop->trigger_tstamp);
dsnoop->state = SND_PCM_STATE_XRUN;
dsnoop->avail_max = avail;
return -EPIPE;
@@ -175,7 +172,10 @@ static int snd_pcm_dsnoop_status(snd_pcm
state = snd_pcm_state(dsnoop->spcm);
status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state;
status->trigger_tstamp = dsnoop->trigger_tstamp;
- status->tstamp = snd_pcm_hw_fast_tstamp(dsnoop->spcm);
+ if (pcm->tstamp_mode == SND_PCM_TSTAMP_MMAP)
+ status->tstamp = snd_pcm_hw_fast_tstamp(dsnoop->spcm);
+ else
+ gettimestamp(&status->tstamp);
status->avail = snd_pcm_mmap_capture_avail(pcm);
status->avail_max = status->avail > dsnoop->avail_max ? status->avail : dsnoop->avail_max;
dsnoop->avail_max = 0;
@@ -264,7 +264,6 @@ static int snd_pcm_dsnoop_start(snd_pcm_
static int snd_pcm_dsnoop_start(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dsnoop = pcm->private_data;
- struct timeval tv;
int err;
if (dsnoop->state != SND_PCM_STATE_PREPARED)
@@ -275,9 +274,7 @@ static int snd_pcm_dsnoop_start(snd_pcm_
if (err < 0)
return err;
dsnoop->state = SND_PCM_STATE_RUNNING;
- gettimeofday(&tv, 0);
- dsnoop->trigger_tstamp.tv_sec = tv.tv_sec;
- dsnoop->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&dsnoop->trigger_tstamp);
return 0;
}
diff -r 39d34d6a4587 -r 3539f279ec38 src/pcm/pcm_ioplug.c
--- a/src/pcm/pcm_ioplug.c Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_ioplug.c Wed Nov 21 12:19:43 2007 +0100
@@ -438,7 +438,6 @@ static int snd_pcm_ioplug_start(snd_pcm_
static int snd_pcm_ioplug_start(snd_pcm_t *pcm)
{
ioplug_priv_t *io = pcm->private_data;
- struct timeval tv;
int err;
if (io->data->state != SND_PCM_STATE_PREPARED)
@@ -448,9 +447,7 @@ static int snd_pcm_ioplug_start(snd_pcm_
if (err < 0)
return err;
- gettimeofday(&tv, 0);
- io->trigger_tstamp.tv_sec = tv.tv_sec;
- io->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&io->trigger_tstamp);
io->data->state = SND_PCM_STATE_RUNNING;
return 0;
@@ -459,16 +456,13 @@ static int snd_pcm_ioplug_drop(snd_pcm_t
static int snd_pcm_ioplug_drop(snd_pcm_t *pcm)
{
ioplug_priv_t *io = pcm->private_data;
- struct timeval tv;
if (io->data->state == SND_PCM_STATE_OPEN)
return -EBADFD;
io->data->callback->stop(io->data);
- gettimeofday(&tv, 0);
- io->trigger_tstamp.tv_sec = tv.tv_sec;
- io->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&io->trigger_tstamp);
io->data->state = SND_PCM_STATE_SETUP;
return 0;
diff -r 39d34d6a4587 -r 3539f279ec38 src/pcm/pcm_local.h
--- a/src/pcm/pcm_local.h Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_local.h Wed Nov 21 12:19:43 2007 +0100
@@ -838,3 +838,13 @@ typedef union snd_tmp_double {
double d;
int64_t l;
} snd_tmp_double_t;
+
+/* get the current timestamp */
+static inline void gettimestamp(snd_htimestamp_t *tstamp)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, 0);
+ tstamp->tv_sec = tv.tv_sec;
+ tstamp->tv_nsec = tv.tv_usec * 1000L;
+}
diff -r 39d34d6a4587 -r 3539f279ec38 src/pcm/pcm_null.c
--- a/src/pcm/pcm_null.c Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_null.c Wed Nov 21 12:19:43 2007 +0100
@@ -82,13 +82,10 @@ static int snd_pcm_null_status(snd_pcm_t
static int snd_pcm_null_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
{
snd_pcm_null_t *null = pcm->private_data;
- struct timeval tv;
memset(status, 0, sizeof(*status));
status->state = null->state;
status->trigger_tstamp = null->trigger_tstamp;
- gettimeofday(&tv, 0);
- status->tstamp.tv_sec = tv.tv_sec;
- status->tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&status->tstamp);
status->avail = pcm->buffer_size;
status->avail_max = status->avail;
return 0;
diff -r 39d34d6a4587 -r 3539f279ec38 src/pcm/pcm_rate.c
--- a/src/pcm/pcm_rate.c Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_rate.c Wed Nov 21 12:19:43 2007 +0100
@@ -1090,7 +1090,6 @@ static int snd_pcm_rate_start(snd_pcm_t
{
snd_pcm_rate_t *rate = pcm->private_data;
snd_pcm_uframes_t avail;
- struct timeval tv;
if (pcm->stream == SND_PCM_STREAM_CAPTURE)
return snd_pcm_start(rate->gen.slave);
@@ -1098,9 +1097,7 @@ static int snd_pcm_rate_start(snd_pcm_t
if (snd_pcm_state(rate->gen.slave) != SND_PCM_STATE_PREPARED)
return -EBADFD;
- gettimeofday(&tv, 0);
- rate->trigger_tstamp.tv_sec = tv.tv_sec;
- rate->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&rate->trigger_tstamp);
avail = snd_pcm_mmap_playback_hw_avail(rate->gen.slave);
if (avail == 0) {
diff -r 39d34d6a4587 -r 3539f279ec38 src/pcm/pcm_share.c
--- a/src/pcm/pcm_share.c Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_share.c Wed Nov 21 12:19:43 2007 +0100
@@ -914,7 +914,6 @@ static int snd_pcm_share_start(snd_pcm_t
snd_pcm_share_t *share = pcm->private_data;
snd_pcm_share_slave_t *slave = share->slave;
snd_pcm_t *spcm = slave->pcm;
- struct timeval tv;
int err = 0;
if (share->state != SND_PCM_STATE_PREPARED)
return -EBADFD;
@@ -970,9 +969,7 @@ static int snd_pcm_share_start(snd_pcm_t
}
slave->running_count++;
_snd_pcm_share_update(pcm);
- gettimeofday(&tv, 0);
- share->trigger_tstamp.tv_sec = tv.tv_sec;
- share->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&share->trigger_tstamp);
_end:
Pthread_mutex_unlock(&slave->mutex);
return err;
@@ -1099,16 +1096,13 @@ static void _snd_pcm_share_stop(snd_pcm_
{
snd_pcm_share_t *share = pcm->private_data;
snd_pcm_share_slave_t *slave = share->slave;
- struct timeval tv;
#if 0
if (!pcm->mmap_channels) {
/* PCM closing already begun in the main thread */
return;
}
#endif
- gettimeofday(&tv, 0);
- share->trigger_tstamp.tv_sec = tv.tv_sec;
- share->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
+ gettimestamp(&share->trigger_tstamp);
if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
snd_pcm_areas_copy(pcm->stopped_areas, 0,
pcm->running_areas, 0,

View File

@ -0,0 +1,70 @@
# HG changeset patch
# User tiwai
# Date 1195829208 -3600
# Node ID 672c5387645d33ec98157257b5221476064ac810
# Parent 3539f279ec3847636ec20110e9237b88382722a9
Fix mmap with multi plugin
The mmap of multi plugin seems broken (for a long time!) due to its
creation of local buffer via snd_pcm_mmap(). Since the multi plugin
just needs to shadow the mmap buffer of each slave, it now has
mmap_shadow=1 and its own mmap/unmap method to do shadowing.
diff -r 3539f279ec38 -r 672c5387645d src/pcm/pcm_multi.c
--- a/src/pcm/pcm_multi.c Wed Nov 21 12:19:43 2007 +0100
+++ b/src/pcm/pcm_multi.c Fri Nov 23 15:46:48 2007 +0100
@@ -690,13 +690,44 @@ static snd_pcm_sframes_t snd_pcm_multi_m
return size;
}
-static int snd_pcm_multi_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+static int snd_pcm_multi_munmap(snd_pcm_t *pcm)
{
+ free(pcm->mmap_channels);
+ free(pcm->running_areas);
+ pcm->mmap_channels = NULL;
+ pcm->running_areas = NULL;
return 0;
}
-static int snd_pcm_multi_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+static int snd_pcm_multi_mmap(snd_pcm_t *pcm)
{
+ snd_pcm_multi_t *multi = pcm->private_data;
+ unsigned int c;
+
+ pcm->mmap_channels = calloc(pcm->channels,
+ sizeof(pcm->mmap_channels[0]));
+ pcm->running_areas = calloc(pcm->channels,
+ sizeof(pcm->running_areas[0]));
+ if (!pcm->mmap_channels || !pcm->running_areas) {
+ snd_pcm_multi_munmap(pcm);
+ return -ENOMEM;
+ }
+
+ /* Copy the slave mmapped buffer data */
+ for (c = 0; c < pcm->channels; c++) {
+ snd_pcm_multi_channel_t *chan = &multi->channels[c];
+ snd_pcm_t *slave;
+ if (chan->slave_idx < 0) {
+ snd_pcm_multi_munmap(pcm);
+ return -ENXIO;
+ }
+ slave = multi->slaves[chan->slave_idx].pcm;
+ pcm->mmap_channels[c] =
+ slave->mmap_channels[chan->slave_channel];
+ pcm->mmap_channels[c].channel = c;
+ pcm->running_areas[c] =
+ slave->running_areas[chan->slave_channel];
+ }
return 0;
}
@@ -850,6 +881,7 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp,
return err;
}
pcm->mmap_rw = 1;
+ pcm->mmap_shadow = 1; /* has own mmap method */
pcm->ops = &snd_pcm_multi_ops;
pcm->fast_ops = &snd_pcm_multi_fast_ops;
pcm->private_data = multi;

View File

@ -1,3 +1,10 @@
-------------------------------------------------------------------
Fri Nov 23 16:48:19 CET 2007 - tiwai@suse.de
- fix possible CPU hog problem with too small avail_min
- fix time-stamp with dmix/dsnoop plugins
- fix mmap of multi plugins
-------------------------------------------------------------------
Fri Nov 16 12:09:29 CET 2007 - tiwai@suse.de

View File

@ -21,7 +21,7 @@ PreReq: %insserv_prereq %fillup_prereq
AutoReqProv: on
Summary: Advanced Linux Sound Architecture
Version: 1.0.15
Release: 11
Release: 13
Source: ftp://ftp.alsa-project.org/pub/lib/alsa-lib-%{package_version}.tar.bz2
Source8: 40-alsa.rules
Source11: alsasound
@ -40,6 +40,9 @@ Patch1: alsa-lib-ioplug-fix.diff
Patch2: alsa-lib-smixer-range-fix.diff
Patch3: alsa-lib-rate-plugin-fix.diff
Patch4: alsa-lib-dmix-error-code-fix.diff
Patch5: alsa-lib-avail_min-fix.diff
Patch6: alsa-lib-dmix-tstamp-fix.diff
Patch7: alsa-lib-multi-mmap-fix.diff
Url: http://www.alsa-project.org/
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@ -116,6 +119,9 @@ Authors:
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%{?suse_update_config:%{suse_update_config -f .}}
%build
@ -255,7 +261,12 @@ exit 0
%{_libdir}/libasound.so.*
%{_libdir}/alsa-lib
%{_datadir}/alsa
%changelog
* Fri Nov 23 2007 - tiwai@suse.de
- fix possible CPU hog problem with too small avail_min
- fix time-stamp with dmix/dsnoop plugins
- fix mmap of multi plugins
* Fri Nov 16 2007 - tiwai@suse.de
- fix the wrong error codes in dmix (#339507)
* Mon Nov 12 2007 - tiwai@suse.de