linuxOS_AP06/buildroot/package/alsa-lib/0005-LOCAL-pcm-add-the-setting-of-SND_PCM_FORCE_ALIGN_FRA.patch
2025-06-03 12:28:32 +08:00

149 lines
4.6 KiB
Diff

From 6047814d2bdda181c34f33a44befca46ee9f1b0f Mon Sep 17 00:00:00 2001
From: Xing Zheng <zhengxing@rock-chips.com>
Date: Wed, 10 Apr 2024 22:34:47 +0800
Subject: [PATCH] LOCAL: pcm: add the setting of SND_PCM_FORCE_ALIGN_FRAME via
plugin or ENV
Some plugins (especially capture) cannot obtain a stable
period size and require PCM to obtain the avail phase for
forced synchronization, so that the plugin passed to
post-processing has a fixed size.
Note: If the algorithm in the plug-in needs to specify a fixed
frame size, the uncertain length in the recording 'ACCESS_MMAP'
mode will make the situation very troublesome, so here the frame
size is forced to be aligned and fixed according to the flag
'SND_PCM_FORCE_ALIGN_FRAME' specified by the plug-in.
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---
include/pcm.h | 2 ++
src/pcm/pcm.c | 46 ++++++++++++++++++++++++++++++++-----------
src/pcm/pcm_extplug.c | 4 ++++
src/pcm/pcm_plugin.c | 15 ++++++++++++++
4 files changed, 56 insertions(+), 11 deletions(-)
diff --git a/include/pcm.h b/include/pcm.h
index 102ff81..0c78ff4 100644
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -413,6 +413,8 @@ typedef long snd_pcm_sframes_t;
#define SND_PCM_NO_AUTO_FORMAT 0x00040000
/** Disable soft volume control */
#define SND_PCM_NO_SOFTVOL 0x00080000
+/** Force align frame size */
+#define SND_PCM_FORCE_ALIGN_FRAME 0x00100000
/** PCM handle */
typedef struct _snd_pcm snd_pcm_t;
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 0a8cd0d..cedb3e5 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7805,19 +7805,43 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
err = avail;
goto _end;
}
- if (avail == 0) {
- if (state == SND_PCM_STATE_DRAINING)
- goto _end;
- if (pcm->mode & SND_PCM_NONBLOCK) {
- err = -EAGAIN;
- goto _end;
+ if (pcm->mode & SND_PCM_FORCE_ALIGN_FRAME) {
+ if (state == SND_PCM_STATE_RUNNING &&
+ size > (snd_pcm_uframes_t)avail) {
+ if (snd_pcm_may_wait_for_avail_min(pcm, avail)) {
+ if (pcm->mode & SND_PCM_NONBLOCK) {
+ err = -EAGAIN;
+ goto _end;
+ }
+
+ err = snd_pcm_wait_nocheck(pcm, SND_PCM_WAIT_IO);
+ if (err < 0)
+ break;
+ goto _again;
+ }
+ /* the snd_pcm_may_wait_for_avail_min may check against the
+ * updated hw.ptr (slaves), get the avail again here
+ */
+ avail = __snd_pcm_avail_update(pcm);
+ if (avail < 0) {
+ err = avail;
+ goto _end;
+ }
}
+ } else {
+ if (avail == 0) {
+ if (state == SND_PCM_STATE_DRAINING)
+ goto _end;
+ if (pcm->mode & SND_PCM_NONBLOCK) {
+ err = -EAGAIN;
+ goto _end;
+ }
- err = __snd_pcm_wait_in_lock(pcm, SND_PCM_WAIT_IO);
- if (err < 0)
- break;
- goto _again;
-
+ err = __snd_pcm_wait_in_lock(pcm, SND_PCM_WAIT_IO);
+ if (err < 0)
+ break;
+ goto _again;
+ }
}
frames = size;
if (frames > (snd_pcm_uframes_t) avail)
diff --git a/src/pcm/pcm_extplug.c b/src/pcm/pcm_extplug.c
index feb32b9..919e660 100644
--- a/src/pcm/pcm_extplug.c
+++ b/src/pcm/pcm_extplug.c
@@ -681,6 +681,7 @@ int snd_pcm_extplug_create(snd_pcm_extplug_t *extplug, const char *name,
int err;
snd_pcm_t *spcm, *pcm;
snd_config_t *sconf;
+ char *env_str = getenv("ALSA_EXTPLUG_FORCE_ALIGN_FRAME");
assert(root);
assert(extplug && extplug->callback);
@@ -720,6 +721,9 @@ int snd_pcm_extplug_create(snd_pcm_extplug_t *extplug, const char *name,
if (extplug->version >= 0x010001 && extplug->callback->init)
ext->plug.init = snd_pcm_extplug_init;
+ if (env_str && (strcasecmp(env_str, "true") == 0))
+ mode |= SND_PCM_FORCE_ALIGN_FRAME;
+
err = snd_pcm_new(&pcm, SND_PCM_TYPE_EXTPLUG, name, stream, mode);
if (err < 0) {
free(ext);
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 9d7e233..8580284 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -485,6 +485,21 @@ snd_pcm_plugin_sync_hw_ptr_capture(snd_pcm_t *pcm,
* there is more data available.
*/
slave_size = snd_pcm_avail_update(slave);
+
+ /**
+ * NOTE: If the algorithm in the plug-in needs to specify a fixed
+ * frame size, the uncertain length in the recording 'ACCESS_MMAP'
+ * mode will make the situation very troublesome, so here the frame
+ * size is forced to be aligned and fixed according to the flag
+ * 'SND_PCM_FORCE_ALIGN_FRAME' specified by the plug-in.
+ */
+ if (pcm->mode & SND_PCM_FORCE_ALIGN_FRAME) {
+ if (slave_size < pcm->period_size)
+ continue;
+ if (slave_size > pcm->period_size)
+ slave_size = pcm->period_size;
+ }
+
result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
if (result < 0) {
err = result;
--
2.34.1