VirtualBox

Changeset 70974 in vbox


Ignore:
Timestamp:
Feb 12, 2018 3:18:01 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
120819
Message:

Audio/DrvHostDSound.cpp: Fixed playback start latency and made some estimates about when actually stopping a (streaming) output buffer.

File:
1 edited

Legend:

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

    r70967 r70974  
    152152            /** Total amount (in bytes) written. */
    153153            uint64_t                    cbWritten;
     154            /** Total amount (in bytes) played (to the DirectSound buffer). */
     155            uint64_t                    cbPlayed;
    154156            /** Flag indicating whether playback was (re)started. */
    155157            bool                        fFirstPlayback;
     
    680682        bd.dwFlags    |= DSBCAPS_CTRLPOSITIONNOTIFY;
    681683
    682         bd.dwBufferBytes = DrvAudioHlpCalcBitrate(&pCfgReq->Props) / 8;
     684        bd.dwBufferBytes = DrvAudioHlpMsToBytes(&pCfgReq->Props, pThis->Cfg.msLatencyOut);
    683685
    684686        DSLOG(("DSound: Playback buffer is %ld bytes\n", bd.dwBufferBytes));
     
    756758        RTCritSectEnter(&pThis->CritSect);
    757759
    758         rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->cbBufSize);
     760        rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->cbBufSize * 2 /* Double buffering */);
    759761        AssertRC(rc);
    760762
     
    778780            dsPosNotify[2].hEventNotify = pThis->aEvents[DSOUNDEVENT_OUTPUT];
    779781
    780             hr = IDirectSoundNotify_SetNotificationPositions(pNotify, 3 /* Count */, dsPosNotify);
     782            hr = IDirectSoundNotify_SetNotificationPositions(pNotify, RT_ELEMENTS(dsPosNotify), dsPosNotify);
    781783            if (FAILED(hr))
    782784                DSLOGREL(("DSound: Setting playback position notification failed with %Rhrc\n", hr));
     
    11221124        bd.dwSize        = sizeof(bd);
    11231125        bd.lpwfxFormat   = &wfx;
    1124         bd.dwBufferBytes = DrvAudioHlpCalcBitrate(&pCfgReq->Props) / 8;
     1126        bd.dwBufferBytes = DrvAudioHlpMsToBytes(&pCfgReq->Props, pThis->Cfg.msLatencyIn);
    11251127
    11261128        DSLOG(("DSound: Capture buffer is %ld bytes\n", bd.dwBufferBytes));
     
    12041206        pStreamDS->cbBufSize     = bc.dwBufferBytes;
    12051207
    1206         rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->cbBufSize);
     1208        rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->cbBufSize * 2 /* Double buffering */);
    12071209        AssertRC(rc);
    12081210
     
    15441546    pStreamDS->Out.offPlayCursorLastPending = 0;
    15451547    pStreamDS->Out.cbWritten = 0;
     1548    pStreamDS->Out.cbPlayed = 0;
    15461549    pStreamDS->Out.fFirstPlayback = true;
    15471550    pStreamDS->Out.tsLastPlayMs = 0;
     
    16561659    Assert(cbWrittenTotal <= cxBuf);
    16571660
     1661    pStreamDS->Out.cbWritten += cbWrittenTotal;
     1662
    16581663    if (   pStreamDS->Out.fFirstPlayback
    1659         && RTCircBufUsed(pCircBuf))
     1664        && pStreamDS->Out.cbWritten >= pStreamDS->cbBufSize)
    16601665    {
    16611666        BOOL fRc = SetEvent(pThis->aEvents[DSOUNDEVENT_OUTPUT]);
    16621667        RT_NOREF(fRc);
    16631668        Assert(fRc);
    1664 
    1665 //        Log3Func(("cxBuf=%RU32, cbWrittenTotal=%RU32, %RU64ms\n", cxBuf, cbWrittenTotal, tsNow - s_lastplayed));
    16661669    }
    16671670
     
    20302033                    HRESULT hr;
    20312034
     2035                    DWORD offPlayCursor, offWriteCursor;
     2036                    hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &offPlayCursor, &offWriteCursor);
     2037                    if (FAILED(hr))
     2038                        break;
     2039
    20322040                    DWORD cbFree, cbRemaining;
    20332041                    if (pStreamDS->Out.fFirstPlayback)
    20342042                    {
    2035                         DWORD offWriteCursor;
    2036                         hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, NULL, &offWriteCursor);
    2037                         if (FAILED(hr))
    2038                             break;
    2039 
    2040                         pStreamDS->Out.offWritePos = offWriteCursor;
    2041 
    2042                         cbFree      = pStreamDS->cbBufSize;
    2043                         cbRemaining = pStreamDS->cbBufSize;
     2043                        cbRemaining = 0;
     2044                        cbFree      = dsoundRingDistance(pStreamDS->Out.offWritePos, 0, pStreamDS->cbBufSize);
    20442045                    }
    20452046                    else
    20462047                    {
    2047                         DWORD offPlayCursor;
    2048                         hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &offPlayCursor, NULL);
    2049                         if (FAILED(hr))
    2050                             break;
    2051 
    20522048                        cbFree      = dsoundRingDistance(offPlayCursor, pStreamDS->Out.offWritePos, pStreamDS->cbBufSize);
    20532049                        cbRemaining = dsoundRingDistance(pStreamDS->Out.offWritePos, offPlayCursor, pStreamDS->cbBufSize);
     
    20582054
    20592055                    DWORD cbUsed   = (uint32_t)RTCircBufUsed(pCircBuf);
     2056                    DWORD cbToPlay = RT_MIN(cbFree, cbUsed);
     2057
    20602058                    if (   !cbUsed
    2061                         || pStreamDS->Out.cUnderruns < 32) /** @todo Make this configurable. */
     2059                        && pStreamDS->Out.cbWritten
     2060                        && pStreamDS->Out.cUnderruns < 32) /** @todo Make this configurable. */
    20622061                    {
    2063                         DSLOG(("DSound: Warning: No more playback data available within time (%RU32 bytes free)\n", cbFree));
     2062                        //DSLOG(("DSound: Warning: No more playback data available within time (%RU32 bytes free)\n", cbFree));
     2063                        Log3Func(("Underrun (cbFree=%ld, cbRemaining=%ld, cbUsed=%ld, cbToPlay=%ld, offPlay=%ld, offWrite=%ld)\n",
     2064                                  cbFree, cbRemaining, cbUsed, cbToPlay, offPlayCursor, offWriteCursor));
    20642065                        pStreamDS->Out.cUnderruns++;
    20652066                    }
    2066 
    2067                     DWORD cbToPlay = RT_MIN(cbFree, cbUsed);
    2068 
    2069                     Log3Func(("cbUsed=%ld, cbToPlay=%ld\n", cbUsed, cbToPlay));
    20702067
    20712068                    while (cbToPlay)
     
    20992096                            cbToPlay -= (uint32_t)cbBuf;
    21002097
    2101                             pStreamDS->Out.cbWritten += cb1 + cb2;
     2098                            pStreamDS->Out.cbPlayed += cb1 + cb2;
    21022099                        }
    21032100
     
    21052102                    }
    21062103
    2107                     if (pStreamDS->Out.fFirstPlayback)
     2104                    if (   pStreamDS->Out.fFirstPlayback
     2105                        && RTCircBufUsed(pCircBuf) >= pStreamDS->cbBufSize)
    21082106                    {
    21092107                        DWORD fFlags = DSCBSTART_LOOPING;
     
    21252123                        {
    21262124                            DSLOG(("DSound: Started playing output\n"));
    2127                             pStreamDS->Out.fFirstPlayback   = false;
     2125                            pStreamDS->Out.fFirstPlayback = false;
    21282126                        }
    21292127                    }
     
    21312129                    {
    21322130                        if (   !RTCircBufUsed(pCircBuf)
    2133                             && !cbRemaining)
     2131                            && pStreamDS->Out.cbPlayed == pStreamDS->Out.cbWritten)
    21342132                        {
     2133                            Assert(pStreamDS->Out.cbPlayed == pStreamDS->Out.cbWritten);
     2134
     2135                            Log3Func(("Stopping (cbFree=%ld, cbRemaining=%ld, cbUsed=%ld, cbToPlay=%ld, offPlay=%ld, offWrite=%ld)\n",
     2136                                      cbFree, cbRemaining, cbUsed, cbToPlay, offPlayCursor, offWriteCursor));
     2137
     2138                            /* As we're using a streaming buffer and DirectSound apparently has no clean way of figuring out
     2139                             * when such a buffer was played back fully, we need to make a guess ourselves:
     2140                             *
     2141                             * See if there's any data left between the play and write cursors and calculate some rough estimate
     2142                             * how long we have to wait before actually stopping the buffer.
     2143                             *
     2144                             * Sleeping here is fine, as we're running in a (dedicated) thread anyway. */
     2145                            const DWORD cbRemaining = dsoundRingDistance(offWriteCursor, offPlayCursor, pStreamDS->cbBufSize);
     2146                            uint64_t msWait = cbRemaining / DrvAudioHlpMsToBytes(&pStreamDS->pCfg->Props, 1 /* ms */);
     2147
     2148                            if (msWait)
     2149                            {
     2150                                Log3Func(("Waiting %RU64ms (%ld bytes)\n", msWait, cbRemaining));
     2151                                RTThreadSleep(msWait);
     2152                            }
     2153
    21352154                            DSLOG(("DSound: Stopping playing output\n"));
    21362155                            hr = IDirectSoundBuffer8_Stop(pDSB);
     
    23092328    {
    23102329        pStreamDS->pCfg = DrvAudioHlpStreamCfgDup(pCfgAcq);
    2311         if (!pStreamDS->pCfg)
     2330        if (pStreamDS->pCfg)
     2331        {
     2332            rc = RTCritSectInit(&pStreamDS->CritSect);
     2333        }
     2334        else
    23122335            rc = VERR_NO_MEMORY;
    23132336    }
     
    23382361    if (RT_SUCCESS(rc))
    23392362    {
     2363        rc = RTCritSectDelete(&pStreamDS->CritSect);
     2364
    23402365        DrvAudioHlpStreamCfgFree(pStreamDS->pCfg);
    23412366        pStreamDS->pCfg = NULL;
     
    24302455                pStreamDS->Out.tsLastPlayMs = tsNowMs;
    24312456
     2457            PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
     2458
    24322459            const uint64_t diffLastPlayMs = tsNowMs - pStreamDS->Out.tsLastPlayMs;
    2433             const uint64_t msThreshold    = 100;
     2460            const uint64_t msThreshold    = pThis->Cfg.msLatencyOut;
    24342461
    24352462            Log3Func(("diffLastPlayMs=%RU64ms\n", diffLastPlayMs));
     
    24372464            cbPending = (diffLastPlayMs >= msThreshold) ? 0 : 1;
    24382465
    2439             //if (!cbPending)
    2440             //    directSoundPlayStop(pThis, pStreamDS, false /* fFlush */);
     2466            pStreamDS->Out.tsLastPlayMs = tsNowMs;
    24412467        }
    24422468
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