Changeset 88913 in vbox for trunk/src/VBox
- Timestamp:
- May 6, 2021 6:56:26 PM (4 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r88909 r88913 1603 1603 } 1604 1604 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 1606 static uint32_t audioMixerSinkUpdateOutputCalcFramesToRead(PAUDMIXSINK pSink, uint32_t *pcWritableStreams) 1607 { 1622 1608 uint32_t cFramesToRead = AudioMixBufLive(&pSink->MixBuf); /* (to read from the mixing buffer) */ 1623 1609 uint32_t cWritableStreams = 0; … … 1637 1623 uint32_t const cbWritable = pMixStream->pConn->pfnStreamGetWritable(pMixStream->pConn, pMixStream->pStream); 1638 1624 uint32_t cFrames = PDMAudioPropsBytesToFrames(&pMixStream->pStream->Props, cbWritable); 1625 pMixStream->cFramesLastAvail = cFrames; 1639 1626 if (PDMAudioPropsHz(&pMixStream->pStream->Props) == PDMAudioPropsHz(&pSink->MixBuf.Props)) 1640 1627 { /* likely */ } … … 1644 1631 cFrames = cFrames > 2 ? cFrames - 2 : 0; /* rounding safety fudge */ 1645 1632 } 1646 if (cFramesToRead > cFrames )1633 if (cFramesToRead > cFrames && !pMixStream->fUnreliable) 1647 1634 { 1648 1635 Log4Func(("%s: cFramesToRead %u -> %u; %s (%u bytes writable)\n", … … 1653 1640 } 1654 1641 } 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 */ 1654 static 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 } 1657 1723 1658 1724 if (cWritableStreams > 0) … … 1692 1758 1693 1759 /* 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. */ 1695 1762 uint32_t cbDstWritten = 0; 1696 1763 int rc2 = pMixStream->pConn->pfnStreamPlay(pMixStream->pConn, pMixStream->pStream, … … 1702 1769 #endif 1703 1770 if (RT_SUCCESS(rc2)) 1704 AssertLogRelMsg(cbDstWritten == cbDstPeeked ,1771 AssertLogRelMsg(cbDstWritten == cbDstPeeked || pMixStream->fUnreliable, 1705 1772 ("cbDstWritten=%#x cbDstPeeked=%#x - (sink '%s')\n", 1706 1773 cbDstWritten, cbDstPeeked, pSink->pszName)); -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r88909 r88913 103 103 /** Stream status of type AUDMIXSTREAM_STATUS_. */ 104 104 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; 105 111 /** Pointer to audio connector being used. */ 106 112 PPDMIAUDIOCONNECTOR pConn;
Note:
See TracChangeset
for help on using the changeset viewer.