- Timestamp:
- Aug 1, 2018 12:46:06 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 124043
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r73408 r73421 922 922 return 0; 923 923 924 const uint64_t deltaLastReadWriteNs = RTTimeNanoTS() - pSink->tsLastReadWrittenNs; 925 924 926 uint32_t cbWritable = 0; 925 927 … … 931 933 #else 932 934 /* Return how much data we expect since the last write. */ 933 cbWritable = DrvAudioHlpMilliToBytes(RTTimeMilliTS() - pSink->tsLastReadWrittenMs, &pSink->PCMProps); 935 cbWritable = DrvAudioHlpNanoToBytes(deltaLastReadWriteNs, &pSink->PCMProps); 936 cbWritable = DrvAudioHlpBytesAlign(cbWritable, &pSink->PCMProps); 934 937 #endif 935 938 } 936 939 937 Log3Func((" [%s] cbWritable=%RU32\n", pSink->pszName, cbWritable));940 Log3Func(("Mixer: [%s] cbWritable=%RU32 (%RU64ms)\n", pSink->pszName, cbWritable, deltaLastReadWriteNs / RT_NS_1MS_64)); 938 941 939 942 int rc2 = RTCritSectLeave(&pSink->CritSect); … … 1158 1161 1159 1162 /* Update our last read time stamp. */ 1160 pSink->tsLastReadWritten Ms = RTTimeMilliTS();1163 pSink->tsLastReadWrittenNs = RTTimeNanoTS(); 1161 1164 1162 1165 #ifdef VBOX_AUDIO_MIXER_DEBUG … … 1739 1742 1740 1743 cbWritten += (uint32_t)cbChunk; 1744 Assert(cbWritten <= cbBuf); 1741 1745 1742 1746 Assert(cbToWrite >= cbChunk); … … 1745 1749 1746 1750 if (cbWritten < cbBuf) 1751 { 1747 1752 LogFunc(("[%s] Warning: Only written %RU32/%RU32 bytes for stream '%s'\n", 1748 1753 pSink->pszName, cbWritten, cbBuf, pMixStream->pszName)); 1749 1750 if (!pMixStream->tsLastReadWrittenMs) 1751 pMixStream->tsLastReadWrittenMs = RTTimeMilliTS(); 1752 1753 pMixStream->tsLastReadWrittenMs = RTTimeMilliTS(); 1754 1755 const uint32_t cbWritableStream = pMixStream->pConn->pfnStreamGetWritable(pMixStream->pConn, pMixStream->pStream); 1756 cbToWrite = RT_MIN(cbWritableStream, (uint32_t)RTCircBufUsed(pCircBuf)); 1754 LogRel2(("Audio: Buffer overrun for mixer sink '%s', stream '%s'\n", pSink->pszName, pMixStream->pszName)); 1755 #ifdef DEBUG_andy 1756 AssertFailed(); 1757 #endif 1758 } 1759 1760 if (cbWritten) /* Update the mixer stream's last written time stamp. */ 1761 pMixStream->tsLastReadWrittenNs = RTTimeNanoTS(); 1762 1763 cbToWrite = RT_MIN(pMixStream->pConn->pfnStreamGetWritable(pMixStream->pConn, pMixStream->pStream), 1764 (uint32_t)RTCircBufUsed(pCircBuf)); 1765 cbToWrite = DrvAudioHlpBytesAlign(cbToWrite, &pSink->PCMProps); 1757 1766 1758 1767 int rc2 = VINF_SUCCESS; … … 1774 1783 if ( !cbWritten 1775 1784 || cbWritten < cbChunk) 1785 { 1786 #ifdef DEBUG_andy 1787 AssertFailed(); 1788 #endif 1776 1789 break; 1790 } 1777 1791 1778 1792 if (RT_FAILURE(rc2)) … … 1790 1804 } 1791 1805 1792 /* Update ourlast written time stamp. */1793 pSink->tsLastReadWritten Ms = RTTimeMilliTS();1806 /* Update the sink's last written time stamp. */ 1807 pSink->tsLastReadWrittenNs = RTTimeNanoTS(); 1794 1808 1795 1809 if (pcbWritten) -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r73403 r73421 72 72 /** Pointer to PDM audio stream this mixer stream handles. */ 73 73 PPDMAUDIOSTREAM pStream; 74 /** Last read (recording) / written (playback) timestamp (in ms). */75 uint64_t tsLastReadWritten Ms;74 /** Last read (recording) / written (playback) timestamp (in ns). */ 75 uint64_t tsLastReadWrittenNs; 76 76 /** The stream's circular buffer for temporarily 77 77 * holding (raw) device audio data. */ … … 203 203 /** Timestamp since last update (in ms). */ 204 204 uint64_t tsLastUpdatedMs; 205 /** Last read (recording) / written (playback) timestamp (in ms). */206 uint64_t tsLastReadWritten Ms;205 /** Last read (recording) / written (playback) timestamp (in ns). */ 206 uint64_t tsLastReadWrittenNs; 207 207 #ifdef VBOX_AUDIO_MIXER_DEBUG 208 208 struct -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r73408 r73421 666 666 */ 667 667 668 /* Check if the backend did return sane values and correct if necessary. 669 * Should never happen with our own backends, but you never know ... */ 670 if (CfgHostAcq.Backend.cfBufferSize < CfgHostAcq.Backend.cfPreBuf) 671 { 672 LogRel2(("Audio: Warning: Pre-buffering size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), " 673 "setting pre-buffering size to %RU32 frames\n", 674 CfgHostAcq.Backend.cfPreBuf, pHstStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize)); 675 CfgHostAcq.Backend.cfPreBuf = CfgHostAcq.Backend.cfBufferSize; 676 } 677 678 if (CfgHostAcq.Backend.cfPeriod > CfgHostAcq.Backend.cfBufferSize) 679 { 680 LogRel2(("Audio: Warning: Period size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), setting to %RU32 frames\n", 681 CfgHostAcq.Backend.cfPeriod, pHstStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize)); 682 CfgHostAcq.Backend.cfPeriod = CfgHostAcq.Backend.cfBufferSize; 683 } 684 685 uint32_t msBufferSize = DrvAudioHlpFramesToMilli(CfgHostAcq.Backend.cfBufferSize, &pCfgHost->Props); 686 687 LogRel2(("Audio: Buffer size of stream '%s' is %RU32ms (%RU32 frames)\n", 688 pHstStream->szName, msBufferSize, CfgHostAcq.Backend.cfBufferSize)); 689 668 690 /* If no own pre-buffer is set, let the backend choose. */ 669 691 uint32_t msPreBuf = DrvAudioHlpFramesToMilli(CfgHostAcq.Backend.cfPreBuf, &pCfgHost->Props); … … 676 698 LogRel2(("Audio: Period size of stream '%s' is %RU32ms (%RU32 frames)\n", 677 699 pHstStream->szName, msPeriod, CfgHostAcq.Backend.cfPeriod)); 678 679 /* Check if the backend did return sane values and correct if necessary. */680 if (CfgHostAcq.Backend.cfBufferSize < CfgHostAcq.Backend.cfPeriod)681 {682 LogRel2(("Audio: Warning: Backend of stream '%s' did not set a valid buffer size (%RU32 frames), setting to %RU32 frames",683 pHstStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfPeriod));684 AssertFailed(); /* Should never happen. */685 }686 687 uint32_t msBufferSize = DrvAudioHlpFramesToMilli(CfgHostAcq.Backend.cfBufferSize, &pCfgHost->Props);688 689 LogRel2(("Audio: Buffer size of stream '%s' is %RU32ms (%RU32 frames)\n",690 pHstStream->szName, msBufferSize, CfgHostAcq.Backend.cfBufferSize));691 700 692 701 /* Set set host buffer size multiplicator. */ … … 974 983 AssertPtr(pGstStream); 975 984 985 AssertMsg(DrvAudioHlpBytesIsAligned(cbBuf, &pGstStream->Cfg.Props), 986 ("Writing audio data (%RU32 bytes) to stream '%s' is not properly aligned\n", cbBuf, pGstStream->szName)); 987 976 988 #ifdef LOG_ENABLED 977 989 pszGstSts = dbgAudioStreamStatusToStr(pGstStream->fStatus); … … 991 1003 992 1004 const uint32_t cbFree = AudioMixBufFreeBytes(&pHstStream->MixBuf); 993 if (cbFree < cbBuf) /* No space left on host side? Bail out. */994 LogRel2(("Audio: Lost audio frames (%RU32) due to full host stream '%s', expect stuttering audio output\n",995 DrvAudioHlpBytesTo Frames(cbBuf - cbFree, &pHstStream->Cfg.Props), pHstStream->szName));1005 if (cbFree < cbBuf) 1006 LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n", 1007 DrvAudioHlpBytesToMilli(cbBuf - cbFree, &pHstStream->Cfg.Props), cbFree, cbBuf, pHstStream->szName)); 996 1008 997 1009 uint32_t cbToWrite = RT_MIN(cbBuf, cbFree); … … 1001 1013 if (!cbToWrite) 1002 1014 break; 1003 1004 uint64_t tsDeltaWrittenMs = RTTimeMilliTS() - pHstStream->tsLastReadWrittenMs;1005 1006 Log3Func(("[%s] fThresholdReached=%RTbool, tsDeltaWrittenMs=%RU64\n",1007 pHstStream->szName, pHstStream->fThresholdReached, tsDeltaWrittenMs));1008 1009 if ( pHstStream->fThresholdReached1010 && tsDeltaWrittenMs < pGstStream->Cfg.Device.uSchedulingHintMs)1011 {1012 break;1013 }1014 1015 1015 1016 /* We use the guest side mixing buffer as an intermediate buffer to do some … … 1043 1044 else 1044 1045 { 1045 Log3Func(("[%s] Buffer: Last written %RU64ms, writing %RU32 frames (%RU64ms), now filled with %RU64ms -- %RU8%%\n",1046 pHstStream->szName, tsDeltaWrittenMs,cfGstWritten, DrvAudioHlpFramesToMilli(cfGstWritten, &pHstStream->Cfg.Props),1046 Log3Func(("[%s] Buffer: Writing %RU32 frames (%RU64ms), now filled with %RU64ms -- %RU8%%\n", 1047 pHstStream->szName, cfGstWritten, DrvAudioHlpFramesToMilli(cfGstWritten, &pHstStream->Cfg.Props), 1047 1048 DrvAudioHlpFramesToMilli(AudioMixBufUsed(&pHstStream->MixBuf), &pHstStream->Cfg.Props), 1048 1049 AudioMixBufUsed(&pHstStream->MixBuf) * 100 / AudioMixBufSize(&pHstStream->MixBuf))); 1049 1050 1050 pHstStream->tsLastReadWritten Ms = RTTimeMilliTS();1051 pHstStream->tsLastReadWrittenNs = RTTimeNanoTS(); 1051 1052 1052 1053 /* Keep going. */ … … 1057 1058 1058 1059 cbWrittenTotal = AUDIOMIXBUF_F2B(&pGstStream->MixBuf, cfGstWritten); 1060 #ifdef DEBUG 1061 if (pHstStream->fThresholdReached) 1062 pHstStream->Out.Dbg.cbJitterWrittenPlayed += cbWrittenTotal; 1063 #endif 1059 1064 1060 1065 #ifdef VBOX_WITH_STATISTICS … … 1300 1305 1301 1306 /* Update timestamps. */ 1302 pGstStream->tsLastIterated Ms = RTTimeMilliTS();1307 pGstStream->tsLastIteratedNs = RTTimeNanoTS(); 1303 1308 1304 1309 if (RT_FAILURE(rc)) … … 1375 1380 1376 1381 AssertPtr(pThis->pHostDrvAudio->pfnStreamGetWritable); 1377 uint32_t cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pHstStream->pvBackend); 1378 if (cbWritable) 1379 { 1380 if (cfToPlay > AUDIOMIXBUF_B2F(&pHstStream->MixBuf, cbWritable)) /* More frames available than we can write? Limit. */ 1381 cfToPlay = AUDIOMIXBUF_B2F(&pHstStream->MixBuf, cbWritable); 1382 uint32_t cfWritable = AUDIOMIXBUF_B2F(&pHstStream->MixBuf, 1383 pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pHstStream->pvBackend)); 1384 1385 Log3Func(("[%s] cfToPlay=%RU32 (%RU64ms), cfWritable=%RU32 (%RU64ms)\n", pHstStream->szName, 1386 cfToPlay, DrvAudioHlpFramesToMilli(cfToPlay, &pHstStream->Cfg.Props), 1387 cfWritable, DrvAudioHlpFramesToMilli(cfWritable, &pHstStream->Cfg.Props))); 1388 1389 if (cfWritable) 1390 { 1391 if (cfToPlay > cfWritable) /* More frames available than we can write? Limit. */ 1392 cfToPlay = cfWritable; 1382 1393 1383 1394 if (cfToPlay) … … 1385 1396 uint8_t auBuf[256]; /** @todo Get rid of this here. */ 1386 1397 1387 uint32_t c bLeft = AUDIOMIXBUF_F2B(&pHstStream->MixBuf, cfToPlay);1398 uint32_t cfLeft = cfToPlay; 1388 1399 uint32_t cbChunk = sizeof(auBuf); 1389 1400 1390 while (c bLeft)1401 while (cfLeft) 1391 1402 { 1392 1403 uint32_t cfRead = 0; 1393 rc = AudioMixBufAcquireReadBlock(&pHstStream->MixBuf, auBuf, RT_MIN(cbChunk, cbLeft), &cfRead);1404 rc = AudioMixBufAcquireReadBlock(&pHstStream->MixBuf, auBuf, RT_MIN(cbChunk, AUDIOMIXBUF_F2B(&pHstStream->MixBuf, cfLeft)), &cfRead); 1394 1405 if (RT_FAILURE(rc)) 1395 1406 break; … … 1409 1420 1410 1421 if (cbRead != cbPlayed) 1411 LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32 (%RI32), writable was %RU32)\n",1412 pHstStream->szName, cbRead, cbPlayed , cbRead - cbPlayed, cbWritable));1422 LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n", 1423 pHstStream->szName, cbRead, cbPlayed)); 1413 1424 1414 1425 cfPlayed = AUDIOMIXBUF_B2F(&pHstStream->MixBuf, cbPlayed); 1415 1426 cfPlayedTotal += cfPlayed; 1416 1427 1417 Assert(c bLeft >= cbPlayed);1418 c bLeft -= cbPlayed;1428 Assert(cfLeft >= cfPlayed); 1429 cfLeft -= cfPlayed; 1419 1430 } 1420 1431 … … 1576 1587 #ifdef LOG_ENABLED 1577 1588 char *pszStreamSts = dbgAudioStreamStatusToStr(stsHstStream); 1578 Log3Func(("[%s] Start:stsHstStream=%s\n", pHstStream->szName, pszStreamSts));1589 Log3Func(("[%s] Buffer: Start stsHstStream=%s\n", pHstStream->szName, pszStreamSts)); 1579 1590 RTStrFree(pszStreamSts); 1580 1591 #endif /* LOG_ENABLED */ … … 1591 1602 const uint8_t uLivePercent = (100 * cfLive) / AudioMixBufSize(&pHstStream->MixBuf); 1592 1603 1593 if (!pHstStream->tsLastPlayedCapturedMs) 1594 pHstStream->tsLastPlayedCapturedMs = RTTimeMilliTS(); 1595 uint64_t tsDeltaPlayedCapturedMs = RTTimeMilliTS() - pHstStream->tsLastPlayedCapturedMs; 1596 pHstStream->tsLastPlayedCapturedMs = RTTimeMilliTS(); 1597 1598 #ifdef LOG_ENABLED 1599 Log3Func(("[%s] Buffer: Last played %RU64ms, filled with %RU64ms (%RU8%%) total, " 1604 const uint64_t tsDeltaPlayedCapturedNs = RTTimeNanoTS() - pHstStream->tsLastPlayedCapturedNs; 1605 1606 pHstStream->tsLastPlayedCapturedNs = RTTimeNanoTS(); 1607 1608 Log3Func(("[%s] Buffer: Last played %RU64ns (%RU64ms), filled with %RU64ms (%RU8%%) total, " 1600 1609 "(cfLive=%RU32, fThresholdReached=%RTbool)\n", 1601 pHstStream->szName, tsDeltaPlayedCapturedMs, DrvAudioHlpFramesToMilli(cfLive, &pHstStream->Cfg.Props), 1610 pHstStream->szName, tsDeltaPlayedCapturedNs, tsDeltaPlayedCapturedNs / RT_NS_1MS_64, 1611 DrvAudioHlpFramesToMilli(cfLive, &pHstStream->Cfg.Props), 1602 1612 uLivePercent, cfLive, pHstStream->fThresholdReached)); 1603 #endif 1613 1604 1614 bool fDoPlay = pHstStream->fThresholdReached; 1605 1615 bool fJustStarted = false; … … 1612 1622 fDoPlay = true; 1613 1623 } 1614 1615 1624 /* Some audio files are shorter than the pre-buffering level (e.g. the "click" Explorer sounds on some Windows guests), 1616 1625 * so make sure that we also play those by checking if the stream already is pending disable mode, even if we didn't … … 1618 1627 * 1619 1628 * To reproduce, use "Windows Navigation Start.wav" on Windows 7 (2824 samples). */ 1620 if ( cfLive1621 && pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)1629 else if ( cfLive 1630 && pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE) 1622 1631 { 1623 1632 LogRel2(("Audio: Stream '%s' buffering complete (short sound)\n", pHstStream->szName)); … … 1638 1647 if (fDoPlay) 1639 1648 { 1640 if (pHstStream->tsLastPlayedCapturedMs < 2) 1641 break; 1642 1643 uint32_t cfToPlay; 1649 uint32_t cfToPlay = 0; 1644 1650 if (fJustStarted) 1645 cfToPlay = pHstStream->Cfg.Backend.cfPeriod; 1646 else 1647 cfToPlay = DrvAudioHlpMilliToFrames(tsDeltaPlayedCapturedMs, &pHstStream->Cfg.Props); 1648 1649 Log3Func(("[%s] Buffer: fJustStarted=%RTbool, cfLive=%RU32, cfToPlay=%RU32\n", 1651 cfToPlay = pHstStream->Cfg.Backend.cfPeriod; /* cfPeriod can be 0. */ 1652 1653 if (!cfToPlay) 1654 { 1655 cfToPlay = DrvAudioHlpNanoToFrames(tsDeltaPlayedCapturedNs, &pHstStream->Cfg.Props); 1656 if (pHstStream->Cfg.Device.uSchedulingHintMs) 1657 cfToPlay = RT_MIN(cfToPlay, DrvAudioHlpMilliToFrames(pHstStream->Cfg.Device.uSchedulingHintMs, &pHstStream->Cfg.Props)); 1658 } 1659 1660 LogRelFunc(("[%s] Buffer: fJustStarted=%RTbool, cfLive=%RU32, cfToPlay=%RU32\n", 1650 1661 pHstStream->szName, fJustStarted, cfLive, cfToPlay)); 1651 1662 … … 1653 1664 * If we're in pending disabled mode, try to play (drain) the remaining audio data. */ 1654 1665 if ( !(pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE) 1655 && !fJustStarted 1656 && cfLive < cfToPlay) 1666 && !fJustStarted) 1657 1667 { 1658 pHstStream->fThresholdReached = false; 1659 LogRel2(("Audio: Stream '%s' buffer underrun (total %RU8%%, which is %RU8%% of a period), buffering ...\n", 1660 pHstStream->szName, uLivePercent, (100 * cfLive) / pHstStream->Cfg.Backend.cfPeriod)); 1661 break; 1668 if (cfLive < cfToPlay) 1669 { 1670 pHstStream->fThresholdReached = false; 1671 Log3Func(("[%s] Buffer: Underrun (cfLive=%RU32, cfToPlay=%RU32)\n", pHstStream->szName, cfLive, cfToPlay)); 1672 LogRel2(("Audio: Stream '%s' buffer underrun (total %RU8%%, which is %RU8%% of a period), buffering ...\n", 1673 pHstStream->szName, uLivePercent, (100 * cfLive) / pHstStream->Cfg.Backend.cfPeriod)); 1674 break; 1675 } 1662 1676 } 1663 1677 … … 1665 1679 cfToPlay = cfLive; 1666 1680 1667 Log3Func(("[%s] Buffer: Playing %RU32 frames (%RU64ms since last playback)\n", 1668 pHstStream->szName, cfToPlay, tsDeltaPlayedCapturedMs)); 1669 1681 if (!cfToPlay) 1682 break; 1683 #ifdef DEBUG 1684 if (!fJustStarted) 1685 pHstStream->Out.Dbg.cbJitterWrittenPlayed -= AUDIOMIXBUF_F2B(&pHstStream->MixBuf, cfToPlay); 1686 Log3Func(("[%s] Buffer: Playing %RU32 frames (%RU64ms), now filled with %RU64ms -- %RU8%% (cbJitterWrittenPlayed=%RI64)\n", 1687 pHstStream->szName, cfToPlay, DrvAudioHlpFramesToMilli(cfToPlay, &pHstStream->Cfg.Props), 1688 DrvAudioHlpFramesToMilli(AudioMixBufUsed(&pHstStream->MixBuf), &pHstStream->Cfg.Props), 1689 AudioMixBufUsed(&pHstStream->MixBuf) * 100 / AudioMixBufSize(&pHstStream->MixBuf), 1690 pHstStream->Out.Dbg.cbJitterWrittenPlayed)); 1691 #endif 1670 1692 if (pThis->pHostDrvAudio->pfnStreamPlayBegin) 1671 1693 pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pHstStream->pvBackend); … … 1702 1724 uint32_t cfLive = AudioMixBufLive(&pHstStream->MixBuf); 1703 1725 pszStreamSts = dbgAudioStreamStatusToStr(stsHstStream); 1704 Log3Func(("[%s] End:stsHstStream=%s, cfLive=%RU32, cfPlayedTotal=%RU32, rc=%Rrc\n",1726 Log3Func(("[%s] Buffer: End stsHstStream=%s, cfLive=%RU32, cfPlayedTotal=%RU32, rc=%Rrc\n", 1705 1727 pHstStream->szName, pszStreamSts, cfLive, cfPlayedTotal, rc)); 1706 1728 RTStrFree(pszStreamSts); … … 3036 3058 3037 3059 /* As the host side sets the overall pace, return the writable bytes from that side. */ 3038 uint32_t cbWritable = AudioMixBufFreeBytes(&pHstStream->MixBuf); 3039 3040 Log3Func(("[%s] cbWritable=%RU32\n", pHstStream->szName, cbWritable)); 3060 const uint64_t deltaLastReadWriteNs = RTTimeNanoTS() - pHstStream->tsLastReadWrittenNs; 3061 3062 uint32_t cbWritable = DrvAudioHlpNanoToBytes(deltaLastReadWriteNs, &pHstStream->Cfg.Props); 3063 cbWritable = DrvAudioHlpBytesAlign(cbWritable, &pHstStream->Cfg.Props); 3064 3065 Log3Func(("Audio: [%s] cbWritable=%RU32 (%RU64ms)\n", pHstStream->szName, cbWritable, deltaLastReadWriteNs / RT_NS_1MS_64)); 3041 3066 3042 3067 rc2 = RTCritSectLeave(&pThis->CritSect);
Note:
See TracChangeset
for help on using the changeset viewer.