Changeset 63958 in vbox
- Timestamp:
- Sep 22, 2016 3:20:29 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
r63927 r63958 495 495 /** The stream's thread handle for maintaining the audio queue. */ 496 496 RTTHREAD hThread; 497 /** Flag indicating to start a stream's data processing. */ 498 bool fRun; 497 499 /** Whether the stream is in a running (active) state or not. 498 500 * For playback streams this means that audio data can be (or is being) played, 499 501 * for capturing streams this means that audio data is being captured (if available). */ 500 bool f Running;502 bool fIsRunning; 501 503 /** Thread shutdown indicator. */ 502 504 bool fShutdown; … … 1822 1824 1823 1825 #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 */ 1824 1835 static DECLCALLBACK(int) coreAudioQueueThread(RTTHREAD hThreadSelf, void *pvUser) 1825 1836 { … … 1856 1867 return VERR_GENERAL_FAILURE; /** @todo Fudge! */ 1857 1868 1858 const size_t cbBufSize = _4K; 1869 const size_t cbBufSize = _4K; /** @todo Make this configurable! */ 1859 1870 1860 1871 /* … … 1863 1874 for (size_t i = 0; i < RT_ELEMENTS(pCAStream->audioBuffer); i++) 1864 1875 { 1865 AudioQueueBufferRef pBuf = pCAStream->audioBuffer[i]; 1866 1867 err = AudioQueueAllocateBuffer(pCAStream->audioQueue, cbBufSize, &pBuf); 1876 err = AudioQueueAllocateBuffer(pCAStream->audioQueue, cbBufSize, &pCAStream->audioBuffer[i]); 1868 1877 if (err != noErr) 1869 1878 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;1877 1879 } 1878 1880 … … 1880 1882 return VERR_GENERAL_FAILURE; /** @todo Fudge! */ 1881 1883 1882 /* Signal the main thread . */1884 /* Signal the main thread before entering the main loop. */ 1883 1885 RTThreadUserSignal(RTThreadSelf()); 1884 1886 … … 1917 1919 } 1918 1920 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 */ 1928 int 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 */ 1978 static DECLCALLBACK(void) coreAudioInputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer, 1979 const AudioTimeStamp *pAudioTS, 1980 UInt32 cPacketDesc, const AudioStreamPacketDescription *paPacketDesc) 1922 1981 { 1923 1982 RT_NOREF(audioQueue, pAudioTS, cPacketDesc, paPacketDesc); … … 1929 1988 AssertRC(rc); 1930 1989 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); 1966 1993 1967 1994 rc = RTCritSectLeave(&pCAStream->CritSect); 1968 1995 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 */ 2005 int 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 */ 2064 static DECLCALLBACK(void) coreAudioOutputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer) 1978 2065 { 1979 2066 RT_NOREF(audioQueue); … … 1985 2072 AssertRC(rc); 1986 2073 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); 2040 2077 2041 2078 rc = RTCritSectLeave(&pCAStream->CritSect); … … 2043 2080 } 2044 2081 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 */ 2088 static 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 */ 2045 2126 static int coreAudioStreamInitQueue(PCOREAUDIOSTREAM pCAStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq) 2046 2127 { … … 2085 2166 } 2086 2167 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 */ 2087 2174 static int coreAudioStreamUninitQueue(PCOREAUDIOSTREAM pCAStream) 2088 2175 { … … 2118 2205 } 2119 2206 2207 /** 2208 * Unitializes a Core Audio stream. 2209 * 2210 * @returns IPRT status code. 2211 * @param pCAStream Core Audio stream to uninitialize. 2212 */ 2120 2213 static int coreAudioStreamUninit(PCOREAUDIOSTREAM pCAStream) 2121 2214 { … … 3246 3339 #endif 3247 3340 3248 uint32_t cLive = AudioMixBufLive(&pStream->MixBuf); 3249 if (!cLive) /* Not live samples to play? Bail out. */ 3341 if (ASMAtomicReadU32(&pCAStream->enmStatus) != COREAUDIOSTATUS_INIT) 3250 3342 { 3251 3343 if (pcbWritten) … … 3254 3346 } 3255 3347 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 3256 3356 size_t cbLive = AUDIOMIXBUF_S2B(&pStream->MixBuf, cLive); 3257 3357 … … 3303 3403 3304 3404 #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 3305 3418 int rc2 = RTCritSectLeave(&pCAStream->CritSect); 3306 3419 AssertRC(rc2); … … 3348 3461 { 3349 3462 #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); 3354 3465 #else 3355 3466 /* Only start the device if it is actually stopped */ … … 3377 3488 3378 3489 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 3379 3500 case PDMAUDIOSTREAMCMD_PAUSE: 3380 3501 { 3381 3502 #ifdef VBOX_WITH_AUDIO_CA_QUEUES 3382 LogFunc(("Queue disable/pause\n")); 3383 ASMAtomicXchgBool(&pCAStream->fRunning, false); 3384 3503 LogFunc(("Queue pause\n")); 3385 3504 AudioQueuePause(pCAStream->audioQueue); 3505 ASMAtomicXchgBool(&pCAStream->fIsRunning, false); 3386 3506 #else 3387 3507 /* Only stop the device if it is actually running */ … … 3546 3666 return rc; 3547 3667 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; 3551 3672 #endif 3552 3673
Note:
See TracChangeset
for help on using the changeset viewer.