VirtualBox

Changeset 88913 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 6, 2021 6:56:26 PM (4 years ago)
Author:
vboxsync
Message:

AudioMixer: Added crude heuristics to audioMixerSinkUpdateOutput for prevent that a malfunctioning stream will clog up everything for everyone else. bugref:9890

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

Legend:

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

    r88909 r88913  
    16031603}
    16041604
    1605 /**
    1606  * Updates an output mixer sink.
    1607  *
    1608  * @returns VBox status code.
    1609  * @param   pSink               Mixer sink to update.
    1610  */
    1611 static int audioMixerSinkUpdateOutput(PAUDMIXSINK pSink)
    1612 {
    1613     /*
    1614      * Update each mixing sink stream's status and check how much we can
    1615      * write into them.
    1616      *
    1617      * We're currently using the minimum size of all streams, however this
    1618      * isn't a smart approach as it means one disfunctional stream can block
    1619      * working ones.
    1620      */
    1621     /** @todo rework this so a broken stream cannot hold up everyone. */
     1605
     1606static uint32_t audioMixerSinkUpdateOutputCalcFramesToRead(PAUDMIXSINK pSink, uint32_t *pcWritableStreams)
     1607{
    16221608    uint32_t      cFramesToRead    = AudioMixBufLive(&pSink->MixBuf); /* (to read from the mixing buffer) */
    16231609    uint32_t      cWritableStreams = 0;
     
    16371623            uint32_t const cbWritable = pMixStream->pConn->pfnStreamGetWritable(pMixStream->pConn, pMixStream->pStream);
    16381624            uint32_t cFrames = PDMAudioPropsBytesToFrames(&pMixStream->pStream->Props, cbWritable);
     1625            pMixStream->cFramesLastAvail = cFrames;
    16391626            if (PDMAudioPropsHz(&pMixStream->pStream->Props) == PDMAudioPropsHz(&pSink->MixBuf.Props))
    16401627            { /* likely */ }
     
    16441631                cFrames = cFrames > 2 ? cFrames - 2 : 0; /* rounding safety fudge */
    16451632            }
    1646             if (cFramesToRead > cFrames)
     1633            if (cFramesToRead > cFrames && !pMixStream->fUnreliable)
    16471634            {
    16481635                Log4Func(("%s: cFramesToRead %u -> %u; %s (%u bytes writable)\n",
     
    16531640        }
    16541641    }
    1655     Log3Func(("%s: cLiveFrames=%#x cFramesToRead=%#x cWritableStreams=%#x\n", pSink->pszName,
    1656               AudioMixBufLive(&pSink->MixBuf), cFramesToRead, cWritableStreams));
     1642
     1643    *pcWritableStreams = cWritableStreams;
     1644    return cFramesToRead;
     1645}
     1646
     1647
     1648/**
     1649 * Updates an output mixer sink.
     1650 *
     1651 * @returns VBox status code.
     1652 * @param   pSink               Mixer sink to update.
     1653 */
     1654static int audioMixerSinkUpdateOutput(PAUDMIXSINK pSink)
     1655{
     1656    PAUDMIXSTREAM pMixStream;
     1657
     1658    /*
     1659     * Update each mixing sink stream's status and check how much we can
     1660     * write into them.
     1661     *
     1662     * We're currently using the minimum size of all streams, however this
     1663     * isn't a smart approach as it means one disfunctional stream can block
     1664     * working ones.  So, if we end up with zero frames and a full mixer
     1665     * buffer we'll disregard the stream that accept the smallest amount and
     1666     * try again.
     1667     */
     1668    uint32_t cReliableStreams  = 0;
     1669    uint32_t cMarkedUnreliable = 0;
     1670    uint32_t cWritableStreams  = 0;
     1671    uint32_t cFramesToRead     = audioMixerSinkUpdateOutputCalcFramesToRead(pSink, &cWritableStreams);
     1672    if (   cFramesToRead != 0
     1673        || cWritableStreams <= 1
     1674        || AudioMixBufFree(&pSink->MixBuf) > 2)
     1675        Log3Func(("%s: cLiveFrames=%#x cFramesToRead=%#x cWritableStreams=%#x\n", pSink->pszName,
     1676                  AudioMixBufLive(&pSink->MixBuf), cFramesToRead, cWritableStreams));
     1677    else
     1678    {
     1679        Log3Func(("%s: MixBuf is full but one or more streams only want zero frames.  Try disregarding those...\n", pSink->pszName));
     1680        PAUDMIXSTREAM pMixStreamMin     = NULL;
     1681        RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
     1682        {
     1683            if (pMixStream->fStatus & AUDMIXSTREAM_STATUS_CAN_WRITE)
     1684            {
     1685                if (!pMixStream->fUnreliable)
     1686                {
     1687                    if (pMixStream->cFramesLastAvail == 0)
     1688                    {
     1689                        cMarkedUnreliable++;
     1690                        pMixStream->fUnreliable = true;
     1691                        Log3Func(("%s: Marked '%s' as unreliable.\n", pSink->pszName, pMixStream->pszName));
     1692                        pMixStreamMin = pMixStreamMin;
     1693                    }
     1694                    else
     1695                    {
     1696                        if (!pMixStreamMin || pMixStream->cFramesLastAvail < pMixStreamMin->cFramesLastAvail)
     1697                            pMixStreamMin = pMixStreamMin;
     1698                        cReliableStreams++;
     1699                    }
     1700                }
     1701            }
     1702        }
     1703
     1704        if (cMarkedUnreliable == 0 && pMixStreamMin && cReliableStreams > 1)
     1705        {
     1706            cReliableStreams--;
     1707            cMarkedUnreliable++;
     1708            pMixStreamMin->fUnreliable = true;
     1709            Log3Func(("%s: Marked '%s' as unreliable (%u frames).\n",
     1710                      pSink->pszName, pMixStream->pszName, pMixStream->cFramesLastAvail));
     1711        }
     1712
     1713        if (cMarkedUnreliable > 0)
     1714        {
     1715            cWritableStreams = 0;
     1716            cFramesToRead = audioMixerSinkUpdateOutputCalcFramesToRead(pSink, &cWritableStreams);
     1717        }
     1718
     1719        Log3Func(("%s: cLiveFrames=%#x cFramesToRead=%#x cWritableStreams=%#x cMarkedUnreliable=%#x cReliableStreams=%#x\n",
     1720                  pSink->pszName, AudioMixBufLive(&pSink->MixBuf), cFramesToRead,
     1721                  cWritableStreams, cMarkedUnreliable, cReliableStreams));
     1722    }
    16571723
    16581724    if (cWritableStreams > 0)
     
    16921758
    16931759                        /* Write it to the backend.  Since've checked that there is buffer
    1694                            space available, this should always write the whole buffer. */
     1760                           space available, this should always write the whole buffer unless
     1761                           it's an unreliable stream. */
    16951762                        uint32_t cbDstWritten = 0;
    16961763                        int rc2 = pMixStream->pConn->pfnStreamPlay(pMixStream->pConn, pMixStream->pStream,
     
    17021769#endif
    17031770                        if (RT_SUCCESS(rc2))
    1704                             AssertLogRelMsg(cbDstWritten == cbDstPeeked,
     1771                            AssertLogRelMsg(cbDstWritten == cbDstPeeked || pMixStream->fUnreliable,
    17051772                                            ("cbDstWritten=%#x cbDstPeeked=%#x - (sink '%s')\n",
    17061773                                             cbDstWritten, cbDstPeeked, pSink->pszName));
  • trunk/src/VBox/Devices/Audio/AudioMixer.h

    r88909 r88913  
    103103    /** Stream status of type AUDMIXSTREAM_STATUS_. */
    104104    uint32_t                fStatus;
     105    /** Number of writable/readable frames the last time we checked. */
     106    uint32_t                cFramesLastAvail;
     107    /** Set if the stream has been found unreliable wrt. consuming/producing
     108     * samples, and that we shouldn't consider it when deciding how much to move
     109     * from the mixer buffer and to the drivers. */
     110    bool                    fUnreliable;
    105111    /** Pointer to audio connector being used. */
    106112    PPDMIAUDIOCONNECTOR     pConn;
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