This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 904f391982c48e4de26a2f2f34baceb45b17e275
Author: yangyalei <[email protected]>
AuthorDate: Mon Jul 21 19:55:24 2025 +0800

    nuttx/audio: Add audio_try_enqueue
    
    support upper driver check whether enqueue apb buffer to the lower
    driver
    
    Signed-off-by: yangyalei <[email protected]>
---
 audio/audio.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 73 insertions(+), 5 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index 861da7e94df..ba31a29f5c0 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -26,6 +26,7 @@
 
 #include <nuttx/config.h>
 
+#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdint.h>
@@ -66,6 +67,8 @@
 #  define CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO  1
 #endif
 
+#define AUDIO_ENQUEUE_THRESHOLD 2
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -375,6 +378,66 @@ static inline int audio_getnstate(FAR struct 
audio_upperhalf_s *upper,
   return nstate;
 }
 
+/****************************************************************************
+ * Name: audio_try_enqueue
+ *
+ * Description:
+ *   Try enqueue audio buffer
+ *
+ ****************************************************************************/
+
+static int audio_try_enqueue(FAR struct audio_upperhalf_s *upper)
+{
+  FAR struct audio_lowerhalf_s *lower = upper->dev;
+  FAR struct audio_openpriv_s *priv;
+  int ret = OK;
+
+  for (; ; )
+    {
+      uint32_t count = upper->status->head - upper->status->tail;
+      bool ready = false;
+      bool wait = false;
+
+      for (priv = upper->head; priv != NULL; priv = priv->flink)
+        {
+          if (priv->state == AUDIO_STATE_OPEN ||
+              priv->state == AUDIO_STATE_PAUSED)
+            {
+              continue;
+            }
+          else if (priv->head > upper->status->head)
+            {
+              ready = true;
+            }
+          else if (priv->head < upper->status->head ||
+                   priv->head <= upper->status->tail)
+            {
+              priv->state = AUDIO_STATE_XRUN;
+            }
+          else
+            {
+              wait = true;
+            }
+        }
+
+      if (!ready || (wait && count > AUDIO_ENQUEUE_THRESHOLD))
+        {
+          return OK;
+        }
+
+      ret = lower->ops->enqueuebuffer(
+          lower, upper->apbs[upper->status->head % upper->periods]);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      upper->status->head++;
+    }
+
+  return ret;
+}
+
 /****************************************************************************
  * Name: audio_configure
  *
@@ -756,7 +819,7 @@ static int audio_enqueuebuffer(FAR struct file *filep,
   FAR struct audio_lowerhalf_s *lower = upper->dev;
   FAR struct audio_openpriv_s *priv = filep->f_priv;
   irqstate_t flags;
-  int ret;
+  int ret = OK;
 
   DEBUGASSERT(lower->ops->enqueuebuffer != NULL);
 
@@ -774,12 +837,16 @@ static int audio_enqueuebuffer(FAR struct file *filep,
     }
   else
     {
-      flags = spin_lock_irqsave(&upper->spinlock);
-      priv->head += bufdesc->numbytes;
-      spin_unlock_irqrestore(&upper->spinlock, flags);
+      flags = spin_lock_irqsave_nopreempt(&upper->spinlock);
+      upper->apbs[priv->head % upper->periods]->nbytes =
+          MAX(upper->apbs[priv->head % upper->periods]->nbytes,
+              bufdesc->numbytes);
+      priv->head++;
+      ret = audio_try_enqueue(upper);
+      spin_unlock_irqrestore_nopreempt(&upper->spinlock, flags);
     }
 
-  return OK;
+  return ret;
 }
 
 /****************************************************************************
@@ -1319,6 +1386,7 @@ static inline void audio_dequeuebuffer(FAR struct 
audio_upperhalf_s *upper,
 
   flags = spin_lock_irqsave_nopreempt(&upper->spinlock);
   upper->status->tail++;
+  audio_try_enqueue(upper);
   for (priv = upper->head; priv != NULL; priv = priv->flink)
     {
       if (priv->fd > 0)

Reply via email to