Changeset 70925 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Feb 9, 2018 9:51:46 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r70921 r70925 121 121 bool fEnabled; 122 122 RTCRITSECT CritSect; 123 PRTCIRCBUF pCircBuf; 123 124 union 124 125 { … … 132 133 /** Size (in bytes) of the DirectSound buffer. */ 133 134 DWORD cbBufSize; 134 HRESULT hrLastCapture;135 135 } In; 136 136 struct … … 154 154 bool fPendingPlayback; 155 155 bool fPendingClose; 156 PRTCIRCBUF pCircBuf;157 156 } Out; 158 157 }; … … 236 235 static HRESULT directSoundPlayRestore(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB); 237 236 static HRESULT directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush); 238 static HRESULT directSoundCaptureStop(PD SOUNDSTREAM pStreamDS);237 static HRESULT directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush); 239 238 240 239 static void dsoundDeviceRemove(PDSOUNDDEV pDev); … … 586 585 DSLOG(("DSound: Closing playback stream\n")); 587 586 588 if (pStreamDS-> Out.pCircBuf)589 Assert(RTCircBufUsed(pStreamDS-> Out.pCircBuf) == 0);587 if (pStreamDS->pCircBuf) 588 Assert(RTCircBufUsed(pStreamDS->pCircBuf) == 0); 590 589 591 590 if (SUCCEEDED(hr)) … … 593 592 RTCritSectEnter(&pThis->CritSect); 594 593 595 if (pStreamDS-> Out.pCircBuf)596 { 597 RTCircBufDestroy(pStreamDS-> Out.pCircBuf);598 pStreamDS-> Out.pCircBuf = NULL;594 if (pStreamDS->pCircBuf) 595 { 596 RTCircBufDestroy(pStreamDS->pCircBuf); 597 pStreamDS->pCircBuf = NULL; 599 598 } 600 599 … … 766 765 RTCritSectEnter(&pThis->CritSect); 767 766 768 rc = RTCircBufCreate(&pStreamDS-> Out.pCircBuf, pStreamDS->Out.cbBufSize);767 rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->Out.cbBufSize); 769 768 AssertRC(rc); 770 769 … … 906 905 { 907 906 if (fFlush) 908 RTCircBufReset(pStreamDS-> Out.pCircBuf);907 RTCircBufReset(pStreamDS->pCircBuf); 909 908 } 910 909 … … 1069 1068 1070 1069 1071 static HRESULT directSoundCaptureClose(PDSOUNDSTREAM pStreamDS) 1072 { 1070 static HRESULT directSoundCaptureClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS) 1071 { 1072 AssertPtrReturn(pThis, E_POINTER); 1073 1073 AssertPtrReturn(pStreamDS, E_POINTER); 1074 1074 1075 1075 LogFlowFuncEnter(); 1076 1076 1077 HRESULT hr = S_OK; 1077 HRESULT hr = directSoundCaptureStop(pThis, pStreamDS, true /* fFlush */); 1078 if (FAILED(hr)) 1079 return hr; 1078 1080 1079 1081 if ( pStreamDS … … 1082 1084 DSLOG(("DSound: Closing capturing stream\n")); 1083 1085 1084 hr = directSoundCaptureStop(pStreamDS); 1085 if (SUCCEEDED(hr)) 1086 { 1087 IDirectSoundCaptureBuffer8_Release(pStreamDS->In.pDSCB); 1088 pStreamDS->In.pDSCB = NULL; 1089 } 1090 else 1091 DSLOGREL(("DSound: Stopping capture buffer failed with %Rhrc\n", hr)); 1086 IDirectSoundCaptureBuffer8_Release(pStreamDS->In.pDSCB); 1087 pStreamDS->In.pDSCB = NULL; 1092 1088 } 1093 1089 … … 1212 1208 1213 1209 /* Initial state: reading at the initial capture position, no error. */ 1214 pStreamDS->In.offReadPos = offByteReadPos;1210 pStreamDS->In.offReadPos = 0; 1215 1211 pStreamDS->In.cbBufSize = bc.dwBufferBytes; 1216 pStreamDS->In.hrLastCapture = S_OK; 1217 1218 pCfgAcq->cFrameBufferHint = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, bc.dwBufferBytes); 1212 1213 rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->In.cbBufSize); 1214 AssertRC(rc); 1215 1216 /* 1217 * Install notification. 1218 */ 1219 LPDIRECTSOUNDNOTIFY8 pNotify; 1220 hr = IDirectSoundNotify_QueryInterface(pStreamDS->In.pDSCB, IID_IDirectSoundNotify8, (PVOID *)&pNotify); 1221 if (SUCCEEDED(hr)) 1222 { 1223 DSBPOSITIONNOTIFY dsPosNotify[3]; 1224 RT_ZERO(dsPosNotify); 1225 1226 dsPosNotify[0].dwOffset = 0; 1227 dsPosNotify[0].hEventNotify = pThis->aEvents[DSOUNDEVENT_INPUT]; 1228 1229 dsPosNotify[1].dwOffset = float(pStreamDS->In.cbBufSize * 0.3); 1230 dsPosNotify[1].hEventNotify = pThis->aEvents[DSOUNDEVENT_INPUT]; 1231 1232 dsPosNotify[2].dwOffset = float(pStreamDS->In.cbBufSize * 0.6); 1233 dsPosNotify[2].hEventNotify = pThis->aEvents[DSOUNDEVENT_INPUT]; 1234 1235 hr = IDirectSoundNotify_SetNotificationPositions(pNotify, 3 /* Count */, dsPosNotify); 1236 if (FAILED(hr)) 1237 DSLOGREL(("DSound: Setting capture position notification failed with %Rhrc\n", hr)); 1238 1239 IDirectSoundNotify_Release(pNotify); 1240 1241 pThis->pDSStrmIn = pStreamDS; 1242 } 1243 1244 pCfgAcq->cFrameBufferHint = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, pStreamDS->In.cbBufSize); 1219 1245 1220 1246 } while (0); 1221 1247 1222 1248 if (FAILED(hr)) 1223 directSoundCaptureClose(p StreamDS);1249 directSoundCaptureClose(pThis, pStreamDS); 1224 1250 1225 1251 LogFlowFunc(("Returning %Rhrc\n", hr)); … … 1228 1254 1229 1255 1230 static HRESULT directSoundCaptureStop(PDSOUNDSTREAM pStreamDS) 1231 { 1256 static HRESULT directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush) 1257 { 1258 AssertPtrReturn(pThis, E_POINTER); 1232 1259 AssertPtrReturn(pStreamDS, E_POINTER); 1260 1261 RT_NOREF(pThis); 1233 1262 1234 1263 HRESULT hr = S_OK; … … 1244 1273 pStreamDS->fEnabled = false; 1245 1274 } 1275 } 1276 1277 if (SUCCEEDED(hr)) 1278 { 1279 if (fFlush) 1280 RTCircBufReset(pStreamDS->pCircBuf); 1246 1281 } 1247 1282 … … 1609 1644 1610 1645 uint8_t *pbBuf = (uint8_t *)pvBuf; 1611 PRTCIRCBUF pCircBuf = pStreamDS-> Out.pCircBuf;1646 PRTCIRCBUF pCircBuf = pStreamDS->pCircBuf; 1612 1647 1613 1648 uint32_t cbToPlay = RT_MIN(cxBuf, (uint32_t)RTCircBufFree(pCircBuf)); … … 1683 1718 pStreamDS->In.cbBufSize = 0; 1684 1719 pStreamDS->In.pDSCB = NULL; 1685 pStreamDS->In.hrLastCapture = S_OK;1686 1720 1687 1721 int rc = VINF_SUCCESS; … … 1711 1745 if (FAILED(hr)) 1712 1746 { 1713 hr = directSoundCaptureClose(p StreamDS);1747 hr = directSoundCaptureClose(pThis, pStreamDS); 1714 1748 if (SUCCEEDED(hr)) 1715 1749 { … … 1740 1774 AssertPtr(pThis->pDSC); 1741 1775 1742 directSoundCaptureStop(pStreamDS); 1776 directSoundCaptureStop(pThis, pStreamDS, 1777 enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE /* fFlush */); 1743 1778 1744 1779 /* Return success in any case, as stopping the capture can fail if … … 1761 1796 } 1762 1797 1763 1764 1798 /** 1765 1799 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture} … … 1777 1811 PDSOUNDSTREAM pStreamDS = (PDSOUNDSTREAM)pStream; 1778 1812 1779 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB = pStreamDS->In.pDSCB;1780 AssertPtr(pDSCB);1781 1782 1813 int rc = VINF_SUCCESS; 1783 1814 1784 1815 uint32_t cbReadTotal = 0; 1785 1816 1786 do 1787 { 1788 if (pDSCB == NULL) 1789 { 1790 rc = VERR_NOT_AVAILABLE; 1791 break; 1792 } 1793 1794 /* Get DirectSound capture position in bytes. */ 1795 DWORD offCurPos; 1796 HRESULT hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pDSCB, NULL, &offCurPos); 1797 if (FAILED(hr)) 1798 { 1799 if (hr != pStreamDS->In.hrLastCapture) 1800 { 1801 DSLOGREL(("DSound: Getting capture position failed with %Rhrc\n", hr)); 1802 pStreamDS->In.hrLastCapture = hr; 1803 } 1804 1805 rc = VERR_NOT_AVAILABLE; 1806 break; 1807 } 1808 1809 pStreamDS->In.hrLastCapture = hr; 1810 1811 if (offCurPos & pStreamDS->uAlign) 1812 DSLOGF(("DSound: Misaligned capture read position %ld (alignment: %RU32)\n", 1813 offCurPos, pStreamDS->uAlign + 1)); 1814 1815 /* Number of samples available in the DirectSound capture buffer. */ 1816 DWORD cbToCapture = dsoundRingDistance(offCurPos, pStreamDS->In.offReadPos, pStreamDS->In.cbBufSize); 1817 if (cbToCapture == 0) 1818 break; 1819 1820 if (cxBuf == 0) 1821 { 1822 DSLOGF(("DSound: Capture buffer full\n")); 1823 break; 1824 } 1825 1826 DSLOGF(("DSound: Capture cxBuf=%RU32, offCurPos=%ld, offReadPos=%ld, cbToCapture=%ld\n", 1827 cxBuf, offCurPos, pStreamDS->In.offReadPos, cbToCapture)); 1828 1829 /* No need to fetch more samples than mix buffer can receive. */ 1830 cbToCapture = RT_MIN(cbToCapture, cxBuf); 1831 1832 /* Lock relevant range in the DirectSound capture buffer. */ 1833 PVOID pv1, pv2; 1834 DWORD cb1, cb2; 1835 hr = directSoundCaptureLock(pStreamDS, 1836 pStreamDS->In.offReadPos, /* dwOffset */ 1837 cbToCapture, /* dwBytes */ 1838 &pv1, &pv2, &cb1, &cb2, 1839 0 /* dwFlags */); 1840 if (FAILED(hr)) 1841 { 1842 rc = VERR_ACCESS_DENIED; 1843 break; 1844 } 1845 1846 if (pv1 && cb1) 1847 { 1848 memcpy((uint8_t *)pvBuf + cbReadTotal, pv1, cb1); 1849 cbReadTotal += cb1; 1850 } 1851 1852 if (pv2 && cb2) 1853 { 1854 memcpy((uint8_t *)pvBuf + cbReadTotal, pv2, cb2); 1855 cbReadTotal += cb2; 1856 } 1857 1858 directSoundCaptureUnlock(pDSCB, pv1, pv2, cb1, cb2); 1859 1860 if (RT_SUCCESS(rc)) 1861 { 1862 pStreamDS->In.offReadPos = (pStreamDS->In.offReadPos + cbReadTotal) 1863 % pStreamDS->In.cbBufSize; 1864 DSLOGF(("DSound: Captured %ld bytes (%RU32 total)\n", cbToCapture, cbReadTotal)); 1865 } 1866 1867 } while (0); 1817 uint32_t cbToRead = RT_MIN((uint32_t)RTCircBufUsed(pStreamDS->pCircBuf), cxBuf); 1818 while (cbToRead) 1819 { 1820 void *pvChunk; 1821 size_t cbChunk; 1822 RTCircBufAcquireReadBlock(pStreamDS->pCircBuf, cbToRead, &pvChunk, &cbChunk); 1823 1824 if (cbChunk) 1825 { 1826 memcpy((uint8_t *)pvBuf + cbReadTotal, pvChunk, cbChunk); 1827 cbReadTotal += (uint32_t)cbChunk; 1828 Assert(cbToRead >= cbChunk); 1829 cbToRead -= (uint32_t)cbChunk; 1830 } 1831 1832 RTCircBufReleaseReadBlock(pStreamDS->pCircBuf, cbChunk); 1833 } 1868 1834 1869 1835 if (RT_SUCCESS(rc)) … … 1878 1844 } 1879 1845 1880 static int dsoundDestroyStreamIn(PD SOUNDSTREAM pStreamDS)1846 static int dsoundDestroyStreamIn(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS) 1881 1847 { 1882 1848 LogFlowFuncEnter(); 1883 1849 1884 directSoundCaptureClose(p StreamDS);1850 directSoundCaptureClose(pThis, pStreamDS); 1885 1851 1886 1852 return VINF_SUCCESS; … … 1974 1940 dwObj -= WAIT_OBJECT_0; 1975 1941 1976 Log3Func(("Event %ld\n", dwObj));1977 1978 PDSOUNDSTREAM pStreamDS = pThis->pDSStrmOut;1979 1980 if (! pStreamDS1981 || !pStreamDS->fEnabled)1982 break;1983 1984 1942 if (dwObj == DSOUNDEVENT_NOTIFY) 1985 1943 { 1944 Log3Func(("Notify\n")); 1986 1945 } 1987 1946 else if (dwObj == DSOUNDEVENT_INPUT) 1988 1947 { 1948 PDSOUNDSTREAM pStreamDS = pThis->pDSStrmIn; 1949 1950 if ( !pStreamDS 1951 || !pStreamDS->fEnabled) 1952 { 1953 Log3Func(("Skipping capture\n")); 1954 break; 1955 } 1956 1957 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB = pStreamDS->In.pDSCB; 1958 AssertPtr(pDSCB); 1959 1960 DWORD offCaptureCursor; 1961 HRESULT hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pDSCB, NULL, &offCaptureCursor); 1962 if (FAILED(hr)) 1963 break; 1964 1965 DWORD cbUsed = dsoundRingDistance(offCaptureCursor, pStreamDS->In.offReadPos, pStreamDS->In.cbBufSize); 1966 1967 PRTCIRCBUF pCircBuf = pStreamDS->pCircBuf; 1968 AssertPtr(pCircBuf); 1969 1970 uint32_t cbFree = (uint32_t)RTCircBufFree(pCircBuf); 1971 if (!cbFree) 1972 DSLOG(("DSound: Warning: Capture buffer full, skipping to record data (%RU32 bytes)\n", cbUsed)); 1973 1974 DWORD cbToCapture = RT_MIN(cbUsed, cbFree); 1975 1976 Log3Func(("cbUsed=%ld, cbToCapture=%ld\n", cbUsed, cbToCapture)); 1977 1978 while (cbToCapture) 1979 { 1980 void *pvBuf; 1981 size_t cbBuf; 1982 RTCircBufAcquireWriteBlock(pCircBuf, cbToCapture, &pvBuf, &cbBuf); 1983 1984 if (cbBuf) 1985 { 1986 PVOID pv1, pv2; 1987 DWORD cb1, cb2; 1988 hr = directSoundCaptureLock(pStreamDS, pStreamDS->In.offReadPos, (DWORD)cbBuf, 1989 &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */); 1990 if (FAILED(hr)) 1991 break; 1992 1993 AssertPtr(pv1); 1994 Assert(cb1); 1995 1996 memcpy(pvBuf, pv1, cb1); 1997 1998 if (pv2 && cb2) /* Buffer wrap-around? Write second part. */ 1999 memcpy((uint8_t *)pvBuf + cb1, pv2, cb2); 2000 2001 directSoundCaptureUnlock(pDSCB, pv1, pv2, cb1, cb2); 2002 2003 pStreamDS->In.offReadPos = (pStreamDS->In.offReadPos + cb1 + cb2) % pStreamDS->In.cbBufSize; 2004 2005 Assert(cbToCapture >= cbBuf); 2006 cbToCapture -= (uint32_t)cbBuf; 2007 } 2008 2009 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA 2010 if (cbBuf) 2011 { 2012 RTFILE fh; 2013 int rc2 = RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "dsoundCapture.pcm", 2014 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 2015 if (RT_SUCCESS(rc2)) 2016 { 2017 RTFileWrite(fh, pvBuf, cbBuf, NULL); 2018 RTFileClose(fh); 2019 } 2020 } 2021 #endif 2022 RTCircBufReleaseWriteBlock(pCircBuf, cbBuf); 2023 } 1989 2024 } 1990 2025 else if (dwObj == DSOUNDEVENT_OUTPUT) 1991 2026 { 2027 PDSOUNDSTREAM pStreamDS = pThis->pDSStrmOut; 2028 2029 if ( !pStreamDS 2030 || !pStreamDS->fEnabled) 2031 { 2032 Log3Func(("Skipping playback\n")); 2033 break; 2034 } 2035 1992 2036 LPDIRECTSOUNDBUFFER8 pDSB = pStreamDS->Out.pDSB; 1993 if (!pDSB) 1994 break; 2037 AssertPtr(pDSB); 1995 2038 1996 2039 HRESULT hr; 1997 1998 DWORD offPlayCursor; DWORD offWriteCursor2;1999 hr = IDirectSoundBuffer8_GetCurrentPosition(pStreamDS->Out.pDSB, &offPlayCursor, &offWriteCursor2);2000 2001 //Log3Func(("p=%ld, w=%ld\n", offPlayCursor, offWriteCursor2));2002 2040 2003 2041 DWORD cbFree, cbRemaining; … … 2005 2043 { 2006 2044 DWORD offWriteCursor; 2007 hr = IDirectSoundBuffer8_GetCurrentPosition(p StreamDS->Out.pDSB, NULL, &offWriteCursor);2045 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, NULL, &offWriteCursor); 2008 2046 if (FAILED(hr)) 2009 2047 break; … … 2017 2055 { 2018 2056 DWORD offPlayCursor; 2019 hr = IDirectSoundBuffer8_GetCurrentPosition(p StreamDS->Out.pDSB, &offPlayCursor, NULL);2057 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &offPlayCursor, NULL); 2020 2058 if (FAILED(hr)) 2021 2059 break; … … 2025 2063 } 2026 2064 2027 PRTCIRCBUF pCircBuf = pStreamDS-> Out.pCircBuf;2065 PRTCIRCBUF pCircBuf = pStreamDS->pCircBuf; 2028 2066 AssertPtr(pCircBuf); 2029 2067 2030 2068 DWORD cbUsed = (uint32_t)RTCircBufUsed(pCircBuf); 2069 if (!cbUsed) 2070 DSLOG(("DSound: Warning: No more playback data available within time (%RU32 bytes free)\n", cbFree)); 2071 2031 2072 DWORD cbToPlay = RT_MIN(cbFree, cbUsed); 2032 2073 2033 //Log3Func(("cbUsed=%ld, cbToPlay=%ld\n", cbUsed, cbToPlay));2074 Log3Func(("cbUsed=%ld, cbToPlay=%ld\n", cbUsed, cbToPlay)); 2034 2075 2035 2076 while (cbToPlay) … … 2075 2116 for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++) 2076 2117 { 2077 hr = IDirectSoundBuffer8_Play(p StreamDS->Out.pDSB, 0, 0, fFlags);2118 hr = IDirectSoundBuffer8_Play(pDSB, 0, 0, fFlags); 2078 2119 if ( SUCCEEDED(hr) 2079 2120 || hr != DSERR_BUFFERLOST) … … 2082 2123 { 2083 2124 LogFunc(("Restarting playback failed due to lost buffer, restoring ...\n")); 2084 directSoundPlayRestore(pThis, p StreamDS->Out.pDSB);2125 directSoundPlayRestore(pThis, pDSB); 2085 2126 } 2086 2127 } … … 2099 2140 { 2100 2141 DSLOG(("DSound: Stopping playing output\n")); 2101 hr = IDirectSoundBuffer8_Stop(p StreamDS->Out.pDSB);2142 hr = IDirectSoundBuffer8_Stop(pDSB); 2102 2143 } 2103 2144 } … … 2303 2344 int rc; 2304 2345 if (pStreamDS->pCfg->enmDir == PDMAUDIODIR_IN) 2305 rc = dsoundDestroyStreamIn(p StreamDS);2346 rc = dsoundDestroyStreamIn(pThis, pStreamDS); 2306 2347 else 2307 2348 rc = dsoundDestroyStreamOut(pThis, pStreamDS); … … 2352 2393 PDSOUNDSTREAM pStreamDS = (PDSOUNDSTREAM)pStream; 2353 2394 2354 if (pStreamDS->fEnabled) 2355 return UINT32_MAX; 2395 if ( pStreamDS->fEnabled 2396 && pStreamDS->pCircBuf) 2397 { 2398 return (uint32_t)RTCircBufUsed(pStreamDS->pCircBuf); 2399 } 2356 2400 2357 2401 return 0; … … 2370 2414 2371 2415 if (pStreamDS->fEnabled) 2372 return (uint32_t)RTCircBufFree(pStreamDS-> Out.pCircBuf);2416 return (uint32_t)RTCircBufFree(pStreamDS->pCircBuf); 2373 2417 2374 2418 return 0; … … 2391 2435 2392 2436 /* Any uncommitted data left? */ 2393 if (pStreamDS-> Out.pCircBuf)2394 cbPending = (uint32_t)RTCircBufUsed(pStreamDS-> Out.pCircBuf);2437 if (pStreamDS->pCircBuf) 2438 cbPending = (uint32_t)RTCircBufUsed(pStreamDS->pCircBuf); 2395 2439 2396 2440 /* Check if we have committed data which still needs to be played by
Note:
See TracChangeset
for help on using the changeset viewer.