VirtualBox

Changeset 63958 in vbox


Ignore:
Timestamp:
Sep 22, 2016 3:20:29 PM (8 years ago)
Author:
vboxsync
Message:

Audio/DrvHostCoreAudio.cpp: Update on Audio Queues (work in progress, not yet enabled by default).

File:
1 edited

Legend:

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

    r63927 r63958  
    495495    /** The stream's thread handle for maintaining the audio queue. */
    496496    RTTHREAD                hThread;
     497    /** Flag indicating to start a stream's data processing. */
     498    bool                    fRun;
    497499    /** Whether the stream is in a running (active) state or not.
    498500     *  For playback streams this means that audio data can be (or is being) played,
    499501     *  for capturing streams this means that audio data is being captured (if available). */
    500     bool                    fRunning;
     502    bool                    fIsRunning;
    501503    /** Thread shutdown indicator. */
    502504    bool                    fShutdown;
     
    18221824
    18231825#ifdef VBOX_WITH_AUDIO_CA_QUEUES
     1826/**
     1827 * Thread for a Core Audio stream's audio queue handling.
     1828 * This thread is required per audio queue to pump data to/from the Core Audio stream and
     1829 * handling its callbacks.
     1830 *
     1831 * @returns IPRT status code.
     1832 * @param   hThreadSelf         Thread handle.
     1833 * @param   pvUser              User argument.
     1834 */
    18241835static DECLCALLBACK(int) coreAudioQueueThread(RTTHREAD hThreadSelf, void *pvUser)
    18251836{
     
    18561867        return VERR_GENERAL_FAILURE; /** @todo Fudge! */
    18571868
    1858     const size_t cbBufSize = _4K;
     1869    const size_t cbBufSize = _4K; /** @todo Make this configurable! */
    18591870
    18601871    /*
     
    18631874    for (size_t i = 0; i < RT_ELEMENTS(pCAStream->audioBuffer); i++)
    18641875    {
    1865         AudioQueueBufferRef pBuf = pCAStream->audioBuffer[i];
    1866 
    1867         err = AudioQueueAllocateBuffer(pCAStream->audioQueue, cbBufSize, &pBuf);
     1876        err = AudioQueueAllocateBuffer(pCAStream->audioQueue, cbBufSize, &pCAStream->audioBuffer[i]);
    18681877        if (err != noErr)
    18691878            break;
    1870 
    1871         RT_BZERO(pBuf->mAudioData, sizeof(pBuf->mAudioDataBytesCapacity));
    1872         pBuf->mAudioDataByteSize = pBuf->mAudioDataBytesCapacity;
    1873 
    1874         err = AudioQueueEnqueueBuffer(pCAStream->audioQueue, pBuf, 0, NULL);
    1875         if (err != noErr)
    1876             break;
    18771879    }
    18781880
     
    18801882        return VERR_GENERAL_FAILURE; /** @todo Fudge! */
    18811883
    1882     /* Signal the main thread. */
     1884    /* Signal the main thread before entering the main loop. */
    18831885    RTThreadUserSignal(RTThreadSelf());
    18841886
     
    19171919}
    19181920
    1919 static void coreAudioInputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer,
    1920                                   const AudioTimeStamp *pAudioTS,
    1921                                   UInt32 cPacketDesc, const AudioStreamPacketDescription *paPacketDesc)
     1921/**
     1922 * Processes input data of an audio queue buffer and stores it into a Core Audio stream.
     1923 *
     1924 * @returns IPRT status code.
     1925 * @param   pCAStream           Core Audio stream to store input data into.
     1926 * @param   audioBuffer         Audio buffer to process input data from.
     1927 */
     1928int coreAudioInputQueueProcBuffer(PCOREAUDIOSTREAM pCAStream, AudioQueueBufferRef audioBuffer)
     1929{
     1930    size_t cbWritten = 0;
     1931
     1932    PRTCIRCBUF pCircBuf = pCAStream->pCircBuf;
     1933    AssertPtr(pCircBuf);
     1934
     1935    UInt8 *pvSrc = (UInt8 *)audioBuffer->mAudioData;
     1936    UInt8 *pvDst = NULL;
     1937
     1938    size_t cbToWrite = audioBuffer->mAudioDataByteSize;
     1939    size_t cbLeft    = cbToWrite;
     1940
     1941    while (cbLeft)
     1942    {
     1943        /* Try to acquire the necessary block from the ring buffer. */
     1944        RTCircBufAcquireWriteBlock(pCircBuf, cbLeft, (void **)&pvDst, &cbToWrite);
     1945
     1946        if (!cbToWrite)
     1947            break;
     1948
     1949        /* Copy the data from our ring buffer to the core audio buffer. */
     1950        memcpy((UInt8 *)pvDst + cbWritten, pvSrc + cbWritten, cbToWrite);
     1951
     1952        /* Release the read buffer, so it could be used for new data. */
     1953        RTCircBufReleaseWriteBlock(pCircBuf, cbToWrite);
     1954
     1955        cbWritten += cbToWrite;
     1956
     1957        Assert(cbLeft >= cbToWrite);
     1958        cbLeft -= cbToWrite;
     1959    }
     1960
     1961    audioBuffer->mAudioDataByteSize = cbWritten;
     1962
     1963    Log3Func(("pCAStream=%p, cbWritten=%zu\n", pCAStream, cbWritten));
     1964
     1965    return VINF_SUCCESS;
     1966}
     1967
     1968/**
     1969 * Input audio queue callback. Called whenever input data from the audio queue becomes available.
     1970 *
     1971 * @param   pvUser              User argument.
     1972 * @param   audioQueue          Audio queue to process input data from.
     1973 * @param   audioBuffer         Audio buffer to process input data from. Must be part of audio queue.
     1974 * @param   pAudioTS            Audio timestamp.
     1975 * @param   cPacketDesc         Number of packet descriptors.
     1976 * @param   paPacketDesc        Array of packet descriptors.
     1977 */
     1978static DECLCALLBACK(void) coreAudioInputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer,
     1979                                                const AudioTimeStamp *pAudioTS,
     1980                                                UInt32 cPacketDesc, const AudioStreamPacketDescription *paPacketDesc)
    19221981{
    19231982    RT_NOREF(audioQueue, pAudioTS, cPacketDesc, paPacketDesc);
     
    19291988    AssertRC(rc);
    19301989
    1931     size_t cbWritten = 0;
    1932 
    1933     const bool fRunning = ASMAtomicReadBool(&pCAStream->fRunning);
    1934 
    1935     if (fRunning)
    1936     {
    1937         PRTCIRCBUF pCircBuf = pCAStream->pCircBuf;
    1938         AssertPtr(pCircBuf);
    1939 
    1940         UInt8 *pvSrc = (UInt8 *)audioBuffer->mAudioData;
    1941         UInt8 *pvDst = NULL;
    1942 
    1943         size_t cbToWrite = audioBuffer->mAudioDataByteSize;
    1944         size_t cbLeft    = cbToWrite;
    1945 
    1946         while (cbLeft)
    1947         {
    1948             /* Try to acquire the necessary block from the ring buffer. */
    1949             RTCircBufAcquireWriteBlock(pCircBuf, cbLeft, (void **)&pvDst, &cbToWrite);
    1950 
    1951             if (!cbToWrite)
    1952                 break;
    1953 
    1954             /* Copy the data from our ring buffer to the core audio buffer. */
    1955             memcpy((UInt8 *)pvDst + cbWritten, pvSrc + cbWritten, cbToWrite);
    1956 
    1957             /* Release the read buffer, so it could be used for new data. */
    1958             RTCircBufReleaseWriteBlock(pCircBuf, cbToWrite);
    1959 
    1960             cbWritten += cbToWrite;
    1961 
    1962             Assert(cbLeft >= cbToWrite);
    1963             cbLeft -= cbToWrite;
    1964         }
    1965     }
     1990    rc = coreAudioInputQueueProcBuffer(pCAStream, audioBuffer);
     1991    if (RT_SUCCESS(rc))
     1992        AudioQueueEnqueueBuffer(audioQueue, audioBuffer, 0, NULL);
    19661993
    19671994    rc = RTCritSectLeave(&pCAStream->CritSect);
    19681995    AssertRC(rc);
    1969 
    1970     audioBuffer->mAudioDataByteSize = cbWritten;
    1971 
    1972     AudioQueueEnqueueBuffer(pCAStream->audioQueue, audioBuffer, 0, NULL);
    1973 
    1974     Log3Func(("pCAStream=%p, fRunning=%RTbool, cbWritten=%zu\n", pCAStream, fRunning, cbWritten));
    1975 }
    1976 
    1977 static void coreAudioOutputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer)
     1996}
     1997
     1998/**
     1999 * Processes output data of a Core Audio stream into an audio queue buffer.
     2000 *
     2001 * @returns IPRT status code.
     2002 * @param   pCAStream           Core Audio stream to process output data for.
     2003 * @param   audioBuffer         Audio buffer to store data into.
     2004 */
     2005int coreAudioOutputQueueProcBuffer(PCOREAUDIOSTREAM pCAStream, AudioQueueBufferRef audioBuffer)
     2006{
     2007    PRTCIRCBUF pCircBuf = pCAStream->pCircBuf;
     2008    AssertPtr(pCircBuf);
     2009
     2010    size_t cbRead = 0;
     2011
     2012    UInt8 *pvSrc = NULL;
     2013    UInt8 *pvDst = (UInt8 *)audioBuffer->mAudioData;
     2014
     2015    size_t cbToRead = RT_MIN(RTCircBufUsed(pCircBuf), audioBuffer->mAudioDataBytesCapacity);
     2016    size_t cbLeft   = cbToRead;
     2017
     2018    while (cbLeft)
     2019    {
     2020        /* Try to acquire the necessary block from the ring buffer. */
     2021        RTCircBufAcquireReadBlock(pCircBuf, cbLeft, (void **)&pvSrc, &cbToRead);
     2022
     2023        /* Break if nothing is used anymore. */
     2024        if (!cbToRead)
     2025            break;
     2026
     2027        /* Copy the data from our ring buffer to the core audio buffer. */
     2028        memcpy((UInt8 *)pvDst + cbRead, pvSrc, cbToRead);
     2029
     2030        /* Release the read buffer, so it could be used for new data. */
     2031        RTCircBufReleaseReadBlock(pCircBuf, cbToRead);
     2032
     2033        /* Move offset. */
     2034        cbRead += cbToRead;
     2035        Assert(cbRead <= audioBuffer->mAudioDataBytesCapacity);
     2036
     2037        Assert(cbToRead <= cbLeft);
     2038        cbLeft -= cbToRead;
     2039    }
     2040
     2041    audioBuffer->mAudioDataByteSize = cbRead;
     2042
     2043    if (audioBuffer->mAudioDataByteSize < audioBuffer->mAudioDataBytesCapacity)
     2044    {
     2045        RT_BZERO((UInt8 *)audioBuffer->mAudioData + audioBuffer->mAudioDataByteSize,
     2046                 audioBuffer->mAudioDataBytesCapacity - audioBuffer->mAudioDataByteSize);
     2047
     2048        audioBuffer->mAudioDataByteSize = audioBuffer->mAudioDataBytesCapacity;
     2049    }
     2050
     2051    Log3Func(("pCAStream=%p, cbCapacity=%RU32, cbRead=%zu\n",
     2052              pCAStream, audioBuffer->mAudioDataBytesCapacity, cbRead));
     2053
     2054    return VINF_SUCCESS;
     2055}
     2056
     2057/**
     2058 * Output audio queue callback. Called whenever an audio queue is ready to process more output data.
     2059 *
     2060 * @param   pvUser              User argument.
     2061 * @param   audioQueue          Audio queue to process output data for.
     2062 * @param   audioBuffer         Audio buffer to store output data in. Must be part of audio queue.
     2063 */
     2064static DECLCALLBACK(void) coreAudioOutputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer)
    19782065{
    19792066    RT_NOREF(audioQueue);
     
    19852072    AssertRC(rc);
    19862073
    1987     size_t cbRead = 0;
    1988 
    1989     const bool fRunning = ASMAtomicReadBool(&pCAStream->fRunning);
    1990 
    1991     if (fRunning)
    1992     {
    1993         PRTCIRCBUF pCircBuf = pCAStream->pCircBuf;
    1994         AssertPtr(pCircBuf);
    1995 
    1996         UInt8 *pvSrc = NULL;
    1997         UInt8 *pvDst = (UInt8 *)audioBuffer->mAudioData;
    1998 
    1999         size_t cbToRead = RT_MIN(RTCircBufUsed(pCircBuf), audioBuffer->mAudioDataBytesCapacity);
    2000         size_t cbLeft   = cbToRead;
    2001 
    2002         while (cbLeft)
    2003         {
    2004             /* Try to acquire the necessary block from the ring buffer. */
    2005             RTCircBufAcquireReadBlock(pCircBuf, cbLeft, (void **)&pvSrc, &cbToRead);
    2006 
    2007             /* Break if nothing is used anymore. */
    2008             if (!cbToRead)
    2009                 break;
    2010 
    2011             /* Copy the data from our ring buffer to the core audio buffer. */
    2012             memcpy((UInt8 *)pvDst + cbRead, pvSrc, cbToRead);
    2013 
    2014             /* Release the read buffer, so it could be used for new data. */
    2015             RTCircBufReleaseReadBlock(pCircBuf, cbToRead);
    2016 
    2017             /* Move offset. */
    2018             cbRead += cbToRead;
    2019             Assert(cbRead <= audioBuffer->mAudioDataBytesCapacity);
    2020 
    2021             Assert(cbToRead <= cbLeft);
    2022             cbLeft -= cbToRead;
    2023         }
    2024     }
    2025 
    2026     audioBuffer->mAudioDataByteSize = cbRead;
    2027 
    2028     if (audioBuffer->mAudioDataByteSize < audioBuffer->mAudioDataBytesCapacity)
    2029     {
    2030         RT_BZERO((UInt8 *)audioBuffer->mAudioData + audioBuffer->mAudioDataByteSize,
    2031                  audioBuffer->mAudioDataBytesCapacity - audioBuffer->mAudioDataByteSize);
    2032 
    2033         audioBuffer->mAudioDataByteSize = audioBuffer->mAudioDataBytesCapacity;
    2034     }
    2035 
    2036     AudioQueueEnqueueBuffer(pCAStream->audioQueue, audioBuffer, 0, NULL);
    2037 
    2038     Log3Func(("pCAStream=%p, fRunning=%RTbool, cbCapacity=%RU32, cbRead=%zu\n",
    2039               pCAStream, fRunning, audioBuffer->mAudioDataBytesCapacity, cbRead));
     2074    rc = coreAudioOutputQueueProcBuffer(pCAStream, audioBuffer);
     2075    if (RT_SUCCESS(rc))
     2076        AudioQueueEnqueueBuffer(audioQueue, audioBuffer, 0, NULL);
    20402077
    20412078    rc = RTCritSectLeave(&pCAStream->CritSect);
     
    20432080}
    20442081
     2082/**
     2083 * Invalidates a Core Audio stream's audio queue.
     2084 *
     2085 * @returns IPRT status code.
     2086 * @param   pCAStream           Core Audio stream to invalidate its queue for.
     2087 */
     2088static int coreAudioStreamInvalidateQueue(PCOREAUDIOSTREAM pCAStream)
     2089{
     2090    int rc = VINF_SUCCESS;
     2091
     2092    for (size_t i = 0; i < RT_ELEMENTS(pCAStream->audioBuffer); i++)
     2093    {
     2094        AudioQueueBufferRef pBuf = pCAStream->audioBuffer[i];
     2095
     2096        if (pCAStream->enmDir == PDMAUDIODIR_IN)
     2097        {
     2098        }
     2099        else if (pCAStream->enmDir == PDMAUDIODIR_OUT)
     2100        {
     2101            int rc2 = coreAudioOutputQueueProcBuffer(pCAStream, pBuf);
     2102            if (   RT_SUCCESS(rc2)
     2103                && pBuf->mAudioDataByteSize)
     2104            {
     2105                AudioQueueEnqueueBuffer(pCAStream->audioQueue, pBuf, 0, NULL);
     2106            }
     2107
     2108            if (RT_SUCCESS(rc))
     2109                rc = rc2;
     2110        }
     2111        else
     2112            AssertFailed();
     2113    }
     2114
     2115    return rc;
     2116}
     2117
     2118/**
     2119 * Initializes a Core Audio stream's audio queue.
     2120 *
     2121 * @returns IPRT status code.
     2122 * @param   pCAStream           Core Audio stream to initialize audio queue for.
     2123 * @param   pCfgReq             Requested stream configuration.
     2124 * @param   pCfgAcq             Acquired stream configuration on success.
     2125 */
    20452126static int coreAudioStreamInitQueue(PCOREAUDIOSTREAM pCAStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    20462127{
     
    20852166}
    20862167
     2168/**
     2169 * Unitializes a Core Audio stream's audio queue.
     2170 *
     2171 * @returns IPRT status code.
     2172 * @param   pCAStream           Core Audio stream to unitialize audio queue for.
     2173 */
    20872174static int coreAudioStreamUninitQueue(PCOREAUDIOSTREAM pCAStream)
    20882175{
     
    21182205}
    21192206
     2207/**
     2208 * Unitializes a Core Audio stream.
     2209 *
     2210 * @returns IPRT status code.
     2211 * @param   pCAStream           Core Audio stream to uninitialize.
     2212 */
    21202213static int coreAudioStreamUninit(PCOREAUDIOSTREAM pCAStream)
    21212214{
     
    32463339#endif
    32473340
    3248     uint32_t cLive = AudioMixBufLive(&pStream->MixBuf);
    3249     if (!cLive) /* Not live samples to play? Bail out. */
     3341    if (ASMAtomicReadU32(&pCAStream->enmStatus) != COREAUDIOSTATUS_INIT)
    32503342    {
    32513343        if (pcbWritten)
     
    32543346    }
    32553347
     3348    uint32_t cLive = AudioMixBufLive(&pStream->MixBuf);
     3349    if (!cLive) /* Not live samples to play? Bail out. */
     3350    {
     3351        if (pcbWritten)
     3352            *pcbWritten = 0;
     3353        return VINF_SUCCESS;
     3354    }
     3355
    32563356    size_t cbLive  = AUDIOMIXBUF_S2B(&pStream->MixBuf, cLive);
    32573357
     
    33033403
    33043404#ifdef VBOX_WITH_AUDIO_CA_QUEUES
     3405    if (    RT_SUCCESS(rc)
     3406        &&  pCAStream->fRun
     3407        && !pCAStream->fIsRunning)
     3408    {
     3409        rc = coreAudioStreamInvalidateQueue(pCAStream);
     3410        if (RT_SUCCESS(rc))
     3411        {
     3412            AudioQueueStart(pCAStream->audioQueue, NULL);
     3413            pCAStream->fRun       = false;
     3414            pCAStream->fIsRunning = true;
     3415        }
     3416    }
     3417
    33053418    int rc2 = RTCritSectLeave(&pCAStream->CritSect);
    33063419    AssertRC(rc2);
     
    33483461        {
    33493462#ifdef VBOX_WITH_AUDIO_CA_QUEUES
    3350             LogFunc(("Queue enable/resume\n"));
    3351             ASMAtomicXchgBool(&pCAStream->fRunning, true);
    3352 
    3353             AudioQueueStart(pCAStream->audioQueue, NULL);
     3463            LogFunc(("Queue enable\n"));
     3464            ASMAtomicXchgBool(&pCAStream->fRun, true);
    33543465#else
    33553466            /* Only start the device if it is actually stopped */
     
    33773488
    33783489        case PDMAUDIOSTREAMCMD_DISABLE:
     3490        {
     3491#ifdef VBOX_WITH_AUDIO_CA_QUEUES
     3492            LogFunc(("Queue disable\n"));
     3493            AudioQueueStop(pCAStream->audioQueue, 1 /* Immediately */);
     3494            ASMAtomicXchgBool(&pCAStream->fRun,       false);
     3495            ASMAtomicXchgBool(&pCAStream->fIsRunning, false);
     3496#endif
     3497            break;
     3498        }
     3499
    33793500        case PDMAUDIOSTREAMCMD_PAUSE:
    33803501        {
    33813502#ifdef VBOX_WITH_AUDIO_CA_QUEUES
    3382             LogFunc(("Queue disable/pause\n"));
    3383             ASMAtomicXchgBool(&pCAStream->fRunning, false);
    3384 
     3503            LogFunc(("Queue pause\n"));
    33853504            AudioQueuePause(pCAStream->audioQueue);
     3505            ASMAtomicXchgBool(&pCAStream->fIsRunning, false);
    33863506#else
    33873507            /* Only stop the device if it is actually running */
     
    35463666        return rc;
    35473667
    3548     pCAStream->hThread   = NIL_RTTHREAD;
    3549     pCAStream->fRunning  = false;
    3550     pCAStream->fShutdown = false;
     3668    pCAStream->hThread    = NIL_RTTHREAD;
     3669    pCAStream->fRun       = false;
     3670    pCAStream->fIsRunning = false;
     3671    pCAStream->fShutdown  = false;
    35513672#endif
    35523673
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