2626
2727#include <nuttx/config.h>
2828
29+ #include <sys/param.h>
2930#include <sys/types.h>
3031#include <sys/stat.h>
3132#include <stdint.h>
6667# define CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO 1
6768#endif
6869
70+ #define AUDIO_ENQUEUE_THRESHOLD 2
71+
6972/****************************************************************************
7073 * Private Types
7174 ****************************************************************************/
@@ -375,6 +378,66 @@ static inline int audio_getnstate(FAR struct audio_upperhalf_s *upper,
375378 return nstate ;
376379}
377380
381+ /****************************************************************************
382+ * Name: audio_try_enqueue
383+ *
384+ * Description:
385+ * Try enqueue audio buffer
386+ *
387+ ****************************************************************************/
388+
389+ static int audio_try_enqueue (FAR struct audio_upperhalf_s * upper )
390+ {
391+ FAR struct audio_lowerhalf_s * lower = upper -> dev ;
392+ FAR struct audio_openpriv_s * priv ;
393+ int ret = OK ;
394+
395+ for (; ; )
396+ {
397+ uint32_t count = upper -> status -> head - upper -> status -> tail ;
398+ bool ready = false;
399+ bool wait = false;
400+
401+ for (priv = upper -> head ; priv != NULL ; priv = priv -> flink )
402+ {
403+ if (priv -> state == AUDIO_STATE_OPEN ||
404+ priv -> state == AUDIO_STATE_PAUSED )
405+ {
406+ continue ;
407+ }
408+ else if (priv -> head > upper -> status -> head )
409+ {
410+ ready = true;
411+ }
412+ else if (priv -> head < upper -> status -> head ||
413+ priv -> head <= upper -> status -> tail )
414+ {
415+ priv -> state = AUDIO_STATE_XRUN ;
416+ }
417+ else
418+ {
419+ wait = true;
420+ }
421+ }
422+
423+ if (!ready || (wait && count > AUDIO_ENQUEUE_THRESHOLD ))
424+ {
425+ return OK ;
426+ }
427+
428+ ret = lower -> ops -> enqueuebuffer (
429+ lower , upper -> apbs [upper -> status -> head % upper -> periods ]);
430+ if (ret < 0 )
431+ {
432+ return ret ;
433+ }
434+
435+ upper -> status -> head ++ ;
436+ }
437+
438+ return ret ;
439+ }
440+
378441/****************************************************************************
379442 * Name: audio_configure
380443 *
@@ -756,7 +819,7 @@ static int audio_enqueuebuffer(FAR struct file *filep,
756819 FAR struct audio_lowerhalf_s * lower = upper -> dev ;
757820 FAR struct audio_openpriv_s * priv = filep -> f_priv ;
758821 irqstate_t flags ;
759- int ret ;
822+ int ret = OK ;
760823
761824 DEBUGASSERT (lower -> ops -> enqueuebuffer != NULL );
762825
@@ -774,12 +837,16 @@ static int audio_enqueuebuffer(FAR struct file *filep,
774837 }
775838 else
776839 {
777- flags = spin_lock_irqsave (& upper -> spinlock );
778- priv -> head += bufdesc -> numbytes ;
779- spin_unlock_irqrestore (& upper -> spinlock , flags );
840+ flags = spin_lock_irqsave_nopreempt (& upper -> spinlock );
841+ upper -> apbs [priv -> head % upper -> periods ]-> nbytes =
842+ MAX (upper -> apbs [priv -> head % upper -> periods ]-> nbytes ,
843+ bufdesc -> numbytes );
844+ priv -> head ++ ;
845+ ret = audio_try_enqueue (upper );
846+ spin_unlock_irqrestore_nopreempt (& upper -> spinlock , flags );
780847 }
781848
782- return OK ;
849+ return ret ;
783850}
784851
785852/****************************************************************************
@@ -1319,6 +1386,7 @@ static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper,
13191386
13201387 flags = spin_lock_irqsave_nopreempt (& upper -> spinlock );
13211388 upper -> status -> tail ++ ;
1389+ audio_try_enqueue (upper );
13221390 for (priv = upper -> head ; priv != NULL ; priv = priv -> flink )
13231391 {
13241392 if (priv -> fd > 0 )
0 commit comments