VirtualBox

Changeset 75980 in vbox


Ignore:
Timestamp:
Dec 5, 2018 3:56:13 PM (6 years ago)
Author:
vboxsync
Message:

Audio/HDA: Optimized stream creation / startup time a lot by re-using the existing mixer / driver chain if the stream's hardware parameters did not change. No need to completely remove and add the same stream again, going through all the PDM interfaces, LUNs and backends.

Location:
trunk/src/VBox/Devices/Audio
Files:
2 edited

Legend:

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

    r75965 r75980  
    13011301    const bool fInReset  = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_SRST);
    13021302
    1303 # ifdef LOG_ENABLED
    1304     if (fRun)
    1305     {
    1306         PDMAUDIOPCMPROPS Props;
    1307         int rc2 = hdaR3SDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, uSD), &Props);
    1308         AssertRC(rc2);
    1309         LogFunc(("[SD%RU8] %RU32Hz, %RU8bit, %RU8 channel(s)\n",
    1310                  uSD, Props.uHz, Props.cBytes * 8 /* Bit */, Props.cChannels));
    1311     }
    1312 # endif
    1313 
    1314     LogFunc(("[SD%RU8] fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
    1315              uSD, fRun, fInRun, fReset, fInReset, u32Value));
    1316 
    1317     if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
    1318     {
    1319         const uint8_t uStripeCtl = ((u32Value >> HDA_SDCTL_STRIPE_SHIFT) & HDA_SDCTL_STRIPE_MASK) + 1;
    1320         LogFunc(("[SD%RU8] Using %RU8 SDOs (stripe control)\n", uSD, uStripeCtl));
    1321         if (uStripeCtl > 1)
    1322             LogRel2(("HDA: Warning: Striping output over more than one SDO for stream #%RU8 currently is not implemented " \
    1323                      "(%RU8 SDOs requested)\n", uSD, uStripeCtl));
    1324     }
     1303    /*LogFunc(("[SD%RU8] fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
     1304               uSD, fRun, fInRun, fReset, fInReset, u32Value));*/
    13251305
    13261306    /*
     
    13411321    }
    13421322
    1343     PHDATAG pTag = &pThis->aTags[uTag];
    1344     AssertPtr(pTag);
    1345 
    1346     LogFunc(("[SD%RU8] Using stream tag=%RU8\n", uSD, uTag));
    1347 
    1348     /* Assign new values. */
    1349     pTag->uTag    = uTag;
    1350     pTag->pStream = hdaGetStreamFromSD(pThis, uSD);
    1351 
    1352     PHDASTREAM pStream = pTag->pStream;
     1323    PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uSD);
    13531324    AssertPtr(pStream);
    13541325
     
    14101381            if (fRun)
    14111382            {
     1383                if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
     1384                {
     1385                    const uint8_t uStripeCtl = ((u32Value >> HDA_SDCTL_STRIPE_SHIFT) & HDA_SDCTL_STRIPE_MASK) + 1;
     1386                    LogFunc(("[SD%RU8] Using %RU8 SDOs (stripe control)\n", uSD, uStripeCtl));
     1387                    if (uStripeCtl > 1)
     1388                        LogRel2(("HDA: Warning: Striping output over more than one SDO for stream #%RU8 currently is not implemented " \
     1389                                 "(%RU8 SDOs requested)\n", uSD, uStripeCtl));
     1390                }
     1391
     1392                PHDATAG pTag = &pThis->aTags[uTag];
     1393                AssertPtr(pTag);
     1394
     1395                LogFunc(("[SD%RU8] Using stream tag=%RU8\n", uSD, uTag));
     1396
     1397                /* Assign new values. */
     1398                pTag->uTag    = uTag;
     1399                pTag->pStream = hdaGetStreamFromSD(pThis, uSD);
     1400
     1401# ifdef LOG_ENABLED
     1402                PDMAUDIOPCMPROPS Props;
     1403                rc2 = hdaR3SDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, pStream->u8SD), &Props);
     1404                AssertRC(rc2);
     1405                LogFunc(("[SD%RU8] %RU32Hz, %RU8bit, %RU8 channel(s)\n",
     1406                         pStream->u8SD, Props.uHz, Props.cBytes * 8 /* Bit */, Props.cChannels));
     1407# endif
    14121408                /* (Re-)initialize the stream with current values. */
    14131409                rc2 = hdaR3StreamInit(pStream, pStream->u8SD);
    1414                 AssertRC(rc2);
    1415 
    1416                 /* Remove the old stream from the device setup. */
    1417                 rc2 = hdaR3RemoveStream(pThis, &pStream->State.Cfg);
    1418                 AssertRC(rc2);
    1419 
    1420                 /* Add the stream to the device setup. */
    1421                 rc2 = hdaR3AddStream(pThis, &pStream->State.Cfg);
    1422                 AssertRC(rc2);
     1410                if (   RT_SUCCESS(rc2)
     1411                    /* Any vital stream change occurred so that we need to (re-)add the stream to our setup?
     1412                     * Otherwise just skip this, as this costs a lot of performance. */
     1413                    && rc2 != VINF_NO_CHANGE)
     1414                {
     1415                    /* Remove the old stream from the device setup. */
     1416                    rc2 = hdaR3RemoveStream(pThis, &pStream->State.Cfg);
     1417                    AssertRC(rc2);
     1418
     1419                    /* Add the stream to the device setup. */
     1420                    rc2 = hdaR3AddStream(pThis, &pStream->State.Cfg);
     1421                    AssertRC(rc2);
     1422                }
    14231423            }
    14241424
     
    42104210                             ("HDA: Saved state contains invalid DMA buffer usage (%RU32/%RU32) for stream #%RU8",
    42114211                              cbCircBufUsed, cbCircBufSize, uStreamID));
    4212             AssertPtr(pStream->State.pCircBuf);
    42134212
    42144213            /* Do we need to cre-create the circular buffer do fit the data size? */
    4215             if (cbCircBufSize != (uint32_t)RTCircBufSize(pStream->State.pCircBuf))
     4214            if (   pStream->State.pCircBuf
     4215                && cbCircBufSize != (uint32_t)RTCircBufSize(pStream->State.pCircBuf))
    42164216            {
    42174217                RTCircBufDestroy(pStream->State.pCircBuf);
    42184218                pStream->State.pCircBuf = NULL;
    4219 
    4220                 rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBufSize);
    4221                 AssertRC(rc);
    42224219            }
     4220
     4221            rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBufSize);
     4222            AssertRC(rc);
    42234223
    42244224            if (   RT_SUCCESS(rc)
  • trunk/src/VBox/Devices/Audio/HDAStream.cpp

    r75962 r75980  
    135135    AssertPtrReturnVoid(pStream);
    136136
    137     LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD));
     137    LogFlowFunc(("[SD%RU8] Destroying ...\n", pStream->u8SD));
    138138
    139139    hdaR3StreamMapDestroy(&pStream->State.Mapping);
     
    186186 * Initializes an HDA stream.
    187187 *
    188  * @returns IPRT status code.
     188 * @returns IPRT status code. VINF_NO_CHANGE if the stream does not need (re-)initialization because the stream's (hardware)
     189 *          parameters did not change.
    189190 * @param   pStream             HDA stream to initialize.
    190191 * @param   uSD                 SD (stream descriptor) number to assign the HDA stream to.
     
    197198    AssertPtr(pThis);
    198199
    199     pStream->u8SD       = uSD;
    200     pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
    201                                       HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
    202     pStream->u16LVI     = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
    203     pStream->u32CBL     = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
    204     pStream->u16FIFOS   = HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD) + 1;
    205 
    206     PPDMAUDIOSTREAMCFG pCfg = &pStream->State.Cfg;
    207 
    208     int rc = hdaR3SDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, uSD), &pCfg->Props);
     200    const uint64_t u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, uSD),
     201                                            HDA_STREAM_REG(pThis, BDPU, uSD));
     202    const uint16_t u16LVI     = HDA_STREAM_REG(pThis, LVI, uSD);
     203    const uint32_t u32CBL     = HDA_STREAM_REG(pThis, CBL, uSD);
     204    const uint16_t u16FIFOS   = HDA_STREAM_REG(pThis, FIFOS, uSD) + 1;
     205    const uint32_t u32FMT     = HDA_STREAM_REG(pThis, FMT, uSD);
     206
     207    /* Is the bare minimum set of registers configured for the stream?
     208     * If not, bail out early, as there's nothing to do here for us (yet). */
     209    if (   !u64BDLBase
     210        || !u16LVI
     211        || !u32CBL
     212        || !u16FIFOS
     213        || !u32FMT)
     214    {
     215        LogFunc(("[SD%RU8] Registers not set up yet, skipping (re-)initialization\n", uSD));
     216        return VINF_SUCCESS;
     217    }
     218
     219    PDMAUDIOPCMPROPS Props;
     220    int rc = hdaR3SDFMTToPCMProps(u32FMT, &Props);
    209221    if (RT_FAILURE(rc))
    210222    {
     
    213225    }
    214226
    215     /* Set scheduling hint (if available). */
    216     if (pThis->uTimerHz)
    217         pCfg->Device.uSchedulingHintMs = 1000 /* ms */ / pThis->uTimerHz;
     227    /* Reset (any former) stream map. */
     228    hdaR3StreamMapReset(&pStream->State.Mapping);
     229
     230    /*
     231     * Initialize the stream mapping in any case, regardless if
     232     * we support surround audio or not. This is needed to handle
     233     * the supported channels within a single audio stream, e.g. mono/stereo.
     234     *
     235     * In other words, the stream mapping *always* knows the real
     236     * number of channels in a single audio stream.
     237     */
     238    rc = hdaR3StreamMapInit(&pStream->State.Mapping, &Props);
     239    AssertRCReturn(rc, rc);
     240
     241#ifndef VBOX_WITH_AUDIO_HDA_51_SURROUND
     242    if (Props.cChannels > 2)
     243    {
     244        /*
     245         * When not running with surround support enabled, override the audio channel count
     246         * with stereo (2) channels so that we at least can properly work with those.
     247         *
     248         * Note: This also involves dealing with surround setups the guest might has set up for us.
     249         */
     250        LogRel2(("HDA: More than stereo (2) channels are not supported (%RU8 requested), "
     251                 "falling back to stereo channels for stream #%RU8\n", Props.cChannels, uSD));
     252        Props.cChannels = 2;
     253    }
     254#endif
     255
     256    /* Did some of the vital / critical parameters change?
     257     * If not, we can skip a lot of the (re-)initialization and just (re-)use the existing stuff.
     258     * Also, tell the caller so that further actions can be taken. */
     259    if (   uSD        == pStream->u8SD
     260        && u64BDLBase == pStream->u64BDLBase
     261        && u16LVI     == pStream->u16LVI
     262        && u32CBL     == pStream->u32CBL
     263        && u16FIFOS   == pStream->u16FIFOS
     264        && DrvAudioHlpPCMPropsAreEqual(&Props, &pStream->State.Cfg.Props))
     265    {
     266        LogFunc(("[SD%RU8] No format change, skipping (re-)initialization\n", uSD));
     267        return VINF_NO_CHANGE;
     268    }
     269
     270    pStream->u8SD       = uSD;
     271    pStream->u64BDLBase = u64BDLBase;
     272    pStream->u16LVI     = u16LVI;
     273    pStream->u32CBL     = u32CBL;
     274    pStream->u16FIFOS   = u16FIFOS;
     275
     276    PPDMAUDIOSTREAMCFG pCfg = &pStream->State.Cfg;
     277    pCfg->Props = Props;
    218278
    219279    /* (Re-)Allocate the stream's internal DMA buffer, based on the PCM  properties we just got above. */
     
    225285
    226286    /* By default we allocate an internal buffer of 100ms. */
    227     rc = RTCircBufCreate(&pStream->State.pCircBuf, DrvAudioHlpMilliToBytes(100 /* ms */, &pCfg->Props)); /** @todo Make this configurable. */
     287    rc = RTCircBufCreate(&pStream->State.pCircBuf,
     288                         DrvAudioHlpMilliToBytes(100 /* ms */, &pCfg->Props)); /** @todo Make this configurable. */
    228289    AssertRCReturn(rc, rc);
    229290
     
    254315    }
    255316
    256     if (   !pStream->u32CBL
    257         || !pStream->u16LVI
    258         || !pStream->u64BDLBase
    259         || !pStream->u16FIFOS)
    260     {
    261         return VINF_SUCCESS;
    262     }
    263 
    264     /*
    265      * Initialize the stream mapping in any case, regardless if
    266      * we support surround audio or not. This is needed to handle
    267      * the supported channels within a single audio stream, e.g. mono/stereo.
    268      *
    269      * In other words, the stream mapping *always* knows the real
    270      * number of channels in a single audio stream.
    271      */
    272     rc = hdaR3StreamMapInit(&pStream->State.Mapping, &pCfg->Props);
    273     AssertRCReturn(rc, rc);
    274 
    275 #ifndef VBOX_WITH_AUDIO_HDA_51_SURROUND
    276     /*
    277      * When not running with surround support enabled, override the channel count
    278      * with stereo (2) channels so that we at least can properly work with those.
    279      *
    280      * Note: This also involves dealing with surround setups the guest might has set up for us.
    281      */
    282     pCfg->Props.cChannels = 2;
    283 #endif
    284 
    285     LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16, Hz=%RU32, rc=%Rrc\n",
    286              pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS,
    287              pStream->State.Cfg.Props.uHz, rc));
     317    LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16\n",
     318             pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS));
    288319
    289320    /* Make sure that mandatory parameters are set up correctly. */
     
    397428            pStream->State.cbTransferChunk = pStream->State.cbTransferSize;
    398429
    399         pStream->State.cbTransferProcessed        = 0;
    400         pStream->State.cTransferPendingInterrupts = 0;
    401         pStream->State.tsLastUpdateNs             = 0;
    402 
    403430        const uint64_t cTicksPerHz = TMTimerGetFreq(pStream->pTimer) / pThis->uTimerHz;
    404431
     
    410437        pStream->State.cTransferTicks     = pStream->State.cbTransferChunk * pStream->State.cTicksPerByte;
    411438        Assert(pStream->State.cTransferTicks);
    412 
    413         /* Initialize the transfer timestamps. */
    414         pStream->State.tsTransferLast     = 0;
    415         pStream->State.tsTransferNext     = 0;
    416439
    417440        LogFunc(("[SD%RU8] Timer %uHz (%RU64 ticks per Hz), cTicksPerByte=%RU64, cbTransferChunk=%RU32, cTransferTicks=%RU64, " \
     
    451474# endif
    452475
    453     LogFunc(("[SD%RU8]: Reset\n", uSD));
     476    LogFunc(("[SD%RU8] Reset\n", uSD));
    454477
    455478    /*
     
    482505
    483506    /* Assign the default mixer sink to the stream. */
    484     pStream->pMixSink             = hdaR3GetDefaultSink(pThis, uSD);
    485 
     507    pStream->pMixSink = hdaR3GetDefaultSink(pThis, uSD);
     508
     509    /* Reset transfer stuff. */
     510    pStream->State.cbTransferProcessed        = 0;
     511    pStream->State.cTransferPendingInterrupts = 0;
    486512    pStream->State.tsTransferLast = 0;
    487513    pStream->State.tsTransferNext = 0;
    488514
     515    /* Initialize other timestamps. */
     516    pStream->State.tsLastUpdateNs = 0;
     517
    489518    RT_ZERO(pStream->State.BDLE);
    490519    pStream->State.uCurBDLE = 0;
     
    492521    if (pStream->State.pCircBuf)
    493522        RTCircBufReset(pStream->State.pCircBuf);
    494 
    495     /* Reset stream map. */
    496     hdaR3StreamMapReset(&pStream->State.Mapping);
    497 
    498     /* (Re-)initialize the stream with current values. */
    499     int rc2 = hdaR3StreamInit(pStream, uSD);
    500     AssertRC(rc2);
    501523
    502524    /* Reset the stream's period. */
     
    534556    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    535557
    536     LogFunc(("[SD%RU8]: fEnable=%RTbool, pMixSink=%p\n", pStream->u8SD, fEnable, pStream->pMixSink));
     558    LogFunc(("[SD%RU8] fEnable=%RTbool, pMixSink=%p\n", pStream->u8SD, fEnable, pStream->pMixSink));
    537559
    538560    int rc = VINF_SUCCESS;
     
    781803    if (!pSink)
    782804    {
    783         AssertMsgFailed(("[SD%RU8]: Can't read from a stream with no sink attached\n", pStream->u8SD));
     805        AssertMsgFailed(("[SD%RU8] Can't read from a stream with no sink attached\n", pStream->u8SD));
    784806
    785807        if (pcbRead)
     
    814836
    815837            Assert(cbSrc >= cbWritten);
    816             Log2Func(("[SD%RU8]: %RU32/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc));
     838            Log2Func(("[SD%RU8] %RU32/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc));
    817839        }
    818840
     
    15651587    u32LPIB = RT_MIN(u32LPIB, pStream->u32CBL);
    15661588
    1567     LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
     1589    LogFlowFunc(("[SD%RU8] LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
    15681590                 pStream->u8SD, u32LPIB, pThis->fDMAPosition));
    15691591
     
    17771799    RTThreadUserSignal(hThreadSelf);
    17781800
    1779     LogFunc(("[SD%RU8]: Started\n", pStream->u8SD));
     1801    LogFunc(("[SD%RU8] Started\n", pStream->u8SD));
    17801802
    17811803    for (;;)
     
    18061828    }
    18071829
    1808     LogFunc(("[SD%RU8]: Ended\n", pStream->u8SD));
     1830    LogFunc(("[SD%RU8] Ended\n", pStream->u8SD));
    18091831
    18101832    ASMAtomicXchgBool(&pAIO->fStarted, false);
     
    18511873        rc = VINF_SUCCESS;
    18521874
    1853     LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
     1875    LogFunc(("[SD%RU8] Returning %Rrc\n", pStream->u8SD, rc));
    18541876    return rc;
    18551877}
     
    18901912    }
    18911913
    1892     LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
     1914    LogFunc(("[SD%RU8] Returning %Rrc\n", pStream->u8SD, rc));
    18931915    return rc;
    18941916}
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