VirtualBox

Changeset 88243 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Mar 22, 2021 12:32:22 PM (4 years ago)
Author:
vboxsync
Message:

DrvAudio: Replaced the scratch buffer with stack buffers. This will later allow for concurrently service input and output streams w/o needing the DrvAudio instance lock. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r88240 r88243  
    142142    /** Shutdown indicator. */
    143143    bool                    fTerminate;
     144#ifdef VBOX_WITH_AUDIO_ENUM
     145    /** Flag indicating to perform an (re-)enumeration of the host audio devices. */
     146    bool                    fEnumerateDevices;
     147#endif
    144148    /** Our audio connector interface. */
    145149    PDMIAUDIOCONNECTOR      IAudioConnector;
     
    150154    /** List of audio streams. */
    151155    RTLISTANCHOR            lstStreams;
    152 #ifdef VBOX_WITH_AUDIO_ENUM
    153     /** Flag indicating to perform an (re-)enumeration of the host audio devices. */
    154     bool                    fEnumerateDevices;
    155 #endif
    156156    /** Audio configuration settings retrieved from the backend. */
    157157    PDMAUDIOBACKENDCFG      BackendCfg;
    158     /** Commonly used scratch buffer. */
    159     void                   *pvScratchBuf;
    160     /** Size (in bytes) of commonly used scratch buffer. */
    161     size_t                  cbScratchBuf;
    162 #ifdef VBOX_WITH_STATISTICS
    163     /** Statistics for the statistics manager (STAM). */
    164     DRVAUDIOSTATS           Stats;
    165 #endif
    166158    struct
    167159    {
     
    192184        DRVAUDIOCFG         Cfg;
    193185    } Out;
    194 } DRVAUDIO, *PDRVAUDIO;
     186#ifdef VBOX_WITH_STATISTICS
     187    /** Statistics for the statistics manager (STAM). */
     188    DRVAUDIOSTATS           Stats;
     189#endif
     190} DRVAUDIO;
     191/** Pointer to the instance data of an audio driver. */
     192typedef DRVAUDIO *PDRVAUDIO;
    195193
    196194
     
    14501448 * Plays an audio host output stream which has been configured for non-interleaved (layout) data.
    14511449 *
    1452  * @return  IPRT status code.
     1450 * @returns VBox status code.
    14531451 * @param   pThis               Pointer to driver instance.
    14541452 * @param   pStream             Stream to play.
     
    14591457                                            PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed)
    14601458{
    1461     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     1459    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    14621460    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1463     /* pcfPlayed is optional. */
    1464 
     1461    AssertPtrNullReturn(pcfPlayed, VERR_INVALID_POINTER);
     1462    Assert(pStream->enmDir == PDMAUDIODIR_OUT);
     1463    Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
     1464
     1465    /*
     1466     * ...
     1467     */
    14651468    if (!cfToPlay)
    14661469    {
     
    14701473    }
    14711474
    1472     /* Sanity. */
    1473     Assert(pStream->enmDir == PDMAUDIODIR_OUT);
    1474     Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
    1475 
    1476     int rc = VINF_SUCCESS;
    1477 
     1475    /*
     1476     * ...
     1477     */
     1478    int      rc            = VINF_SUCCESS;
    14781479    uint32_t cfPlayedTotal = 0;
    1479 
    1480     uint32_t cfLeft  = cfToPlay;
    1481 
    1482     uint8_t  *pvChunk = (uint8_t *)pThis->pvScratchBuf;
    1483     uint32_t  cbChunk = (uint32_t)pThis->cbScratchBuf;
    1484 
     1480    uint32_t cfLeft        = cfToPlay;
    14851481    while (cfLeft)
    14861482    {
     1483        uint8_t  abChunk[_4K];
    14871484        uint32_t cfRead = 0;
    14881485        rc = AudioMixBufAcquireReadBlock(&pStream->Host.MixBuf,
    1489                                          pvChunk, RT_MIN(cbChunk, AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfLeft)),
     1486                                         abChunk, RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfLeft)),
    14901487                                         &cfRead);
    14911488        if (RT_FAILURE(rc))
     
    14931490
    14941491        uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfRead);
    1495         Assert(cbRead <= cbChunk);
     1492        Assert(cbRead <= sizeof(abChunk));
    14961493
    14971494        uint32_t cfPlayed = 0;
    14981495        uint32_t cbPlayed = 0;
    1499         rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend,
    1500                                                  pvChunk, cbRead, &cbPlayed);
     1496        rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, abChunk, cbRead, &cbPlayed);
    15011497        if (   RT_SUCCESS(rc)
    15021498            && cbPlayed)
    15031499        {
    15041500            if (pThis->Out.Cfg.Dbg.fEnabled)
    1505                 AudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, pvChunk, cbPlayed, 0 /* fFlags */);
     1501                AudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */);
    15061502
    15071503            if (cbRead != cbPlayed)
     
    15361532 * Plays an audio host output stream which has been configured for raw audio (layout) data.
    15371533 *
    1538  * @return  IPRT status code.
     1534 * @returns VBox status code.
    15391535 * @param   pThis               Pointer to driver instance.
    15401536 * @param   pStream             Stream to play.
     
    15451541                                 PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed)
    15461542{
    1547     AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
     1543    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    15481544    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1549     /* pcfPlayed is optional. */
    1550 
    1551     /* Sanity. */
     1545    AssertPtrNullReturn(pcfPlayed, VERR_INVALID_POINTER);
    15521546    Assert(pStream->enmDir == PDMAUDIODIR_OUT);
    15531547    Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
    15541548
     1549    /*
     1550     * ...
     1551     */
    15551552    if (!cfToPlay)
    15561553    {
     
    15601557    }
    15611558
    1562     int rc = VINF_SUCCESS;
    1563 
    1564     uint32_t cfPlayedTotal = 0;
    1565 
    1566     PPDMAUDIOFRAME paFrames = (PPDMAUDIOFRAME)pThis->pvScratchBuf;
    1567     const uint32_t  cFrames =      (uint32_t)(pThis->cbScratchBuf / sizeof(PDMAUDIOFRAME));
    1568 
    1569     uint32_t cfLeft = cfToPlay;
     1559    /*
     1560     * ...
     1561     */
     1562    int         rc              = VINF_SUCCESS;
     1563    uint32_t    cfPlayedTotal   = 0;
     1564    uint32_t    cfLeft          = cfToPlay;
    15701565    while (cfLeft)
    15711566    {
    1572         uint32_t cfRead = 0;
    1573         rc = AudioMixBufPeek(&pStream->Host.MixBuf, cfLeft, paFrames,
    1574                              RT_MIN(cfLeft, cFrames), &cfRead);
    1575 
     1567        PDMAUDIOFRAME   aFrames[_2K];
     1568        uint32_t        cfRead = 0;
     1569        rc = AudioMixBufPeek(&pStream->Host.MixBuf, cfLeft, aFrames, RT_MIN(cfLeft, RT_ELEMENTS(aFrames)), &cfRead);
    15761570        if (RT_SUCCESS(rc))
    15771571        {
    15781572            if (cfRead)
    15791573            {
    1580                 uint32_t cfPlayed;
    1581 
    1582                 /* Note: As the stream layout is RPDMAUDIOSTREAMLAYOUT_RAW, operate on audio frames
    1583                  *       rather on bytes. */
    1584                 Assert(cfRead <= cFrames);
    1585                 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend,
    1586                                                          paFrames, cfRead, &cfPlayed);
     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);
    15871578                if (   RT_FAILURE(rc)
    15881579                    || !cfPlayed)
    1589                 {
    15901580                    break;
    1591                 }
    15921581
    15931582                cfPlayedTotal += cfPlayed;
     
    15991588            else
    16001589            {
     1590/** @todo r=bird: This looks totally loopy.  Why should another call return data
     1591 *        when the first one didn't? */
    16011592                if (rc == VINF_AUDIO_MORE_DATA_AVAILABLE) /* Do another peeking round if there is more data available. */
    16021593                    continue;
    1603 
    16041594                break;
    16051595            }
    16061596        }
    1607         else if (RT_FAILURE(rc))
     1597        else
    16081598            break;
    16091599    }
    16101600
     1601    if (RT_SUCCESS(rc) && pcfPlayed)
     1602        *pcfPlayed = cfPlayedTotal;
    16111603    Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cfPlayedTotal, cfToPlay, rc));
    1612 
    1613     if (RT_SUCCESS(rc))
    1614     {
    1615         if (pcfPlayed)
    1616             *pcfPlayed = cfPlayedTotal;
    1617 
    1618     }
    1619 
    16201604    return rc;
    16211605}
     
    16241608 * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamPlay}
    16251609 */
    1626 static DECLCALLBACK(int) drvAudioStreamPlay(PPDMIAUDIOCONNECTOR pInterface,
    1627                                             PPDMAUDIOSTREAM pStream, uint32_t *pcFramesPlayed)
     1610static DECLCALLBACK(int) drvAudioStreamPlay(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcFramesPlayed)
    16281611{
    16291612    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
     
    16311614    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    16321615    AssertPtrNullReturn(pcFramesPlayed, VERR_INVALID_POINTER);
    1633 
    16341616
    16351617    int rc = RTCritSectEnter(&pThis->CritSect);
     
    18021784    RTCritSectLeave(&pThis->CritSect);
    18031785
    1804     if (RT_SUCCESS(rc))
    1805     {
    1806         if (pcFramesPlayed)
    1807             *pcFramesPlayed = cfPlayedTotal;
    1808     }
     1786    if (RT_SUCCESS(rc) && pcFramesPlayed)
     1787        *pcFramesPlayed = cfPlayedTotal;
    18091788
    18101789    if (RT_FAILURE(rc))
     
    18231802static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured)
    18241803{
    1825     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     1804    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    18261805    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1827     /* pcfCaptured is optional. */
    1828 
    1829     /* Sanity. */
     1806    AssertPtrNullReturn(pcfCaptured, VERR_INVALID_POINTER);
    18301807    Assert(pStream->enmDir == PDMAUDIODIR_IN);
    18311808    Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
    18321809
    1833     int rc = VINF_SUCCESS;
    1834 
    1835     uint32_t cfCapturedTotal = 0;
    1836 
     1810    /*
     1811     * ...
     1812     */
    18371813    AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable);
    1838 
    18391814    uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend);
    18401815    if (!cbReadable)
     
    18481823        cbReadable = cbFree;
    18491824
     1825    /*
     1826     * ...
     1827     */
     1828    int      rc = VINF_SUCCESS;
     1829    uint32_t cfCapturedTotal = 0;
    18501830    while (cbReadable)
    18511831    {
     1832        uint8_t  abChunk[_4K];
    18521833        uint32_t cbCaptured;
    18531834        rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream->pvBackend,
    1854                                                     pThis->pvScratchBuf, RT_MIN(cbReadable, (uint32_t)pThis->cbScratchBuf), &cbCaptured);
     1835                                                    abChunk, RT_MIN(cbReadable, (uint32_t)sizeof(abChunk)), &cbCaptured);
    18551836        if (RT_FAILURE(rc))
    18561837        {
    18571838            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
    18581839            AssertRC(rc2);
    1859 
    18601840            break;
    18611841        }
    18621842
    1863         Assert(cbCaptured <= pThis->cbScratchBuf);
    1864         if (cbCaptured > pThis->cbScratchBuf) /* Paranoia. */
    1865             cbCaptured = (uint32_t)pThis->cbScratchBuf;
     1843        Assert(cbCaptured <= sizeof(abChunk));
     1844        if (cbCaptured > sizeof(abChunk)) /* Paranoia. */
     1845            cbCaptured = (uint32_t)sizeof(abChunk);
    18661846
    18671847        if (!cbCaptured) /* Nothing captured? Take a shortcut. */
     
    18711851         * (first) processing (if needed), so always write the incoming data at offset 0. */
    18721852        uint32_t cfHstWritten = 0;
    1873         rc = AudioMixBufWriteAt(&pStream->Host.MixBuf, 0 /* offFrames */, pThis->pvScratchBuf, cbCaptured, &cfHstWritten);
     1853        rc = AudioMixBufWriteAt(&pStream->Host.MixBuf, 0 /* offFrames */, abChunk, cbCaptured, &cfHstWritten);
    18741854        if (   RT_FAILURE(rc)
    18751855            || !cfHstWritten)
     
    18811861
    18821862        if (pThis->In.Cfg.Dbg.fEnabled)
    1883             AudioHlpFileWrite(pStream->In.Dbg.pFileCaptureNonInterleaved, pThis->pvScratchBuf, cbCaptured, 0 /* fFlags */);
     1863            AudioHlpFileWrite(pStream->In.Dbg.pFileCaptureNonInterleaved, abChunk, cbCaptured, 0 /* fFlags */);
    18841864
    18851865        uint32_t cfHstMixed = 0;
     
    19331913    AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable);
    19341914
    1935     int rc = VINF_SUCCESS;
    1936 
    1937     uint32_t cfCapturedTotal = 0;
    1938 
     1915    /*
     1916     * ...
     1917     */
    19391918    /* Note: Raw means *audio frames*, not bytes! */
    19401919    uint32_t cfReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend);
     
    19491928        cfReadable = cfFree;
    19501929
     1930    /*
     1931     * ...
     1932     */
     1933    int      rc              = VINF_SUCCESS;
     1934    uint32_t cfCapturedTotal = 0;
    19511935    while (cfReadable)
    19521936    {
     
    19561940        if (   RT_FAILURE(rc)
    19571941            || !cfWritable)
    1958         {
    19591942            break;
    1960         }
    19611943
    19621944        uint32_t cfCaptured;
     
    19671949            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
    19681950            AssertRC(rc2);
    1969 
    19701951            break;
    19711952        }
     
    19801961    }
    19811962
    1982     Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc));
    1983 
    19841963    if (pcfCaptured)
    19851964        *pcfCaptured = cfCapturedTotal;
    1986 
     1965    Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc));
    19871966    return rc;
    19881967}
     
    20101989
    20111990    /*
    2012      *
     1991     * ...
    20131992     */
    20141993    uint32_t cfCaptured = 0;
     
    20312010         * Do the actual capturing.
    20322011         */
    2033 
    20342012        if (pThis->pHostDrvAudio->pfnStreamCaptureBegin)
    20352013            pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pStream->pvBackend);
     
    20562034        }
    20572035        else if (RT_UNLIKELY(RT_FAILURE(rc)))
    2058         {
    20592036            LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStream->szName, rc));
    2060         }
    2061 
    20622037    } while (0);
    20632038
     
    36233598#endif
    36243599
    3625     if (pThis->pvScratchBuf)
    3626     {
    3627         Assert(pThis->cbScratchBuf);
    3628 
    3629         RTMemFree(pThis->pvScratchBuf);
    3630         pThis->pvScratchBuf = NULL;
    3631     }
    3632 
    36333600    if (RTCritSectIsInitialized(&pThis->CritSect))
    36343601    {
     
    38313798    rc = RTCritSectInit(&pThis->CritSect);
    38323799    AssertRCReturn(rc, rc);
    3833 
    3834     const size_t cbScratchBuf = _4K; /** @todo Make this configurable? */
    3835     pThis->pvScratchBuf = RTMemAlloc(cbScratchBuf);
    3836     AssertPtrReturn(pThis->pvScratchBuf, VERR_NO_MEMORY);
    3837     pThis->cbScratchBuf = cbScratchBuf;
    38383800
    38393801    pThis->fTerminate                           = false;
Note: See TracChangeset for help on using the changeset viewer.

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