VirtualBox

Changeset 88259 in vbox


Ignore:
Timestamp:
Mar 23, 2021 12:10:36 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143462
Message:

DrvAudio: Hacked the underruns detection so it won't falsely trigger when there is still enough bytes buffered in the host driver. bugref:9890

Location:
trunk
Files:
2 edited

Legend:

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

    r88255 r88259  
    12281228        STAMCOUNTER     TotalTimesWritten;
    12291229    } Stats;
     1230    /** Hack alert: Max writable amount reported by the backend.
     1231     * This is used to aid buffer underrun detection in DrvAudio while playing.
     1232     * Ideally, the backend should have a method for querying number of buffered
     1233     * bytes instead.  However this will do for now. */
     1234    uint32_t            cbBackendMaxWritable;
    12301235} PDMAUDIOSTREAMOUT;
    12311236/** Pointer to the specifics for an audio output stream. */
     
    13191324
    13201325/** Magic value for PDMAUDIOSTREAM. */
    1321 #define PDMAUDIOSTREAM_MAGIC    PDM_VERSION_MAKE(0xa0d3, 1, 0)
     1326#define PDMAUDIOSTREAM_MAGIC    PDM_VERSION_MAKE(0xa0d3, 1, 1)
    13221327
    13231328
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r88256 r88259  
    183183        /** The driver's output confguration (tweakable via CFGM). */
    184184        DRVAUDIOCFG         Cfg;
     185        /** Number of times underruns triggered re-(pre-)buffering. */
     186        STAMCOUNTER         StatsReBuffering;
    185187    } Out;
    186188#ifdef VBOX_WITH_STATISTICS
     
    16111613        return VERR_AUDIO_STREAM_NOT_READY;
    16121614
    1613 
    1614     /*
    1615      *
    1616      */
    1617     const uint32_t cFramesLive             = AudioMixBufLive(&pStream->Host.MixBuf);
    1618     const uint64_t tsDeltaPlayedCapturedNs = RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs;
    1619     const uint32_t cFramesPassedReal       = PDMAudioPropsNanoToFrames(&pStream->Host.Cfg.Props, tsDeltaPlayedCapturedNs);
    1620 
    1621     Log3Func(("[%s] Last played %'RU64 ns ago; filled with %u frm / %RU64 ms / %RU8%% total%s\n",
    1622               pStream->szName, tsDeltaPlayedCapturedNs, cFramesLive,
     1615    /*
     1616     * Get number of frames in the mix buffer and do some logging.
     1617     */
     1618    uint32_t const cFramesLive = AudioMixBufLive(&pStream->Host.MixBuf);
     1619    Log3Func(("[%s] Last played %'RI64 ns ago; filled with %u frm / %RU64 ms / %RU8%% total%s\n",
     1620              pStream->szName, pStream->fThresholdReached ? RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs : -1, cFramesLive,
    16231621              PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive),
    16241622              (100 * cFramesLive) / AudioMixBufSize(&pStream->Host.MixBuf), pStream->fThresholdReached ? "" : ", pre-buffering"));
     
    16321630    else
    16331631    {
    1634         LogRel2(("Audio: Buffer underrun for stream '%s' occurred (%RU64ms passed)\n",
    1635                  pStream->szName, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesPassedReal)));
    1636 
    1637         if (pStream->Host.Cfg.Backend.cFramesPreBuffering) /* Any pre-buffering configured? */
    1638         {
    1639             /* Enter pre-buffering stage again. */
    1640             pStream->fThresholdReached = false;
     1632        /* It's not an underrun if the host audio driver still has an reasonable amount
     1633           buffered.  We don't have a direct way of querying that, so instead we'll use
     1634           some heuristics based on number of writable bytes now compared to when
     1635           prebuffering ended the first time around. */
     1636        uint32_t cbBuffered = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
     1637        if (cbBuffered < pStream->Out.cbBackendMaxWritable)
     1638            cbBuffered = pStream->Out.cbBackendMaxWritable - cbBuffered;
     1639        else
     1640            cbBuffered = 0;
     1641        uint32_t cbMinBuf = PDMAudioPropsMilliToBytes(&pStream->Host.Cfg.Props, pStream->Guest.Cfg.Device.cMsSchedulingHint * 2);
     1642        Log3Func(("Potential underrun: cbBuffered=%#x vs cbMinBuf=%#x\n", cbBuffered, cbMinBuf));
     1643        if (cbBuffered < cbMinBuf)
     1644        {
     1645            LogRel2(("Audio: Buffer underrun for stream '%s' (%RI64 ms since last call, %u buffered)\n",
     1646                     pStream->szName, RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs, cbBuffered));
     1647
     1648            /* Re-enter the pre-buffering stage again if enabled. */
     1649            if (pStream->Host.Cfg.Backend.cFramesPreBuffering > 0)
     1650            {
     1651                pStream->fThresholdReached = false;
     1652                STAM_REL_COUNTER_INC(&pThis->Out.StatsReBuffering);
     1653            }
    16411654        }
    16421655    }
     
    16471660     * This is straight forward, the backend
    16481661     */
     1662    uint32_t cbWritable;
    16491663    bool fJustStarted = false;
    16501664    if (pStream->fThresholdReached)
    1651     { /* not-prebuffering, likely after a while at least */ }
     1665    {
     1666        /* not-prebuffering, likely after a while at least */
     1667        cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
     1668    }
    16521669    else
    16531670    {
     
    16591676        {
    16601677            LogRel2(("Audio: Stream '%s' buffering complete\n", pStream->szName));
    1661             Log3Func(("[%s] Dbg: Buffering complete\n", pStream->szName));
     1678            Log3Func(("[%s] Dbg: Buffering complete!\n", pStream->szName));
    16621679            pStream->fThresholdReached = fJustStarted = true;
    16631680        }
     
    16741691        {
    16751692            LogRel2(("Audio: Stream '%s' buffering complete (short sound)\n", pStream->szName));
    1676             Log3Func(("[%s] Dbg: Buffering complete (short)\n", pStream->szName));
     1693            Log3Func(("[%s] Dbg: Buffering complete (short)!\n", pStream->szName));
    16771694            pStream->fThresholdReached = fJustStarted = true;
    16781695        }
     
    16861703            return VINF_SUCCESS;
    16871704        }
     1705
     1706        /* Hack alert! This is for the underrun detection.  */
     1707        cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
     1708        if (cbWritable > pStream->Out.cbBackendMaxWritable)
     1709            pStream->Out.cbBackendMaxWritable = cbWritable;
    16881710    }
    16891711
     
    16921714     * Easy, as much as the host audio backend will allow us to.
    16931715     */
    1694     uint32_t cbWritable      = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
    16951716    uint32_t cFramesWritable = PDMAUDIOPCMPROPS_B2F(&pStream->Host.Cfg.Props, cbWritable);
    16961717    uint32_t cFramesToPlay   = cFramesWritable;
     
    17481769    }
    17491770
    1750     Log3Func(("[%s] Passed=%RU64 ms (%RU32 fr) Live=%RU32 fr (%RU64 ms) Period=%RU32 fr (%RU64 ms) Writable=%RU32 fr (%RU64 ms) -> ToPlay=%RU32 fr (%RU64 ms) Played=%RU32 fr (%RU64 ms)%s\n",
     1771    Log3Func(("[%s] Live=%RU32 fr (%RU64 ms) Period=%RU32 fr (%RU64 ms) Writable=%RU32 fr (%RU64 ms) -> ToPlay=%RU32 fr (%RU64 ms) Played=%RU32 fr (%RU64 ms)%s\n",
    17511772              pStream->szName,
    1752               PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesPassedReal), cFramesPassedReal,
    17531773              cFramesLive, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive),
    17541774              pStream->Host.Cfg.Backend.cFramesPeriod,
     
    38393859     * Statistics.
    38403860     */
     3861    PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->Out.StatsReBuffering, "OutputReBuffering",
     3862                              STAMUNIT_COUNT, "Number of times the output stream was re-buffered after starting.");
     3863
    38413864#ifdef VBOX_WITH_STATISTICS
    38423865    PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->Stats.TotalStreamsActive,   "TotalStreamsActive",
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