VirtualBox

Changeset 73585 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 9, 2018 12:32:51 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
124224
Message:

Audio/DrvAudio: Handling returning silence for backends which cannot / will not provide (enough) input data in drvAudioStreamRead(). That way it's always guaranteed the device DMA gets enough data, no matter what happens on the backend side.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r73583 r73585  
    22772277        }
    22782278
    2279         if (   pThis->pHostDrvAudio
    2280             && pThis->pHostDrvAudio->pfnGetStatus
    2281             && pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_IN) != PDMAUDIOBACKENDSTS_RUNNING)
    2282         {
    2283             rc = VERR_AUDIO_STREAM_NOT_READY;
    2284             break;
    2285         }
    2286 
    22872279        /*
    22882280         * Read from the parent buffer (that is, the guest buffer) which
     
    22912283        uint32_t cfReadTotal = 0;
    22922284
    2293         uint32_t cfToRead = RT_MIN(AUDIOMIXBUF_B2F(&pStream->Guest.MixBuf, cbBuf), AudioMixBufLive(&pStream->Guest.MixBuf));
     2285        const uint32_t cfBuf = AUDIOMIXBUF_B2F(&pStream->Guest.MixBuf, cbBuf);
     2286
     2287        uint32_t cfToRead = RT_MIN(cfBuf, AudioMixBufLive(&pStream->Guest.MixBuf));
    22942288        while (cfToRead)
    22952289        {
     
    23152309        }
    23162310
     2311        /* If we were not able to read as much data as requested, fill up the returned
     2312         * data with silence.
     2313         *
     2314         * This is needed to keep the device emulation DMA transfers up and running at a constant rate. */
     2315        if (cfReadTotal < cfBuf)
     2316        {
     2317            Log3Func(("[%s] Filling in silence (%RU64ms / %RU64ms)\n", pStream->szName,
     2318                      DrvAudioHlpFramesToMilli(cfBuf - cfReadTotal, &pStream->Guest.Cfg.Props),
     2319                      DrvAudioHlpFramesToMilli(cfBuf, &pStream->Guest.Cfg.Props)));
     2320
     2321            DrvAudioHlpClearBuf(&pStream->Guest.Cfg.Props,
     2322                                (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal),
     2323                                AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfBuf - cfReadTotal),
     2324                                cfBuf - cfReadTotal);
     2325
     2326            cfReadTotal = cfBuf;
     2327        }
     2328
    23172329        if (cfReadTotal)
    23182330        {
     
    23262338        }
    23272339
     2340        pStream->tsLastReadWrittenNs = RTTimeNanoTS();
     2341
     2342        Log3Func(("[%s] fEnabled=%RTbool, cbReadTotal=%RU32, rc=%Rrc\n", pStream->szName, pThis->In.fEnabled, cbReadTotal, rc));
     2343
    23282344    } while (0);
    23292345
    2330     Log3Func(("[%s] fEnabled=%RTbool, cbReadTotal=%RU32, rc=%Rrc\n", pStream->szName, pThis->In.fEnabled, cbReadTotal, rc));
    23312346
    23322347    int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    27282743        const uint32_t cfReadable = AudioMixBufLive(&pStream->Guest.MixBuf);
    27292744
    2730         Log3Func(("[%s] cfReadable=%RU32 (%zu bytes)\n", pStream->szName, cfReadable,
    2731                   AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadable)));
    2732 
    27332745        cbReadable = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadable);
    2734     }
    2735 
     2746
     2747        if (!cbReadable)
     2748        {
     2749            /*
     2750             * If Nothing is readable, check if the stream on the backend side is ready to be read from.
     2751             * If it isn't, return the number of bytes readable since the last read from this stream.
     2752             *
     2753             * This is needed for backends (e.g. VRDE) which do not provide any input data in certain
     2754             * situations, but the device emulation needs input data to keep the DMA transfers moving.
     2755             * Reading the actual data from a stream then will return silence then.
     2756             */
     2757            if (!DrvAudioHlpStreamStatusCanRead(
     2758                    pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend)))
     2759            {
     2760                cbReadable = DrvAudioHlpNanoToBytes(RTTimeNanoTS() - pStream->tsLastReadWrittenNs,
     2761                                                    &pStream->Host.Cfg.Props);
     2762                Log3Func(("[%s] Backend stream not ready, returning silence\n", pStream->szName));
     2763            }
     2764        }
     2765
     2766        /* Make sure to align the readable size to the guest's frame size. */
     2767        cbReadable = DrvAudioHlpBytesAlign(cbReadable, &pStream->Guest.Cfg.Props);
     2768    }
     2769
     2770        Log3Func(("[%s] cbReadable=%RU32 (%RU64ms)\n",
     2771                  pStream->szName, cbReadable, DrvAudioHlpBytesToMilli(cbReadable, &pStream->Host.Cfg.Props)));
     2772   
    27362773    rc2 = RTCritSectLeave(&pThis->CritSect);
    27372774    AssertRC(rc2);
     
    27902827    AssertRC(rc2);
    27912828
    2792     /* If the connector is ready to operate, also make sure to ask the backend. */
    27932829    PDMAUDIOSTREAMSTS stsStream = pStream->fStatus;
    2794     if (DrvAudioHlpStreamStatusIsReady(stsStream))
    2795         stsStream = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend);
    27962830
    27972831#ifdef LOG_ENABLED
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette