Changeset 88243 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Mar 22, 2021 12:32:22 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r88240 r88243 142 142 /** Shutdown indicator. */ 143 143 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 144 148 /** Our audio connector interface. */ 145 149 PDMIAUDIOCONNECTOR IAudioConnector; … … 150 154 /** List of audio streams. */ 151 155 RTLISTANCHOR lstStreams; 152 #ifdef VBOX_WITH_AUDIO_ENUM153 /** Flag indicating to perform an (re-)enumeration of the host audio devices. */154 bool fEnumerateDevices;155 #endif156 156 /** Audio configuration settings retrieved from the backend. */ 157 157 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_STATISTICS163 /** Statistics for the statistics manager (STAM). */164 DRVAUDIOSTATS Stats;165 #endif166 158 struct 167 159 { … … 192 184 DRVAUDIOCFG Cfg; 193 185 } 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. */ 192 typedef DRVAUDIO *PDRVAUDIO; 195 193 196 194 … … 1450 1448 * Plays an audio host output stream which has been configured for non-interleaved (layout) data. 1451 1449 * 1452 * @return IPRTstatus code.1450 * @returns VBox status code. 1453 1451 * @param pThis Pointer to driver instance. 1454 1452 * @param pStream Stream to play. … … 1459 1457 PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed) 1460 1458 { 1461 AssertPtrReturn(pThis, 1459 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1462 1460 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 */ 1465 1468 if (!cfToPlay) 1466 1469 { … … 1470 1473 } 1471 1474 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; 1478 1479 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; 1485 1481 while (cfLeft) 1486 1482 { 1483 uint8_t abChunk[_4K]; 1487 1484 uint32_t cfRead = 0; 1488 1485 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)), 1490 1487 &cfRead); 1491 1488 if (RT_FAILURE(rc)) … … 1493 1490 1494 1491 uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfRead); 1495 Assert(cbRead <= cbChunk);1492 Assert(cbRead <= sizeof(abChunk)); 1496 1493 1497 1494 uint32_t cfPlayed = 0; 1498 1495 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); 1501 1497 if ( RT_SUCCESS(rc) 1502 1498 && cbPlayed) 1503 1499 { 1504 1500 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 */); 1506 1502 1507 1503 if (cbRead != cbPlayed) … … 1536 1532 * Plays an audio host output stream which has been configured for raw audio (layout) data. 1537 1533 * 1538 * @return IPRTstatus code.1534 * @returns VBox status code. 1539 1535 * @param pThis Pointer to driver instance. 1540 1536 * @param pStream Stream to play. … … 1545 1541 PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed) 1546 1542 { 1547 AssertPtrReturn(pThis, 1543 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1548 1544 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1549 /* pcfPlayed is optional. */ 1550 1551 /* Sanity. */ 1545 AssertPtrNullReturn(pcfPlayed, VERR_INVALID_POINTER); 1552 1546 Assert(pStream->enmDir == PDMAUDIODIR_OUT); 1553 1547 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 1554 1548 1549 /* 1550 * ... 1551 */ 1555 1552 if (!cfToPlay) 1556 1553 { … … 1560 1557 } 1561 1558 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; 1570 1565 while (cfLeft) 1571 1566 { 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); 1576 1570 if (RT_SUCCESS(rc)) 1577 1571 { 1578 1572 if (cfRead) 1579 1573 { 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); 1587 1578 if ( RT_FAILURE(rc) 1588 1579 || !cfPlayed) 1589 {1590 1580 break; 1591 }1592 1581 1593 1582 cfPlayedTotal += cfPlayed; … … 1599 1588 else 1600 1589 { 1590 /** @todo r=bird: This looks totally loopy. Why should another call return data 1591 * when the first one didn't? */ 1601 1592 if (rc == VINF_AUDIO_MORE_DATA_AVAILABLE) /* Do another peeking round if there is more data available. */ 1602 1593 continue; 1603 1604 1594 break; 1605 1595 } 1606 1596 } 1607 else if (RT_FAILURE(rc))1597 else 1608 1598 break; 1609 1599 } 1610 1600 1601 if (RT_SUCCESS(rc) && pcfPlayed) 1602 *pcfPlayed = cfPlayedTotal; 1611 1603 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 1620 1604 return rc; 1621 1605 } … … 1624 1608 * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamPlay} 1625 1609 */ 1626 static DECLCALLBACK(int) drvAudioStreamPlay(PPDMIAUDIOCONNECTOR pInterface, 1627 PPDMAUDIOSTREAM pStream, uint32_t *pcFramesPlayed) 1610 static DECLCALLBACK(int) drvAudioStreamPlay(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcFramesPlayed) 1628 1611 { 1629 1612 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector); … … 1631 1614 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1632 1615 AssertPtrNullReturn(pcFramesPlayed, VERR_INVALID_POINTER); 1633 1634 1616 1635 1617 int rc = RTCritSectEnter(&pThis->CritSect); … … 1802 1784 RTCritSectLeave(&pThis->CritSect); 1803 1785 1804 if (RT_SUCCESS(rc)) 1805 { 1806 if (pcFramesPlayed) 1807 *pcFramesPlayed = cfPlayedTotal; 1808 } 1786 if (RT_SUCCESS(rc) && pcFramesPlayed) 1787 *pcFramesPlayed = cfPlayedTotal; 1809 1788 1810 1789 if (RT_FAILURE(rc)) … … 1823 1802 static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured) 1824 1803 { 1825 AssertPtrReturn(pThis, 1804 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1826 1805 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1827 /* pcfCaptured is optional. */ 1828 1829 /* Sanity. */ 1806 AssertPtrNullReturn(pcfCaptured, VERR_INVALID_POINTER); 1830 1807 Assert(pStream->enmDir == PDMAUDIODIR_IN); 1831 1808 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED); 1832 1809 1833 int rc = VINF_SUCCESS; 1834 1835 uint32_t cfCapturedTotal = 0; 1836 1810 /* 1811 * ... 1812 */ 1837 1813 AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable); 1838 1839 1814 uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend); 1840 1815 if (!cbReadable) … … 1848 1823 cbReadable = cbFree; 1849 1824 1825 /* 1826 * ... 1827 */ 1828 int rc = VINF_SUCCESS; 1829 uint32_t cfCapturedTotal = 0; 1850 1830 while (cbReadable) 1851 1831 { 1832 uint8_t abChunk[_4K]; 1852 1833 uint32_t cbCaptured; 1853 1834 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); 1855 1836 if (RT_FAILURE(rc)) 1856 1837 { 1857 1838 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 1858 1839 AssertRC(rc2); 1859 1860 1840 break; 1861 1841 } 1862 1842 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); 1866 1846 1867 1847 if (!cbCaptured) /* Nothing captured? Take a shortcut. */ … … 1871 1851 * (first) processing (if needed), so always write the incoming data at offset 0. */ 1872 1852 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); 1874 1854 if ( RT_FAILURE(rc) 1875 1855 || !cfHstWritten) … … 1881 1861 1882 1862 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 */); 1884 1864 1885 1865 uint32_t cfHstMixed = 0; … … 1933 1913 AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable); 1934 1914 1935 int rc = VINF_SUCCESS; 1936 1937 uint32_t cfCapturedTotal = 0; 1938 1915 /* 1916 * ... 1917 */ 1939 1918 /* Note: Raw means *audio frames*, not bytes! */ 1940 1919 uint32_t cfReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend); … … 1949 1928 cfReadable = cfFree; 1950 1929 1930 /* 1931 * ... 1932 */ 1933 int rc = VINF_SUCCESS; 1934 uint32_t cfCapturedTotal = 0; 1951 1935 while (cfReadable) 1952 1936 { … … 1956 1940 if ( RT_FAILURE(rc) 1957 1941 || !cfWritable) 1958 {1959 1942 break; 1960 }1961 1943 1962 1944 uint32_t cfCaptured; … … 1967 1949 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 1968 1950 AssertRC(rc2); 1969 1970 1951 break; 1971 1952 } … … 1980 1961 } 1981 1962 1982 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc));1983 1984 1963 if (pcfCaptured) 1985 1964 *pcfCaptured = cfCapturedTotal; 1986 1965 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc)); 1987 1966 return rc; 1988 1967 } … … 2010 1989 2011 1990 /* 2012 * 1991 * ... 2013 1992 */ 2014 1993 uint32_t cfCaptured = 0; … … 2031 2010 * Do the actual capturing. 2032 2011 */ 2033 2034 2012 if (pThis->pHostDrvAudio->pfnStreamCaptureBegin) 2035 2013 pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pStream->pvBackend); … … 2056 2034 } 2057 2035 else if (RT_UNLIKELY(RT_FAILURE(rc))) 2058 {2059 2036 LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStream->szName, rc)); 2060 }2061 2062 2037 } while (0); 2063 2038 … … 3623 3598 #endif 3624 3599 3625 if (pThis->pvScratchBuf)3626 {3627 Assert(pThis->cbScratchBuf);3628 3629 RTMemFree(pThis->pvScratchBuf);3630 pThis->pvScratchBuf = NULL;3631 }3632 3633 3600 if (RTCritSectIsInitialized(&pThis->CritSect)) 3634 3601 { … … 3831 3798 rc = RTCritSectInit(&pThis->CritSect); 3832 3799 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;3838 3800 3839 3801 pThis->fTerminate = false;
Note:
See TracChangeset
for help on using the changeset viewer.