VirtualBox

Changeset 88253 in vbox


Ignore:
Timestamp:
Mar 22, 2021 6:14:09 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143453
Message:

DrvAudio,++: Started going over and tidying up the StreamPlay functionality. First major change is to treat the RAW layout just like non-RAW ones and count all in bytes. bugref:9890

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmaudioifs.h

    r88144 r88253  
    18241824     * @param   pStream     Pointer to audio stream.
    18251825     * @param   pvBuf       Pointer to audio data buffer to play.
    1826      * @param   uBufSize    The audio data buffer size (see note below for unit).
    1827      * @param   puWritten   Number of unit written.
    1828      * @note    The @a uBufSize and @a puWritten values are in bytes for non-raw
    1829      *          layout streams and in frames for raw layout ones.
     1826     * @param   cbBuf       The number of bytes of audio data to play.
     1827     * @param   pcbWritten  Where to return the actual number of bytes played.
    18301828     */
    18311829    DECLR3CALLBACKMEMBER(int, pfnStreamPlay, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    1832                                               const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten));
     1830                                              const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten));
    18331831
    18341832    /**
     
    18741872
    18751873/** PDMIHOSTAUDIO interface ID. */
    1876 #define PDMIHOSTAUDIO_IID                           "007847a0-0075-4964-007d-343f0010f081"
     1874#define PDMIHOSTAUDIO_IID                           "be34182b-d579-41e8-96e0-abb94900460f"
    18771875
    18781876/** @} */
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp

    r88061 r88253  
    149149 * @remark  This function is not thread safe!
    150150 */
     151/** @todo r=bird: This isn't a 'ing Peek function, it's a Read function!
     152 *        Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaarg!!!!!!!!!!!!!!!!!!! */
    151153int AudioMixBufPeek(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToRead,
    152154                    PPDMAUDIOFRAME paFrameBuf, uint32_t cFrameBuf, uint32_t *pcFramesRead)
     
    15411543 * Reads audio frames. The audio format of the mixing buffer will be used.
    15421544 *
    1543  * @return  IPRT status code.
    1544  * @param   pMixBuf                 Mixing buffer to read audio frames from.
    1545  * @param   pvBuf                   Pointer to buffer to write output to.
    1546  * @param   cbBuf                   Size (in bytes) of buffer to write to.
    1547  * @param   pcBlock                 Returns acquired block to read (in audio frames).
    1548  */
    1549 int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcBlock)
    1550 {
    1551     return AudioMixBufAcquireReadBlockEx(pMixBuf, pMixBuf->uAudioFmt, pvBuf, cbBuf, pcBlock);
     1545 * @returns VBox status code.
     1546 * @param   pMixBuf             Mixing buffer to read audio frames from.
     1547 * @param   pvBuf               Pointer to buffer to write output to.
     1548 * @param   cbBuf               Size (in bytes) of buffer to write to.
     1549 * @param   pcAcquiredFrames    Where to return the number of frames in
     1550 *                              the block that was acquired.
     1551 */
     1552int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames)
     1553{
     1554    return AudioMixBufAcquireReadBlockEx(pMixBuf, pMixBuf->uAudioFmt, pvBuf, cbBuf, pcAcquiredFrames);
    15521555}
    15531556
     
    15581561 *
    15591562 * @return  IPRT status code.
    1560  * @param   pMixBuf                 Mixing buffer to read audio frames from.
    1561  * @param   enmFmt                  Audio format to use for output.
    1562  * @param   pvBuf                   Pointer to buffer to write output to.
    1563  * @param   cbBuf                   Size (in bytes) of buffer to write to.
    1564  * @param   pcBlock                 Returns acquired block to read (in audio frames).
    1565  */
    1566 int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, uint32_t cbBuf,
    1567                                   uint32_t *pcBlock)
     1563 * @param   pMixBuf             Mixing buffer to read audio frames from.
     1564 * @param   enmFmt              Audio format to use for output.
     1565 * @param   pvBuf               Pointer to buffer to write output to.
     1566 * @param   cbBuf               Size (in bytes) of buffer to write to.
     1567 * @param   pcAcquiredFrames    Where to return the number of frames in
     1568 *                              the block that was acquired.
     1569 */
     1570int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt,
     1571                                  void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames)
    15681572{
    15691573    AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
    1570     AssertReturn(cbBuf,      VERR_INVALID_PARAMETER);
    1571     AssertPtrReturn(pvBuf,   VERR_INVALID_POINTER);
    1572     AssertPtrReturn(pcBlock, VERR_INVALID_POINTER);
     1574    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
     1575    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     1576    AssertPtrReturn(pcAcquiredFrames, VERR_INVALID_POINTER);
    15731577
    15741578    /* Make sure that we at least have space for a full audio frame. */
    15751579    AssertReturn(AUDIOMIXBUF_B2F(pMixBuf, cbBuf), VERR_INVALID_PARAMETER);
    15761580
    1577     uint32_t cToRead = RT_MIN(pMixBuf->cUsed, AUDIOMIXBUF_B2F(pMixBuf, cbBuf));
    1578 
    1579     AUDMIXBUF_LOG(("%s: cbBuf=%RU32 (%RU32 frames), cToRead=%RU32, fmtSrc=0x%x, fmtDst=0x%x\n",
    1580                    pMixBuf->pszName, cbBuf, AUDIOMIXBUF_B2F(pMixBuf, cbBuf), cToRead, pMixBuf->uAudioFmt, enmFmt));
    1581 
    1582     if (!cToRead)
     1581    uint32_t cFramesToRead = RT_MIN(pMixBuf->cUsed, AUDIOMIXBUF_B2F(pMixBuf, cbBuf));
     1582
     1583    AUDMIXBUF_LOG(("%s: cbBuf=%RU32 (%RU32 frames), cFramesToRead=%RU32, fmtSrc=0x%x, fmtDst=0x%x\n",
     1584                   pMixBuf->pszName, cbBuf, AUDIOMIXBUF_B2F(pMixBuf, cbBuf), cFramesToRead, pMixBuf->uAudioFmt, enmFmt));
     1585
     1586    if (!cFramesToRead)
    15831587    {
    15841588#ifdef DEBUG
    15851589        audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);
    15861590#endif
    1587         *pcBlock = 0;
     1591        *pcAcquiredFrames = 0;
    15881592        return VINF_SUCCESS;
    15891593    }
    15901594
    1591     PFNPDMAUDIOMIXBUFCONVTO pfnConvTo = NULL;
    1592     if (pMixBuf->uAudioFmt != enmFmt)
     1595    PFNPDMAUDIOMIXBUFCONVTO pfnConvTo;
     1596    if (pMixBuf->uAudioFmt == enmFmt)
     1597        pfnConvTo = pMixBuf->pfnConvTo;
     1598    else
    15931599        pfnConvTo = audioMixBufConvToLookup(enmFmt);
    1594     else
    1595         pfnConvTo = pMixBuf->pfnConvTo;
    1596 
    1597     if (!pfnConvTo) /* Audio format not supported. */
    1598     {
    1599         AssertFailed();
    1600         return VERR_NOT_SUPPORTED;
    1601     }
    1602 
    1603     cToRead = RT_MIN(cToRead, pMixBuf->cFrames - pMixBuf->offRead);
    1604     if (cToRead)
     1600    AssertReturn(pfnConvTo, VERR_NOT_SUPPORTED);
     1601
     1602    cFramesToRead = RT_MIN(cFramesToRead, pMixBuf->cFrames - pMixBuf->offRead);
     1603    if (cFramesToRead)
    16051604    {
    16061605        PDMAUDMIXBUFCONVOPTS convOpts;
    16071606        RT_ZERO(convOpts);
    1608         convOpts.cFrames = cToRead;
    1609 
    1610         AUDMIXBUF_LOG(("cToRead=%RU32\n", cToRead));
     1607        convOpts.cFrames = cFramesToRead;
     1608
     1609        AUDMIXBUF_LOG(("cFramesToRead=%RU32\n", cFramesToRead));
    16111610
    16121611        pfnConvTo(pvBuf, pMixBuf->pFrames + pMixBuf->offRead, &convOpts);
     
    16181617        if (RT_SUCCESS(rc2))
    16191618        {
    1620             RTFileWrite(fh, pvBuf, AUDIOMIXBUF_F2B(pMixBuf, cToRead), NULL);
     1619            RTFileWrite(fh, pvBuf, AUDIOMIXBUF_F2B(pMixBuf, cFramesToRead), NULL);
    16211620            RTFileClose(fh);
    16221621        }
     
    16241623    }
    16251624
    1626     *pcBlock = cToRead;
     1625    *pcAcquiredFrames = cFramesToRead;
    16271626
    16281627#ifdef DEBUG
     
    16301629#endif
    16311630
    1632     AUDMIXBUF_LOG(("cRead=%RU32 (%RU32 bytes)\n", cToRead, AUDIOMIXBUF_F2B(pMixBuf, cToRead)));
     1631    AUDMIXBUF_LOG(("*pcAcquiredFrames=%RU32 (%RU32 bytes)\n", cFramesToRead, AUDIOMIXBUF_F2B(pMixBuf, cFramesToRead)));
    16331632    return VINF_SUCCESS;
    16341633}
    16351634
    16361635/**
    1637  * Releases a formerly acquired read block again.
    1638  *
    1639  * @param   pMixBuf             Mixing buffer to release acquired read block for.
    1640  * @param   cBlock              Size of the block to release (in audio frames).
    1641  */
    1642 void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cBlock)
     1636 * Releases a formerly acquired read block.
     1637 *
     1638 * @param   pMixBuf     Mixing buffer to release acquired read block for.
     1639 * @param   cFrames     The number of frames to release.  (Can be less than the
     1640 *                      acquired count.)
     1641 */
     1642void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames)
    16431643{
    16441644    AssertPtrReturnVoid(pMixBuf);
    16451645
    1646     if (!cBlock)
    1647         return;
    1648 
    1649     pMixBuf->offRead  = (pMixBuf->offRead + cBlock) % pMixBuf->cFrames;
    1650     Assert(pMixBuf->cUsed >= cBlock);
    1651     pMixBuf->cUsed   -= RT_MIN(cBlock, pMixBuf->cUsed);
     1646    if (cFrames)
     1647    {
     1648        AssertStmt(pMixBuf->cUsed >= cFrames, cFrames = pMixBuf->cUsed);
     1649        pMixBuf->offRead  = (pMixBuf->offRead + cFrames) % pMixBuf->cFrames;
     1650        pMixBuf->cUsed   -= cFrames;
     1651    }
    16521652}
    16531653
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.h

    r82968 r88253  
    7070int AudioMixBufReadAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
    7171int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
    72 int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcBlock);
    73 int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, uint32_t cbBuf, uint32_t *pcBlock);
    74 void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cBlock);
     72int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames);
     73int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames);
     74void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames);
    7575uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf);
    7676void AudioMixBufReset(PPDMAUDIOMIXBUF pMixBuf);
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r88243 r88253  
    14461446
    14471447/**
    1448  * Plays an audio host output stream which has been configured for non-interleaved (layout) data.
     1448 * Worker for drvAudioStreamPlay that plays non-interleaved data.
     1449 *
     1450 * @returns VBox status code.
     1451 * @param   pThis           The audio driver instance data.
     1452 * @param   pStream         The stream to play.
     1453 * @param   cFramesToPlay   Number of audio frames to play.
     1454 * @param   pcFramesPlayed  Where to return the number of audio frames played.
     1455 */
     1456static int drvAudioStreamPlayNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream,
     1457                                            uint32_t cFramesToPlay, uint32_t *pcFramesPlayed)
     1458{
     1459    Assert(pStream->enmDir == PDMAUDIODIR_OUT);
     1460    Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
     1461
     1462    /*
     1463     * Push data to the host device.
     1464     */
     1465    int      rc          = VINF_SUCCESS;
     1466    uint32_t cFramesLeft = cFramesToPlay;
     1467    while (cFramesLeft > 0)
     1468    {
     1469        /*
     1470         * Grab a chunk of audio data in the backend format.
     1471         */
     1472        uint8_t  abChunk[_4K];
     1473        uint32_t cFramesRead = 0;
     1474        rc = AudioMixBufAcquireReadBlock(&pStream->Host.MixBuf, abChunk,
     1475                                         RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cFramesLeft)),
     1476                                         &cFramesRead);
     1477        AssertRCBreak(rc);
     1478
     1479        uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cFramesRead);
     1480        Assert(cbRead <= sizeof(abChunk));
     1481
     1482        /*
     1483         * Feed it to the backend.
     1484         */
     1485        uint32_t cFramesPlayed = 0;
     1486        uint32_t cbPlayed      = 0;
     1487        rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, abChunk, cbRead, &cbPlayed);
     1488        if (RT_SUCCESS(rc))
     1489        {
     1490            if (cbPlayed)
     1491            {
     1492                if (pThis->Out.Cfg.Dbg.fEnabled)
     1493                    AudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */);
     1494
     1495                if (cbRead != cbPlayed)
     1496                    LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n",
     1497                             pStream->szName, cbRead, cbPlayed));
     1498
     1499                cFramesPlayed  = AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbPlayed);
     1500                AssertStmt(cFramesLeft >= cFramesPlayed, cFramesPlayed = cFramesLeft);
     1501                cFramesLeft   -= cFramesPlayed;
     1502            }
     1503            else
     1504            {
     1505                /** @todo r=bird: If the backend is doing non-blocking writes, we'll probably
     1506                 *        be spinning like crazy here...  The ALSA backend is non-blocking.   */
     1507            }
     1508        }
     1509
     1510        AudioMixBufReleaseReadBlock(&pStream->Host.MixBuf, cFramesPlayed);
     1511
     1512        AssertRCBreak(rc); /* (this is here for Acquire/Release symmetry - which isn't at all necessary) */
     1513    }
     1514
     1515    Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc));
     1516    *pcFramesPlayed = cFramesToPlay - cFramesLeft;
     1517    return rc;
     1518}
     1519
     1520/**
     1521 * Plays an audio host output stream which has been configured for raw audio (layout) data.
    14491522 *
    14501523 * @returns VBox status code.
    14511524 * @param   pThis               Pointer to driver instance.
    14521525 * @param   pStream             Stream to play.
    1453  * @param   cfToPlay            Number of audio frames to play.
    1454  * @param   pcfPlayed           Returns number of audio frames played. Optional.
    1455  */
    1456 static int drvAudioStreamPlayNonInterleaved(PDRVAUDIO pThis,
    1457                                             PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed)
    1458 {
    1459     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1460     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1461     AssertPtrNullReturn(pcfPlayed, VERR_INVALID_POINTER);
     1526 * @param   cFramesToPlay       Number of audio frames to play.
     1527 * @param   pcFramesPlayed      Where to return number of audio frames played.
     1528 */
     1529static int drvAudioStreamPlayRaw(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t cFramesToPlay, uint32_t *pcFramesPlayed)
     1530{
    14621531    Assert(pStream->enmDir == PDMAUDIODIR_OUT);
    1463     Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
     1532    Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
    14641533
    14651534    /*
    14661535     * ...
    14671536     */
    1468     if (!cfToPlay)
    1469     {
    1470         if (pcfPlayed)
    1471             *pcfPlayed = 0;
    1472         return VINF_SUCCESS;
    1473     }
    1474 
    1475     /*
    1476      * ...
    1477      */
    1478     int      rc            = VINF_SUCCESS;
    1479     uint32_t cfPlayedTotal = 0;
    1480     uint32_t cfLeft        = cfToPlay;
    1481     while (cfLeft)
    1482     {
    1483         uint8_t  abChunk[_4K];
    1484         uint32_t cfRead = 0;
    1485         rc = AudioMixBufAcquireReadBlock(&pStream->Host.MixBuf,
    1486                                          abChunk, RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfLeft)),
    1487                                          &cfRead);
    1488         if (RT_FAILURE(rc))
    1489             break;
    1490 
    1491         uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfRead);
    1492         Assert(cbRead <= sizeof(abChunk));
    1493 
    1494         uint32_t cfPlayed = 0;
    1495         uint32_t cbPlayed = 0;
    1496         rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, abChunk, cbRead, &cbPlayed);
    1497         if (   RT_SUCCESS(rc)
    1498             && cbPlayed)
    1499         {
    1500             if (pThis->Out.Cfg.Dbg.fEnabled)
    1501                 AudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */);
    1502 
    1503             if (cbRead != cbPlayed)
    1504                 LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n",
    1505                          pStream->szName, cbRead, cbPlayed));
    1506 
    1507             cfPlayed       = AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbPlayed);
    1508             cfPlayedTotal += cfPlayed;
    1509 
    1510             Assert(cfLeft >= cfPlayed);
    1511             cfLeft        -= cfPlayed;
    1512         }
    1513 
    1514         AudioMixBufReleaseReadBlock(&pStream->Host.MixBuf, cfPlayed);
    1515 
    1516         if (RT_FAILURE(rc))
    1517             break;
    1518     }
    1519 
    1520     Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cfPlayedTotal, cfToPlay, rc));
    1521 
    1522     if (RT_SUCCESS(rc))
    1523     {
    1524         if (pcfPlayed)
    1525             *pcfPlayed = cfPlayedTotal;
    1526     }
    1527 
    1528     return rc;
    1529 }
    1530 
    1531 /**
    1532  * Plays an audio host output stream which has been configured for raw audio (layout) data.
    1533  *
    1534  * @returns VBox status code.
    1535  * @param   pThis               Pointer to driver instance.
    1536  * @param   pStream             Stream to play.
    1537  * @param   cfToPlay            Number of audio frames to play.
    1538  * @param   pcfPlayed           Returns number of audio frames played. Optional.
    1539  */
    1540 static int drvAudioStreamPlayRaw(PDRVAUDIO pThis,
    1541                                  PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed)
    1542 {
    1543     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1544     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1545     AssertPtrNullReturn(pcfPlayed, VERR_INVALID_POINTER);
    1546     Assert(pStream->enmDir == PDMAUDIODIR_OUT);
    1547     Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
    1548 
    1549     /*
    1550      * ...
    1551      */
    1552     if (!cfToPlay)
    1553     {
    1554         if (pcfPlayed)
    1555             *pcfPlayed = 0;
    1556         return VINF_SUCCESS;
    1557     }
    1558 
    1559     /*
    1560      * ...
    1561      */
    1562     int         rc              = VINF_SUCCESS;
    1563     uint32_t    cfPlayedTotal   = 0;
    1564     uint32_t    cfLeft          = cfToPlay;
    1565     while (cfLeft)
     1537    int      rc          = VINF_SUCCESS;
     1538    uint32_t cFramesLeft = cFramesToPlay;
     1539    while (cFramesLeft > 0)
    15661540    {
    15671541        PDMAUDIOFRAME   aFrames[_2K];
    1568         uint32_t        cfRead = 0;
    1569         rc = AudioMixBufPeek(&pStream->Host.MixBuf, cfLeft, aFrames, RT_MIN(cfLeft, RT_ELEMENTS(aFrames)), &cfRead);
     1542        uint32_t        cFramesRead = 0;
     1543        /** @todo r=bird: Peek functions do _not_ generally drop stuff from what they're
     1544         *        peeking into.  We normally name such functions Read.  (Oh man, am I
     1545         *        getting tired of this kind of crap.) */
     1546        rc = AudioMixBufPeek(&pStream->Host.MixBuf, cFramesLeft, aFrames,
     1547                             RT_MIN(cFramesLeft, RT_ELEMENTS(aFrames)), &cFramesRead);
    15701548        if (RT_SUCCESS(rc))
    15711549        {
    1572             if (cfRead)
    1573             {
    1574                 /* Note: As the stream layout is RPDMAUDIOSTREAMLAYOUT_RAW, operate on audio frames rather on bytes. */
    1575                 Assert(cfRead <= RT_ELEMENTS(aFrames));
    1576                 uint32_t cfPlayed = 0;
    1577                 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, aFrames, cfRead, &cfPlayed);
    1578                 if (   RT_FAILURE(rc)
    1579                     || !cfPlayed)
    1580                     break;
    1581 
    1582                 cfPlayedTotal += cfPlayed;
    1583                 Assert(cfPlayedTotal <= cfToPlay);
    1584 
    1585                 Assert(cfLeft >= cfRead);
    1586                 cfLeft        -= cfRead;
     1550            Assert(cFramesRead <= RT_ELEMENTS(aFrames));
     1551            if (cFramesRead)
     1552            {
     1553                uint32_t cbPlayed = 0;
     1554                rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend,
     1555                                                         aFrames, cFramesRead * sizeof(aFrames[0]), &cbPlayed);
     1556                AssertRCBreak(rc);
     1557                /** @todo r=bird: This is a natural follow up to the non-peeking peek crap
     1558                 *        above.  It works because VRDE is the only consumer and it always
     1559                 *        processes all that it gets. */
     1560                AssertBreakStmt(cbPlayed == cFramesRead * sizeof(aFrames[0]), rc = VERR_INTERNAL_ERROR_2);
     1561
     1562                Assert(cFramesRead <= cFramesLeft);
     1563                cFramesLeft -= cFramesRead;
    15871564            }
    15881565            else
     
    15991576    }
    16001577
    1601     if (RT_SUCCESS(rc) && pcfPlayed)
    1602         *pcfPlayed = cfPlayedTotal;
    1603     Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cfPlayedTotal, cfToPlay, rc));
     1578    *pcFramesPlayed = cFramesToPlay - cFramesLeft;
     1579    Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc));
    16041580    return rc;
    16051581}
     
    16141590    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    16151591    AssertPtrNullReturn(pcFramesPlayed, VERR_INVALID_POINTER);
    1616 
    1617     int rc = RTCritSectEnter(&pThis->CritSect);
    1618     AssertRCReturn(rc, rc);
    1619 
    16201592    AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT,
    16211593              ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n",
    16221594               pStream->szName, pStream->enmDir));
     1595    int rc = RTCritSectEnter(&pThis->CritSect);
     1596    AssertRCReturn(rc, rc);
    16231597
    16241598    uint32_t cfPlayedTotal = 0;
     
    17371711                    pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStream->pvBackend);
    17381712
     1713                /** @todo r=bird: I don't honestly see any difference in interleaved,
     1714                 *        non-interrleaved, raw, complicate, or whatever frame format we're
     1715                 *        dealing with here.  We'll be formatting a chunk of audio data and feed
     1716                 *        it to the backend, the formatting is taken care of by the mixer and
     1717                 *        we don't really care about the format anywhere here.
     1718                 *
     1719                 *        Raw audio is just stereo S64, btw.  Since drvAudioStreamPlayRaw
     1720                 *        actually copies the mixer data instead of accessing the internal mixer
     1721                 *        buffer directly, there is no advantage to having separate code paths
     1722                 *        here.  It only leads to more incomplete crappy code (I find the code
     1723                 *        quality quite appaling, given the amount of time spent on it).
     1724                 *
     1725                 *        What's more, I think the non-interleaved designation here is wrong
     1726                 *        anyway.  Non-interleaved means a stereo chunk of 8 frames is
     1727                 *        formatted:
     1728                 *              - LLLLLLLLRRRRRRRR
     1729                 *        whereas I'm pretty darn sure we do:
     1730                 *              - LRLRLRLRLRLRLRLR
     1731                 *        given that the mixer doesn't know how to output the former.  See the
     1732                 *        audioMixBufConvTo##a_Name##Stereo() code, it clearly output LR pairs.
     1733                 *
     1734                 *        https://stackoverflow.com/questions/17879933/whats-the-interleaved-audio
     1735                 */
    17391736                if (RT_LIKELY(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED))
    17401737                    rc = drvAudioStreamPlayNonInterleaved(pThis, pStream, cfToPlay, &cfPlayedTotal);
  • trunk/src/VBox/Main/include/ConsoleVRDPServer.h

    r82968 r88253  
    136136    void SendUpdateBitmap (unsigned uScreenId, uint32_t x, uint32_t y, uint32_t w, uint32_t h) const;
    137137
    138     void SendAudioSamples (void *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format) const;
     138    void SendAudioSamples (void const *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format) const;
    139139    void SendAudioVolume (uint16_t left, uint16_t right) const;
    140140    void SendUSBRequest (uint32_t u32ClientId, void *pvParms, uint32_t cbParms) const;
  • trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp

    r82968 r88253  
    37303730}
    37313731
    3732 void ConsoleVRDPServer::SendAudioSamples(void *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format) const
     3732void ConsoleVRDPServer::SendAudioSamples(void const *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format) const
    37333733{
    37343734    if (mpEntryPoints && mhServer)
  • trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp

    r88028 r88253  
    106106        pCfgAcq->enmLayout                      = PDMAUDIOSTREAMLAYOUT_RAW;
    107107        pCfgAcq->Backend.cFramesPeriod          = cFramesVrdpServer;
    108         pCfgAcq->Backend.cFramesBufferSize      = pCfgAcq->Backend.cFramesPeriod * 2; /* Use "double buffering". */
    109         pCfgAcq->Backend.cFramesPreBuffering    = pCfgAcq->Backend.cFramesPeriod;
     108/** @todo r=bird: This is inconsistent with the above buffer allocation and I
     109 * think also ALSA and Pulse backends way of setting cFramesBufferSize. */
     110        pCfgAcq->Backend.cFramesBufferSize      = cFramesVrdpServer * 2; /* Use "double buffering". */
     111        pCfgAcq->Backend.cFramesPreBuffering    = cFramesVrdpServer;
    110112    }
    111113
     
    270272 */
    271273static DECLCALLBACK(int) drvAudioVrdeHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    272                                                    const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten)
    273 {
    274     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    275     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    276     AssertPtrReturn(pvBuf,      VERR_INVALID_POINTER);
    277     AssertReturn(uBufSize,         VERR_INVALID_PARAMETER);
    278     /* puWritten is optional. */
    279 
    280     PDRVAUDIOVRDE pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
    281     PVRDESTREAM   pStreamVRDE = (PVRDESTREAM)pStream;
     274                                                   const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     275{
     276    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     277    AssertPtr(pDrv);
     278    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     279    PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream;
     280    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     281    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
     282    AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
    282283
    283284    if (!pDrv->pConsoleVRDPServer)
    284285        return VERR_NOT_AVAILABLE;
    285286
    286     /* Note: We get the number of *frames* in uBufSize
    287      *       (since we specified PDMAUDIOSTREAMLAYOUT_RAW as the audio data layout) on stream creation. */
    288     uint32_t cFramesLive = uBufSize;
    289 
     287    /* Prepate the format. */
    290288    PPDMAUDIOPCMPROPS pProps = &pStreamVRDE->pCfg->Props;
    291 
    292     VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pProps->uHz,
    293                                                  pProps->cChannels,
    294                                                  pProps->cbSample * 8 /* Bit */,
    295                                                  pProps->fSigned);
    296 
    297     /* Use the internal counter to track if we (still) can write to the VRDP server
    298      * or if we need to wait another round (time slot). */
    299     uint32_t cFramesToWrite = cFramesLive;
    300 
    301     Log3Func(("cFramesLive=%RU32, cFramesToWrite=%RU32\n", cFramesLive, cFramesToWrite));
    302 
    303     /* Don't play more than available. */
    304     if (cFramesToWrite > cFramesLive)
    305         cFramesToWrite = cFramesLive;
    306 
    307     int rc = VINF_SUCCESS;
    308 
    309     PPDMAUDIOFRAME paSampleBuf = (PPDMAUDIOFRAME)pvBuf;
    310     AssertPtr(paSampleBuf);
     289    VRDEAUDIOFORMAT const VrdpFormat = VRDE_AUDIO_FMT_MAKE(pProps->uHz,
     290                                                           pProps->cChannels,
     291                                                           pProps->cbSample * 8 /* Bit */,
     292                                                           pProps->fSigned);
     293
     294    /* We specified PDMAUDIOSTREAMLAYOUT_RAW (== S64), so
     295       convert the buffer pointe and size accordingly:  */
     296    PCPDMAUDIOFRAME paSampleBuf    = (PCPDMAUDIOFRAME)pvBuf;
     297    uint32_t const  cFramesToWrite = cbBuf / sizeof(paSampleBuf[0]);
     298    Assert(cFramesToWrite * sizeof(paSampleBuf[0]) == cbBuf);
     299
     300    /** @todo r=bird: there was some incoherent mumbling about "using the
     301     *        internal counter to track if we (still) can write to the VRDP
     302     *        server or if need to wait anothe round (time slot)".  However it
     303     *        wasn't accessing any internal counter nor doing anything else
     304     *        sensible, so I've removed it. */
    311305
    312306    /*
    313307     * Call the VRDP server with the data.
    314308     */
    315     uint32_t cfWritten = 0;
    316     while (cFramesToWrite)
    317     {
    318         uint32_t cfChunk = cFramesToWrite; /** @todo For now write all at once. */
    319 
    320         if (!cfChunk) /* Nothing to send. Bail out. */
    321             break;
    322 
    323         /* Note: The VRDP server expects int64_t samples per channel, regardless of the actual
    324          *       sample bits (e.g 8 or 16 bits). */
    325         pDrv->pConsoleVRDPServer->SendAudioSamples(paSampleBuf + cfWritten, cfChunk /* Frames */, format);
    326 
    327         cfWritten += cfChunk;
    328         Assert(cfWritten <= cFramesLive);
    329 
    330         Assert(cFramesToWrite >= cfChunk);
    331         cFramesToWrite -= cfChunk;
    332     }
    333 
    334     if (RT_SUCCESS(rc))
    335     {
    336         /* Return frames instead of bytes here
    337          * (since we specified PDMAUDIOSTREAMLAYOUT_RAW as the audio data layout). */
    338         if (puWritten)
    339             *puWritten = cfWritten;
    340     }
    341 
    342     return rc;
     309    uint32_t cFramesWritten = 0;
     310    while (cFramesWritten < cFramesToWrite)
     311    {
     312        uint32_t const cFramesChunk = cFramesToWrite - cFramesWritten; /** @todo For now write all at once. */
     313
     314        /* Note: The VRDP server expects int64_t samples per channel, regardless
     315                 of the actual  sample bits (e.g 8 or 16 bits). */
     316        pDrv->pConsoleVRDPServer->SendAudioSamples(&paSampleBuf[cFramesWritten], cFramesChunk /* Frames */, VrdpFormat);
     317
     318        cFramesWritten += cFramesChunk;
     319    }
     320
     321    Log3Func(("cFramesWritten=%RU32\n", cFramesWritten));
     322    if (pcbWritten)
     323        *pcbWritten = cFramesWritten * sizeof(PDMAUDIOFRAME);
     324    return VINF_SUCCESS;
    343325}
    344326
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette