Changeset 98405 in vbox for trunk/src/VBox
- Timestamp:
- Feb 1, 2023 3:13:23 PM (23 months ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r98103 r98405 113 113 static int audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 114 114 static void audioMixerSinkResetInternal(PAUDMIXSINK pSink); 115 static int audioMixerSinkWaitForDrainedLocked(PAUDMIXSINK pSink, RTMSINTERVAL msTimeout); 115 116 116 117 static int audioMixerStreamCtlInternal(PAUDMIXSTREAM pMixStream, PDMAUDIOSTREAMCMD enmCmd); … … 414 415 /* AIO */ 415 416 AssertPtr(pDevIns); 416 pSink->AIO.pDevIns = pDevIns; 417 pSink->AIO.hThread = NIL_RTTHREAD; 418 pSink->AIO.hEvent = NIL_RTSEMEVENT; 419 pSink->AIO.fStarted = false; 420 pSink->AIO.fShutdown = false; 421 pSink->AIO.cUpdateJobs = 0; 417 pSink->AIO.pDevIns = pDevIns; 418 pSink->AIO.hThread = NIL_RTTHREAD; 419 pSink->AIO.hEvent = NIL_RTSEMEVENT; 420 pSink->AIO.hEventDrained = NIL_RTSEMEVENT; 421 pSink->AIO.fStarted = false; 422 pSink->AIO.fShutdown = false; 423 pSink->AIO.cUpdateJobs = 0; 422 424 423 425 /* … … 578 580 * buffers that the update job has yet to transfer. This 579 581 * is ignored for input streams. 580 */ 581 int AudioMixerSinkDrainAndStop(PAUDMIXSINK pSink, uint32_t cbComming) 582 * @param msTimeout Timeout to use for synchronously waiting for the draining / update jobs. 583 * Set to 0 for running asynchronously. 584 */ 585 int AudioMixerSinkDrainAndStopEx(PAUDMIXSINK pSink, uint32_t cbComming, RTMSINTERVAL msTimeout) 582 586 { 583 587 AssertPtrReturn(pSink, VERR_INVALID_POINTER); … … 620 624 status. (The device's DMA timer won't kick it any more, so we must.) */ 621 625 AudioMixerSinkSignalUpdateJob(pSink); 626 #ifdef LOG_ENABLED 627 uint64_t const msStart = RTTimeMilliTS(); 628 Log3Func(("Waiting for %RU32 update jobs (msTimeout=%RU32)\n", pSink->AIO.cUpdateJobs, msTimeout)); 629 #endif 630 if ( msTimeout 631 && pSink->AIO.cUpdateJobs) 632 { 633 rc = audioMixerSinkWaitForDrainedLocked(pSink, msTimeout); 634 AssertRCReturn(rc, rc); 635 #ifdef LOG_ENABLED 636 Log3Func(("Waiting for update jobs done (rc=%Rrc, took %RU64ms)\n", rc, RTTimeMilliTS() - msStart)); 637 #endif 638 } 622 639 } 623 640 else … … 662 679 663 680 /** 681 * Kicks off the draining and stopping playback/capture on the mixer sink. 682 * 683 * For input streams this causes an immediate stop, as draining only makes sense 684 * to output stream in the VBox device context. 685 * 686 * @returns VBox status code. Generally always VINF_SUCCESS unless the input 687 * is invalid. Individual driver errors are suppressed and ignored. 688 * @param pSink Mixer sink to control. 689 * @param cbComming The number of bytes still left in the device's DMA 690 * buffers that the update job has yet to transfer. This 691 * is ignored for input streams. 692 */ 693 int AudioMixerSinkDrainAndStop(PAUDMIXSINK pSink, uint32_t cbComming) 694 { 695 return AudioMixerSinkDrainAndStopEx(pSink, cbComming, 0 /* Don't wait */); 696 } 697 698 699 /** 664 700 * Destroys and frees a mixer sink. 665 701 * … … 720 756 { 721 757 int rc2 = RTSemEventSignal(pSink->AIO.hEvent); 758 AssertRC(rc2); 759 } 760 if (pSink->AIO.hEventDrained != NIL_RTSEMEVENT) 761 { 762 int rc2 = RTSemEventSignal(pSink->AIO.hEventDrained); 722 763 AssertRC(rc2); 723 764 } … … 734 775 AssertRC(rc2); 735 776 pSink->AIO.hEvent = NIL_RTSEMEVENT; 777 } 778 if (pSink->AIO.hEventDrained != NIL_RTSEMEVENT) 779 { 780 int rc2 = RTSemEventDestroy(pSink->AIO.hEventDrained); 781 AssertRC(rc2); 782 pSink->AIO.hEventDrained = NIL_RTSEMEVENT; 736 783 } 737 784 … … 1771 1818 * The run loop. 1772 1819 */ 1820 bool fDrainingFinished = false; /* Whether draining the stream is finished. */ 1821 #ifdef LOG_ENABLED 1822 char szStatus[AUDIOMIXERSINK_STATUS_STR_MAX]; 1823 #endif 1824 1773 1825 LogFlowFunc(("%s: Entering run loop...\n", pSink->pszName)); 1774 1826 while (!pSink->AIO.fShutdown) … … 1777 1829 1778 1830 RTCritSectEnter(&pSink->CritSect); 1831 1832 #ifdef LOG_ENABLED 1833 Log3Func(("%s: Running async I/O (fStatus=%s) ...\n", pSink->pszName, 1834 dbgAudioMixerSinkStatusToStr(pSink->fStatus, szStatus))); 1835 #endif 1779 1836 if (pSink->fStatus & (AUDMIXSINK_STS_RUNNING | AUDMIXSINK_STS_DRAINING)) 1780 1837 { 1838 uint32_t fStatusOld = pSink->fStatus; 1839 1781 1840 /* 1782 1841 * Before doing jobs, always update input sinks. … … 1804 1863 */ 1805 1864 if (!(pSink->fStatus & AUDMIXSINK_STS_DRAINING)) 1806 { /* likely */ } 1865 { 1866 /* likely */ 1867 if (fStatusOld & AUDMIXSINK_STS_DRAINING) 1868 { 1869 Log3Func(("%s: Started draining\n", pSink->pszName)); 1870 fDrainingFinished = true; 1871 } 1872 } 1807 1873 else 1808 1874 { … … 1812 1878 } 1813 1879 1880 fStatusOld = pSink->fStatus; 1881 1882 Log3Func(("%s: Running async I/O finished (fStatus=%s, cMsSleep=%RU32)\n", 1883 pSink->pszName, dbgAudioMixerSinkStatusToStr(pSink->fStatus, szStatus), cMsSleep)); 1814 1884 } 1815 1885 RTCritSectLeave(&pSink->CritSect); 1886 1887 /* 1888 * Signal waiters. 1889 */ 1890 if (fDrainingFinished) 1891 { 1892 Log3Func(("%s: Finished draining\n", pSink->pszName)); 1893 int rc = RTSemEventSignal(pSink->AIO.hEventDrained); 1894 AssertLogRelMsgReturn(RT_SUCCESS(rc), ("%s: RTSemEventSignal(hEventDrained) -> %Rrc\n", pSink->pszName, rc), rc); 1895 fDrainingFinished = false; 1896 } 1816 1897 1817 1898 /* … … 1822 1903 int rc = RTSemEventWait(pSink->AIO.hEvent, cMsSleep); 1823 1904 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_TIMEOUT, ("%s: RTSemEventWait -> %Rrc\n", pSink->pszName, rc), rc); 1905 #ifdef LOG_ENABLED 1906 Log3Func(("%s: Got signalled (fStatus=%s)\n", pSink->pszName, dbgAudioMixerSinkStatusToStr(pSink->fStatus, szStatus))); 1907 #endif 1824 1908 } 1825 1909 } … … 1887 1971 { 1888 1972 rc = RTSemEventCreate(&pSink->AIO.hEvent); 1973 AssertRCReturnStmt(rc, RTCritSectLeave(&pSink->CritSect), rc); 1974 } 1975 if (pSink->AIO.hEventDrained == NIL_RTSEMEVENT) 1976 { 1977 rc = RTSemEventCreate(&pSink->AIO.hEventDrained); 1889 1978 AssertRCReturnStmt(rc, RTCritSectLeave(&pSink->CritSect), rc); 1890 1979 } … … 1960 2049 1961 2050 /** 2051 * Waits for the sink's draining to complete, internal version. 2052 * 2053 * @returns VBox status code. 2054 * @param pSink The mixer sink which AIO thread needs waiting on. 2055 * @þaram msTimeout Timeout (in ms) to use for waiting on draining to be finished. 2056 * 2057 * @note Caller holds the sink's lock. 2058 */ 2059 static int audioMixerSinkWaitForDrainedLocked(PAUDMIXSINK pSink, RTMSINTERVAL msTimeout) 2060 { 2061 AssertReturn((pSink->fStatus & AUDMIXSINK_STS_DRAINING), VERR_WRONG_ORDER); 2062 2063 int rc; 2064 2065 if (pSink->AIO.cUpdateJobs) 2066 { 2067 rc = RTCritSectLeave(&pSink->CritSect); 2068 AssertRCReturn(rc, rc); 2069 2070 rc = RTSemEventWait(pSink->AIO.hEventDrained, msTimeout); 2071 2072 int rc2 = RTCritSectEnter(&pSink->CritSect); 2073 AssertRCReturn(rc2, rc2); 2074 2075 } 2076 else 2077 rc = VINF_SUCCESS; 2078 2079 return rc; 2080 } 2081 2082 2083 /** 2084 * Waits for the sink's draining to complete. 2085 * 2086 * @returns VBox status code. 2087 * @param pSink The mixer sink which AIO thread needs waiting on. 2088 * @þaram msTimeout Timeout (in ms) to use for waiting on draining to be finished. 2089 */ 2090 int AudioMixerSinkWaitForDrained(PAUDMIXSINK pSink, RTMSINTERVAL msTimeout) 2091 { 2092 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 2093 Assert(pSink->uMagic == AUDMIXSINK_MAGIC); 2094 2095 int rc = RTCritSectEnter(&pSink->CritSect); 2096 AssertRCReturn(rc, rc); 2097 2098 rc = audioMixerSinkWaitForDrainedLocked(pSink, msTimeout); 2099 2100 int rc2 = RTCritSectLeave(&pSink->CritSect); 2101 AssertRCReturn(rc2, rc2); 2102 2103 return rc; 2104 } 2105 2106 2107 /** 1962 2108 * Writes data to a mixer output sink. 1963 2109 * … … 2024 2170 idStream, cbSinkWritable, cbCircBufReadable, cbToTransfer, offStream)); 2025 2171 AssertMsg(!(pSink->fStatus & AUDMIXSINK_STS_DRAINING) || cbCircBufReadable == pSink->cbDmaLeftToDrain, 2026 ("cbCircBufReadable=%#x cbDmaLeftToDrain=%#x\n", cbCircBufReadable, pSink->cbDmaLeftToDrain)); 2172 ("idStream=%u: fStatus=%#x cbCircBufReadable=%#x cbDmaLeftToDrain=%#x\n", 2173 idStream, pSink->fStatus, cbCircBufReadable, pSink->cbDmaLeftToDrain)); 2027 2174 2028 2175 /* -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r98103 r98405 244 244 /** Event for letting the thread know there is some data to process. */ 245 245 RTSEMEVENT hEvent; 246 /** Event for letting the waiters know that draining the sink is done. */ 247 RTSEMEVENT hEventDrained; 246 248 /** The device instance (same for all update jobs). */ 247 249 PPDMDEVINS pDevIns; … … 309 311 * @{ */ 310 312 int AudioMixerSinkStart(PAUDMIXSINK pSink); 313 int AudioMixerSinkDrainAndStopEx(PAUDMIXSINK pSink, uint32_t cbComming, RTMSINTERVAL msTimeout); 311 314 int AudioMixerSinkDrainAndStop(PAUDMIXSINK pSink, uint32_t cbComming); 312 315 void AudioMixerSinkDestroy(PAUDMIXSINK pSink, PPDMDEVINS pDevIns); … … 324 327 int AudioMixerSinkRemoveUpdateJob(PAUDMIXSINK pSink, PFNAUDMIXSINKUPDATE pfnUpdate, void *pvUser); 325 328 int AudioMixerSinkSignalUpdateJob(PAUDMIXSINK pSink); 329 int AudioMixerSinkWaitForDrained(PAUDMIXSINK pSink, RTMSINTERVAL msTimeout); 326 330 uint64_t AudioMixerSinkTransferFromCircBuf(PAUDMIXSINK pSink, PRTCIRCBUF pCircBuf, uint64_t offStream, 327 331 uint32_t idStream, PAUDIOHLPFILE pDbgFile); -
trunk/src/VBox/Devices/Audio/DevHdaStream.cpp
r98103 r98405 1059 1059 } 1060 1060 else 1061 rc = AudioMixerSinkDrainAndStop(pSink, 1062 pStreamR3->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStreamR3->State.pCircBuf) : 0); 1061 rc = AudioMixerSinkDrainAndStopEx(pSink, 1062 pStreamR3->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStreamR3->State.pCircBuf) : 0, 1063 RT_MS_5SEC); 1063 1064 } 1064 1065 if ( RT_SUCCESS(rc) -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r98333 r98405 2348 2348 else 2349 2349 { 2350 rc = AudioMixerSinkDrainAndStop(pSink, pStreamCC->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStreamCC->State.pCircBuf) : 0); 2350 rc = AudioMixerSinkDrainAndStopEx(pSink, 2351 pStreamCC->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStreamCC->State.pCircBuf) : 0, 2352 RT_MS_5SEC); 2351 2353 ichac97R3StreamTearDown(pStream); 2352 2354 } -
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r98103 r98405 2012 2012 else 2013 2013 { 2014 rc = AudioMixerSinkDrainAndStop(pSink, pStream->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStream->State.pCircBuf) : 0); 2014 rc = AudioMixerSinkDrainAndStopEx(pSink, pStream->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStream->State.pCircBuf) : 0, 2015 RT_MS_5SEC); 2015 2016 AssertRCReturn(rc, rc); 2016 2017 }
Note:
See TracChangeset
for help on using the changeset viewer.