Changeset 103134 in vbox
- Timestamp:
- Jan 31, 2024 9:21:06 AM (10 months ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r99415 r103134 2012 2012 RT_NOREF(idStream); 2013 2013 2014 int rc = RTCritSectEnter(&pSink->CritSect); 2015 AssertRCReturn(rc, rc); 2016 2014 2017 /* 2015 2018 * Figure how much that we can push down. … … 2023 2026 Log3Func(("idStream=%u: cbSinkWritable=%#RX32 cbCircBufReadable=%#RX32 -> cbToTransfer=%#RX32 @%#RX64\n", 2024 2027 idStream, cbSinkWritable, cbCircBufReadable, cbToTransfer, offStream)); 2025 AssertMsg(!(pSink->fStatus & AUDMIXSINK_STS_DRAINING) || cbCircBufReadable == pSink->cbDmaLeftToDrain, 2028 /* Note: There now can be more data in the DMA buffer than initially announced. See @bugref{10354}. */ 2029 AssertMsg(!(pSink->fStatus & AUDMIXSINK_STS_DRAINING) || cbCircBufReadable >= pSink->cbDmaLeftToDrain, 2026 2030 ("cbCircBufReadable=%#x cbDmaLeftToDrain=%#x\n", cbCircBufReadable, pSink->cbDmaLeftToDrain)); 2027 2031 … … 2081 2085 Assert(cbToTransfer2 == 0); 2082 2086 2087 Log3Func(("idStream=%u: cbCircBufUsed=%RX32 left\n", idStream, (uint32_t)RTCircBufUsed(pCircBuf))); 2088 2089 RTCritSectLeave(&pSink->CritSect); 2090 2091 LogFlowFuncLeave(); 2083 2092 return offStream; 2084 2093 } -
trunk/src/VBox/Devices/Audio/DevHdaStream.cpp
r98456 r103134 798 798 */ 799 799 800 /* (Re-)Allocate the stream's internal DMA buffer,801 * based on the timing *and* PCM properties we just got above. */802 if (pStreamR3->State.pCircBuf)803 {804 RTCircBufDestroy(pStreamR3->State.pCircBuf);805 pStreamR3->State.pCircBuf = NULL;806 pStreamR3->State.StatDmaBufSize = 0;807 pStreamR3->State.StatDmaBufUsed = 0;808 }809 pStreamShared->State.offWrite = 0;810 pStreamShared->State.offRead = 0;811 812 800 /* 813 801 * The default internal ring buffer size must be: … … 858 846 if (RT_SUCCESS(rc)) 859 847 { 860 rc = RTCircBufCreate(&pStreamR3->State.pCircBuf, cbCircBuf); 861 if (RT_SUCCESS(rc)) 848 /** 849 * Note: Only re-create the DMA buffer if the size actually has changed. 850 * 851 * Otherwise do *not* reset the stream's circular buffer here, as the audio mixer still relies on 852 * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. 853 * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ 854 if (pStreamR3->State.StatDmaBufSize != cbCircBuf) 862 855 { 863 pStreamR3->State.StatDmaBufSize = cbCircBuf; 864 865 /* 866 * Forward the timer frequency hint to TM as well for better accuracy on 867 * systems w/o preemption timers (also good for 'info timers'). 868 */ 869 PDMDevHlpTimerSetFrequencyHint(pDevIns, pStreamShared->hTimer, uTransferHz); 856 /* (Re-)Allocate the stream's internal DMA buffer, 857 * based on the timing *and* PCM properties we just got above. */ 858 if (pStreamR3->State.pCircBuf) 859 { 860 RTCircBufDestroy(pStreamR3->State.pCircBuf); 861 pStreamR3->State.pCircBuf = NULL; 862 pStreamR3->State.StatDmaBufSize = 0; 863 pStreamR3->State.StatDmaBufUsed = 0; 864 } 865 pStreamShared->State.offWrite = 0; 866 pStreamShared->State.offRead = 0; 867 868 rc = RTCircBufCreate(&pStreamR3->State.pCircBuf, cbCircBuf); 869 if (RT_SUCCESS(rc)) 870 { 871 pStreamR3->State.StatDmaBufSize = cbCircBuf; 872 873 /* 874 * Forward the timer frequency hint to TM as well for better accuracy on 875 * systems w/o preemption timers (also good for 'info timers'). 876 */ 877 PDMDevHlpTimerSetFrequencyHint(pDevIns, pStreamShared->hTimer, uTransferHz); 878 } 870 879 } 871 880 } … … 1004 1013 pStreamShared->State.fInputPreBuffered = false; 1005 1014 1006 if (pStreamR3->State.pCircBuf) 1007 RTCircBufReset(pStreamR3->State.pCircBuf); 1008 pStreamShared->State.offWrite = 0; 1009 pStreamShared->State.offRead = 0; 1015 /* Note: Do *not* reset the stream's circular buffer here, as the audio mixer still relies on 1016 * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. 1017 * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ 1010 1018 1011 1019 /* Report that we're done resetting this stream. */ … … 1042 1050 if (pSink) 1043 1051 { 1052 AudioMixerSinkLock(pSink); 1053 1044 1054 if (fEnable) 1045 1055 { … … 1061 1071 rc = AudioMixerSinkDrainAndStop(pSink, 1062 1072 pStreamR3->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStreamR3->State.pCircBuf) : 0); 1073 1074 AudioMixerSinkUnlock(pSink); 1063 1075 } 1064 1076 if ( RT_SUCCESS(rc) -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r99739 r103134 1731 1731 LogFunc(("[SD%RU8]\n", pStream->u8SD)); 1732 1732 1733 if (pStreamCC->State.pCircBuf) 1734 RTCircBufReset(pStreamCC->State.pCircBuf); 1733 /* Note: Do *not* reset the stream's circular buffer here, as the audio mixer still relies on 1734 * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. 1735 * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ 1735 1736 1736 1737 pStream->Regs.bdbar = 0; … … 2199 2200 if ( pStreamCC->State.pCircBuf 2200 2201 && RTCircBufSize(pStreamCC->State.pCircBuf) == cbCircBuf) 2201 RTCircBufReset(pStreamCC->State.pCircBuf); 2202 { 2203 /* Note: Do *not* reset the stream's circular buffer here, as the audio mixer still relies on 2204 * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. 2205 * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ 2206 } 2202 2207 else 2203 2208 { -
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r98456 r103134 111 111 typedef struct SB16STREAMSTATE 112 112 { 113 /** Critical section for this stream. */ 114 RTCRITSECT CritSect; 113 115 /** Flag indicating whether this stream is in enabled state or not. */ 114 116 bool fEnabled; … … 336 338 static int sb16StreamOpen(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream); 337 339 static void sb16StreamClose(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream); 340 DECLINLINE(void) sb16StreamLock(PSB16STREAM pStream); 341 DECLINLINE(void) sb16StreamUnlock(PSB16STREAM pStream); 338 342 DECLINLINE(PAUDMIXSINK) sb16StreamIndexToSink(PSB16STATE pThis, uint8_t uIdx); 339 343 static void sb16StreamTransferScheduleNext(PSB16STATE pThis, PSB16STREAM pStream, uint32_t cSamples); … … 1924 1928 *********************************************************************************************************************************/ 1925 1929 1930 /** 1931 * Reads DMA output data into the internal DMA buffer. 1932 * 1933 * @returns VBox status code. 1934 * @param pStream The SB16 stream to read DMA output data from. 1935 * @param uDmaChan DMA channel to read from. 1936 * @param offDma DMA offset (in bytes) to start reading from. 1937 * @param cbDma DMA area size in bytes. 1938 * @param cbToRead How much bytes to read in total. 1939 * @param pcbRead Where to return the DMA bytes read. 1940 * 1941 * @thread µEMT 1942 */ 1926 1943 static int sb16StreamDoDmaOutput(PSB16STATE pThis, PSB16STREAM pStream, int uDmaChan, uint32_t offDma, uint32_t cbDma, 1927 1944 uint32_t cbToRead, uint32_t *pcbRead) … … 1930 1947 //Assert(cbToRead <= cbFree); /** @todo Add statistics for overflows. */ 1931 1948 cbToRead = RT_MIN(cbToRead, cbFree); 1949 1950 sb16StreamLock(pStream); 1932 1951 1933 1952 uint32_t cbReadTotal = 0; … … 1949 1968 break; 1950 1969 *pcbRead = 0; 1970 1971 sb16StreamUnlock(pStream); 1951 1972 return rc; 1952 1973 } … … 1957 1978 AudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMA, pv, cbRead); 1958 1979 1980 Log3Func(("Writing %#RX32 bytes to DMA buffer\n", cbRead)); 1981 1959 1982 RTCircBufReleaseWriteBlock(pStream->State.pCircBuf, cbRead); 1983 1984 Log3Func(("Now %#RX32 bytes in buffer\n", RTCircBufUsed(pStream->State.pCircBuf))); 1960 1985 1961 1986 Assert(cbToRead >= cbRead); … … 1971 1996 pStream->State.StatDmaBufUsed = (uint32_t)RTCircBufUsed(pStream->State.pCircBuf); 1972 1997 1998 Log3Func(("[SD%RU8] cbCircBufUsed=%#RX64\n", pStream->uIdx, RTCircBufUsed(pStream->State.pCircBuf))); 1999 2000 sb16StreamUnlock(pStream); 1973 2001 return VINF_SUCCESS; 1974 2002 } … … 2012 2040 else 2013 2041 { 2014 rc = AudioMixerSinkDrainAndStop(pSink, pStream->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStream->State.pCircBuf) : 0); 2042 /* We need to lock the stream here in order to synchronize the amount of bytes we have to drain 2043 * here with the mixer's async I/O thread. See @bugref{10354}. */ 2044 sb16StreamLock(pStream); 2045 2046 uint32_t const cbToDrain = pStream->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStream->State.pCircBuf) : 0; 2047 Log3Func(("cbToDrain=%#RX32\n", cbToDrain)); 2048 2049 sb16StreamUnlock(pStream); 2050 2051 rc = AudioMixerSinkDrainAndStop(pSink, cbToDrain); 2015 2052 AssertRCReturn(rc, rc); 2053 2054 2016 2055 } 2017 2056 … … 2068 2107 { 2069 2108 LogFlowFuncEnter(); 2109 2110 int rc = RTCritSectInit(&pStream->State.CritSect); 2111 AssertRCReturn(rc, rc); 2070 2112 2071 2113 pStream->Dbg.Runtime.fEnabled = pThis->Dbg.fEnabled; … … 2112 2154 } 2113 2155 2156 int rc2 = RTCritSectDelete(&pStream->State.CritSect); 2157 AssertRC(rc2); 2158 2114 2159 if (pStream->State.pCircBuf) 2115 2160 { … … 2178 2223 2179 2224 /** 2225 * Locks a SB16 stream for serialized access. 2226 * 2227 * @param pStream The SB16 stream to lock. 2228 */ 2229 DECLINLINE(void) sb16StreamLock(PSB16STREAM pStream) 2230 { 2231 int rc2 = RTCritSectEnter(&pStream->State.CritSect); 2232 AssertRC(rc2); 2233 } 2234 2235 /** 2236 * Unlocks a formerly locked SB16 stream. 2237 * 2238 * @param pStream The SB16 stream to unlock. 2239 */ 2240 DECLINLINE(void) sb16StreamUnlock(PSB16STREAM pStream) 2241 { 2242 int rc2 = RTCritSectLeave(&pStream->State.CritSect); 2243 AssertRC(rc2); 2244 } 2245 2246 /** 2180 2247 * Opens a SB16 stream with its current mixer settings. 2181 2248 * … … 2210 2277 PDMAudioPropsSampleBits(&pStream->Cfg.Props))); 2211 2278 2212 /* (Re-)create the stream's internal ring buffer. */2213 if (pStream->State.pCircBuf)2214 {2215 RTCircBufDestroy(pStream->State.pCircBuf);2216 pStream->State.pCircBuf = NULL;2217 }2218 2219 2279 /** @todo r=bird: two DMA periods is probably too little. */ 2220 2280 const uint32_t cbCircBuf = PDMAudioPropsMilliToBytes(&pStream->Cfg.Props, 2221 2281 (RT_MS_1SEC / pStream->uTimerHz) * 2 /* Use double buffering here */); 2222 2223 int rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBuf); 2224 AssertRCReturn(rc, rc); 2225 pStream->State.StatDmaBufSize = (uint32_t)RTCircBufSize(pStream->State.pCircBuf); 2226 2227 /* Set scheduling hint. */ 2228 pStream->Cfg.Device.cMsSchedulingHint = RT_MS_1SEC / RT_MIN(pStream->uTimerHz, 1); 2229 2230 PAUDMIXSINK pMixerSink = sb16StreamIndexToSink(pThis, pStream->uIdx); 2231 AssertPtrReturn(pMixerSink, VERR_INVALID_POINTER); 2232 2233 sb16RemoveDrvStreams(pDevIns, pThis, 2234 sb16StreamIndexToSink(pThis, pStream->uIdx), pStream->Cfg.enmDir, pStream->Cfg.enmPath); 2235 2236 rc = sb16AddDrvStreams(pDevIns, pThis, pMixerSink, &pStream->Cfg); 2237 if (RT_SUCCESS(rc)) 2238 { 2239 if (RT_LIKELY(!pStream->Dbg.Runtime.fEnabled)) 2240 { /* likely */ } 2241 else 2282 int rc = VINF_SUCCESS; 2283 2284 /** 2285 * Note: Only re-create the DMA buffer if the size actually has changed. 2286 * 2287 * Otherwise do *not* reset the stream's circular buffer here, as the audio mixer still relies on 2288 * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. 2289 * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ 2290 if (pStream->State.StatDmaBufSize != cbCircBuf) 2291 { 2292 Log3Func(("Re-creating ring buffer (%#RX32 -> %#RX32)\n", pStream->State.StatDmaBufSize, cbCircBuf)); 2293 2294 /* (Re-)create the stream's internal ring buffer. */ 2295 if (pStream->State.pCircBuf) 2242 2296 { 2243 /* Make sure to close + delete a former debug file, as the PCM format has changed (e.g. U8 -> S16). */ 2244 if (AudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMA)) 2297 RTCircBufDestroy(pStream->State.pCircBuf); 2298 pStream->State.pCircBuf = NULL; 2299 } 2300 2301 rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBuf); 2302 AssertRCReturn(rc, rc); 2303 pStream->State.StatDmaBufSize = (uint32_t)RTCircBufSize(pStream->State.pCircBuf); 2304 2305 /* Set scheduling hint. */ 2306 pStream->Cfg.Device.cMsSchedulingHint = RT_MS_1SEC / RT_MIN(pStream->uTimerHz, 1); 2307 2308 PAUDMIXSINK pMixerSink = sb16StreamIndexToSink(pThis, pStream->uIdx); 2309 AssertPtrReturn(pMixerSink, VERR_INVALID_POINTER); 2310 2311 sb16RemoveDrvStreams(pDevIns, pThis, 2312 sb16StreamIndexToSink(pThis, pStream->uIdx), pStream->Cfg.enmDir, pStream->Cfg.enmPath); 2313 2314 rc = sb16AddDrvStreams(pDevIns, pThis, pMixerSink, &pStream->Cfg); 2315 if (RT_SUCCESS(rc)) 2316 { 2317 if (RT_LIKELY(!pStream->Dbg.Runtime.fEnabled)) 2318 { /* likely */ } 2319 else 2245 2320 { 2246 AudioHlpFileClose(pStream->Dbg.Runtime.pFileDMA); 2247 AudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMA); 2321 /* Make sure to close + delete a former debug file, as the PCM format has changed (e.g. U8 -> S16). */ 2322 if (AudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMA)) 2323 { 2324 AudioHlpFileClose(pStream->Dbg.Runtime.pFileDMA); 2325 AudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMA); 2326 } 2327 2328 int rc2 = AudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMA, AUDIOHLPFILE_DEFAULT_OPEN_FLAGS, 2329 &pStream->Cfg.Props); 2330 AssertRC(rc2); 2248 2331 } 2249 2250 int rc2 = AudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMA, AUDIOHLPFILE_DEFAULT_OPEN_FLAGS,2251 &pStream->Cfg.Props);2252 AssertRC(rc2);2253 2332 } 2254 2333 } … … 2303 2382 * @param pStream The SB16 stream. 2304 2383 * @param pSink The mixer sink to push to. 2384 * 2385 * @thread MixAIO-n 2386 * 2387 * @note Takes the stream's lock. 2305 2388 */ 2306 2389 static void sb16StreamPushToMixer(PSB16STREAM pStream, PAUDMIXSINK pSink) 2307 2390 { 2391 sb16StreamLock(pStream); 2392 2308 2393 #ifdef LOG_ENABLED 2309 2394 uint64_t const offReadOld = pStream->State.offRead; 2395 Log3Func(("[SD%RU8] cbCircBufUsed=%#RX64\n", pStream->uIdx, RTCircBufUsed(pStream->State.pCircBuf))); 2310 2396 #endif 2311 2397 pStream->State.offRead = AudioMixerSinkTransferFromCircBuf(pSink, … … 2316 2402 ? pStream->Dbg.Runtime.pFileStream :*/ NULL); 2317 2403 2318 Log3Func(("[SD%RU8] transferred=%#RX64 bytes -> @%#RX64 \n", pStream->uIdx,2319 pStream->State.offRead - offReadOld, pStream->State.offRead ));2404 Log3Func(("[SD%RU8] transferred=%#RX64 bytes -> @%#RX64 (cbCircBufUsed=%#RX64)\n", pStream->uIdx, 2405 pStream->State.offRead - offReadOld, pStream->State.offRead, RTCircBufUsed(pStream->State.pCircBuf))); 2320 2406 2321 2407 /* Update buffer stats. */ 2322 2408 pStream->State.StatDmaBufUsed = (uint32_t)RTCircBufUsed(pStream->State.pCircBuf); 2409 2410 sb16StreamUnlock(pStream); 2323 2411 } 2324 2412 … … 2328 2416 * 2329 2417 * For output streams this moves data from the internal DMA buffer (in which 2330 * ichac97R3StreamUpdateDmaput it), thru the mixer and to the various backend2418 * sb16StreamDoDmaOutput put it), thru the mixer and to the various backend 2331 2419 * audio devices. 2420 * 2421 * @thread MixAIO-n 2332 2422 */ 2333 2423 static DECLCALLBACK(void) sb16StreamUpdateAsyncIoJob(PPDMDEVINS pDevIns, PAUDMIXSINK pSink, void *pvUser)
Note:
See TracChangeset
for help on using the changeset viewer.