Changeset 88566 in vbox
- Timestamp:
- Apr 16, 2021 1:55:05 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostAudioDSound.cpp
r88564 r88566 108 108 typedef struct DSOUNDSTREAM 109 109 { 110 /** Entry in DRVHOSTDSOUND::HeadStreams. */ 111 RTLISTNODE ListEntry; 110 112 /** The stream's acquired configuration. */ 111 113 PDMAUDIOSTREAMCFG Cfg; … … 155 157 * to the DirectSound buffer was. */ 156 158 uint32_t cbLastTransferred; 159 /** The RTTimeMilliTS() deadline for the draining of this stream. */ 160 uint64_t msDrainDeadline; 157 161 } Out; 158 162 }; … … 165 169 char szStatus[127]; 166 170 /** Fixed zero terminator. */ 167 char const chStateZero;171 char const chStateZero; 168 172 } DSOUNDSTREAM, *PDSOUNDSTREAM; 169 173 … … 213 217 /** The Direct Sound capturing interface. */ 214 218 LPDIRECTSOUNDCAPTURE8 pDSC; 219 /** A drain stop timer that makes sure a draining stream will be 220 * properly stopped (seem the non-loop mode is a bit buggy). */ 221 TMTIMERHANDLE hDrainTimer; 222 /** List of streams (DSOUNDSTREAM). 223 * Requires CritSect ownership. */ 224 RTLISTANCHOR HeadStreams; 225 215 226 #ifdef VBOX_WITH_AUDIO_MMNOTIFICATION_CLIENT 216 227 DrvHostAudioDSoundMMNotifClient *m_pNotificationClient; … … 1641 1652 pCfgReq->enmDir == PDMAUDIODIR_IN ? PDMAudioRecSrcGetName(pCfgReq->u.enmSrc) 1642 1653 : PDMAudioPlaybackDstGetName(pCfgReq->u.enmDst), pCfgReq->szName)); 1654 RTListInit(&pStreamDS->ListEntry); /* paranoia */ 1643 1655 1644 1656 /* For whatever reason: */ … … 1693 1705 PDMAudioStrmCfgCopy(&pStreamDS->Cfg, pCfgAcq); 1694 1706 drvHostDSoundStreamReset(pThis, pStreamDS); 1707 1708 RTCritSectEnter(&pThis->CritSect); 1709 RTListAppend(&pThis->HeadStreams, &pStreamDS->ListEntry); 1710 RTCritSectLeave(&pThis->CritSect); 1711 1695 1712 rc = VINF_SUCCESS; 1696 1713 } … … 1712 1729 AssertPtrReturn(pStreamDS, VERR_INVALID_POINTER); 1713 1730 LogFlowFunc(("Stream '%s' {%s}\n", pStreamDS->Cfg.szName, drvHostDSoundStreamStatusString(pStreamDS))); 1731 1732 RTCritSectEnter(&pThis->CritSect); 1733 RTListNodeRemove(&pStreamDS->ListEntry); 1734 RTCritSectLeave(&pThis->CritSect); 1714 1735 1715 1736 if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN) … … 2069 2090 2070 2091 /** 2092 * This is used by the timer function as well as when arming the timer. 2093 * 2094 * @param pThis The DSound host audio driver instance data. 2095 * @param msNow A current RTTimeMilliTS() value. 2096 */ 2097 static void drvHostDSoundDrainTimerWorker(PDRVHOSTDSOUND pThis, uint64_t msNow) 2098 { 2099 /* 2100 * Go thru the stream list and look at draining streams. 2101 */ 2102 uint64_t msNext = UINT64_MAX; 2103 RTCritSectEnter(&pThis->CritSect); 2104 PDSOUNDSTREAM pCur; 2105 RTListForEach(&pThis->HeadStreams, pCur, DSOUNDSTREAM, ListEntry) 2106 { 2107 if ( pCur->Cfg.enmDir == PDMAUDIODIR_OUT 2108 && pCur->Out.fDrain) 2109 { 2110 uint64_t const msCurDeadline = pCur->Out.msDrainDeadline; 2111 if (msCurDeadline > 0 && msCurDeadline < msNext) 2112 { 2113 if (msCurDeadline > msNow) 2114 msNext = pCur->Out.msDrainDeadline; 2115 else 2116 { 2117 LogRel2(("DSound: Stopping draining of '%s' {%s} ...\n", 2118 pCur->Cfg.szName, drvHostDSoundStreamStatusString(pCur))); 2119 if (pCur->Out.pDSB) 2120 { 2121 HRESULT hrc = IDirectSoundBuffer8_Stop(pCur->Out.pDSB); 2122 if (FAILED(hrc)) 2123 LogRelMax(64, ("DSound: Failed to stop draining stream '%s': %Rhrc\n", pCur->Cfg.szName, hrc)); 2124 } 2125 pCur->Out.fDrain = false; 2126 } 2127 } 2128 } 2129 } 2130 2131 /* 2132 * Re-arm the timer if necessary. 2133 */ 2134 if (msNext != UINT64_MAX) 2135 PDMDrvHlpTimerSetMillies(pThis->pDrvIns, pThis->hDrainTimer, msNext - msNow); 2136 RTCritSectLeave(&pThis->CritSect); 2137 } 2138 2139 2140 /** 2141 * @callback_method_impl{FNTMTIMERDRV, 2142 * This is a hack to ensure that draining streams stop playing.} 2143 */ 2144 static DECLCALLBACK(void) drvHostDSoundDrainStopHackTimer(PPDMDRVINS pDrvIns, TMTIMERHANDLE hTimer, void *pvUser) 2145 { 2146 PDRVHOSTDSOUND pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTDSOUND); 2147 RT_NOREF(hTimer, pvUser); 2148 drvHostDSoundDrainTimerWorker(pThis, RTTimeMilliTS()); 2149 } 2150 2151 2152 /** 2071 2153 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamDrain} 2072 2154 */ … … 2092 2174 hrc = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, 0); 2093 2175 if (SUCCEEDED(hrc)) 2094 pStreamDS->Out.fDrain = true; 2176 { 2177 uint64_t const msNow = RTTimeMilliTS(); 2178 pStreamDS->Out.msDrainDeadline = PDMAudioPropsBytesToMilli(&pStreamDS->Cfg.Props, pStreamDS->cbBufSize) + msNow; 2179 pStreamDS->Out.fDrain = true; 2180 drvHostDSoundDrainTimerWorker(pThis, msNow); 2181 } 2095 2182 else 2096 2183 LogRelMax(64, ("DSound: Failed to restart '%s' in drain mode: %Rhrc\n", pStreamDS->Cfg.szName, hrc)); … … 2115 2202 return rc; 2116 2203 } 2204 2117 2205 2118 2206 /** … … 2665 2753 * Init basic data members and interfaces. 2666 2754 */ 2755 RTListInit(&pThis->HeadStreams); 2667 2756 pThis->pDrvIns = pDrvIns; 2757 pThis->hDrainTimer = NIL_TMTIMERHANDLE; 2668 2758 /* IBase */ 2669 2759 pDrvIns->IBase.pfnQueryInterface = drvHostDSoundQueryInterface; … … 2754 2844 LogRel2(("DSound: Notification client is disabled (ver %#RX64)\n", RTSystemGetNtVersion())); 2755 2845 #endif 2846 2847 /* 2848 * Create a timer that helps making sure draining streams actually stop playing. 2849 * (Seem dsound doesn't stop by itself in many cases.) 2850 */ 2851 int rc = PDMDrvHlpTMTimerCreate(pDrvIns, TMCLOCK_REAL, drvHostDSoundDrainStopHackTimer, NULL /*pvUser*/, 0 /*fFlags*/, 2852 "DSound drain", &pThis->hDrainTimer); 2853 AssertRCReturn(rc, rc); 2756 2854 2757 2855 /*
Note:
See TracChangeset
for help on using the changeset viewer.

