diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-07-31 16:36:09 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-07-31 16:36:09 -0600 |
commit | 753c87342ecb63da03961944f13bd80d897a45d8 (patch) | |
tree | e22d11b966d50315aae625bd499c049a83d15309 | |
parent | 46d2d7391d973f805d633c1a112ad37cc4ec1f78 (diff) | |
download | px4-nuttx-753c87342ecb63da03961944f13bd80d897a45d8.tar.gz px4-nuttx-753c87342ecb63da03961944f13bd80d897a45d8.tar.bz2 px4-nuttx-753c87342ecb63da03961944f13bd80d897a45d8.zip |
Audio: Change how the end of the audio stream is detected by the leaf audio component. This used by be done by looking for the first partial buffer. That does not work with the in-place sub-sampling performed by the PCM decoder: That always reduces the size of the buffer so that all buffers only partially filled by the time they get to the leaf. Now, a flag is set in the audio buffer flags set to indicate the final buffer in the stream.
-rw-r--r-- | apps/system/nxplayer/nxplayer.c | 23 | ||||
-rw-r--r-- | nuttx/drivers/audio/audio_null.c | 16 | ||||
-rw-r--r-- | nuttx/drivers/audio/vs1053.c | 124 | ||||
-rw-r--r-- | nuttx/drivers/audio/wm8904.c | 70 | ||||
-rw-r--r-- | nuttx/include/nuttx/audio/audio.h | 7 | ||||
-rw-r--r-- | nuttx/libc/audio/lib_buffer.c | 22 |
6 files changed, 174 insertions, 88 deletions
diff --git a/apps/system/nxplayer/nxplayer.c b/apps/system/nxplayer/nxplayer.c index d3c2366a3..49d015de6 100644 --- a/apps/system/nxplayer/nxplayer.c +++ b/apps/system/nxplayer/nxplayer.c @@ -489,7 +489,7 @@ static int nxplayer_mediasearch(FAR struct nxplayer_s *pPlayer, ****************************************************************************/ static int nxplayer_enqueuebuffer(FAR struct nxplayer_s *pPlayer, - FAR struct ap_buffer_s* pBuf) + FAR struct ap_buffer_s* apb) { struct audio_buf_desc_s bufdesc; int ret; @@ -510,10 +510,11 @@ static int nxplayer_enqueuebuffer(FAR struct nxplayer_s *pPlayer, /* Read data into the buffer. */ - pBuf->nbytes = fread(&pBuf->samp, 1, pBuf->nmaxbytes, pPlayer->fileFd); - pBuf->curbyte = 0; + apb->nbytes = fread(&apb->samp, 1, apb->nmaxbytes, pPlayer->fileFd); + apb->curbyte = 0; + apb->flags = 0; - if (pBuf->nbytes < pBuf->nmaxbytes) + if (apb->nbytes < apb->nmaxbytes) { int errcode = errno; int readerror = ferror(pPlayer->fileFd); @@ -523,14 +524,18 @@ static int nxplayer_enqueuebuffer(FAR struct nxplayer_s *pPlayer, */ audvdbg("Closing audio file, nbytes=%d readerr=%d\n", - pBuf->nbytes, readerror); + apb->nbytes, readerror); fclose(pPlayer->fileFd); pPlayer->fileFd = NULL; + /* Set a flag to indicate that this is the final buffer in the stream */ + + apb->flags |= AUDIO_APB_FINAL; + /* Was this a file read error */ - if (pBuf->nbytes == 0 && readerror) + if (apb->nbytes == 0 && readerror) { DEBUGASSERT(errcode > 0); @@ -541,7 +546,7 @@ static int nxplayer_enqueuebuffer(FAR struct nxplayer_s *pPlayer, /* Do nothing more if this was the end-of-file with nothing read */ - if (pBuf->nbytes > 0) + if (apb->nbytes > 0) { /* Now enqueue the buffer with the audio device. If the number of * bytes in the file happens to be an exact multiple of the audio @@ -553,8 +558,8 @@ static int nxplayer_enqueuebuffer(FAR struct nxplayer_s *pPlayer, #ifdef CONFIG_AUDIO_MULTI_SESSION bufdesc.session = pPlayer->session; #endif - bufdesc.numbytes = pBuf->nbytes; - bufdesc.u.pBuffer = pBuf; + bufdesc.numbytes = apb->nbytes; + bufdesc.u.pBuffer = apb; ret = ioctl(pPlayer->devFd, AUDIOIOC_ENQUEUEBUFFER, (unsigned long)&bufdesc); diff --git a/nuttx/drivers/audio/audio_null.c b/nuttx/drivers/audio/audio_null.c index e753f5171..4ebb0042f 100644 --- a/nuttx/drivers/audio/audio_null.c +++ b/nuttx/drivers/audio/audio_null.c @@ -650,6 +650,7 @@ static int null_enqueuebuffer(FAR struct audio_lowerhalf_s *dev, FAR struct ap_buffer_s *apb) { FAR struct null_dev_s *priv = (FAR struct null_dev_s *)dev; + bool final; audvdbg("apb=%p curbyte=%d nbytes=%d\n", apb, apb->curbyte, apb->nbytes); @@ -657,6 +658,10 @@ static int null_enqueuebuffer(FAR struct audio_lowerhalf_s *dev, apb->curbyte = apb->nbytes; + /* Check if this was the last buffer in the stream */ + + done = ((apb->flags & AUDIO_APB_FINAL) != 0); + /* And return the buffer to the upper level */ DEBUGASSERT(priv && apb && priv->dev.upper); @@ -671,6 +676,17 @@ static int null_enqueuebuffer(FAR struct audio_lowerhalf_s *dev, priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK); #endif + /* Say we are done playing if this was the last buffer in the stream */ + + if (done) + { +#ifdef CONFIG_AUDIO_MULTI_SESSION + priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_COMPLETE, NULL, OK, NULL); +#else + priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_COMPLETE, NULL, OK); +#endif + } + audvdbg("Return OK\n"); return OK; } diff --git a/nuttx/drivers/audio/vs1053.c b/nuttx/drivers/audio/vs1053.c index 734c884ae..102fa4e65 100644 --- a/nuttx/drivers/audio/vs1053.c +++ b/nuttx/drivers/audio/vs1053.c @@ -43,7 +43,9 @@ #include <sys/types.h> #include <sys/ioctl.h> + #include <stdint.h> +#include <stdbool.h> #include <stdio.h> #include <fcntl.h> #include <string.h> @@ -111,7 +113,7 @@ struct vs1053_struct_s const FAR struct vs1053_lower_s *hw_lower;/* Pointer to the hardware lower functions */ FAR struct spi_dev_s *spi; /* Pointer to the SPI bus */ - FAR struct ap_buffer_s *pBuf; /* Pointer to the buffer we are processing */ + FAR struct ap_buffer_s *apb; /* Pointer to the buffer we are processing */ struct dq_queue_s apbq; /* Our queue for enqueued buffers */ unsigned long spi_freq; /* Frequency to run the SPI bus at. */ unsigned long chip_freq; /* Current chip frequency */ @@ -131,13 +133,13 @@ struct vs1053_struct_s #endif uint16_t endfillbytes; uint8_t endfillchar; /* Fill char to send when no more data */ - uint8_t running; - uint8_t paused; - uint8_t endmode; + bool running; + bool paused; + bool endmode; #ifndef CONFIG_AUDIO_EXCLUDE_STOP - uint8_t cancelmode; + bool cancelmode; #endif - uint8_t busy; /* Set true when device reserved */ + bool busy; /* Set true when device reserved */ }; /**************************************************************************** @@ -511,7 +513,7 @@ static void vs1053_setvolume(FAR struct vs1053_struct_s *dev) leftreg = vs1053_logapprox(leftlevel / 10); rightreg = vs1053_logapprox(rightlevel / 10); - /* Lock the SPI bus to get exclsive access to the chip. */ + /* Lock the SPI bus to get exclusive access to the chip. */ vs1053_spi_lock(spi, dev->spi_freq); vs1053_writereg(dev, VS1053_SCI_VOL, (leftreg << 8) | rightreg); @@ -941,7 +943,7 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) int ret; uint8_t *pSamp = NULL; uint16_t reg; - struct ap_buffer_s *pBuf; + struct ap_buffer_s *apb; FAR struct spi_dev_s *spi = dev->spi; /* Check for false interrupt caused by an SCI transaction */ @@ -960,14 +962,14 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) /* Local stack copy of our active buffer */ - pBuf = dev->pBuf; - //auddbg("Entry pBuf=%p, Bytes left=%d\n", pBuf, pBuf->nbytes - pBuf->curbyte); + apb = dev->apb; + //auddbg("Entry apb=%p, Bytes left=%d\n", apb, apb->nbytes - apb->curbyte); /* Setup pointer to the next sample in the buffer */ - if (pBuf) + if (apb) { - pSamp = &pBuf->samp[pBuf->curbyte]; + pSamp = &apb->samp[apb->curbyte]; } else if (!dev->endmode) { @@ -1018,14 +1020,14 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) /* Do a hard reset and terminate */ vs1053_hardreset(dev); - dev->running = FALSE; - dev->endmode = FALSE; + dev->running = false; + dev->endmode = false; break; } else if (dev->endfillbytes > 32*65) { /* After each 32 byte of endfillchar, check the status - * register to see if SM_CANCEL has been cleard. If + * register to see if SM_CANCEL has been cleared. If * it has been cleared, then we're done. */ @@ -1041,8 +1043,9 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) auddbg("EndFillChar: 0x%0X\n", dev->endfillchar); reg = vs1053_readreg(dev, VS1053_SCI_MODE); vs1053_writereg(dev, VS1053_SCI_MODE, reg | VS1053_SM_RESET); - dev->running = FALSE; - dev->endmode = FALSE; + + dev->running = false; + dev->endmode = false; break; } } @@ -1055,7 +1058,7 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) * will recheck the DREQ line again. */ - bytecount = pBuf->nbytes - pBuf->curbyte; + bytecount = apb->nbytes - apb->curbyte; if (bytecount > 32) { bytecount = 32; @@ -1073,7 +1076,7 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) pSamp++; } #endif - pBuf->curbyte += bytecount; + apb->curbyte += bytecount; /* Test if we are in cancel mode. If we are, then we need * to continue sending file data and check for the SM_CANCEL @@ -1097,16 +1100,19 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) { /* Cancel has begun. Switch to endmode */ - pBuf->curbyte = pBuf->nbytes = 0; + apb->nbytes = 0; + apb->curbyte = 0; } } #endif /* CONFIG_AUDIO_EXCLUDE_STOP */ /* Test if we are at the end of the buffer */ - if (pBuf->curbyte >= pBuf->nbytes) + if (apb->curbyte >= apb->nbytes) { - if (pBuf->nbytes != pBuf->nmaxbytes) + /* Check if this was the final buffer in stream */ + + if ((apb->flags & AUDIO_APB_FINAL) != 0) { /* This is the final buffer. Get the VS1053 endfillchar */ @@ -1119,7 +1125,8 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) /* Mark the device as endmode */ - dev->endmode = TRUE; + dev->endmode = true; + #ifndef CONFIG_AUDIO_EXCLUDE_STOP if (dev->cancelmode) { @@ -1140,13 +1147,13 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) /* We referenced the buffer so we must free it */ - apb_free(pBuf); + apb_free(apb); #ifdef CONFIG_AUDIO_MULTI_SESSION dev->lower.upper(dev->lower.priv, AUDIO_CALLBACK_DEQUEUE, - pBuf, OK, NULL); + apb, OK, NULL); #else dev->lower.upper(dev->lower.priv, AUDIO_CALLBACK_DEQUEUE, - pBuf, OK); + apb, OK); #endif /* Lock the buffer queue to pop the next buffer */ @@ -1167,18 +1174,18 @@ static void vs1053_feeddata(FAR struct vs1053_struct_s *dev) /* Pop the next entry */ - pBuf = (struct ap_buffer_s *) dq_remfirst(&dev->apbq); - dev->pBuf = pBuf; + apb = (struct ap_buffer_s *) dq_remfirst(&dev->apbq); + dev->apb = apb; - //auddbg("Next Buffer = %p, bytes = %d\n", pBuf, pBuf ? pBuf->nbytes : 0); - if (pBuf == NULL) + //auddbg("Next Buffer = %p, bytes = %d\n", apb, apb ? apb->nbytes : 0); + if (apb == NULL) { sem_post(&dev->apbq_sem); break; } - pSamp = &pBuf->samp[pBuf->curbyte]; - apb_reference(pBuf); /* Add our buffer reference */ + pSamp = &apb->samp[apb->curbyte]; + apb_reference(apb); /* Add our buffer reference */ sem_post(&dev->apbq_sem); } } @@ -1254,7 +1261,7 @@ static void *vs1053_workerthread(pthread_addr_t pvarg) { FAR struct vs1053_struct_s *dev = (struct vs1053_struct_s *) pvarg; struct audio_msg_s msg; - FAR struct ap_buffer_s *pBuf; + FAR struct ap_buffer_s *apb; int size; int prio; #ifndef CONFIG_AUDIO_EXCLUDE_STOP @@ -1265,9 +1272,10 @@ static void *vs1053_workerthread(pthread_addr_t pvarg) auddbg("Entry\n"); #ifndef CONFIG_AUDIO_EXCLUDE_STOP - dev->cancelmode = 0; + dev->cancelmode = false; #endif - dev->endmode = dev->endfillbytes = 0; + dev->endmode = false; + dev->endfillbytes = 0; /* Fill the VS1053 FIFO with initial data. */ @@ -1284,7 +1292,7 @@ static void *vs1053_workerthread(pthread_addr_t pvarg) /* Loop as long as we are supposed to be running */ - dev->running = TRUE; + dev->running = true; dev->hw_lower->enable(dev->hw_lower); /* Enable the DREQ interrupt */ while (dev->running || dev->endmode) { @@ -1303,7 +1311,7 @@ static void *vs1053_workerthread(pthread_addr_t pvarg) { /* Should we just stop running? */ - dev->running = FALSE; + dev->running = false; break; } @@ -1338,7 +1346,7 @@ static void *vs1053_workerthread(pthread_addr_t pvarg) /* Set cancelmode */ - dev->cancelmode = TRUE; + dev->cancelmode = true; break; #endif @@ -1363,7 +1371,7 @@ static void *vs1053_workerthread(pthread_addr_t pvarg) { /* Get the next buffer from the queue */ - while ((pBuf = (FAR struct ap_buffer_s *) dq_remfirst(&dev->apbq)) != NULL) + while ((apb = (FAR struct ap_buffer_s *) dq_remfirst(&dev->apbq)) != NULL) ; } @@ -1371,10 +1379,10 @@ static void *vs1053_workerthread(pthread_addr_t pvarg) /* Free the active buffer */ - if (dev->pBuf != NULL) + if (dev->apb != NULL) { - apb_free(dev->pBuf); - dev->pBuf = NULL; + apb_free(dev->apb); + dev->apb = NULL; } /* Close the message queue */ @@ -1458,8 +1466,8 @@ static int vs1053_start(FAR struct audio_lowerhalf_s *lower) if ((ret = sem_wait(&dev->apbq_sem)) == OK) { - dev->pBuf = (FAR struct ap_buffer_s *) dq_remfirst(&dev->apbq); - apb_reference(dev->pBuf); /* Add our buffer reference */ + dev->apb = (FAR struct ap_buffer_s *) dq_remfirst(&dev->apbq); + apb_reference(dev->apb); /* Add our buffer reference */ sem_post(&dev->apbq_sem); } else @@ -1560,11 +1568,13 @@ static int vs1053_pause(FAR struct audio_lowerhalf_s *lower) FAR struct vs1053_struct_s *dev = (struct vs1053_struct_s *) lower; if (!dev->running) - return OK; + { + return OK; + } - /* Disable interrupts to prevent us from suppling any more data */ + /* Disable interrupts to prevent us from supplying any more data */ - dev->paused = TRUE; + dev->paused = true; dev->hw_lower->disable(dev->hw_lower); /* Disable the DREQ interrupt */ return OK; } @@ -1587,11 +1597,13 @@ static int vs1053_resume(FAR struct audio_lowerhalf_s *lower) FAR struct vs1053_struct_s *dev = (struct vs1053_struct_s *) lower; if (!dev->running) - return OK; + { + return OK; + } /* Enable interrupts to allow suppling data */ - dev->paused = FALSE; + dev->paused = false; vs1053_feeddata(dev); dev->hw_lower->enable(dev->hw_lower); /* Enable the DREQ interrupt */ return OK; @@ -1621,7 +1633,7 @@ static int vs1053_enqueuebuffer(FAR struct audio_lowerhalf_s *lower, /* We can now safely add the buffer to the queue */ apb->curbyte = 0; - apb->flags = AUDIO_APB_OUTPUT_ENQUEUED; + apb->flags |= AUDIO_APB_OUTPUT_ENQUEUED; dq_addlast(&apb->dq_entry, &dev->apbq); sem_post(&dev->apbq_sem); @@ -1730,9 +1742,9 @@ static int vs1053_reserve(FAR struct audio_lowerhalf_s *lower) #ifdef CONFIG_AUDIO_MULTI_SESSION *psession = NULL; #endif - dev->busy = TRUE; - dev->running = FALSE; - dev->paused = FALSE; + dev->busy = true; + dev->running = false; + dev->paused = false; } sem_post(&dev->apbq_sem); @@ -1774,7 +1786,7 @@ static int vs1053_release(FAR struct audio_lowerhalf_s *lower) /* Really we should free any queued buffers here */ - dev->busy = 0; + dev->busy = false; sem_post(&dev->apbq_sem); return OK; @@ -1825,9 +1837,9 @@ struct audio_lowerhalf_s *vs1053_initialize(FAR struct spi_dev_s *spi, dev->spi_freq = CONFIG_VS1053_XTALI / 7; dev->spi = spi; dev->mq = NULL; - dev->busy = FALSE; + dev->busy = false; dev->threadid = 0; - dev->running = 0; + dev->running = false; #ifndef CONFIG_AUDIO_EXCLUDE_VOLUME dev->volume = 250; /* 25% volume as default */ diff --git a/nuttx/drivers/audio/wm8904.c b/nuttx/drivers/audio/wm8904.c index 02f83f375..1120aa2da 100644 --- a/nuttx/drivers/audio/wm8904.c +++ b/nuttx/drivers/audio/wm8904.c @@ -451,6 +451,8 @@ static void wm8904_setvolume(FAR struct wm8904_dev_s *priv, uint16_t volume, uint32_t rightlevel; uint16_t regval; + audvdbg("volume=%u mute=%u\n", volume, mute); + #ifndef CONFIG_AUDIO_EXCLUDE_BALANCE /* Calculate the left channel volume level {0..1000} */ @@ -524,6 +526,7 @@ static void wm8904_setvolume(FAR struct wm8904_dev_s *priv, uint16_t volume, #ifndef CONFIG_AUDIO_EXCLUDE_TONE static void wm8904_setbass(FAR struct wm8904_dev_s *priv, uint8_t bass) { + audvdbg("bass=%u\n", bass); #warning Missing logic } #endif /* CONFIG_AUDIO_EXCLUDE_TONE */ @@ -541,6 +544,7 @@ static void wm8904_setbass(FAR struct wm8904_dev_s *priv, uint8_t bass) #ifndef CONFIG_AUDIO_EXCLUDE_TONE static void wm8904_settreble(FAR struct wm8904_dev_s *priv, uint8_t treble) { + audvdbg("treble=%u\n", treble); #warning Missing logic } #endif /* CONFIG_AUDIO_EXCLUDE_TONE */ @@ -555,11 +559,10 @@ static void wm8904_settreble(FAR struct wm8904_dev_s *priv, uint8_t treble) static int wm8904_getcaps(FAR struct audio_lowerhalf_s *dev, int type, FAR struct audio_caps_s *caps) { - audvdbg("Entry\n"); - /* Validate the structure */ - DEBUGASSERT(caps->ac_len >= sizeof(struct audio_caps_s)); + DEBUGASSERT(caps && caps->ac_len >= sizeof(struct audio_caps_s)); + audvdbg("type=%d ac_type=%d\n", type, caps->ac_type); /* Fill in the caller's structure based on requested info */ @@ -726,6 +729,7 @@ static int wm8904_configure(FAR struct audio_lowerhalf_s *dev, #endif int ret = OK; + DEBUGASSERT(priv && caps); audvdbg("ac_type: %d\n", caps->ac_type); /* Process the configure operation */ @@ -858,6 +862,7 @@ static int wm8904_shutdown(FAR struct audio_lowerhalf_s *dev) { FAR struct wm8904_dev_s *priv = (FAR struct wm8904_dev_s *)dev; + DEBUGASSERT(priv); wm8904_reset(priv); return OK; } @@ -881,6 +886,7 @@ static void wm8904_senddone(FAR struct i2s_dev_s *i2s, int ret; DEBUGASSERT(i2s && priv && priv->running && apb); + audvdbg("apb=%p inflight=%d\n", apb, priv->inflight); /* We do not place any restriction on the context in which this function * is called. It may be called from an interrupt handler. Therefore, the @@ -933,7 +939,7 @@ static void wm8904_senddone(FAR struct i2s_dev_s *i2s, static void wm8904_returnbuffers(FAR struct wm8904_dev_s *priv) { FAR struct ap_buffer_s *apb; - irqstate_t flags; + irqstate_t flags; /* The doneq and in-flight values might be accessed from the interrupt * level in some implementations. Not the best design. But we will @@ -943,14 +949,43 @@ static void wm8904_returnbuffers(FAR struct wm8904_dev_s *priv) flags = irqsave(); while (dq_peek(&priv->doneq) != NULL) { - /* Take next buffer from the queue of completed transfers */ + /* Take the next buffer from the queue of completed transfers */ apb = (FAR struct ap_buffer_s *)dq_remfirst(&priv->doneq); irqrestore(flags); + audvdbg("Returning apb=%p flags=%04x\n", apb, apb->flags); + + /* Are we returning the final buffer in the stream? */ + + if ((apb->flags & AUDIO_APB_FINAL) != 0) + { + /* Both the pending and the done queues should be empty and there + * should be no buffers in-flight. + */ + + DEBUGASSERT(dq_empty(&priv->doneq) && dq_empty(&priv->pendq) && + priv->inflight == 0); + + /* Set the terminating flag. This will, eventually, cause the + * worker thread to exit (if it is not already terminating). + */ + + audvdbg("Terminating\n"); + priv->terminating = true; + } + /* Release our reference to the audio buffer */ apb_free(apb); + + /* Send the buffer back up to the previous level. */ + +#ifdef CONFIG_AUDIO_MULTI_SESSION + priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK, NULL); +#else + priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK); +#endif flags = irqsave(); } @@ -993,7 +1028,8 @@ static int wm8904_sendbuffer(FAR struct wm8904_dev_s *priv) /* Take next buffer from the queue of pending transfers */ apb = (FAR struct ap_buffer_s *)dq_remfirst(&priv->pendq); - audvdbg("Sending apb=%p, size=%d\n", apb, apb->nbytes); + audvdbg("Sending apb=%p, size=%d inflight=%d\n", + apb, apb->nbytes, priv->inflight); /* Increment the number of buffers in-flight before sending in order * to avoid a possible race condition. @@ -1082,7 +1118,9 @@ static void *wm8904_workerthread(pthread_addr_t pvarg) WM8904_ENABLE(priv->lower); wm8904_setvolume(priv, priv->volume, false); - /* Loop as long as we are supposed to be running */ + /* Loop as long as we are supposed to be running and as long as we have + * buffers in-flight. + */ while (priv->running || priv->inflight > 0) { @@ -1125,7 +1163,7 @@ static void *wm8904_workerthread(pthread_addr_t pvarg) */ case AUDIO_MSG_DATA_REQUEST: - /* REVISIT this */ + audvdbg("AUDIO_MSG_DATA_REQUEST\n"); break; /* Stop the playback */ @@ -1134,6 +1172,7 @@ static void *wm8904_workerthread(pthread_addr_t pvarg) case AUDIO_MSG_STOP: /* Indicate that we are terminating */ + audvdbg("AUDIO_MSG_STOP: Terminating\n"); priv->terminating = true; break; #endif @@ -1143,11 +1182,13 @@ static void *wm8904_workerthread(pthread_addr_t pvarg) */ case AUDIO_MSG_ENQUEUE: + audvdbg("AUDIO_MSG_ENQUEUE\n"); break; /* We will wake up from the I2S callback with this message */ case AUDIO_MSG_COMPLETE: + audvdbg("AUDIO_MSG_COMPLETE\n"); wm8904_returnbuffers(priv); break; @@ -1170,6 +1211,14 @@ static void *wm8904_workerthread(pthread_addr_t pvarg) /* Release our reference to the buffer */ apb_free(apb); + + /* Send the buffer back up to the previous level. */ + +#ifdef CONFIG_AUDIO_MULTI_SESSION + priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK, NULL); +#else + priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK); +#endif } wm8904_givesem(&priv->pendsem); @@ -1386,7 +1435,7 @@ static int wm8904_enqueuebuffer(FAR struct audio_lowerhalf_s *dev, struct audio_msg_s term_msg; int ret = -EAGAIN; - audvdbg("Entry\n"); + audvdbg("apb=%p\n", apb); /* Take a reference on the new audio buffer */ @@ -1395,7 +1444,7 @@ static int wm8904_enqueuebuffer(FAR struct audio_lowerhalf_s *dev, /* Add the new buffer to the tail of pending audio buffers */ wm8904_takesem(&priv->pendsem); - apb->flags = AUDIO_APB_OUTPUT_ENQUEUED; + apb->flags |= AUDIO_APB_OUTPUT_ENQUEUED; dq_addlast(&apb->dq_entry, &priv->pendq); wm8904_givesem(&priv->pendsem); @@ -1434,6 +1483,7 @@ static int wm8904_enqueuebuffer(FAR struct audio_lowerhalf_s *dev, static int wm8904_cancelbuffer(FAR struct audio_lowerhalf_s *dev, FAR struct ap_buffer_s *apb) { + audvdbg("apb=%p\n", apb); return OK; } diff --git a/nuttx/include/nuttx/audio/audio.h b/nuttx/include/nuttx/audio/audio.h index 351e9ec54..78fc1944e 100644 --- a/nuttx/include/nuttx/audio/audio.h +++ b/nuttx/include/nuttx/audio/audio.h @@ -289,9 +289,10 @@ /* Audio Pipeline Buffer flags */ -#define AUDIO_APB_OUTPUT_ENQUEUED 0x0001; -#define AUDIO_APB_OUTPUT_PROCESS 0x0002; -#define AUDIO_APB_DEQUEUED 0x0004; +#define AUDIO_APB_OUTPUT_ENQUEUED (1 << 0) +#define AUDIO_APB_OUTPUT_PROCESS (1 << 1) +#define AUDIO_APB_DEQUEUED (1 << 2) +#define AUDIO_APB_FINAL (1 << 3) /* Last buffer in the stream */ /**************************************************************************** * Public Types diff --git a/nuttx/libc/audio/lib_buffer.c b/nuttx/libc/audio/lib_buffer.c index cf518de16..50c504b46 100644 --- a/nuttx/libc/audio/lib_buffer.c +++ b/nuttx/libc/audio/lib_buffer.c @@ -118,15 +118,15 @@ int apb_alloc(FAR struct audio_buf_desc_s *bufdesc) { uint32_t bufsize; int ret; - struct ap_buffer_s *pBuf; + struct ap_buffer_s *apb; DEBUGASSERT(bufdesc->u.ppBuffer != NULL); /* Perform a user mode allocation */ bufsize = sizeof(struct ap_buffer_s) + bufdesc->numbytes; - pBuf = lib_umalloc(bufsize); - *bufdesc->u.ppBuffer = pBuf; + apb = lib_umalloc(bufsize); + *bufdesc->u.ppBuffer = apb; /* Test if the allocation was successful or not */ @@ -138,15 +138,17 @@ int apb_alloc(FAR struct audio_buf_desc_s *bufdesc) { /* Populate the buffer contents */ - memset(pBuf, 0, bufsize); - pBuf->i.channels = 1; - pBuf->crefs = 1; - pBuf->nmaxbytes = bufdesc->numbytes; - pBuf->nbytes = 0; + memset(apb, 0, bufsize); + apb->i.channels = 1; + apb->crefs = 1; + apb->nmaxbytes = bufdesc->numbytes; + apb->nbytes = 0; + apb->flags = 0; #ifdef CONFIG_AUDIO_MULTI_SESSION - pBuf->session = bufdesc->session; + apb->session = bufdesc->session; #endif - sem_init(&pBuf->sem, 0, 1); + + sem_init(&apb->sem, 0, 1); ret = sizeof(struct audio_buf_desc_s); } |