Changeset 87159 in vbox for trunk/src/VBox/Devices/Audio/DrvAudio.cpp
- Timestamp:
- Jan 4, 2021 11:38:37 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r86595 r87159 448 448 return VINF_SUCCESS; 449 449 450 LogRel2(("Audio: %s stream '%s'\n", DrvAudioHlpStreamCmdToStr(enmStreamCmd), pStream->szName));451 452 450 int rc = VINF_SUCCESS; 453 451 452 /* 453 * Whether to propagate commands down to the backend. 454 * 455 * This is needed for critical operations like recording audio if audio input is disabled on a per-driver level. 456 * 457 * Note that not all commands will be covered by this, such as operations like stopping, draining and droppping, 458 * which are considered uncritical and sometimes even are required for certain backends (like DirectSound on Windows). 459 * 460 * The actual stream state will be untouched to not make the state machine handling more complicated than 461 * it already is. 462 * 463 * See #9882. 464 */ 465 const bool fEnabled = ( pStream->enmDir == PDMAUDIODIR_IN 466 && pThis->In.fEnabled) 467 || ( pStream->enmDir == PDMAUDIODIR_OUT 468 && pThis->Out.fEnabled); 469 470 LogRel2(("Audio: %s stream '%s' in backend (%s is %s)\n", DrvAudioHlpStreamCmdToStr(enmStreamCmd), pStream->szName, 471 DrvAudioHlpAudDirToStr(pStream->enmDir), 472 fEnabled ? "enabled" : "disabled")); 454 473 switch (enmStreamCmd) 455 474 { 456 475 case PDMAUDIOSTREAMCMD_ENABLE: 457 476 { 458 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_ENABLE); 477 if (fEnabled) 478 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_ENABLE); 459 479 break; 460 480 } … … 468 488 case PDMAUDIOSTREAMCMD_PAUSE: 469 489 { 470 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_PAUSE); 490 if (fEnabled) /* Needed, as resume below also is being checked for. */ 491 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_PAUSE); 471 492 break; 472 493 } … … 474 495 case PDMAUDIOSTREAMCMD_RESUME: 475 496 { 476 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_RESUME); 497 if (fEnabled) 498 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_RESUME); 477 499 break; 478 500 } … … 939 961 do 940 962 { 941 if ( !pThis->Out.fEnabled 942 || !DrvAudioHlpStreamStatusIsReady(pStream->fStatus)) 963 if (!DrvAudioHlpStreamStatusIsReady(pStream->fStatus)) 943 964 { 944 965 rc = VERR_AUDIO_STREAM_NOT_READY; 966 break; 967 } 968 969 /* If output is disabled on a per-driver level, send data to the bit bucket instead. See #9882. */ 970 if (!pThis->Out.fEnabled) 971 { 972 fToBitBucket = true; 945 973 break; 946 974 } … … 2390 2418 do 2391 2419 { 2392 if ( !pThis->In.fEnabled2393 || !DrvAudioHlpStreamStatusCanRead(pStream->fStatus))2394 {2395 rc = VERR_AUDIO_STREAM_NOT_READY;2396 break;2397 }2398 2399 /*2400 * Read from the parent buffer (that is, the guest buffer) which2401 * should have the audio data in the format the guest needs.2402 */2403 2420 uint32_t cfReadTotal = 0; 2404 2421 2405 2422 const uint32_t cfBuf = AUDIOMIXBUF_B2F(&pStream->Guest.MixBuf, cbBuf); 2406 2423 2407 uint32_t cfToRead = RT_MIN(cfBuf, AudioMixBufLive(&pStream->Guest.MixBuf)); 2408 while (cfToRead) 2409 { 2410 uint32_t cfRead; 2411 rc = AudioMixBufAcquireReadBlock(&pStream->Guest.MixBuf, 2412 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal), 2413 AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfToRead), &cfRead); 2414 if (RT_FAILURE(rc)) 2424 if (pThis->In.fEnabled) /* Input for this audio driver enabled? See #9822. */ 2425 { 2426 if (!DrvAudioHlpStreamStatusCanRead(pStream->fStatus)) 2427 { 2428 rc = VERR_AUDIO_STREAM_NOT_READY; 2415 2429 break; 2430 } 2431 2432 /* 2433 * Read from the parent buffer (that is, the guest buffer) which 2434 * should have the audio data in the format the guest needs. 2435 */ 2436 uint32_t cfToRead = RT_MIN(cfBuf, AudioMixBufLive(&pStream->Guest.MixBuf)); 2437 while (cfToRead) 2438 { 2439 uint32_t cfRead; 2440 rc = AudioMixBufAcquireReadBlock(&pStream->Guest.MixBuf, 2441 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal), 2442 AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfToRead), &cfRead); 2443 if (RT_FAILURE(rc)) 2444 break; 2416 2445 2417 2446 #ifdef VBOX_WITH_STATISTICS 2418 const uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfRead);2419 2420 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead, cbRead);2421 2422 STAM_COUNTER_ADD(&pStream->In.Stats.TotalFramesRead, cfRead);2423 STAM_COUNTER_INC(&pStream->In.Stats.TotalTimesRead);2447 const uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfRead); 2448 2449 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead, cbRead); 2450 2451 STAM_COUNTER_ADD(&pStream->In.Stats.TotalFramesRead, cfRead); 2452 STAM_COUNTER_INC(&pStream->In.Stats.TotalTimesRead); 2424 2453 #endif 2425 Assert(cfToRead >= cfRead); 2426 cfToRead -= cfRead; 2427 2428 cfReadTotal += cfRead; 2429 2430 AudioMixBufReleaseReadBlock(&pStream->Guest.MixBuf, cfRead); 2431 } 2432 2433 if (cfReadTotal) 2434 { 2435 if (pThis->In.Cfg.Dbg.fEnabled) 2436 DrvAudioHlpFileWrite(pStream->In.Dbg.pFileStreamRead, 2437 pvBuf, AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal), 0 /* fFlags */); 2438 2439 AudioMixBufFinish(&pStream->Guest.MixBuf, cfReadTotal); 2454 Assert(cfToRead >= cfRead); 2455 cfToRead -= cfRead; 2456 2457 cfReadTotal += cfRead; 2458 2459 AudioMixBufReleaseReadBlock(&pStream->Guest.MixBuf, cfRead); 2460 } 2461 2462 if (cfReadTotal) 2463 { 2464 if (pThis->In.Cfg.Dbg.fEnabled) 2465 DrvAudioHlpFileWrite(pStream->In.Dbg.pFileStreamRead, 2466 pvBuf, AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal), 0 /* fFlags */); 2467 2468 AudioMixBufFinish(&pStream->Guest.MixBuf, cfReadTotal); 2469 } 2440 2470 } 2441 2471 … … 2719 2749 fEnable ? "Enabling" : "Disabling", enmDir == PDMAUDIODIR_IN ? "input" : "output", pThis->szName)); 2720 2750 2751 /* Update the status first, as this will be checked for in drvAudioStreamControlInternalBackend() below. */ 2752 *pfEnabled = fEnable; 2753 2721 2754 PPDMAUDIOSTREAM pStream; 2722 2755 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node) … … 2725 2758 continue; 2726 2759 2727 int rc2 = drvAudioStreamControlInternal(pThis, pStream, 2728 fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE); 2760 /* Note: Only enable / disable the backend, do *not* change the stream's internal status. 2761 * Callers (device emulation, mixer, ...) from outside will not see any status or behavior change, 2762 * to not confuse the rest of the state machine. 2763 * 2764 * When disabling: 2765 * - playing back audo data would go to /dev/null 2766 * - recording audio data would return silence instead 2767 * 2768 * See #9882. 2769 */ 2770 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, 2771 fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE); 2729 2772 if (RT_FAILURE(rc2)) 2730 2773 { … … 2743 2786 /* Keep going. */ 2744 2787 } 2745 2746 *pfEnabled = fEnable;2747 2788 } 2748 2789 … … 2864 2905 uint32_t cbReadable = 0; 2865 2906 2907 /* All input streams for this driver disabled? See #9882. */ 2908 const bool fDisabled = !pThis->In.fEnabled; 2909 2866 2910 if ( pThis->pHostDrvAudio 2867 && DrvAudioHlpStreamStatusCanRead(pStream->fStatus)) 2911 && ( DrvAudioHlpStreamStatusCanRead(pStream->fStatus) 2912 || fDisabled) 2913 ) 2868 2914 { 2869 2915 const uint32_t cfReadable = AudioMixBufLive(&pStream->Guest.MixBuf); … … 2881 2927 * Reading the actual data from a stream then will return silence then. 2882 2928 */ 2883 if (!DrvAudioHlpStreamStatusCanRead( 2884 pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend))) 2929 if ( !DrvAudioHlpStreamStatusCanRead( 2930 pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend) 2931 || fDisabled)) 2885 2932 { 2886 2933 cbReadable = DrvAudioHlpNanoToBytes(RTTimeNanoTS() - pStream->tsLastReadWrittenNs, 2887 2934 &pStream->Host.Cfg.Props); 2888 Log3Func(("[%s] Backend stream not ready , returning silence\n", pStream->szName));2935 Log3Func(("[%s] Backend stream not ready or driver has disabled audio input, returning silence\n", pStream->szName)); 2889 2936 } 2890 2937 }
Note:
See TracChangeset
for help on using the changeset viewer.