Changeset 88375 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Apr 6, 2021 8:31:12 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143622
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r88362 r88375 91 91 uintptr_t uMagic; 92 92 93 /** List entry (some DrvAudio internal list). */93 /** List entry in DRVAUDIO::lstStreams. */ 94 94 RTLISTNODE ListEntry; 95 95 … … 314 314 STAMCOUNTER StatsReBuffering; 315 315 } Out; 316 317 /** Handle to the disable-iteration timer. */ 318 TMTIMERHANDLE hTimer; 319 /** Set if hTimer is armed. */ 320 bool volatile fTimerArmed; 321 /** Unique name for the the disable-iteration timer. */ 322 char szTimerName[23]; 323 316 324 #ifdef VBOX_WITH_STATISTICS 317 325 /** Statistics for the statistics manager (STAM). */ … … 336 344 static void drvAudioStreamFree(PDRVAUDIOSTREAM pStream); 337 345 static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 338 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 346 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, bool fWorkMixBuf); 347 static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcFramesPlayed); 339 348 static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 340 349 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); … … 651 660 LogFunc(("[%s] Pending disable/pause\n", pStreamEx->Core.szName)); 652 661 pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE; 662 663 /* Schedule a follow up timer to the pending-disable state. We cannot rely 664 on the device to provide further callouts to finish the state transition. 665 10ms is taking out of thin air and may be too course grained, we should 666 really consider the amount of unplayed buffer in the backend and what not... */ 667 if (!pThis->fTimerArmed) 668 { 669 LogFlowFunc(("Arming emergency pending-disable hack...\n")); 670 int rc2 = PDMDrvHlpTimerSetMillies(pThis->pDrvIns, pThis->hTimer, 10 /*ms*/); 671 AssertRC(rc2); 672 pThis->fTimerArmed = true; 673 } 653 674 } 654 675 … … 730 751 return VINF_SUCCESS; 731 752 732 int rc = VINF_SUCCESS;733 753 734 754 /* … … 753 773 PDMAudioDirGetName(pStreamEx->Core.enmDir), 754 774 fEnabled ? "enabled" : "disabled")); 775 int rc = VINF_SUCCESS; 755 776 switch (enmStreamCmd) 756 777 { … … 1180 1201 AssertRCReturn(rc, rc); 1181 1202 1182 rc = drvAudioStreamIterateInternal(pThis, pStreamEx );1203 rc = drvAudioStreamIterateInternal(pThis, pStreamEx, false /*fWorkMixBuf*/); /** @todo r=bird: why didn't it work the mixing buffer initially. We can probably set this to true... It may cause repeat work though. */ 1183 1204 1184 1205 RTCritSectLeave(&pThis->CritSect); … … 1264 1285 /** 1265 1286 * Does one iteration of an audio stream. 1287 * 1266 1288 * This function gives the backend the chance of iterating / altering data and 1267 1289 * does the actual mixing between the guest <-> host mixing buffers. … … 1270 1292 * @param pThis Pointer to driver instance. 1271 1293 * @param pStreamEx Stream to iterate. 1272 */ 1273 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx) 1294 * @param fWorkMixBuf Push data from the mixing buffer to the backend. 1295 * @todo r=bird: Don't know why the default behavior isn't to push data into 1296 * the backend... We'll never get out of the pending-disable state if 1297 * the mixing buffer doesn't empty out. 1298 */ 1299 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, bool fWorkMixBuf) 1274 1300 { 1275 1301 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 1308 1334 /* No audio frames to transfer from guest to host (anymore)? 1309 1335 * Then try closing this stream if marked so in the next block. */ 1310 const uint32_t cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf); 1336 uint32_t cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf); 1337 if (cFramesLive && fWorkMixBuf) 1338 { 1339 uint32_t cIgnored = 0; 1340 drvAudioStreamPlayLocked(pThis, pStreamEx, &cIgnored); 1341 1342 cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf); 1343 } 1344 1311 1345 fTryClosePending = cFramesLive == 0; 1312 1346 Log3Func(("[%s] fTryClosePending=%RTbool, cFramesLive=%RU32\n", pStreamEx->Core.szName, fTryClosePending, cFramesLive)); … … 1358 1392 1359 1393 return rc; 1394 } 1395 1396 /** 1397 * @callback_method_impl{FNTMTIMERDRV} 1398 */ 1399 static DECLCALLBACK(void) drvAudioEmergencyIterateTimer(PPDMDRVINS pDrvIns, TMTIMERHANDLE hTimer, void *pvUser) 1400 { 1401 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 1402 RT_NOREF(hTimer, pvUser); 1403 RTCritSectEnter(&pThis->CritSect); 1404 1405 /* 1406 * Iterate any stream with the pending-disable flag set. 1407 */ 1408 uint32_t cMilliesToNext = 0; 1409 PDRVAUDIOSTREAM pStreamEx, pStreamExNext; 1410 RTListForEachSafe(&pThis->lstStreams, pStreamEx, pStreamExNext, DRVAUDIOSTREAM, ListEntry) 1411 { 1412 if ( pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC 1413 && pStreamEx->Core.cRefs >= 1) 1414 { 1415 if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE) 1416 { 1417 drvAudioStreamIterateInternal(pThis, pStreamEx, true /*fWorkMixBuf*/); 1418 1419 if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE) 1420 cMilliesToNext = 10; 1421 } 1422 } 1423 } 1424 1425 /* 1426 * Re-arm the timer if we still got streams in the pending state. 1427 */ 1428 if (cMilliesToNext) 1429 { 1430 pThis->fTimerArmed = true; 1431 PDMDrvHlpTimerSetMillies(pDrvIns, pThis->hTimer, cMilliesToNext); 1432 } 1433 else 1434 pThis->fTimerArmed = false; 1435 1436 RTCritSectLeave(&pThis->CritSect); 1360 1437 } 1361 1438 … … 3833 3910 STAMUNIT_NS_PER_CALL, "Profiling of output data processing."); 3834 3911 #endif 3912 3913 /* 3914 * Create a timer to do finish closing output streams in PENDING_DISABLE state. 3915 * 3916 * The device won't call us again after it has disabled a the stream and this is 3917 * a real problem for truely cyclic buffer backends like DSound which will just 3918 * continue to loop and loop if not stopped. 3919 */ 3920 RTStrPrintf(pThis->szTimerName, sizeof(pThis->szTimerName), "AudioIterate-%u", pDrvIns->iInstance); 3921 rc = PDMDrvHlpTMTimerCreate(pDrvIns, TMCLOCK_VIRTUAL, drvAudioEmergencyIterateTimer, NULL /*pvUser*/, 3922 0 /*fFlags*/, pThis->szTimerName, &pThis->hTimer); 3923 AssertRCReturn(rc, rc); 3835 3924 3836 3925 /*
Note:
See TracChangeset
for help on using the changeset viewer.