VirtualBox

Changeset 89224 in vbox for trunk


Ignore:
Timestamp:
May 21, 2021 1:00:39 PM (4 years ago)
Author:
vboxsync
Message:

DrvHostAudioCoreAudio: Moved COREAUDIOBUF::fQueued to mUserData of the buffer to make sure we can't be harmed should a buffer callback arrive after AudioQueueDispose and we've freed paBuffers. Documentation says this shouldn't happen, but better play safe. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvHostAudioCoreAudio.cpp

    r89220 r89224  
    130130 *
    131131 * 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.
    132136 */
    133137typedef struct COREAUDIOBUF
     
    135139    /** The buffer. */
    136140    AudioQueueBufferRef     pBuf;
    137     /** Set if the buffer is queued. */
    138     bool volatile           fQueued;
    139141    /** The buffer read offset (input only). */
    140142    uint32_t                offRead;
     
    13471349
    13481350/**
     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 */
     1357DECLINLINE(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 */
     1370DECLINLINE(bool) drvHostAudioCaIsBufferQueued(AudioQueueBufferRef pAudioBuffer)
     1371{
     1372    return ((uintptr_t)pAudioBuffer->mUserData & 1) == 1;
     1373}
     1374
     1375
     1376/**
    13491377 * Output audio queue buffer callback.
    13501378 *
     
    13611389static void drvHostAudioCaOutputQueueBufferCallback(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef pAudioBuffer)
    13621390{
     1391#if defined(VBOX_STRICT) || defined(LOG_ENABLED)
    13631392    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser;
    13641393    AssertPtr(pStreamCA);
    13651394    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;
    13691397    Log4Func(("Got back buffer #%zu (%p)\n", idxBuf, pAudioBuffer));
    13701398    AssertReturnVoid(   idxBuf < pStreamCA->cBuffers
    13711399                     && pStreamCA->paBuffers[idxBuf].pBuf == pAudioBuffer);
     1400#endif
    13721401
    13731402    pAudioBuffer->mAudioDataByteSize = 0;
    1374     bool fWasQueued = ASMAtomicXchgBool(&pStreamCA->paBuffers[idxBuf].fQueued, false);
     1403    bool fWasQueued = drvHostAudioCaSetBufferQueued(pAudioBuffer, false /*fQueued*/);
     1404    Assert(!drvHostAudioCaIsBufferQueued(pAudioBuffer));
    13751405    Assert(fWasQueued); RT_NOREF(fWasQueued);
     1406
     1407    RT_NOREF(pvUser, hAudioQueue);
    13761408}
    13771409
     
    13951427                                                   UInt32 cPacketDesc, const AudioStreamPacketDescription *paPacketDesc)
    13961428{
     1429#if defined(VBOX_STRICT) || defined(LOG_ENABLED)
    13971430    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser;
    13981431    AssertPtr(pStreamCA);
    13991432    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;
    14031435    Log4Func(("Got back buffer #%zu (%p) with %#x bytes\n", idxBuf, pAudioBuffer, pAudioBuffer->mAudioDataByteSize));
    14041436    AssertReturnVoid(   idxBuf < pStreamCA->cBuffers
    14051437                     && 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));
    14081442    Assert(fWasQueued); RT_NOREF(fWasQueued);
     1443
     1444    RT_NOREF(pvUser, hAudioQueue, pAudioTS, cPacketDesc, paPacketDesc);
    14091445}
    14101446
     
    15681604                            if (RT_LIKELY(orc == noErr))
    15691605                            {
    1570                                 pBuf->mUserData = (void *)(uintptr_t)iBuf;
     1606                                pBuf->mUserData = (void *)(uintptr_t)(iBuf << 8); /* bit zero is the queued-indicator. */
    15711607                                pStreamCA->paBuffers[iBuf].pBuf = pBuf;
    15721608                                cFramesBufferSize += PDMAudioPropsBytesToFrames(&pStreamCA->Cfg.Props,
     
    17781814    Assert(orc == noErr);
    17791815    for (uint32_t iBuf = 0; iBuf < pStreamCA->cBuffers; iBuf++)
    1780         Assert(!pStreamCA->paBuffers[iBuf].fQueued);
     1816        Assert(!drvHostAudioCaIsBufferQueued(pStreamCA->paBuffers[iBuf].pBuf));
    17811817
    17821818    pStreamCA->offInternal      = 0;
     
    18001836            RT_BZERO(pBuf->mAudioData, pBuf->mAudioDataBytesCapacity);
    18011837            pBuf->mAudioDataByteSize = 0;
    1802             ASMAtomicWriteBool(&pStreamCA->paBuffers[iBuf].fQueued, true);
     1838            drvHostAudioCaSetBufferQueued(pBuf, true /*fQueued*/);
    18031839
    18041840            orc = AudioQueueEnqueueBuffer(pStreamCA->hAudioQueue, pBuf, 0 /*inNumPacketDescs*/, NULL /*inPacketDescs*/);
    18051841            AssertLogRelMsgBreakStmt(orc == noErr, ("CoreAudio: AudioQueueEnqueueBuffer(#%u) -> %#x (%d) - stream '%s'\n",
    18061842                                                    iBuf, orc, orc, pStreamCA->Cfg.szName),
    1807                                      pStreamCA->paBuffers[iBuf].fQueued = false);
     1843                                     drvHostAudioCaSetBufferQueued(pBuf, false /*fQueued*/));
    18081844        }
    18091845
     
    20552091        uint32_t const      idxStart  = pStreamCA->idxBuffer;
    20562092        uint32_t            idxBuffer = idxStart;
     2093        AudioQueueBufferRef pBuf;
    20572094
    20582095        if (   cBuffers > 0
    2059             && !paBuffers[idxBuffer].fQueued)
     2096            && !drvHostAudioCaIsBufferQueued(pBuf = paBuffers[idxBuffer].pBuf))
    20602097        {
    20612098            do
    20622099            {
    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;
    20662102                AssertStmt(cbFill <= cbTotal, cbFill = cbTotal);
    2067                 uint32_t                  off     = paBuffers[idxBuffer].offRead;
     2103                uint32_t        off     = paBuffers[idxBuffer].offRead;
    20682104                AssertStmt(off < cbFill, off = cbFill);
    20692105
     
    20762112                else
    20772113                    idxBuffer = 0;
    2078             } while (idxBuffer != idxStart && !paBuffers[idxBuffer].fQueued);
     2114            } while (idxBuffer != idxStart && !drvHostAudioCaIsBufferQueued(pBuf = paBuffers[idxBuffer].pBuf));
    20792115        }
    20802116
     
    21042140        uint32_t const      idxStart  = pStreamCA->idxBuffer;
    21052141        uint32_t            idxBuffer = idxStart;
     2142        AudioQueueBufferRef pBuf;
    21062143
    21072144        if (   cBuffers > 0
    2108             && !paBuffers[idxBuffer].fQueued)
     2145            && !drvHostAudioCaIsBufferQueued(pBuf = paBuffers[idxBuffer].pBuf))
    21092146        {
    21102147            do
    21112148            {
    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;
    21152151                AssertStmt(cbUsed <= cbTotal, paBuffers[idxBuffer].pBuf->mAudioDataByteSize = cbUsed = cbTotal);
    21162152
     
    21232159                else
    21242160                    idxBuffer = 0;
    2125             } while (idxBuffer != idxStart && !paBuffers[idxBuffer].fQueued);
     2161            } while (idxBuffer != idxStart && !drvHostAudioCaIsBufferQueued(pBuf = paBuffers[idxBuffer].pBuf));
    21262162        }
    21272163
     
    21562192            uintptr_t           idxBuffer = pStreamCA->cBuffers;
    21572193            while (idxBuffer-- > 0)
    2158                 if (!paBuffers[idxBuffer].fQueued)
     2194                if (!drvHostAudioCaIsBufferQueued(paBuffers[idxBuffer].pBuf))
    21592195                { /* likely */ }
    21602196                else
     
    21632199                    uint32_t cQueued = 1;
    21642200                    while (idxBuffer-- > 0)
    2165                         cQueued += paBuffers[idxBuffer].fQueued;
     2201                        cQueued += drvHostAudioCaIsBufferQueued(paBuffers[idxBuffer].pBuf);
    21662202                    LogFunc(("Still done draining '%s': %u queued buffers\n", pStreamCA->Cfg.szName, cQueued));
    21672203#endif
     
    22292265         * Check out how much we can put into the current buffer.
    22302266         */
    2231         if (!paBuffers[idxBuffer].fQueued)
     2267        AudioQueueBufferRef const pBuf = paBuffers[idxBuffer].pBuf;
     2268        if (!drvHostAudioCaIsBufferQueued(pBuf))
    22322269        { /* likely */ }
    22332270        else
     
    22382275        }
    22392276
    2240         AudioQueueBufferRef const pBuf    = paBuffers[idxBuffer].pBuf;
    22412277        AssertPtrBreakStmt(pBuf, rc = VERR_INTERNAL_ERROR_2);
    2242         uint32_t const            cbTotal = pBuf->mAudioDataBytesCapacity;
    2243         uint32_t                  cbUsed  = pBuf->mAudioDataByteSize;
     2278        uint32_t const  cbTotal = pBuf->mAudioDataBytesCapacity;
     2279        uint32_t        cbUsed  = pBuf->mAudioDataByteSize;
    22442280        AssertStmt(cbUsed < cbTotal, cbUsed = cbTotal);
    2245         uint32_t const            cbAvail = cbTotal - cbUsed;
     2281        uint32_t const  cbAvail = cbTotal - cbUsed;
    22462282
    22472283        /*
     
    22672303        cbWritten               += cbAvail;
    22682304        pStreamCA->offInternal  += cbAvail;
    2269         ASMAtomicWriteBool(&paBuffers[idxBuffer].fQueued, true);
     2305        drvHostAudioCaSetBufferQueued(pBuf, true /*fQueued*/);
    22702306
    22712307        OSStatus orc = AudioQueueEnqueueBuffer(pStreamCA->hAudioQueue, pBuf, 0 /*inNumPacketDesc*/, NULL /*inPacketDescs*/);
     
    22762312            LogRelMax(256, ("CoreAudio: AudioQueueEnqueueBuffer('%s', #%u) failed: %#x (%d)\n",
    22772313                            pStreamCA->Cfg.szName, idxBuffer, orc, orc));
    2278             ASMAtomicWriteBool(&paBuffers[idxBuffer].fQueued, false);
     2314            drvHostAudioCaSetBufferQueued(pBuf, false /*fQueued*/);
    22792315            pBuf->mAudioDataByteSize -= PDMAudioPropsFramesToBytes(&pStreamCA->Cfg.Props, 1); /* avoid assertions above */
    22802316            rc = VERR_AUDIO_STREAM_NOT_READY;
     
    24012437         * Check out how much we can read from the current buffer (if anything at all).
    24022438         */
    2403         if (!paBuffers[idxBuffer].fQueued)
     2439        AudioQueueBufferRef const pBuf = paBuffers[idxBuffer].pBuf;
     2440        if (!drvHostAudioCaIsBufferQueued(pBuf))
    24042441        { /* likely */ }
    24052442        else
     
    24102447        }
    24112448
    2412         AudioQueueBufferRef const pBuf    = paBuffers[idxBuffer].pBuf;
    24132449        AssertPtrBreakStmt(pBuf, rc = VERR_INTERNAL_ERROR_2);
    2414         uint32_t const            cbTotal = pBuf->mAudioDataBytesCapacity;
    2415         uint32_t                  cbValid = pBuf->mAudioDataByteSize;
     2450        uint32_t const  cbTotal = pBuf->mAudioDataBytesCapacity;
     2451        uint32_t        cbValid = pBuf->mAudioDataByteSize;
    24162452        AssertStmt(cbValid < cbTotal, cbValid = cbTotal);
    2417         uint32_t                  offRead = paBuffers[idxBuffer].offRead;
    2418         uint32_t const            cbLeft  = cbValid - offRead;
     2453        uint32_t        offRead = paBuffers[idxBuffer].offRead;
     2454        uint32_t const  cbLeft  = cbValid - offRead;
    24192455
    24202456        /*
     
    24412477        paBuffers[idxBuffer].offRead = 0;
    24422478        pBuf->mAudioDataByteSize     = 0;
    2443         ASMAtomicWriteBool(&paBuffers[idxBuffer].fQueued, true);
     2479        drvHostAudioCaSetBufferQueued(pBuf, true /*fQueued*/);
    24442480
    24452481        OSStatus orc = AudioQueueEnqueueBuffer(pStreamCA->hAudioQueue, pBuf, 0 /*inNumPacketDesc*/, NULL /*inPacketDescs*/);
     
    24502486            LogRelMax(256, ("CoreAudio: AudioQueueEnqueueBuffer('%s', #%u) failed: %#x (%d)\n",
    24512487                            pStreamCA->Cfg.szName, idxBuffer, orc, orc));
    2452             ASMAtomicWriteBool(&paBuffers[idxBuffer].fQueued, false);
     2488            drvHostAudioCaSetBufferQueued(pBuf, false /*fQueued*/);
    24532489            rc = VERR_AUDIO_STREAM_NOT_READY;
    24542490            break;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette