- Timestamp:
- May 21, 2021 1:00:39 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostAudioCoreAudio.cpp
r89220 r89224 130 130 * 131 131 * For input buffer we'll be using offRead to track how much we've read. 132 * 133 * The queued/not-queued state is stored in the first bit of 134 * AudioQueueBuffer::mUserData. While bits 8 and up holds the index into 135 * COREAUDIOSTREAM::paBuffers. 132 136 */ 133 137 typedef struct COREAUDIOBUF … … 135 139 /** The buffer. */ 136 140 AudioQueueBufferRef pBuf; 137 /** Set if the buffer is queued. */138 bool volatile fQueued;139 141 /** The buffer read offset (input only). */ 140 142 uint32_t offRead; … … 1347 1349 1348 1350 /** 1351 * Marks the given buffer as queued or not-queued. 1352 * 1353 * @returns Old queued value. 1354 * @param pAudioBuffer The buffer. 1355 * @param fQueued The new queued state. 1356 */ 1357 DECLINLINE(bool) drvHostAudioCaSetBufferQueued(AudioQueueBufferRef pAudioBuffer, bool fQueued) 1358 { 1359 if (fQueued) 1360 return ASMAtomicBitTestAndSet(&pAudioBuffer->mUserData, 0); 1361 return ASMAtomicBitTestAndClear(&pAudioBuffer->mUserData, 0); 1362 } 1363 1364 1365 /** 1366 * Gets the queued state of the buffer. 1367 * @returns true if queued, false if not. 1368 * @param pAudioBuffer The buffer. 1369 */ 1370 DECLINLINE(bool) drvHostAudioCaIsBufferQueued(AudioQueueBufferRef pAudioBuffer) 1371 { 1372 return ((uintptr_t)pAudioBuffer->mUserData & 1) == 1; 1373 } 1374 1375 1376 /** 1349 1377 * Output audio queue buffer callback. 1350 1378 * … … 1361 1389 static void drvHostAudioCaOutputQueueBufferCallback(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef pAudioBuffer) 1362 1390 { 1391 #if defined(VBOX_STRICT) || defined(LOG_ENABLED) 1363 1392 PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser; 1364 1393 AssertPtr(pStreamCA); 1365 1394 Assert(pStreamCA->hAudioQueue == hAudioQueue); 1366 RT_NOREF(hAudioQueue); 1367 1368 uintptr_t idxBuf = (uintptr_t)pAudioBuffer->mUserData; 1395 1396 uintptr_t idxBuf = (uintptr_t)pAudioBuffer->mUserData >> 8; 1369 1397 Log4Func(("Got back buffer #%zu (%p)\n", idxBuf, pAudioBuffer)); 1370 1398 AssertReturnVoid( idxBuf < pStreamCA->cBuffers 1371 1399 && pStreamCA->paBuffers[idxBuf].pBuf == pAudioBuffer); 1400 #endif 1372 1401 1373 1402 pAudioBuffer->mAudioDataByteSize = 0; 1374 bool fWasQueued = ASMAtomicXchgBool(&pStreamCA->paBuffers[idxBuf].fQueued, false); 1403 bool fWasQueued = drvHostAudioCaSetBufferQueued(pAudioBuffer, false /*fQueued*/); 1404 Assert(!drvHostAudioCaIsBufferQueued(pAudioBuffer)); 1375 1405 Assert(fWasQueued); RT_NOREF(fWasQueued); 1406 1407 RT_NOREF(pvUser, hAudioQueue); 1376 1408 } 1377 1409 … … 1395 1427 UInt32 cPacketDesc, const AudioStreamPacketDescription *paPacketDesc) 1396 1428 { 1429 #if defined(VBOX_STRICT) || defined(LOG_ENABLED) 1397 1430 PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser; 1398 1431 AssertPtr(pStreamCA); 1399 1432 Assert(pStreamCA->hAudioQueue == hAudioQueue); 1400 RT_NOREF(hAudioQueue, pAudioTS, cPacketDesc, paPacketDesc); 1401 1402 uintptr_t idxBuf = (uintptr_t)pAudioBuffer->mUserData; 1433 1434 uintptr_t idxBuf = (uintptr_t)pAudioBuffer->mUserData >> 8; 1403 1435 Log4Func(("Got back buffer #%zu (%p) with %#x bytes\n", idxBuf, pAudioBuffer, pAudioBuffer->mAudioDataByteSize)); 1404 1436 AssertReturnVoid( idxBuf < pStreamCA->cBuffers 1405 1437 && pStreamCA->paBuffers[idxBuf].pBuf == pAudioBuffer); 1406 1407 bool fWasQueued = ASMAtomicXchgBool(&pStreamCA->paBuffers[idxBuf].fQueued, false); 1438 #endif 1439 1440 bool fWasQueued = drvHostAudioCaSetBufferQueued(pAudioBuffer, false /*fQueued*/); 1441 Assert(!drvHostAudioCaIsBufferQueued(pAudioBuffer)); 1408 1442 Assert(fWasQueued); RT_NOREF(fWasQueued); 1443 1444 RT_NOREF(pvUser, hAudioQueue, pAudioTS, cPacketDesc, paPacketDesc); 1409 1445 } 1410 1446 … … 1568 1604 if (RT_LIKELY(orc == noErr)) 1569 1605 { 1570 pBuf->mUserData = (void *)(uintptr_t) iBuf;1606 pBuf->mUserData = (void *)(uintptr_t)(iBuf << 8); /* bit zero is the queued-indicator. */ 1571 1607 pStreamCA->paBuffers[iBuf].pBuf = pBuf; 1572 1608 cFramesBufferSize += PDMAudioPropsBytesToFrames(&pStreamCA->Cfg.Props, … … 1778 1814 Assert(orc == noErr); 1779 1815 for (uint32_t iBuf = 0; iBuf < pStreamCA->cBuffers; iBuf++) 1780 Assert(! pStreamCA->paBuffers[iBuf].fQueued);1816 Assert(!drvHostAudioCaIsBufferQueued(pStreamCA->paBuffers[iBuf].pBuf)); 1781 1817 1782 1818 pStreamCA->offInternal = 0; … … 1800 1836 RT_BZERO(pBuf->mAudioData, pBuf->mAudioDataBytesCapacity); 1801 1837 pBuf->mAudioDataByteSize = 0; 1802 ASMAtomicWriteBool(&pStreamCA->paBuffers[iBuf].fQueued, true);1838 drvHostAudioCaSetBufferQueued(pBuf, true /*fQueued*/); 1803 1839 1804 1840 orc = AudioQueueEnqueueBuffer(pStreamCA->hAudioQueue, pBuf, 0 /*inNumPacketDescs*/, NULL /*inPacketDescs*/); 1805 1841 AssertLogRelMsgBreakStmt(orc == noErr, ("CoreAudio: AudioQueueEnqueueBuffer(#%u) -> %#x (%d) - stream '%s'\n", 1806 1842 iBuf, orc, orc, pStreamCA->Cfg.szName), 1807 pStreamCA->paBuffers[iBuf].fQueued = false);1843 drvHostAudioCaSetBufferQueued(pBuf, false /*fQueued*/)); 1808 1844 } 1809 1845 … … 2055 2091 uint32_t const idxStart = pStreamCA->idxBuffer; 2056 2092 uint32_t idxBuffer = idxStart; 2093 AudioQueueBufferRef pBuf; 2057 2094 2058 2095 if ( cBuffers > 0 2059 && ! paBuffers[idxBuffer].fQueued)2096 && !drvHostAudioCaIsBufferQueued(pBuf = paBuffers[idxBuffer].pBuf)) 2060 2097 { 2061 2098 do 2062 2099 { 2063 AudioQueueBufferRef const pBuf = paBuffers[idxBuffer].pBuf; 2064 uint32_t const cbTotal = pBuf->mAudioDataBytesCapacity; 2065 uint32_t cbFill = pBuf->mAudioDataByteSize; 2100 uint32_t const cbTotal = pBuf->mAudioDataBytesCapacity; 2101 uint32_t cbFill = pBuf->mAudioDataByteSize; 2066 2102 AssertStmt(cbFill <= cbTotal, cbFill = cbTotal); 2067 uint32_t 2103 uint32_t off = paBuffers[idxBuffer].offRead; 2068 2104 AssertStmt(off < cbFill, off = cbFill); 2069 2105 … … 2076 2112 else 2077 2113 idxBuffer = 0; 2078 } while (idxBuffer != idxStart && ! paBuffers[idxBuffer].fQueued);2114 } while (idxBuffer != idxStart && !drvHostAudioCaIsBufferQueued(pBuf = paBuffers[idxBuffer].pBuf)); 2079 2115 } 2080 2116 … … 2104 2140 uint32_t const idxStart = pStreamCA->idxBuffer; 2105 2141 uint32_t idxBuffer = idxStart; 2142 AudioQueueBufferRef pBuf; 2106 2143 2107 2144 if ( cBuffers > 0 2108 && ! paBuffers[idxBuffer].fQueued)2145 && !drvHostAudioCaIsBufferQueued(pBuf = paBuffers[idxBuffer].pBuf)) 2109 2146 { 2110 2147 do 2111 2148 { 2112 AudioQueueBufferRef const pBuf = paBuffers[idxBuffer].pBuf; 2113 uint32_t const cbTotal = pBuf->mAudioDataBytesCapacity; 2114 uint32_t cbUsed = pBuf->mAudioDataByteSize; 2149 uint32_t const cbTotal = pBuf->mAudioDataBytesCapacity; 2150 uint32_t cbUsed = pBuf->mAudioDataByteSize; 2115 2151 AssertStmt(cbUsed <= cbTotal, paBuffers[idxBuffer].pBuf->mAudioDataByteSize = cbUsed = cbTotal); 2116 2152 … … 2123 2159 else 2124 2160 idxBuffer = 0; 2125 } while (idxBuffer != idxStart && ! paBuffers[idxBuffer].fQueued);2161 } while (idxBuffer != idxStart && !drvHostAudioCaIsBufferQueued(pBuf = paBuffers[idxBuffer].pBuf)); 2126 2162 } 2127 2163 … … 2156 2192 uintptr_t idxBuffer = pStreamCA->cBuffers; 2157 2193 while (idxBuffer-- > 0) 2158 if (! paBuffers[idxBuffer].fQueued)2194 if (!drvHostAudioCaIsBufferQueued(paBuffers[idxBuffer].pBuf)) 2159 2195 { /* likely */ } 2160 2196 else … … 2163 2199 uint32_t cQueued = 1; 2164 2200 while (idxBuffer-- > 0) 2165 cQueued += paBuffers[idxBuffer].fQueued;2201 cQueued += drvHostAudioCaIsBufferQueued(paBuffers[idxBuffer].pBuf); 2166 2202 LogFunc(("Still done draining '%s': %u queued buffers\n", pStreamCA->Cfg.szName, cQueued)); 2167 2203 #endif … … 2229 2265 * Check out how much we can put into the current buffer. 2230 2266 */ 2231 if (!paBuffers[idxBuffer].fQueued) 2267 AudioQueueBufferRef const pBuf = paBuffers[idxBuffer].pBuf; 2268 if (!drvHostAudioCaIsBufferQueued(pBuf)) 2232 2269 { /* likely */ } 2233 2270 else … … 2238 2275 } 2239 2276 2240 AudioQueueBufferRef const pBuf = paBuffers[idxBuffer].pBuf;2241 2277 AssertPtrBreakStmt(pBuf, rc = VERR_INTERNAL_ERROR_2); 2242 uint32_t const 2243 uint32_t 2278 uint32_t const cbTotal = pBuf->mAudioDataBytesCapacity; 2279 uint32_t cbUsed = pBuf->mAudioDataByteSize; 2244 2280 AssertStmt(cbUsed < cbTotal, cbUsed = cbTotal); 2245 uint32_t const 2281 uint32_t const cbAvail = cbTotal - cbUsed; 2246 2282 2247 2283 /* … … 2267 2303 cbWritten += cbAvail; 2268 2304 pStreamCA->offInternal += cbAvail; 2269 ASMAtomicWriteBool(&paBuffers[idxBuffer].fQueued, true);2305 drvHostAudioCaSetBufferQueued(pBuf, true /*fQueued*/); 2270 2306 2271 2307 OSStatus orc = AudioQueueEnqueueBuffer(pStreamCA->hAudioQueue, pBuf, 0 /*inNumPacketDesc*/, NULL /*inPacketDescs*/); … … 2276 2312 LogRelMax(256, ("CoreAudio: AudioQueueEnqueueBuffer('%s', #%u) failed: %#x (%d)\n", 2277 2313 pStreamCA->Cfg.szName, idxBuffer, orc, orc)); 2278 ASMAtomicWriteBool(&paBuffers[idxBuffer].fQueued, false);2314 drvHostAudioCaSetBufferQueued(pBuf, false /*fQueued*/); 2279 2315 pBuf->mAudioDataByteSize -= PDMAudioPropsFramesToBytes(&pStreamCA->Cfg.Props, 1); /* avoid assertions above */ 2280 2316 rc = VERR_AUDIO_STREAM_NOT_READY; … … 2401 2437 * Check out how much we can read from the current buffer (if anything at all). 2402 2438 */ 2403 if (!paBuffers[idxBuffer].fQueued) 2439 AudioQueueBufferRef const pBuf = paBuffers[idxBuffer].pBuf; 2440 if (!drvHostAudioCaIsBufferQueued(pBuf)) 2404 2441 { /* likely */ } 2405 2442 else … … 2410 2447 } 2411 2448 2412 AudioQueueBufferRef const pBuf = paBuffers[idxBuffer].pBuf;2413 2449 AssertPtrBreakStmt(pBuf, rc = VERR_INTERNAL_ERROR_2); 2414 uint32_t const 2415 uint32_t 2450 uint32_t const cbTotal = pBuf->mAudioDataBytesCapacity; 2451 uint32_t cbValid = pBuf->mAudioDataByteSize; 2416 2452 AssertStmt(cbValid < cbTotal, cbValid = cbTotal); 2417 uint32_t 2418 uint32_t const 2453 uint32_t offRead = paBuffers[idxBuffer].offRead; 2454 uint32_t const cbLeft = cbValid - offRead; 2419 2455 2420 2456 /* … … 2441 2477 paBuffers[idxBuffer].offRead = 0; 2442 2478 pBuf->mAudioDataByteSize = 0; 2443 ASMAtomicWriteBool(&paBuffers[idxBuffer].fQueued, true);2479 drvHostAudioCaSetBufferQueued(pBuf, true /*fQueued*/); 2444 2480 2445 2481 OSStatus orc = AudioQueueEnqueueBuffer(pStreamCA->hAudioQueue, pBuf, 0 /*inNumPacketDesc*/, NULL /*inPacketDescs*/); … … 2450 2486 LogRelMax(256, ("CoreAudio: AudioQueueEnqueueBuffer('%s', #%u) failed: %#x (%d)\n", 2451 2487 pStreamCA->Cfg.szName, idxBuffer, orc, orc)); 2452 ASMAtomicWriteBool(&paBuffers[idxBuffer].fQueued, false);2488 drvHostAudioCaSetBufferQueued(pBuf, false /*fQueued*/); 2453 2489 rc = VERR_AUDIO_STREAM_NOT_READY; 2454 2490 break;
Note:
See TracChangeset
for help on using the changeset viewer.