Changeset 70974 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Feb 12, 2018 3:18:01 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 120819
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r70967 r70974 152 152 /** Total amount (in bytes) written. */ 153 153 uint64_t cbWritten; 154 /** Total amount (in bytes) played (to the DirectSound buffer). */ 155 uint64_t cbPlayed; 154 156 /** Flag indicating whether playback was (re)started. */ 155 157 bool fFirstPlayback; … … 680 682 bd.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; 681 683 682 bd.dwBufferBytes = DrvAudioHlp CalcBitrate(&pCfgReq->Props) / 8;684 bd.dwBufferBytes = DrvAudioHlpMsToBytes(&pCfgReq->Props, pThis->Cfg.msLatencyOut); 683 685 684 686 DSLOG(("DSound: Playback buffer is %ld bytes\n", bd.dwBufferBytes)); … … 756 758 RTCritSectEnter(&pThis->CritSect); 757 759 758 rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->cbBufSize );760 rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->cbBufSize * 2 /* Double buffering */); 759 761 AssertRC(rc); 760 762 … … 778 780 dsPosNotify[2].hEventNotify = pThis->aEvents[DSOUNDEVENT_OUTPUT]; 779 781 780 hr = IDirectSoundNotify_SetNotificationPositions(pNotify, 3 /* Count */, dsPosNotify);782 hr = IDirectSoundNotify_SetNotificationPositions(pNotify, RT_ELEMENTS(dsPosNotify), dsPosNotify); 781 783 if (FAILED(hr)) 782 784 DSLOGREL(("DSound: Setting playback position notification failed with %Rhrc\n", hr)); … … 1122 1124 bd.dwSize = sizeof(bd); 1123 1125 bd.lpwfxFormat = &wfx; 1124 bd.dwBufferBytes = DrvAudioHlp CalcBitrate(&pCfgReq->Props) / 8;1126 bd.dwBufferBytes = DrvAudioHlpMsToBytes(&pCfgReq->Props, pThis->Cfg.msLatencyIn); 1125 1127 1126 1128 DSLOG(("DSound: Capture buffer is %ld bytes\n", bd.dwBufferBytes)); … … 1204 1206 pStreamDS->cbBufSize = bc.dwBufferBytes; 1205 1207 1206 rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->cbBufSize );1208 rc = RTCircBufCreate(&pStreamDS->pCircBuf, pStreamDS->cbBufSize * 2 /* Double buffering */); 1207 1209 AssertRC(rc); 1208 1210 … … 1544 1546 pStreamDS->Out.offPlayCursorLastPending = 0; 1545 1547 pStreamDS->Out.cbWritten = 0; 1548 pStreamDS->Out.cbPlayed = 0; 1546 1549 pStreamDS->Out.fFirstPlayback = true; 1547 1550 pStreamDS->Out.tsLastPlayMs = 0; … … 1656 1659 Assert(cbWrittenTotal <= cxBuf); 1657 1660 1661 pStreamDS->Out.cbWritten += cbWrittenTotal; 1662 1658 1663 if ( pStreamDS->Out.fFirstPlayback 1659 && RTCircBufUsed(pCircBuf))1664 && pStreamDS->Out.cbWritten >= pStreamDS->cbBufSize) 1660 1665 { 1661 1666 BOOL fRc = SetEvent(pThis->aEvents[DSOUNDEVENT_OUTPUT]); 1662 1667 RT_NOREF(fRc); 1663 1668 Assert(fRc); 1664 1665 // Log3Func(("cxBuf=%RU32, cbWrittenTotal=%RU32, %RU64ms\n", cxBuf, cbWrittenTotal, tsNow - s_lastplayed));1666 1669 } 1667 1670 … … 2030 2033 HRESULT hr; 2031 2034 2035 DWORD offPlayCursor, offWriteCursor; 2036 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &offPlayCursor, &offWriteCursor); 2037 if (FAILED(hr)) 2038 break; 2039 2032 2040 DWORD cbFree, cbRemaining; 2033 2041 if (pStreamDS->Out.fFirstPlayback) 2034 2042 { 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); 2044 2045 } 2045 2046 else 2046 2047 { 2047 DWORD offPlayCursor;2048 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &offPlayCursor, NULL);2049 if (FAILED(hr))2050 break;2051 2052 2048 cbFree = dsoundRingDistance(offPlayCursor, pStreamDS->Out.offWritePos, pStreamDS->cbBufSize); 2053 2049 cbRemaining = dsoundRingDistance(pStreamDS->Out.offWritePos, offPlayCursor, pStreamDS->cbBufSize); … … 2058 2054 2059 2055 DWORD cbUsed = (uint32_t)RTCircBufUsed(pCircBuf); 2056 DWORD cbToPlay = RT_MIN(cbFree, cbUsed); 2057 2060 2058 if ( !cbUsed 2061 || pStreamDS->Out.cUnderruns < 32) /** @todo Make this configurable. */ 2059 && pStreamDS->Out.cbWritten 2060 && pStreamDS->Out.cUnderruns < 32) /** @todo Make this configurable. */ 2062 2061 { 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)); 2064 2065 pStreamDS->Out.cUnderruns++; 2065 2066 } 2066 2067 DWORD cbToPlay = RT_MIN(cbFree, cbUsed);2068 2069 Log3Func(("cbUsed=%ld, cbToPlay=%ld\n", cbUsed, cbToPlay));2070 2067 2071 2068 while (cbToPlay) … … 2099 2096 cbToPlay -= (uint32_t)cbBuf; 2100 2097 2101 pStreamDS->Out.cb Written+= cb1 + cb2;2098 pStreamDS->Out.cbPlayed += cb1 + cb2; 2102 2099 } 2103 2100 … … 2105 2102 } 2106 2103 2107 if (pStreamDS->Out.fFirstPlayback) 2104 if ( pStreamDS->Out.fFirstPlayback 2105 && RTCircBufUsed(pCircBuf) >= pStreamDS->cbBufSize) 2108 2106 { 2109 2107 DWORD fFlags = DSCBSTART_LOOPING; … … 2125 2123 { 2126 2124 DSLOG(("DSound: Started playing output\n")); 2127 pStreamDS->Out.fFirstPlayback 2125 pStreamDS->Out.fFirstPlayback = false; 2128 2126 } 2129 2127 } … … 2131 2129 { 2132 2130 if ( !RTCircBufUsed(pCircBuf) 2133 && !cbRemaining)2131 && pStreamDS->Out.cbPlayed == pStreamDS->Out.cbWritten) 2134 2132 { 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 2135 2154 DSLOG(("DSound: Stopping playing output\n")); 2136 2155 hr = IDirectSoundBuffer8_Stop(pDSB); … … 2309 2328 { 2310 2329 pStreamDS->pCfg = DrvAudioHlpStreamCfgDup(pCfgAcq); 2311 if (!pStreamDS->pCfg) 2330 if (pStreamDS->pCfg) 2331 { 2332 rc = RTCritSectInit(&pStreamDS->CritSect); 2333 } 2334 else 2312 2335 rc = VERR_NO_MEMORY; 2313 2336 } … … 2338 2361 if (RT_SUCCESS(rc)) 2339 2362 { 2363 rc = RTCritSectDelete(&pStreamDS->CritSect); 2364 2340 2365 DrvAudioHlpStreamCfgFree(pStreamDS->pCfg); 2341 2366 pStreamDS->pCfg = NULL; … … 2430 2455 pStreamDS->Out.tsLastPlayMs = tsNowMs; 2431 2456 2457 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 2458 2432 2459 const uint64_t diffLastPlayMs = tsNowMs - pStreamDS->Out.tsLastPlayMs; 2433 const uint64_t msThreshold = 100;2460 const uint64_t msThreshold = pThis->Cfg.msLatencyOut; 2434 2461 2435 2462 Log3Func(("diffLastPlayMs=%RU64ms\n", diffLastPlayMs)); … … 2437 2464 cbPending = (diffLastPlayMs >= msThreshold) ? 0 : 1; 2438 2465 2439 //if (!cbPending) 2440 // directSoundPlayStop(pThis, pStreamDS, false /* fFlush */); 2466 pStreamDS->Out.tsLastPlayMs = tsNowMs; 2441 2467 } 2442 2468
Note:
See TracChangeset
for help on using the changeset viewer.