Changeset 89706 in vbox for trunk/src/VBox
- Timestamp:
- Jun 15, 2021 2:12:56 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 145154
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r89694 r89706 1032 1032 RTCircBufReset(pStreamCC->State.pCircBuf); 1033 1033 1034 /* (Re-)Open the st eram if necessary. */1034 /* (Re-)Open the stream if necessary. */ 1035 1035 rc = ichac97R3StreamOpen(pDevIns, pThis, pThisCC, pStream, pStreamCC, false /* fForce */); 1036 1036 … … 2005 2005 } 2006 2006 2007 /** @todo r=bird: If uHz == 0 then we'll just keep the previous stream, so 2008 * wonder how that's going to play out if the guest tries to enable it... This 2009 * makes no real sense. 2010 * 2011 * Comment your code and changes you make, please! This is frigging tedious. 2012 * 2013 * Test added in r127402? The test is older (before r118166, r113296, r112652, 2014 * r112463, r107142), but it used to be placed after calling 2015 * ichac97R3MixerRemoveDrvStreams() since r112652. Till ~r112463 a zero uHz 2016 * caused a VERR_INVALID_PARAMETER return. Before r107142 it would disable the 2017 * stream if uHz was zero. */ 2018 if (Cfg.Props.uHz) 2019 { /* likely */ } 2020 else 2021 { 2022 LogFlowFunc(("[SD%RU8] Hz is zero!! skipping/ignoring\n")); 2023 return VINF_SUCCESS; 2024 } 2025 2007 2026 /* 2008 2027 * Read the buffer descriptors and check what the max distance between … … 2064 2083 2065 2084 /* 2085 * Calculate the timer Hz / scheduling hint based on the stream frame rate. 2086 */ 2087 uint32_t uTimerHz; 2088 if (pThis->uTimerHz == AC97_TIMER_HZ_DEFAULT) /* Make sure that we don't have any custom Hz rate set we want to enforce */ 2089 { 2090 if (Cfg.Props.uHz > 44100) /* E.g. 48000 Hz. */ 2091 uTimerHz = 200; 2092 else /* Just take the global Hz rate otherwise. */ 2093 uTimerHz = pThis->uTimerHz; 2094 } 2095 else 2096 uTimerHz = pThis->uTimerHz; 2097 2098 if ( uTimerHz >= 10 2099 && uTimerHz <= 500) 2100 { /* likely */ } 2101 else 2102 { 2103 LogFunc(("[SD%RU8] Adjusting uTimerHz=%u to %u\n", pStream->u8SD, uTimerHz, 2104 Cfg.Props.uHz > 44100 ? 200 : AC97_TIMER_HZ_DEFAULT)); 2105 uTimerHz = Cfg.Props.uHz > 44100 ? 200 : AC97_TIMER_HZ_DEFAULT; 2106 } 2107 2108 /* Translate it to a scheduling hint. */ 2109 uint32_t const cMsSchedulingHint = RT_MS_1SEC / uTimerHz; 2110 2111 /* 2112 * Calculate the circular buffer size so we can decide whether to recreate 2113 * the stream or not. 2114 * 2115 * As mentioned in the HDA code, this should be at least able to hold the 2116 * data transferred in three DMA periods and in three AIO period (whichever 2117 * is higher). However, if we assume that the DMA code will engage the DMA 2118 * timer thread (currently EMT) if the AIO thread isn't getting schduled to 2119 * transfer data thru the stack, we don't need to go overboard and double 2120 * the minimums here. The less buffer the less possible delay can build when 2121 * TM is doing catch up. 2122 */ 2123 uint32_t cMsCircBuf = Cfg.enmDir == PDMAUDIODIR_IN ? pThis->cMsCircBufIn : pThis->cMsCircBufOut; 2124 cMsCircBuf = RT_MAX(cMsCircBuf, cMsDmaMinBuf); 2125 cMsCircBuf = RT_MAX(cMsCircBuf, cMsSchedulingHint * 3); 2126 cMsCircBuf = RT_MIN(cMsCircBuf, RT_MS_1SEC * 2); 2127 uint32_t const cbCircBuf = PDMAudioPropsMilliToBytes(&Cfg.Props, cMsCircBuf); 2128 2129 /* 2066 2130 * Only (re-)create the stream (and driver chain) if we really have to. 2067 2131 * Otherwise avoid this and just reuse it, as this costs performance. … … 2071 2135 || !PDMAudioStrmCfgMatchesProps(&Cfg, &pStreamCC->State.Cfg.Props) 2072 2136 || !pStreamCC->State.pCircBuf 2073 || cb DmaMinBuf >RTCircBufSize(pStreamCC->State.pCircBuf))2137 || cbCircBuf != RTCircBufSize(pStreamCC->State.pCircBuf)) 2074 2138 { 2075 2139 LogRel2(("AC97: (Re-)Opening stream '%s' (%RU32Hz, %RU8 channels, %s%RU8)\n", Cfg.szName, Cfg.Props.uHz, … … 2078 2142 LogFlowFunc(("[SD%RU8] uHz=%RU32\n", pStream->u8SD, Cfg.Props.uHz)); 2079 2143 2080 if (Cfg.Props.uHz) 2144 Assert(Cfg.enmDir != PDMAUDIODIR_UNKNOWN); 2145 2146 /* 2147 * Set the stream's timer rate and scheduling hint. 2148 */ 2149 pStreamCC->State.uTimerHz = uTimerHz; 2150 Cfg.Device.cMsSchedulingHint = cMsSchedulingHint; 2151 2152 /* 2153 * Re-create the circular buffer if necessary. 2154 */ 2155 if (pStreamCC->State.pCircBuf && RTCircBufSize(pStreamCC->State.pCircBuf) == cbCircBuf) 2156 RTCircBufReset(pStreamCC->State.pCircBuf); 2157 else 2081 2158 { 2082 Assert(Cfg.enmDir != PDMAUDIODIR_UNKNOWN); 2083 2084 /* 2085 * Set the stream's timer Hz rate, based on the PCM properties Hz rate. 2086 */ 2087 if (pThis->uTimerHz == AC97_TIMER_HZ_DEFAULT) /* Make sure that we don't have any custom Hz rate set we want to enforce */ 2088 { 2089 if (Cfg.Props.uHz > 44100) /* E.g. 48000 Hz. */ 2090 pStreamCC->State.uTimerHz = 200; 2091 else /* Just take the global Hz rate otherwise. */ 2092 pStreamCC->State.uTimerHz = pThis->uTimerHz; 2093 } 2094 else 2095 pStreamCC->State.uTimerHz = pThis->uTimerHz; 2096 2097 if ( pStreamCC->State.uTimerHz >= 10 2098 && pStreamCC->State.uTimerHz <= 500) 2099 { /* likely */ } 2100 else 2101 { 2102 LogFunc(("[SD%RU8] Adjusting uTimerHz=%u to %u\n", pStream->u8SD, pStreamCC->State.uTimerHz, 2103 Cfg.Props.uHz > 44100 ? 200 : AC97_TIMER_HZ_DEFAULT)); 2104 pStreamCC->State.uTimerHz = Cfg.Props.uHz > 44100 ? 200 : AC97_TIMER_HZ_DEFAULT; 2105 } 2106 2107 /* Set scheduling hint. */ 2108 Cfg.Device.cMsSchedulingHint = RT_MS_1SEC / pStreamCC->State.uTimerHz; 2109 2110 /* 2111 * Re-create the circular buffer if necessary. 2112 * 2113 * As mentioned in the HDA code, this should be at least able to hold the 2114 * data transferred in three DMA periods and in three AIO period (whichever 2115 * is higher). However, if we assume that the DMA code will engage the DMA 2116 * timer thread (currently EMT) if the AIO thread isn't getting schduled to 2117 * transfer data thru the stack, we don't need to go overboard and double 2118 * the minimums here. The less buffer the less possible delay can build when 2119 * TM is doing catch up. 2120 */ 2121 uint32_t cMsCircBuf = Cfg.enmDir == PDMAUDIODIR_IN ? pThis->cMsCircBufIn : pThis->cMsCircBufOut; 2122 cMsCircBuf = RT_MAX(cMsCircBuf, cMsDmaMinBuf); 2123 cMsCircBuf = RT_MAX(cMsCircBuf, Cfg.Device.cMsSchedulingHint * 3); 2124 cMsCircBuf = RT_MIN(cMsCircBuf, RT_MS_1SEC * 2); /** @todo make sure the DMA timer doesn't go over 500ms (use uTimerHz as max, really). */ 2125 uint32_t const cbCircBuf = PDMAudioPropsMilliToBytes(&Cfg.Props, cMsCircBuf); 2126 2127 if (pStreamCC->State.pCircBuf && RTCircBufSize(pStreamCC->State.pCircBuf) == cbCircBuf) 2128 RTCircBufReset(pStreamCC->State.pCircBuf); 2129 else 2130 { 2131 LogFlowFunc(("Re-creating circular buffer with size %u ms / %#x bytes (was %#x); cMsSchedulingHint=%u cMsDmaMinBuf=%u cMsCircBufXxx=%u\n", 2132 cMsCircBuf, cbCircBuf, pStreamCC->State.StatDmaBufSize, Cfg.Device.cMsSchedulingHint, cMsDmaMinBuf, 2133 Cfg.enmDir == PDMAUDIODIR_IN ? pThis->cMsCircBufIn : pThis->cMsCircBufOut)); 2134 if (pStreamCC->State.pCircBuf) 2135 RTCircBufDestroy(pStreamCC->State.pCircBuf); 2136 2137 rc = RTCircBufCreate(&pStreamCC->State.pCircBuf, cbCircBuf); 2138 AssertRCReturnStmt(rc, pStreamCC->State.pCircBuf = NULL, rc); 2139 2140 pStreamCC->State.StatDmaBufSize = (uint32_t)RTCircBufSize(pStreamCC->State.pCircBuf); 2141 } 2142 Assert(pStreamCC->State.StatDmaBufSize == cbCircBuf); 2143 2144 /* 2145 * <there should be a comment here> 2146 */ 2147 ichac97R3MixerRemoveDrvStreams(pDevIns, pThisCC, pMixSink, Cfg.enmDir, Cfg.enmPath); 2148 rc = ichac97R3MixerAddDrvStreams(pDevIns, pThisCC, pMixSink, &Cfg); 2149 if (RT_SUCCESS(rc)) 2150 rc = PDMAudioStrmCfgCopy(&pStreamCC->State.Cfg, &Cfg); 2159 LogFlowFunc(("Re-creating circular buffer with size %u ms / %#x bytes (was %#x); cMsSchedulingHint=%u cMsDmaMinBuf=%u cMsCircBufXxx=%u\n", 2160 cMsCircBuf, cbCircBuf, pStreamCC->State.StatDmaBufSize, Cfg.Device.cMsSchedulingHint, cMsDmaMinBuf, 2161 Cfg.enmDir == PDMAUDIODIR_IN ? pThis->cMsCircBufIn : pThis->cMsCircBufOut)); 2162 if (pStreamCC->State.pCircBuf) 2163 RTCircBufDestroy(pStreamCC->State.pCircBuf); 2164 2165 rc = RTCircBufCreate(&pStreamCC->State.pCircBuf, cbCircBuf); 2166 AssertRCReturnStmt(rc, pStreamCC->State.pCircBuf = NULL, rc); 2167 2168 pStreamCC->State.StatDmaBufSize = (uint32_t)RTCircBufSize(pStreamCC->State.pCircBuf); 2151 2169 } 2170 Assert(pStreamCC->State.StatDmaBufSize == cbCircBuf); 2171 2172 /* 2173 * <there should be a comment here> 2174 */ 2175 ichac97R3MixerRemoveDrvStreams(pDevIns, pThisCC, pMixSink, Cfg.enmDir, Cfg.enmPath); 2176 rc = ichac97R3MixerAddDrvStreams(pDevIns, pThisCC, pMixSink, &Cfg); 2177 if (RT_SUCCESS(rc)) 2178 rc = PDMAudioStrmCfgCopy(&pStreamCC->State.Cfg, &Cfg); 2179 2152 2180 LogFlowFunc(("[SD%RU8] rc=%Rrc\n", pStream->u8SD, rc)); 2153 2181 }
Note:
See TracChangeset
for help on using the changeset viewer.